1 /* This file is part of the KDE project
2 Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License version 2 as published by the Free Software Foundation.
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
13 You should have received a copy of the GNU Library General Public License
14 along with this library; see the file COPYING.LIB. If not, write to
15 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 Boston, MA 02110-1301, USA.
20 #include "kiomediastream.h"
21 #include "kiomediastream_p.h"
23 #include <kprotocolmanager.h>
24 #include <kio/filejob.h>
31 KioMediaStream::KioMediaStream(const QUrl
&url
, QObject
*parent
)
32 : AbstractMediaStream(parent
),
33 d_ptr(new KioMediaStreamPrivate(url
))
40 void KioMediaStream::reset()
45 d
->kiojob
->disconnect(this);
48 d
->endOfDataSent
= false;
55 if (KProtocolManager::supportsOpening(d
->url
)) {
56 d
->kiojob
= KIO::open(d
->url
, QIODevice::ReadOnly
);
59 setStreamSeekable(true);
60 connect(d
->kiojob
, SIGNAL(open(KIO::Job
*)), this, SLOT(_k_bytestreamFileJobOpen(KIO::Job
*)));
61 connect(d
->kiojob
, SIGNAL(position(KIO::Job
*, KIO::filesize_t
)),
62 this, SLOT(_k_bytestreamSeekDone(KIO::Job
*, KIO::filesize_t
)));
64 d
->kiojob
= KIO::get(d
->url
, KIO::NoReload
, KIO::HideProgressInfo
);
66 setStreamSeekable(false);
67 connect(d
->kiojob
, SIGNAL(totalSize(KJob
*, qulonglong
)),
68 this, SLOT(_k_bytestreamTotalSize(KJob
*,qulonglong
)));
72 d
->kiojob
->addMetaData("UserAgent", QLatin1String("KDE Phonon"));
73 connect(d
->kiojob
, SIGNAL(data(KIO::Job
*,const QByteArray
&)),
74 this, SLOT(_k_bytestreamData(KIO::Job
*,const QByteArray
&)));
75 connect(d
->kiojob
, SIGNAL(result(KJob
*)), this, SLOT(_k_bytestreamResult(KJob
*)));
78 KioMediaStream::~KioMediaStream()
83 d
->kiojob
->disconnect(this);
84 KIO::FileJob
*filejob
= qobject_cast
<KIO::FileJob
*>(d
->kiojob
);
93 void KioMediaStream::needData()
97 // no job => job is finished and endOfData was already sent
100 KIO::FileJob
*filejob
= qobject_cast
<KIO::FileJob
*>(d
->kiojob
);
102 // while d->seeking the backend won't get any data
103 if (d
->seeking
|| !d
->open
) {
105 } else if (!d
->reading
) {
107 QMetaObject::invokeMethod(this, "_k_read", Qt::QueuedConnection
);
108 //filejob->read(32768);
116 void KioMediaStream::enoughData()
120 // Don't suspend when using a FileJob. The FileJob is controlled by calls to
122 if (d
->kiojob
&& !qobject_cast
<KIO::FileJob
*>(d
->kiojob
) && !d
->kiojob
->isSuspended()) {
123 d
->kiojob
->suspend();
129 void KioMediaStream::seekStream(qint64 position
)
132 if (!d
->kiojob
|| d
->endOfDataSent
) {
133 // no job => job is finished and endOfData was already sent
134 kDebug(600) << "no job/job finished -> recreate it";
138 kDebug(600) << position
<< " = " << qulonglong(position
);
140 d
->seekPosition
= position
;
142 KIO::FileJob
*filejob
= qobject_cast
<KIO::FileJob
*>(d
->kiojob
);
143 filejob
->seek(position
);
147 void KioMediaStreamPrivate::_k_bytestreamData(KIO::Job
*, const QByteArray
&data
)
151 if (q
->streamSize() == 0) {
152 q
->setStreamSize(-1);
155 // seek doesn't block, so don't send data to the backend until it signals us
156 // that the seek is done
157 kDebug(600) << "seeking: do nothing";
161 if (data
.isEmpty()) {
163 if (!endOfDataSent
) {
164 kDebug(600) << "empty data: stopping the stream";
165 endOfDataSent
= true;
171 //kDebug(600) << "calling writeData on the Backend ByteStream " << data.size();
174 Q_ASSERT(qobject_cast
<KIO::FileJob
*>(kiojob
));
175 QMetaObject::invokeMethod(q
, "_k_read", Qt::QueuedConnection
);
179 void KioMediaStreamPrivate::_k_bytestreamResult(KJob
*job
)
182 Q_ASSERT(kiojob
== job
);
184 QString kioErrorString
= job
->errorString();
185 kDebug(600) << "KIO Job error: " << kioErrorString
;
186 QObject::disconnect(kiojob
, SIGNAL(data(KIO::Job
*,const QByteArray
&)),
187 q
, SLOT(_k_bytestreamData(KIO::Job
*,const QByteArray
&)));
188 QObject::disconnect(kiojob
, SIGNAL(result(KJob
*)),
189 q
, SLOT(_k_bytestreamResult(KJob
*)));
190 KIO::FileJob
*filejob
= qobject_cast
<KIO::FileJob
*>(kiojob
);
192 QObject::disconnect(kiojob
, SIGNAL(open(KIO::Job
*)),
193 q
, SLOT(_k_bytestreamFileJobOpen(KIO::Job
*)));
194 QObject::disconnect(kiojob
, SIGNAL(position(KIO::Job
*, KIO::filesize_t
)),
195 q
, SLOT(_k_bytestreamSeekDone(KIO::Job
*, KIO::filesize_t
)));
197 QObject::disconnect(kiojob
, SIGNAL(totalSize(KJob
*, qulonglong
)),
198 q
, SLOT(_k_bytestreamTotalSize(KJob
*,qulonglong
)));
200 // go to ErrorState - NormalError
201 q
->error(NormalError
, kioErrorString
);
202 } else if (seeking
) {
205 endOfDataSent
= false;
212 kDebug(600) << "KIO Job is done (will delete itself) and d->kiojob reset to 0";
213 endOfDataSent
= true;
218 void KioMediaStreamPrivate::_k_bytestreamTotalSize(KJob
*, qulonglong size
)
222 q
->setStreamSize(size
> 0 ? size
: -1);
225 void KioMediaStreamPrivate::_k_bytestreamFileJobOpen(KIO::Job
*)
230 endOfDataSent
= false;
231 KIO::FileJob
*filejob
= static_cast<KIO::FileJob
*>(kiojob
);
232 kDebug(600) << filejob
->size();
233 q
->setStreamSize(filejob
->size() > 0 ? filejob
->size() : -1);
236 filejob
->seek(seekPosition
);
237 } else if (reading
) {
238 //filejob->read(32768);
239 QMetaObject::invokeMethod(q
, "_k_read", Qt::QueuedConnection
);
243 void KioMediaStreamPrivate::_k_bytestreamSeekDone(KIO::Job
*, KIO::filesize_t offset
)
246 kDebug(600) << offset
;
248 endOfDataSent
= false;
251 Q_ASSERT(qobject_cast
<KIO::FileJob
*>(kiojob
));
252 QMetaObject::invokeMethod(q
, "_k_read", Qt::QueuedConnection
);
256 void KioMediaStreamPrivate::_k_read()
258 KIO::FileJob
*filejob
= qobject_cast
<KIO::FileJob
*>(kiojob
);
260 filejob
->read(32768);
263 } // namespace Phonon
265 #include "kiomediastream.moc"
266 // vim: sw=4 sts=4 et tw=100