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
32namespace Phonon
33{
34
35MediaSource::MediaSource(MediaSourcePrivate &dd)
36 : d(&dd)
37{
38}
39
40MediaSource::MediaSource()
41 : d(new MediaSourcePrivate(Empty))
42{
43}
44
45MediaSource::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
85MediaSource::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
111MediaSource::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
123MediaSource::MediaSource(const DeviceAccess &)
124 : d(new MediaSourcePrivate(Invalid))
125{
126}
127
128#ifndef PHONON_NO_AUDIOCAPTURE
129MediaSource::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
137MediaSource::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)
145MediaSource::MediaSource(CaptureCategory category)
146 : d(new MediaSourcePrivate(AudioVideoCapture))
147{
148 d->setCaptureDevices(category);
149}
150
151MediaSource::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
159MediaSource::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
169MediaSource::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
182MediaSource::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
191QList<MediaSource> MediaSource::substreams() const
192{
193 return d->linkedSources;
194}
195*/
196
197MediaSource::~MediaSource()
198{
199}
200
201MediaSourcePrivate::~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
215MediaSource::MediaSource(const MediaSource &rhs)
216 : d(rhs.d)
217{
218}
219
220MediaSource &MediaSource::operator=(const MediaSource &rhs)
221{
222 d = rhs.d;
223 return *this;
224}
225
226bool MediaSource::operator==(const MediaSource &rhs) const
227{
228 return d == rhs.d;
229}
230
231void MediaSource::setAutoDelete(bool autoDelete)
232{
233 d->autoDelete = autoDelete;
234}
235
236bool MediaSource::autoDelete() const
237{
238 return d->autoDelete;
239}
240
241MediaSource::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
251QString MediaSource::fileName() const
252{
253 return d->url.toLocalFile();
254}
255
256Mrl MediaSource::mrl() const
257{
258 return Mrl(d->url);
259}
260
261QUrl MediaSource::url() const
262{
263 return d->url;
264}
265
266DiscType MediaSource::discType() const
267{
268 return d->discType;
269}
270
271const 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
286const DeviceAccessList& MediaSource::audioDeviceAccessList() const
287{
288 return d->audioDeviceAccessList;
289}
290
291const DeviceAccessList& MediaSource::videoDeviceAccessList() const
292{
293 return d->videoDeviceAccessList;
294}
295
296QString MediaSource::deviceName() const
297{
298 return d->deviceName;
299}
300
301#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
302AbstractMediaStream *MediaSource::stream() const
303{
304 return d->stream;
305}
306
307void MediaSourcePrivate::setStream(AbstractMediaStream *s)
308{
309 stream = s;
310}
311#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
312
313#ifndef PHONON_NO_AUDIOCAPTURE
314AudioCaptureDevice MediaSource::audioCaptureDevice() const
315{
316 return d->audioCaptureDevice;
317}
318#endif //PHONON_NO_AUDIOCAPTURE
319
320#ifndef PHONON_NO_VIDEOCAPTURE
321VideoCaptureDevice 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)
328void 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
344void 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
351void 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
376QDebug 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

source code of phonon/phonon/mediasource.cpp