00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <kapplication.h>
00033 #include <kdebug.h>
00034 #include <kio/job.h>
00035 #include <kio/kmimetype.h>
00036 #include <kio/jobclasses.h>
00037 #include <qtimer.h>
00038 #include <qdatastream.h>
00039 #include "artsversion.h"
00040 #include "kioinputstream_impl.moc"
00041
00042 using namespace Arts;
00043
00044 const unsigned int KIOInputStream_impl::PACKET_COUNT = 10;
00045
00046 KIOInputStream_impl::KIOInputStream_impl() : m_packetSize(2048)
00047 {
00048 m_job = 0;
00049 m_finished = false;
00050 m_firstBuffer = false;
00051 m_packetBuffer = 16;
00052 m_streamStarted = false;
00053 m_streamSuspended = false;
00054 m_streamPulled = false;
00055 m_size = 0;
00056 }
00057
00058 KIOInputStream_impl::~KIOInputStream_impl()
00059 {
00060 if(m_job != 0)
00061 m_job->kill();
00062 }
00063
00064 void KIOInputStream_impl::streamStart()
00065 {
00066
00067 if (m_streamStarted) {
00068 kdDebug( 400 ) << "not restarting stream!\n";
00069 if (m_job->isSuspended())
00070 m_job->resume();
00071 return;
00072 }
00073
00074 kdDebug( 400 ) << "(re)starting stream\n";
00075
00076 if(m_job != 0)
00077 m_job->kill();
00078 m_job = KIO::get(m_url, false, false);
00079
00080 m_job->addMetaData("accept", "audio/x-mp3, video/mpeg, application/ogg");
00081 m_job->addMetaData("UserAgent", QString::fromLatin1("aRts/") + QString::fromLatin1(ARTS_VERSION));
00082
00083 QObject::connect(m_job, SIGNAL(data(KIO::Job *, const QByteArray &)),
00084 this, SLOT(slotData(KIO::Job *, const QByteArray &)));
00085 QObject::connect(m_job, SIGNAL(result(KIO::Job *)),
00086 this, SLOT(slotResult(KIO::Job *)));
00087 QObject::connect(m_job, SIGNAL(mimetype(KIO::Job *, const QString &)),
00088 this, SLOT(slotScanMimeType(KIO::Job *, const QString &)));
00089 QObject::connect(m_job, SIGNAL(totalSize( KIO::Job *, KIO::filesize_t)),
00090 this, SLOT(slotTotalSize(KIO::Job *, KIO::filesize_t)));
00091
00092 m_streamStarted = true;
00093 }
00094
00095 void KIOInputStream_impl::streamEnd()
00096 {
00097 kdDebug( 400 ) << "streamEnd()\n";
00098
00099 if(m_job != 0)
00100 {
00101 QObject::disconnect(m_job, SIGNAL(data(KIO::Job *, const QByteArray &)),
00102 this, SLOT(slotData(KIO::Job *, const QByteArray &)));
00103 QObject::disconnect(m_job, SIGNAL(result(KIO::Job *)),
00104 this, SLOT(slotResult(KIO::Job *)));
00105 QObject::disconnect(m_job, SIGNAL(mimetype(KIO::Job *, const QString &)),
00106 this, SLOT(slotScanMimeType(KIO::Job *, const QString &)));
00107 QObject::disconnect(m_job, SIGNAL(totalSize( KIO::Job *, KIO::filesize_t)),
00108 this, SLOT(slotTotalSize(KIO::Job *, KIO::filesize_t)));
00109
00110 if ( m_streamPulled )
00111 outdata.endPull();
00112
00113 m_job->kill();
00114 m_job = 0;
00115 }
00116
00117 m_streamStarted = false;
00118 }
00119
00120 bool KIOInputStream_impl::openURL(const std::string& url)
00121 {
00122 m_url = KURL(url.c_str());
00123 m_size = 0;
00124 return true;
00125 }
00126
00127 void KIOInputStream_impl::slotData(KIO::Job *, const QByteArray &data)
00128 {
00129 if(m_finished)
00130 m_finished = false;
00131
00132 QDataStream dataStream(m_data, IO_WriteOnly | IO_Append);
00133 dataStream.writeRawBytes(data.data(), data.size());
00134
00135
00136 processQueue();
00137 }
00138
00139 void KIOInputStream_impl::slotResult(KIO::Job *job)
00140 {
00141
00142 m_finished = true;
00143 m_streamStarted = false;
00144 m_job = 0;
00145
00146 if(job->error()) {
00147
00148
00149 emit mimeTypeFound("application/x-zerosize");
00150 job->showErrorDialog();
00151 }
00152 }
00153
00154 void KIOInputStream_impl::slotScanMimeType(KIO::Job *, const QString &mimetype)
00155 {
00156 kdDebug( 400 ) << "got mimetype: " << mimetype << endl;
00157 emit mimeTypeFound(mimetype);
00158 }
00159
00160 void KIOInputStream_impl::slotTotalSize(KIO::Job *, KIO::filesize_t size)
00161 {
00162 m_size = size;
00163 }
00164
00165 bool KIOInputStream_impl::eof()
00166 {
00167 return (m_finished && m_data.size() == 0);
00168 }
00169
00170 bool KIOInputStream_impl::seekOk()
00171 {
00172 return false;
00173 }
00174
00175 long KIOInputStream_impl::size()
00176 {
00177 return m_size ? m_size : m_data.size();
00178 }
00179
00180 long KIOInputStream_impl::seek(long)
00181 {
00182 return -1;
00183 }
00184
00185 void KIOInputStream_impl::processQueue()
00186 {
00187 if(m_job != 0)
00188 {
00189 if(m_data.size() > (m_packetBuffer * m_packetSize * 2) && !m_job->isSuspended())
00190 {
00191 kdDebug( 400 ) << "STREAMING: suspend job" << endl;
00192 m_job->suspend();
00193 }
00194 else if(m_data.size() < (m_packetBuffer * m_packetSize) && m_job->isSuspended())
00195 {
00196 kdDebug( 400 ) << "STREAMING: resume job" << endl;
00197 m_job->resume();
00198 }
00199 }
00200
00201 if (!m_firstBuffer) {
00202 if(m_data.size() < (m_packetBuffer * m_packetSize * 2) ) {
00203 kdDebug( 400 ) << "STREAMING: Buffering in progress... (Needed bytes before it starts to play: " << ((m_packetBuffer * m_packetSize * 2) - m_data.size()) << ")" << endl;
00204 return;
00205 } else {
00206 m_firstBuffer = true;
00207 m_streamPulled = true;
00208 outdata.setPull(PACKET_COUNT, m_packetSize);
00209 }
00210 }
00211 }
00212
00213 void KIOInputStream_impl::request_outdata(DataPacket<mcopbyte> *packet)
00214 {
00215 processQueue();
00216 packet->size = std::min(m_packetSize, m_data.size());
00217 kdDebug( 400 ) << "STREAMING: Filling one DataPacket with " << packet->size << " bytes of the stream!" << endl;
00218
00219 if (!m_finished) {
00220 if( (unsigned)packet->size < m_packetSize || ! m_firstBuffer) {
00221 m_firstBuffer = false;
00222 packet->size = 0;
00223 outdata.endPull();
00224 }
00225 }
00226
00227 if (packet->size > 0)
00228 {
00229 memcpy(packet->contents, m_data.data(), packet->size);
00230 memmove(m_data.data(), m_data.data() + packet->size, m_data.size() - packet->size);
00231 m_data.resize(m_data.size() - packet->size);
00232 }
00233 packet->send();
00234 }
00235
00236 REGISTER_IMPLEMENTATION(KIOInputStream_impl);