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