Merge lp:~phablet-team/media-hub/fix-1538703 into lp:media-hub

Proposed by Konrad Zapałowicz
Status: Approved
Approved by: Alfonso Sanchez-Beato
Approved revision: 185
Proposed branch: lp:~phablet-team/media-hub/fix-1538703
Merge into: lp:media-hub
Diff against target: 322 lines (+125/-17)
9 files modified
debian/libmedia-hub-doc.install (+1/-1)
doc/CMakeLists.txt (+2/-2)
include/core/media/service.h (+0/-3)
src/core/media/player_configuration.h (+3/-0)
src/core/media/player_implementation.cpp (+68/-6)
src/core/media/player_skeleton.h (+2/-0)
src/core/media/service_implementation.cpp (+3/-3)
src/core/media/service_skeleton.cpp (+35/-2)
src/core/media/service_skeleton.h (+11/-0)
To merge this branch: bzr merge lp:~phablet-team/media-hub/fix-1538703
Reviewer Review Type Date Requested Status
Alfonso Sanchez-Beato Approve
Review via email: mp+292038@code.launchpad.net

This proposal supersedes a proposal from 2016-04-12.

Commit message

A rewrite of how the current player is set which is what the MPRIS control interface actively uses.

Description of the change

A rewrite of how the current player is set which is what the MPRIS control interface actively uses.

To post a comment you must log in.
Revision history for this message
Alfonso Sanchez-Beato (alfonsosanchezbeato) wrote : Posted in a previous version of this proposal

Looks good, but maybe we need to call update_current_player() also when adding complete track lists? Which is done with AddTrack(s) DBus calls.

review: Needs Information
Revision history for this message
Jim Hodapp (jhodapp) wrote : Posted in a previous version of this proposal

> Looks good, but maybe we need to call update_current_player() also when adding
> complete track lists? Which is done with AddTrack(s) DBus calls.

Can you explain more why you think we need to do this? I don't see any gap that this would fix.

Revision history for this message
Jim Hodapp (jhodapp) wrote : Posted in a previous version of this proposal

Addressed review comments.

Revision history for this message
Alfonso Sanchez-Beato (alfonsosanchezbeato) wrote : Posted in a previous version of this proposal

LGTM

review: Approve
Revision history for this message
Alfonso Sanchez-Beato (alfonsosanchezbeato) wrote : Posted in a previous version of this proposal

So I have just seen that Jim modified service.h too to add reset_current_player(), for some reason I did not notice last time I reviewed. TBH I do not like adding reset_current_player() and get_current_player() to service.h. That file is, in the end, defining a DBus interface so we should add only functions that make sense to a media-hub client, and these functions are not even implemented in the service stub (client library).

I think that changing PlayerSkeleton so player_service is a pointer to ServiceSkeleton, and implementing these functions only in ServiceSkeleton should work. We will make sure the DBus interface is not contaminated and we remove the need for dummy implementations in ServiceStub and ServiceImplementation.

@Konrad maybe we con wait for Jim if you do not feel comfortable with this change.

Finally, I appreciate the long description in the last commit message, but I think most of it should move to a comment inside the code so it is more easily found.

The change looks good beside this issue with service.h.

review: Needs Fixing
Revision history for this message
Konrad Zapałowicz (kzapalowicz) wrote : Posted in a previous version of this proposal

Thanks for the review and I will try to make the changes that you suggest. Either I'm successful or not and the Jim will take over when he is back however before that happens I will get my hands dirty :)

Revision history for this message
Alfonso Sanchez-Beato (alfonsosanchezbeato) wrote :

LGTM

review: Approve
186. By Jim Hodapp

Pass a Service* instead of ServiceSkeleton* to avoid weird inheritance segfault

Unmerged revisions

186. By Jim Hodapp

