|
MythTV
0.26-pre
|
00001 // c/c++ 00002 #include <unistd.h> 00003 #include <stdio.h> 00004 #include <assert.h> 00005 00006 // qt 00007 #include <QApplication> 00008 #include <QUrl> 00009 #include <QFileInfo> 00010 00011 // mythtv 00012 #include <mythdownloadmanager.h> 00013 #include <mythdirs.h> 00014 #include <mythlogging.h> 00015 #include <compat.h> // For random() on MINGW32 00016 #include <remotefile.h> 00017 #include <mythcorecontext.h> 00018 00019 // mythmusic 00020 #include "decoderhandler.h" 00021 #include "decoder.h" 00022 #include "metadata.h" 00023 #include "streaminput.h" 00024 #include "shoutcast.h" 00025 00026 /**********************************************************************/ 00027 00028 QEvent::Type DecoderHandlerEvent::Ready = (QEvent::Type) QEvent::registerEventType(); 00029 QEvent::Type DecoderHandlerEvent::Meta = (QEvent::Type) QEvent::registerEventType(); 00030 QEvent::Type DecoderHandlerEvent::Info = (QEvent::Type) QEvent::registerEventType(); 00031 QEvent::Type DecoderHandlerEvent::OperationStart = (QEvent::Type) QEvent::registerEventType(); 00032 QEvent::Type DecoderHandlerEvent::OperationStop = (QEvent::Type) QEvent::registerEventType(); 00033 QEvent::Type DecoderHandlerEvent::Error = (QEvent::Type) QEvent::registerEventType(); 00034 00035 DecoderHandlerEvent::DecoderHandlerEvent(Type t, const Metadata &meta) 00036 : MythEvent(t), m_msg(NULL), m_meta(NULL) 00037 { 00038 m_meta = new Metadata(meta); 00039 } 00040 00041 DecoderHandlerEvent::~DecoderHandlerEvent(void) 00042 { 00043 if (m_msg) 00044 delete m_msg; 00045 00046 if (m_meta) 00047 delete m_meta; 00048 } 00049 00050 MythEvent* DecoderHandlerEvent::clone(void) const 00051 { 00052 DecoderHandlerEvent *result = new DecoderHandlerEvent(*this); 00053 00054 if (m_msg) 00055 result->m_msg = new QString(*m_msg); 00056 00057 if (m_meta) 00058 result->m_meta = new Metadata(*m_meta); 00059 00060 return result; 00061 } 00062 00063 /**********************************************************************/ 00064 00065 DecoderIOFactory::DecoderIOFactory(DecoderHandler *parent) 00066 { 00067 m_handler = parent; 00068 } 00069 00070 DecoderIOFactory::~DecoderIOFactory(void) 00071 { 00072 } 00073 00074 void DecoderIOFactory::doConnectDecoder(const QString &format) 00075 { 00076 m_handler->doOperationStop(); 00077 m_handler->doConnectDecoder(getUrl(), format); 00078 } 00079 00080 Decoder *DecoderIOFactory::getDecoder(void) 00081 { 00082 return m_handler->getDecoder(); 00083 } 00084 00085 void DecoderIOFactory::doFailed(const QString &message) 00086 { 00087 m_handler->doOperationStop(); 00088 m_handler->doFailed(getUrl(), message); 00089 } 00090 00091 void DecoderIOFactory::doInfo(const QString &message) 00092 { 00093 m_handler->doInfo(message); 00094 } 00095 00096 void DecoderIOFactory::doOperationStart(const QString &name) 00097 { 00098 m_handler->doOperationStart(name); 00099 } 00100 00101 void DecoderIOFactory::doOperationStop(void) 00102 { 00103 m_handler->doOperationStop(); 00104 } 00105 00106 /**********************************************************************/ 00107 00108 DecoderIOFactoryFile::DecoderIOFactoryFile(DecoderHandler *parent) 00109 : DecoderIOFactory(parent), m_input (NULL) 00110 { 00111 } 00112 00113 DecoderIOFactoryFile::~DecoderIOFactoryFile(void) 00114 { 00115 if (m_input) 00116 delete m_input; 00117 } 00118 00119 QIODevice* DecoderIOFactoryFile::takeInput(void) 00120 { 00121 QIODevice *result = m_input; 00122 m_input = NULL; 00123 return result; 00124 } 00125 00126 void DecoderIOFactoryFile::start(void) 00127 { 00128 QString sourcename = getMetadata().Filename(); 00129 00130 LOG(VB_PLAYBACK, LOG_INFO, 00131 QString("DecoderIOFactory: Opening Local File %1").arg(sourcename)); 00132 00133 m_input = new QFile(sourcename); 00134 doConnectDecoder(getUrl().toLocalFile()); 00135 } 00136 00137 /**********************************************************************/ 00138 00139 DecoderIOFactorySG::DecoderIOFactorySG(DecoderHandler *parent) 00140 : DecoderIOFactory(parent), m_input(NULL) 00141 { 00142 } 00143 00144 DecoderIOFactorySG::~DecoderIOFactorySG(void) 00145 { 00146 if (m_input) 00147 delete m_input; 00148 } 00149 00150 QIODevice* DecoderIOFactorySG::takeInput(void) 00151 { 00152 QIODevice *result = m_input; 00153 m_input = NULL; 00154 return result; 00155 } 00156 00157 void DecoderIOFactorySG::start(void) 00158 { 00159 QString url = getUrl().toString(); 00160 LOG(VB_PLAYBACK, LOG_INFO, 00161 QString("DecoderIOFactorySG: Opening Myth URL %1").arg(url)); 00162 m_input = new MusicSGIODevice(url); 00163 doConnectDecoder(getUrl().path()); 00164 } 00165 00166 /**********************************************************************/ 00167 00168 DecoderIOFactoryUrl::DecoderIOFactoryUrl(DecoderHandler *parent) : DecoderIOFactory(parent) 00169 { 00170 m_accessManager = new QNetworkAccessManager(this); 00171 m_input = new MusicIODevice(); 00172 connect(m_input, SIGNAL(freeSpaceAvailable()), SLOT(readyRead())); 00173 00174 m_input->open(QIODevice::ReadWrite); 00175 00176 m_bytesWritten = 0; 00177 m_redirectCount = 0; 00178 } 00179 00180 DecoderIOFactoryUrl::~DecoderIOFactoryUrl(void) 00181 { 00182 doClose(); 00183 00184 m_accessManager->deleteLater(); 00185 00186 if (m_input) 00187 delete m_input; 00188 } 00189 00190 QIODevice* DecoderIOFactoryUrl::takeInput(void) 00191 { 00192 QIODevice *result = m_input; 00193 //m_input = NULL; 00194 return result; 00195 } 00196 00197 void DecoderIOFactoryUrl::start(void) 00198 { 00199 LOG(VB_PLAYBACK, LOG_INFO, 00200 QString("DecoderIOFactory: Url %1").arg(getUrl().toString())); 00201 00202 m_started = false; 00203 00204 doOperationStart("Fetching remote file"); 00205 00206 m_reply = m_accessManager->get(QNetworkRequest(getUrl())); 00207 00208 connect(m_reply, SIGNAL(readyRead()), this, SLOT(readyRead())); 00209 connect(m_accessManager, SIGNAL(finished(QNetworkReply*)), 00210 this, SLOT(replyFinished(QNetworkReply*))); 00211 } 00212 00213 void DecoderIOFactoryUrl::stop(void) 00214 { 00215 doClose(); 00216 } 00217 00218 void DecoderIOFactoryUrl::replyFinished(QNetworkReply *reply) 00219 { 00220 if (reply->error() != QNetworkReply::NoError) 00221 { 00222 doFailed("Cannot retrieve remote file."); 00223 return; 00224 } 00225 00226 QUrl possibleRedirectUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); 00227 00228 if (!possibleRedirectUrl.isEmpty() && (m_redirectedURL != possibleRedirectUrl)) 00229 { 00230 LOG(VB_PLAYBACK, LOG_INFO, 00231 QString("DecoderIOFactory: Got redirected to %1") 00232 .arg(possibleRedirectUrl.toString())); 00233 00234 m_redirectCount++; 00235 00236 if (m_redirectCount > MaxRedirects) 00237 { 00238 doFailed("Too many redirects"); 00239 } 00240 else 00241 { 00242 setUrl(possibleRedirectUrl); 00243 m_redirectedURL = possibleRedirectUrl; 00244 start(); 00245 } 00246 00247 return; 00248 } 00249 00250 m_redirectedURL.clear(); 00251 00252 if (!m_started) 00253 doStart(); 00254 } 00255 00256 void DecoderIOFactoryUrl::readyRead(void) 00257 { 00258 int available = DecoderIOFactory::DefaultBufferSize - m_input->bytesAvailable(); 00259 QByteArray data = m_reply->read(available); 00260 00261 m_bytesWritten += data.size(); 00262 m_input->writeData(data.data(), data.size()); 00263 00264 if (!m_started && m_bytesWritten > DecoderIOFactory::DefaultPrebufferSize) 00265 { 00266 m_reply->setReadBufferSize(DecoderIOFactory::DefaultPrebufferSize); 00267 doStart(); 00268 } 00269 00270 #if 0 00271 LOG(VB_GENERAL, LOG_DEBUG, 00272 QString("DecoderIOFactoryUrl::readyRead file size: %1") 00273 .arg(m_bytesWritten)); 00274 #endif 00275 } 00276 00277 void DecoderIOFactoryUrl::doStart(void) 00278 { 00279 doConnectDecoder(getUrl().toString()); 00280 m_started = true; 00281 } 00282 00283 void DecoderIOFactoryUrl::doClose(void) 00284 { 00285 if (m_input && m_input->isOpen()) 00286 m_input->close(); 00287 } 00288 00289 /**********************************************************************/ 00290 00291 DecoderHandler::DecoderHandler(void) : 00292 m_state(STOPPED), 00293 m_playlist_pos(0), 00294 m_io_factory(NULL), 00295 m_decoder(NULL), 00296 m_meta(NULL), 00297 m_op(false), 00298 m_redirects(0) 00299 { 00300 } 00301 00302 DecoderHandler::~DecoderHandler(void) 00303 { 00304 stop(); 00305 } 00306 00307 void DecoderHandler::start(Metadata *mdata) 00308 { 00309 m_state = LOADING; 00310 00311 m_playlist.clear(); 00312 m_meta = mdata; 00313 m_playlist_pos = -1; 00314 m_redirects = 0; 00315 00316 QUrl url; 00317 if (QFileInfo(mdata->Filename()).isAbsolute()) 00318 url = QUrl::fromLocalFile(mdata->Filename()); 00319 else 00320 url.setUrl(mdata->Filename()); 00321 00322 bool result = createPlaylist(url); 00323 if (m_state == LOADING && result) 00324 { 00325 for (int ii = 0; ii < m_playlist.size(); ii++) 00326 LOG(VB_PLAYBACK, LOG_INFO, QString("Track %1 = %2") 00327 .arg(ii) .arg(m_playlist.get(ii)->File())); 00328 next(); 00329 } 00330 else 00331 { 00332 if (m_state != STOPPED) 00333 { 00334 doFailed(url, "Could not get playlist"); 00335 } 00336 } 00337 } 00338 00339 void DecoderHandler::error(const QString &e) 00340 { 00341 QString *str = new QString(e); 00342 DecoderHandlerEvent ev(DecoderHandlerEvent::Error, str); 00343 dispatch(ev); 00344 } 00345 00346 bool DecoderHandler::done(void) 00347 { 00348 if (m_state == STOPPED) 00349 return true; 00350 00351 if (m_playlist_pos + 1 >= m_playlist.size()) 00352 { 00353 m_state = STOPPED; 00354 return true; 00355 } 00356 00357 return false; 00358 } 00359 00360 bool DecoderHandler::next(void) 00361 { 00362 if (done()) 00363 return false; 00364 00365 if (m_meta && m_meta->Format() == "cast") 00366 { 00367 m_playlist_pos = random() % m_playlist.size(); 00368 } 00369 else 00370 { 00371 m_playlist_pos++; 00372 } 00373 00374 PlayListFileEntry *entry = m_playlist.get(m_playlist_pos); 00375 00376 QUrl url; 00377 if (QFileInfo(entry->File()).isAbsolute()) 00378 url = QUrl::fromLocalFile(entry->File()); 00379 else 00380 url.setUrl(entry->File()); 00381 00382 LOG(VB_PLAYBACK, LOG_INFO, QString("Now playing '%1'").arg(url.toString())); 00383 00384 deleteIOFactory(); 00385 createIOFactory(url); 00386 00387 if (! haveIOFactory()) 00388 return false; 00389 00390 getIOFactory()->addListener(this); 00391 getIOFactory()->setUrl(url); 00392 getIOFactory()->setMeta(m_meta); 00393 getIOFactory()->start(); 00394 m_state = ACTIVE; 00395 00396 return true; 00397 } 00398 00399 void DecoderHandler::stop(void) 00400 { 00401 LOG(VB_PLAYBACK, LOG_INFO, QString("DecoderHandler: Stopping decoder")); 00402 00403 if (m_decoder && m_decoder->isRunning()) 00404 { 00405 m_decoder->lock(); 00406 m_decoder->stop(); 00407 m_decoder->unlock(); 00408 } 00409 00410 if (m_decoder) 00411 { 00412 m_decoder->lock(); 00413 m_decoder->cond()->wakeAll(); 00414 m_decoder->unlock(); 00415 } 00416 00417 if (m_decoder) 00418 { 00419 m_decoder->wait(); 00420 //delete m_decoder->input(); // TODO: need to sort out who is responsible for the input 00421 delete m_decoder; 00422 m_decoder = NULL; 00423 } 00424 00425 deleteIOFactory(); 00426 doOperationStop(); 00427 00428 m_state = STOPPED; 00429 } 00430 00431 void DecoderHandler::customEvent(QEvent *e) 00432 { 00433 if (class DecoderHandlerEvent *event = dynamic_cast<DecoderHandlerEvent*>(e)) 00434 { 00435 // Proxy all DecoderHandlerEvents 00436 return dispatch(*event); 00437 } 00438 } 00439 00440 bool DecoderHandler::createPlaylist(const QUrl &url) 00441 { 00442 QString extension = QFileInfo(url.path()).suffix(); 00443 LOG(VB_NETWORK, LOG_INFO, 00444 QString("File %1 has extension %2") 00445 .arg(QFileInfo(url.path()).fileName()).arg(extension)); 00446 00447 if (extension == "pls" || extension == "m3u") 00448 { 00449 if (url.scheme() == "file" || QFileInfo(url.toString()).isAbsolute()) 00450 return createPlaylistFromFile(url); 00451 else 00452 return createPlaylistFromRemoteUrl(url); 00453 } 00454 00455 return createPlaylistForSingleFile(url); 00456 } 00457 00458 bool DecoderHandler::createPlaylistForSingleFile(const QUrl &url) 00459 { 00460 PlayListFileEntry *entry = new PlayListFileEntry; 00461 00462 if (url.scheme() == "file" || QFileInfo(url.toString()).isAbsolute()) 00463 entry->setFile(url.toLocalFile()); 00464 else 00465 entry->setFile(url.toString()); 00466 00467 m_playlist.add(entry); 00468 00469 return m_playlist.size() > 0; 00470 } 00471 00472 bool DecoderHandler::createPlaylistFromFile(const QUrl &url) 00473 { 00474 QFile f(QFileInfo(url.path()).absolutePath() + "/" + QFileInfo(url.path()).fileName()); 00475 f.open(QIODevice::ReadOnly); 00476 QTextStream stream(&f); 00477 00478 QString extension = QFileInfo(url.path()).suffix().toLower(); 00479 00480 if (PlayListFile::parse(&m_playlist, &stream, extension) <= 0) 00481 return false; 00482 00483 return m_playlist.size() > 0; 00484 } 00485 00486 bool DecoderHandler::createPlaylistFromRemoteUrl(const QUrl &url) 00487 { 00488 LOG(VB_NETWORK, LOG_INFO, 00489 QString("Retrieving playlist from '%1'").arg(url.toString())); 00490 00491 doOperationStart("Retrieving playlist"); 00492 00493 QByteArray data; 00494 00495 if (!GetMythDownloadManager()->download(url.toString(), &data)) 00496 { 00497 LOG(VB_GENERAL, LOG_ERR, QString("DecoderHandler:: Failed to download playlist from: %1").arg(url.toString())); 00498 doOperationStop(); 00499 return false; 00500 } 00501 00502 doOperationStop(); 00503 00504 QTextStream stream(&data, QIODevice::ReadOnly); 00505 00506 QString extension = QFileInfo(url.path()).suffix().toLower(); 00507 00508 bool result = PlayListFile::parse(&m_playlist, &stream, extension) > 0; 00509 00510 return result; 00511 } 00512 00513 void DecoderHandler::doConnectDecoder(const QUrl &url, const QString &format) 00514 { 00515 if (m_decoder && !m_decoder->factory()->supports(format)) 00516 { 00517 delete m_decoder; 00518 m_decoder = NULL; 00519 } 00520 00521 if (!m_decoder) 00522 { 00523 if ((m_decoder = Decoder::create(format, NULL, NULL, true)) == NULL) 00524 { 00525 doFailed(url, QString("No decoder for this format '%1'").arg(format)); 00526 return; 00527 } 00528 } 00529 00530 m_decoder->setInput(getIOFactory()->takeInput()); 00531 m_decoder->setFilename(url.toString()); 00532 00533 DecoderHandlerEvent ev(DecoderHandlerEvent::Ready); 00534 dispatch(ev); 00535 } 00536 00537 void DecoderHandler::doFailed(const QUrl &url, const QString &message) 00538 { 00539 LOG(VB_NETWORK, LOG_ERR, 00540 QString("DecoderHandler: Unsupported file format: '%1' - %2") 00541 .arg(url.toString()).arg(message)); 00542 DecoderHandlerEvent ev(DecoderHandlerEvent::Error, new QString(message)); 00543 dispatch(ev); 00544 } 00545 00546 void DecoderHandler::doInfo(const QString &message) 00547 { 00548 DecoderHandlerEvent ev(DecoderHandlerEvent::Info, new QString(message)); 00549 dispatch(ev); 00550 } 00551 00552 void DecoderHandler::doOperationStart(const QString &name) 00553 { 00554 m_op = true; 00555 DecoderHandlerEvent ev(DecoderHandlerEvent::OperationStart, new QString(name)); 00556 dispatch(ev); 00557 } 00558 00559 void DecoderHandler::doOperationStop(void) 00560 { 00561 if (!m_op) 00562 return; 00563 00564 m_op = false; 00565 DecoderHandlerEvent ev(DecoderHandlerEvent::OperationStop); 00566 dispatch(ev); 00567 } 00568 00569 void DecoderHandler::createIOFactory(const QUrl &url) 00570 { 00571 if (haveIOFactory()) 00572 deleteIOFactory(); 00573 00574 if (url.scheme() == "myth") 00575 m_io_factory = new DecoderIOFactorySG(this); 00576 else if (m_meta && m_meta->Format() == "cast") 00577 m_io_factory = new DecoderIOFactoryShoutCast(this); 00578 else if (url.scheme() == "http") 00579 m_io_factory = new DecoderIOFactoryUrl(this); 00580 else 00581 m_io_factory = new DecoderIOFactoryFile(this); 00582 } 00583 00584 void DecoderHandler::deleteIOFactory(void) 00585 { 00586 if (!haveIOFactory()) 00587 return; 00588 00589 if (m_state == ACTIVE) 00590 m_io_factory->stop(); 00591 00592 m_io_factory->removeListener(this); 00593 m_io_factory->disconnect(); 00594 m_io_factory->deleteLater(); 00595 m_io_factory = NULL; 00596 } 00597 00598 /**********************************************************************/ 00599 00600 qint64 MusicBuffer::read(char *data, qint64 max, bool doRemove) 00601 { 00602 QMutexLocker holder (&m_mutex); 00603 const char *buffer_data = m_buffer.data(); 00604 00605 if (max > m_buffer.size()) 00606 max = m_buffer.size(); 00607 00608 memcpy(data, buffer_data, max); 00609 00610 if (doRemove) 00611 m_buffer.remove(0, max); 00612 00613 return max; 00614 } 00615 00616 qint64 MusicBuffer::read(QByteArray &data, qint64 max, bool doRemove) 00617 { 00618 QMutexLocker holder (&m_mutex); 00619 const char *buffer_data = m_buffer.data(); 00620 00621 if (max > m_buffer.size()) 00622 max = m_buffer.size(); 00623 00624 data.append(buffer_data, max); 00625 00626 if (doRemove) 00627 m_buffer.remove(0, max); 00628 00629 return max; 00630 } 00631 00632 void MusicBuffer::write(const char *data, uint sz) 00633 { 00634 if (sz == 0) 00635 return; 00636 00637 QMutexLocker holder(&m_mutex); 00638 m_buffer.append(data, sz); 00639 } 00640 00641 void MusicBuffer::write(QByteArray &array) 00642 { 00643 if (array.size() == 0) 00644 return; 00645 00646 QMutexLocker holder(&m_mutex); 00647 m_buffer.append(array); 00648 } 00649 00650 void MusicBuffer::remove(int index, int len) 00651 { 00652 QMutexLocker holder(&m_mutex); 00653 m_buffer.remove(index, len); 00654 } 00655 00656 /**********************************************************************/ 00657 00658 MusicIODevice::MusicIODevice(void) 00659 { 00660 m_buffer = new MusicBuffer; 00661 setOpenMode(ReadWrite); 00662 } 00663 00664 MusicIODevice::~MusicIODevice(void) 00665 { 00666 delete m_buffer; 00667 } 00668 00669 bool MusicIODevice::open(int) 00670 { 00671 return true; 00672 } 00673 00674 qint64 MusicIODevice::size(void) const 00675 { 00676 return m_buffer->readBufAvail(); 00677 } 00678 00679 qint64 MusicIODevice::readData(char *data, qint64 maxlen) 00680 { 00681 qint64 res = m_buffer->read(data, maxlen); 00682 emit freeSpaceAvailable(); 00683 return res; 00684 } 00685 00686 qint64 MusicIODevice::writeData(const char *data, qint64 sz) 00687 { 00688 m_buffer->write(data, sz); 00689 return sz; 00690 } 00691 00692 qint64 MusicIODevice::bytesAvailable(void) const 00693 { 00694 return m_buffer->readBufAvail(); 00695 } 00696 00697 int MusicIODevice::getch(void) 00698 { 00699 assert(0); 00700 return -1; 00701 } 00702 00703 int MusicIODevice::putch(int) 00704 { 00705 assert(0); 00706 return -1; 00707 } 00708 00709 int MusicIODevice::ungetch(int) 00710 { 00711 assert(0); 00712 return -1; 00713 } 00714 00715 /**********************************************************************/ 00716 00717 MusicSGIODevice::MusicSGIODevice(const QString &url) 00718 { 00719 m_remotefile = new RemoteFile(url); 00720 m_remotefile->Open(); 00721 00722 setOpenMode(ReadWrite); 00723 } 00724 00725 MusicSGIODevice::~MusicSGIODevice(void) 00726 { 00727 m_remotefile->Close(); 00728 delete m_remotefile; 00729 } 00730 00731 bool MusicSGIODevice::open(int) 00732 { 00733 return true; 00734 } 00735 00736 bool MusicSGIODevice::seek(qint64 pos) 00737 { 00738 long int newPos = -1; 00739 00740 if (m_remotefile) 00741 newPos = m_remotefile->Seek(pos, 0); 00742 00743 return (newPos == pos); 00744 } 00745 00746 qint64 MusicSGIODevice::size(void) const 00747 { 00748 return m_remotefile->GetFileSize(); 00749 } 00750 00751 qint64 MusicSGIODevice::readData(char *data, qint64 maxlen) 00752 { 00753 qint64 res = m_remotefile->Read(data, maxlen); 00754 return res; 00755 } 00756 00757 qint64 MusicSGIODevice::writeData(const char *data, qint64 sz) 00758 { 00759 m_remotefile->Write(data, sz); 00760 return sz; 00761 } 00762 00763 qint64 MusicSGIODevice::bytesAvailable(void) const 00764 { 00765 return m_remotefile->GetFileSize(); 00766 } 00767 00768 int MusicSGIODevice::getch(void) 00769 { 00770 assert(0); 00771 return -1; 00772 } 00773 00774 int MusicSGIODevice::putch(int) 00775 { 00776 assert(0); 00777 return -1; 00778 } 00779 00780 int MusicSGIODevice::ungetch(int) 00781 { 00782 assert(0); 00783 return -1; 00784 }
1.7.6.1