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