diff options
Diffstat (limited to 'arts/kde/kioinputstream_impl.cpp')
-rw-r--r-- | arts/kde/kioinputstream_impl.cpp | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/arts/kde/kioinputstream_impl.cpp b/arts/kde/kioinputstream_impl.cpp new file mode 100644 index 000000000..b82764931 --- /dev/null +++ b/arts/kde/kioinputstream_impl.cpp @@ -0,0 +1,236 @@ + /* + + Copyright (C) 2001 Nikolas Zimmermann <wildfox@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +/* + * How does it work? + * ----------------- + * + * First the buffer has to be filled. When it reaches a defined size the outdata + * stream has to start pulling packets. If the buffer reaches a size of zero the + * stream has to stop. If the buffer gets to big the job has to be suspended + * until the buffer is small enough again. + */ + +#include <kapplication.h> +#include <kdebug.h> +#include <kio/job.h> +#include <kio/kmimetype.h> +#include <kio/jobclasses.h> +#include <qtimer.h> +#include <qdatastream.h> +#include "artsversion.h" +#include "kioinputstream_impl.moc" + +using namespace Arts; + +const unsigned int KIOInputStream_impl::PACKET_COUNT = 10; + +KIOInputStream_impl::KIOInputStream_impl() : m_packetSize(2048) +{ + m_job = 0; + m_finished = false; + m_firstBuffer = false; + m_packetBuffer = 16; + m_streamStarted = false; + m_streamSuspended = false; + m_streamPulled = false; + m_size = 0; +} + +KIOInputStream_impl::~KIOInputStream_impl() +{ + if(m_job != 0) + m_job->kill(); +} + +void KIOInputStream_impl::streamStart() +{ + // prevent kill/reconnect + if (m_streamStarted) { + kdDebug( 400 ) << "not restarting stream!\n"; + if (m_job->isSuspended()) + m_job->resume(); + return; + } + + kdDebug( 400 ) << "(re)starting stream\n"; + + if(m_job != 0) + m_job->kill(); + m_job = KIO::get(m_url, false, false); + + m_job->addMetaData("accept", "audio/x-mp3, video/mpeg, application/ogg"); + m_job->addMetaData("UserAgent", QString::fromLatin1("aRts/") + QString::fromLatin1(ARTS_VERSION)); + + QObject::connect(m_job, SIGNAL(data(KIO::Job *, const QByteArray &)), + this, SLOT(slotData(KIO::Job *, const QByteArray &))); + QObject::connect(m_job, SIGNAL(result(KIO::Job *)), + this, SLOT(slotResult(KIO::Job *))); + QObject::connect(m_job, SIGNAL(mimetype(KIO::Job *, const QString &)), + this, SLOT(slotScanMimeType(KIO::Job *, const QString &))); + QObject::connect(m_job, SIGNAL(totalSize( KIO::Job *, KIO::filesize_t)), + this, SLOT(slotTotalSize(KIO::Job *, KIO::filesize_t))); + + m_streamStarted = true; +} + +void KIOInputStream_impl::streamEnd() +{ + kdDebug( 400 ) << "streamEnd()\n"; + + if(m_job != 0) + { + QObject::disconnect(m_job, SIGNAL(data(KIO::Job *, const QByteArray &)), + this, SLOT(slotData(KIO::Job *, const QByteArray &))); + QObject::disconnect(m_job, SIGNAL(result(KIO::Job *)), + this, SLOT(slotResult(KIO::Job *))); + QObject::disconnect(m_job, SIGNAL(mimetype(KIO::Job *, const QString &)), + this, SLOT(slotScanMimeType(KIO::Job *, const QString &))); + QObject::disconnect(m_job, SIGNAL(totalSize( KIO::Job *, KIO::filesize_t)), + this, SLOT(slotTotalSize(KIO::Job *, KIO::filesize_t))); + + if ( m_streamPulled ) + outdata.endPull(); + + m_job->kill(); + m_job = 0; + } + + m_streamStarted = false; +} + +bool KIOInputStream_impl::openURL(const std::string& url) +{ + m_url = KURL(url.c_str()); + m_size = 0; + return true; +} + +void KIOInputStream_impl::slotData(KIO::Job *, const QByteArray &data) +{ + if(m_finished) + m_finished = false; + + QDataStream dataStream(m_data, IO_WriteOnly | IO_Append); + dataStream.writeRawBytes(data.data(), data.size()); + //kdDebug( 400 ) << "STREAMING: buffersize = " << m_data.size() << " bytes" << endl; + + processQueue(); +} + +void KIOInputStream_impl::slotResult(KIO::Job *job) +{ + // jobs delete themselves after emitting their result + m_finished = true; + m_streamStarted = false; + m_job = 0; + + if(job->error()) { + // break out of the event loop in case of + // connection error + emit mimeTypeFound("application/x-zerosize"); + job->showErrorDialog(); + } +} + +void KIOInputStream_impl::slotScanMimeType(KIO::Job *, const QString &mimetype) +{ + kdDebug( 400 ) << "got mimetype: " << mimetype << endl; + emit mimeTypeFound(mimetype); +} + +void KIOInputStream_impl::slotTotalSize(KIO::Job *, KIO::filesize_t size) +{ + m_size = size; +} + +bool KIOInputStream_impl::eof() +{ + return (m_finished && m_data.size() == 0); +} + +bool KIOInputStream_impl::seekOk() +{ + return false; +} + +long KIOInputStream_impl::size() +{ + return m_size ? m_size : m_data.size(); +} + +long KIOInputStream_impl::seek(long) +{ + return -1; +} + +void KIOInputStream_impl::processQueue() +{ + if(m_job != 0) + { + if(m_data.size() > (m_packetBuffer * m_packetSize * 2) && !m_job->isSuspended()) + { + kdDebug( 400 ) << "STREAMING: suspend job" << endl; + m_job->suspend(); + } + else if(m_data.size() < (m_packetBuffer * m_packetSize) && m_job->isSuspended()) + { + kdDebug( 400 ) << "STREAMING: resume job" << endl; + m_job->resume(); + } + } + + if (!m_firstBuffer) { + if(m_data.size() < (m_packetBuffer * m_packetSize * 2) ) { + kdDebug( 400 ) << "STREAMING: Buffering in progress... (Needed bytes before it starts to play: " << ((m_packetBuffer * m_packetSize * 2) - m_data.size()) << ")" << endl; + return; + } else { + m_firstBuffer = true; + m_streamPulled = true; + outdata.setPull(PACKET_COUNT, m_packetSize); + } + } +} + +void KIOInputStream_impl::request_outdata(DataPacket<mcopbyte> *packet) +{ + processQueue(); + packet->size = std::min(m_packetSize, m_data.size()); + kdDebug( 400 ) << "STREAMING: Filling one DataPacket with " << packet->size << " bytes of the stream!" << endl; + + if (!m_finished) { + if( (unsigned)packet->size < m_packetSize || ! m_firstBuffer) { + m_firstBuffer = false; + packet->size = 0; + outdata.endPull(); + } + } + + if (packet->size > 0) + { + memcpy(packet->contents, m_data.data(), packet->size); + memmove(m_data.data(), m_data.data() + packet->size, m_data.size() - packet->size); + m_data.resize(m_data.size() - packet->size); + } + packet->send(); +} + +REGISTER_IMPLEMENTATION(KIOInputStream_impl); |