# # SVN commit 941287 by jbache: # # Phonon/Gstreamer: Add support for audio CD tracks # through the MediaController interface. # # This patch adds basic support for cdda to the # GStreamer backend. It's still somewhat limited # by the limited autodetection of CD media but should # be enough to make KSCD work with GStreamer. # # # # M +96 -4 mediaobject.cpp # M +35 -14 mediaobject.h # Index: gstreamer/mediaobject.h =================================================================== --- gstreamer/mediaobject.h (revision 941286) +++ gstreamer/mediaobject.h (revision 941287) @@ -21,7 +21,6 @@ #include "backend.h" #include "common.h" #include "medianode.h" - #include <phonon/mediaobjectinterface.h> #include <phonon/addoninterface.h> @@ -32,7 +31,6 @@ #include <QtCore/QDate> #include <QtCore/QEvent> #include <QtCore/QUrl> - #include <gst/gst.h> QT_BEGIN_NAMESPACE @@ -50,11 +48,20 @@ class VideoPath; class AudioOutput; -class MediaObject : public QObject, public MediaObjectInterface, public AddonInterface, public MediaNode +class MediaObject : public QObject, public MediaObjectInterface +#ifndef QT_NO_PHONON_MEDIACONTROLLER + , public AddonInterface +#endif + , public MediaNode { friend class Stream; Q_OBJECT - Q_INTERFACES(Phonon::MediaObjectInterface Phonon::AddonInterface Phonon::Gstreamer::MediaNode) + Q_INTERFACES(Phonon::MediaObjectInterface +#ifndef QT_NO_PHONON_MEDIACONTROLLER + Phonon::AddonInterface +#endif + Phonon::Gstreamer::MediaNode + ) public: @@ -93,16 +100,10 @@ MediaSource source() const; // No additional interfaces currently supported - bool hasInterface(Interface) const - { - return false; - } - - QVariant interfaceCall(Interface, int, const QList<QVariant> &) - { - return QVariant(); - } - +#ifndef QT_NO_PHONON_MEDIACONTROLLER + bool hasInterface(Interface) const; + QVariant interfaceCall(Interface, int, const QList<QVariant> &); +#endif bool isLoading() { return m_loading; @@ -176,6 +177,19 @@ QMultiMap<QString, QString> metaData(); void setMetaData(QMultiMap<QString, QString> newData); + // AddonInterface: + void titleChanged(int); + void availableTitlesChanged(int); + + // Not implemented + void chapterChanged(int); + void availableChaptersChanged(int); + void angleChanged(int); + void availableAnglesChanged(int); + + void availableSubtitlesChanged(); + void availableAudioChannelsChanged(); + protected: void beginLoad(); void loadingComplete(); @@ -219,6 +233,10 @@ void updateSeekable(); qint64 getPipelinePos() const; + int _iface_availableTitles() const; + int _iface_currentTitle() const; + void _iface_setCurrentTitle(int title); + bool m_resumeState; State m_oldState; quint64 m_oldPos; @@ -264,6 +282,9 @@ bool m_resetNeeded; QStringList m_missingCodecs; QMultiMap<QString, QString> m_metaData; + bool m_autoplayTitles; + int m_availableTitles; + int m_currentTitle; }; } } //namespace Phonon::Gstreamer --- gstreamer/mediaobject.cpp~ 2009-03-20 01:01:06.000000000 +0100 +++ gstreamer/mediaobject.cpp 2009-03-20 01:10:25.000000000 +0100 @@ -81,6 +81,9 @@ , m_videoGraph(0) , m_previousTickTime(-1) , m_resetNeeded(false) + , m_autoplayTitles(true) + , m_availableTitles(0) + , m_currentTitle(1) { qRegisterMetaType<GstCaps*>("GstCaps*"); qRegisterMetaType<State>("State"); @@ -953,8 +956,13 @@ break; case MediaSource::Disc: // CD tracks can be specified by setting the url in the following way uri=cdda:4 - m_backend->logMessage("Source type Disc not currently supported", Backend::Warning, this); - setError(tr("Could not open media source."), Phonon::NormalError); + { + QUrl cdurl(QLatin1String("cdda://")); + if (createPipefromURL(cdurl)) + m_loading = true; + else + setError(tr("Could not open media source.")); + } break; default: @@ -1005,6 +1013,18 @@ m_hasVideo = m_videoStreamFound; emit hasVideoChanged(m_hasVideo); } + + m_availableTitles = 1; + gint64 titleCount; + GstFormat format = gst_format_get_by_nick("track"); + if (gst_element_query_duration (m_pipeline, &format, &titleCount)) { + int oldAvailableTitles = m_availableTitles; + m_availableTitles = (int)titleCount; + if (m_availableTitles != oldAvailableTitles) { + emit availableTitlesChanged(m_availableTitles); + m_backend->logMessage(QString("Available titles changed: %0").arg(m_availableTitles), Backend::Info, this); + } + } } void MediaObject::setPrefinishMark(qint32 newPrefinishMark) @@ -1487,6 +1507,13 @@ if (!m_seekable) m_atEndOfStream = true; + if (m_autoplayTitles && + m_availableTitles > 1 && + m_currentTitle < m_availableTitles) { + _iface_setCurrentTitle(m_currentTitle + 1); + return; + } + if (m_nextSource.type() != MediaSource::Invalid && m_nextSource.type() != MediaSource::Empty) { // We only emit finish when the queue is actually empty QTimer::singleShot (qMax(0, transitionTime()), this, SLOT(beginPlay())); @@ -1515,6 +1542,71 @@ notify(&event); } +#ifndef QT_NO_PHONON_MEDIACONTROLLER +//interface management +bool MediaObject::hasInterface(Interface iface) const +{ + return iface == AddonInterface::TitleInterface; +} + +QVariant MediaObject::interfaceCall(Interface iface, int command, const QList<QVariant> ¶ms) +{ + if (hasInterface(iface)) { + + switch (iface) + { + case TitleInterface: + switch (command) + { + case availableTitles: + return _iface_availableTitles(); + case title: + return _iface_currentTitle(); + case setTitle: + _iface_setCurrentTitle(params.first().toInt()); + break; + case autoplayTitles: + return m_autoplayTitles; + case setAutoplayTitles: + m_autoplayTitles = params.first().toBool(); + break; + } + break; + default: + break; + } + } + return QVariant(); +} +#endif + +int MediaObject::_iface_availableTitles() const +{ + return m_availableTitles; +} + +int MediaObject::_iface_currentTitle() const +{ + return m_currentTitle; +} + +void MediaObject::_iface_setCurrentTitle(int title) +{ + GstFormat trackFormat = gst_format_get_by_nick("track"); + m_backend->logMessage(QString("setCurrentTitle %0").arg(title), Backend::Info, this); + if ((title == m_currentTitle) || (title < 1) || (title > m_availableTitles)) + return; + + m_currentTitle = title; + + //let's seek to the beginning of the song + if (gst_element_seek_simple(m_pipeline, trackFormat, GST_SEEK_FLAG_FLUSH, m_currentTitle - 1)) { + updateTotalTime(); + m_atEndOfStream = false; + emit titleChanged(title); + emit totalTimeChanged(totalTime()); + } +} } // ns Gstreamer } // ns Phonon