UPnpCDSExtensionResults *UPnpCDSExtension::ProcessAll ( UPnpCDSRequest *pRequest, UPnpCDSExtensionResults *pResults, QStringList &/*idPath*/ ) { pResults->m_nTotalMatches = 0; pResults->m_nUpdateID = 1; // ---------------------------------------------------------------------- // // ---------------------------------------------------------------------- switch( pRequest->m_eBrowseFlag ) { case CDS_BrowseMetadata: { // -------------------------------------------------------------- // Return Container Object Only // -------------------------------------------------------------- UPnpCDSRootInfo *pInfo = GetRootInfo( 0 ); if (pInfo != NULL) { pResults->m_nTotalMatches = 1; pResults->m_nUpdateID = 1; CDSObject *pItem = CreateContainer( pRequest->m_sObjectId, QObject::tr( pInfo->title ), m_sExtensionId ); pItem->SetChildCount( GetDistinctCount( pInfo ) ); pResults->Add( pItem ); } break; } case CDS_BrowseDirectChildren: { CreateItems( pRequest, pResults, 0, "", false ); break; } case CDS_BrowseUnknown: default: break; } return pResults; }
UPnpCDSExtensionResults *UPnpCDSExtension::ProcessKey( UPnpCDSRequest *pRequest, UPnpCDSExtensionResults *pResults, QStringList &idPath ) { pResults->m_nTotalMatches = 0; pResults->m_nUpdateID = 1; // ---------------------------------------------------------------------- // // ---------------------------------------------------------------------- QString sKey = idPath.last().section( '=', 1, 1 ); QUrl::decode( sKey ); if (sKey.length() > 0) { int nNodeIdx = idPath[ idPath.count() - 2 ].toInt(); switch( pRequest->m_eBrowseFlag ) { case CDS_BrowseMetadata: { UPnpCDSRootInfo *pInfo = GetRootInfo( nNodeIdx ); if (pInfo == NULL) return pResults; pRequest->m_sParentId = RemoveToken( "/", pRequest->m_sObjectId, 1 ); // -------------------------------------------------------------- // Since Key is not always the title, we need to lookup title. // -------------------------------------------------------------- MSqlQuery query(MSqlQuery::InitCon()); if (query.isConnected()) { QString sSQL = QString( pInfo->sql ) .arg( pInfo->where ); // -=>TODO: There is a problem when called for an Item, instead of a container // sKey = '<KeyName>/item?ChanId' which is incorrect. query.prepare ( sSQL ); query.bindValue( ":KEY", sKey ); query.exec(); if (query.isActive() && query.size() > 0) { if ( query.next() ) { // ---------------------------------------------- // Return Container Object Only // ---------------------------------------------- pResults->m_nTotalMatches = 1; pResults->m_nUpdateID = 1; CDSObject *pItem = CreateContainer( pRequest->m_sObjectId, query.value(1).toString(), pRequest->m_sParentId ); pItem->SetChildCount( GetDistinctCount( pInfo )); pResults->Add( pItem ); } } } break; } case CDS_BrowseDirectChildren: { CreateItems( pRequest, pResults, nNodeIdx, sKey, true ); break; } case CDS_BrowseUnknown: default: break; } } return pResults; }
UPnpCDSExtensionResults *UPnpCDSExtension::ProcessRoot( UPnpCDSRequest *pRequest, UPnpCDSExtensionResults *pResults, QStringList &/*idPath*/ ) { pResults->m_nTotalMatches = 0; pResults->m_nUpdateID = 1; short nRootCount = GetRootCount(); switch( pRequest->m_eBrowseFlag ) { case CDS_BrowseMetadata: { // -------------------------------------------------------------- // Return Root Object Only // -------------------------------------------------------------- pResults->m_nTotalMatches = 1; pResults->m_nUpdateID = 1; CDSObject *pRoot = CreateContainer( m_sExtensionId, m_sName, "0"); pRoot->SetChildCount( nRootCount ); pResults->Add( pRoot ); break; } case CDS_BrowseDirectChildren: { VERBOSE(VB_UPNP, "CDS_BrowseDirectChildren"); pResults->m_nUpdateID = 1; pResults->m_nTotalMatches = nRootCount ; if ( pRequest->m_nRequestedCount == 0) pRequest->m_nRequestedCount = nRootCount ; short nStart = Max( pRequest->m_nStartingIndex, short( 0 )); short nEnd = Min( nRootCount, short( nStart + pRequest->m_nRequestedCount)); if (nStart < nRootCount) { for (short nIdx = nStart; nIdx < nEnd; nIdx++) { UPnpCDSRootInfo *pInfo = GetRootInfo( nIdx ); if (pInfo != NULL) { QString sId = QString( "%1/%2" ).arg( pRequest->m_sObjectId ) .arg( nIdx ); CDSObject *pItem = CreateContainer( sId, QObject::tr( pInfo->title ), m_sExtensionId ); pItem->SetChildCount( GetDistinctCount( pInfo ) ); pResults->Add( pItem ); } } } } case CDS_BrowseUnknown: default: break; } return pResults; }
UPnpCDSExtensionResults *UPnpCDSExtension::ProcessContainer( UPnpCDSRequest *pRequest, UPnpCDSExtensionResults *pResults, int nNodeIdx, QStringList &/*idPath*/ ) { pResults->m_nUpdateID = 1; pResults->m_nTotalMatches = 0; UPnpCDSRootInfo *pInfo = GetRootInfo( nNodeIdx ); if (pInfo == NULL) return pResults; switch( pRequest->m_eBrowseFlag ) { case CDS_BrowseMetadata: { // -------------------------------------------------------------- // Return Container Object Only // -------------------------------------------------------------- pResults->m_nTotalMatches = 1; pResults->m_nUpdateID = 1; CDSObject *pItem = CreateContainer( pRequest->m_sObjectId, QObject::tr( pInfo->title ), m_sExtensionId ); pItem->SetChildCount( GetDistinctCount( pInfo )); pResults->Add( pItem ); break; } case CDS_BrowseDirectChildren: { pResults->m_nTotalMatches = GetDistinctCount( pInfo ); pResults->m_nUpdateID = 1; if (pRequest->m_nRequestedCount == 0) pRequest->m_nRequestedCount = SHRT_MAX; MSqlQuery query(MSqlQuery::InitCon()); if (query.isConnected()) { // Remove where clause placeholder. QString sSQL = pInfo->sql; sSQL.replace( "%1", "" ); sSQL += QString( " LIMIT %2, %3" ) .arg( pRequest->m_nStartingIndex ) .arg( pRequest->m_nRequestedCount ); query.prepare( sSQL ); query.exec(); if (query.isActive() && query.size() > 0) { while(query.next()) { QString sKey = query.value(0).toString(); QString sTitle = QString::fromUtf8(query.value(1).toString()); long nCount = query.value(2).toInt(); if (sTitle.length() == 0) sTitle = "(undefined)"; QString sId = QString( "%1/key=%2" ) .arg( pRequest->m_sParentId ) .arg( sKey ); CDSObject *pRoot = CreateContainer( sId, sTitle, pRequest->m_sParentId ); pRoot->SetChildCount( nCount ); pResults->Add( pRoot ); } } } break; } case CDS_BrowseUnknown: break; } return pResults; }
bool UPnpCDSVideo::LoadGenres(const UPnpCDSRequest* pRequest, UPnpCDSExtensionResults* pResults, IDTokenMap tokens) { QString sRequestId = pRequest->m_sObjectId; 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.category, g.genre, COUNT(DISTINCT v.intid) " "FROM videometadata v " "LEFT JOIN videogenre g ON g.intid=v.category " "%1 " // whereString "GROUP BY g.intid " "ORDER BY g.genre " "LIMIT :OFFSET,:COUNT "; QStringList clauses; clauses.append("v.category != 0"); 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 nGenreID = query.value(0).toInt(); QString sName = query.value(1).toString(); int nVideoCount = query.value(2).toInt(); // TODO Album or plain old container? CDSObject* pContainer = CDSObject::CreateMovieGenre( CreateIDString(sRequestId, "Genre", nGenreID), sName, pRequest->m_sParentId, NULL ); pContainer->SetChildCount(nVideoCount); pContainer->SetChildContainerCount(0); pResults->Add(pContainer); pContainer->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; }
bool UPnpCDSVideo::LoadSeasons(const UPnpCDSRequest* pRequest, UPnpCDSExtensionResults* pResults, IDTokenMap tokens) { QString sRequestId = pRequest->m_sObjectId; 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.season, COUNT(DISTINCT v.intid), v.intid " "FROM videometadata v " "%1 " // whereString "GROUP BY v.season " "ORDER BY v.season " "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 nSeason = query.value(0).toInt(); int nVideoCount = query.value(1).toInt(); int nVidID = query.value(2).toInt(); QString sTitle = QObject::tr("Season %1").arg(nSeason); // TODO Album or plain old container? CDSObject* pContainer = CDSObject::CreateAlbum( CreateIDString(sRequestId, "Season", nSeason), sTitle, pRequest->m_sParentId, NULL ); pContainer->SetPropValue("description", QObject::tr("%n Episode(s)", "", nVideoCount)); pContainer->SetPropValue("longdescription", QObject::tr("%n Episode(s)", "", nVideoCount)); pContainer->SetPropValue("storageMedium", "HDD"); pContainer->SetChildCount(nVideoCount); pContainer->SetChildContainerCount(0); PopulateArtworkURIS(pContainer, nVidID, m_URIBase); pResults->Add(pContainer); pContainer->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; }
void UPnpCDSVideo::CreateRoot() { if (m_pRoot) return; m_pRoot = CDSObject::CreateContainer(m_sExtensionId, m_sName, "0"); CDSObject* pContainer; QString containerId = m_sExtensionId + "/%1"; // HACK: I'm not entirely happy with this solution, but it's at least // tidier than passing through half a dozen extra args to Load[Foo] // or having yet more methods just to load the counts UPnpCDSRequest *pRequest = new UPnpCDSRequest(); pRequest->m_nRequestedCount = 0; // We don't want to load any results, we just want the TotalCount UPnpCDSExtensionResults *pResult = new UPnpCDSExtensionResults(); IDTokenMap tokens; // END HACK // ----------------------------------------------------------------------- // All Videos // ----------------------------------------------------------------------- pContainer = CDSObject::CreateContainer ( containerId.arg("Video"), QObject::tr("All Videos"), m_sExtensionId, // Parent Id NULL ); // HACK LoadVideos(pRequest, pResult, tokens); pContainer->SetChildCount(pResult->m_nTotalMatches); pContainer->SetChildContainerCount(0); // END HACK m_pRoot->AddChild(pContainer); // ----------------------------------------------------------------------- // Films // ----------------------------------------------------------------------- pContainer = CDSObject::CreateContainer ( containerId.arg("Movie"), QObject::tr("Movies"), m_sExtensionId, // Parent Id NULL ); // HACK LoadMovies(pRequest, pResult, tokens); pContainer->SetChildCount(pResult->m_nTotalMatches); pContainer->SetChildContainerCount(0); // END HACK m_pRoot->AddChild(pContainer); // ----------------------------------------------------------------------- // Series // ----------------------------------------------------------------------- pContainer = CDSObject::CreateContainer ( containerId.arg("Series"), QObject::tr("Series"), m_sExtensionId, // Parent Id NULL ); // HACK LoadSeries(pRequest, pResult, tokens); pContainer->SetChildCount(pResult->m_nTotalMatches); pContainer->SetChildContainerCount(0); // END HACK m_pRoot->AddChild(pContainer); // ----------------------------------------------------------------------- // Other (Home videos?) // ----------------------------------------------------------------------- // pContainer = CDSObject::CreateContainer ( containerId.arg("Other"), // QObject::tr("Other"), // m_sExtensionId, // Parent Id // NULL ); // m_pRoot->AddChild(pContainer); // ----------------------------------------------------------------------- // Genre // ----------------------------------------------------------------------- pContainer = CDSObject::CreateContainer ( containerId.arg("Genre"), QObject::tr("Genre"), m_sExtensionId, // Parent Id NULL ); // HACK LoadGenres(pRequest, pResult, tokens); pContainer->SetChildCount(pResult->m_nTotalMatches); pContainer->SetChildContainerCount(0); // END HACK m_pRoot->AddChild(pContainer); // ----------------------------------------------------------------------- // By Directory // ----------------------------------------------------------------------- // pContainer = CDSObject::CreateStorageSystem ( containerId.arg("Directory"), // QObject::tr("Directory"), // m_sExtensionId, // Parent Id // NULL ); // m_pRoot->AddChild(pContainer); // HACK delete pRequest; delete pResult; // END HACK }