Merge lp:~phablet-team/qtubuntu-media/enable-mpris-controls into lp:qtubuntu-media/stable

Proposed by Jim Hodapp
Status: Merged
Approved by: Alfonso Sanchez-Beato
Approved revision: no longer in the source branch.
Merged at revision: 86
Proposed branch: lp:~phablet-team/qtubuntu-media/enable-mpris-controls
Merge into: lp:qtubuntu-media/stable
Diff against target: 413 lines (+128/-68)
8 files modified
README (+4/-0)
debian/control (+1/-1)
src/aal/aalmediaplayerservice.cpp (+52/-21)
src/aal/aalmediaplayerservice.h (+4/-2)
tests/integration/tst_mediaplaylist.cpp (+58/-44)
tests/integration/tst_mediaplaylist.h (+4/-0)
tests/unit/service.cpp (+4/-0)
tests/unit/service.h (+1/-0)
To merge this branch: bzr merge lp:~phablet-team/qtubuntu-media/enable-mpris-controls
Reviewer Review Type Date Requested Status
Alfonso Sanchez-Beato Approve
Review via email: mp+270445@code.launchpad.net

Commit message

Make sure the that the current player instance is controlable by MPRIS controls if the type of player is appropriate for playlist control. Also, don't add a track to the tracklist when AalMediaPlayerService::setMedia() is called.

Description of the change

Make sure the that the current player instance is controlable by MPRIS controls if the type of player is appropriate for playlist control. Also, don't add a track to the tracklist when AalMediaPlayerService::setMedia() is called.

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

Looks good, some minor issues detected. I would also like to have a branch for trunk too.

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

Comments addresses.

Revision history for this message
Alfonso Sanchez-Beato (alfonsosanchezbeato) :
review: Approve
86. By Alfonso Sanchez-Beato

Make sure the that the current player instance is controlable by MPRIS controls
if the type of player is appropriate for playlist control. Also, don't add a
track to the tracklist when AalMediaPlayerService::setMedia() is called.

87. By Alfonso Sanchez-Beato

Do not detach from media-hub when we are inactive, as that is needed only
when the application terminates.

88. By Alfonso Sanchez-Beato

Fix and add integration tests

89. By Jim Hodapp

