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