File indexing completed on 2025-02-09 05:31:49
0001 /* This file is part of the KDE project 0002 Copyright (C) 2007 Matthias Kretz <kretz@kde.org> 0003 0004 This library is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU Lesser General Public 0006 License as published by the Free Software Foundation; either 0007 version 2.1 of the License, or (at your option) version 3, or any 0008 later version accepted by the membership of KDE e.V. (or its 0009 successor approved by the membership of KDE e.V.), Nokia Corporation 0010 (or its successors, if any) and the KDE Free Qt Foundation, which shall 0011 act as a proxy defined in Section 6 of version 3 of the license. 0012 0013 This library is distributed in the hope that it will be useful, 0014 but WITHOUT ANY WARRANTY; without even the implied warranty of 0015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0016 Lesser General Public License for more details. 0017 0018 You should have received a copy of the GNU Lesser General Public 0019 License along with this library. If not, see <http://www.gnu.org/licenses/>. 0020 0021 */ 0022 0023 #include "mediasource.h" 0024 #include "mediasource_p.h" 0025 #include "iodevicestream_p.h" 0026 #include "abstractmediastream_p.h" 0027 #include "globalconfig.h" 0028 0029 #include <QFileInfo> 0030 #include <QFile> 0031 0032 namespace Phonon 0033 { 0034 0035 MediaSource::MediaSource(MediaSourcePrivate &dd) 0036 : d(&dd) 0037 { 0038 } 0039 0040 MediaSource::MediaSource() 0041 : d(new MediaSourcePrivate(Empty)) 0042 { 0043 } 0044 0045 MediaSource::MediaSource(const QString &filename) 0046 : d(new MediaSourcePrivate(LocalFile)) 0047 { 0048 if (filename.startsWith(QLatin1String(":/")) || filename.startsWith(QLatin1String("qrc:///"))) { 0049 #ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM 0050 d->url.setScheme("qrc"); 0051 d->url.setPath(filename.mid(filename.startsWith(QLatin1Char(':')) ? 1 : 6)); 0052 0053 // QFile needs :/ syntax 0054 QString path(QLatin1Char(':') + d->url.path()); 0055 0056 if (QFile::exists(path)) { 0057 d->type = Stream; 0058 d->ioDevice = new QFile(path); 0059 d->setStream(new IODeviceStream(d->ioDevice, d->ioDevice)); 0060 } else { 0061 d->type = Invalid; 0062 } 0063 #else 0064 d->type = Invalid; 0065 #endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM 0066 } else { 0067 const QFileInfo fileinfo(filename); 0068 if (fileinfo.exists()) { 0069 d->url = QUrl::fromLocalFile(fileinfo.absoluteFilePath()); 0070 if (!d->url.host().isEmpty()) { 0071 // filename points to a file on a network share (eg \\host\share\path) 0072 d->type = Url; 0073 } 0074 } else { 0075 d->url = filename; 0076 if (d->url.isValid()) { 0077 d->type = Url; 0078 } else { 0079 d->type = Invalid; 0080 } 0081 } 0082 } 0083 } 0084 0085 MediaSource::MediaSource(const QUrl &url) 0086 : d(new MediaSourcePrivate(Url)) 0087 { 0088 if (url.isValid()) { 0089 if (url.scheme() == QLatin1String("qrc")) { 0090 #ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM 0091 // QFile needs :/ syntax 0092 QString path(QLatin1Char(':') + url.path()); 0093 0094 if (QFile::exists(path)) { 0095 d->type = Stream; 0096 d->ioDevice = new QFile(path); 0097 d->setStream(new IODeviceStream(d->ioDevice, d->ioDevice)); 0098 } else { 0099 d->type = Invalid; 0100 } 0101 #else 0102 d->type = Invalid; 0103 #endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM 0104 } 0105 d->url = url; 0106 } else { 0107 d->type = Invalid; 0108 } 0109 } 0110 0111 MediaSource::MediaSource(DiscType dt, const QString &deviceName) 0112 : d(new MediaSourcePrivate(Disc)) 0113 { 0114 if (dt == NoDisc) { 0115 d->type = Invalid; 0116 return; 0117 } 0118 d->discType = dt; 0119 d->deviceName = deviceName; 0120 } 0121 0122 // NOTE: this is deprecated 0123 MediaSource::MediaSource(const DeviceAccess &) 0124 : d(new MediaSourcePrivate(Invalid)) 0125 { 0126 } 0127 0128 #ifndef PHONON_NO_AUDIOCAPTURE 0129 MediaSource::MediaSource(const AudioCaptureDevice& device) 0130 : d(new MediaSourcePrivate(CaptureDevice)) 0131 { 0132 d->setCaptureDevices(device, VideoCaptureDevice()); 0133 } 0134 #endif //PHONON_NO_AUDIOCAPTURE 0135 0136 #ifndef PHONON_NO_VIDEOCAPTURE 0137 MediaSource::MediaSource(const VideoCaptureDevice& device) 0138 : d(new MediaSourcePrivate(CaptureDevice)) 0139 { 0140 d->setCaptureDevices(AudioCaptureDevice(), device); 0141 } 0142 #endif //PHONON_NO_VIDEOCAPTURE 0143 0144 #if !defined(PHONON_NO_VIDEOCAPTURE) && !defined(PHONON_NO_AUDIOCAPTURE) 0145 MediaSource::MediaSource(CaptureCategory category) 0146 : d(new MediaSourcePrivate(AudioVideoCapture)) 0147 { 0148 d->setCaptureDevices(category); 0149 } 0150 0151 MediaSource::MediaSource(Capture::DeviceType deviceType, CaptureCategory category) 0152 : d(new MediaSourcePrivate(CaptureDevice)) 0153 { 0154 d->setCaptureDevice(deviceType, category); 0155 } 0156 #endif // !PHONON_NO_VIDEOCAPTURE && !PHONON_NO_AUDIOCAPTURE 0157 0158 #ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM 0159 MediaSource::MediaSource(AbstractMediaStream *stream) 0160 : d(new MediaSourcePrivate(Stream)) 0161 { 0162 if (stream) { 0163 d->setStream(stream); 0164 } else { 0165 d->type = Invalid; 0166 } 0167 } 0168 0169 MediaSource::MediaSource(QIODevice *ioDevice) 0170 : d(new MediaSourcePrivate(Stream)) 0171 { 0172 if (ioDevice) { 0173 d->setStream(new IODeviceStream(ioDevice, ioDevice)); 0174 d->ioDevice = ioDevice; 0175 } else { 0176 d->type = Invalid; 0177 } 0178 } 0179 #endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM 0180 0181 /* post 4.0 0182 MediaSource::MediaSource(const QList<MediaSource> &mediaList) 0183 : d(new MediaSourcePrivate(Link)) 0184 { 0185 d->linkedSources = mediaList; 0186 foreach (MediaSource ms, mediaList) { 0187 Q_ASSERT(ms.type() != Link); 0188 } 0189 } 0190 0191 QList<MediaSource> MediaSource::substreams() const 0192 { 0193 return d->linkedSources; 0194 } 0195 */ 0196 0197 MediaSource::~MediaSource() 0198 { 0199 } 0200 0201 MediaSourcePrivate::~MediaSourcePrivate() 0202 { 0203 #ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM 0204 if (autoDelete) { 0205 //here we use deleteLater because this object 0206 //might be destroyed from another thread 0207 if (stream) 0208 stream->deleteLater(); 0209 if (ioDevice) 0210 ioDevice->deleteLater(); 0211 } 0212 #endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM 0213 } 0214 0215 MediaSource::MediaSource(const MediaSource &rhs) 0216 : d(rhs.d) 0217 { 0218 } 0219 0220 MediaSource &MediaSource::operator=(const MediaSource &rhs) 0221 { 0222 d = rhs.d; 0223 return *this; 0224 } 0225 0226 bool MediaSource::operator==(const MediaSource &rhs) const 0227 { 0228 return d == rhs.d; 0229 } 0230 0231 void MediaSource::setAutoDelete(bool autoDelete) 0232 { 0233 d->autoDelete = autoDelete; 0234 } 0235 0236 bool MediaSource::autoDelete() const 0237 { 0238 return d->autoDelete; 0239 } 0240 0241 MediaSource::Type MediaSource::type() const 0242 { 0243 #ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM 0244 if (d->type == Stream && d->stream == nullptr) { 0245 return Invalid; 0246 } 0247 #endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM 0248 return d->type; 0249 } 0250 0251 QString MediaSource::fileName() const 0252 { 0253 return d->url.toLocalFile(); 0254 } 0255 0256 Mrl MediaSource::mrl() const 0257 { 0258 return Mrl(d->url); 0259 } 0260 0261 QUrl MediaSource::url() const 0262 { 0263 return d->url; 0264 } 0265 0266 DiscType MediaSource::discType() const 0267 { 0268 return d->discType; 0269 } 0270 0271 const DeviceAccessList& MediaSource::deviceAccessList() const 0272 { 0273 #ifndef PHONON_NO_AUDIOCAPTURE 0274 if (d->audioCaptureDevice.isValid()) 0275 return d->audioDeviceAccessList; 0276 #endif 0277 0278 #ifndef PHONON_NO_VIDEOCAPTURE 0279 if (d->videoCaptureDevice.isValid()) 0280 return d->videoDeviceAccessList; 0281 #endif 0282 0283 return d->audioDeviceAccessList; // It should be invalid 0284 } 0285 0286 const DeviceAccessList& MediaSource::audioDeviceAccessList() const 0287 { 0288 return d->audioDeviceAccessList; 0289 } 0290 0291 const DeviceAccessList& MediaSource::videoDeviceAccessList() const 0292 { 0293 return d->videoDeviceAccessList; 0294 } 0295 0296 QString MediaSource::deviceName() const 0297 { 0298 return d->deviceName; 0299 } 0300 0301 #ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM 0302 AbstractMediaStream *MediaSource::stream() const 0303 { 0304 return d->stream; 0305 } 0306 0307 void MediaSourcePrivate::setStream(AbstractMediaStream *s) 0308 { 0309 stream = s; 0310 } 0311 #endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM 0312 0313 #ifndef PHONON_NO_AUDIOCAPTURE 0314 AudioCaptureDevice MediaSource::audioCaptureDevice() const 0315 { 0316 return d->audioCaptureDevice; 0317 } 0318 #endif //PHONON_NO_AUDIOCAPTURE 0319 0320 #ifndef PHONON_NO_VIDEOCAPTURE 0321 VideoCaptureDevice MediaSource::videoCaptureDevice() const 0322 { 0323 return d->videoCaptureDevice; 0324 } 0325 #endif //PHONON_NO_VIDEOCAPTURE 0326 0327 #if !defined(PHONON_NO_VIDEOCAPTURE) && !defined(PHONON_NO_AUDIOCAPTURE) 0328 void MediaSourcePrivate::setCaptureDevice(Capture::DeviceType deviceType, CaptureCategory category) 0329 { 0330 switch (deviceType) { 0331 case Capture::VideoType: { 0332 setCaptureDevices(AudioCaptureDevice(), 0333 VideoCaptureDevice::fromIndex(GlobalConfig().videoCaptureDeviceFor(category))); 0334 break; 0335 } 0336 case Capture::AudioType: { 0337 setCaptureDevices( 0338 AudioCaptureDevice::fromIndex(GlobalConfig().audioCaptureDeviceFor(category)), VideoCaptureDevice()); 0339 break; 0340 } 0341 } 0342 } 0343 0344 void MediaSourcePrivate::setCaptureDevices(CaptureCategory category) 0345 { 0346 setCaptureDevices( 0347 AudioCaptureDevice::fromIndex(GlobalConfig().audioCaptureDeviceFor(category)), 0348 VideoCaptureDevice::fromIndex(GlobalConfig().videoCaptureDeviceFor(category))); 0349 } 0350 0351 void MediaSourcePrivate::setCaptureDevices(const AudioCaptureDevice &audioDevice, const VideoCaptureDevice &videoDevice) 0352 { 0353 audioCaptureDevice = audioDevice; 0354 videoCaptureDevice = videoDevice; 0355 0356 if (audioDevice.propertyNames().contains("deviceAccessList") && 0357 !audioDevice.property("deviceAccessList").value<DeviceAccessList>().isEmpty()) { 0358 audioDeviceAccessList = audioDevice.property("deviceAccessList").value<DeviceAccessList>(); 0359 } 0360 0361 if (videoDevice.propertyNames().contains("deviceAccessList") && 0362 !videoDevice.property("deviceAccessList").value<DeviceAccessList>().isEmpty()) { 0363 videoDeviceAccessList = videoDevice.property("deviceAccessList").value<DeviceAccessList>(); 0364 } 0365 0366 bool validAudio = !audioDeviceAccessList.isEmpty(); 0367 bool validVideo = !videoDeviceAccessList.isEmpty(); 0368 type = MediaSource::Invalid; 0369 if (validAudio && validVideo) 0370 type = MediaSource::AudioVideoCapture; 0371 else if (validAudio || validVideo) 0372 type = MediaSource::CaptureDevice; 0373 } 0374 #endif // !PHONON_NO_VIDEOCAPTURE && !PHONON_NO_AUDIOCAPTURE 0375 0376 QDebug operator <<(QDebug dbg, const Phonon::MediaSource &source) 0377 { 0378 switch (source.type()) { 0379 case MediaSource::Invalid: 0380 dbg.nospace() << "Invalid()"; 0381 break; 0382 case MediaSource::LocalFile: 0383 dbg.nospace() << "LocalFile(" << source.url() << ")"; 0384 break; 0385 case MediaSource::Url: 0386 dbg.nospace() << "Url(" << source.url() << ")"; 0387 break; 0388 case MediaSource::Disc: 0389 dbg.nospace() << "Disc("; 0390 switch (source.discType()) { 0391 case NoDisc: 0392 dbg.nospace() << "NoDisc"; 0393 break; 0394 case Cd: 0395 dbg.nospace() << "Cd: " << source.deviceName(); 0396 break; 0397 case Dvd: 0398 dbg.nospace() << "Dvd: " << source.deviceName(); 0399 break; 0400 case Vcd: 0401 dbg.nospace() << "Vcd: " << source.deviceName(); 0402 break; 0403 case BluRay: 0404 dbg.nospace() << "BluRay: " << source.deviceName(); 0405 break; 0406 } 0407 dbg.nospace() << ")"; 0408 break; 0409 case MediaSource::Stream: { 0410 dbg.nospace() << "Stream(IOAddr: " << source.d->ioDevice; 0411 QObject *qiodevice = qobject_cast<QObject *>(source.d->ioDevice); 0412 if (qiodevice) 0413 dbg.nospace() << " IOClass: " << qiodevice->metaObject()->className(); 0414 0415 dbg.nospace() << "; StreamAddr: " << source.stream(); 0416 QObject *qstream = qobject_cast<QObject *>(source.stream()); 0417 if (qstream) 0418 dbg.nospace() << " StreamClass: " << qstream->metaObject()->className(); 0419 0420 dbg.nospace() << ")"; 0421 break; 0422 } 0423 case MediaSource::CaptureDevice: 0424 case MediaSource::AudioVideoCapture: 0425 dbg.nospace() << "AudioVideoCapture(A:" << source.audioCaptureDevice().name() 0426 << "/V: " << source.videoCaptureDevice().name() << ")"; 0427 break; 0428 case MediaSource::Empty: 0429 dbg.nospace() << "Empty()"; 0430 break; 0431 } 0432 0433 return dbg.maybeSpace(); 0434 } 0435 0436 } // namespace Phonon 0437 0438 // vim: sw=4 sts=4 et tw=100