23#include "mediaobject.h"
24#include "mediaobject_p.h"
27#include "mediaobjectinterface.h"
28#include "audiooutput.h"
29#include "phonondefs_p.h"
30#include "abstractmediastream.h"
31#include "abstractmediastream_p.h"
32#include "frontendinterface_p.h"
34#include <QStringBuilder>
40#include "phononnamespace_p.h"
41#include "platform_p.h"
42#include "statesvalidator_p.h"
44#define PHONON_CLASSNAME MediaObject
45#define PHONON_INTERFACENAME MediaObjectInterface
54 if (d->m_backendObject) {
72#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
73 if (d->errorOverride) {
76 if (d->ignoreLoadingToBufferingStateChange) {
77 return BufferingState;
79 if (d->ignoreErrorToLoadingStateChange) {
83 if (!d->m_backendObject) {
86 return INTERFACE_CALL(
state());
89PHONON_INTERFACE_SETTER(setTickInterval, tickInterval, qint32)
90PHONON_INTERFACE_GETTER(qint32, tickInterval, d->tickInterval)
91PHONON_INTERFACE_GETTER(
bool, hasVideo, false)
92PHONON_INTERFACE_GETTER(
bool, isSeekable, false)
93PHONON_INTERFACE_GETTER(qint64, currentTime, d->currentTime)
95static inline
bool isPlayable(const
MediaSource::Type t)
103 if (d->backendObject() && isPlayable(d->mediaSource.type())) {
104 INTERFACE_CALL(
play());
111 if (d->backendObject() && isPlayable(d->mediaSource.type())) {
112 INTERFACE_CALL(
pause());
119 if (d->backendObject() && isPlayable(d->mediaSource.type())) {
120 INTERFACE_CALL(
stop());
127 if (d->backendObject() && isPlayable(d->mediaSource.type())) {
128 INTERFACE_CALL(
seek(time));
134 if (
state() == Phonon::ErrorState) {
136#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
137 if (d->errorOverride) {
138 return d->errorString;
148 if (
state() == Phonon::ErrorState) {
150#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
151 if (d->errorOverride) {
157 return Phonon::NoError;
173 case TracknumberMetaData:
175 case DescriptionMetaData:
177 case MusicBrainzDiscIdMetaData:
186 return d->metaData.values(key);
195PHONON_INTERFACE_GETTER(qint32, prefinishMark, d->prefinishMark)
196PHONON_INTERFACE_SETTER(setPrefinishMark, prefinishMark, qint32)
198PHONON_INTERFACE_GETTER(qint32, transitionTime, d->transitionTime)
199PHONON_INTERFACE_SETTER(setTransitionTime, transitionTime, qint32)
204 if (!d->m_backendObject) {
207 return INTERFACE_CALL(totalTime());
213 if (!d->m_backendObject) {
226 return d->mediaSource;
232 if (!k_ptr->backendObject()) {
233 d->mediaSource = newSource;
237 pDebug() << Q_FUNC_INFO << newSource.
type() << newSource.
url() << newSource.
deviceName();
242 d->mediaSource = newSource;
244#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
245 d->abstractStream =
nullptr;
247 Q_ASSERT(d->mediaSource.stream());
248 d->mediaSource.stream()->d_func()->setMediaObjectPrivate(d);
252 d->playingQueuedSource =
false;
254 INTERFACE_CALL(setSource(d->mediaSource));
260 d->sourceQueue.clear();
267 return d->sourceQueue;
273 d->sourceQueue.clear();
280 d->sourceQueue.clear();
287 if (!isPlayable(d->mediaSource.type())) {
291 d->sourceQueue << source;
297 for (
int i = 0; i < sources.
count(); ++i) {
304 for (
int i = 0; i < urls.
count(); ++i) {
312 d->sourceQueue.clear();
315bool MediaObjectPrivate::aboutToDeleteBackendObject()
318 prefinishMark = pINTERFACE_CALL(prefinishMark());
319 transitionTime = pINTERFACE_CALL(transitionTime());
321 if (m_backendObject) {
322 state = pINTERFACE_CALL(state());
323 currentTime = pINTERFACE_CALL(currentTime());
324 tickInterval = pINTERFACE_CALL(tickInterval());
329#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
330void MediaObjectPrivate::streamError(Phonon::ErrorType type,
const QString &text)
333 State lastState = q->state();
334 errorOverride =
true;
344void MediaObjectPrivate::_k_stateChanged(Phonon::State newstate, Phonon::State oldstate)
350 errorOverride =
false;
351 if (newstate == ErrorState) {
354 oldstate = ErrorState;
359 emit q->stateChanged(newstate, oldstate);
364 if (newstate == Phonon::ErrorState && !abstractStream) {
365 abstractStream = Platform::createMediaStream(mediaSource.url(), q);
366 if (!abstractStream) {
367 pDebug() <<
"backend MediaObject reached ErrorState, no KIO fallback available";
368 emit q->stateChanged(newstate, oldstate);
371 pDebug() <<
"backend MediaObject reached ErrorState, trying Platform::createMediaStream now";
372 ignoreLoadingToBufferingStateChange =
false;
373 ignoreErrorToLoadingStateChange =
false;
375 case Phonon::BufferingState:
378 ignoreLoadingToBufferingStateChange =
true;
380 case Phonon::LoadingState:
381 ignoreErrorToLoadingStateChange =
true;
385 pError() <<
"backend MediaObject reached ErrorState after " << oldstate
386 <<
". It seems a KioMediaStream will not help here, trying anyway.";
387 emit q->stateChanged(Phonon::LoadingState, oldstate);
390 abstractStream->d_func()->setMediaObjectPrivate(
this);
391 MediaSource mediaSource(abstractStream);
392 mediaSource.setAutoDelete(
true);
393 pINTERFACE_CALL(setSource(mediaSource));
394 if (oldstate == Phonon::BufferingState) {
398 }
else if (ignoreLoadingToBufferingStateChange &&
400 oldstate == Phonon::LoadingState) {
401 if (newstate != Phonon::BufferingState) {
402 emit q->stateChanged(newstate, Phonon::BufferingState);
405 }
else if (ignoreErrorToLoadingStateChange && abstractStream && oldstate == ErrorState) {
406 if (newstate != LoadingState) {
407 emit q->stateChanged(newstate, Phonon::LoadingState);
412 emit q->stateChanged(newstate, oldstate);
415void MediaObjectPrivate::_k_aboutToFinish()
418 pDebug() << Q_FUNC_INFO;
420#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
421 abstractStream =
nullptr;
424 if (sourceQueue.isEmpty()) {
425 emit q->aboutToFinish();
426 if (sourceQueue.isEmpty()) {
431 mediaSource = sourceQueue.head();
432 playingQueuedSource =
true;
433 pINTERFACE_CALL(setNextSource(mediaSource));
436 validator->sourceQueued();
439void MediaObjectPrivate::_k_currentSourceChanged(
const MediaSource &source)
442 pDebug() << Q_FUNC_INFO;
444 if (!sourceQueue.isEmpty() && sourceQueue.head() == source)
445 sourceQueue.dequeue();
447 emit q->currentSourceChanged(source);
450void MediaObjectPrivate::setupBackendObject()
453 Q_ASSERT(m_backendObject);
461 qRegisterMetaType<MediaSource>(
"MediaSource");
462 qRegisterMetaType<QMultiMap<QString, QString> >(
"QMultiMap<QString, QString>");
465 validator =
new StatesValidator(q);
467#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
468 QObject::connect(m_backendObject, SIGNAL(stateChanged(Phonon::State,Phonon::State)),
471 QObject::connect(m_backendObject, SIGNAL(stateChanged(Phonon::State,Phonon::State)),
474#ifndef QT_NO_PHONON_VIDEO
495 QObject::connect(m_backendObject, SIGNAL(currentSourceChanged(MediaSource)),
499 pINTERFACE_CALL(setTickInterval(tickInterval));
500 pINTERFACE_CALL(setPrefinishMark(prefinishMark));
501 pINTERFACE_CALL(setTransitionTime(transitionTime));
517 const State backendState = pINTERFACE_CALL(state());
518 if (state != backendState && state != ErrorState) {
522 pDebug() <<
"emitting a state change because the backend object has been replaced";
523 emit q->stateChanged(backendState, state);
524 state = backendState;
527#ifndef QT_NO_PHONON_MEDIACONTROLLER
528 for (
int i = 0 ; i < interfaceList.count(); ++i) {
529 interfaceList.at(i)->_backendObjectChanged();
534 if (isPlayable(mediaSource.type())) {
535#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
537 Q_ASSERT(mediaSource.stream());
538 mediaSource.stream()->d_func()->setMediaObjectPrivate(
this);
541 pINTERFACE_CALL(setSource(mediaSource));
545void MediaObjectPrivate::_k_resumePlay()
547 qobject_cast<MediaObjectInterface *>(m_backendObject)->play();
548 if (currentTime > 0) {
549 qobject_cast<MediaObjectInterface *>(m_backendObject)->seek(currentTime);
553void MediaObjectPrivate::_k_resumePause()
555 pINTERFACE_CALL(
pause());
556 if (currentTime > 0) {
557 qobject_cast<MediaObjectInterface *>(m_backendObject)->seek(currentTime);
563 metaData = newMetaData;
564 emit q_func()->metaDataChanged();
567void MediaObjectPrivate::phononObjectDestroyed(MediaNodePrivate *bp)
576MediaObject *createPlayer(Phonon::Category category,
const MediaSource &source)
578 MediaObject *mo =
new MediaObject;
579 AudioOutput *ao =
new AudioOutput(category, mo);
581 if (isPlayable(source.type())) {
582 mo->setCurrentSource(source);
589#include "moc_mediaobject.cpp"
591#undef PHONON_CLASSNAME
592#undef PHONON_INTERFACENAME
Q_SCRIPTABLE Q_NOREPLY void pause()
VehicleSection::Type type(QStringView coachNumber, QStringView coachClassification)
const_reference at(qsizetype i) const const
qsizetype count() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)