DTC::LiveStreamInfo *Content::AddRecordingLiveStream( int nChanId, const QDateTime &dtStartTime, int nMaxSegments, int nWidth, int nHeight, int nBitrate, int nAudioBitrate, int nSampleRate ) { if (!dtStartTime.isValid()) throw( "StartTime is invalid" ); // ------------------------------------------------------------------ // Read Recording From Database // ------------------------------------------------------------------ ProgramInfo pginfo( (uint)nChanId, dtStartTime ); if (!pginfo.GetChanID()) { LOG( VB_UPNP, LOG_ERR, QString("AddRecordingLiveStream - for %1, %2 failed") .arg( nChanId ) .arg( dtStartTime.toString() )); return NULL; } if ( pginfo.GetHostname().toLower() != gCoreContext->GetHostName().toLower()) { // We only handle requests for local resources QString sMsg = QString("GetRecording: Wrong Host '%1' request from '%2'.") .arg( gCoreContext->GetHostName()) .arg( pginfo.GetHostname() ); LOG(VB_UPNP, LOG_ERR, sMsg); throw HttpRedirectException( pginfo.GetHostname() ); } QString sFileName( GetPlaybackURL(&pginfo) ); // ---------------------------------------------------------------------- // check to see if the file exists // ---------------------------------------------------------------------- if (!QFile::exists( sFileName )) { LOG( VB_UPNP, LOG_ERR, QString("AddRecordingLiveStream - for %1, %2 failed") .arg( nChanId ) .arg( dtStartTime.toString() )); return NULL; } QFileInfo fInfo( sFileName ); return AddLiveStream( pginfo.GetStorageGroup(), fInfo.fileName(), pginfo.GetHostname(), nMaxSegments, nWidth, nHeight, nBitrate, nAudioBitrate, nSampleRate ); }
QFileInfo Content::GetRecording( int nChanId, const QDateTime &recstarttsRaw ) { if (!recstarttsRaw.isValid()) throw( "StartTime is invalid" ); // ------------------------------------------------------------------ // Read Recording From Database // ------------------------------------------------------------------ QDateTime recstartts = recstarttsRaw.toUTC(); ProgramInfo pginfo((uint)nChanId, recstartts); if (!pginfo.GetChanID()) { LOG(VB_UPNP, LOG_ERR, QString("GetRecording - for '%1' failed") .arg(ProgramInfo::MakeUniqueKey(nChanId, recstartts))); return QFileInfo(); } if (pginfo.GetHostname().toLower() != gCoreContext->GetHostName().toLower()) { // We only handle requests for local resources QString sMsg = QString("GetRecording: Wrong Host '%1' request from '%2'.") .arg( gCoreContext->GetHostName()) .arg( pginfo.GetHostname() ); LOG(VB_UPNP, LOG_ERR, sMsg); throw HttpRedirectException( pginfo.GetHostname() ); } QString sFileName( GetPlaybackURL(&pginfo) ); // ---------------------------------------------------------------------- // check to see if the file exists // ---------------------------------------------------------------------- if (QFile::exists( sFileName )) return QFileInfo( sFileName ); return QFileInfo(); }
QString FileServerHandler::LocalFilePath(const QUrl &url, const QString &wantgroup) { QString lpath = url.path(); if (lpath.section('/', -2, -2) == "channels") { // This must be an icon request. Check channel.icon to be safe. QString querytext; QString file = lpath.section('/', -1); lpath = ""; MSqlQuery query(MSqlQuery::InitCon()); query.prepare("SELECT icon FROM channel WHERE icon LIKE :FILENAME ;"); query.bindValue(":FILENAME", QString("%/") + file); if (query.exec() && query.next()) { lpath = query.value(0).toString(); } else { MythDB::DBError("Icon path", query); } } else { lpath = lpath.section('/', -1); QString fpath = lpath; if (fpath.right(4) == ".png") fpath = fpath.left(fpath.length() - 4); ProgramInfo pginfo(fpath); if (pginfo.GetChanID()) { QString pburl = GetPlaybackURL(&pginfo); if (pburl.left(1) == "/") { lpath = pburl.section('/', 0, -2) + "/" + lpath; LOG(VB_FILE, LOG_INFO, QString("Local file path: %1").arg(lpath)); } else { LOG(VB_GENERAL, LOG_ERR, QString("LocalFilePath unable to find local " "path for '%1', found '%2' instead.") .arg(lpath).arg(pburl)); lpath = ""; } } else if (!lpath.isEmpty()) { // For securities sake, make sure filename is really the pathless. QString opath = lpath; StorageGroup sgroup; if (!wantgroup.isEmpty()) { sgroup.Init(wantgroup); lpath = url.toString(); } else { lpath = QFileInfo(lpath).fileName(); } QString tmpFile = sgroup.FindFile(lpath); if (!tmpFile.isEmpty()) { lpath = tmpFile; LOG(VB_FILE, LOG_INFO, QString("LocalFilePath(%1 '%2'), found through " "exhaustive search at '%3'") .arg(url.toString()).arg(opath).arg(lpath)); } else { LOG(VB_GENERAL, LOG_ERR, QString("LocalFilePath unable to " "find local path for '%1'.") .arg(opath)); lpath = ""; } } else { lpath = ""; } } return lpath; }
QFileInfo Content::GetPreviewImage( int nChanId, const QDateTime &recstarttsRaw, int nWidth, int nHeight, int nSecsIn ) { if (!recstarttsRaw.isValid()) { QString sMsg = QString("GetPreviewImage: bad start time '%1'") .arg(MythDate::toString(recstarttsRaw, MythDate::ISODate)); LOG(VB_GENERAL, LOG_ERR, sMsg); throw sMsg; } QDateTime recstartts = recstarttsRaw.toUTC(); // ---------------------------------------------------------------------- // Read Recording From Database // ---------------------------------------------------------------------- ProgramInfo pginfo( (uint)nChanId, recstartts); if (!pginfo.GetChanID()) { LOG(VB_GENERAL, LOG_ERR, QString("GetPreviewImage: No recording for '%1'") .arg(ProgramInfo::MakeUniqueKey(nChanId, recstartts))); return QFileInfo(); } if (pginfo.GetHostname().toLower() != gCoreContext->GetHostName().toLower()) { QString sMsg = QString("GetPreviewImage: Wrong Host '%1' request from '%2'") .arg( gCoreContext->GetHostName()) .arg( pginfo.GetHostname() ); LOG(VB_UPNP, LOG_ERR, sMsg); throw HttpRedirectException( pginfo.GetHostname() ); } QString sFileName = GetPlaybackURL(&pginfo); // ---------------------------------------------------------------------- // check to see if default preview image is already created. // ---------------------------------------------------------------------- QString sPreviewFileName; if (nSecsIn <= 0) { nSecsIn = -1; sPreviewFileName = sFileName + ".png"; } else { sPreviewFileName = QString("%1.%2.png").arg(sFileName).arg(nSecsIn); } if (!QFile::exists( sPreviewFileName )) { // ------------------------------------------------------------------ // Must generate Preview Image, Generate Image and save. // ------------------------------------------------------------------ if (!pginfo.IsLocal() && sFileName.startsWith("/")) pginfo.SetPathname(sFileName); if (!pginfo.IsLocal()) return QFileInfo(); PreviewGenerator *previewgen = new PreviewGenerator( &pginfo, QString(), PreviewGenerator::kLocal); previewgen->SetPreviewTimeAsSeconds( nSecsIn ); previewgen->SetOutputFilename ( sPreviewFileName ); bool ok = previewgen->Run(); previewgen->deleteLater(); if (!ok) return QFileInfo(); } float fAspect = 0.0; QImage *pImage = new QImage(sPreviewFileName); if (!pImage) return QFileInfo(); if (fAspect <= 0) fAspect = (float)(pImage->width()) / pImage->height(); if (fAspect == 0) { delete pImage; return QFileInfo(); } bool bDefaultPixmap = (nWidth == 0) && (nHeight == 0); if ( nWidth == 0 ) nWidth = (int)rint(nHeight * fAspect); if ( nHeight == 0 ) nHeight = (int)rint(nWidth / fAspect); QString sNewFileName; if (bDefaultPixmap) sNewFileName = sPreviewFileName; else sNewFileName = QString( "%1.%2.%3x%4.png" ) .arg( sFileName ) .arg( nSecsIn ) .arg( nWidth ) .arg( nHeight ); // ---------------------------------------------------------------------- // check to see if scaled preview image is already created. // ---------------------------------------------------------------------- if (QFile::exists( sNewFileName )) { delete pImage; return QFileInfo( sNewFileName ); } PreviewGenerator *previewgen = new PreviewGenerator( &pginfo, QString(), PreviewGenerator::kLocal); previewgen->SetPreviewTimeAsSeconds( nSecsIn ); previewgen->SetOutputFilename ( sNewFileName ); previewgen->SetOutputSize (QSize(nWidth,nHeight)); bool ok = previewgen->Run(); previewgen->deleteLater(); if (!ok) return QFileInfo(); delete pImage; return QFileInfo( sNewFileName ); }
/** \fn MythSystemEventHandler::SubstituteMatches(const QStringList &tokens, QString &command) * \brief Substitutes %MATCH% variables in given command line. * \sa ProgramInfo::SubstituteMatches(QString &str) * * Subsitutes values for %MATCH% type variables in given command string. * Some of these matches come from the tokens list passed in and some * may come from a ProgramInfo if a chanid and starttime are specified * in the tokens list. * * \param tokens Const QStringList containing token list passed with event. * \param command Command line containing %MATCH% variables to be substituted. */ void MythSystemEventHandler::SubstituteMatches(const QStringList &tokens, QString &command) { if (command.isEmpty()) return; LOG(VB_FILE, LOG_DEBUG, LOC + QString("SubstituteMatches: BEFORE: %1") .arg(command)); QString args; uint chanid = 0; QDateTime recstartts; QString sender; QStringList::const_iterator it = tokens.begin(); ++it; command.replace(QString("%EVENTNAME%"), *it); ++it; while (it != tokens.end()) { if (!args.isEmpty()) args += " "; args += *it; // Check for some token names that we substitute one for one as // %MATCH% type variables. if ((*it == "CARDID") || (*it == "COMMAND") || (*it == "RECSTATUS") || (*it == "HOSTNAME") || (*it == "SECS") || (*it == "SENDER") || (*it == "PATH")) { QString token = *it; if (++it == tokens.end()) break; if (token == "SENDER") sender = *it; // The following string is broken up on purpose to indicate // what we're replacing is the token surrounded by percent signs command.replace(QString("%" "%1" "%").arg(token), *it); if (!args.isEmpty()) args += " "; args += *it; } // Remember any chanid and starttime so we can lookup info about // the recording from the database. if (*it == "CHANID") { if (++it == tokens.end()) break; chanid = (*it).toUInt(); if (!args.isEmpty()) args += " "; args += *it; } if (*it == "STARTTIME") { if (++it == tokens.end()) break; recstartts = MythDate::fromString(*it); if (!args.isEmpty()) args += " "; args += *it; } ++it; } command.replace(QString("%ARGS%"), args); ProgramInfo pginfo(chanid, recstartts); bool pginfo_loaded = pginfo.GetChanID(); if (!pginfo_loaded) { RecordingInfo::LoadStatus status; pginfo = RecordingInfo(chanid, recstartts, false, 0, &status); pginfo_loaded = RecordingInfo::kFoundProgram == status; } if (pginfo_loaded) { pginfo.SubstituteMatches(command); } else { command.replace(QString("%CHANID%"), QString::number(chanid)); command.replace(QString("%STARTTIME%"), MythDate::toString(recstartts, MythDate::kFilename)); command.replace(QString("%STARTTIMEISO%"), recstartts.toString(Qt::ISODate)); } command.replace(QString("%VERBOSELEVEL%"), QString("%1").arg(verboseMask)); LOG(VB_FILE, LOG_DEBUG, LOC + QString("SubstituteMatches: AFTER : %1") .arg(command)); }
uint32_t *arm_dataabort(uint32_t *regs, uint32_t dfar, uint32_t dfsr) { struct tcb_s *tcb = this_task(); uint32_t *savestate; /* Save the saved processor context in CURRENT_REGS where it can be accessed * for register dumps and possibly context switching. */ savestate = (uint32_t *)CURRENT_REGS; CURRENT_REGS = regs; /* In the NuttX on-demand paging implementation, only the read-only, .text * section is paged. However, the ARM compiler generated PC-relative data * fetches from within the .text sections. Also, it is customary to locate * read-only data (.rodata) within the same section as .text so that it * does not require copying to RAM. Misses in either of these case should * cause a data abort. * * We are only interested in data aborts due to page translations faults. * Sections should already be in place and permissions should already be * be set correctly (to read-only) so any other data abort reason is a * fatal error. */ pginfo("DFSR: %08x DFAR: %08x\n", dfsr, dfar); if ((dfsr & FSR_MASK) != FSR_PAGE) { goto segfault; } /* Check the (virtual) address of data that caused the data abort. When * the exception occurred, this address was provided in the DFAR register. * (It has not yet been saved in the register context save area). */ pginfo("VBASE: %08x VEND: %08x\n", PG_PAGED_VBASE, PG_PAGED_VEND); if (dfar < PG_PAGED_VBASE || dfar >= PG_PAGED_VEND) { goto segfault; } /* Save the offending data address as the fault address in the TCB of * the currently task. This fault address is also used by the prefetch * abort handling; this will allow common paging logic for both * prefetch and data aborts. */ tcb->xcp.dfar = regs[REG_R15]; /* Call pg_miss() to schedule the page fill. A consequences of this * call are: * * (1) The currently executing task will be blocked and saved on * on the g_waitingforfill task list. * (2) An interrupt-level context switch will occur so that when * this function returns, it will return to a different task, * most likely the page fill worker thread. * (3) The page fill worker task has been signalled and should * execute immediately when we return from this exception. */ pg_miss(); /* Restore the previous value of CURRENT_REGS. NULL would indicate that * we are no longer in an interrupt handler. It will be non-NULL if we * are returning from a nested interrupt. */ CURRENT_REGS = savestate; return regs; segfault: _alert("Data abort. PC: %08x DFAR: %08x DFSR: %08x\n", regs[REG_PC], dfar, dfsr); PANIC(); return regs; /* To keep the compiler happy */ }
void ScheduleCommon::customEvent(QEvent *event) { if (event->type() == DialogCompletionEvent::kEventType) { DialogCompletionEvent *dce = (DialogCompletionEvent*)(event); QString resultid = dce->GetId(); QString resulttext = dce->GetResultText(); if (resultid == "schedulenotscheduled") { if (!qVariantCanConvert<RecordingInfo>(dce->GetData())) return; RecordingInfo recInfo = qVariantValue<RecordingInfo> (dce->GetData()); if (resulttext == tr("Record only this showing")) recInfo.ApplyRecordStateChange(kSingleRecord); else if (resulttext == tr("Record all showings")) recInfo.ApplyRecordStateChange(kAllRecord); else if (resulttext == tr("Record one showing of this episode")) { recInfo.ApplyRecordStateChange(kOneRecord, false); recInfo.GetRecordingRule()->m_filter |= 64; // This episode recInfo.GetRecordingRule()->Save(); } else if (resulttext == tr("Record all showings on this channel")) { recInfo.ApplyRecordStateChange(kAllRecord, false); recInfo.GetRecordingRule()->m_filter |= 1024; // This channel recInfo.GetRecordingRule()->Save(); } else if (resulttext == tr("Record with more options")) { EditScheduled(&recInfo); } } else if (resultid == "schedulenotrecording") { if (!qVariantCanConvert<RecordingInfo>(dce->GetData())) return; RecordingInfo recInfo = qVariantValue<RecordingInfo> (dce->GetData()); if (resulttext == tr("Restart recording this showing")) recInfo.ReactivateRecording(); else if (resulttext == tr("Record this showing anyway")) { recInfo.ApplyRecordStateChange(kOverrideRecord); if (recInfo.GetRecordingStartTime() < MythDate::current()) recInfo.ReactivateRecording(); } else if (resulttext == tr("Forget previous recording")) recInfo.ForgetHistory(); else if (resulttext == tr("Don't record this showing")) recInfo.ApplyRecordStateChange(kDontRecord); else if (resulttext == tr("Never record this episode")) { recInfo.SetRecordingStatus(rsNeverRecord); recInfo.SetScheduledStartTime(MythDate::current()); recInfo.SetScheduledEndTime(recInfo.GetRecordingStartTime()); recInfo.AddHistory(true, true); } else if (resulttext == tr("Delete override rule") || resulttext == tr("Delete recording rule")) recInfo.ApplyRecordStateChange(kNotRecording); else if (resulttext == tr("Edit override options") || resulttext == tr("Edit recording options")) { EditScheduled(&recInfo); } else if (resulttext == tr("Override this showing with options")) { MakeOverride(&recInfo); } } else if (resultid == "schedulerecording") { if (!qVariantCanConvert<RecordingInfo>(dce->GetData())) return; RecordingInfo recInfo = qVariantValue<RecordingInfo> (dce->GetData()); if (resulttext == tr("Restart recording this showing")) recInfo.ReactivateRecording(); else if (resulttext == tr("Stop recording this showing")) { ProgramInfo pginfo( recInfo.GetChanID(), recInfo.GetRecordingStartTime()); if (pginfo.GetChanID()) RemoteStopRecording(&pginfo); } else if (resulttext == tr("Don't record this showing")) recInfo.ApplyRecordStateChange(kDontRecord); else if (resulttext == tr("Never record this episode")) { recInfo.SetRecordingStatus(rsNeverRecord); recInfo.SetScheduledStartTime(MythDate::current()); recInfo.SetScheduledEndTime(recInfo.GetRecordingStartTime()); recInfo.AddHistory(true, true); } else if (resulttext == tr("Delete override rule") || resulttext == tr("Delete recording rule")) recInfo.ApplyRecordStateChange(kNotRecording); else if (resulttext == tr("Edit options for this showing")) { if (recInfo.GetRecordingRuleType() == kSingleRecord || recInfo.GetRecordingRuleType() == kOverrideRecord || recInfo.GetRecordingRuleType() == kOneRecord) EditScheduled(&recInfo); else MakeOverride(&recInfo, true); } else if (resulttext == tr("Edit override options") || resulttext == tr("Edit recording options")) { EditScheduled(&recInfo); } else if (resulttext == tr("Override this showing with options")) { MakeOverride(&recInfo); } } } }
void up_prefetchabort(uint32_t *regs) { #ifdef CONFIG_PAGING uint32_t *savestate; /* Save the saved processor context in CURRENT_REGS where it can be accessed * for register dumps and possibly context switching. */ savestate = (uint32_t *)CURRENT_REGS; #endif CURRENT_REGS = regs; #ifdef CONFIG_PAGING /* Get the (virtual) address of instruction that caused the prefetch abort. * When the exception occurred, this address was provided in the lr register * and this value was saved in the context save area as the PC at the * REG_R15 index. * * Check to see if this miss address is within the configured range of * virtual addresses. */ pginfo("VADDR: %08x VBASE: %08x VEND: %08x\n", regs[REG_PC], PG_PAGED_VBASE, PG_PAGED_VEND); if (regs[REG_R15] >= PG_PAGED_VBASE && regs[REG_R15] < PG_PAGED_VEND) { /* Save the offending PC as the fault address in the TCB of the currently * executing task. This value is, of course, already known in regs[REG_R15], * but saving it in this location will allow common paging logic for both * prefetch and data aborts. */ struct tcb_s *tcb = this_task(); tcb->xcp.far = regs[REG_R15]; /* Call pg_miss() to schedule the page fill. A consequences of this * call are: * * (1) The currently executing task will be blocked and saved on * on the g_waitingforfill task list. * (2) An interrupt-level context switch will occur so that when * this function returns, it will return to a different task, * most likely the page fill worker thread. * (3) The page fill worker task has been signalled and should * execute immediately when we return from this exception. */ pg_miss(); /* Restore the previous value of CURRENT_REGS. NULL would indicate that * we are no longer in an interrupt handler. It will be non-NULL if we * are returning from a nested interrupt. */ CURRENT_REGS = savestate; } else #endif { _alert("Prefetch abort. PC: %08x\n", regs[REG_PC]); PANIC(); } }
void ScheduleCommon::customEvent(QEvent *event) { if (event->type() == DialogCompletionEvent::kEventType) { DialogCompletionEvent *dce = (DialogCompletionEvent*)(event); QString resultid = dce->GetId(); QString resulttext = dce->GetResultText(); if (resultid == "schedulenotrecording") { if (!qVariantCanConvert<RecordingInfo>(dce->GetData())) return; RecordingInfo recInfo = qVariantValue<RecordingInfo> (dce->GetData()); if (resulttext == tr("Reactivate")) recInfo.ReactivateRecording(); else if (resulttext == tr("Record anyway")) { recInfo.ApplyRecordStateChange(kOverrideRecord); if (recInfo.GetRecordingStartTime() < QDateTime::currentDateTime()) recInfo.ReactivateRecording(); } else if (resulttext == tr("Forget Previous")) recInfo.ForgetHistory(); else if (resulttext == tr("Don't record")) recInfo.ApplyRecordStateChange(kDontRecord); else if (resulttext == tr("Never record")) { recInfo.SetRecordingStatus(rsNeverRecord); recInfo.SetScheduledStartTime(QDateTime::currentDateTime()); recInfo.SetScheduledEndTime(recInfo.GetRecordingStartTime()); recInfo.AddHistory(true, true); } else if (resulttext == tr("Clear Override")) recInfo.ApplyRecordStateChange(kNotRecording); else if (resulttext == tr("Edit Override") || resulttext == tr("Edit Options")) { EditScheduled(&recInfo); } else if (resulttext == tr("Add Override")) { MakeOverride(&recInfo); } } else if (resultid == "schedulerecording") { if (!qVariantCanConvert<RecordingInfo>(dce->GetData())) return; RecordingInfo recInfo = qVariantValue<RecordingInfo> (dce->GetData()); if (resulttext == tr("Reactivate")) recInfo.ReactivateRecording(); else if (resulttext == tr("Stop recording")) { ProgramInfo pginfo( recInfo.GetChanID(), recInfo.GetRecordingStartTime()); if (pginfo.GetChanID()) RemoteStopRecording(&pginfo); } else if (resulttext == tr("Don't record")) recInfo.ApplyRecordStateChange(kDontRecord); else if (resulttext == tr("Never record")) { recInfo.SetRecordingStatus(rsNeverRecord); recInfo.SetScheduledStartTime(QDateTime::currentDateTime()); recInfo.SetScheduledEndTime(recInfo.GetRecordingStartTime()); recInfo.AddHistory(true, true); } else if (resulttext == tr("Clear Override")) recInfo.ApplyRecordStateChange(kNotRecording); else if (resulttext == tr("Modify Recording Options")) { if (recInfo.GetRecordingRuleType() == kSingleRecord || recInfo.GetRecordingRuleType() == kOverrideRecord || recInfo.GetRecordingRuleType() == kFindOneRecord) EditScheduled(&recInfo); else MakeOverride(&recInfo, true); } else if (resulttext == tr("Edit Override") || resulttext == tr("Edit Options")) { EditScheduled(&recInfo); } else if (resulttext == tr("Add Override")) { MakeOverride(&recInfo); } } } }