MythTV master
upnpcdsobjects.cpp
Go to the documentation of this file.
1
2// 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#include "upnpcdsobjects.h"
13
14#include <QtGlobal>
15#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
16#include <QStringConverter>
17#else
18#include <QTextCodec>
19#endif
20#include <QTextStream>
21#include <QUrl>
22
24
25inline QString GetBool( bool bVal ) { return( (bVal) ? "1" : "0" ); }
26
29//
30//
31//
34
35CDSObject::CDSObject( const QString &sId,
36 const QString &sTitle,
37 const QString &sParentId )
38 : ReferenceCounter("CDSObject", false),
39 m_sId(HTTPRequest::Encode(sId)),
40 m_sParentId(HTTPRequest::Encode(sParentId)),
41 m_sTitle(HTTPRequest::Encode(sTitle))
42{
43}
44
46//
48
50{
51 while (!m_resources.empty())
52 {
53 delete m_resources.takeLast();
54 }
55
56 while (!m_children.empty())
57 {
58 m_children.takeLast()->DecrRef();
59 }
60
61 // NOLINTNEXTLINE(modernize-loop-convert)
62 for (auto it = m_properties.begin(); it != m_properties.end(); ++it)
63 {
64 delete *it;
65 *it = nullptr;
66 }
67 m_properties.clear();
68}
69
71//
73
75{
76 if (pProp)
77 {
78 // If this property is allowed multiple times in an object
79 // e.g. Different sizes of artwork, then just insert it
80 // Otherwise remove all existing instances of this property first
81 // NOTE: This requires ALL instances of a property which can exist
82 // more than once to have m_bAllowMulti set to true.
83 if (pProp->m_bMultiValue)
84 m_properties.insert(pProp->m_sName, pProp);
85 else
86 m_properties.replace(pProp->m_sName, pProp);
87 }
88
89 return pProp;
90}
91
93//
95
96QList<Property*> CDSObject::GetProperties( const QString &sName )
97{
98 QList<Property*> props;
99 Properties::iterator it = m_properties.find(sName);
100 while (it != m_properties.end() && it.key() == sName)
101 {
102 if (*it)
103 props.append(*it);
104 ++it;
105 }
106
107 return props;
108}
109
111//
113
114void CDSObject::SetPropValue( const QString &sName, const QString &sValue,
115 const QString &sType )
116{
117 Properties::iterator it = m_properties.find(sName);
118 if (it != m_properties.end() && *it)
119 {
120 if ((*it)->m_bMultiValue)
121 {
122 LOG(VB_UPNP, LOG_WARNING,
123 QString("SetPropValue(%1) called on property with bAllowMulti. "
124 "Only the last inserted property will be updated.").arg(sName));
125 }
126 (*it)->SetValue(sValue);
127
128 if (!sType.isEmpty())
129 (*it)->AddAttribute( "type", sType );
130 }
131 else
132 {
133 LOG(VB_UPNP, LOG_WARNING,
134 QString("SetPropValue(%1) called with non-existent property.").arg(sName));
135 }
136}
137
139//
141
142QString CDSObject::GetPropValue(const QString &sName) const
143{
144 Properties::const_iterator it = m_properties.find(sName);
145
146 if (it != m_properties.end() && *it)
147 {
148 if ((*it)->m_bMultiValue)
149 {
150 LOG(VB_UPNP, LOG_WARNING,
151 QString("GetPropValue(%1) called on property with bAllowMulti. "
152 "Only the last inserted property will be return."));
153 }
154 return (*it)->GetValue().toUtf8();
155 }
156
157 return "";
158}
159
161//
163
165{
166 if (pChild && !m_children.contains(pChild))
167 {
168 pChild->IncrRef();
170 if (pChild->m_eType == OT_Container)
172 pChild->m_sParentId = m_sId;
173 m_children.append( pChild );
174 }
175
176 return( pChild );
177}
178
180//
182
183CDSObject *CDSObject::GetChild( const QString &sID )
184{
185 CDSObject *pChild = nullptr;
186 CDSObjects::iterator it;
187 for (it = m_children.begin(); it != m_children.end(); ++it)
188 {
189 pChild = *it;
190 if (!pChild)
191 continue;
192
193 if (pChild->m_sId == sID)
194 return pChild;
195 }
196
197 return nullptr;
198}
199
201//
203
204Resource *CDSObject::AddResource( const QString& sProtocol, const QString& sURI )
205{
206 auto *pRes = new Resource( sProtocol, sURI );
207
208 m_resources.append( pRes );
209
210 return( pRes );
211}
212
213
218uint32_t CDSObject::GetChildCount(void) const
219{
220 uint32_t nCount = m_children.count();
221 if (nCount == 0)
222 return( m_nChildCount );
223
224 return( nCount );
225}
226
231void CDSObject::SetChildCount( uint32_t nCount )
232{
233 m_nChildCount = nCount;
234}
235
245{
247}
248
255{
256 m_nChildContainerCount = nCount;
257}
258
260//
262
264 bool ignoreChildren ) const
265{
266 QString sXML;
267 QTextStream os( &sXML, QIODevice::WriteOnly );
268#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
269 os.setCodec(QTextCodec::codecForName("UTF-8"));
270#else
271 os.setEncoding(QStringConverter::Utf8);
272#endif
273 toXml(os, filter, ignoreChildren);
274 os << Qt::flush;
275 return( sXML );
276}
277
279//
281
282void CDSObject::toXml( QTextStream &os, FilterMap &filter,
283 bool ignoreChildren ) const
284{
285 QString sEndTag = "";
286
311 bool bFilter = true;
312
313 if (filter.contains("*"))
314 bFilter = false;
315
316 switch( m_eType )
317 {
318 case OT_Container:
319 {
320 if (bFilter && filter.contains("container#"))
321 bFilter = false;
322
323 os << "<container id=\"" << m_sId
324 << "\" parentID=\"" << m_sParentId
325 << "\" restricted=\"" << GetBool( m_bRestricted );
326
327 if (!bFilter || filter.contains("@searchable"))
328 os << "\" searchable=\"" << GetBool( m_bSearchable );
329
330 if (!bFilter || filter.contains("@childCount"))
331 os << "\" childCount=\"" << GetChildCount();
332
333 if (!bFilter || filter.contains("@childContainerCount"))
334 os << "\" childContainerCount=\"" << GetChildContainerCount();
335
336 os << "\" >" << Qt::endl;
337
338 sEndTag = "</container>";
339
340 break;
341 }
342 case OT_Item:
343 {
344 if (bFilter && filter.contains("item#"))
345 bFilter = false;
346
347 os << "<item id=\"" << m_sId
348 << "\" parentID=\"" << m_sParentId
349 << "\" restricted=\"" << GetBool( m_bRestricted )
350 << "\" >" << Qt::endl;
351
352 sEndTag = "</item>";
353
354 break;
355 }
356 default: break;
357 }
358
359 os << "<dc:title>" << m_sTitle << "</dc:title>" << Qt::endl;
360 os << "<upnp:class>" << m_sClass << "</upnp:class>" << Qt::endl;
361
362 // ----------------------------------------------------------------------
363 // Output all Properties
364 // ----------------------------------------------------------------------
365
366 for (auto *pProp : std::as_const(m_properties))
367 {
368 if (pProp->m_bRequired || (!pProp->GetValue().isEmpty()))
369 {
370 QString sName;
371
372 if (!pProp->m_sNameSpace.isEmpty())
373 sName = pProp->m_sNameSpace + ':' + pProp->m_sName;
374 else
375 sName = pProp->m_sName;
376
377 if (pProp->m_bRequired ||
378 (!bFilter) ||
379 FilterContains(filter, sName))
380 {
381 bool filterAttributes = true;
382 if (!bFilter || filter.contains(QString("%1#").arg(sName)))
383 filterAttributes = false;
384
385 os << "<" << sName;
386
387 for (const auto & attr : std::as_const(pProp->m_lstAttributes))
388 {
389 QString filterName = QString("%1@%2").arg(sName,
390 attr.m_sName);
391 if (attr.m_bRequired || !filterAttributes ||
392 filter.contains(filterName))
393 os << " " << attr.m_sName << "=\"" << attr.m_sValue << "\"";
394 }
395
396 os << ">";
397 os << pProp->GetEncodedValue();
398 os << "</" << sName << ">" << Qt::endl;
399 }
400 }
401 }
402
403 // ----------------------------------------------------------------------
404 // Output any Res Elements
405 // ----------------------------------------------------------------------
406
407 if (!bFilter || filter.contains("res"))
408 {
409 bool filterAttributes = true;
410 if (!bFilter || filter.contains("res#"))
411 filterAttributes = false;
412 for (auto *resource : std::as_const(m_resources))
413 {
414 os << "<res protocolInfo=\"" << resource->m_sProtocolInfo << "\" ";
415
416 QString filterName;
417 for (const auto & attr : std::as_const(resource->m_lstAttributes))
418 {
419 filterName = QString("res@%1").arg(attr.m_sName);
420 if (attr.m_bRequired || !filterAttributes ||
421 filter.contains(filterName))
422 os << attr.m_sName << "=\"" << attr.m_sValue << "\" ";
423 }
424
425 os << ">" << resource->m_sURI;
426 os << "</res>" << Qt::endl;
427 }
428 }
429
430 // ----------------------------------------------------------------------
431 // Output any children
432 // ----------------------------------------------------------------------
433
434 if (!ignoreChildren)
435 {
436 for (auto *cit : m_children)
437 cit->toXml(os, filter);
438 }
439
440 // ----------------------------------------------------------------------
441 // Close Element Tag
442 // ----------------------------------------------------------------------
443
444 os << sEndTag << Qt::endl;
445 os << Qt::flush;
446}
447
448
450//
452
453CDSObject *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
471CDSObject *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
498CDSObject *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
524CDSObject *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
566CDSObject *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
587CDSObject *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
606CDSObject *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
664CDSObject *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
682CDSObject *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
700CDSObject *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
720CDSObject *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
745CDSObject *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
762CDSObject *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
784CDSObject *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
811CDSObject *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
838CDSObject *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
858CDSObject *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
873CDSObject *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
888CDSObject *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
903CDSObject *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
918CDSObject *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
941CDSObject *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
958CDSObject *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
976CDSObject *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
997CDSObject *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
1017CDSObject *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
1032bool CDSObject::FilterContains(const FilterMap &filter, const QString& name)
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
QMap< uint, int > FilterMap
static CDSObject * CreateContainer(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
CDSObjects m_children
uint32_t GetChildCount(void) const
Return the number of children in this container.
static CDSObject * CreateVideoBroadcast(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
static CDSObject * CreateMusicArtist(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
static CDSObject * CreateImageItem(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
CDSObject(const QString &sId="-1", const QString &sTitle="", const QString &sParentId="-1")
void SetChildCount(uint32_t nCount)
Allows the caller to set childCount without having to load children.
static CDSObject * CreateVideoItem(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
QString m_sParentId
static CDSObject * CreateMovie(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
static CDSObject * CreatePhoto(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
static CDSObject * CreateMusicTrack(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
static CDSObject * CreateAudioItem(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Resources m_resources
QString toXml(FilterMap &filter, bool ignoreChildren=false) const
static CDSObject * CreatePerson(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
static CDSObject * CreateGenre(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
QString m_sClass
static CDSObject * CreateMusicVideoClip(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Resource * AddResource(const QString &sProtocol, const QString &sURI)
bool m_bSearchable
CDSObject * AddChild(CDSObject *pChild)
QString m_sTitle
static CDSObject * CreatePhotoAlbum(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
static CDSObject * CreateAlbum(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)
static CDSObject * CreateItem(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
uint32_t m_nChildContainerCount
static CDSObject * CreateMovieGenre(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
ObjectTypes m_eType
CDSObject * GetChild(const QString &sID)
static CDSObject * CreateAudioBook(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
uint32_t m_nChildCount
uint32_t GetChildContainerCount(void) const
Return the number of child containers in this container.
void SetPropValue(const QString &sName, const QString &sValue, const QString &type="")
QList< Property * > GetProperties(const QString &sName)
static CDSObject * CreateAudioBroadcast(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Property * AddProperty(Property *pProp)
QString m_sId
~CDSObject() override
QString GetPropValue(const QString &sName) const
static bool FilterContains(const FilterMap &filter, const QString &name)
void SetChildContainerCount(uint32_t nCount)
Allows the caller to set childContainerCount without having to load children.
static CDSObject * CreatePlaylistContainer(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Properties m_properties
static CDSObject * CreatePlaylistItem(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
bool m_bRestricted
static CDSObject * CreateStorageVolume(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)
static CDSObject * CreateMusicAlbum(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)
static CDSObject * CreateStorageFolder(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
bool m_bMultiValue
QString m_sName
General purpose reference counter.
virtual int IncrRef(void)
Increments reference count.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
QString GetBool(bool bVal)
@ OT_Item
@ OT_Container
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:89