src/3rdparty/phonon/ds9/mediaobject.h
changeset 0 1918ee327afb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/3rdparty/phonon/ds9/mediaobject.h	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,313 @@
+/*  This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation, either version 2.1 or 3 of the License.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this library.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PHONON_MEDIAOBJECT_H
+#define PHONON_MEDIAOBJECT_H
+
+#include <phonon/mediaobjectinterface.h>
+#include <phonon/addoninterface.h>
+
+#include <QtCore/QHash>
+#include <QtCore/QObject>
+#include <QtCore/QQueue>
+#include <QtCore/QBasicTimer>
+#include <QtCore/QMutex>
+#include <QtCore/QThread>
+
+#include "backendnode.h"
+#include "mediagraph.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+    class MediaSource;
+
+    namespace DS9
+    {
+        class VideoWidget;
+        class AudioOutput;
+
+        class QWinWaitCondition
+        {
+        public:
+            QWinWaitCondition() : m_handle(::CreateEvent(0,0,0,0))
+            {
+            }
+
+            ~QWinWaitCondition()
+            {
+                ::CloseHandle(m_handle);
+            }
+
+            void reset()
+            {
+                //will block
+                ::ResetEvent(m_handle);
+            }
+
+            void set()
+            {
+                //will unblock
+                ::SetEvent(m_handle);
+            }
+
+            operator HANDLE()
+            {
+                return m_handle;
+            }
+
+            operator HEVENT()
+            {
+                return reinterpret_cast<HEVENT>(m_handle);
+            }
+
+
+        private:
+            HANDLE m_handle;
+        };
+
+        class WorkerThread : public QThread
+        {
+            Q_OBJECT
+        public:
+            WorkerThread();
+            ~WorkerThread();
+
+            virtual void run();
+
+            //wants to know as soon as the state is set
+            void addStateChangeRequest(Graph graph, OAFilterState, QList<Filter> = QList<Filter>());
+
+            quint16 addSeekRequest(Graph graph, qint64 time);
+            quint16 addUrlToRender(const QString &url);
+            quint16 addFilterToRender(const Filter &filter);
+
+            void replaceGraphForEventManagement(Graph newGraph, Graph oldGraph);
+
+    		void abortCurrentRender(qint16 renderId);
+
+            //tells the thread to stop processing
+            void signalStop();
+
+        Q_SIGNALS:
+            void asyncRenderFinished(quint16, HRESULT, Graph);
+            void asyncSeekingFinished(quint16, qint64);
+            void stateReady(Graph, Phonon::State);
+            void eventReady(Graph, long eventCode, long param1);
+
+        private:
+
+            enum Task
+            {
+                None,
+                Render,
+                Seek,
+                ChangeState,
+                ReplaceGraph //just updates recalls WaitForMultipleObject
+            };
+
+            struct Work
+            {
+                Work() : task(None), id(0), time(0) { }
+                Task task;
+                quint16 id;
+                Graph graph;
+                Graph oldGraph;
+                Filter filter;
+                QString url;
+                union
+                {
+                    qint64 time;
+                    OAFilterState state;
+                };
+                QList<Filter> decoders; //for the state change requests
+            };
+            void handleTask();
+
+            Work m_currentWork;
+            QQueue<Work> m_queue;
+            bool m_finished;
+            quint16 m_currentWorkId;
+            QWinWaitCondition m_waitCondition;
+            QMutex m_mutex; // mutex for the m_queue, m_finished and m_currentWorkId
+
+            //this is for WaitForMultipleObjects
+            struct
+            {
+                Graph graph;
+                HANDLE handle;
+            } m_graphHandle[FILTER_COUNT];
+        };
+
+
+        class MediaObject : public BackendNode, public Phonon::MediaObjectInterface
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+            , public Phonon::AddonInterface
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+        {
+            friend class Stream;
+            Q_OBJECT
+                Q_INTERFACES(Phonon::MediaObjectInterface 
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+                    Phonon::AddonInterface
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+                    )
+        public:
+            MediaObject(QObject *parent);
+            ~MediaObject();
+            Phonon::State state() const;
+            bool hasVideo() const;
+            bool isSeekable() const;
+            qint64 currentTime() const;
+            qint32 tickInterval() const;
+
+            void setTickInterval(qint32 newTickInterval);
+            void play();
+            void pause();
+            void stop();
+            void ensureStopped();
+            void seek(qint64 time);
+
+            QString errorString() const;
+            Phonon::ErrorType errorType() const;
+
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+            bool hasInterface(Interface) const;
+            QVariant interfaceCall(Interface iface, int command, const QList<QVariant> &params);
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+            qint64 totalTime() const;
+            qint32 prefinishMark() const;
+            void setPrefinishMark(qint32 newPrefinishMark);
+
+            qint32 transitionTime() const;
+            void setTransitionTime(qint32);
+
+            qint64 remainingTime() const;
+
+            MediaSource source() const;
+            void setSource(const MediaSource &source);
+            void setNextSource(const MediaSource &source);
+
+
+            //COM error management
+            bool catchComError(HRESULT hr);
+
+            void grabNode(BackendNode *node);
+            bool connectNodes(BackendNode *source, BackendNode *sink);
+            bool disconnectNodes(BackendNode *source, BackendNode *sink);
+
+            void switchFilters(int index, Filter oldFilter, Filter newFilter);
+
+            WorkerThread *workerThread();
+            void loadingFinished(MediaGraph *mg);
+            void seekingFinished(MediaGraph *mg);
+            MediaGraph *currentGraph() const;
+
+            //this is used by the backend only
+            Phonon::State transactionState;
+
+         private Q_SLOTS:
+            void switchToNextSource();
+            void slotStateReady(Graph, Phonon::State);
+            void handleEvents(Graph, long eventCode, long param1);
+            void finishLoading(quint16 workId, HRESULT hr, Graph);
+            void finishSeeking(quint16 workId, qint64 time);
+
+         Q_SIGNALS:
+            void stateChanged(Phonon::State newstate, Phonon::State oldstate);
+            void tick(qint64 time);
+            void metaDataChanged(QMultiMap<QString, QString>);
+            void seekableChanged(bool);
+            void hasVideoChanged(bool);
+            void bufferStatus(int);
+
+            // AddonInterface:
+            void titleChanged(int);
+            void availableTitlesChanged(int);
+            void chapterChanged(int);
+            void availableChaptersChanged(int);
+            void angleChanged(int);
+            void availableAnglesChanged(int);
+
+            void finished();
+            void prefinishMarkReached(qint32);
+            void aboutToFinish();
+            void totalTimeChanged(qint64 length) const;
+            void currentSourceChanged(const MediaSource &);
+
+        protected:
+            void setState(Phonon::State);
+            void timerEvent(QTimerEvent *e);
+
+        private:
+#ifndef QT_NO_PHONON_VIDEO
+            void updateVideoGeometry();
+#endif // QT_NO_PHONON_VIDEO
+            void handleComplete(IGraphBuilder *graph);
+            MediaGraph *nextGraph() const;
+
+            void updateTargetTick();
+            void updateStopPosition();
+
+            mutable QString m_errorString;
+            mutable Phonon::ErrorType m_errorType;
+
+            Phonon::State m_state;
+            Phonon::State m_nextState;
+            qint32 m_transitionTime;
+
+            qint32 m_prefinishMark;
+
+            QBasicTimer m_tickTimer;
+            qint32 m_tickInterval;
+
+            //the graph(s)
+            MediaGraph* m_graphs[FILTER_COUNT];
+
+            //...the videowidgets in the graph
+            QList<VideoWidget*> m_videoWidgets;
+            QList<AudioOutput*> m_audioOutputs;
+
+            bool m_buffering:1;
+            bool m_oldHasVideo:1;
+            bool m_prefinishMarkSent:1;
+            bool m_aboutToFinishSent:1;
+            bool m_nextSourceReadyToStart:1;
+
+            //for TitleInterface (and commands)
+#ifndef QT_NO_PHONON_MEDIACONTROLLER
+            bool m_autoplayTitles:1;
+            QList<qint64> m_titles;
+            int m_currentTitle;
+            int _iface_availableTitles() const;
+            int _iface_currentTitle() const;
+            void _iface_setCurrentTitle(int title, bool bseek = true);
+            void setTitles(const QList<qint64> &titles);
+            qint64 titleAbsolutePosition(int title) const;
+#endif //QT_NO_PHONON_MEDIACONTROLLER
+            qint64 m_targetTick;
+
+            WorkerThread m_thread;
+        };
+    }
+}
+
+QT_END_NAMESPACE
+
+#endif // PHONON_MEDIAOBJECT_H