Make sure the current player is set when the client app regains focus.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file 'README'
--- README 1970-01-01 00:00:00 +0000
+++ README 2015-10-14 20:56:01 +0000
@@ -0,0 +1,4 @@
1Coding Convention:
2------------------
3
4This project follows the Qt coding style as detailed here: https://wiki.qt.io/Qt_Coding_Style
05
=== modified file 'debian/control'
--- debian/control 2015-08-04 01:56:17 +0000
+++ debian/control 2015-10-14 20:56:01 +0000
@@ -9,7 +9,7 @@
9 libgl1-mesa-dev | libgl-dev,9 libgl1-mesa-dev | libgl-dev,
10 libgles2-mesa-dev,10 libgles2-mesa-dev,
11 libhybris-dev (>= 0.1.0+git20131207+e452e83-0ubuntu13),11 libhybris-dev (>= 0.1.0+git20131207+e452e83-0ubuntu13),
12 libmedia-hub-dev (>= 3.1.0),12 libmedia-hub-dev (>= 3.2.0),
13 libpulse-dev,13 libpulse-dev,
14 libqt5opengl5-dev,14 libqt5opengl5-dev,
15 libqtubuntu-media-signals-dev (>= 0.3+15.04.20150618.1-0ubuntu1),15 libqtubuntu-media-signals-dev (>= 0.3+15.04.20150618.1-0ubuntu1),
1616
=== modified file 'src/aal/aalmediaplayerservice.cpp'
--- src/aal/aalmediaplayerservice.cpp 2015-08-18 15:49:35 +0000
+++ src/aal/aalmediaplayerservice.cpp 2015-10-14 20:56:01 +0000
@@ -35,7 +35,10 @@
3535
36#include <qtubuntu_media_signals.h>36#include <qtubuntu_media_signals.h>
3737
38// Uncomment to re-enable media-hub Player session detach/reattach functionality38// Uncomment to re-enable media-hub Player session detach/reattach functionality.
39// It is not clear at all whether we should do this or not, as detaching
40// is probably something that should be done when the app finishes, not when it
41// simply moves to the background.
39//#define DO_PLAYER_ATTACH_DETACH42//#define DO_PLAYER_ATTACH_DETACH
4043
41// Defined in aalvideorenderercontrol.h44// Defined in aalvideorenderercontrol.h
@@ -86,7 +89,7 @@
8689
87 // As core::Connection doesn't allow us to start with a disconnected connection90 // As core::Connection doesn't allow us to start with a disconnected connection
88 // instance we have to connect it first with a dummy signal and then disconnect91 // instance we have to connect it first with a dummy signal and then disconnect
89 // it again. If we don't do this connect_signals() will never be able to attach92 // it again. If we don't do this connectSignals() will never be able to attach
90 // to the relevant signals.93 // to the relevant signals.
91 m_endOfStreamConnection.disconnect();94 m_endOfStreamConnection.disconnect();
9295
@@ -271,7 +274,7 @@
271274
272void AalMediaPlayerService::setMedia(const QUrl &url)275void AalMediaPlayerService::setMedia(const QUrl &url)
273{276{
274 if (m_hubPlayerSession == NULL)277 if (m_hubPlayerSession == nullptr)
275 {278 {
276 qWarning() << "Cannot open uri without a valid media-hub player session";279 qWarning() << "Cannot open uri without a valid media-hub player session";
277 return;280 return;
@@ -292,16 +295,19 @@
292295
293 qDebug() << "Setting media to: " << url;296 qDebug() << "Setting media to: " << url;
294 const media::Track::UriType uri(url.url().toStdString());297 const media::Track::UriType uri(url.url().toStdString());
295 try {298 if (m_mediaPlaylistProvider == nullptr)
296 if (m_mediaPlaylistProvider != NULL)299 {
297 m_mediaPlaylistProvider->addMedia(QMediaContent(url));300 try {
298 else
299 m_hubPlayerSession->open_uri(uri);301 m_hubPlayerSession->open_uri(uri);
300 }302 }
301 catch (const std::runtime_error &e) {303 catch (const std::runtime_error &e) {
302 qWarning() << "Failed to open media " << url << ": " << e.what();304 qWarning() << "Failed to set media " << url << ": " << e.what();
303 return;305 return;
304 }306 }
307 }
308
309 // Make sure this player can be controlled by MPRIS if appropriate
310 updateCurrentPlayer();
305311
306 if (isVideoSource())312 if (isVideoSource())
307 m_videoOutput->setupSurface();313 m_videoOutput->setupSurface();
@@ -327,13 +333,18 @@
327333
328 qDebug() << "Setting media to: " << AalUtility::unescape(media);334 qDebug() << "Setting media to: " << AalUtility::unescape(media);
329 try {335 try {
336 // TODO: Change this to use the QUrl from QMediaContent and then call
337 // open_uri(uri) like the other version of setMedia does above
330 m_mediaPlaylistProvider->addMedia(media);338 m_mediaPlaylistProvider->addMedia(media);
331 }339 }
332 catch (const std::runtime_error &e) {340 catch (const std::runtime_error &e) {
333 qWarning() << "Failed to open media " << AalUtility::unescape(media) << ": " << e.what();341 qWarning() << "Failed to set media " << AalUtility::unescape(media) << ": " << e.what();
334 return;342 return;
335 }343 }
336344
345 // Make sure this player can be controlled by MPRIS if appropriate
346 updateCurrentPlayer();
347
337 if (isVideoSource())348 if (isVideoSource())
338 m_videoOutput->setupSurface();349 m_videoOutput->setupSurface();
339}350}
@@ -546,7 +557,7 @@
546 return;557 return;
547558
548 m_mediaPlayerControl = new AalMediaPlayerControl(this);559 m_mediaPlayerControl = new AalMediaPlayerControl(this);
549 connect_signals();560 connectSignals();
550}561}
551562
552void AalMediaPlayerService::createVideoRendererControl()563void AalMediaPlayerService::createVideoRendererControl()
@@ -704,7 +715,7 @@
704 case Qt::ApplicationInactive:715 case Qt::ApplicationInactive:
705 qDebug() << "** Application is now inactive";716 qDebug() << "** Application is now inactive";
706#ifdef DO_PLAYER_ATTACH_DETACH717#ifdef DO_PLAYER_ATTACH_DETACH
707 disconnect_signals();718 disconnectSignals();
708 m_hubService->detach_session(m_sessionUuid, media::Player::Client::default_configuration());719 m_hubService->detach_session(m_sessionUuid, media::Player::Client::default_configuration());
709 m_doReattachSession = true;720 m_doReattachSession = true;
710#endif721#endif
@@ -716,13 +727,16 @@
716 // will break video playback727 // will break video playback
717 if (m_doReattachSession)728 if (m_doReattachSession)
718 {729 {
719 m_hubPlayerSession = m_hubService->reattach_session(m_sessionUuid, media::Player::Client::default_configuration());730 m_hubPlayerSession = m_hubService->
720 // Make sure the client's status (position, duraiton, state, etc) are all correct when reattaching731 reattach_session(m_sessionUuid,
721 // to the media-hub Player session732 media::Player::Client::default_configuration());
733 // Make sure the client's status (position, duraiton, state, etc) are all
734 // correct when reattaching to the media-hub Player session
722 updateClientSignals();735 updateClientSignals();
723 connect_signals();736 connectSignals();
724 }737 }
725#endif738#endif
739 updateCurrentPlayer();
726 break;740 break;
727 default:741 default:
728 qDebug() << "Unknown ApplicationState";742 qDebug() << "Unknown ApplicationState";
@@ -758,7 +772,7 @@
758 }772 }
759}773}
760774
761void AalMediaPlayerService::connect_signals()775void AalMediaPlayerService::connectSignals()
762{776{
763 if (!m_endOfStreamConnection.is_connected())777 if (!m_endOfStreamConnection.is_connected())
764 {778 {
@@ -770,12 +784,29 @@
770 }784 }
771}785}
772786
773void AalMediaPlayerService::disconnect_signals()787void AalMediaPlayerService::disconnectSignals()
774{788{
775 if (m_endOfStreamConnection.is_connected())789 if (m_endOfStreamConnection.is_connected())
776 m_endOfStreamConnection.disconnect();790 m_endOfStreamConnection.disconnect();
777}791}
778792
793void AalMediaPlayerService::updateCurrentPlayer()
794{
795 // If this player is a multimedia audioRole, then it should possible to
796 // use it for MPRIS control
797 if (audioRole() == QMediaPlayer::MultimediaRole)
798 {
799 qDebug() << "Setting player as current player";
800 try {
801 const media::Player::PlayerKey key = m_hubPlayerSession->key();
802 m_hubService->set_current_player(key);
803 } catch (const std::runtime_error &e) {
804 qWarning() << "Failed to set player as current player: " << e.what();
805 return;
806 }
807 }
808}
809
779void AalMediaPlayerService::onError(const core::ubuntu::media::Player::Error &error)810void AalMediaPlayerService::onError(const core::ubuntu::media::Player::Error &error)
780{811{
781 qWarning() << "** Media playback error: " << error;812 qWarning() << "** Media playback error: " << error;
782813
=== modified file 'src/aal/aalmediaplayerservice.h'
--- src/aal/aalmediaplayerservice.h 2015-08-18 15:48:31 +0000
+++ src/aal/aalmediaplayerservice.h 2015-10-14 20:56:01 +0000
@@ -114,8 +114,9 @@
114114
115protected:115protected:
116 void updateClientSignals();116 void updateClientSignals();
117 void connect_signals();117 void connectSignals();
118 void disconnect_signals();118 void disconnectSignals();
119 void updateCurrentPlayer();
119#ifdef MEASURE_PERFORMANCE120#ifdef MEASURE_PERFORMANCE
120 void measurePerformance();121 void measurePerformance();
121#endif122#endif
@@ -153,6 +154,7 @@
153 const QMediaPlaylist* m_mediaPlaylist;154 const QMediaPlaylist* m_mediaPlaylist;
154155
155 core::ubuntu::media::Player::PlaybackStatus m_newStatus;156 core::ubuntu::media::Player::PlaybackStatus m_newStatus;
157
156 std::string m_sessionUuid;158 std::string m_sessionUuid;
157 bool m_doReattachSession;159 bool m_doReattachSession;
158160
159161
=== modified file 'tests/integration/tst_mediaplaylist.cpp'
--- tests/integration/tst_mediaplaylist.cpp 2015-07-10 14:49:05 +0000
+++ tests/integration/tst_mediaplaylist.cpp 2015-10-14 20:56:01 +0000
@@ -215,23 +215,11 @@
215215
216 QCOMPARE(playlist->mediaCount(), 3);216 QCOMPARE(playlist->mediaCount(), 3);
217217
218 QMediaContent current_media;
219 std::promise<QMediaContent> promise;
220 std::future<QMediaContent> future{promise.get_future()};
221 QMetaObject::Connection c = connect(playlist, &QMediaPlaylist::currentMediaChanged, [&](const QMediaContent& content)
222 {
223 qDebug() << "currentMediaChanged to: " << content.canonicalUrl().toString();
224 current_media = content;
225 promise.set_value(current_media);
226 // Make sure the promise is not fulfilled twice
227 QObject::disconnect(c);
228 });
229
230 qDebug() << "Setting current index to be 1";218 qDebug() << "Setting current index to be 1";
231 playlist->setCurrentIndex(1);219 playlist->setCurrentIndex(1);
232220
233 // Wait for the currentMediaChanged signal to be emited221 // Wait for the currentMediaChanged signal to be emited
234 wait_for_signal(future);222 waitTrackChange(playlist);
235223
236 qDebug() << "Checking if current index is 1";224 qDebug() << "Checking if current index is 1";
237 QCOMPARE(playlist->currentIndex(), 1);225 QCOMPARE(playlist->currentIndex(), 1);
@@ -312,30 +300,16 @@
312300
313 QCOMPARE(playlist->mediaCount(), 2);301 QCOMPARE(playlist->mediaCount(), 2);
314302
315 QMediaContent current_media;
316 std::promise<QMediaContent> promise;
317 std::future<QMediaContent> future{promise.get_future()};
318 QMetaObject::Connection c = connect(playlist, &QMediaPlaylist::currentMediaChanged, [&](const QMediaContent& content)
319 {
320 qDebug() << "currentMediaChanged to: " << content.canonicalUrl().toString();
321 current_media = content;
322 promise.set_value(current_media);
323 // Make sure the promise is not fulfilled twice
324 QObject::disconnect(c);
325 });
326
327 playlist->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);303 playlist->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);
328304
329 qDebug() << "Call player->play()";305 qDebug() << "Call player->play()";
330 player->play();306 player->play();
331307
332 // Wait for the currentMediaChanged signal to be emited308 // Wait for the currentMediaChanged signal to be emited
333 wait_for_signal(future);309 waitTrackChange(playlist);
334310
335 QCOMPARE(playlist->currentIndex(), 0);311 QCOMPARE(playlist->currentIndex(), 0);
336312
337 QObject::disconnect(c);
338
339 delete playlist;313 delete playlist;
340 delete player;314 delete player;
341}315}
@@ -346,19 +320,6 @@
346 QMediaPlaylist *playlist = new QMediaPlaylist;320 QMediaPlaylist *playlist = new QMediaPlaylist;
347 player->setPlaylist(playlist);321 player->setPlaylist(playlist);
348322
349 QMediaContent current_media;
350 std::promise<QMediaContent> promise;
351 std::future<QMediaContent> future{promise.get_future()};
352
353 QMetaObject::Connection c = connect(playlist, &QMediaPlaylist::currentMediaChanged, [&](const QMediaContent& content)
354 {
355 qDebug() << "currentMediaChanged to: " << content.canonicalUrl().toString();
356 current_media = content;
357 promise.set_value(current_media);
358 // Make sure the promise is not fulfilled twice
359 QObject::disconnect(c);
360 });
361
362 QList<QMediaContent> content;323 QList<QMediaContent> content;
363 content.push_back(QUrl("file://" + QFINDTESTDATA("testdata/testfile.ogg")));324 content.push_back(QUrl("file://" + QFINDTESTDATA("testdata/testfile.ogg")));
364 content.push_back(QUrl("file://" + QFINDTESTDATA("testdata/testfile.ogg")));325 content.push_back(QUrl("file://" + QFINDTESTDATA("testdata/testfile.ogg")));
@@ -368,14 +329,48 @@
368329
369 playlist->setPlaybackMode(QMediaPlaylist::Sequential);330 playlist->setPlaybackMode(QMediaPlaylist::Sequential);
370331
332 // Wait until the first track is set as the current one
333 waitTrackChange(playlist);
334
371 player->play();335 player->play();
372336
373 // Wait for the currentMediaChanged signal to be emited337 // Wait until the second track is selected
374 wait_for_signal(future);338 waitTrackChange(playlist);
375339
376 QCOMPARE(playlist->currentIndex(), 1);340 QCOMPARE(playlist->currentIndex(), 1);
377341
378 QObject::disconnect(c);342 delete playlist;
343 delete player;
344}
345
346void tst_MediaPlaylist::playReusePlayTrackList()
347{
348 QMediaPlayer *player = new QMediaPlayer;
349 QMediaPlaylist *playlist = new QMediaPlaylist;
350 player->setPlaylist(playlist);
351
352 const QUrl audio(QUrl("file://" + QFINDTESTDATA("testdata/testfile.ogg")));
353 const QUrl video(QUrl("file://" + QFINDTESTDATA("testdata/testfile.mp4")));
354
355 for (int i = 0; i < 5; ++i) {
356 playlist->addMedia(audio);
357 playlist->addMedia(video);
358 playlist->addMedia(audio);
359 QCOMPARE(playlist->mediaCount(), 3);
360
361 player->play();
362 QCoreApplication::processEvents();
363
364 const QUrl audioToVerify(playlist->currentMedia().canonicalUrl());
365 QCOMPARE(audioToVerify, audio);
366
367 player->stop();
368 QCoreApplication::processEvents();
369
370 playlist->clear();
371
372 QCOMPARE(playlist->mediaCount(), 0);
373 }
379374
380 delete playlist;375 delete playlist;
381 delete player;376 delete player;
@@ -393,4 +388,23 @@
393 }388 }
394}389}
395390
391void tst_MediaPlaylist::waitTrackChange(QMediaPlaylist *playlist)
392{
393 QMediaContent current_media;
394 std::promise<QMediaContent> promise;
395 std::future<QMediaContent> future{promise.get_future()};
396
397 QMetaObject::Connection c = connect(playlist, &QMediaPlaylist::currentMediaChanged,
398 [&](const QMediaContent& content)
399 {
400 qDebug() << "currentMediaChanged to: " << content.canonicalUrl().toString();
401 current_media = content;
402 promise.set_value(current_media);
403 // Make sure the promise is not fulfilled twice
404 QObject::disconnect(c);
405 });
406
407 wait_for_signal(future);
408}
409
396QTEST_GUILESS_MAIN(tst_MediaPlaylist)410QTEST_GUILESS_MAIN(tst_MediaPlaylist)
397411
=== modified file 'tests/integration/tst_mediaplaylist.h'
--- tests/integration/tst_mediaplaylist.h 2015-07-10 14:49:05 +0000
+++ tests/integration/tst_mediaplaylist.h 2015-10-14 20:56:01 +0000
@@ -63,6 +63,8 @@
63 void verifyPlaybackModeCurrentItemInLoop();63 void verifyPlaybackModeCurrentItemInLoop();
64 void verifyPlaybackModeSequential();64 void verifyPlaybackModeSequential();
6565
66 void playReusePlayTrackList();
67
66private:68private:
67 template<typename R>69 template<typename R>
68 bool is_ready(std::future<R> const& f)70 bool is_ready(std::future<R> const& f)
@@ -70,6 +72,8 @@
7072
71 template<typename R>73 template<typename R>
72 void wait_for_signal(std::future<R> const& f);74 void wait_for_signal(std::future<R> const& f);
75
76 void waitTrackChange(QMediaPlaylist *playlist);
73};77};
7478
75#endif // TST_MEDIAPLAYLIST_H79#endif // TST_MEDIAPLAYLIST_H
7680
=== modified file 'tests/unit/service.cpp'
--- tests/unit/service.cpp 2015-06-08 19:15:43 +0000
+++ tests/unit/service.cpp 2015-10-14 20:56:01 +0000
@@ -54,6 +54,10 @@
54 return 0;54 return 0;
55}55}
5656
57void TestService::set_current_player(Player::PlayerKey)
58{
59}
60
57void TestService::pause_other_sessions(Player::PlayerKey)61void TestService::pause_other_sessions(Player::PlayerKey)
58{62{
59}63}
6064
=== modified file 'tests/unit/service.h'
--- tests/unit/service.h 2015-06-08 19:15:43 +0000
+++ tests/unit/service.h 2015-10-14 20:56:01 +0000
@@ -50,6 +50,7 @@
50 virtual void destroy_session(const std::string& uuid, const Player::Configuration&);50 virtual void destroy_session(const std::string& uuid, const Player::Configuration&);
51 virtual std::shared_ptr<Player> create_fixed_session(const std::string& name, const Player::Configuration&);51 virtual std::shared_ptr<Player> create_fixed_session(const std::string& name, const Player::Configuration&);
52 virtual std::shared_ptr<Player> resume_session(Player::PlayerKey);52 virtual std::shared_ptr<Player> resume_session(Player::PlayerKey);
53 virtual void set_current_player(Player::PlayerKey key);
53 virtual void pause_other_sessions(Player::PlayerKey);54 virtual void pause_other_sessions(Player::PlayerKey);
54};55};
55}56}

Subscribers

People subscribed via source and target branches

to all changes: