1/* This file is part of the KDE project.
2
3 Copyright (C) 2011 Torrie Fischer <tdfischer@kde.org>
4
5 This library is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation, either version 2.1 or 3 of the License.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with this library. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#ifndef Phonon_GSTREAMER_PIPELINE_H
19#define Phonon_GSTREAMER_PIPELINE_H
20
21#include "plugininstaller.h"
22#include <gst/gst.h>
23#include <phonon/MediaSource>
24#include <phonon/MediaController>
25#include <QtCore/QMutex>
26
27typedef QMultiMap<QString, QString> TagMap;
28
29namespace Phonon
30{
31namespace Gstreamer
32{
33
34class MediaObject;
35class PluginInstaller;
36class StreamReader;
37
38class Pipeline : public QObject
39{
40 Q_OBJECT
41
42 public:
43 Pipeline(QObject *parent = 0);
44 virtual ~Pipeline();
45 GstElement *element() const;
46 GstElement *videoGraph() const;
47 GstElement *audioGraph() const;
48 GstElement *videoElement() const;
49 GstElement *audioElement() const;
50 GstStateChangeReturn setState(GstState state);
51 GstState state() const;
52 Phonon::MediaSource currentSource() const;
53 void writeToDot(MediaObject *media, const QString &type);
54 bool queryDuration(GstFormat *format, gint64 *duration) const;
55 qint64 totalDuration() const;
56
57 static gboolean cb_eos(GstBus *bus, GstMessage *msg, gpointer data);
58 static gboolean cb_warning(GstBus *bus, GstMessage *msg, gpointer data);
59 static gboolean cb_duration(GstBus *bus, GstMessage *msg, gpointer data);
60 static gboolean cb_buffering(GstBus *bus, GstMessage *msg, gpointer data);
61 static gboolean cb_state(GstBus *bus, GstMessage *msg, gpointer data);
62 static gboolean cb_element(GstBus *bus, GstMessage *msg, gpointer data);
63 static gboolean cb_error(GstBus *bus, GstMessage *msg, gpointer data);
64 static gboolean cb_tag(GstBus *bus, GstMessage *msg, gpointer data);
65
66 static void cb_aboutToFinish(GstElement *appSrc, gpointer data);
67 static void cb_endOfPads(GstElement *playbin, gpointer data);
68
69 void setSource(const Phonon::MediaSource &source, bool reset = false);
70
71 static void cb_videoChanged(GstElement *playbin, gpointer data);
72 static void cb_textTagsChanged(GstElement *playbin, gint stream, gpointer data);
73 static void cb_audioTagsChanged(GstElement *playbin, gint stream, gpointer data);
74
75 GstElement *audioPipe();
76 GstElement *videoPipe();
77 GstElement *audioGraph();
78 GstElement *videoGraph();
79
80 bool videoIsAvailable() const;
81 bool audioIsAvailable() const;
82
83 QMultiMap<QString, QString> metaData() const;
84 //FIXME: We should be able to specify merging of metadata a la gstreamer's API design
85 void setMetaData(const QMultiMap<QString, QString> &newData);
86
87 QList<MediaController::NavigationMenu> availableMenus() const;
88 void updateNavigation();
89
90 bool seekToMSec(qint64 time);
91 bool isSeekable() const;
92
93 Phonon::State phononState() const;
94 static void cb_setupSource(GstElement *playbin, GParamSpec *spec, gpointer data);
95
96 qint64 position() const;
97 QByteArray captureDeviceURI(const MediaSource &source) const;
98
99 signals:
100 void windowIDNeeded();
101 void eos();
102 void warning(const QString &message);
103 void durationChanged(qint64 totalDuration);
104 void trackCountChanged(int tracks);
105 void buffering(int);
106 void stateChanged(GstState oldState, GstState newState);
107 void videoAvailabilityChanged(bool);
108 void textTagChanged(int stream);
109 void audioTagChanged(int stream);
110 void errorMessage(const QString &message, Phonon::ErrorType type);
111 // Only emitted when metadata changes in the middle of a stream.
112 void metaDataChanged(QMultiMap<QString, QString>);
113 void mouseOverActive(bool isActive);
114 void availableMenusChanged(QList<MediaController::NavigationMenu>);
115 void seekableChanged(bool isSeekable);
116 void aboutToFinish();
117 void streamChanged();
118
119 private:
120 GstPipeline *m_pipeline;
121 int m_bufferPercent;
122
123 // Keeps track of whether or not we jump to GST_STATE_PLAYING after plugin installtion is finished.
124 // Otherwise, it is possible to jump to another track, play a few seconds, pause, then finish installation
125 // and spontaniously start playback without user action.
126 bool m_resumeAfterInstall;
127 // Determines if we're using an QIODevice stream
128 bool m_isStream;
129 bool m_isHttpUrl;
130 QMultiMap<QString, QString> m_metaData;
131 QList<MediaController::NavigationMenu> m_menus;
132 Phonon::MediaSource m_currentSource;
133 PluginInstaller *m_installer;
134 StreamReader *m_reader;
135 GstElement *m_audioGraph;
136 GstElement *m_videoGraph;
137 GstElement *m_audioPipe;
138 GstElement *m_videoPipe;
139
140 bool m_seeking;
141 bool m_resetting;
142 qint64 m_posAtReset;
143 QMutex m_tagLock;
144
145 private Q_SLOTS:
146 void pluginInstallFailure(const QString &msg);
147 void pluginInstallComplete();
148 void pluginInstallStarted();
149
150};
151
152}
153}
154
155#endif // Phonon_GSTREAMER_PIPELINE_H
156