MythTV  master
upnpcds.cpp
Go to the documentation of this file.
1 // Program Name: upnpcds.cpp
3 // Created : Oct. 24, 2005
4 //
5 // Purpose : uPnp Content Directory Service
6 //
7 // Copyright (c) 2005 David Blain <dblain@mythtv.org>
8 //
9 // Licensed under the GPL v2 or later, see COPYING for details
10 //
12 
13 #include <algorithm>
14 #include <cmath>
15 #include <cstdint>
16 
17 #include "upnp.h"
18 #include "upnpcds.h"
19 #include "upnputil.h"
20 #include "mythlogging.h"
21 #include "mythversion.h"
22 
23 #define DIDL_LITE_BEGIN "<DIDL-Lite xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:upnp=\"urn:schemas-upnp-org:metadata-1-0/upnp/\" xmlns=\"urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/\">"
24 #define DIDL_LITE_END "</DIDL-Lite>";
25 
27 //
29 
31 {
32  if (pObject)
33  {
34  pObject->IncrRef();
35  m_List.append( pObject );
36  }
37 }
38 
40 //
42 
44 {
45  for (auto *const object : qAsConst(objects))
46  {
47  object->IncrRef();
48  m_List.append( object );
49  }
50 }
51 
53 //
55 
57  bool ignoreChildren)
58 {
59  QString sXML;
60 
61  for (auto *item : qAsConst(m_List))
62  sXML += item->toXml(filter, ignoreChildren);
63 
64  return sXML;
65 }
66 
68 //
70 
71 UPnpCDS::UPnpCDS( UPnpDevice *pDevice, const QString &sSharePath )
72  : Eventing( "UPnpCDS", "CDS_Event", sSharePath )
73 {
75  m_root.m_sId = "0";
76  m_root.m_sParentId = "-1";
77  m_root.m_sTitle = "MythTV";
78  m_root.m_sClass = "object.container";
79  m_root.m_bRestricted = true;
80  m_root.m_bSearchable = true;
81 
82  AddVariable( new StateVariable< QString >( "TransferIDs" , true ) );
83  AddVariable( new StateVariable< QString >( "ContainerUpdateIDs", true ) );
84  AddVariable( new StateVariable< uint16_t >( "SystemUpdateID" , true ) );
85  AddVariable( new StateVariable< QString >( "ServiceResetToken" , true ) );
86 
87  SetValue< uint16_t >( "SystemUpdateID", 0 );
88  // ServiceResetToken must be unique (never repeat) and it must change when
89  // the backend restarts (all internal state is reset)
90  //
91  // The current date + time fits the criteria.
92  SetValue< QString >( "ServiceResetToken",
93  QDateTime::currentDateTimeUtc().toString(Qt::ISODate) );
94 
95  QString sUPnpDescPath = UPnp::GetConfiguration()->GetValue( "UPnP/DescXmlPath", sSharePath );
96 
97  m_sServiceDescFileName = sUPnpDescPath + "CDS_scpd.xml";
98  m_sControlUrl = "/CDS_Control";
99 
102 
103  // Add our Service Definition to the device.
104 
105  RegisterService( pDevice );
106 
107  // ContentDirectoryService uses a different schema definition for the FeatureList
108  // to the ConnectionManager, although they appear to be identical
110  "urn:schemas-upnp-org:av:avs" ));
111  m_features.AddAttribute(NameValue( "xmlns:xsi",
112  "http://www.w3.org/2001/XMLSchema-instance" ));
113  m_features.AddAttribute(NameValue( "xsi:schemaLocation",
114  "urn:schemas-upnp-org:av:avs "
115  "http://www.upnp.org/schemas/av/avs.xsd" ));
116 }
117 
119 //
121 
123 {
124  while (!m_extensions.isEmpty())
125  {
126  delete m_extensions.takeLast();
127  }
128 }
129 
131 //
133 
134 UPnpCDSMethod UPnpCDS::GetMethod( const QString &sURI )
135 {
136  if (sURI == "GetServDesc" ) return CDSM_GetServiceDescription;
137  if (sURI == "Browse" ) return CDSM_Browse ;
138  if (sURI == "Search" ) return CDSM_Search ;
139  if (sURI == "GetSearchCapabilities" ) return CDSM_GetSearchCapabilities;
140  if (sURI == "GetSortCapabilities" ) return CDSM_GetSortCapabilities ;
141  if (sURI == "GetSystemUpdateID" ) return CDSM_GetSystemUpdateID ;
142  if (sURI == "X_GetFeatureList" || // HACK: Samsung
143  sURI == "GetFeatureList" ) return CDSM_GetFeatureList ;
144  if (sURI == "GetServiceResetToken" ) return CDSM_GetServiceResetToken ;
145 
146  return( CDSM_Unknown );
147 }
148 
150 //
152 
154 {
155  if (sFlag == "BrowseMetadata" ) return( CDS_BrowseMetadata );
156  if (sFlag == "BrowseDirectChildren" ) return( CDS_BrowseDirectChildren );
157 
158  return( CDS_BrowseUnknown );
159 }
160 
162 //
164 
166 {
167  if (pExtension)
168  {
169  m_extensions.append( pExtension );
170 
171  CDSShortCutList shortcuts = pExtension->GetShortCuts();
172  CDSShortCutList::iterator it;
173  for (it = shortcuts.begin(); it != shortcuts.end(); ++it)
174  {
175  RegisterShortCut(it.key(), it.value());
176  }
177  }
178 }
179 
181 //
183 
185 {
186  if (pExtension)
187  {
188  m_extensions.removeAll(pExtension);
189  delete pExtension;
190  }
191 }
192 
194 //
196 
198  const QString& objectID)
199 {
200  m_pShortCuts->AddShortCut(type, objectID);
201 }
202 
204 //
206 
208 {
209  m_features.AddFeature(feature); // m_features takes ownership
210 }
211 
213 //
215 
217 {
219 }
220 
222 //
224 
226 {
227  if (pRequest)
228  {
229  if (Eventing::ProcessRequest( pRequest ))
230  return true;
231 
232  if ( pRequest->m_sBaseUrl != m_sControlUrl )
233  {
234 #if 0
235  LOG(VB_UPNP, LOG_DEBUG,
236  QString("UPnpCDS::ProcessRequest - BaseUrl (%1) not ours...")
237  .arg(pRequest->m_sBaseUrl));
238 #endif
239  return false;
240  }
241 
242  switch( GetMethod( pRequest->m_sMethod ) )
243  {
246  break;
247  case CDSM_Browse :
248  HandleBrowse( pRequest );
249  break;
250  case CDSM_Search :
251  HandleSearch( pRequest );
252  break;
254  HandleGetSearchCapabilities( pRequest );
255  break;
257  HandleGetSortCapabilities( pRequest );
258  break;
260  HandleGetSystemUpdateID( pRequest );
261  break;
262  case CDSM_GetFeatureList :
263  HandleGetFeatureList( pRequest );
264  break;
266  HandleGetServiceResetToken( pRequest );
267  break;
268  default:
270  break;
271  }
272 
273  return true;
274  }
275 
276  return false;
277 }
278 
279 static const std::array<const UPnpCDSClientException,5> clientExceptions {{
280  // Windows Media Player version 12
281  { CDS_ClientWMP,
282  "User-Agent",
283  "Windows-Media-Player/" },
284  // Windows Media Player version < 12
285  { CDS_ClientWMP,
286  "User-Agent",
287  "Mozilla/4.0 (compatible; UPnP/1.0; Windows 9x" },
288  // XBMC
289  { CDS_ClientXBMC,
290  "User-Agent",
291  "Platinum/" },
292  // XBox 360
293  { CDS_ClientXBox,
294  "User-Agent",
295  "Xbox" },
296  // Sony Blu-ray players
298  "X-AV-Client-Info",
299  R"(cn="Sony Corporation"; mn="Blu-ray Disc Player")" },
300 }};
301 
303  UPnpCDSRequest *pCDSRequest )
304 {
305  pCDSRequest->m_eClient = CDS_ClientDefault;
306  pCDSRequest->m_nClientVersion = 0;
307 
308  // Do we know this client string?
309  for ( const auto & except : clientExceptions )
310  {
311  QString sHeaderValue = pRequest->GetRequestHeader(except.sHeaderKey, "");
312  int idx = sHeaderValue.indexOf(except.sHeaderValue);
313  if (idx == -1)
314  continue;
315 
316  pCDSRequest->m_eClient = except.nClientType;
317 
318  idx += except.sHeaderValue.length();
319 
320  // If we have a / at the end of the string then we
321  // increment the string to skip over it
322  if ( sHeaderValue[idx] == '/')
323  {
324  idx++;
325  }
326 
327  // Now find the version number
328  QString version = sHeaderValue.mid(idx).trimmed();
329  idx = version.indexOf( '.' );
330  if (idx != -1)
331  {
332  idx = version.indexOf( '.', idx + 1 );
333  }
334  if (idx != -1)
335  {
336  version = version.left( idx );
337  }
338  idx = version.indexOf( ' ' );
339  if (idx != -1)
340  {
341  version = version.left( idx );
342  }
343 
344  pCDSRequest->m_nClientVersion = version.toDouble();
345 
346  LOG(VB_UPNP, LOG_INFO,
347  QString("DetermineClient %1:%2 Identified as %3 version %4")
348  .arg(except.sHeaderKey) .arg(sHeaderValue)
349  .arg(pCDSRequest->m_eClient)
350  .arg(pCDSRequest->m_nClientVersion));
351  break;
352  }
353 }
354 
355 
357 //
359 
361 {
362  UPnpCDSExtensionResults *pResult = nullptr;
363  UPnpCDSRequest request;
364 
365  DetermineClient( pRequest, &request );
366  request.m_sObjectId = pRequest->m_mapParams[ "objectid" ];
367  request.m_sParentId = "0";
368  request.m_eBrowseFlag =
369  GetBrowseFlag( pRequest->m_mapParams[ "browseflag" ] );
370  request.m_sFilter = pRequest->m_mapParams[ "filter" ];
371  request.m_nStartingIndex = Max(pRequest->m_mapParams[ "startingindex" ].toUShort(),
372  uint16_t(0));
373  request.m_nRequestedCount =
374  pRequest->m_mapParams[ "requestedcount"].toUShort();
375  if (request.m_nRequestedCount == 0)
376  request.m_nRequestedCount = UINT16_MAX;
377  request.m_sSortCriteria = pRequest->m_mapParams[ "sortcriteria" ];
378 
379 
380  LOG(VB_UPNP, LOG_DEBUG, QString("UPnpCDS::ProcessRequest \n"
381  ": url = %1 \n"
382  ": Method = %2 \n"
383  ": ObjectId = %3 \n"
384  ": BrowseFlag = %4 \n"
385  ": Filter = %5 \n"
386  ": StartingIndex = %6 \n"
387  ": RequestedCount = %7 \n"
388  ": SortCriteria = %8 " )
389  .arg( pRequest->m_sBaseUrl )
390  .arg( pRequest->m_sMethod )
391  .arg( request.m_sObjectId )
392  .arg( request.m_eBrowseFlag )
393  .arg( request.m_sFilter )
394  .arg( request.m_nStartingIndex )
395  .arg( request.m_nRequestedCount)
396  .arg( request.m_sSortCriteria ));
397 
399  QString sErrorDesc = "";
400  uint16_t nNumberReturned = 0;
401  uint16_t nTotalMatches = 0;
402  uint16_t nUpdateID = 0;
403  QString sResultXML;
404  FilterMap filter = request.m_sFilter.split(',');
405 
406  LOG(VB_UPNP, LOG_INFO,
407  QString("UPnpCDS::HandleBrowse ObjectID=%1")
408  .arg(request.m_sObjectId));
409 
410  if (request.m_sObjectId == "0")
411  {
412  // ------------------------------------------------------------------
413  // This is for the root object... lets handle it.
414  // ------------------------------------------------------------------
415 
416  switch( request.m_eBrowseFlag )
417  {
418  case CDS_BrowseMetadata:
419  {
420  // -----------------------------------------------------------
421  // Return Root Object Only
422  // -----------------------------------------------------------
423 
424  eErrorCode = UPnPResult_Success;
425  nNumberReturned = 1;
426  nTotalMatches = 1;
427  nUpdateID = m_root.m_nUpdateId;
428 
429  m_root.SetChildCount( m_extensions.count() );
431 
432  sResultXML = m_root.toXml(filter);
433 
434  break;
435  }
436 
438  {
439  // Loop Through each extension and Build the Root Folders
440 
441  eErrorCode = UPnPResult_Success;
442  nTotalMatches = m_extensions.count();
443  nUpdateID = m_root.m_nUpdateId;
444 
445  if (request.m_nRequestedCount == 0)
446  request.m_nRequestedCount = nTotalMatches;
447 
448  uint16_t nStart = Max( request.m_nStartingIndex, uint16_t( 0 ));
449  uint16_t nCount = Min( nTotalMatches, request.m_nRequestedCount );
450 
451  DetermineClient( pRequest, &request );
452 
453  for (uint i = nStart;
454  (i < (uint)m_extensions.size()) &&
455  (nNumberReturned < nCount);
456  i++)
457  {
458  UPnpCDSExtension *pExtension = m_extensions[i];
459  CDSObject* pExtensionRoot = pExtension->GetRoot();
460  sResultXML += pExtensionRoot->toXml(filter, true); // Ignore Children
461  nNumberReturned ++;
462  }
463 
464  break;
465  }
466  default: break;
467  }
468  }
469  else
470  {
471  // ------------------------------------------------------------------
472  // Look for a CDS Extension that knows how to handle this ObjectID
473  // ------------------------------------------------------------------
474 
475  UPnpCDSExtensionList::iterator it = m_extensions.begin();
476  for (; (it != m_extensions.end()) && !pResult; ++it)
477  {
478  LOG(VB_UPNP, LOG_INFO,
479  QString("UPNP Browse : Searching for : %1 / ObjectID : %2")
480  .arg((*it)->m_sExtensionId).arg(request.m_sObjectId));
481 
482  pResult = (*it)->Browse(&request);
483  }
484 
485  if (pResult != nullptr)
486  {
487  eErrorCode = pResult->m_eErrorCode;
488  sErrorDesc = pResult->m_sErrorDesc;
489 
490  if (eErrorCode == UPnPResult_Success)
491  {
492  while (pResult->m_List.size() > request.m_nRequestedCount)
493  {
494  pResult->m_List.takeLast()->DecrRef();
495  }
496 
497  nNumberReturned = pResult->m_List.count();
498  nTotalMatches = pResult->m_nTotalMatches;
499  nUpdateID = pResult->m_nUpdateID;
500  if (request.m_eBrowseFlag == CDS_BrowseMetadata)
501  sResultXML = pResult->GetResultXML(filter, true); // Ignore children
502  else
503  sResultXML = pResult->GetResultXML(filter);
504  }
505 
506  delete pResult;
507  pResult = nullptr;
508  }
509  }
510 
511  // ----------------------------------------------------------------------
512  // Output Results of Browse Method
513  // ----------------------------------------------------------------------
514 
515  if (eErrorCode == UPnPResult_Success)
516  {
517  NameValues list;
518 
519  QString sResults = DIDL_LITE_BEGIN;
520  sResults += sResultXML;
521  sResults += DIDL_LITE_END;
522 
523  list.push_back(NameValue("Result", sResults));
524  list.push_back(NameValue("NumberReturned", nNumberReturned));
525  list.push_back(NameValue("TotalMatches", nTotalMatches));
526  list.push_back(NameValue("UpdateID", nUpdateID));
527 
528  pRequest->FormatActionResponse(list);
529  }
530  else
531  UPnp::FormatErrorResponse ( pRequest, eErrorCode, sErrorDesc );
532 
533 }
534 
536 //
538 
540 {
541  UPnpCDSExtensionResults *pResult = nullptr;
542  UPnpCDSRequest request;
543 
545  QString sErrorDesc = "";
546  uint16_t nNumberReturned = 0;
547  uint16_t nTotalMatches = 0;
548  uint16_t nUpdateID = 0;
549  QString sResultXML;
550 
551  DetermineClient( pRequest, &request );
552  request.m_sObjectId = pRequest->m_mapParams[ "objectid" ];
553  request.m_sContainerID = pRequest->m_mapParams[ "containerid" ];
554  request.m_sFilter = pRequest->m_mapParams[ "filter" ];
555  request.m_nStartingIndex =
556  pRequest->m_mapParams[ "startingindex" ].toLong();
557  request.m_nRequestedCount =
558  pRequest->m_mapParams[ "requestedcount"].toLong();
559  request.m_sSortCriteria = pRequest->m_mapParams[ "sortcriteria" ];
560  request.m_sSearchCriteria = pRequest->m_mapParams[ "searchcriteria"];
561 
562  LOG(VB_UPNP, LOG_INFO,
563  QString("UPnpCDS::HandleSearch ObjectID=%1, ContainerId=%2")
564  .arg(request.m_sObjectId) .arg(request.m_sContainerID));
565 
566  // ----------------------------------------------------------------------
567  // Break the SearchCriteria into it's parts
568  // -=>TODO: This DOES NOT handle ('s or other complex expressions
569  // ----------------------------------------------------------------------
570 
571  QRegularExpression re {"\\b(or|and)\\b", QRegularExpression::CaseInsensitiveOption};
572 
573 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
574  request.m_sSearchList = request.m_sSearchCriteria.split(
575  re, QString::SkipEmptyParts);
576 #else
577  request.m_sSearchList = request.m_sSearchCriteria.split(
578  re, Qt::SkipEmptyParts);
579 #endif
580  request.m_sSearchClass = "object"; // Default to all objects.
581 
582  // ----------------------------------------------------------------------
583  // -=>TODO: Need to process all expressions in searchCriteria... for now,
584  // Just focus on the "upnp:class derivedfrom" expression
585  // ----------------------------------------------------------------------
586 
587  for ( QStringList::Iterator it = request.m_sSearchList.begin();
588  it != request.m_sSearchList.end();
589  ++it )
590  {
591  if ((*it).contains("upnp:class derivedfrom", Qt::CaseInsensitive))
592  {
593 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
594  QStringList sParts = (*it).split(' ', QString::SkipEmptyParts);
595 #else
596  QStringList sParts = (*it).split(' ', Qt::SkipEmptyParts);
597 #endif
598 
599  if (sParts.count() > 2)
600  {
601  request.m_sSearchClass = sParts[2].trimmed();
602  request.m_sSearchClass.remove( '"' );
603 
604  break;
605  }
606  }
607  }
608 
609  // ----------------------------------------------------------------------
610 
611 
612  LOG(VB_UPNP, LOG_INFO, QString("UPnpCDS::ProcessRequest \n"
613  ": url = %1 \n"
614  ": Method = %2 \n"
615  ": ObjectId = %3 \n"
616  ": SearchCriteria = %4 \n"
617  ": Filter = %5 \n"
618  ": StartingIndex = %6 \n"
619  ": RequestedCount = %7 \n"
620  ": SortCriteria = %8 \n"
621  ": SearchClass = %9" )
622  .arg( pRequest->m_sBaseUrl )
623  .arg( pRequest->m_sMethod )
624  .arg( request.m_sObjectId )
625  .arg( request.m_sSearchCriteria)
626  .arg( request.m_sFilter )
627  .arg( request.m_nStartingIndex )
628  .arg( request.m_nRequestedCount)
629  .arg( request.m_sSortCriteria )
630  .arg( request.m_sSearchClass ));
631 
632 #if 0
633  bool bSearchDone = false;
634 #endif
635 
636  UPnpCDSExtensionList::iterator it = m_extensions.begin();
637  for (; (it != m_extensions.end()) && !pResult; ++it)
638  pResult = (*it)->Search(&request);
639 
640  if (pResult != nullptr)
641  {
642  eErrorCode = pResult->m_eErrorCode;
643  sErrorDesc = pResult->m_sErrorDesc;
644 
645  if (eErrorCode == UPnPResult_Success)
646  {
647  FilterMap filter = request.m_sFilter.split(',');
648  nNumberReturned = pResult->m_List.count();
649  nTotalMatches = pResult->m_nTotalMatches;
650  nUpdateID = pResult->m_nUpdateID;
651  sResultXML = pResult->GetResultXML(filter);
652 #if 0
653  bSearchDone = true;
654 #endif
655  }
656 
657  delete pResult;
658  pResult = nullptr;
659  }
660 
661 #if 0
662  nUpdateID = 0;
663  LOG(VB_UPNP, LOG_DEBUG, sResultXML);
664 #endif
665 
666  if (eErrorCode == UPnPResult_Success)
667  {
668  NameValues list;
669  QString sResults = DIDL_LITE_BEGIN;
670  sResults += sResultXML;
671  sResults += DIDL_LITE_END;
672 
673  list.push_back(NameValue("Result", sResults));
674  list.push_back(NameValue("NumberReturned", nNumberReturned));
675  list.push_back(NameValue("TotalMatches", nTotalMatches));
676  list.push_back(NameValue("UpdateID", nUpdateID));
677 
678  pRequest->FormatActionResponse(list);
679  }
680  else
681  UPnp::FormatErrorResponse( pRequest, eErrorCode, sErrorDesc );
682 }
683 
691 {
692  NameValues list;
693 
694  LOG(VB_UPNP, LOG_INFO,
695  QString("UPnpCDS::ProcessRequest : %1 : %2")
696  .arg(pRequest->m_sBaseUrl) .arg(pRequest->m_sMethod));
697 
698  // -=>TODO: Need to implement based on CDS Extension Capabilities
699 
700 // list.push_back(
701 // NameValue("SearchCaps",
702 // "dc:title,dc:creator,dc:date,upnp:class,res@size,"
703 // "res@protocolInfo","@refID"));
704  list.push_back(
705  NameValue("SearchCaps","")); // We don't support any searching
706 
707  pRequest->FormatActionResponse(list);
708 }
709 
717 {
718  NameValues list;
719 
720  LOG(VB_UPNP, LOG_INFO,
721  QString("UPnpCDS::ProcessRequest : %1 : %2")
722  .arg(pRequest->m_sBaseUrl) .arg(pRequest->m_sMethod));
723 
724  // -=>TODO: Need to implement based on CDS Extension Capabilities
725 
726 // list.push_back(
727 // NameValue("SortCaps",
728 // "dc:title,dc:creator,dc:date,upnp:class,res@size,"
729 // "res@protocolInfo,@refID"));
730  list.push_back(
731  NameValue("SortCaps","")); // We don't support any sorting
732 
733  pRequest->FormatActionResponse(list);
734 }
735 
737 //
739 
741 {
742  NameValues list;
743 
744  LOG(VB_UPNP, LOG_INFO,
745  QString("UPnpCDS::ProcessRequest : %1 : %2")
746  .arg(pRequest->m_sBaseUrl) .arg(pRequest->m_sMethod));
747 
748  auto nId = GetValue<uint16_t>("SystemUpdateID");
749 
750  list.push_back(NameValue("Id", nId));
751 
752  pRequest->FormatActionResponse(list);
753 }
754 
756 //
758 
760 {
761  NameValues list;
762  LOG(VB_UPNP, LOG_INFO,
763  QString("UPnpCDS::ProcessRequest : %1 : %2")
764  .arg(pRequest->m_sBaseUrl) .arg(pRequest->m_sMethod));
765 
766  QString sResults = m_features.toXML();
767 
768  list.push_back(NameValue("FeatureList", sResults));
769 
770  pRequest->FormatActionResponse(list);
771 }
772 
774 {
775  NameValues list;
776 
777  LOG(VB_UPNP, LOG_INFO,
778  QString("UPnpCDS::ProcessRequest : %1 : %2")
779  .arg(pRequest->m_sBaseUrl) .arg(pRequest->m_sMethod));
780 
781  auto sToken = GetValue<QString>("ServiceResetToken");
782 
783  list.push_back(NameValue("ResetToken", sToken));
784 
785  pRequest->FormatActionResponse(list);
786 }
787 
790 //
791 // UPnpCDSExtension Implementation
792 //
795 
797 {
798  if (m_pRoot)
799  {
800  m_pRoot->DecrRef();
801  m_pRoot = nullptr;
802  }
803 }
804 
806 //
808 
810 {
811  if (!pRequest->m_sObjectId.startsWith(m_sExtensionId, Qt::CaseSensitive))
812  return false;
813 
814  LOG(VB_UPNP, LOG_INFO, QString("%1: Browse request is for us.").arg(m_sExtensionId));
815 
816  return true;
817 }
818 
820 //
822 
824 {
825  // -=>TODO: Need to add Filter & Sorting Support.
826 
827  if (!IsBrowseRequestForUs( pRequest ))
828  return( nullptr );
829 
830  // ----------------------------------------------------------------------
831  // Split the request ID into token key/value
832  //
833  // Music/Artist=123/Album=15
834  // Music/Genre=32/Artist=616/Album=13/Track=2632
835  // ----------------------------------------------------------------------
836  IDTokenMap tokens = TokenizeIDString(pRequest->m_sObjectId);
837  QString currentToken = GetCurrentToken(pRequest->m_sObjectId).first;
838 
839  LOG(VB_UPNP, LOG_DEBUG, QString("Browse (%1): Current Token '%2'")
840  .arg(m_sExtensionId).arg(currentToken));
841 
842  // ----------------------------------------------------------------------
843  // Process based on location in hierarchy
844  // ----------------------------------------------------------------------
845 
846  auto *pResults = new UPnpCDSExtensionResults();
847 
848  if (pResults != nullptr)
849  {
850  switch( pRequest->m_eBrowseFlag )
851  {
852  case CDS_BrowseMetadata:
853  {
854  if (pRequest->m_nRequestedCount == 0)
855  pRequest->m_nRequestedCount = 1; // This should be the case anyway, but enforce it just in case
856 
857  pRequest->m_sParentId = "0"; // Root
858 
859  // Create parent ID by stripping the last token from the object ID
860  if (pRequest->m_sObjectId.contains("/"))
861  pRequest->m_sParentId = pRequest->m_sObjectId.section("/", 0, -2);
862 
863  LOG(VB_UPNP, LOG_DEBUG, QString("UPnpCDS::Browse: BrowseMetadata (%1)").arg(pRequest->m_sObjectId));
864  if (LoadMetadata(pRequest, pResults, tokens, currentToken))
865  return pResults;
866  pResults->m_eErrorCode = UPnPResult_CDS_NoSuchObject;
867  break;
868  }
869 
871  {
872  pRequest->m_sParentId = pRequest->m_sObjectId;
873  LOG(VB_UPNP, LOG_DEBUG, QString("UPnpCDS::Browse: BrowseDirectChildren (%1)").arg(pRequest->m_sObjectId));
874  if (LoadChildren(pRequest, pResults, tokens, currentToken))
875  return pResults;
876  pResults->m_eErrorCode = UPnPResult_CDS_NoSuchObject;
877  break;
878  }
879 
880  default:
881  {
882  pResults->m_eErrorCode = UPnPResult_CDS_NoSuchObject;
883  pResults->m_sErrorDesc = "";
884  }
885  }
886 
887  }
888 
889  return( pResults );
890 }
891 
893 //
895 
897 {
898  return m_sClass.startsWith( pRequest->m_sSearchClass );
899 }
900 
902 //
904 
906 {
907  // -=>TODO: Need to add Filter & Sorting Support.
908  // -=>TODO: Need to add Sub-Folder/Category Support!!!!!
909 
910  QStringList sEmptyList;
911  LOG(VB_UPNP, LOG_INFO,
912  QString("UPnpCDSExtension::Search : m_sClass = %1 : "
913  "m_sSearchClass = %2")
914  .arg(m_sClass).arg(pRequest->m_sSearchClass));
915 
916  if ( !IsSearchRequestForUs( pRequest ))
917  {
918  LOG(VB_UPNP, LOG_INFO,
919  QString("UPnpCDSExtension::Search - Not For Us : "
920  "m_sClass = %1 : m_sSearchClass = %2")
921  .arg(m_sClass).arg(pRequest->m_sSearchClass));
922  return nullptr;
923  }
924 
925  auto *pResults = new UPnpCDSExtensionResults();
926 
927 // CreateItems( pRequest, pResults, 0, "", false );
928 
929  return pResults;
930 }
931 
933 //
935 
936 QString UPnpCDSExtension::RemoveToken( const QString &sToken,
937  const QString &sStr, int num )
938 {
939  QString sResult( "" );
940  int nPos = -1;
941 
942  for (int nIdx=0; nIdx < num; nIdx++)
943  {
944  if ((nPos = sStr.lastIndexOf( sToken, nPos )) == -1)
945  break;
946  }
947 
948  if (nPos > 0)
949  sResult = sStr.left( nPos );
950 
951  return sResult;
952 }
953 
968  UPnpCDSExtensionResults* /*pResults*/,
969  const IDTokenMap& /*tokens*/,
970  const QString& /*currentToken*/)
971 {
972  return false;
973 }
974 
975 
990  UPnpCDSExtensionResults* /*pResults*/,
991  const IDTokenMap& /*tokens*/,
992  const QString& /*currentToken*/)
993 {
994  return false;
995 }
996 
1012 {
1013  IDTokenMap tokenMap;
1014 
1015  QStringList tokens = Id.split('/');
1016 
1017  QStringList::iterator it;
1018  for (it = tokens.begin() + 1; it < tokens.end(); ++it) // Skip the 'root' token
1019  {
1020 
1021  QString key = (*it).section('=', 0, 0).toLower();
1022  QString value = (*it).section('=', 1, 1);
1023 
1024  tokenMap.insert(key, value);
1025  LOG(VB_UPNP, LOG_DEBUG, QString("Token Key: %1 Value: %2").arg(key)
1026  .arg(value));
1027  }
1028 
1029  return tokenMap;
1030 }
1031 
1032 
1048 {
1049  QStringList tokens = Id.split('/');
1050  QString current = tokens.last();
1051  QString key = current.section('=', 0, 0).toLower();
1052  QString value = current.section('=', 1, 1);
1053 
1054  return IDToken(key, value);
1055 }
1056 
1057 QString UPnpCDSExtension::CreateIDString(const QString &requestId,
1058  const QString &name,
1059  int value)
1060 {
1061  return CreateIDString(requestId, name, QString::number(value));
1062 }
1063 
1064 QString UPnpCDSExtension::CreateIDString(const QString &requestId,
1065  const QString &name,
1066  const QString &value)
1067 {
1068  IDToken currentToken = GetCurrentToken(requestId);
1069  QString currentName = currentToken.first;
1070  QString currentValue = currentToken.second;
1071 
1072  // For metadata requests the request ID will be the ID of the result, so
1073  // we don't need to do anything
1074  if (currentName == name.toLower() && !currentValue.isEmpty() &&
1075  currentValue == value.toLower())
1076  return requestId;
1077  if (currentName == name.toLower() && currentValue.isEmpty())
1078  return QString("%1=%2").arg(requestId).arg(value);
1079  return QString("%1/%2=%3").arg(requestId).arg(name).arg(value);
1080 }
1081 
1083 {
1084  LOG(VB_GENERAL, LOG_CRIT, "UPnpCDSExtension::CreateRoot() called on base class");
1086  m_sName,
1087  "0");
1088 }
1089 
1091 {
1092  if (!m_pRoot)
1093  CreateRoot();
1094 
1095  return m_pRoot;
1096 }
1097 
1099 //
1101 
1103 {
1104  QString xml;
1105 
1106  xml = "<shortcutlist>\r\n";
1107 
1108  QMap<ShortCutType, QString>::iterator it;
1109  for (it = m_shortcuts.begin(); it != m_shortcuts.end(); ++it)
1110  {
1111  ShortCutType type = it.key();
1112  QString objectID = *it;
1113  xml += "<shortcut>\r\n";
1114  xml += QString("<name>%1</name>\r\n").arg(TypeToName(type));
1115  xml += QString("<objectID>%1</objectID>\r\n").arg(HTTPRequest::Encode(objectID));
1116  xml += "</shortcut>\r\n";
1117  }
1118 
1119  xml += "</shortcutlist>\r\n";
1120 
1121  return xml;
1122 }
1123 
1125  const QString &objectID)
1126 {
1127  if (!m_shortcuts.contains(type))
1128  m_shortcuts.insert(type, objectID);
1129  else
1130  {
1131  LOG(VB_GENERAL, LOG_ERR, QString("UPnPCDSShortcuts::AddShortCut(): "
1132  "Attempted to register duplicate "
1133  "shortcut").arg(TypeToName(type)));
1134  }
1135 
1136  return false;
1137 }
1138 
1140 {
1141  QString str;
1142 
1143  switch (type)
1144  {
1145  case MUSIC :
1146  str = "MUSIC";
1147  break;
1148  case MUSIC_ALBUMS :
1149  str = "MUSIC_ALBUMS";
1150  break;
1151  case MUSIC_ARTISTS :
1152  str = "MUSIC_ARTISTS";
1153  break;
1154  case MUSIC_GENRES :
1155  str = "MUSIC_GENRES";
1156  break;
1157  case MUSIC_PLAYLISTS :
1158  str = "MUSIC_PLAYLISTS";
1159  break;
1160  case MUSIC_RECENTLY_ADDED :
1161  str = "MUSIC_RECENTLY_ADDED";
1162  break;
1163  case MUSIC_LAST_PLAYED :
1164  str = "MUSIC_LAST_PLAYED";
1165  break;
1166  case MUSIC_AUDIOBOOKS :
1167  str = "MUSIC_AUDIOBOOKS";
1168  break;
1169  case MUSIC_STATIONS :
1170  str = "MUSIC_STATIONS";
1171  break;
1172  case MUSIC_ALL :
1173  str = "MUSIC_ALL";
1174  break;
1175  case MUSIC_FOLDER_STRUCTURE :
1176  str = "MUSIC_FOLDER_STRUCTURE";
1177  break;
1178 
1179  case IMAGES :
1180  str = "IMAGES";
1181  break;
1182  case IMAGES_YEARS :
1183  str = "IMAGES_YEARS";
1184  break;
1185  case IMAGES_YEARS_MONTH :
1186  str = "IMAGES_YEARS_MONTH";
1187  break;
1188  case IMAGES_ALBUM :
1189  str = "IMAGES_ALBUM";
1190  break;
1191  case IMAGES_SLIDESHOWS :
1192  str = "IMAGES_SLIDESHOWS";
1193  break;
1194  case IMAGES_RECENTLY_ADDED :
1195  str = "IMAGES_RECENTLY_ADDED";
1196  break;
1197  case IMAGES_LAST_WATCHED :
1198  str = "IMAGES_LAST_WATCHED";
1199  break;
1200  case IMAGES_ALL :
1201  str = "IMAGES_ALL";
1202  break;
1204  str = "IMAGES_FOLDER_STRUCTURE";
1205  break;
1206 
1207  case VIDEOS :
1208  str = "VIDEOS";
1209  break;
1210  case VIDEOS_GENRES :
1211  str = "VIDEOS_GENRES";
1212  break;
1213  case VIDEOS_YEARS :
1214  str = "VIDEOS_YEARS";
1215  break;
1216  case VIDEOS_YEARS_MONTH :
1217  str = "VIDEOS_YEARS_MONTH";
1218  break;
1219  case VIDEOS_ALBUM :
1220  str = "VIDEOS_ALBUM";
1221  break;
1222  case VIDEOS_RECENTLY_ADDED :
1223  str = "VIDEOS_RECENTLY_ADDED";
1224  break;
1225  case VIDEOS_LAST_PLAYED :
1226  str = "VIDEOS_LAST_PLAYED";
1227  break;
1228  case VIDEOS_RECORDINGS :
1229  str = "VIDEOS_RECORDINGS";
1230  break;
1231  case VIDEOS_ALL :
1232  str = "VIDEOS_ALL";
1233  break;
1235  case FOLDER_STRUCTURE :
1236  str = "VIDEOS_FOLDER_STRUCTURE";
1237  break;
1238  }
1239 
1240  return str;
1241 }
1242 
1243 // vim:ts=4:sw=4:ai:et:si:sts=4
UPnPShortcutFeature::IMAGES
@ IMAGES
Definition: upnpcds.h:163
UPnpCDSExtensionResults::GetResultXML
QString GetResultXML(FilterMap &filter, bool ignoreChildren=false)
Definition: upnpcds.cpp:56
HTTPRequest::GetRequestHeader
QString GetRequestHeader(const QString &sKey, const QString &sDefault)
Definition: httprequest.cpp:1176
UPnpCDS::m_sControlUrl
QString m_sControlUrl
Definition: upnpcds.h:291
UPnpCDS::m_root
CDSObject m_root
Definition: upnpcds.h:288
NameValue
Definition: upnputil.h:52
UPnpCDSRequest::m_nRequestedCount
uint16_t m_nRequestedCount
Definition: upnpcds.h:80
HTTPRequest::m_sBaseUrl
QString m_sBaseUrl
Definition: httprequest.h:125
UPnpCDSRequest::m_sFilter
QString m_sFilter
Definition: upnpcds.h:78
UPnPShortcutFeature::VIDEOS_LAST_PLAYED
@ VIDEOS_LAST_PLAYED
Definition: upnpcds.h:179
UPnpCDS::m_features
UPnPFeatureList m_features
Definition: upnpcds.h:293
HTTPRequest
Definition: httprequest.h:107
UPnpCDS::GetBasePaths
QStringList GetBasePaths() override
Definition: upnpcds.cpp:216
UPnpCDSExtension::CreateRoot
virtual void CreateRoot()
Definition: upnpcds.cpp:1082
CDSShortCutList
QMap< UPnPShortcutFeature::ShortCutType, QString > CDSShortCutList
Definition: upnpcds.h:195
UPnpCDSExtension
Definition: upnpcds.h:202
ReferenceCounter::DecrRef
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
Definition: referencecounter.cpp:125
UPnpCDSExtension::~UPnpCDSExtension
virtual ~UPnpCDSExtension()
Definition: upnpcds.cpp:796
CDSObject::m_sTitle
QString m_sTitle
Definition: upnpcdsobjects.h:194
UPnPShortcutFeature::MUSIC_STATIONS
@ MUSIC_STATIONS
Definition: upnpcds.h:159
Eventing::GetBasePaths
QStringList GetBasePaths() override
Definition: eventing.cpp:137
UPnpCDS::HandleGetSortCapabilities
static void HandleGetSortCapabilities(HTTPRequest *pRequest)
Return the list of supported sorting fields.
Definition: upnpcds.cpp:716
CDSObject
Definition: upnpcdsobjects.h:183
UPnPShortcutFeature::VIDEOS_ALBUM
@ VIDEOS_ALBUM
Definition: upnpcds.h:177
UPnPShortcutFeature
Standard UPnP Shortcut feature.
Definition: upnpcds.h:138
CDSObject::m_nUpdateId
short m_nUpdateId
Definition: upnpcdsobjects.h:186
UPnpCDS::HandleSearch
void HandleSearch(HTTPRequest *pRequest)
Definition: upnpcds.cpp:539
UPnPShortcutFeature::IMAGES_ALL
@ IMAGES_ALL
Definition: upnpcds.h:170
UPnpCDSRequest::m_sParentId
QString m_sParentId
Definition: upnpcds.h:85
CDS_ClientWMP
@ CDS_ClientWMP
Definition: upnpcds.h:55
CDSM_Browse
@ CDSM_Browse
Definition: upnpcds.h:36
HTTPRequest::m_sMethod
QString m_sMethod
Definition: httprequest.h:127
UPnpCDS::HandleGetSystemUpdateID
void HandleGetSystemUpdateID(HTTPRequest *pRequest)
Definition: upnpcds.cpp:740
UPnpCDSBrowseFlag
UPnpCDSBrowseFlag
Definition: upnpcds.h:45
UPnPShortcutFeature::IMAGES_SLIDESHOWS
@ IMAGES_SLIDESHOWS
Definition: upnpcds.h:167
UPnPShortcutFeature::VIDEOS_RECORDINGS
@ VIDEOS_RECORDINGS
Definition: upnpcds.h:180
UPnpCDSExtension::CreateIDString
static QString CreateIDString(const QString &RequestId, const QString &Name, int Value)
Definition: upnpcds.cpp:1057
arg
arg(title).arg(filename).arg(doDelete))
Eventing
Definition: eventing.h:250
StateVariable
Definition: eventing.h:117
UPnpCDSExtension::m_sName
QString m_sName
Definition: upnpcds.h:207
UPnpCDSRequest::m_nStartingIndex
uint16_t m_nStartingIndex
Definition: upnpcds.h:79
UPnPShortcutFeature::MUSIC_ALL
@ MUSIC_ALL
Definition: upnpcds.h:160
UPnPShortcutFeature::IMAGES_LAST_WATCHED
@ IMAGES_LAST_WATCHED
Definition: upnpcds.h:169
UPnpCDS::m_extensions
UPnpCDSExtensionList m_extensions
Definition: upnpcds.h:287
UPnpCDSExtension::IsSearchRequestForUs
virtual bool IsSearchRequestForUs(UPnpCDSRequest *pRequest)
Definition: upnpcds.cpp:896
UPnPFeatureList::AddFeature
void AddFeature(UPnPFeature *feature)
Definition: upnpserviceimpl.cpp:36
UPnpCDSRequest::m_eClient
UPnpCDSClient m_eClient
Definition: upnpcds.h:95
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
Eventing::ProcessRequest
bool ProcessRequest(HTTPRequest *pRequest) override
Definition: eventing.cpp:149
UPnpCDS::~UPnpCDS
~UPnpCDS() override
Definition: upnpcds.cpp:122
upnpcds.h
UPnpCDSExtension::TokenizeIDString
static IDTokenMap TokenizeIDString(const QString &Id)
Split the 'Id' String up into tokens for handling by each extension.
Definition: upnpcds.cpp:1011
CDSObject::SetChildContainerCount
void SetChildContainerCount(uint32_t nCount)
Allows the caller to set childContainerCount without having to load children.
Definition: upnpcdsobjects.cpp:255
UPnPShortcutFeature::VIDEOS_ALL
@ VIDEOS_ALL
Definition: upnpcds.h:181
UPnPShortcutFeature::MUSIC_AUDIOBOOKS
@ MUSIC_AUDIOBOOKS
Definition: upnpcds.h:158
CDS_ClientXBMC
@ CDS_ClientXBMC
Definition: upnpcds.h:56
UPnpCDSRequest::m_eBrowseFlag
UPnpCDSBrowseFlag m_eBrowseFlag
Definition: upnpcds.h:86
HTTPRequest::Encode
static QString Encode(const QString &sIn)
Definition: httprequest.cpp:1805
DIDL_LITE_END
#define DIDL_LITE_END
Definition: upnpcds.cpp:24
CDSObject::m_sParentId
QString m_sParentId
Definition: upnpcdsobjects.h:193
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
UPnpCDSRequest::m_nClientVersion
double m_nClientVersion
Definition: upnpcds.h:96
UPnp::FormatErrorResponse
static void FormatErrorResponse(HTTPRequest *pRequest, UPnPResultCode eCode, const QString &sMsg="")
Definition: upnp.cpp:280
mythversion.h
UPnpCDSExtension::Browse
virtual UPnpCDSExtensionResults * Browse(UPnpCDSRequest *pRequest)
Definition: upnpcds.cpp:823
UPnpCDSRequest::m_sContainerID
QString m_sContainerID
Definition: upnpcds.h:77
NameValues
Definition: upnputil.h:89
CDS_BrowseDirectChildren
@ CDS_BrowseDirectChildren
Definition: upnpcds.h:49
toString
QString toString(MarkTypes type)
Definition: programtypes.cpp:26
HTTPRequest::FormatActionResponse
void FormatActionResponse(Serializer *ser)
Definition: httprequest.cpp:771
UPnPShortcutFeature::VIDEOS_YEARS
@ VIDEOS_YEARS
Definition: upnpcds.h:175
UPnpServiceImpl::RegisterService
void RegisterService(UPnpDevice *device)
Creates a UPnpService and adds it to the UPnpDevice's list of services.
Definition: upnpserviceimpl.cpp:5
UPnpCDS::UPnpCDS
UPnpCDS(UPnpDevice *pDevice, const QString &sSharePath)
Definition: upnpcds.cpp:71
FilterMap
QMap< uint, int > FilterMap
Definition: ExternalSignalMonitor.h:13
upnp.h
UPnpCDS::DetermineClient
static void DetermineClient(HTTPRequest *pRequest, UPnpCDSRequest *pCDSRequest)
Definition: upnpcds.cpp:302
mythlogging.h
UPnPShortcutFeature::FOLDER_STRUCTURE
@ FOLDER_STRUCTURE
Definition: upnpcds.h:184
UPnPShortcutFeature::MUSIC_PLAYLISTS
@ MUSIC_PLAYLISTS
Definition: upnpcds.h:155
UPnPShortcutFeature::VIDEOS
@ VIDEOS
Definition: upnpcds.h:173
UPnpCDSRequest::m_sSearchCriteria
QString m_sSearchCriteria
Definition: upnpcds.h:90
UPnpCDSExtension::m_sClass
QString m_sClass
Definition: upnpcds.h:208
feature
static const std::array< featureStruct, 7 > feature
Definition: audiooutputsettings.cpp:433
UPnPShortcutFeature::MUSIC
@ MUSIC
Definition: upnpcds.h:151
clientExceptions
static const std::array< const UPnpCDSClientException, 5 > clientExceptions
Definition: upnpcds.cpp:279
UPnpCDS::HandleGetServiceResetToken
void HandleGetServiceResetToken(HTTPRequest *pRequest)
Definition: upnpcds.cpp:773
HTTPRequest::m_mapParams
QStringMap m_mapParams
Definition: httprequest.h:129
UPnpCDSExtensionResults::m_nTotalMatches
uint16_t m_nTotalMatches
Definition: upnpcds.h:113
UPnpCDS::UnregisterExtension
void UnregisterExtension(UPnpCDSExtension *pExtension)
Definition: upnpcds.cpp:184
UPnpCDS::m_sServiceDescFileName
QString m_sServiceDescFileName
Definition: upnpcds.h:290
UPnPShortcutFeature::VIDEOS_GENRES
@ VIDEOS_GENRES
Definition: upnpcds.h:174
UPnpCDSExtension::Search
virtual UPnpCDSExtensionResults * Search(UPnpCDSRequest *pRequest)
Definition: upnpcds.cpp:905
UPnpCDSExtensionResults::Add
void Add(CDSObject *pObject)
Definition: upnpcds.cpp:30
CDSM_Unknown
@ CDSM_Unknown
Definition: upnpcds.h:34
UPnPShortcutFeature::m_shortcuts
QMap< ShortCutType, QString > m_shortcuts
Definition: upnpcds.h:192
CDSM_GetSearchCapabilities
@ CDSM_GetSearchCapabilities
Definition: upnpcds.h:38
UPnPFeatureList::AddAttribute
void AddAttribute(const NameValue &attribute)
Definition: upnpserviceimpl.cpp:41
CDS_ClientXBox
@ CDS_ClientXBox
Definition: upnpcds.h:58
UPnpCDS::RegisterFeature
void RegisterFeature(UPnPFeature *feature)
Definition: upnpcds.cpp:207
UPnpCDSExtensionResults::m_eErrorCode
UPnPResultCode m_eErrorCode
Definition: upnpcds.h:110
CDSObject::m_bSearchable
bool m_bSearchable
Definition: upnpcdsobjects.h:197
CDSObject::m_bRestricted
bool m_bRestricted
Definition: upnpcdsobjects.h:196
UPnpCDSExtension::m_pRoot
CDSObject * m_pRoot
Definition: upnpcds.h:248
CDSObjects
QList< CDSObject * > CDSObjects
Definition: upnpcdsobjects.h:96
UPnPShortcutFeature::AddShortCut
bool AddShortCut(ShortCutType type, const QString &objectID)
Definition: upnpcds.cpp:1124
UPnpDevice
Definition: upnpdevice.h:99
UPnPShortcutFeature::IMAGES_ALBUM
@ IMAGES_ALBUM
Definition: upnpcds.h:166
UPnPShortcutFeature::IMAGES_FOLDER_STRUCTURE
@ IMAGES_FOLDER_STRUCTURE
Definition: upnpcds.h:171
UPnPShortcutFeature::MUSIC_RECENTLY_ADDED
@ MUSIC_RECENTLY_ADDED
Definition: upnpcds.h:156
CDSObject::SetChildCount
void SetChildCount(uint32_t nCount)
Allows the caller to set childCount without having to load children.
Definition: upnpcdsobjects.cpp:232
UPnpCDS::HandleBrowse
void HandleBrowse(HTTPRequest *pRequest)
Definition: upnpcds.cpp:360
CDS_BrowseMetadata
@ CDS_BrowseMetadata
Definition: upnpcds.h:48
CDSM_GetServiceDescription
@ CDSM_GetServiceDescription
Definition: upnpcds.h:35
UPnPShortcutFeature::IMAGES_YEARS
@ IMAGES_YEARS
Definition: upnpcds.h:164
UPnpCDS::ProcessRequest
bool ProcessRequest(HTTPRequest *pRequest) override
Definition: upnpcds.cpp:225
DIDL_LITE_BEGIN
#define DIDL_LITE_BEGIN
Definition: upnpcds.cpp:23
uint
unsigned int uint
Definition: compat.h:141
UPnpCDS::GetBrowseFlag
static UPnpCDSBrowseFlag GetBrowseFlag(const QString &sFlag)
Definition: upnpcds.cpp:153
UPnPShortcutFeature::VIDEOS_YEARS_MONTH
@ VIDEOS_YEARS_MONTH
Definition: upnpcds.h:176
UPnpCDSExtension::LoadMetadata
virtual bool LoadMetadata(const UPnpCDSRequest *pRequest, UPnpCDSExtensionResults *pResults, const IDTokenMap &tokens, const QString &currentToken)
Fetch just the metadata for the item identified in the request.
Definition: upnpcds.cpp:967
UPnPShortcutFeature::ShortCutType
ShortCutType
Allowed values for the Container Shortcut feature.
Definition: upnpcds.h:149
UPnPShortcutFeature::MUSIC_ALBUMS
@ MUSIC_ALBUMS
Definition: upnpcds.h:152
CDSObject::m_sId
QString m_sId
Definition: upnpcdsobjects.h:192
UPnpCDSRequest::m_sObjectId
QString m_sObjectId
Definition: upnpcds.h:75
CDS_BrowseUnknown
@ CDS_BrowseUnknown
Definition: upnpcds.h:47
UPnPResult_InvalidAction
@ UPnPResult_InvalidAction
Definition: upnp.h:40
CDS_ClientSonyDB
@ CDS_ClientSonyDB
Definition: upnpcds.h:59
UPnpCDSExtension::LoadChildren
virtual bool LoadChildren(const UPnpCDSRequest *pRequest, UPnpCDSExtensionResults *pResults, const IDTokenMap &tokens, const QString &currentToken)
Fetch the children of the container identified in the request.
Definition: upnpcds.cpp:989
UPnpCDS::GetMethod
static UPnpCDSMethod GetMethod(const QString &sURI)
Definition: upnpcds.cpp:134
CDSM_GetSystemUpdateID
@ CDSM_GetSystemUpdateID
Definition: upnpcds.h:40
UPnpCDSRequest::m_sSearchList
QStringList m_sSearchList
Definition: upnpcds.h:91
Max
const T & Max(const T &x, const T &y)
Definition: upnputil.h:35
UPnPShortcutFeature::MUSIC_LAST_PLAYED
@ MUSIC_LAST_PLAYED
Definition: upnpcds.h:157
CDS_ClientDefault
@ CDS_ClientDefault
Definition: upnpcds.h:54
UPnpCDSExtension::GetRoot
virtual CDSObject * GetRoot()
Definition: upnpcds.cpp:1090
Min
const T & Min(const T &x, const T &y)
Definition: upnputil.h:30
HTTPRequest::FormatFileResponse
void FormatFileResponse(const QString &sFileName)
Definition: httprequest.cpp:859
MythDate::ISODate
@ ISODate
Default UTC.
Definition: mythdate.h:14
IDTokenMap
QMap< QString, QString > IDTokenMap
Definition: upnpcds.h:199
UPnpCDSExtension::RemoveToken
static QString RemoveToken(const QString &sToken, const QString &sStr, int num)
Definition: upnpcds.cpp:936
UPnPResult_CDS_NoSuchObject
@ UPnPResult_CDS_NoSuchObject
Definition: upnp.h:57
CDSObject::CreateContainer
static CDSObject * CreateContainer(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Definition: upnpcdsobjects.cpp:468
CDSM_GetSortCapabilities
@ CDSM_GetSortCapabilities
Definition: upnpcds.h:39
CDSM_Search
@ CDSM_Search
Definition: upnpcds.h:37
UPnPShortcutFeature::MUSIC_ARTISTS
@ MUSIC_ARTISTS
Definition: upnpcds.h:153
Configuration::GetValue
virtual int GetValue(const QString &sSetting, int Default)=0
UPnpCDS::HandleGetSearchCapabilities
static void HandleGetSearchCapabilities(HTTPRequest *pRequest)
Return the list of supported search fields.
Definition: upnpcds.cpp:690
StateVariables::AddVariable
void AddVariable(StateVariableBase *pBase)
Definition: eventing.h:191
CDSObject::m_sClass
QString m_sClass
Definition: upnpcdsobjects.h:195
UPnp::GetConfiguration
static Configuration * GetConfiguration()
Definition: upnp.cpp:84
UPnpCDSExtensionResults::m_List
CDSObjects m_List
Definition: upnpcds.h:109
UPnPFeature
Definition: upnpserviceimpl.h:50
CDSObject::toXml
QString toXml(FilterMap &filter, bool ignoreChildren=false) const
Definition: upnpcdsobjects.cpp:264
uint16_t
unsigned short uint16_t
Definition: iso6937tables.h:3
IDToken
QPair< QString, QString > IDToken
Definition: upnpcds.h:200
OT_Container
@ OT_Container
Definition: upnpcdsobjects.h:35
UPnPFeatureList::toXML
QString toXML()
Definition: upnpserviceimpl.cpp:46
UPnPShortcutFeature::MUSIC_FOLDER_STRUCTURE
@ MUSIC_FOLDER_STRUCTURE
Definition: upnpcds.h:161
UPnPResult_Success
@ UPnPResult_Success
Definition: upnp.h:38
UPnpCDSExtensionResults
Definition: upnpcds.h:105
UPnPShortcutFeature::MUSIC_GENRES
@ MUSIC_GENRES
Definition: upnpcds.h:154
UPnpCDSMethod
UPnpCDSMethod
Definition: upnpcds.h:32
UPnPShortcutFeature::VIDEOS_FOLDER_STRUCTURE
@ VIDEOS_FOLDER_STRUCTURE
Definition: upnpcds.h:182
UPnPShortcutFeature::CreateXML
QString CreateXML() override
Definition: upnpcds.cpp:1102
UPnpCDS::RegisterExtension
void RegisterExtension(UPnpCDSExtension *pExtension)
Definition: upnpcds.cpp:165
UPnPShortcutFeature::IMAGES_YEARS_MONTH
@ IMAGES_YEARS_MONTH
Definition: upnpcds.h:165
ReferenceCounter::IncrRef
virtual int IncrRef(void)
Increments reference count.
Definition: referencecounter.cpp:101
UPnPShortcutFeature::TypeToName
static QString TypeToName(ShortCutType type)
Definition: upnpcds.cpp:1139
UPnpCDSExtension::GetCurrentToken
static IDToken GetCurrentToken(const QString &Id)
Split the 'Id' String up into tokens and return the last (current) token.
Definition: upnpcds.cpp:1047
upnputil.h
UPnpCDSExtension::GetShortCuts
virtual CDSShortCutList GetShortCuts()
Definition: upnpcds.h:270
CDSM_GetServiceResetToken
@ CDSM_GetServiceResetToken
Definition: upnpcds.h:42
UPnpCDSExtensionResults::m_nUpdateID
uint16_t m_nUpdateID
Definition: upnpcds.h:114
UPnpCDS::m_pShortCuts
UPnPShortcutFeature * m_pShortCuts
Definition: upnpcds.h:294
UPnpCDSRequest::m_sSortCriteria
QString m_sSortCriteria
Definition: upnpcds.h:81
nv_python_libs.bbciplayer.bbciplayer_api.version
string version
Definition: bbciplayer_api.py:81
UPnpCDSRequest
Definition: upnpcds.h:71
CDSObject::m_eType
ObjectTypes m_eType
Definition: upnpcdsobjects.h:188
UPnPShortcutFeature::VIDEOS_RECENTLY_ADDED
@ VIDEOS_RECENTLY_ADDED
Definition: upnpcds.h:178
UPnPShortcutFeature::IMAGES_RECENTLY_ADDED
@ IMAGES_RECENTLY_ADDED
Definition: upnpcds.h:168
UPnpCDSExtensionResults::m_sErrorDesc
QString m_sErrorDesc
Definition: upnpcds.h:111
UPnPResultCode
UPnPResultCode
Definition: upnp.h:36
UPnpCDSExtension::m_sExtensionId
QString m_sExtensionId
Definition: upnpcds.h:206
UPnpCDS::HandleGetFeatureList
void HandleGetFeatureList(HTTPRequest *pRequest)
Definition: upnpcds.cpp:759
UPnpCDS::RegisterShortCut
void RegisterShortCut(UPnPShortcutFeature::ShortCutType type, const QString &objectID)
Definition: upnpcds.cpp:197
UPnpCDSExtension::IsBrowseRequestForUs
virtual bool IsBrowseRequestForUs(UPnpCDSRequest *pRequest)
Definition: upnpcds.cpp:809
UPnpCDSRequest::m_sSearchClass
QString m_sSearchClass
Definition: upnpcds.h:92
CDSM_GetFeatureList
@ CDSM_GetFeatureList
Definition: upnpcds.h:41