17
17
#include "aalmediaplayercontrol.h"
18
18
#include "aalmediaplayerservice.h"
19
19
#include "aalmetadatareadercontrol.h"
20
#include "aalmediaplaylistcontrol.h"
21
#include "aalmediaplaylistprovider.h"
22
#include "aalutility.h"
24
#include <qmediaplaylistcontrol_p.h>
21
26
#include <core/media/service.h>
22
27
#include <core/media/track_list.h>
26
31
#include <QAbstractVideoSurface>
32
#include <QGuiApplication>
27
33
#include <QTimerEvent>
30
36
#include <qtubuntu_media_signals.h>
38
// Uncomment to re-enable media-hub Player session detach/reattach functionality
39
//#define DO_PLAYER_ATTACH_DETACH
32
41
// Defined in aalvideorenderercontrol.h
33
42
#ifdef MEASURE_PERFORMANCE
34
43
#include <QDateTime>
56
65
m_hubPlayerSession(NULL),
57
66
m_playbackStatusChangedConnection(the_void.connect([](){})),
58
67
m_errorConnection(the_void.connect([](){})),
68
m_endOfStreamConnection(the_void.connect([](){})),
59
69
m_mediaPlayerControl(nullptr),
60
70
m_videoOutput(nullptr),
61
m_metaDataReaderControl(nullptr),
71
m_mediaPlaylistControl(nullptr),
72
m_mediaPlaylistProvider(nullptr),
62
73
m_videoOutputReady(false),
63
74
m_firstPlayback(true),
64
75
m_cachedDuration(0),
76
m_mediaPlaylist(NULL),
77
m_doReattachSession(false)
66
78
#ifdef MEASURE_PERFORMANCE
67
79
, m_lastFrameDecodeStart(0)
68
80
, m_currentFrameDecodeStart(0)
73
85
m_hubService = media::Service::Client::instance();
87
// 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 disconnect
89
// it again. If we don't do this connect_signals() will never be able to attach
90
// to the relevant signals.
91
m_endOfStreamConnection.disconnect();
75
93
if (!newMediaPlayer())
76
94
qWarning() << "Failed to create a new media player backend. Video playback will not function." << endl;
94
111
m_errorConnection = m_hubPlayerSession->error().connect(
95
112
std::bind(&AalMediaPlayerService::onError, this, _1));
114
connect(qGuiApp, &QGuiApplication::applicationStateChanged, this, &AalMediaPlayerService::onApplicationStateChanged);
98
117
AalMediaPlayerService::~AalMediaPlayerService()
100
119
m_errorConnection.disconnect();
101
120
m_playbackStatusChangedConnection.disconnect();
103
deleteMediaPlayerControl();
105
123
deleteVideoRendererControl();
107
deleteMetaDataReaderControl();
125
if (m_mediaPlaylistControl)
126
deletePlaylistControl();
128
if (m_mediaPlayerControl)
129
deleteMediaPlayerControl();
131
if (m_hubPlayerSession)
132
destroyPlayerSession();
110
135
QMediaControl *AalMediaPlayerService::requestControl(const char *name)
125
150
return m_videoOutput;
128
if (qstrcmp(name, QMetaDataReaderControl_iid) == 0)
153
if (qstrcmp(name, QMediaPlaylistControl_iid) == 0)
130
if (not m_metaDataReaderControl)
131
createMetaDataReaderControl();
133
return m_metaDataReaderControl;
155
if (not m_mediaPlaylistControl)
156
createPlaylistControl();
158
// Pass on the media-hub Player object to the playlist control
159
if (m_hubPlayerSession)
160
m_mediaPlaylistControl->setPlayerSession(m_hubPlayerSession);
162
return m_mediaPlaylistControl;
139
168
void AalMediaPlayerService::releaseControl(QMediaControl *control)
141
if (control == m_mediaPlayerControl)
142
deleteMediaPlayerControl();
143
else if (control == m_videoOutput)
170
if (control == m_videoOutput)
144
171
deleteVideoRendererControl();
145
else if (control == m_metaDataReaderControl)
146
deleteMetaDataReaderControl();
151
174
bool AalMediaPlayerService::newMediaPlayer()
261
293
qDebug() << "Setting media to: " << url;
262
294
const media::Track::UriType uri(url.url().toStdString());
264
m_hubPlayerSession->open_uri(uri);
296
if (m_mediaPlaylistProvider != NULL)
297
m_mediaPlaylistProvider->addMedia(QMediaContent(url));
299
m_hubPlayerSession->open_uri(uri);
266
301
catch (const std::runtime_error &e) {
267
302
qWarning() << "Failed to open media " << url << ": " << e.what();
272
307
m_videoOutput->setupSurface();
310
void AalMediaPlayerService::setMedia(const QMediaContent &media)
312
if (m_hubPlayerSession == NULL)
314
qWarning() << "Cannot open media without a valid media-hub player session";
317
if (m_mediaPlaylistProvider == NULL)
319
qWarning() << "Cannot open media without a valid QMediaPlaylistProvider instance";
324
qWarning() << "Failed to set media source, media must be set." << endl;
328
qDebug() << "Setting media to: " << AalUtility::unescape(media);
330
m_mediaPlaylistProvider->addMedia(media);
332
catch (const std::runtime_error &e) {
333
qWarning() << "Failed to open media " << AalUtility::unescape(media) << ": " << e.what();
338
m_videoOutput->setupSurface();
275
341
void AalMediaPlayerService::play()
277
343
qDebug() << Q_FUNC_INFO;
495
557
m_videoOutput = new AalVideoRendererControl(this);
498
void AalMediaPlayerService::createMetaDataReaderControl()
560
void AalMediaPlayerService::createPlaylistControl()
500
562
qDebug() << Q_FUNC_INFO;
502
m_metaDataReaderControl = new AalMetaDataReaderControl(this);
504
if (m_mediaPlayerControl == nullptr)
505
qDebug() << "m_mediaPlayerControl is NULL, can't connect mediaChanged signal";
507
connect(m_mediaPlayerControl, SIGNAL(mediaChanged(QMediaContent)),
508
m_metaDataReaderControl, SLOT(onMediaChanged(QMediaContent)));
563
m_mediaPlaylistControl = new AalMediaPlaylistControl(this);
564
m_mediaPlaylistProvider = new AalMediaPlaylistProvider(this);
565
m_mediaPlaylistControl->setPlaylistProvider(m_mediaPlaylistProvider);
511
568
void AalMediaPlayerService::deleteMediaPlayerControl()
513
if (m_hubPlayerSession == NULL)
516
delete m_mediaPlayerControl;
517
m_mediaPlayerControl = NULL;
570
qDebug() << Q_FUNC_INFO;
572
if (not m_hubPlayerSession)
575
if (m_mediaPlayerControl)
577
delete m_mediaPlayerControl;
578
m_mediaPlayerControl = nullptr;
582
void AalMediaPlayerService::destroyPlayerSession()
584
qDebug() << Q_FUNC_INFO;
586
if (not m_hubPlayerSession)
590
// Invalidates the media-hub player session
591
m_hubService->destroy_session(m_sessionUuid, media::Player::Client::default_configuration());
592
m_sessionUuid.clear();
594
// When we arrived here the session is already invalid and we
595
// can safely drop the reference.
596
m_hubPlayerSession = nullptr;
598
catch (const std::runtime_error &e) {
599
qWarning() << "Failed to destroy existing media-hub player session: " << e.what();
520
603
void AalMediaPlayerService::deleteVideoRendererControl()
522
if (m_hubPlayerSession == nullptr)
525
delete m_videoOutput;
526
m_videoOutput = nullptr;
607
delete m_videoOutput;
608
m_videoOutput = nullptr;
529
void AalMediaPlayerService::deleteMetaDataReaderControl()
612
void AalMediaPlayerService::deletePlaylistControl()
531
if (m_hubPlayerSession == nullptr)
614
qDebug() << Q_FUNC_INFO;
534
delete m_metaDataReaderControl;
535
m_metaDataReaderControl = nullptr;
616
if (m_mediaPlaylistProvider)
618
delete m_mediaPlaylistProvider;
619
m_mediaPlaylistProvider = nullptr;
621
if (m_mediaPlaylistControl)
623
delete m_mediaPlaylistControl;
624
m_mediaPlaylistControl = nullptr;
538
628
void AalMediaPlayerService::signalQMediaPlayerError(const media::Player::Error &error)
598
687
qWarning() << "Unknown PlaybackStatus: " << m_newStatus;
690
qDebug() << "PlaybackStatus changed to: " << m_newStatus;
693
void AalMediaPlayerService::onApplicationStateChanged(Qt::ApplicationState state)
698
case Qt::ApplicationSuspended:
699
qDebug() << "** Application has been suspended";
701
case Qt::ApplicationHidden:
702
qDebug() << "** Application is now hidden";
704
case Qt::ApplicationInactive:
705
qDebug() << "** Application is now inactive";
706
#ifdef DO_PLAYER_ATTACH_DETACH
707
disconnect_signals();
708
m_hubService->detach_session(m_sessionUuid, media::Player::Client::default_configuration());
709
m_doReattachSession = true;
712
case Qt::ApplicationActive:
713
qDebug() << "** Application is now active";
714
#ifdef DO_PLAYER_ATTACH_DETACH
715
// Avoid doing this for when the client application first loads as this
716
// will break video playback
717
if (m_doReattachSession)
719
m_hubPlayerSession = m_hubService->reattach_session(m_sessionUuid, media::Player::Client::default_configuration());
720
// Make sure the client's status (position, duraiton, state, etc) are all correct when reattaching
721
// to the media-hub Player session
722
updateClientSignals();
728
qDebug() << "Unknown ApplicationState";
731
} catch (const std::runtime_error &e) {
732
qWarning() << "Failed to respond to ApplicationState change: " << e.what();
736
void AalMediaPlayerService::updateClientSignals()
738
qDebug() << Q_FUNC_INFO;
739
if (m_mediaPlayerControl == nullptr)
742
Q_EMIT m_mediaPlayerControl->durationChanged(duration());
743
Q_EMIT m_mediaPlayerControl->positionChanged(position());
746
case media::Player::PlaybackStatus::ready:
747
case media::Player::PlaybackStatus::stopped:
748
m_mediaPlayerControl->setState(QMediaPlayer::StoppedState);
750
case media::Player::PlaybackStatus::paused:
751
m_mediaPlayerControl->setState(QMediaPlayer::PausedState);
753
case media::Player::PlaybackStatus::playing:
754
m_mediaPlayerControl->setState(QMediaPlayer::PlayingState);
757
qWarning() << "Unknown PlaybackStatus: " << m_newStatus;
761
void AalMediaPlayerService::connect_signals()
763
if (!m_endOfStreamConnection.is_connected())
765
m_endOfStreamConnection = m_hubPlayerSession->end_of_stream().connect([this]()
767
m_firstPlayback = false;
768
Q_EMIT playbackComplete();
773
void AalMediaPlayerService::disconnect_signals()
775
if (m_endOfStreamConnection.is_connected())
776
m_endOfStreamConnection.disconnect();
602
779
void AalMediaPlayerService::onError(const core::ubuntu::media::Player::Error &error)
605
782
signalQMediaPlayerError(error);
608
void AalMediaPlayerService::pushPlaylist()
610
if (m_hubPlayerSession == NULL)
612
qWarning() << "Cannot push playlist without a valid media-hub player session";
616
if (m_mediaPlaylist == NULL)
619
for (int i = 0; i < m_mediaPlaylist->mediaCount(); i++)
621
const media::Track::UriType uri(m_mediaPlaylist->media(i).canonicalUrl().url().toStdString());
622
m_hubPlayerSession->track_list()->add_track_with_uri_at(uri, media::TrackList::after_empty_track(), false);
626
785
void AalMediaPlayerService::setPlayer(const std::shared_ptr<core::ubuntu::media::Player> &player)
628
787
m_hubPlayerSession = player;
630
789
createMediaPlayerControl();
631
790
createVideoRendererControl();
632
createMetaDataReaderControl();
634
m_hubPlayerSession->playback_status_changed().connect(
635
[this](const media::Player::PlaybackStatus &status) {
636
m_newStatus = status;
637
QMetaObject::invokeMethod(this, "onPlaybackStatusChanged", Qt::QueuedConnection);
792
if (!m_playbackStatusChangedConnection.is_connected())
794
m_playbackStatusChangedConnection = m_hubPlayerSession->playback_status_changed().connect(
795
[this](const media::Player::PlaybackStatus &status) {
796
m_newStatus = status;
797
QMetaObject::invokeMethod(this, "onPlaybackStatusChanged", Qt::QueuedConnection);
641
802
void AalMediaPlayerService::setService(const std::shared_ptr<core::ubuntu::media::Service> &service)