MythTV  master
upnpcdsobjects.cpp
Go to the documentation of this file.
1 // Program Name: upnpcdsobjects.cpp
3 // Created : Oct. 24, 2005
4 //
5 // Purpose : uPnp Content Directory Service Object Definitions
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 <QtGlobal>
14 #if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
15 #include <QStringConverter>
16 #else
17 #include <QTextCodec>
18 #endif
19 #include <QTextStream>
20 #include <QUrl>
21 
23 
24 #include "upnpcds.h"
25 
26 inline QString GetBool( bool bVal ) { return( (bVal) ? "1" : "0" ); }
27 
30 //
31 //
32 //
35 
36 CDSObject::CDSObject( const QString &sId,
37  const QString &sTitle,
38  const QString &sParentId )
39  : ReferenceCounter("CDSObject", false),
40  m_sId(HTTPRequest::Encode(sId)),
41  m_sParentId(HTTPRequest::Encode(sParentId)),
42  m_sTitle(HTTPRequest::Encode(sTitle))
43 {
44 }
45 
47 //
49 
51 {
52  while (!m_resources.empty())
53  {
54  delete m_resources.takeLast();
55  }
56 
57  while (!m_children.empty())
58  {
59  m_children.takeLast()->DecrRef();
60  }
61 
62  // NOLINTNEXTLINE(modernize-loop-convert)
63  for (auto it = m_properties.begin(); it != m_properties.end(); ++it)
64  {
65  delete *it;
66  *it = nullptr;
67  }
68  m_properties.clear();
69 }
70 
72 //
74 
76 {
77  if (pProp)
78  {
79  // If this property is allowed multiple times in an object
80  // e.g. Different sizes of artwork, then just insert it
81  // Otherwise remove all existing instances of this property first
82  // NOTE: This requires ALL instances of a property which can exist
83  // more than once to have m_bAllowMulti set to true.
84  if (pProp->m_bMultiValue)
85  m_properties.insert(pProp->m_sName, pProp);
86  else
87  m_properties.replace(pProp->m_sName, pProp);
88  }
89 
90  return pProp;
91 }
92 
94 //
96 
97 QList<Property*> CDSObject::GetProperties( const QString &sName )
98 {
99  QList<Property*> props;
100  Properties::iterator it = m_properties.find(sName);
101  while (it != m_properties.end() && it.key() == sName)
102  {
103  if (*it)
104  props.append(*it);
105  ++it;
106  }
107 
108  return props;
109 }
110 
112 //
114 
115 void CDSObject::SetPropValue( const QString &sName, const QString &sValue,
116  const QString &sType )
117 {
118  Properties::iterator it = m_properties.find(sName);
119  if (it != m_properties.end() && *it)
120  {
121  if ((*it)->m_bMultiValue)
122  {
123  LOG(VB_UPNP, LOG_WARNING,
124  QString("SetPropValue(%1) called on property with bAllowMulti. "
125  "Only the last inserted property will be updated.").arg(sName));
126  }
127  (*it)->SetValue(sValue);
128 
129  if (!sType.isEmpty())
130  (*it)->AddAttribute( "type", sType );
131  }
132  else
133  {
134  LOG(VB_UPNP, LOG_WARNING,
135  QString("SetPropValue(%1) called with non-existent property.").arg(sName));
136  }
137 }
138 
140 //
142 
143 QString CDSObject::GetPropValue(const QString &sName) const
144 {
145  Properties::const_iterator it = m_properties.find(sName);
146 
147  if (it != m_properties.end() && *it)
148  {
149  if ((*it)->m_bMultiValue)
150  {
151  LOG(VB_UPNP, LOG_WARNING,
152  QString("GetPropValue(%1) called on property with bAllowMulti. "
153  "Only the last inserted property will be return."));
154  }
155  return (*it)->GetValue().toUtf8();
156  }
157 
158  return "";
159 }
160 
162 //
164 
166 {
167  if (pChild && !m_children.contains(pChild))
168  {
169  pChild->IncrRef();
170  m_nChildCount++;
171  if (pChild->m_eType == OT_Container)
173  pChild->m_sParentId = m_sId;
174  m_children.append( pChild );
175  }
176 
177  return( pChild );
178 }
179 
181 //
183 
184 CDSObject *CDSObject::GetChild( const QString &sID )
185 {
186  CDSObject *pChild = nullptr;
187  CDSObjects::iterator it;
188  for (it = m_children.begin(); it != m_children.end(); ++it)
189  {
190  pChild = *it;
191  if (!pChild)
192  continue;
193 
194  if (pChild->m_sId == sID)
195  return pChild;
196  }
197 
198  return nullptr;
199 }
200 
202 //
204 
205 Resource *CDSObject::AddResource( const QString& sProtocol, const QString& sURI )
206 {
207  auto *pRes = new Resource( sProtocol, sURI );
208 
209  m_resources.append( pRes );
210 
211  return( pRes );
212 }
213 
214 
219 uint32_t CDSObject::GetChildCount(void) const
220 {
221  uint32_t nCount = m_children.count();
222  if (nCount == 0)
223  return( m_nChildCount );
224 
225  return( nCount );
226 }
227 
232 void CDSObject::SetChildCount( uint32_t nCount )
233 {
234  m_nChildCount = nCount;
235 }
236 
246 {
247  return m_nChildContainerCount;
248 }
249 
255 void CDSObject::SetChildContainerCount( uint32_t nCount )
256 {
257  m_nChildContainerCount = nCount;
258 }
259 
261 //
263 
264 QString CDSObject::toXml( FilterMap &filter,
265  bool ignoreChildren ) const
266 {
267  QString sXML;
268  QTextStream os( &sXML, QIODevice::WriteOnly );
269 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
270  os.setCodec(QTextCodec::codecForName("UTF-8"));
271 #else
272  os.setEncoding(QStringConverter::Utf8);
273 #endif
274  toXml(os, filter, ignoreChildren);
275  os << Qt::flush;
276  return( sXML );
277 }
278 
280 //
282 
283 void CDSObject::toXml( QTextStream &os, FilterMap &filter,
284  bool ignoreChildren ) const
285 {
286  QString sEndTag = "";
287 
312  bool bFilter = true;
313 
314  if (filter.contains("*"))
315  bFilter = false;
316 
317  switch( m_eType )
318  {
319  case OT_Container:
320  {
321  if (bFilter && filter.contains("container#"))
322  bFilter = false;
323 
324  os << "<container id=\"" << m_sId
325  << "\" parentID=\"" << m_sParentId
326  << "\" restricted=\"" << GetBool( m_bRestricted );
327 
328  if (!bFilter || filter.contains("@searchable"))
329  os << "\" searchable=\"" << GetBool( m_bSearchable );
330 
331  if (!bFilter || filter.contains("@childCount"))
332  os << "\" childCount=\"" << GetChildCount();
333 
334  if (!bFilter || filter.contains("@childContainerCount"))
335  os << "\" childContainerCount=\"" << GetChildContainerCount();
336 
337  os << "\" >" << Qt::endl;
338 
339  sEndTag = "</container>";
340 
341  break;
342  }
343  case OT_Item:
344  {
345  if (bFilter && filter.contains("item#"))
346  bFilter = false;
347 
348  os << "<item id=\"" << m_sId
349  << "\" parentID=\"" << m_sParentId
350  << "\" restricted=\"" << GetBool( m_bRestricted )
351  << "\" >" << Qt::endl;
352 
353  sEndTag = "</item>";
354 
355  break;
356  }
357  default: break;
358  }
359 
360  os << "<dc:title>" << m_sTitle << "</dc:title>" << Qt::endl;
361  os << "<upnp:class>" << m_sClass << "</upnp:class>" << Qt::endl;
362 
363  // ----------------------------------------------------------------------
364  // Output all Properties
365  // ----------------------------------------------------------------------
366 
367  for (auto *pProp : std::as_const(m_properties))
368  {
369  if (pProp->m_bRequired || (!pProp->GetValue().isEmpty()))
370  {
371  QString sName;
372 
373  if (!pProp->m_sNameSpace.isEmpty())
374  sName = pProp->m_sNameSpace + ':' + pProp->m_sName;
375  else
376  sName = pProp->m_sName;
377 
378  if (pProp->m_bRequired ||
379  (!bFilter) ||
380  FilterContains(filter, sName))
381  {
382  bool filterAttributes = true;
383  if (!bFilter || filter.contains(QString("%1#").arg(sName)))
384  filterAttributes = false;
385 
386  os << "<" << sName;
387 
388  for (const auto & attr : std::as_const(pProp->m_lstAttributes))
389  {
390  QString filterName = QString("%1@%2").arg(sName,
391  attr.m_sName);
392  if (attr.m_bRequired || !filterAttributes ||
393  filter.contains(filterName))
394  os << " " << attr.m_sName << "=\"" << attr.m_sValue << "\"";
395  }
396 
397  os << ">";
398  os << pProp->GetEncodedValue();
399  os << "</" << sName << ">" << Qt::endl;
400  }
401  }
402  }
403 
404  // ----------------------------------------------------------------------
405  // Output any Res Elements
406  // ----------------------------------------------------------------------
407 
408  if (!bFilter || filter.contains("res"))
409  {
410  bool filterAttributes = true;
411  if (!bFilter || filter.contains("res#"))
412  filterAttributes = false;
413  for (auto *resource : std::as_const(m_resources))
414  {
415  os << "<res protocolInfo=\"" << resource->m_sProtocolInfo << "\" ";
416 
417  QString filterName;
418  for (const auto & attr : std::as_const(resource->m_lstAttributes))
419  {
420  filterName = QString("res@%1").arg(attr.m_sName);
421  if (attr.m_bRequired || !filterAttributes ||
422  filter.contains(filterName))
423  os << attr.m_sName << "=\"" << attr.m_sValue << "\" ";
424  }
425 
426  os << ">" << resource->m_sURI;
427  os << "</res>" << Qt::endl;
428  }
429  }
430 
431  // ----------------------------------------------------------------------
432  // Output any children
433  // ----------------------------------------------------------------------
434 
435  if (!ignoreChildren)
436  {
437  for (auto *cit : m_children)
438  cit->toXml(os, filter);
439  }
440 
441  // ----------------------------------------------------------------------
442  // Close Element Tag
443  // ----------------------------------------------------------------------
444 
445  os << sEndTag << Qt::endl;
446  os << Qt::flush;
447 }
448 
449 
451 //
453 
454 CDSObject *CDSObject::CreateItem( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
455 {
456  if (pObject == nullptr)
457  {
458  pObject = new CDSObject( sId, sTitle, sParentId );
459  pObject->m_sClass = "object.item";
460  }
461 
462  pObject->m_eType = OT_Item;
463  pObject->m_bSearchable = false; // UPnP - CDS B.1.5 @searchable
464 
465  pObject->AddProperty( new Property( "refID" ) );
466 
467  return( pObject );
468 }
469 
471 
472 CDSObject *CDSObject::CreateContainer( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
473 {
474  if (pObject == nullptr)
475  {
476  pObject = new CDSObject( sId, sTitle, sParentId );
477  pObject->m_sClass = "object.container";
478  }
479 
480  pObject->m_eType = OT_Container;
481  pObject->m_bSearchable = true; // DLNA requirement - 7.4.3.5.9
482 
483  pObject->AddProperty( new Property( "childCount" ));
484  pObject->AddProperty( new Property( "createClass" ));
485  pObject->AddProperty( new Property( "searchClass" ));
486  pObject->AddProperty( new Property( "searchable" ));
487 
488  pObject->AddProperty( new Property( "creator", "dc" ));
489  pObject->AddProperty( new Property( "date" , "dc" ));
490 
491  pObject->AddProperty( new Property( "longDescription", "upnp" ));
492  pObject->AddProperty( new Property( "description" , "dc" ));
493 
494  return( pObject );
495 }
496 
498 
499 CDSObject *CDSObject::CreateAudioItem( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
500 {
501  if (pObject == nullptr)
502  {
503  pObject = new CDSObject( sId, sTitle, sParentId );
504  pObject->m_sClass = "object.item.audioItem";
505  }
506 
507  CreateItem( sId, sTitle, sParentId, pObject );
508 
509  pObject->AddProperty( new Property( "genre" , "upnp" ));
510  pObject->AddProperty( new Property( "description" , "dc" ));
511  pObject->AddProperty( new Property( "longDescription" , "upnp" ));
512  pObject->AddProperty( new Property( "publisher" , "dc" ));
513  pObject->AddProperty( new Property( "language" , "dc" ));
514  pObject->AddProperty( new Property( "relation" , "dc" ));
515  pObject->AddProperty( new Property( "rights" , "dc" ));
516 
517  pObject->AddProperty( new Property( "creator" , "dc" ));
518  pObject->AddProperty( new Property( "date" , "dc" ));
519 
520  return( pObject );
521 }
522 
524 
525 CDSObject *CDSObject::CreateMusicTrack( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
526 {
527  if (pObject == nullptr)
528  {
529  pObject = new CDSObject( sId, sTitle, sParentId );
530  pObject->m_sClass = "object.item.audioItem.musicTrack";
531  }
532 
533  CreateAudioItem( sId, sTitle, sParentId, pObject );
534 
535  pObject->AddProperty( new Property( "artist" , "upnp" ));
536  pObject->AddProperty( new Property( "album" , "upnp" ));
537  pObject->AddProperty( new Property( "originalTrackNumber" , "upnp" ));
538  pObject->AddProperty( new Property( "playlist" , "upnp" ));
539  pObject->AddProperty( new Property( "storageMedium" , "upnp" ));
540  pObject->AddProperty( new Property( "contributor" , "dc" ));
541 
542  pObject->AddProperty( new Property( "playbackCount" , "upnp" ));
543  pObject->AddProperty( new Property( "lastPlaybackTime" , "upnp" ));
544 
545  pObject->AddProperty( new Property( "albumArtURI", "upnp", false, "", true)); // TN
546  pObject->AddProperty( new Property( "albumArtURI", "upnp", false, "", true)); // SM
547  pObject->AddProperty( new Property( "albumArtURI", "upnp", false, "", true)); // MED
548  pObject->AddProperty( new Property( "albumArtURI", "upnp", false, "", true)); // LRG
549 
550 #if 0
551  pObject->AddProperty( new Property( "publisher" , "dc" ));
552  pObject->AddProperty( new Property( "language" , "dc" ));
553  pObject->AddProperty( new Property( "relation" , "dc" ));
554  pObject->AddProperty( new Property( "rights" , "dc" ));
555 
556 
557  pObject->AddProperty( new Property( "playlist" , "upnp" ));
558  pObject->AddProperty( new Property( "storageMedium" , "upnp" ));
559  pObject->AddProperty( new Property( "contributor" , "dc" ));
560 #endif
561 
562  return( pObject );
563 }
564 
566 
567 CDSObject *CDSObject::CreateAudioBroadcast( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
568 {
569  if (pObject == nullptr)
570  {
571  pObject = new CDSObject( sId, sTitle, sParentId );
572  pObject->m_sClass = "object.item.audioItem.audioBroadcast";
573  }
574 
575  CreateAudioItem( sId, sTitle, sParentId, pObject );
576 
577  pObject->AddProperty( new Property( "region" , "upnp" ));
578  pObject->AddProperty( new Property( "radioCallSign" , "upnp" ));
579  pObject->AddProperty( new Property( "radioStationID" , "upnp" ));
580  pObject->AddProperty( new Property( "radioBand" , "upnp" ));
581  pObject->AddProperty( new Property( "channelNr" , "upnp" ));
582 
583  return( pObject );
584 }
585 
587 
588 CDSObject *CDSObject::CreateAudioBook( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
589 {
590  if (pObject == nullptr)
591  {
592  pObject = new CDSObject( sId, sTitle, sParentId );
593  pObject->m_sClass = "object.item.audioItem.audioBook";
594  }
595 
596  CreateAudioItem( sId, sTitle, sParentId, pObject );
597 
598  pObject->AddProperty( new Property( "storageMedium", "upnp" ));
599  pObject->AddProperty( new Property( "producer" , "upnp" ));
600  pObject->AddProperty( new Property( "contributor" , "dc" ));
601 
602  return( pObject );
603 }
604 
606 
607 CDSObject *CDSObject::CreateVideoItem( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
608 {
609  if (pObject == nullptr)
610  {
611  pObject = new CDSObject( sId, sTitle, sParentId );
612  pObject->m_sClass = "object.item.videoItem";
613  }
614 
615  CreateItem( sId, sTitle, sParentId, pObject );
616 
617  pObject->AddProperty( new Property( "genre" , "upnp" ));
618  pObject->AddProperty( new Property( "longDescription", "upnp" ));
619  pObject->AddProperty( new Property( "producer" , "upnp" ));
620  pObject->AddProperty( new Property( "rating" , "upnp" ));
621  pObject->AddProperty( new Property( "actor" , "upnp" ));
622  pObject->AddProperty( new Property( "director" , "upnp" ));
623  pObject->AddProperty( new Property( "episodeNumber" , "upnp" ));
624  pObject->AddProperty( new Property( "episodeCount" , "upnp" ));
625  pObject->AddProperty( new Property( "seriesTitle" , "upnp" ));
626  pObject->AddProperty( new Property( "programTitle" , "upnp" ));
627  pObject->AddProperty( new Property( "description" , "dc" ));
628  pObject->AddProperty( new Property( "publisher" , "dc" ));
629  pObject->AddProperty( new Property( "language" , "dc" ));
630  pObject->AddProperty( new Property( "relation" , "dc" ));
631 
632  pObject->AddProperty( new Property( "creator" , "dc" ));
633  pObject->AddProperty( new Property( "date" , "dc" ));
634 
635  pObject->AddProperty( new Property( "channelID" , "upnp" ));
636  pObject->AddProperty( new Property( "callSign" , "upnp" ));
637  pObject->AddProperty( new Property( "channelNr" , "upnp" ));
638  pObject->AddProperty( new Property( "channelName" , "upnp" ));
639 
640  pObject->AddProperty( new Property( "scheduledStartTime", "upnp" ));
641  pObject->AddProperty( new Property( "scheduledEndTime" , "upnp" ));
642  pObject->AddProperty( new Property( "scheduledDuration" , "upnp" ));
643  pObject->AddProperty( new Property( "srsRecordScheduleID" , "upnp" ));
644  pObject->AddProperty( new Property( "recordedStartDateTime" , "upnp" ));
645  pObject->AddProperty( new Property( "recordedDuration" , "upnp" ));
646  pObject->AddProperty( new Property( "recordedDayOfWeek" , "upnp" ));
647 
648  pObject->AddProperty( new Property( "programID" , "upnp" ));
649  pObject->AddProperty( new Property( "seriesID" , "upnp" ));
650 
651  // Added for Microsoft Media Player Compatibility
652  pObject->AddProperty( new Property( "artist" , "upnp" ));
653  pObject->AddProperty( new Property( "album" , "upnp" ));
654  //
655 
656  pObject->AddProperty( new Property( "albumArtURI", "upnp", false, "", true )); // TN
657  pObject->AddProperty( new Property( "albumArtURI", "upnp", false, "", true )); // SM
658  pObject->AddProperty( new Property( "albumArtURI", "upnp", false, "", true )); // MED
659  pObject->AddProperty( new Property( "albumArtURI", "upnp", false, "", true )); // LRG
660  return( pObject );
661 }
662 
664 
665 CDSObject *CDSObject::CreateMovie( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
666 {
667  if (pObject == nullptr)
668  {
669  pObject = new CDSObject( sId, sTitle, sParentId );
670  pObject->m_sClass = "object.item.videoItem.movie";
671  }
672 
673  CreateVideoItem( sId, sTitle, sParentId, pObject );
674 
675  pObject->AddProperty( new Property( "storageMedium" , "upnp" ));
676  pObject->AddProperty( new Property( "DVDRegionCode" , "upnp" ));
677 
678  return( pObject );
679 }
680 
682 
683 CDSObject *CDSObject::CreateVideoBroadcast( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
684 {
685  if (pObject == nullptr)
686  {
687  pObject = new CDSObject( sId, sTitle, sParentId );
688  pObject->m_sClass = "object.item.videoItem.videoBroadcast";
689  }
690 
691  CreateVideoItem( sId, sTitle, sParentId, pObject );
692 
693  pObject->AddProperty( new Property( "icon" , "upnp" ));
694  pObject->AddProperty( new Property( "region" , "upnp" ));
695 
696  return( pObject );
697 }
698 
700 
701 CDSObject *CDSObject::CreateMusicVideoClip( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
702 {
703  if (pObject == nullptr)
704  {
705  pObject = new CDSObject( sId, sTitle, sParentId );
706  pObject->m_sClass = "object.item.videoItem.musicVideoClip";
707  }
708 
709  CreateVideoItem( sId, sTitle, sParentId, pObject );
710 
711  pObject->AddProperty( new Property( "artist" , "upnp" ));
712  pObject->AddProperty( new Property( "storageMedium" , "upnp" ));
713  pObject->AddProperty( new Property( "album" , "upnp" ));
714  pObject->AddProperty( new Property( "contributor" , "dc" ));
715 
716  return( pObject );
717 }
718 
720 
721 CDSObject *CDSObject::CreateImageItem( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
722 {
723  if (pObject == nullptr)
724  {
725  pObject = new CDSObject( sId, sTitle, sParentId );
726  pObject->m_sClass = "object.item.imageItem";
727  }
728 
729  CreateItem( sId, sTitle, sParentId, pObject );
730 
731  pObject->AddProperty( new Property( "longDescription", "upnp" ));
732  pObject->AddProperty( new Property( "storageMedium" , "upnp" ));
733  pObject->AddProperty( new Property( "rating" , "upnp" ));
734  pObject->AddProperty( new Property( "description" , "dc" ));
735  pObject->AddProperty( new Property( "publisher" , "dc" ));
736  pObject->AddProperty( new Property( "rights" , "dc" ));
737 
738  pObject->AddProperty( new Property( "creator" , "dc" ));
739  pObject->AddProperty( new Property( "date" , "dc" ));
740 
741  return( pObject );
742 }
743 
745 
746 CDSObject *CDSObject::CreatePhoto( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
747 {
748  if (pObject == nullptr)
749  {
750  pObject = new CDSObject( sId, sTitle, sParentId );
751  pObject->m_sClass = "object.item.imageItem.photo";
752  }
753 
754  CreateImageItem( sId, sTitle, sParentId, pObject );
755 
756  pObject->AddProperty( new Property( "album", "upnp" ));
757 
758  return( pObject );
759 }
760 
762 
763 CDSObject *CDSObject::CreatePlaylistItem ( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
764 {
765  if (pObject == nullptr)
766  {
767  pObject = new CDSObject( sId, sTitle, sParentId );
768  pObject->m_sClass = "object.item.playlistItem";
769  }
770 
771  CreateItem( sId, sTitle, sParentId, pObject );
772 
773  pObject->AddProperty( new Property( "artist" , "upnp" ));
774  pObject->AddProperty( new Property( "genre" , "upnp" ));
775  pObject->AddProperty( new Property( "longDescription", "upnp" ));
776  pObject->AddProperty( new Property( "storageMedium" , "upnp" ));
777  pObject->AddProperty( new Property( "description" , "dc" ));
778  pObject->AddProperty( new Property( "language" , "dc" ));
779 
780  return( pObject );
781 }
782 
784 
785 CDSObject *CDSObject::CreateTextItem( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
786 {
787  if (pObject == nullptr)
788  {
789  pObject = new CDSObject( sId, sTitle, sParentId );
790  pObject->m_sClass = "object.item.textItem";
791  }
792 
793  CreateItem( sId, sTitle, sParentId, pObject );
794 
795  pObject->AddProperty( new Property( "author" , "upnp" ));
796  pObject->AddProperty( new Property( "protection" , "upnp" ));
797  pObject->AddProperty( new Property( "longDescription", "upnp" ));
798  pObject->AddProperty( new Property( "storageMedium" , "upnp" ));
799  pObject->AddProperty( new Property( "rating" , "upnp" ));
800  pObject->AddProperty( new Property( "description" , "dc" ));
801  pObject->AddProperty( new Property( "publisher" , "dc" ));
802  pObject->AddProperty( new Property( "contributor" , "dc" ));
803  pObject->AddProperty( new Property( "relation" , "dc" ));
804  pObject->AddProperty( new Property( "language" , "dc" ));
805  pObject->AddProperty( new Property( "rights" , "dc" ));
806 
807  return( pObject );
808 }
809 
811 
812 CDSObject *CDSObject::CreateAlbum( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
813 {
814  if (pObject == nullptr)
815  {
816  pObject = new CDSObject( sId, sTitle, sParentId );
817  pObject->m_sClass = "object.container.album";
818  }
819 
820  CreateContainer( sId, sTitle, sParentId, pObject );
821 
822  pObject->AddProperty( new Property( "storageMedium" , "upnp" ));
823  pObject->AddProperty( new Property( "publisher" , "dc" ));
824  pObject->AddProperty( new Property( "contributor" , "dc" ));
825  pObject->AddProperty( new Property( "relation" , "dc" ));
826  pObject->AddProperty( new Property( "rights" , "dc" ));
827 
828  // Artwork
829  pObject->AddProperty( new Property( "albumArtURI", "upnp", false, "", true)); // TN
830  pObject->AddProperty( new Property( "albumArtURI", "upnp", false, "", true)); // SM
831  pObject->AddProperty( new Property( "albumArtURI", "upnp", false, "", true)); // MED
832  pObject->AddProperty( new Property( "albumArtURI", "upnp", false, "", true)); // LRG
833 
834  return( pObject );
835 }
836 
838 
839 CDSObject *CDSObject::CreateMusicAlbum( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
840 {
841  if (pObject == nullptr)
842  {
843  pObject = new CDSObject( sId, sTitle, sParentId );
844  pObject->m_sClass = "object.container.album.musicAlbum";
845  }
846 
847  CreateAlbum( sId, sTitle, sParentId, pObject );
848 
849  pObject->AddProperty( new Property( "artist" , "upnp" ));
850  pObject->AddProperty( new Property( "genre" , "upnp" ));
851  pObject->AddProperty( new Property( "producer" , "upnp" ));
852  pObject->AddProperty( new Property( "toc" , "upnp" ));
853 
854  return( pObject );
855 }
856 
858 
859 CDSObject *CDSObject::CreatePhotoAlbum( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
860 {
861  if (pObject == nullptr)
862  {
863  pObject = new CDSObject( sId, sTitle, sParentId );
864  pObject->m_sClass = "object.container.album.photoAlbum";
865  }
866 
867  CreateAlbum( sId, sTitle, sParentId, pObject );
868 
869  return( pObject );
870 }
871 
873 
874 CDSObject *CDSObject::CreateGenre( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
875 {
876  if (pObject == nullptr)
877  {
878  pObject = new CDSObject( sId, sTitle, sParentId );
879  pObject->m_sClass = "object.container.genre";
880  }
881 
882  CreateContainer( sId, sTitle, sParentId, pObject );
883 
884  return( pObject );
885 }
886 
888 
889 CDSObject *CDSObject::CreateMusicGenre( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
890 {
891  if (pObject == nullptr)
892  {
893  pObject = new CDSObject( sId, sTitle, sParentId );
894  pObject->m_sClass = "object.container.genre.musicGenre";
895  }
896 
897  CreateGenre( sId, sTitle, sParentId, pObject );
898 
899  return( pObject );
900 }
901 
903 
904 CDSObject *CDSObject::CreateMovieGenre( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
905 {
906  if (pObject == nullptr)
907  {
908  pObject = new CDSObject( sId, sTitle, sParentId );
909  pObject->m_sClass = "object.container.genre.movieGenre";
910  }
911 
912  CreateGenre( sId, sTitle, sParentId, pObject );
913 
914  return( pObject );
915 }
916 
918 
919 CDSObject *CDSObject::CreatePlaylistContainer( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
920 {
921  if (pObject == nullptr)
922  {
923  pObject = new CDSObject( sId, sTitle, sParentId );
924  pObject->m_sClass = "object.container.playlistContainer";
925  }
926 
927  CreateContainer( sId, sTitle, sParentId, pObject );
928 
929  pObject->AddProperty( new Property( "artist" , "upnp" ));
930  pObject->AddProperty( new Property( "genre" , "upnp" ));
931  pObject->AddProperty( new Property( "producer" , "upnp" ));
932  pObject->AddProperty( new Property( "storageMedium" , "upnp" ));
933  pObject->AddProperty( new Property( "contributor" , "dc" ));
934  pObject->AddProperty( new Property( "language" , "dc" ));
935  pObject->AddProperty( new Property( "rights" , "dc" ));
936 
937  return( pObject );
938 }
939 
941 
942 CDSObject *CDSObject::CreatePerson( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
943 {
944  if (pObject == nullptr)
945  {
946  pObject = new CDSObject( sId, sTitle, sParentId );
947  pObject->m_sClass = "object.container.person";
948  }
949 
950  CreateContainer( sId, sTitle, sParentId, pObject );
951 
952  pObject->AddProperty( new Property( "language", "dc" ));
953 
954  return( pObject );
955 }
956 
958 
959 CDSObject *CDSObject::CreateMusicArtist( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
960 {
961  if (pObject == nullptr)
962  {
963  pObject = new CDSObject( sId, sTitle, sParentId );
964  pObject->m_sClass = "object.container.person.musicArtist";
965  }
966 
967  CreatePerson( sId, sTitle, sParentId, pObject );
968 
969  pObject->AddProperty( new Property( "genre" , "upnp" ));
970  pObject->AddProperty( new Property( "artistDiscographyURI", "upnp" ));
971 
972  return( pObject );
973 }
974 
976 
977 CDSObject *CDSObject::CreateStorageSystem( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
978 {
979  if (pObject == nullptr)
980  {
981  pObject = new CDSObject( sId, sTitle, sParentId );
982  pObject->m_sClass = "object.container.storageSystem";
983  }
984 
985  CreateContainer( sId, sTitle, sParentId, pObject );
986 
987  pObject->AddProperty( new Property( "storageTotal" , "upnp", true, "-1" ));
988  pObject->AddProperty( new Property( "storageUsed" , "upnp", true, "-1" ));
989  pObject->AddProperty( new Property( "storageFree" , "upnp", true, "-1" ));
990  pObject->AddProperty( new Property( "storageMaxPartition", "upnp", true, "-1" ));
991  pObject->AddProperty( new Property( "storageMedium" , "upnp", true, "HDD" ));
992 
993  return( pObject );
994 }
995 
997 
998 CDSObject *CDSObject::CreateStorageVolume( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
999 {
1000  if (pObject == nullptr)
1001  {
1002  pObject = new CDSObject( sId, sTitle, sParentId );
1003  pObject->m_sClass = "object.container.storageVolume";
1004  }
1005 
1006  CreateContainer( sId, sTitle, sParentId, pObject );
1007 
1008  pObject->AddProperty( new Property( "storageTotal" , "upnp", true, "-1" ));
1009  pObject->AddProperty( new Property( "storageUsed" , "upnp", true, "-1" ));
1010  pObject->AddProperty( new Property( "storageFree" , "upnp", true, "-1" ));
1011  pObject->AddProperty( new Property( "storageMedium", "upnp", true, "HDD" ));
1012 
1013  return( pObject );
1014 }
1015 
1017 
1018 CDSObject *CDSObject::CreateStorageFolder( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
1019 {
1020  if (pObject == nullptr)
1021  {
1022  pObject = new CDSObject( sId, sTitle, sParentId );
1023  pObject->m_sClass = "object.container.storageFolder";
1024  }
1025 
1026  CreateContainer( sId, sTitle, sParentId, pObject );
1027 
1028  pObject->AddProperty( new Property( "storageUsed", "upnp", true, "-1" ));
1029 
1030  return( pObject );
1031 }
1032 
1033 bool CDSObject::FilterContains(const FilterMap &filter, const QString& name)
1034 {
1035  // ContentDirectory Service, 2013 UPnP Forum
1036  // 2.3.18 A_ARG_TYPE_Filter
1037 
1038  // Exact match
1039  if (filter.contains(name, Qt::CaseInsensitive))
1040  return true;
1041 
1042  // # signfies that this property and all it's children must be returned
1043  // This is presently implemented higher up to save time
1044 
1045  // If an attribute is required then it's parent must also be returned
1046  QString dependentAttribute = QString("%1@").arg(name);
1047  QStringList matches = filter.filter(name, Qt::CaseInsensitive);
1048  QStringList::iterator it;
1049  for (it = matches.begin(); it != matches.end(); ++it)
1050  {
1051  if ((*it).startsWith(dependentAttribute))
1052  return true;
1053  }
1054 
1055  return false;
1056 }
1057 
CDSObject::CreateMusicGenre
static CDSObject * CreateMusicGenre(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Definition: upnpcdsobjects.cpp:889
CDSObject::CreateStorageVolume
static CDSObject * CreateStorageVolume(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Definition: upnpcdsobjects.cpp:998
CDSObject::GetProperties
QList< Property * > GetProperties(const QString &sName)
Definition: upnpcdsobjects.cpp:97
Property::m_sName
QString m_sName
Definition: upnpcdsobjects.h:51
HTTPRequest
Definition: httprequest.h:109
CDSObject::m_children
CDSObjects m_children
Definition: upnpcdsobjects.h:215
OT_Container
@ OT_Container
Definition: upnpcdsobjects.h:38
CDSObject::CreateTextItem
static CDSObject * CreateTextItem(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Definition: upnpcdsobjects.cpp:785
CDSObject::m_sTitle
QString m_sTitle
Definition: upnpcdsobjects.h:197
false
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:89
CDSObject
Definition: upnpcdsobjects.h:186
CDSObject::GetChildContainerCount
uint32_t GetChildContainerCount(void) const
Return the number of child containers in this container.
Definition: upnpcdsobjects.cpp:245
CDSObject::CreateGenre
static CDSObject * CreateGenre(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Definition: upnpcdsobjects.cpp:874
Resource
Definition: upnpcdsobjects.h:105
CDSObject::m_nChildCount
uint32_t m_nChildCount
Definition: upnpcdsobjects.h:216
CDSObject::CreateMusicVideoClip
static CDSObject * CreateMusicVideoClip(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Definition: upnpcdsobjects.cpp:701
CDSObject::CreateVideoBroadcast
static CDSObject * CreateVideoBroadcast(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Definition: upnpcdsobjects.cpp:683
CDSObject::m_nChildContainerCount
uint32_t m_nChildContainerCount
Definition: upnpcdsobjects.h:217
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
CDSObject::CreateMovie
static CDSObject * CreateMovie(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Definition: upnpcdsobjects.cpp:665
CDSObject::FilterContains
static bool FilterContains(const FilterMap &filter, const QString &name)
Definition: upnpcdsobjects.cpp:1033
upnpcds.h
CDSObject::SetChildContainerCount
void SetChildContainerCount(uint32_t nCount)
Allows the caller to set childContainerCount without having to load children.
Definition: upnpcdsobjects.cpp:255
CDSObject::m_sParentId
QString m_sParentId
Definition: upnpcdsobjects.h:196
Property
Definition: upnpcdsobjects.h:47
CDSObject::CreatePhoto
static CDSObject * CreatePhoto(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Definition: upnpcdsobjects.cpp:746
CDSObject::CreateAudioBroadcast
static CDSObject * CreateAudioBroadcast(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Definition: upnpcdsobjects.cpp:567
FilterMap
QMap< uint, int > FilterMap
Definition: ExternalSignalMonitor.h:17
Property::m_bMultiValue
bool m_bMultiValue
Definition: upnpcdsobjects.h:54
mythlogging.h
CDSObject::CreatePhotoAlbum
static CDSObject * CreatePhotoAlbum(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Definition: upnpcdsobjects.cpp:859
GetBool
QString GetBool(bool bVal)
Definition: upnpcdsobjects.cpp:26
CDSObject::SetPropValue
void SetPropValue(const QString &sName, const QString &sValue, const QString &type="")
Definition: upnpcdsobjects.cpp:115
CDSObject::m_bSearchable
bool m_bSearchable
Definition: upnpcdsobjects.h:200
CDSObject::m_bRestricted
bool m_bRestricted
Definition: upnpcdsobjects.h:199
CDSObject::~CDSObject
~CDSObject() override
Definition: upnpcdsobjects.cpp:50
CDSObject::SetChildCount
void SetChildCount(uint32_t nCount)
Allows the caller to set childCount without having to load children.
Definition: upnpcdsobjects.cpp:232
CDSObject::CreatePlaylistItem
static CDSObject * CreatePlaylistItem(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Definition: upnpcdsobjects.cpp:763
CDSObject::CreatePerson
static CDSObject * CreatePerson(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Definition: upnpcdsobjects.cpp:942
CDSObject::AddChild
CDSObject * AddChild(CDSObject *pChild)
Definition: upnpcdsobjects.cpp:165
CDSObject::m_sId
QString m_sId
Definition: upnpcdsobjects.h:195
CDSObject::CreateMusicTrack
static CDSObject * CreateMusicTrack(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Definition: upnpcdsobjects.cpp:525
CDSObject::CreateStorageSystem
static CDSObject * CreateStorageSystem(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Definition: upnpcdsobjects.cpp:977
CDSObject::CDSObject
CDSObject(const QString &sId="-1", const QString &sTitle="", const QString &sParentId="-1")
Definition: upnpcdsobjects.cpp:36
CDSObject::AddProperty
Property * AddProperty(Property *pProp)
Definition: upnpcdsobjects.cpp:75
CDSObject::AddResource
Resource * AddResource(const QString &sProtocol, const QString &sURI)
Definition: upnpcdsobjects.cpp:205
CDSObject::CreateAudioBook
static CDSObject * CreateAudioBook(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Definition: upnpcdsobjects.cpp:588
CDSObject::CreateImageItem
static CDSObject * CreateImageItem(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Definition: upnpcdsobjects.cpp:721
CDSObject::CreatePlaylistContainer
static CDSObject * CreatePlaylistContainer(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Definition: upnpcdsobjects.cpp:919
CDSObject::CreateVideoItem
static CDSObject * CreateVideoItem(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Definition: upnpcdsobjects.cpp:607
CDSObject::CreateContainer
static CDSObject * CreateContainer(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Definition: upnpcdsobjects.cpp:472
CDSObject::m_properties
Properties m_properties
Definition: upnpcdsobjects.h:214
CDSObject::m_sClass
QString m_sClass
Definition: upnpcdsobjects.h:198
CDSObject::CreateAlbum
static CDSObject * CreateAlbum(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Definition: upnpcdsobjects.cpp:812
CDSObject::CreateMusicAlbum
static CDSObject * CreateMusicAlbum(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Definition: upnpcdsobjects.cpp:839
CDSObject::toXml
QString toXml(FilterMap &filter, bool ignoreChildren=false) const
Definition: upnpcdsobjects.cpp:264
CDSObject::CreateAudioItem
static CDSObject * CreateAudioItem(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Definition: upnpcdsobjects.cpp:499
CDSObject::m_resources
Resources m_resources
Definition: upnpcdsobjects.h:219
CDSObject::CreateItem
static CDSObject * CreateItem(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Definition: upnpcdsobjects.cpp:454
CDSObject::GetChildCount
uint32_t GetChildCount(void) const
Return the number of children in this container.
Definition: upnpcdsobjects.cpp:219
ReferenceCounter::IncrRef
virtual int IncrRef(void)
Increments reference count.
Definition: referencecounter.cpp:101
OT_Item
@ OT_Item
Definition: upnpcdsobjects.h:39
CDSObject::GetChild
CDSObject * GetChild(const QString &sID)
Definition: upnpcdsobjects.cpp:184
CDSObject::CreateMovieGenre
static CDSObject * CreateMovieGenre(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Definition: upnpcdsobjects.cpp:904
CDSObject::m_eType
ObjectTypes m_eType
Definition: upnpcdsobjects.h:191
ReferenceCounter
General purpose reference counter.
Definition: referencecounter.h:26
CDSObject::CreateMusicArtist
static CDSObject * CreateMusicArtist(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Definition: upnpcdsobjects.cpp:959
CDSObject::GetPropValue
QString GetPropValue(const QString &sName) const
Definition: upnpcdsobjects.cpp:143
CDSObject::CreateStorageFolder
static CDSObject * CreateStorageFolder(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Definition: upnpcdsobjects.cpp:1018