1 namespace Phonon
2 {
3
4
5 class MediaNode
6 {
7 public:
8 // must be connected to the backend to get information about the format
9 QList<Port> inputPorts(MediaStreamType type = Phonon::AllMedia);
10
11 QList<Port> outputPorts(MediaStreamType type = Phonon::AllMedia);
12
13
14 };
15
16 class MediaSource
17 {
18 //the parameter is used to filter
subStreams(MediaStreamType=AllMedia)19 QList<SubStreamDescription> subStreams(MediaStreamType = AllMedia)
20 {
21 //this just asks the source to give us back ots substream information
22 }
23 };
24
25 class MediaObject : public QObject
26 {
27 Q_OBJECT
28 public:
29 MediaObject(const MediaSource &, QObject *parent);
30 QList<DecoderParameter> decoderParameters(const Port &port);
31 /**
32 * Returns 0 if there are no parameters for the given port/decoder.
33 *
34 * \code
35 * media = new MediaObject;
36 * media->setCurrentSource("/music/file.ogg");
37 * output = new AudioOutput(Phonon::Music);
38 * Path path(media, output);
39 * QWidget *w = media->decoderParameterWidget(path.sourcePort());
40 * if (w) {
41 * w->setParent(this);
42 * // or
43 * // w->show();
44 * }
45 * \endcode
46 */
47 QWidget *decoderParameterWidget(const Port &port);
48
49 //the parameter is used to filter
currentSubStreams(MediaStreamType=AllMedia)50 QList<SubStreamDescription> currentSubStreams(MediaStreamType = AllMedia)
51 {
52 //this just asks the source to give us back ots substream information
53 }
54
55
56
selectSubstream(SubStreamDescription,const Port & port=Port ())57 bool selectSubstream(SubStreamDescription, const Port &port = Port())
58 {
59 //check the type of the port...
60 //if the port is invalid, it will do so for every suitable open ports
61 }
62
63 /*
64 * returns an invalid Port in case of errors.
65 * format is optional and can be defined later when the connection is done
66 */
openPort(MediaStreamType type,const char * format=0)67 Port openPort(MediaStreamType type, const char *format = 0)
68 {
69 //it gets the default stream
70 }
71
closePort(const Port &)72 bool closePort(const Port &)
73 {
74 }
75
isPortValid(const Port & p)76 bool isPortValid(const Port &p)
77 {
78 //checks if the port description can correspond to a port in this mediaobject
79 //will most likely be used a lot internally
80 }
81 };
82
83 class Path
84 {
85
86 //addition for the ports
87
88 Phonon::MediaStreamTypes types();
89 QList<Port> inputPorts, outputPorts;
90 };
91
92
93 // post 4.0:
94 class Port
95 {
96 //the real identifier of a port is its index ?
97 //then the format is just information you either give when creating the port
98 //or information you can retrieve once a connection is established
99
100 public:
101 // a null format means that any might be used and one is automatically selected when
102 // a connection is set up
Port(MediaStreamTypes types,int index=0,const char * format=0)103 Port(MediaStreamTypes types, int index = 0, const char *format = 0) : m_supportedTypes(types),
104 m_index(index), m_format(format), m_type(0)
105 {
106 }
107
Port(int index=-1)108 Port(int index = -1) : m_supportedTypes(AllMedia), m_index(index), m_format(0), m_type(0)
109 {
110 //gets the port whatever the mediatype is
111 }
112
isValid() const113 int isValid() const { return index != -1; }
114
type() const115 MediaStreamType type() const { return m_type; }
index() const116 int index() const { return m_index; }
format() const117 char *format() const { return m_format; }
118
119 private:
120 const MediaStreamTypes m_supportedtypes;
121 MediaStreamType m_type;
122 const int m_index; //index (depends on the media type?)
123 const char * const m_format;
124 };
125
createPath(MediaNode * source,const Port & srcport,MediaNode * sink,const Port & sinkport=Port (AllMedia))126 Path createPath(MediaNode *source, const Port &srcport, MediaNode *sink, const Port &sinkport = Port(AllMedia))
127 {
128 // if there's already a path to sink then return invalid Path
129 }
130
131 } // namespace Phonon
132
133 MediaObject *media;
134 {
135 media = new MediaObject("/video/foo.ogm");
136 // post 4.0:
137 /*
138 Path p = Phonon::createPath(media, Port(Phonon::Audio, 0, "pcm"), writer);
139 Path p = Phonon::createPath(media, writer);
140 p.mediaStreamTypes() & (Phonon::Audio | Phonon::Video)
141
142 //ports must always be valid... but they might be 'unconnectable' (depnding on the current source)
143 Port audio_port = media.openPort(Phonon::Audio, "pcm");
144 Port audio_port2 = media.openPort(Phonon::Audio);
145
146
147 //pb: when to call this
148 //is substream referring to the mediasource? Then you could possibly bind it any time?
149 media.selectSubStream(src.subStream(Phonon::Audio).first(), audio_port); <- selects the auid stream for the specified audio_port
150 media.selectSubStream(src.subStream(Phonon::Audio).first()); <-- does it for every audio port (of course only applies to 'src')
151
152 //do this for every source? is the way it works obvious?
153 //example
154 MediaObject o;
155 o.enqueue( QList<QUrl>() <<...
156 foreach(const MediaSource &src, o.queue()) {
157 // 'attach' would be better but what to do in case there is no port specified
158 media.selectSubStream( src.substream(Phonon::Audio)[1] );
159 }
160
161
162
163
164
165 //do we want to have so many formats or are the formats basically raw or decoded (with a specific format)?
166
167 AudioOutput *audioOut = new AudioOutput(Phonon::Music);
168 Path p = Phonon::createPath(media, audio_port2, writer); // <-- the format of audioport2 is selected to coded?
169 //shouldn't the port object be changed to reflect the port format has actually been set
170 Path p = Phonon::createPath(media, audio_port2, audioOut); // <-- this will fail
171 Path p = Phonon::createPath(media, media.outputPorts(Phonon::Video)[0], writer);
172
173 */
174
175 AudioOutput *audioOut = new AudioOutput(Phonon::Music);
176 Path audioPath = Phonon::createPath(media, audioOut);
177 Effect *audioEffect = new Effect(audioEffectDescription, this);
178 audioPath.insertEffect(audioEffect);
179
180 VideoWidget *videoWidget = new VideoWidget;
181 Path videoPath = Phonon::createPath(media, videoWidget);
182 Effect *videoEffect = videoPath.insertEffect(videoEffectDescription);
183
184 videoPath.disconnect();
185
186 media->play();
187
188 // post 4.0:
189 QList<SubtitleStreamDescription> l = media->availableSubtitleStreams();
190 media->setCurrentSubtitleStream(l.first());
191 Port port = media->openPort(Phonon::Subtitles);
192 media->setCurrentSubtitleStream(l.first(), port);
193 }
194 // Paths are not gone
195 delete media;
196 // Paths are gone now
197
198 // Mixing a second media
199 // =====================
200 // _____________
201 // | o |
202 // |audio1 in |
203 // | o |
204 // | audio out|
205 // | o |
206 // |audio2 in |
207 // |_____________|
208 MediaObject *media2 = new MediaObject("/music/foo2.ogg");
209 AudioMixer *amix = new AudioMixer;
210 Path *audioPath2 = new Path(media2, /*"audio",*/ amix);
211
212 Path *audioPath3 = new Path(amix, audioOut); // this unplugs audioPath from audioOut, otherwise this Path would not be possible
213 audioPath->changeOutput(amix); // and here we plug the audioPath back in, but into amix
214
215 media2->play();
216
217
218 // Writing to a file
219 // =================
220 // ____________
221 // | o |
222 // |audio in |
223 // | |
224 // | o |
225 // |video in |
226 // |____________|
227 FileWriter *writer = new FileWriter;
228 writer->setContainerFormat(...);
229 Encoder *audioEnc = writer->createAudioStream("name", ...);
230 Encoder *audioEnc2 = writer->createAudioStream("name", ...);
231 Encoder *videoEnc = writer->createVideoStream(...);
232 Path *writerAudioPath = new Path(media, audioEnc);
233 Path *writerAudioPath2 = new Path(media, audioEnc2);
234 Path *writerVideoPath = new Path(media, videoEnc);
235 writerAudioPath->insertEffect(audioEffect);
236 writerVideoPath->insertEffect(videoEffect);
237 media->setCurrentAudioStream(streamDesc, writerAudioPath);
238 media->setCurrentAudioStream(streamDesc2, writerAudioPath2);
239
240
241 // Visualization
242 // =============
243 // ____________
244 // | |
245 // | |
246 // | o o |
247 // |audio video|
248 // | in out |
249 // |____________|
250 VideoWidget *visWidget = new VideoWidget;
251 Visualization *vis = new Visualization;
252 Path *visAudioInPath = new Path(media, vis);
253 Path *visVideoOutPath = new Path(vis, visWidget);
254
255
256 // Synchronizing two MediaObjects
257 // ==============================
258 Synchronizer *sync = new Synchronizer;
259 sync->addMediaObject(media);
260 sync->addMediaObject(media2);
261 media->pause();// ?
262 sync->pause();
263 // media->state() == Phonon::PausedState == media2->state()
264 sync->play();
265 // media->state() == Phonon::PlayingState == media2->state()
266 ...
267