bool SqlLexer::ExpectNextToken(TokenType::Type typ, const char* expected) { OdbcExpected<bool> hasNext = Shift(); if (!hasNext.IsOk() || !*hasNext) return false; const SqlToken& token = GetCurrentToken(); return token.GetType() == typ && token.ToLower() == expected; }
bool UPnpCDSVideo::LoadVideos(const UPnpCDSRequest* pRequest, UPnpCDSExtensionResults* pResults, IDTokenMap tokens) { QString sId = pRequest->m_sParentId; if (GetCurrentToken(pRequest->m_sParentId).first != "video") sId.append("/Video"); sId.append("=%1"); uint16_t nCount = pRequest->m_nRequestedCount; uint16_t nOffset = pRequest->m_nStartingIndex; // We must use a dedicated connection to get an acccurate value from // FOUND_ROWS() MSqlQuery query(MSqlQuery::InitCon(MSqlQuery::kDedicatedConnection)); QString sql = "SELECT SQL_CALC_FOUND_ROWS " "v.intid, title, subtitle, filename, director, plot, " "rating, year, userrating, length, " "season, episode, coverfile, insertdate, host, " "g.genre, studio, collectionref, contenttype " "FROM videometadata v " "LEFT JOIN videogenre g ON g.intid=v.category " "%1 " // "ORDER BY title, season, episode " "LIMIT :OFFSET,:COUNT "; QStringList clauses; QString whereString = BuildWhereClause(clauses, tokens); query.prepare(sql.arg(whereString)); BindValues(query, tokens); query.bindValue(":OFFSET", nOffset); query.bindValue(":COUNT", nCount); if (!query.exec()) return false; while (query.next()) { int nVidID = query.value( 0).toInt(); QString sTitle = query.value( 1).toString(); QString sSubtitle = query.value( 2).toString(); QString sFilePath = query.value( 3).toString(); QString sDirector = query.value( 4).toString(); QString sPlot = query.value( 5).toString(); // QString sRating = query.value( 6).toString(); int nYear = query.value( 7).toInt(); // int nUserRating = query.value( 8).toInt(); uint32_t nLength = query.value( 9).toUInt(); // Convert from minutes to milliseconds nLength = (nLength * 60 *1000); int nSeason = query.value(10).toInt(); int nEpisode = query.value(11).toInt(); QString sCoverArt = query.value(12).toString(); QDateTime dtInsertDate = MythDate::as_utc(query.value(13).toDateTime()); QString sHostName = query.value(14).toString(); QString sGenre = query.value(15).toString(); // QString sStudio = query.value(16).toString(); // QString sCollectionRef = query.value(17).toString(); QString sContentType = query.value(18).toString(); // ---------------------------------------------------------------------- // Cache Host ip Address & Port // ---------------------------------------------------------------------- // If the host-name is empty then we assume it is our local host // otherwise, we look up the host's IP address and port. When the // client then trys to play the video it will be directed to the // host which actually has the content. if (!m_mapBackendIp.contains( sHostName )) { if (sHostName.isEmpty()) { m_mapBackendIp[sHostName] = gCoreContext->GetBackendServerIP4(); } else { m_mapBackendIp[sHostName] = gCoreContext->GetBackendServerIP4(sHostName); } } if (!m_mapBackendPort.contains( sHostName )) { if (sHostName.isEmpty()) { m_mapBackendPort[sHostName] = gCoreContext->GetBackendStatusPort(); } else { m_mapBackendPort[sHostName] = gCoreContext->GetBackendStatusPort(sHostName); } } // ---------------------------------------------------------------------- // Build Support Strings // ---------------------------------------------------------------------- QString sName = sTitle; if( !sSubtitle.isEmpty() ) { sName += " - " + sSubtitle; } QUrl URIBase; URIBase.setScheme("http"); URIBase.setHost(m_mapBackendIp[sHostName]); URIBase.setPort(m_mapBackendPort[sHostName]); CDSObject *pItem; if (sContentType == "MOVIE") { pItem = CDSObject::CreateMovie( sId.arg(nVidID), sTitle, pRequest->m_sParentId ); } else { pItem = CDSObject::CreateVideoItem( sId.arg(nVidID), sName, pRequest->m_sParentId ); } if (!sSubtitle.isEmpty()) pItem->SetPropValue( "description", sSubtitle ); else pItem->SetPropValue( "description", sPlot.left(128).append(" ...")); pItem->SetPropValue( "longDescription", sPlot ); pItem->SetPropValue( "director" , sDirector ); if (nEpisode > 0 || nSeason > 0) // There has got to be a better way { pItem->SetPropValue( "seriesTitle" , sTitle ); pItem->SetPropValue( "programTitle" , sSubtitle ); pItem->SetPropValue( "episodeNumber" , QString::number(nEpisode)); //pItem->SetPropValue( "episodeCount" , nEpisodeCount); } pItem->SetPropValue( "genre" , sGenre ); if (nYear > 1830 && nYear < 9999) pItem->SetPropValue( "date", QDate(nYear,1,1).toString(Qt::ISODate)); else pItem->SetPropValue( "date", UPnPDateTime::DateTimeFormat(dtInsertDate) ); // HACK: Windows Media Centre Compat (Not a UPnP or DLNA requirement, should only be done for WMC) // pItem->SetPropValue( "genre" , "[Unknown Genre]" ); // pItem->SetPropValue( "actor" , "[Unknown Author]" ); // pItem->SetPropValue( "creator" , "[Unknown Creator]" ); // pItem->SetPropValue( "album" , "[Unknown Album]" ); //// //pItem->SetPropValue( "producer" , ); //pItem->SetPropValue( "rating" , ); //pItem->SetPropValue( "actor" , ); //pItem->SetPropValue( "publisher" , ); //pItem->SetPropValue( "language" , ); //pItem->SetPropValue( "relation" , ); //pItem->SetPropValue( "region" , ); // Only add the reference ID for items which are not in the // 'All Videos' container QString sRefIDBase = QString("%1/Video").arg(m_sExtensionId); if ( pRequest->m_sParentId != sRefIDBase ) { QString sRefId = QString( "%1=%2") .arg( sRefIDBase ) .arg( nVidID ); pItem->SetPropValue( "refID", sRefId ); } // FIXME - If the slave or storage hosting this video is offline we // won't find it. We probably shouldn't list it, but better // still would be storing the filesize in the database so we // don't waste time re-checking it constantly QString sFullFileName = sFilePath; if (!QFile::exists( sFullFileName )) { StorageGroup sgroup("Videos"); sFullFileName = sgroup.FindFile( sFullFileName ); } QFileInfo fInfo( sFullFileName ); // ---------------------------------------------------------------------- // Add Video Resource Element based on File extension (HTTP) // ---------------------------------------------------------------------- QString sMimeType = HTTPRequest::GetMimeType( QFileInfo(sFilePath).suffix() ); // HACK: If we are dealing with a Sony Blu-ray player then we fake the // MIME type to force the video to appear // if ( pRequest->m_eClient == CDS_ClientSonyDB ) // { // sMimeType = "video/avi"; // } QUrl resURI = URIBase; resURI.setPath("Content/GetVideo"); resURI.addQueryItem("Id", QString::number(nVidID)); QString sProtocol = DLNA::ProtocolInfoString(UPNPProtocol::kHTTP, sMimeType); Resource *pRes = pItem->AddResource( sProtocol, resURI.toEncoded() ); pRes->AddAttribute( "size" , QString("%1").arg(fInfo.size()) ); pRes->AddAttribute( "duration", UPnPDateTime::resDurationFormat(nLength) ); // ---------------------------------------------------------------------- // Add Artwork // ---------------------------------------------------------------------- if (!sCoverArt.isEmpty() && (sCoverArt != "No Cover")) { PopulateArtworkURIS(pItem, nVidID, URIBase); } pResults->Add( pItem ); pItem->DecrRef(); } // Just in case FOUND_ROWS() should fail, ensure m_nTotalMatches contains // at least the size of this result set if (query.size() >= 0) pResults->m_nTotalMatches = query.size(); // Fetch the total number of matches ignoring any LIMITs query.prepare("SELECT FOUND_ROWS()"); if (query.exec() && query.next()) pResults->m_nTotalMatches = query.value(0).toUInt(); return true; }