Pass a Service* instead of ServiceSkeleton* to avoid weird inheritance segfault

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/libmedia-hub-doc.install'
2--- debian/libmedia-hub-doc.install 2014-03-06 22:51:51 +0000
3+++ debian/libmedia-hub-doc.install 2016-04-20 15:59:04 +0000
4@@ -1,1 +1,1 @@
5-usr/share/doc/music-hub/html
6+usr/share/doc/media-hub/html
7
8=== modified file 'doc/CMakeLists.txt'
9--- doc/CMakeLists.txt 2013-08-14 18:05:23 +0000
10+++ doc/CMakeLists.txt 2016-04-20 15:59:04 +0000
11@@ -26,5 +26,5 @@
12 COMMENT "Generating API documentation with Doxygen" VERBATIM)
13 install(
14 DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html
15- DESTINATION share/doc/music-hub)
16-endif(DOXYGEN_FOUND)
17\ No newline at end of file
18+ DESTINATION share/doc/media-hub)
19+endif(DOXYGEN_FOUND)
20
21=== modified file 'include/core/media/service.h'
22--- include/core/media/service.h 2015-09-08 20:03:56 +0000
23+++ include/core/media/service.h 2016-04-20 15:59:04 +0000
24@@ -60,9 +60,6 @@
25 /** @brief Resumes a fixed-name session directly by player key. */
26 virtual std::shared_ptr<Player> resume_session(Player::PlayerKey) = 0;
27
28- /** @brief Sets the current player that the MPRIS interface will control */
29- virtual void set_current_player(Player::PlayerKey) = 0;
30-
31 /** @brief Pauses sessions other than the supplied one. */
32 virtual void pause_other_sessions(Player::PlayerKey) = 0;
33
34
35=== modified file 'src/core/media/player_configuration.h'
36--- src/core/media/player_configuration.h 2015-04-17 16:44:30 +0000
37+++ src/core/media/player_configuration.h 2016-04-20 15:59:04 +0000
38@@ -19,6 +19,7 @@
39 #define CORE_UBUNTU_MEDIA_PLAYER_CLIENT_CONFIGURATION_H_
40
41 #include <core/media/player.h>
42+#include <core/media/service.h>
43
44 #include <core/dbus/bus.h>
45 #include <core/dbus/object.h>
46@@ -35,6 +36,8 @@
47 std::shared_ptr<core::dbus::Service> service;
48 // The actual session object representing a player instance.
49 std::shared_ptr<core::dbus::Object> session;
50+ // The Service instance that manages Player instances
51+ core::ubuntu::media::Service* player_service;
52 };
53
54 #endif // CORE_UBUNTU_MEDIA_PLAYER_CLIENT_CONFIGURATION_H_
55
56=== modified file 'src/core/media/player_implementation.cpp'
57--- src/core/media/player_implementation.cpp 2016-02-19 16:14:42 +0000
58+++ src/core/media/player_implementation.cpp 2016-04-20 15:59:04 +0000
59@@ -17,7 +17,10 @@
60 * Jim Hodapp <jim.hodapp@canonical.com>
61 */
62
63+#include <core/media/service.h>
64+
65 #include "player_implementation.h"
66+#include "service_skeleton.h"
67 #include "util/timeout.h"
68
69 #include <unistd.h>
70@@ -302,14 +305,14 @@
71 }
72 }
73
74- void update_mpris_properties(void)
75+ void update_mpris_properties()
76 {
77- bool has_previous = track_list->has_previous()
78+ const bool has_previous = track_list->has_previous()
79 or parent->Parent::loop_status() != Player::LoopStatus::none;
80- bool has_next = track_list->has_next()
81+ const bool has_next = track_list->has_next()
82 or parent->Parent::loop_status() != Player::LoopStatus::none;
83- auto n_tracks = track_list->tracks()->size();
84- bool has_tracks = (n_tracks > 0) ? true : false;
85+ const auto n_tracks = track_list->tracks()->size();
86+ const bool has_tracks = (n_tracks > 0) ? true : false;
87
88 std::cout << "Updating MPRIS TrackList properties"
89 << "; Tracks: " << n_tracks
90@@ -323,6 +326,40 @@
91 parent->can_go_next().set(has_next);
92 }
93
94+ ServiceSkeleton* get_player_service_skeleton() const
95+ {
96+ return reinterpret_cast<ServiceSkeleton*>(config.parent.player_service);
97+ }
98+
99+ bool update_current_player(const media::Player::PlayerKey& key)
100+ {
101+ if (not config.parent.player_service)
102+ return false;
103+
104+ get_player_service_skeleton()->set_current_player(key);
105+ return true;
106+ }
107+
108+ // Utility to hide the complexity of getting the ptr to current player
109+ bool is_current_player(const media::PlayerImplementation<Parent> *p) const
110+ {
111+ return p == get_player_service_skeleton()->get_current_player().get();
112+ }
113+
114+ bool is_multimedia_role() const
115+ {
116+ return get_player_service_skeleton()->is_multimedia_role();
117+ }
118+
119+ bool reset_current_player()
120+ {
121+ if (not get_player_service_skeleton())
122+ return false;
123+
124+ get_player_service_skeleton()->reset_current_player();
125+ return true;
126+ }
127+
128 // Our link back to our parent.
129 media::PlayerImplementation<Parent>* parent;
130 // We just store the parameters passed on construction.
131@@ -479,6 +516,20 @@
132 // are cleared
133 d->clear_wakelocks();
134 d->track_list->reset();
135+
136+ // Here it is decided if it is good to reset the current player. The
137+ // conditions to do so are very simple. It must be a multimedia role
138+ // and the Player that disconnected must be the last player to play
139+ // audio/video.
140+ if (d->is_multimedia_role() && d->is_current_player(this))
141+ {
142+ // This is not a fatal error but merely
143+ // a warning that should be logged
144+ if (not d->reset_current_player())
145+ std::cerr << "Failed to reset current player in "
146+ << __PRETTY_FUNCTION__ << std::endl;
147+ }
148+
149 // And tell the outside world that the client has gone away
150 d->on_client_disconnected();
151 });
152@@ -688,7 +739,8 @@
153 d->track_list->reset();
154
155 // If empty uri, give the same meaning as QMediaPlayer::setMedia("")
156- if (uri.empty()) {
157+ if (uri.empty())
158+ {
159 cout << __PRETTY_FUNCTION__ << ": resetting current media" << endl;
160 return true;
161 }
162@@ -698,6 +750,7 @@
163 // Don't set new track as the current track to play since we're calling open_resource_for_uri above
164 static const bool make_current = false;
165 d->track_list->add_track_with_uri_at(uri, media::TrackList::after_empty_track(), make_current);
166+
167 return ret;
168 }
169
170@@ -722,6 +775,15 @@
171 template<typename Parent>
172 void media::PlayerImplementation<Parent>::play()
173 {
174+ if (Parent::audio_stream_role() == media::Player::AudioStreamRole::multimedia)
175+ {
176+ std::cout << "==== Updating the current player from " << __PRETTY_FUNCTION__ << std::endl;
177+ // This player will begin playing so make sure it's the current player. If
178+ // this operation fails it is not a fatal condition but should be logged
179+ if (not d->update_current_player(d->config.key))
180+ std::cerr << "Failed to update current player in " << __PRETTY_FUNCTION__ << std::endl;
181+ }
182+
183 d->engine->play();
184 }
185
186
187=== modified file 'src/core/media/player_skeleton.h'
188--- src/core/media/player_skeleton.h 2015-04-17 15:13:56 +0000
189+++ src/core/media/player_skeleton.h 2016-04-20 15:59:04 +0000
190@@ -57,6 +57,8 @@
191 std::shared_ptr<core::dbus::Service> service;
192 // The session object that we want to expose the skeleton upon.
193 std::shared_ptr<core::dbus::Object> session;
194+ // The Service instance that manages Player instances
195+ core::ubuntu::media::Service* player_service;
196 // Our functional dependencies.
197 apparmor::ubuntu::RequestContextResolver::Ptr request_context_resolver;
198 apparmor::ubuntu::RequestAuthenticator::Ptr request_authenticator;
199
200=== modified file 'src/core/media/service_implementation.cpp'
201--- src/core/media/service_implementation.cpp 2016-03-02 18:32:46 +0000
202+++ src/core/media/service_implementation.cpp 2016-04-20 15:59:04 +0000
203@@ -185,11 +185,13 @@
204 auto player = std::make_shared<media::PlayerImplementation<media::PlayerSkeleton>>
205 (media::PlayerImplementation<media::PlayerSkeleton>::Configuration
206 {
207+ // Derive a PlayerSkeleton-specific Configuration based on Player::Configuration
208 media::PlayerSkeleton::Configuration
209 {
210 conf.bus,
211 conf.service,
212 conf.session,
213+ conf.player_service,
214 d->request_context_resolver,
215 d->request_authenticator
216 },
217@@ -259,13 +261,11 @@
218
219 void media::ServiceImplementation::set_current_player(Player::PlayerKey)
220 {
221- // no impl
222+ // no impl
223 }
224
225 void media::ServiceImplementation::pause_other_sessions(media::Player::PlayerKey key)
226 {
227- std::cout << __PRETTY_FUNCTION__ << std::endl;
228-
229 if (not d->configuration.player_store->has_player_for_key(key))
230 {
231 cerr << "Could not find Player by key: " << key << endl;
232
233=== modified file 'src/core/media/service_skeleton.cpp'
234--- src/core/media/service_skeleton.cpp 2016-03-02 18:32:46 +0000
235+++ src/core/media/service_skeleton.cpp 2016-04-20 15:59:04 +0000
236@@ -131,7 +131,8 @@
237 key,
238 impl->access_bus(),
239 impl->access_service(),
240- impl->access_service()->add_object_for_path(op)
241+ impl->access_service()->add_object_for_path(op),
242+ impl
243 };
244
245 cout << "Session created by request of: " << msg->sender()
246@@ -366,7 +367,8 @@
247 key,
248 impl->access_bus(),
249 impl->access_service(),
250- impl->access_service()->add_object_for_path(op)
251+ impl->access_service()->add_object_for_path(op),
252+ impl
253 };
254
255 auto session = impl->create_session(config);
256@@ -787,6 +789,22 @@
257 std::cout << __PRETTY_FUNCTION__ << std::endl;
258 // And announce that we can no longer be controlled.
259 player.properties.can_control->set(false);
260+ player.properties.can_play->set(false);
261+ player.properties.can_pause->set(false);
262+ player.properties.can_go_previous->set(false);
263+ player.properties.can_go_next->set(false);
264+
265+ // Reset to null event connections
266+ connections.seeked_to = the_empty_signal.connect([](){});
267+ connections.duration_changed = the_empty_signal.connect([](){});
268+ connections.position_changed = the_empty_signal.connect([](){});
269+ connections.playback_status_changed = the_empty_signal.connect([](){});
270+ connections.loop_status_changed = the_empty_signal.connect([](){});
271+ connections.can_play_changed = the_empty_signal.connect([](){});
272+ connections.can_pause_changed = the_empty_signal.connect([](){});
273+ connections.can_go_previous_changed = the_empty_signal.connect([](){});
274+ connections.can_go_next_changed = the_empty_signal.connect([](){});
275+
276 current_player.reset();
277 }
278
279@@ -901,6 +919,21 @@
280 d->exported.set_current_player(player);
281 }
282
283+bool media::ServiceSkeleton::is_multimedia_role() const
284+{
285+ return d->exported.is_multimedia_role();
286+}
287+
288+std::shared_ptr<media::Player> media::ServiceSkeleton::get_current_player() const
289+{
290+ return d->exported.current_player.lock();
291+}
292+
293+void media::ServiceSkeleton::reset_current_player()
294+{
295+ d->exported.reset_current_player();
296+}
297+
298 void media::ServiceSkeleton::pause_other_sessions(media::Player::PlayerKey key)
299 {
300 d->configuration.impl->pause_other_sessions(key);
301
302=== modified file 'src/core/media/service_skeleton.h'
303--- src/core/media/service_skeleton.h 2015-09-08 20:03:56 +0000
304+++ src/core/media/service_skeleton.h 2016-04-20 15:59:04 +0000
305@@ -60,6 +60,17 @@
306 std::shared_ptr<Player> create_fixed_session(const std::string& name, const Player::Configuration&);
307 std::shared_ptr<Player> resume_session(Player::PlayerKey);
308 void set_current_player(Player::PlayerKey key);
309+
310+ /** @brief returns true for multimedia role */
311+ bool is_multimedia_role() const;
312+
313+ /** @brief gets the current player controlled by MRIS */
314+ std::shared_ptr<Player> get_current_player() const;
315+
316+ /** @detail Resets the current player so that the MPRIS interface will no
317+ * longer have a current player to control
318+ */
319+ void reset_current_player();
320 void pause_other_sessions(Player::PlayerKey key);
321
322 void run();

Subscribers

People subscribed via source and target branches

to all changes: