1 | /* This file is part of the KDE project |
2 | Copyright (C) 2007 Matthias Kretz <kretz@kde.org> |
3 | |
4 | This library is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU Lesser General Public |
6 | License as published by the Free Software Foundation; either |
7 | version 2.1 of the License, or (at your option) version 3, or any |
8 | later version accepted by the membership of KDE e.V. (or its |
9 | successor approved by the membership of KDE e.V.), Nokia Corporation |
10 | (or its successors, if any) and the KDE Free Qt Foundation, which shall |
11 | act as a proxy defined in Section 6 of version 3 of the license. |
12 | |
13 | This library is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 | Lesser General Public License for more details. |
17 | |
18 | You should have received a copy of the GNU Lesser General Public |
19 | License along with this library. If not, see <http://www.gnu.org/licenses/>. |
20 | |
21 | */ |
22 | |
23 | #include "mediasource.h" |
24 | #include "mediasource_p.h" |
25 | #include "iodevicestream_p.h" |
26 | #include "abstractmediastream_p.h" |
27 | #include "globalconfig.h" |
28 | |
29 | #include <QFileInfo> |
30 | #include <QFile> |
31 | |
32 | namespace Phonon |
33 | { |
34 | |
35 | MediaSource::MediaSource(MediaSourcePrivate &dd) |
36 | : d(&dd) |
37 | { |
38 | } |
39 | |
40 | MediaSource::MediaSource() |
41 | : d(new MediaSourcePrivate(Empty)) |
42 | { |
43 | } |
44 | |
45 | MediaSource::MediaSource(const QString &filename) |
46 | : d(new MediaSourcePrivate(LocalFile)) |
47 | { |
48 | if (filename.startsWith(s: QLatin1String(":/" )) || filename.startsWith(s: QLatin1String("qrc:///" ))) { |
49 | #ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM |
50 | d->url.setScheme("qrc" ); |
51 | d->url.setPath(path: filename.mid(position: filename.startsWith(c: QLatin1Char(':')) ? 1 : 6)); |
52 | |
53 | // QFile needs :/ syntax |
54 | QString path(QLatin1Char(':') + d->url.path()); |
55 | |
56 | if (QFile::exists(fileName: path)) { |
57 | d->type = Stream; |
58 | d->ioDevice = new QFile(path); |
59 | d->setStream(new IODeviceStream(d->ioDevice, d->ioDevice)); |
60 | } else { |
61 | d->type = Invalid; |
62 | } |
63 | #else |
64 | d->type = Invalid; |
65 | #endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM |
66 | } else { |
67 | const QFileInfo fileinfo(filename); |
68 | if (fileinfo.exists()) { |
69 | d->url = QUrl::fromLocalFile(localfile: fileinfo.absoluteFilePath()); |
70 | if (!d->url.host().isEmpty()) { |
71 | // filename points to a file on a network share (eg \\host\share\path) |
72 | d->type = Url; |
73 | } |
74 | } else { |
75 | d->url = filename; |
76 | if (d->url.isValid()) { |
77 | d->type = Url; |
78 | } else { |
79 | d->type = Invalid; |
80 | } |
81 | } |
82 | } |
83 | } |
84 | |
85 | MediaSource::MediaSource(const QUrl &url) |
86 | : d(new MediaSourcePrivate(Url)) |
87 | { |
88 | if (url.isValid()) { |
89 | if (url.scheme() == QLatin1String("qrc" )) { |
90 | #ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM |
91 | // QFile needs :/ syntax |
92 | QString path(QLatin1Char(':') + url.path()); |
93 | |
94 | if (QFile::exists(fileName: path)) { |
95 | d->type = Stream; |
96 | d->ioDevice = new QFile(path); |
97 | d->setStream(new IODeviceStream(d->ioDevice, d->ioDevice)); |
98 | } else { |
99 | d->type = Invalid; |
100 | } |
101 | #else |
102 | d->type = Invalid; |
103 | #endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM |
104 | } |
105 | d->url = url; |
106 | } else { |
107 | d->type = Invalid; |
108 | } |
109 | } |
110 | |
111 | MediaSource::MediaSource(DiscType dt, const QString &deviceName) |
112 | : d(new MediaSourcePrivate(Disc)) |
113 | { |
114 | if (dt == NoDisc) { |
115 | d->type = Invalid; |
116 | return; |
117 | } |
118 | d->discType = dt; |
119 | d->deviceName = deviceName; |
120 | } |
121 | |
122 | // NOTE: this is deprecated |
123 | MediaSource::MediaSource(const DeviceAccess &) |
124 | : d(new MediaSourcePrivate(Invalid)) |
125 | { |
126 | } |
127 | |
128 | #ifndef PHONON_NO_AUDIOCAPTURE |
129 | MediaSource::MediaSource(const AudioCaptureDevice& device) |
130 | : d(new MediaSourcePrivate(CaptureDevice)) |
131 | { |
132 | d->setCaptureDevices(audioDevice: device, videoDevice: VideoCaptureDevice()); |
133 | } |
134 | #endif //PHONON_NO_AUDIOCAPTURE |
135 | |
136 | #ifndef PHONON_NO_VIDEOCAPTURE |
137 | MediaSource::MediaSource(const VideoCaptureDevice& device) |
138 | : d(new MediaSourcePrivate(CaptureDevice)) |
139 | { |
140 | d->setCaptureDevices(audioDevice: AudioCaptureDevice(), videoDevice: device); |
141 | } |
142 | #endif //PHONON_NO_VIDEOCAPTURE |
143 | |
144 | #if !defined(PHONON_NO_VIDEOCAPTURE) && !defined(PHONON_NO_AUDIOCAPTURE) |
145 | MediaSource::MediaSource(CaptureCategory category) |
146 | : d(new MediaSourcePrivate(AudioVideoCapture)) |
147 | { |
148 | d->setCaptureDevices(category); |
149 | } |
150 | |
151 | MediaSource::MediaSource(Capture::DeviceType deviceType, CaptureCategory category) |
152 | : d(new MediaSourcePrivate(CaptureDevice)) |
153 | { |
154 | d->setCaptureDevice(deviceType, category); |
155 | } |
156 | #endif // !PHONON_NO_VIDEOCAPTURE && !PHONON_NO_AUDIOCAPTURE |
157 | |
158 | #ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM |
159 | MediaSource::MediaSource(AbstractMediaStream *stream) |
160 | : d(new MediaSourcePrivate(Stream)) |
161 | { |
162 | if (stream) { |
163 | d->setStream(stream); |
164 | } else { |
165 | d->type = Invalid; |
166 | } |
167 | } |
168 | |
169 | MediaSource::MediaSource(QIODevice *ioDevice) |
170 | : d(new MediaSourcePrivate(Stream)) |
171 | { |
172 | if (ioDevice) { |
173 | d->setStream(new IODeviceStream(ioDevice, ioDevice)); |
174 | d->ioDevice = ioDevice; |
175 | } else { |
176 | d->type = Invalid; |
177 | } |
178 | } |
179 | #endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM |
180 | |
181 | /* post 4.0 |
182 | MediaSource::MediaSource(const QList<MediaSource> &mediaList) |
183 | : d(new MediaSourcePrivate(Link)) |
184 | { |
185 | d->linkedSources = mediaList; |
186 | foreach (MediaSource ms, mediaList) { |
187 | Q_ASSERT(ms.type() != Link); |
188 | } |
189 | } |
190 | |
191 | QList<MediaSource> MediaSource::substreams() const |
192 | { |
193 | return d->linkedSources; |
194 | } |
195 | */ |
196 | |
197 | MediaSource::~MediaSource() |
198 | { |
199 | } |
200 | |
201 | MediaSourcePrivate::~MediaSourcePrivate() |
202 | { |
203 | #ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM |
204 | if (autoDelete) { |
205 | //here we use deleteLater because this object |
206 | //might be destroyed from another thread |
207 | if (stream) |
208 | stream->deleteLater(); |
209 | if (ioDevice) |
210 | ioDevice->deleteLater(); |
211 | } |
212 | #endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM |
213 | } |
214 | |
215 | MediaSource::MediaSource(const MediaSource &rhs) |
216 | : d(rhs.d) |
217 | { |
218 | } |
219 | |
220 | MediaSource &MediaSource::operator=(const MediaSource &rhs) |
221 | { |
222 | d = rhs.d; |
223 | return *this; |
224 | } |
225 | |
226 | bool MediaSource::operator==(const MediaSource &rhs) const |
227 | { |
228 | return d == rhs.d; |
229 | } |
230 | |
231 | void MediaSource::setAutoDelete(bool autoDelete) |
232 | { |
233 | d->autoDelete = autoDelete; |
234 | } |
235 | |
236 | bool MediaSource::autoDelete() const |
237 | { |
238 | return d->autoDelete; |
239 | } |
240 | |
241 | MediaSource::Type MediaSource::type() const |
242 | { |
243 | #ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM |
244 | if (d->type == Stream && d->stream == nullptr) { |
245 | return Invalid; |
246 | } |
247 | #endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM |
248 | return d->type; |
249 | } |
250 | |
251 | QString MediaSource::fileName() const |
252 | { |
253 | return d->url.toLocalFile(); |
254 | } |
255 | |
256 | Mrl MediaSource::mrl() const |
257 | { |
258 | return Mrl(d->url); |
259 | } |
260 | |
261 | QUrl MediaSource::url() const |
262 | { |
263 | return d->url; |
264 | } |
265 | |
266 | DiscType MediaSource::discType() const |
267 | { |
268 | return d->discType; |
269 | } |
270 | |
271 | const DeviceAccessList& MediaSource::deviceAccessList() const |
272 | { |
273 | #ifndef PHONON_NO_AUDIOCAPTURE |
274 | if (d->audioCaptureDevice.isValid()) |
275 | return d->audioDeviceAccessList; |
276 | #endif |
277 | |
278 | #ifndef PHONON_NO_VIDEOCAPTURE |
279 | if (d->videoCaptureDevice.isValid()) |
280 | return d->videoDeviceAccessList; |
281 | #endif |
282 | |
283 | return d->audioDeviceAccessList; // It should be invalid |
284 | } |
285 | |
286 | const DeviceAccessList& MediaSource::audioDeviceAccessList() const |
287 | { |
288 | return d->audioDeviceAccessList; |
289 | } |
290 | |
291 | const DeviceAccessList& MediaSource::videoDeviceAccessList() const |
292 | { |
293 | return d->videoDeviceAccessList; |
294 | } |
295 | |
296 | QString MediaSource::deviceName() const |
297 | { |
298 | return d->deviceName; |
299 | } |
300 | |
301 | #ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM |
302 | AbstractMediaStream *MediaSource::stream() const |
303 | { |
304 | return d->stream; |
305 | } |
306 | |
307 | void MediaSourcePrivate::setStream(AbstractMediaStream *s) |
308 | { |
309 | stream = s; |
310 | } |
311 | #endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM |
312 | |
313 | #ifndef PHONON_NO_AUDIOCAPTURE |
314 | AudioCaptureDevice MediaSource::audioCaptureDevice() const |
315 | { |
316 | return d->audioCaptureDevice; |
317 | } |
318 | #endif //PHONON_NO_AUDIOCAPTURE |
319 | |
320 | #ifndef PHONON_NO_VIDEOCAPTURE |
321 | VideoCaptureDevice MediaSource::videoCaptureDevice() const |
322 | { |
323 | return d->videoCaptureDevice; |
324 | } |
325 | #endif //PHONON_NO_VIDEOCAPTURE |
326 | |
327 | #if !defined(PHONON_NO_VIDEOCAPTURE) && !defined(PHONON_NO_AUDIOCAPTURE) |
328 | void MediaSourcePrivate::setCaptureDevice(Capture::DeviceType deviceType, CaptureCategory category) |
329 | { |
330 | switch (deviceType) { |
331 | case Capture::VideoType: { |
332 | setCaptureDevices(audioDevice: AudioCaptureDevice(), |
333 | videoDevice: VideoCaptureDevice::fromIndex(index: GlobalConfig().videoCaptureDeviceFor(category))); |
334 | break; |
335 | } |
336 | case Capture::AudioType: { |
337 | setCaptureDevices( |
338 | audioDevice: AudioCaptureDevice::fromIndex(index: GlobalConfig().audioCaptureDeviceFor(category)), videoDevice: VideoCaptureDevice()); |
339 | break; |
340 | } |
341 | } |
342 | } |
343 | |
344 | void MediaSourcePrivate::setCaptureDevices(CaptureCategory category) |
345 | { |
346 | setCaptureDevices( |
347 | audioDevice: AudioCaptureDevice::fromIndex(index: GlobalConfig().audioCaptureDeviceFor(category)), |
348 | videoDevice: VideoCaptureDevice::fromIndex(index: GlobalConfig().videoCaptureDeviceFor(category))); |
349 | } |
350 | |
351 | void MediaSourcePrivate::setCaptureDevices(const AudioCaptureDevice &audioDevice, const VideoCaptureDevice &videoDevice) |
352 | { |
353 | audioCaptureDevice = audioDevice; |
354 | videoCaptureDevice = videoDevice; |
355 | |
356 | if (audioDevice.propertyNames().contains(t: "deviceAccessList" ) && |
357 | !audioDevice.property(name: "deviceAccessList" ).value<DeviceAccessList>().isEmpty()) { |
358 | audioDeviceAccessList = audioDevice.property(name: "deviceAccessList" ).value<DeviceAccessList>(); |
359 | } |
360 | |
361 | if (videoDevice.propertyNames().contains(t: "deviceAccessList" ) && |
362 | !videoDevice.property(name: "deviceAccessList" ).value<DeviceAccessList>().isEmpty()) { |
363 | videoDeviceAccessList = videoDevice.property(name: "deviceAccessList" ).value<DeviceAccessList>(); |
364 | } |
365 | |
366 | bool validAudio = !audioDeviceAccessList.isEmpty(); |
367 | bool validVideo = !videoDeviceAccessList.isEmpty(); |
368 | type = MediaSource::Invalid; |
369 | if (validAudio && validVideo) |
370 | type = MediaSource::AudioVideoCapture; |
371 | else if (validAudio || validVideo) |
372 | type = MediaSource::CaptureDevice; |
373 | } |
374 | #endif // !PHONON_NO_VIDEOCAPTURE && !PHONON_NO_AUDIOCAPTURE |
375 | |
376 | QDebug operator <<(QDebug dbg, const Phonon::MediaSource &source) |
377 | { |
378 | switch (source.type()) { |
379 | case MediaSource::Invalid: |
380 | dbg.nospace() << "Invalid()" ; |
381 | break; |
382 | case MediaSource::LocalFile: |
383 | dbg.nospace() << "LocalFile(" << source.url() << ")" ; |
384 | break; |
385 | case MediaSource::Url: |
386 | dbg.nospace() << "Url(" << source.url() << ")" ; |
387 | break; |
388 | case MediaSource::Disc: |
389 | dbg.nospace() << "Disc(" ; |
390 | switch (source.discType()) { |
391 | case NoDisc: |
392 | dbg.nospace() << "NoDisc" ; |
393 | break; |
394 | case Cd: |
395 | dbg.nospace() << "Cd: " << source.deviceName(); |
396 | break; |
397 | case Dvd: |
398 | dbg.nospace() << "Dvd: " << source.deviceName(); |
399 | break; |
400 | case Vcd: |
401 | dbg.nospace() << "Vcd: " << source.deviceName(); |
402 | break; |
403 | case BluRay: |
404 | dbg.nospace() << "BluRay: " << source.deviceName(); |
405 | break; |
406 | } |
407 | dbg.nospace() << ")" ; |
408 | break; |
409 | case MediaSource::Stream: { |
410 | dbg.nospace() << "Stream(IOAddr: " << source.d->ioDevice; |
411 | QObject *qiodevice = qobject_cast<QObject *>(object: source.d->ioDevice); |
412 | if (qiodevice) |
413 | dbg.nospace() << " IOClass: " << qiodevice->metaObject()->className(); |
414 | |
415 | dbg.nospace() << "; StreamAddr: " << source.stream(); |
416 | QObject *qstream = qobject_cast<QObject *>(object: source.stream()); |
417 | if (qstream) |
418 | dbg.nospace() << " StreamClass: " << qstream->metaObject()->className(); |
419 | |
420 | dbg.nospace() << ")" ; |
421 | break; |
422 | } |
423 | case MediaSource::CaptureDevice: |
424 | case MediaSource::AudioVideoCapture: |
425 | dbg.nospace() << "AudioVideoCapture(A:" << source.audioCaptureDevice().name() |
426 | << "/V: " << source.videoCaptureDevice().name() << ")" ; |
427 | break; |
428 | case MediaSource::Empty: |
429 | dbg.nospace() << "Empty()" ; |
430 | break; |
431 | } |
432 | |
433 | return dbg.maybeSpace(); |
434 | } |
435 | |
436 | } // namespace Phonon |
437 | |
438 | // vim: sw=4 sts=4 et tw=100 |
439 | |