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() << "not restarting stream!\n";
00069         if (m_job->isSuspended())
00070             m_job->resume();
00071         return;
00072     }
00073 
00074     kdDebug() << "(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() << "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     kdDebug() << "STREAMING: buffersize = " << m_data.size() << " bytes" << endl;
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() << "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() << "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() << "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() << "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     
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);