Warning, file /plasma/plasma-workspace/phonon/platform_kde/kiomediastream.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2007 Matthias Kretz <kretz@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-only 0005 */ 0006 0007 #include "kiomediastream.h" 0008 #include "kiomediastream_p.h" 0009 0010 #include <KIO/FileJob> 0011 #include <KLocalizedString> 0012 #include <KProtocolManager> 0013 0014 #include "debug.h" 0015 0016 namespace Phonon 0017 { 0018 KioMediaStream::KioMediaStream(const QUrl &url, QObject *parent) 0019 : AbstractMediaStream(parent) 0020 , d_ptr(new KioMediaStreamPrivate(url)) 0021 { 0022 d_ptr->q_ptr = this; 0023 qCDebug(PLATFORM); 0024 reset(); 0025 } 0026 0027 void KioMediaStream::reset() 0028 { 0029 qCDebug(PLATFORM); 0030 Q_D(KioMediaStream); 0031 if (d->kiojob) { 0032 d->kiojob->disconnect(this); 0033 d->kiojob->kill(); 0034 0035 d->endOfDataSent = false; 0036 d->seeking = false; 0037 d->reading = false; 0038 d->open = false; 0039 d->seekPosition = 0; 0040 } 0041 0042 if (KProtocolManager::supportsOpening(d->url)) { 0043 d->kiojob = KIO::open(d->url, QIODevice::ReadOnly); 0044 Q_ASSERT(d->kiojob); 0045 d->open = false; 0046 setStreamSeekable(true); 0047 connect(d->kiojob, SIGNAL(open(KIO::Job *)), this, SLOT(_k_bytestreamFileJobOpen(KIO::Job *))); 0048 connect(d->kiojob, SIGNAL(position(KIO::Job *, KIO::filesize_t)), this, SLOT(_k_bytestreamSeekDone(KIO::Job *, KIO::filesize_t))); 0049 } else { 0050 d->kiojob = KIO::get(d->url, KIO::NoReload, KIO::HideProgressInfo); 0051 Q_ASSERT(d->kiojob); 0052 setStreamSeekable(false); 0053 connect(d->kiojob, SIGNAL(totalSize(KJob *, qulonglong)), this, SLOT(_k_bytestreamTotalSize(KJob *, qulonglong))); 0054 d->kiojob->suspend(); 0055 } 0056 0057 d->kiojob->addMetaData(QStringLiteral("UserAgent"), QLatin1String("KDE Phonon")); 0058 connect(d->kiojob, SIGNAL(data(KIO::Job *, QByteArray)), this, SLOT(_k_bytestreamData(KIO::Job *, QByteArray))); 0059 connect(d->kiojob, SIGNAL(result(KJob *)), this, SLOT(_k_bytestreamResult(KJob *))); 0060 } 0061 0062 KioMediaStream::~KioMediaStream() 0063 { 0064 qCDebug(PLATFORM); 0065 Q_D(KioMediaStream); 0066 if (d->kiojob) { 0067 d->kiojob->disconnect(this); 0068 KIO::FileJob *filejob = qobject_cast<KIO::FileJob *>(d->kiojob); 0069 if (filejob) { 0070 filejob->close(); 0071 } 0072 d->kiojob->kill(); 0073 } 0074 delete d_ptr; 0075 } 0076 0077 void KioMediaStream::needData() 0078 { 0079 Q_D(KioMediaStream); 0080 if (!d->kiojob) { 0081 // no job => job is finished and endOfData was already sent 0082 return; 0083 } 0084 KIO::FileJob *filejob = qobject_cast<KIO::FileJob *>(d->kiojob); 0085 if (filejob) { 0086 // while d->seeking the backend won't get any data 0087 if (d->seeking || !d->open) { 0088 d->reading = true; 0089 } else if (!d->reading) { 0090 d->reading = true; 0091 QMetaObject::invokeMethod(this, "_k_read", Qt::QueuedConnection); 0092 // filejob->read(32768); 0093 } 0094 } else { 0095 // KIO::TransferJob 0096 d->kiojob->resume(); 0097 } 0098 } 0099 0100 void KioMediaStream::enoughData() 0101 { 0102 Q_D(KioMediaStream); 0103 qCDebug(PLATFORM); 0104 // Don't suspend when using a FileJob. The FileJob is controlled by calls to 0105 // FileJob::read() 0106 if (d->kiojob && !qobject_cast<KIO::FileJob *>(d->kiojob)) { 0107 if (!d->kiojob->isSuspended()) { 0108 d->kiojob->suspend(); 0109 } 0110 } else { 0111 d->reading = false; 0112 } 0113 } 0114 0115 void KioMediaStream::seekStream(qint64 position) 0116 { 0117 Q_D(KioMediaStream); 0118 if (!d->kiojob || d->endOfDataSent) { 0119 // no job => job is finished and endOfData was already sent 0120 qCDebug(PLATFORM) << "no job/job finished -> recreate it"; 0121 reset(); 0122 } 0123 Q_ASSERT(d->kiojob); 0124 qCDebug(PLATFORM) << position << " = " << qulonglong(position); 0125 d->seeking = true; 0126 d->seekPosition = position; 0127 if (d->open) { 0128 KIO::FileJob *filejob = qobject_cast<KIO::FileJob *>(d->kiojob); 0129 filejob->seek(position); 0130 } 0131 } 0132 0133 void KioMediaStreamPrivate::_k_bytestreamData(KIO::Job *, const QByteArray &data) 0134 { 0135 Q_Q(KioMediaStream); 0136 Q_ASSERT(kiojob); 0137 if (q->streamSize() == 0) { 0138 q->setStreamSize(-1); 0139 } 0140 if (seeking) { 0141 // seek doesn't block, so don't send data to the backend until it signals us 0142 // that the seek is done 0143 qCDebug(PLATFORM) << "seeking: do nothing"; 0144 return; 0145 } 0146 0147 if (data.isEmpty()) { 0148 reading = false; 0149 if (!endOfDataSent) { 0150 qCDebug(PLATFORM) << "empty data: stopping the stream"; 0151 endOfDataSent = true; 0152 q->endOfData(); 0153 } 0154 return; 0155 } 0156 0157 // qCDebug(PLATFORM) << "calling writeData on the Backend ByteStream " << data.size(); 0158 q->writeData(data); 0159 if (reading) { 0160 Q_ASSERT(qobject_cast<KIO::FileJob *>(kiojob)); 0161 QMetaObject::invokeMethod(q, "_k_read", Qt::QueuedConnection); 0162 } 0163 } 0164 0165 void KioMediaStreamPrivate::_k_bytestreamResult(KJob *job) 0166 { 0167 Q_Q(KioMediaStream); 0168 Q_ASSERT(kiojob == job); 0169 if (job->error()) { 0170 QString kioErrorString = job->errorString(); 0171 qCDebug(PLATFORM) << "KIO Job error: " << kioErrorString; 0172 QObject::disconnect(kiojob, SIGNAL(data(KIO::Job *, const QByteArray &)), q, SLOT(_k_bytestreamData(KIO::Job *, const QByteArray &))); 0173 QObject::disconnect(kiojob, SIGNAL(result(KJob *)), q, SLOT(_k_bytestreamResult(KJob *))); 0174 KIO::FileJob *filejob = qobject_cast<KIO::FileJob *>(kiojob); 0175 if (filejob) { 0176 QObject::disconnect(kiojob, SIGNAL(open(KIO::Job *)), q, SLOT(_k_bytestreamFileJobOpen(KIO::Job *))); 0177 QObject::disconnect(kiojob, SIGNAL(position(KIO::Job *, KIO::filesize_t)), q, SLOT(_k_bytestreamSeekDone(KIO::Job *, KIO::filesize_t))); 0178 } else { 0179 QObject::disconnect(kiojob, SIGNAL(totalSize(KJob *, qulonglong)), q, SLOT(_k_bytestreamTotalSize(KJob *, qulonglong))); 0180 } 0181 // go to ErrorState - NormalError 0182 q->error(NormalError, kioErrorString); 0183 } else if (seeking) { 0184 open = false; 0185 kiojob = nullptr; 0186 endOfDataSent = false; 0187 reading = false; 0188 q->reset(); 0189 return; 0190 } 0191 open = false; 0192 kiojob = nullptr; 0193 qCDebug(PLATFORM) << "KIO Job is done (will delete itself) and d->kiojob reset to 0"; 0194 endOfDataSent = true; 0195 q->endOfData(); 0196 reading = false; 0197 } 0198 0199 void KioMediaStreamPrivate::_k_bytestreamTotalSize(KJob *, qulonglong size) 0200 { 0201 Q_Q(KioMediaStream); 0202 qCDebug(PLATFORM) << size; 0203 q->setStreamSize(size > 0 ? size : -1); 0204 } 0205 0206 void KioMediaStreamPrivate::_k_bytestreamFileJobOpen(KIO::Job *) 0207 { 0208 Q_Q(KioMediaStream); 0209 Q_ASSERT(kiojob); 0210 open = true; 0211 endOfDataSent = false; 0212 KIO::FileJob *filejob = static_cast<KIO::FileJob *>(kiojob); 0213 qCDebug(PLATFORM) << filejob->size(); 0214 q->setStreamSize(filejob->size() > 0 ? filejob->size() : -1); 0215 0216 if (seeking) { 0217 filejob->seek(seekPosition); 0218 } else if (reading) { 0219 // filejob->read(32768); 0220 QMetaObject::invokeMethod(q, "_k_read", Qt::QueuedConnection); 0221 } 0222 } 0223 0224 void KioMediaStreamPrivate::_k_bytestreamSeekDone(KIO::Job *, KIO::filesize_t offset) 0225 { 0226 Q_ASSERT(kiojob); 0227 qCDebug(PLATFORM) << offset; 0228 seeking = false; 0229 endOfDataSent = false; 0230 if (reading) { 0231 Q_Q(KioMediaStream); 0232 Q_ASSERT(qobject_cast<KIO::FileJob *>(kiojob)); 0233 QMetaObject::invokeMethod(q, "_k_read", Qt::QueuedConnection); 0234 } 0235 } 0236 0237 void KioMediaStreamPrivate::_k_read() 0238 { 0239 KIO::FileJob *filejob = qobject_cast<KIO::FileJob *>(kiojob); 0240 Q_ASSERT(filejob); 0241 filejob->read(32768); 0242 } 0243 0244 } // namespace Phonon 0245 0246 #include "moc_kiomediastream.cpp"