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