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