void AlarmNotifyThread::run() { RunProlog(); while (!m_stop) { // get the alarm status for all monitors if (ZMClient::get()->connected() && ZMClient::get()->updateAlarmStates()) { // at least one monitor changed state for (int x = 0; x < ZMClient::get()->getMonitorCount(); x++) { Monitor *mon = ZMClient::get()->getMonitorAt(x); if (mon->previousState != mon->state && (mon->state == ALARM || (mon->state == ALERT && mon->previousState != ALARM))) { // have notifications been turned on for this monitor? if (mon->showNotifications) { // we can't show a popup from the AlarmNotifyThread so send // a message to ZMClient to do it for us gCoreContext->dispatch(MythEvent(QString("ZONEMINDER_NOTIFICATION %1").arg(mon->id))); } } } } usleep(999999); } RunEpilog(); }
void SSDP::run() { RunProlog(); fd_set read_set; struct timeval timeout; LOG(VB_UPNP, LOG_INFO, "SSDP::Run - SSDP Thread Started." ); // ---------------------------------------------------------------------- // Listen for new Requests // ---------------------------------------------------------------------- while ( ! m_bTermRequested ) { int nMaxSocket = 0; FD_ZERO( &read_set ); for (uint nIdx = 0; nIdx < NumberOfSockets; nIdx++ ) { if (m_Sockets[nIdx] != NULL && m_Sockets[nIdx]->socket() >= 0) { FD_SET( m_Sockets[ nIdx ]->socket(), &read_set ); nMaxSocket = max( m_Sockets[ nIdx ]->socket(), nMaxSocket ); #if 0 if (m_Sockets[ nIdx ]->bytesAvailable() > 0) { LOG(VB_GENERAL, LOG_DEBUG, QString("Found Extra data before select: %1") .arg(nIdx)); ProcessData( m_Sockets[ nIdx ] ); } #endif } } timeout.tv_sec = 1; timeout.tv_usec = 0; int count; count = select(nMaxSocket + 1, &read_set, NULL, NULL, &timeout); for (int nIdx = 0; count && nIdx < (int)NumberOfSockets; nIdx++ ) { if (m_Sockets[nIdx] != NULL && m_Sockets[nIdx]->socket() >= 0 && FD_ISSET(m_Sockets[nIdx]->socket(), &read_set)) { #if 0 LOG(VB_GENERAL, LOG_DEBUG, QString("FD_ISSET( %1 )").arg(nIdx)); #endif ProcessData(m_Sockets[nIdx]); count--; } } } RunEpilog(); }
void MetadataLoadingThread::run() { RunProlog(); //if you want to simulate a big music collection load //sleep(3); parent->resync(); RunEpilog(); }
void MythSystemSignalManager::run(void) { RunProlog(); LOG(VB_GENERAL, LOG_INFO, "Starting process signal handler"); while( run_system ) { struct timespec ts; ts.tv_sec = 0; ts.tv_nsec = 50 * 1000 * 1000; // 50ms nanosleep(&ts, NULL); // sleep 50ms while( run_system ) { // handle cleanup and signalling for closed processes listLock.lock(); if( msList.isEmpty() ) { listLock.unlock(); break; } MythSystemUnix *ms = msList.takeFirst(); listLock.unlock(); // This can happen if it has been deleted already if (!ms) continue; ms->m_parent->HandlePostRun(); if (ms->m_stdpipe[0] > 0) writeThread->remove(ms->m_stdpipe[0]); CLOSE(ms->m_stdpipe[0]); if (ms->m_stdpipe[1] > 0) readThread->remove(ms->m_stdpipe[1]); CLOSE(ms->m_stdpipe[1]); if (ms->m_stdpipe[2] > 0) readThread->remove(ms->m_stdpipe[2]); CLOSE(ms->m_stdpipe[2]); if( ms->GetStatus() == GENERIC_EXIT_OK ) emit ms->finished(); else emit ms->error(ms->GetStatus()); ms->disconnect(); bool cleanup = ms->m_parent->doAutoCleanup(); ms->Unlock(); if( cleanup ) ms->deleteLater(); } } RunEpilog(); }
// spawn separate thread for signals to prevent manager void MythSystemLegacySignalManager::run(void) { RunProlog(); LOG(VB_GENERAL, LOG_INFO, "Starting process signal handler"); while( run_system ) { usleep(50000); // sleep 50ms while( run_system ) { // handle cleanup and signalling for closed processes listLock.lock(); if( msList.isEmpty() ) { listLock.unlock(); break; } MythSystemLegacyWindows *ms = msList.takeFirst(); listLock.unlock(); if (!ms) continue; if (ms->m_parent) { ms->m_parent->HandlePostRun(); } if (ms->m_stdpipe[0]) writeThread->remove(ms->m_stdpipe[0]); CLOSE(ms->m_stdpipe[0]); if (ms->m_stdpipe[1]) readThread->remove(ms->m_stdpipe[1]); CLOSE(ms->m_stdpipe[1]); if (ms->m_stdpipe[2]) readThread->remove(ms->m_stdpipe[2]); CLOSE(ms->m_stdpipe[2]); if (ms->m_parent) { if( ms->GetStatus() == GENERIC_EXIT_OK ) emit ms->finished(); else emit ms->error(ms->GetStatus()); ms->disconnect(); ms->Unlock(); } ms->DecrRef(); } } RunEpilog(); }
void FetcherThread::run(void) { RunProlog(); LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Starting Fetcher thread.")); if (m_dec) m_dec->FetchFrames(); LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Stopping Fetcher thread.")); RunEpilog(); }
void PlaylistLoadingThread::run() { RunProlog(); while (!all_music->doneLoading()) { msleep(250); } parent->load(); RunEpilog(); }
void DVBStreamHandler::run(void) { RunProlog(); LOG(VB_RECORD, LOG_INFO, LOC + "run(): begin"); if (!SupportsTSMonitoring() && _allow_section_reader) RunSR(); else RunTS(); LOG(VB_RECORD, LOG_INFO, LOC + "run(): end"); RunEpilog(); }
void MythSystemLegacyIOHandler::run(void) { RunProlog(); LOG(VB_GENERAL, LOG_INFO, QString("Starting IO manager (%1)") .arg(m_read ? "read" : "write")); while( run_system ) { { QMutexLocker locker(&m_pWaitLock); m_pWait.wait(&m_pWaitLock); } while( run_system ) { usleep(10000); // ~100x per second, for ~3MBps throughput m_pLock.lock(); if( m_pMap.isEmpty() ) { m_pLock.unlock(); break; } bool datafound = true; m_pLock.unlock(); while ( datafound && run_system ) { m_pLock.lock(); datafound = false; PMap_t::iterator i, next; for( i = m_pMap.begin(); i != m_pMap.end(); i = next ) { next = i + 1; if( m_read ) datafound |= HandleRead(i.key(), i.value()); else datafound |= HandleWrite(i.key(), i.value()); } m_pLock.unlock(); } } } RunEpilog(); }
void GameScannerThread::run(void) { RunProlog(); LOG(VB_GENERAL, LOG_INFO, QString("Beginning Game Scan.")); m_files.clear(); m_remove.clear(); m_dbgames = RomInfo::GetAllRomInfo(); buildFileList(); verifyFiles(); updateDB(); RunEpilog(); }
void MythSignalingTimer::run(void) { running = true; RunProlog(); while (dorun) { QMutexLocker locker(&startStopLock); if (dorun && !timerWait.wait(locker.mutex(), millisec)) { locker.unlock(); emit timeout(); locker.relock(); } } RunEpilog(); running = false; }
/** \class HouseKeepingThread * \ingroup housekeeper * \brief Thread used to perform queued HouseKeeper tasks. * * This class is a long-running thread that pulls tasks out of the * HouseKeeper queue and runs them sequentially. It performs one last check * of the task to make sure something else in the same scope has not * pre-empted it, before running the task. * */ void HouseKeepingThread::run(void) { RunProlog(); m_waitMutex.lock(); HouseKeeperTask *task = NULL; while (m_keepRunning) { m_idle = false; while ((task = m_parent->GetQueuedTask())) { // pull task from housekeeper and process it ReferenceLocker rlock(task); if (!task->ConfirmRun()) { // something else has caused the lastrun time to // change since this was requested to run. abort. task = NULL; continue; } task->UpdateLastRun(); task->Run(); task = NULL; if (!m_keepRunning) // thread has been discarded, don't try to start another task break; } m_idle = true; if (!m_keepRunning) // short out rather than potentially hitting another sleep cycle break; m_waitCondition.wait(&m_waitMutex); } m_waitMutex.unlock(); RunEpilog(); }
/// \brief Basic signal monitoring loop void SignalMonitor::run(void) { RunProlog(); QMutexLocker locker(&startStopLock); running = true; startStopWait.wakeAll(); while (!exit) { locker.unlock(); UpdateValues(); if (notify_frontend && capturecardnum>=0) { QStringList slist = GetStatusList(); MythEvent me(QString("SIGNAL %1").arg(capturecardnum), slist); gCoreContext->dispatch(me); } locker.relock(); startStopWait.wait(locker.mutex(), update_rate); } // We need to send a last informational message because a // signal update may have come in while we were sleeping // if we are using the multithreaded dtvsignalmonitor. locker.unlock(); if (notify_frontend && capturecardnum>=0) { QStringList slist = GetStatusList(); MythEvent me(QString("SIGNAL %1").arg(capturecardnum), slist); gCoreContext->dispatch(me); } locker.relock(); running = false; startStopWait.wakeAll(); RunEpilog(); }
void TaskQueue::run( ) { RunProlog(); Task *pTask; LOG(VB_UPNP, LOG_INFO, "TaskQueue Thread Running."); while ( !m_bTermRequested ) { // ------------------------------------------------------------------ // Process Any Tasks that may need to be executed. // ------------------------------------------------------------------ TaskTime ttNow; gettimeofday( (&ttNow), nullptr ); if ((pTask = GetNextExpiredTask( ttNow )) != nullptr) { try { pTask->Execute( this ); pTask->DecrRef(); } catch( ... ) { LOG(VB_GENERAL, LOG_ERR, "Call to Execute threw an exception."); } } // Make sure to throttle our processing. msleep( 100 ); } RunEpilog(); }
void HLSStreamHandler::run(void) { RunProlog(); int cnt = 0; LOG(VB_GENERAL, LOG_INFO, LOC + "run() -- begin"); SetRunning(true, false, false); if (!m_hls) return; m_hls->Throttle(false); while (_running_desired) { if (!m_hls->IsOpen(m_tuning.GetURL(0).toString())) { if (!m_hls->Open(m_tuning.GetURL(0).toString())) { LOG(VB_CHANNEL, LOG_INFO, LOC + "run: HLS OpenFile() failed"); usleep(500000); continue; } m_hls->Throttle(true); } int size = m_hls->Read(m_buffer, BUFFER_SIZE); if (size < 0) { // error if (++cnt > 10) { Stop(); break; } continue; } else cnt = 0; if (size == 0) { usleep(250000); // .25 second continue; } if (m_buffer[0] != 0x47) { LOG(VB_RECORD, LOG_INFO, LOC + QString("Packet not starting with SYNC Byte (got 0x%1)") .arg((char)m_buffer[0], 2, QLatin1Char('0'))); continue; } int remainder = 0; { QMutexLocker locker(&_listener_lock); HLSStreamHandler::StreamDataList::const_iterator sit; sit = _stream_data_list.begin(); for (; sit != _stream_data_list.end(); ++sit) { remainder = sit.key()->ProcessData(m_buffer, size); } } if (remainder != 0) { LOG(VB_RECORD, LOG_INFO, LOC + QString("data_length = %1 remainder = %2") .arg(size).arg(remainder)); } if (m_hls->IsThrottled()) usleep(1000000); else if (size < BUFFER_SIZE) usleep(100000); // tenth of a second. else usleep(1000); } m_hls->Throttle(false); SetRunning(false, false, false); RunEpilog(); LOG(VB_GENERAL, LOG_INFO, LOC + "run() -- done"); }
void MythSystemIOHandler::run(void) { RunProlog(); LOG(VB_GENERAL, LOG_INFO, QString("Starting IO manager (%1)") .arg(m_read ? "read" : "write")); m_pLock.lock(); BuildFDs(); m_pLock.unlock(); while( run_system ) { { QMutexLocker locker(&m_pWaitLock); m_pWait.wait(&m_pWaitLock); } while( run_system ) { usleep(10000); // ~100x per second, for ~3MBps throughput m_pLock.lock(); if( m_pMap.isEmpty() ) { m_pLock.unlock(); break; } timeval tv; tv.tv_sec = 0; tv.tv_usec = 0; int retval; fd_set fds = m_fds; if( m_read ) retval = select(m_maxfd+1, &fds, NULL, NULL, &tv); else retval = select(m_maxfd+1, NULL, &fds, NULL, &tv); if( retval == -1 ) LOG(VB_SYSTEM, LOG_ERR, QString("MythSystemIOHandler: select(%1, %2) failed: %3") .arg(m_maxfd+1).arg(m_read).arg(strerror(errno))); else if( retval > 0 ) { PMap_t::iterator i, next; for( i = m_pMap.begin(); i != m_pMap.end(); i = next ) { next = i+1; int fd = i.key(); if( FD_ISSET(fd, &fds) ) { if( m_read ) HandleRead(i.key(), i.value()); else HandleWrite(i.key(), i.value()); } } } m_pLock.unlock(); } } RunEpilog(); }
void ExternalStreamHandler::run(void) { QString cmd; QString result; QString xon; QByteArray buffer; uint len; RunProlog(); LOG(VB_RECORD, LOG_INFO, LOC + "run(): begin"); SetRunning(true, true, false); if (m_poll_mode) xon = QString("SendBytes:%1").arg(PACKET_SIZE); else xon = "XON"; uint remainder = 0; while (_running_desired && !_error) { if (!IsOpen()) { if (!Open()) { LOG(VB_RECORD, LOG_WARNING, LOC + QString("TS not open yet: %1") .arg(m_error)); usleep(750000); continue; } } if (StreamingCount() == 0) { usleep(5000); continue; } UpdateFiltersFromStreamData(); ProcessCommand(xon, 1000, result); if (result.startsWith("ERR")) { LOG(VB_GENERAL, LOG_ERR, LOC + QString("Aborting: %1 -> %2") .arg(xon).arg(result)); _error = true; } while ((len = m_IO->Read(buffer, PACKET_SIZE, 10)) > 0 || buffer.size() > 188*50) { if (m_IO->Error()) { m_error = m_IO->ErrorString(); _error = true; LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to read from Extern recorder: %1") .arg(m_error)); break; } if (!_running_desired) break; if (!_listener_lock.tryLock()) continue; if (_stream_data_list.empty()) { LOG(VB_GENERAL, LOG_ERR, LOC + "_stream_data_list is empty"); _listener_lock.unlock(); continue; } if (!m_poll_mode) { ProcessCommand(QString("XOFF"), 50, result); if (result.startsWith("ERR")) { LOG(VB_GENERAL, LOG_ERR, LOC + QString("Aborting: %1 -> %2") .arg(xon).arg(result)); _error = true; } } StreamDataList::const_iterator sit = _stream_data_list.begin(); for (; sit != _stream_data_list.end(); ++sit) remainder = sit.key()->ProcessData (reinterpret_cast<const uint8_t *> (buffer.constData()), buffer.size()); _listener_lock.unlock(); len = buffer.size(); if (m_replay) { m_replay_buffer += buffer.left(len - remainder); if (m_replay_buffer.size() > (5000 * PACKET_SIZE)) { m_replay_buffer.remove(0, len - remainder); LOG(VB_RECORD, LOG_WARNING, LOC + QString("Replay size truncated to %1 bytes") .arg(m_replay_buffer.size())); } } if (remainder > 0 && (len > remainder)) // leftover bytes buffer.remove(0, len - remainder); else buffer.clear(); } usleep(10); } LOG(VB_RECORD, LOG_INFO, LOC + "run(): " + "shutdown"); RemoveAllPIDFilters(); SetRunning(false, true, false); LOG(VB_RECORD, LOG_INFO, LOC + "run(): " + "end"); RunEpilog(); }
void IPTVTableMonitorThread::run(void) { RunProlog(); m_parent->RunTableMonitor(); RunEpilog(); }
void CetonStreamHandler::run(void) { RunProlog(); bool _error = false; QFile file(_device_path); CetonRTP rtp(_ip_address, _tuner); if (_using_rtp) { if (!(rtp.Init() && rtp.StartStreaming())) { LOG(VB_RECORD, LOG_ERR, LOC + "Starting recording (RTP initialization failed). Aborting."); _error = true; } } else { if (!file.open(QIODevice::ReadOnly)) { LOG(VB_RECORD, LOG_ERR, LOC + "Starting recording (file open failed). Aborting."); _error = true; } int flags = fcntl(file.handle(), F_GETFL, 0); if (flags == -1) flags = 0; fcntl(file.handle(), F_SETFL, flags | O_NONBLOCK); } if (_error) { RunEpilog(); return; } SetRunning(true, false, false); int buffer_size = (64 * 1024); // read about 64KB buffer_size /= TSPacket::kSize; buffer_size *= TSPacket::kSize; char *buffer = new char[buffer_size]; LOG(VB_RECORD, LOG_INFO, LOC + "RunTS(): begin"); _read_timer.start(); int remainder = 0; while (_running_desired && !_error) { int bytes_read; if (_using_rtp) bytes_read = rtp.Read(buffer, buffer_size); else bytes_read = file.read(buffer, buffer_size); if (bytes_read <= 0) { if (_read_timer.elapsed() >= 5000) { LOG(VB_RECORD, LOG_WARNING, LOC + "No data received for 5 seconds...checking tuning"); if (!VerifyTuning()) RepeatTuning(); _read_timer.start(); } usleep(5000); continue; } _read_timer.start(); _listener_lock.lock(); if (_stream_data_list.empty()) { _listener_lock.unlock(); continue; } StreamDataList::const_iterator sit = _stream_data_list.begin(); for (; sit != _stream_data_list.end(); ++sit) remainder = sit.key()->ProcessData( reinterpret_cast<unsigned char*>(buffer), bytes_read); _listener_lock.unlock(); if (remainder != 0) { LOG(VB_RECORD, LOG_INFO, LOC + QString("RunTS(): bytes_read = %1 remainder = %2") .arg(bytes_read).arg(remainder)); } } LOG(VB_RECORD, LOG_INFO, LOC + "RunTS(): " + "shutdown"); if (_using_rtp) rtp.StopStreaming(); else file.close(); delete[] buffer; LOG(VB_RECORD, LOG_INFO, LOC + "RunTS(): " + "end"); SetRunning(false, false, false); RunEpilog(); }
void ASIStreamHandler::run(void) { RunProlog(); LOG(VB_RECORD, LOG_INFO, LOC + "run(): begin"); if (!Open()) { LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to open device %1 : %2") .arg(_device).arg(strerror(errno))); _error = true; return; } DeviceReadBuffer *drb = new DeviceReadBuffer(this, true, false); bool ok = drb->Setup(_device, _fd, _packet_size, _buf_size); if (!ok) { LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to allocate DRB buffer"); delete drb; drb = NULL; Close(); _error = true; RunEpilog(); return; } uint buffer_size = _packet_size * 15000; unsigned char *buffer = new unsigned char[buffer_size]; if (!buffer) { LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to allocate buffer"); delete drb; drb = NULL; Close(); _error = true; RunEpilog(); return; } memset(buffer, 0, buffer_size); SetRunning(true, true, false); drb->Start(); { QMutexLocker locker(&_start_stop_lock); _drb = drb; } int remainder = 0; while (_running_desired && !_error) { UpdateFiltersFromStreamData(); ssize_t len = 0; len = drb->Read( &(buffer[remainder]), buffer_size - remainder); if (!_running_desired) break; // Check for DRB errors if (drb->IsErrored()) { LOG(VB_GENERAL, LOG_ERR, LOC + "Device error detected"); _error = true; } if (drb->IsEOF()) { LOG(VB_GENERAL, LOG_ERR, LOC + "Device EOF detected"); _error = true; } if ((0 == len) || (-1 == len)) { usleep(100); continue; } len += remainder; if (len < 10) // 10 bytes = 4 bytes TS header + 6 bytes PES header { remainder = len; continue; } if (!_listener_lock.tryLock()) { remainder = len; continue; } if (_stream_data_list.empty()) { _listener_lock.unlock(); continue; } StreamDataList::const_iterator sit = _stream_data_list.begin(); for (; sit != _stream_data_list.end(); ++sit) remainder = sit.key()->ProcessData(buffer, len); if (_mpts != NULL) _mpts->Write(buffer, len - remainder); _listener_lock.unlock(); if (remainder > 0 && (len > remainder)) // leftover bytes memmove(buffer, &(buffer[len - remainder]), remainder); } LOG(VB_RECORD, LOG_INFO, LOC + "run(): " + "shutdown"); RemoveAllPIDFilters(); { QMutexLocker locker(&_start_stop_lock); _drb = NULL; } if (drb->IsRunning()) drb->Stop(); delete drb; delete[] buffer; Close(); LOG(VB_RECORD, LOG_INFO, LOC + "run(): " + "end"); SetRunning(false, true, false); RunEpilog(); }
/** \fn HDHRStreamHandler::run(void) * \brief Reads HDHomeRun socket for tables & data */ void HDHRStreamHandler::run(void) { RunProlog(); /* Create TS socket. */ if (!hdhomerun_device_stream_start(_hdhomerun_device)) { LOG(VB_GENERAL, LOG_ERR, LOC + "Starting recording (set target failed). Aborting."); _error = true; RunEpilog(); return; } hdhomerun_device_stream_flush(_hdhomerun_device); SetRunning(true, false, false); LOG(VB_RECORD, LOG_INFO, LOC + "RunTS(): begin"); int remainder = 0; QTime last_update; while (_running_desired && !_error) { int elapsed = !last_update.isValid() ? -1 : last_update.elapsed(); elapsed = (elapsed < 0) ? 1000 : elapsed; if (elapsed > 100) { UpdateFiltersFromStreamData(); if (_tune_mode != hdhrTuneModeVChannel) UpdateFilters(); last_update.restart(); } size_t read_size = 64 * 1024; // read about 64KB read_size /= VIDEO_DATA_PACKET_SIZE; read_size *= VIDEO_DATA_PACKET_SIZE; size_t data_length; unsigned char *data_buffer = hdhomerun_device_stream_recv( _hdhomerun_device, read_size, &data_length); if (!data_buffer) { usleep(20000); continue; } // Assume data_length is a multiple of 188 (packet size) _listener_lock.lock(); if (_stream_data_list.empty()) { _listener_lock.unlock(); continue; } StreamDataList::const_iterator sit = _stream_data_list.begin(); for (; sit != _stream_data_list.end(); ++sit) remainder = sit.key()->ProcessData(data_buffer, data_length); _listener_lock.unlock(); if (remainder != 0) { LOG(VB_RECORD, LOG_INFO, LOC + QString("RunTS(): data_length = %1 remainder = %2") .arg(data_length).arg(remainder)); } } LOG(VB_RECORD, LOG_INFO, LOC + "RunTS(): " + "shutdown"); RemoveAllPIDFilters(); hdhomerun_device_stream_stop(_hdhomerun_device); LOG(VB_RECORD, LOG_INFO, LOC + "RunTS(): " + "end"); SetRunning(false, false, false); RunEpilog(); }
void MetadataDownload::run() { RunProlog(); MetadataLookup* lookup; while ((lookup = moreWork()) != NULL) { MetadataLookupList list; // Go go gadget Metadata Lookup if (lookup->GetType() == kMetadataVideo) { if (lookup->GetSubtype() == kProbableTelevision) list = handleTelevision(lookup); else if (lookup->GetSubtype() == kProbableMovie) list = handleMovie(lookup); else list = handleVideoUndetermined(lookup); if (!list.size() && lookup->GetSubtype() == kUnknownVideo) { list = handleMovie(lookup); } } else if (lookup->GetType() == kMetadataRecording) { if (lookup->GetSubtype() == kProbableTelevision) { if (lookup->GetSeason() > 0 || lookup->GetEpisode() > 0) list = handleTelevision(lookup); else if (!lookup->GetSubtitle().isEmpty()) list = handleVideoUndetermined(lookup); if (!list.size()) list = handleRecordingGeneric(lookup); } else if (lookup->GetSubtype() == kProbableMovie) { list = handleMovie(lookup); if (lookup->GetInetref().isEmpty()) list.append(handleRecordingGeneric(lookup)); } else { list = handleRecordingGeneric(lookup); if (lookup->GetInetref().isEmpty()) list.append(handleMovie(lookup)); } } else if (lookup->GetType() == kMetadataGame) list = handleGame(lookup); // inform parent we have lookup ready for it if (m_parent && list.count() >= 1) { // If there's only one result, don't bother asking // our parent about it, just add it to the back of // the queue in kLookupData mode. if (list.count() == 1 && list.at(0)->GetStep() == kLookupSearch) { MetadataLookup *newlookup = list.takeFirst(); newlookup->SetStep(kLookupData); prependLookup(newlookup); continue; } // If we're in automatic mode, we need to make // these decisions on our own. Pass to title match. if (list.at(0)->GetAutomatic() && list.count() > 1) { if (!findBestMatch(list, lookup->GetTitle())) QCoreApplication::postEvent(m_parent, new MetadataLookupFailure(MetadataLookupList() << lookup)); continue; } LOG(VB_GENERAL, LOG_INFO, QString("Returning Metadata Results: %1 %2 %3") .arg(lookup->GetTitle()).arg(lookup->GetSeason()) .arg(lookup->GetEpisode())); QCoreApplication::postEvent(m_parent, new MetadataLookupEvent(list)); } else { list.append(lookup); QCoreApplication::postEvent(m_parent, new MetadataLookupFailure(list)); } } RunEpilog(); }
void VideoScannerThread::run() { RunProlog(); VideoMetadataListManager::metadata_list ml; VideoMetadataListManager::loadAllFromDatabase(ml); m_dbmetadata->setList(ml); QList<QByteArray> image_types = QImageReader::supportedImageFormats(); QStringList imageExtensions; for (QList<QByteArray>::const_iterator p = image_types.begin(); p != image_types.end(); ++p) { imageExtensions.push_back(QString(*p)); } LOG(VB_GENERAL, LOG_INFO, QString("Beginning Video Scan.")); uint counter = 0; FileCheckList fs_files; if (m_HasGUI) SendProgressEvent(counter, (uint)m_directories.size(), tr("Searching for video files")); for (QStringList::const_iterator iter = m_directories.begin(); iter != m_directories.end(); ++iter) { if (!buildFileList(*iter, imageExtensions, fs_files)) { if (iter->startsWith("myth://")) { QUrl sgurl = *iter; QString host = sgurl.host().toLower(); QString path = sgurl.path(); m_liveSGHosts.removeAll(host); LOG(VB_GENERAL, LOG_ERR, QString("Failed to scan :%1:").arg(*iter)); } } if (m_HasGUI) SendProgressEvent(++counter); } PurgeList db_remove; verifyFiles(fs_files, db_remove); m_DBDataChanged = updateDB(fs_files, db_remove); if (m_DBDataChanged) { QCoreApplication::postEvent(m_parent, new VideoScanChanges(m_addList, m_movList, m_delList)); QStringList slist; QList<int>::const_iterator i; for (i = m_addList.begin(); i != m_addList.end(); ++i) slist << QString("added::%1").arg(*i); for (i = m_movList.begin(); i != m_movList.end(); ++i) slist << QString("moved::%1").arg(*i); for (i = m_delList.begin(); i != m_delList.end(); ++i) slist << QString("deleted::%1").arg(*i); MythEvent me("VIDEO_LIST_CHANGE", slist); gCoreContext->SendEvent(me); } else gCoreContext->SendMessage("VIDEO_LIST_NO_CHANGE"); RunEpilog(); }
void MetadataImageDownload::run() { RunProlog(); // Always handle thumbnails first, they're higher priority. ThumbnailData *thumb; while ((thumb = moreThumbs()) != NULL) { QString sFilename = getDownloadFilename(thumb->title, thumb->url); bool exists = QFile::exists(sFilename); if (!exists && !thumb->url.isEmpty()) { if (!GetMythDownloadManager()->download(thumb->url, sFilename)) { LOG(VB_GENERAL, LOG_ERR, QString("MetadataImageDownload: failed to download thumbnail from: %1") .arg(thumb->url)); delete thumb; continue; } } // inform parent we have thumbnail ready for it if (QFile::exists(sFilename) && m_parent) { LOG(VB_GENERAL, LOG_DEBUG, QString("Threaded Image Thumbnail Download: %1") .arg(sFilename)); thumb->url = sFilename; QCoreApplication::postEvent(m_parent, new ThumbnailDLEvent(thumb)); } else delete thumb; } MetadataLookup *lookup; while ((lookup = moreDownloads()) != NULL) { DownloadMap downloads = lookup->GetDownloads(); DownloadMap downloaded; for (DownloadMap::iterator i = downloads.begin(); i != downloads.end(); ++i) { VideoArtworkType type = i.key(); ArtworkInfo info = i.value(); QString filename = getDownloadFilename( type, lookup, info.url ); if (lookup->GetHost().isEmpty()) { QString path = getLocalWritePath(lookup->GetType(), type); QDir dirPath(path); if (!dirPath.exists()) if (!dirPath.mkpath(path)) { LOG(VB_GENERAL, LOG_ERR, QString("Metadata Image Download: Unable to create " "path %1, aborting download.").arg(path)); QCoreApplication::postEvent(m_parent, new ImageDLFailureEvent(lookup)); continue; } QString finalfile = path + "/" + filename; QString oldurl = info.url; info.url = finalfile; if (!QFile::exists(finalfile) || lookup->GetAllowOverwrites()) { QFile dest_file(finalfile); if (dest_file.exists()) { QFileInfo fi(finalfile); GetMythUI()->RemoveFromCacheByFile(fi.fileName()); dest_file.remove(); } LOG(VB_GENERAL, LOG_INFO, QString("Metadata Image Download: %1 ->%2") .arg(oldurl).arg(finalfile)); QByteArray *download = new QByteArray(); GetMythDownloadManager()->download(oldurl, download); QImage testImage; bool didLoad = testImage.loadFromData(*download); if (!didLoad) { LOG(VB_GENERAL, LOG_ERR, QString("Tried to write %1, but it appears to be " "an HTML redirect (filesize %2).") .arg(oldurl).arg(download->size())); delete download; download = NULL; QCoreApplication::postEvent(m_parent, new ImageDLFailureEvent(lookup)); continue; } if (dest_file.open(QIODevice::WriteOnly)) { off_t size = dest_file.write(*download, download->size()); if (size != download->size()) { LOG(VB_GENERAL, LOG_ERR, QString("Image Download: Error Writing Image " "to file: %1").arg(finalfile)); QCoreApplication::postEvent(m_parent, new ImageDLFailureEvent(lookup)); } else downloaded.insert(type, info); } delete download; } else downloaded.insert(type, info); } else { QString path = getStorageGroupURL(type, lookup->GetHost()); QString finalfile = path + filename; QString oldurl = info.url; info.url = finalfile; bool exists = false; bool onMaster = false; QString resolvedFN; if ((lookup->GetHost().toLower() == gCoreContext->GetHostName().toLower()) || (gCoreContext->IsThisHost(lookup->GetHost()))) { StorageGroup sg; resolvedFN = sg.FindFile(filename); exists = QFile::exists(resolvedFN); if (!exists) { resolvedFN = getLocalStorageGroupPath(type, lookup->GetHost()) + "/" + filename; } onMaster = true; } else exists = RemoteFile::Exists(finalfile); if (!exists || lookup->GetAllowOverwrites()) { if (exists && !onMaster) { QFileInfo fi(finalfile); GetMythUI()->RemoveFromCacheByFile(fi.fileName()); RemoteFile::DeleteFile(finalfile); } else if (exists) QFile::remove(resolvedFN); LOG(VB_GENERAL, LOG_INFO, QString("Metadata Image Download: %1 -> %2") .arg(oldurl).arg(finalfile)); QByteArray *download = new QByteArray(); GetMythDownloadManager()->download(oldurl, download); QImage testImage; bool didLoad = testImage.loadFromData(*download); if (!didLoad) { LOG(VB_GENERAL, LOG_ERR, QString("Tried to write %1, but it appears to be " "an HTML redirect or corrupt file " "(filesize %2).") .arg(oldurl).arg(download->size())); delete download; download = NULL; QCoreApplication::postEvent(m_parent, new ImageDLFailureEvent(lookup)); continue; } if (!onMaster) { RemoteFile *outFile = new RemoteFile(finalfile, true); if (!outFile->isOpen()) { LOG(VB_GENERAL, LOG_ERR, QString("Image Download: Failed to open " "remote file (%1) for write. Does " "Storage Group Exist?") .arg(finalfile)); delete outFile; outFile = NULL; QCoreApplication::postEvent(m_parent, new ImageDLFailureEvent(lookup)); } else { off_t written = outFile->Write(*download, download->size()); if (written != download->size()) { LOG(VB_GENERAL, LOG_ERR, QString("Image Download: Error Writing Image " "to file: %1").arg(finalfile)); QCoreApplication::postEvent(m_parent, new ImageDLFailureEvent(lookup)); } else downloaded.insert(type, info); delete outFile; outFile = NULL; } } else { QFile dest_file(resolvedFN); if (dest_file.open(QIODevice::WriteOnly)) { off_t size = dest_file.write(*download, download->size()); if (size != download->size()) { LOG(VB_GENERAL, LOG_ERR, QString("Image Download: Error Writing Image " "to file: %1").arg(finalfile)); QCoreApplication::postEvent(m_parent, new ImageDLFailureEvent(lookup)); } else downloaded.insert(type, info); } } delete download; } else downloaded.insert(type, info); } } lookup->SetDownloads(downloaded); QCoreApplication::postEvent(m_parent, new ImageDLEvent(lookup)); } RunEpilog(); }
/** \fn ImageScanThread::run() * \brief Called when the thread is started. Loads all storage groups files * and directories and also from the database and syncronizes them. * \return void */ void ImageScanThread::run() { RunProlog(); if (!m_continue) { LOG(VB_GENERAL, LOG_DEBUG, QString("Image scanning thread not allowed to start.")); return; } LOG(VB_GENERAL, LOG_DEBUG, "Syncronisation started"); m_progressCount = 0; m_progressTotalCount = 0; // Load all available directories and files from the database so that // they can be compared against the ones on the filesystem. ImageUtils *iu = ImageUtils::getInstance(); iu->LoadDirectoriesFromDB(m_dbDirList); iu->LoadFilesFromDB(m_dbFileList); QStringList paths = iu->GetStorageDirs(); // Get the total list of directories that will be synced. // This is only an additional information that the themer can show. for (int i = 0; i < paths.size(); ++i) { QString path = paths.at(i); QDirIterator it(path, QDirIterator::Subdirectories); while(it.hasNext()) { it.next(); ++m_progressTotalCount; } } // Now start the actual syncronization for (int i = 0; i < paths.size(); ++i) { QString path = paths.at(i); QString base = path; if (!base.endsWith('/')) base.append('/'); SyncFilesFromDir(path, 0, base); } // Adding or updating directories have been completed. // The directory list still contains the remaining directories // that are not in the filesystem anymore. Remove them from the database QMap<QString, ImageMetadata *>::iterator i; for (i = m_dbDirList->begin(); i != m_dbDirList->end(); ++i) { iu->RemoveDirectoryFromDB(m_dbDirList->value(i.key())); } // Repeat the same for the file list. for (i = m_dbFileList->begin(); i != m_dbFileList->end(); ++i) { iu->RemoveFileFromDB(m_dbFileList->value(i.key())); } m_continue = false; m_progressCount = 0; m_progressTotalCount = 0; LOG(VB_GENERAL, LOG_DEBUG, "Syncronisation complete"); RunEpilog(); }
void ThumbGenerator::run() { RunProlog(); m_cancel = false; while (moreWork() && !m_cancel) { QString file, dir; bool isGallery; m_mutex.lock(); dir = m_directory; isGallery = m_isGallery; file = m_fileList.first(); if (!m_fileList.isEmpty()) m_fileList.pop_front(); m_mutex.unlock(); if (file.isEmpty()) continue; QString filePath = dir + QString("/") + file; QFileInfo fileInfo(filePath); if (!fileInfo.exists()) continue; if (isGallery) { if (fileInfo.isDir()) isGallery = checkGalleryDir(fileInfo); else isGallery = checkGalleryFile(fileInfo); } if (!isGallery) { QString cachePath = QString("%1%2.jpg").arg(getThumbcacheDir(dir)) .arg(file); QFileInfo cacheInfo(cachePath); if (cacheInfo.exists() && cacheInfo.lastModified() >= fileInfo.lastModified()) { continue; } else { // cached thumbnail not there or out of date QImage image; // Remove the old one if it exists if (cacheInfo.exists()) QFile::remove(cachePath); if (fileInfo.isDir()) loadDir(image, fileInfo); else loadFile(image, fileInfo); if (image.isNull()) continue; // give up; // if the file is a movie save the image to use as a screenshot if (GalleryUtil::IsMovie(fileInfo.filePath())) { QString screenshotPath = QString("%1%2-screenshot.jpg") .arg(getThumbcacheDir(dir)) .arg(file); image.save(screenshotPath, "JPEG", 95); } image = image.scaled(m_width,m_height, Qt::KeepAspectRatio, Qt::SmoothTransformation); image.save(cachePath, "JPEG", 95); // deep copies all over ThumbData *td = new ThumbData; td->directory = dir; td->fileName = file; td->thumb = image.copy(); // inform parent we have thumbnail ready for it QApplication::postEvent(m_parent, new ThumbGenEvent(td)); } } } RunEpilog(); }
void MetadataImageDownload::run() { RunProlog(); // Always handle thumbnails first, they're higher priority. ThumbnailData *thumb; while ((thumb = moreThumbs()) != NULL) { QString sFilename = getDownloadFilename(thumb->title, thumb->url); bool exists = QFile::exists(sFilename); if (!exists && !thumb->url.isEmpty()) { if (!GetMythDownloadManager()->download(thumb->url, sFilename)) { LOG(VB_GENERAL, LOG_ERR, QString("MetadataImageDownload: failed to download thumbnail from: %1") .arg(thumb->url)); delete thumb; continue; } } // inform parent we have thumbnail ready for it if (QFile::exists(sFilename) && m_parent) { LOG(VB_GENERAL, LOG_DEBUG, QString("Threaded Image Thumbnail Download: %1") .arg(sFilename)); thumb->url = sFilename; QCoreApplication::postEvent(m_parent, new ThumbnailDLEvent(thumb)); } else delete thumb; } while (true) { m_mutex.lock(); if (m_downloadList.isEmpty()) { // no more to process, we're done m_mutex.unlock(); break; } // Ref owns the MetadataLookup object for the duration of the loop // and it will be deleted automatically when the loop completes RefCountHandler<MetadataLookup> ref = m_downloadList.takeFirstAndDecr(); m_mutex.unlock(); MetadataLookup *lookup = ref; DownloadMap downloads = lookup->GetDownloads(); DownloadMap downloaded; bool errored = false; for (DownloadMap::iterator i = downloads.begin(); i != downloads.end(); ++i) { VideoArtworkType type = i.key(); ArtworkInfo info = i.value(); QString filename = getDownloadFilename( type, lookup, info.url ); if (lookup->GetHost().isEmpty()) { QString path = getLocalWritePath(lookup->GetType(), type); QDir dirPath(path); if (!dirPath.exists()) { if (!dirPath.mkpath(path)) { LOG(VB_GENERAL, LOG_ERR, QString("Metadata Image Download: Unable to create " "path %1, aborting download.").arg(path)); errored = true; break; } } QString finalfile = path + "/" + filename; QString oldurl = info.url; info.url = finalfile; if (!QFile::exists(finalfile) || lookup->GetAllowOverwrites()) { QFile dest_file(finalfile); if (dest_file.exists()) { QFileInfo fi(finalfile); GetMythUI()->RemoveFromCacheByFile(fi.fileName()); dest_file.remove(); } LOG(VB_GENERAL, LOG_INFO, QString("Metadata Image Download: %1 ->%2") .arg(oldurl).arg(finalfile)); QByteArray download; GetMythDownloadManager()->download(oldurl, &download); QImage testImage; bool didLoad = testImage.loadFromData(download); if (!didLoad) { LOG(VB_GENERAL, LOG_ERR, QString("Tried to write %1, but it appears to be " "an HTML redirect (filesize %2).") .arg(oldurl).arg(download.size())); errored = true; break; } if (dest_file.open(QIODevice::WriteOnly)) { off_t size = dest_file.write(download, download.size()); dest_file.close(); if (size != download.size()) { // File creation failed for some reason, delete it RemoteFile::DeleteFile(finalfile); LOG(VB_GENERAL, LOG_ERR, QString("Image Download: Error Writing Image " "to file: %1").arg(finalfile)); errored = true; break; } } } } else { QString path = getStorageGroupURL(type, lookup->GetHost()); QString finalfile = path + filename; QString oldurl = info.url; info.url = finalfile; bool exists = false; bool onMaster = false; QString resolvedFN; if (gCoreContext->IsMasterBackend() && gCoreContext->IsThisHost(lookup->GetHost())) { StorageGroup sg(getStorageGroupName(type), lookup->GetHost()); resolvedFN = sg.FindFile(filename); exists = !resolvedFN.isEmpty() && QFile::exists(resolvedFN); if (!exists) { resolvedFN = getLocalStorageGroupPath(type, lookup->GetHost()) + "/" + filename; } onMaster = true; } else exists = RemoteFile::Exists(finalfile); if (!exists || lookup->GetAllowOverwrites()) { if (exists && !onMaster) { QFileInfo fi(finalfile); GetMythUI()->RemoveFromCacheByFile(fi.fileName()); RemoteFile::DeleteFile(finalfile); } else if (exists) QFile::remove(resolvedFN); LOG(VB_GENERAL, LOG_INFO, QString("Metadata Image Download: %1 -> %2") .arg(oldurl).arg(finalfile)); QByteArray download; GetMythDownloadManager()->download(oldurl, &download); QImage testImage; bool didLoad = testImage.loadFromData(download); if (!didLoad) { LOG(VB_GENERAL, LOG_ERR, QString("Tried to write %1, but it appears to be " "an HTML redirect or corrupt file " "(filesize %2).") .arg(oldurl).arg(download.size())); errored = true; break; } if (!onMaster) { RemoteFile outFile(finalfile, true); if (!outFile.isOpen()) { LOG(VB_GENERAL, LOG_ERR, QString("Image Download: Failed to open " "remote file (%1) for write. Does " "Storage Group Exist?") .arg(finalfile)); errored = true; break; } off_t written = outFile.Write(download, download.size()); if (written != download.size()) { // File creation failed for some reason, delete it RemoteFile::DeleteFile(finalfile); LOG(VB_GENERAL, LOG_ERR, QString("Image Download: Error Writing Image " "to file: %1").arg(finalfile)); errored = true; break; } } else { QFile dest_file(resolvedFN); if (dest_file.open(QIODevice::WriteOnly)) { off_t size = dest_file.write(download, download.size()); dest_file.close(); if (size != download.size()) { // File creation failed for some reason, delete it RemoteFile::DeleteFile(resolvedFN); LOG(VB_GENERAL, LOG_ERR, QString("Image Download: Error Writing Image " "to file: %1").arg(finalfile)); errored = true; break; } } } } } if (!errored) { // update future Artwork Map with what we've successfully // retrieved (either downloaded or already existing downloaded.insert(type, info); } } if (errored) { QCoreApplication::postEvent(m_parent, new ImageDLFailureEvent(lookup)); errored = false; } lookup->SetDownloads(downloaded); QCoreApplication::postEvent(m_parent, new ImageDLEvent(lookup)); } RunEpilog(); }
/// \brief Runs ThreadedFileWriter::DiskLoop(void) void TFWWriteThread::run(void) { RunProlog(); m_parent->DiskLoop(); RunEpilog(); }
void FileScannerThread::run() { RunProlog(); m_parent->doScan(); RunEpilog(); }
/// \brief Runs ThreadedFileWriter::SyncLoop(void) void TFWSyncThread::run(void) { RunProlog(); m_parent->SyncLoop(); RunEpilog(); }