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