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(QUrl::toPercentEncoding(sId)),
40 m_sParentId(QUrl::toPercentEncoding(sParentId)),
41 m_sTitle(QUrl::toPercentEncoding(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#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
268 QTextStream os( &sXML, QIODevice::WriteOnly );
269 os.setCodec(QTextCodec::codecForName("UTF-8"));
270#else
271 QTextStream os(&sXML, QIODeviceBase::WriteOnly);
272 os.setEncoding(QStringConverter::Utf8);
273#endif
274 toXml(os, filter, ignoreChildren);
275 os << Qt::flush;
276 return( sXML );
277}
278
280//
282
283void CDSObject::toXml( QTextStream &os, FilterMap &filter,
284 bool ignoreChildren ) const
285{
286 QString sEndTag = "";
287
312 bool bFilter = true;
313
314 if (filter.contains("*"))
315 bFilter = false;
316
317 switch( m_eType )
318 {
319 case OT_Container:
320 {
321 if (bFilter && filter.contains("container#"))
322 bFilter = false;
323
324 os << "<container id=\"" << m_sId
325 << "\" parentID=\"" << m_sParentId
326 << "\" restricted=\"" << GetBool( m_bRestricted );
327
328 if (!bFilter || filter.contains("@searchable"))
329 os << "\" searchable=\"" << GetBool( m_bSearchable );
330
331 if (!bFilter || filter.contains("@childCount"))
332 os << "\" childCount=\"" << GetChildCount();
333
334 if (!bFilter || filter.contains("@childContainerCount"))
335 os << "\" childContainerCount=\"" << GetChildContainerCount();
336
337 os << "\" >" << Qt::endl;
338
339 sEndTag = "</container>";
340
341 break;
342 }
343 case OT_Item:
344 {
345 if (bFilter && filter.contains("item#"))
346 bFilter = false;
347
348 os << "<item id=\"" << m_sId
349 << "\" parentID=\"" << m_sParentId
350 << "\" restricted=\"" << GetBool( m_bRestricted )
351 << "\" >" << Qt::endl;
352
353 sEndTag = "</item>";
354
355 break;
356 }
357 default: break;
358 }
359
360 os << "<dc:title>" << m_sTitle << "</dc:title>" << Qt::endl;
361 os << "<upnp:class>" << m_sClass << "</upnp:class>" << Qt::endl;
362
363 // ----------------------------------------------------------------------
364 // Output all Properties
365 // ----------------------------------------------------------------------
366
367 for (auto *pProp : std::as_const(m_properties))
368 {
369 if (pProp->m_bRequired || (!pProp->GetValue().isEmpty()))
370 {
371 QString sName;
372
373 if (!pProp->m_sNameSpace.isEmpty())
374 sName = pProp->m_sNameSpace + ':' + pProp->m_sName;
375 else
376 sName = pProp->m_sName;
377
378 if (pProp->m_bRequired ||
379 (!bFilter) ||
380 FilterContains(filter, sName))
381 {
382 bool filterAttributes = true;
383 if (!bFilter || filter.contains(QString("%1#").arg(sName)))
384 filterAttributes = false;
385
386 os << "<" << sName;
387
388 for (const auto & attr : std::as_const(pProp->m_lstAttributes))
389 {
390 QString filterName = QString("%1@%2").arg(sName,
391 attr.m_sName);
392 if (attr.m_bRequired || !filterAttributes ||
393 filter.contains(filterName))
394 os << " " << attr.m_sName << "=\"" << attr.m_sValue << "\"";
395 }
396
397 os << ">";
398 os << pProp->GetEncodedValue();
399 os << "</" << sName << ">" << Qt::endl;
400 }
401 }
402 }
403
404 // ----------------------------------------------------------------------
405 // Output any Res Elements
406 // ----------------------------------------------------------------------
407
408 if (!bFilter || filter.contains("res"))
409 {
410 bool filterAttributes = true;
411 if (!bFilter || filter.contains("res#"))
412 filterAttributes = false;
413 for (auto *resource : std::as_const(m_resources))
414 {
415 os << "<res protocolInfo=\"" << resource->m_sProtocolInfo << "\" ";
416
417 QString filterName;
418 for (const auto & attr : std::as_const(resource->m_lstAttributes))
419 {
420 filterName = QString("res@%1").arg(attr.m_sName);
421 if (attr.m_bRequired || !filterAttributes ||
422 filter.contains(filterName))
423 os << attr.m_sName << "=\"" << attr.m_sValue << "\" ";
424 }
425
426 os << ">" << resource->m_sURI;
427 os << "</res>" << Qt::endl;
428 }
429 }
430
431 // ----------------------------------------------------------------------
432 // Output any children
433 // ----------------------------------------------------------------------
434
435 if (!ignoreChildren)
436 {
437 for (auto *cit : m_children)
438 cit->toXml(os, filter);
439 }
440
441 // ----------------------------------------------------------------------
442 // Close Element Tag
443 // ----------------------------------------------------------------------
444
445 os << sEndTag << Qt::endl;
446 os << Qt::flush;
447}
448
449
451//
453
454CDSObject *CDSObject::CreateItem( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
455{
456 if (pObject == nullptr)
457 {
458 pObject = new CDSObject( sId, sTitle, sParentId );
459 pObject->m_sClass = "object.item";
460 }
461
462 pObject->m_eType = OT_Item;
463 pObject->m_bSearchable = false; // UPnP - CDS B.1.5 @searchable
464
465 pObject->AddProperty( new Property( "refID" ) );
466
467 return( pObject );
468}
469
471
472CDSObject *CDSObject::CreateContainer( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
473{
474 if (pObject == nullptr)
475 {
476 pObject = new CDSObject( sId, sTitle, sParentId );
477 pObject->m_sClass = "object.container";
478 }
479
480 pObject->m_eType = OT_Container;
481 pObject->m_bSearchable = true; // DLNA requirement - 7.4.3.5.9
482
483 pObject->AddProperty( new Property( "childCount" ));
484 pObject->AddProperty( new Property( "createClass" ));
485 pObject->AddProperty( new Property( "searchClass" ));
486 pObject->AddProperty( new Property( "searchable" ));
487
488 pObject->AddProperty( new Property( "creator", "dc" ));
489 pObject->AddProperty( new Property( "date" , "dc" ));
490
491 pObject->AddProperty( new Property( "longDescription", "upnp" ));
492 pObject->AddProperty( new Property( "description" , "dc" ));
493
494 return( pObject );
495}
496
498
499CDSObject *CDSObject::CreateAudioItem( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
500{
501 if (pObject == nullptr)
502 {
503 pObject = new CDSObject( sId, sTitle, sParentId );
504 pObject->m_sClass = "object.item.audioItem";
505 }
506
507 CreateItem( sId, sTitle, sParentId, pObject );
508
509 pObject->AddProperty( new Property( "genre" , "upnp" ));
510 pObject->AddProperty( new Property( "description" , "dc" ));
511 pObject->AddProperty( new Property( "longDescription" , "upnp" ));
512 pObject->AddProperty( new Property( "publisher" , "dc" ));
513 pObject->AddProperty( new Property( "language" , "dc" ));
514 pObject->AddProperty( new Property( "relation" , "dc" ));
515 pObject->AddProperty( new Property( "rights" , "dc" ));
516
517 pObject->AddProperty( new Property( "creator" , "dc" ));
518 pObject->AddProperty( new Property( "date" , "dc" ));
519
520 return( pObject );
521}
522
524
525CDSObject *CDSObject::CreateMusicTrack( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
526{
527 if (pObject == nullptr)
528 {
529 pObject = new CDSObject( sId, sTitle, sParentId );
530 pObject->m_sClass = "object.item.audioItem.musicTrack";
531 }
532
533 CreateAudioItem( sId, sTitle, sParentId, pObject );
534
535 pObject->AddProperty( new Property( "artist" , "upnp" ));
536 pObject->AddProperty( new Property( "album" , "upnp" ));
537 pObject->AddProperty( new Property( "originalTrackNumber" , "upnp" ));
538 pObject->AddProperty( new Property( "playlist" , "upnp" ));
539 pObject->AddProperty( new Property( "storageMedium" , "upnp" ));
540 pObject->AddProperty( new Property( "contributor" , "dc" ));
541
542 pObject->AddProperty( new Property( "playbackCount" , "upnp" ));
543 pObject->AddProperty( new Property( "lastPlaybackTime" , "upnp" ));
544
545 pObject->AddProperty( new Property( "albumArtURI", "upnp", false, "", true)); // TN
546 pObject->AddProperty( new Property( "albumArtURI", "upnp", false, "", true)); // SM
547 pObject->AddProperty( new Property( "albumArtURI", "upnp", false, "", true)); // MED
548 pObject->AddProperty( new Property( "albumArtURI", "upnp", false, "", true)); // LRG
549
550#if 0
551 pObject->AddProperty( new Property( "publisher" , "dc" ));
552 pObject->AddProperty( new Property( "language" , "dc" ));
553 pObject->AddProperty( new Property( "relation" , "dc" ));
554 pObject->AddProperty( new Property( "rights" , "dc" ));
555
556
557 pObject->AddProperty( new Property( "playlist" , "upnp" ));
558 pObject->AddProperty( new Property( "storageMedium" , "upnp" ));
559 pObject->AddProperty( new Property( "contributor" , "dc" ));
560#endif
561
562 return( pObject );
563}
564
566
567CDSObject *CDSObject::CreateAudioBroadcast( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
568{
569 if (pObject == nullptr)
570 {
571 pObject = new CDSObject( sId, sTitle, sParentId );
572 pObject->m_sClass = "object.item.audioItem.audioBroadcast";
573 }
574
575 CreateAudioItem( sId, sTitle, sParentId, pObject );
576
577 pObject->AddProperty( new Property( "region" , "upnp" ));
578 pObject->AddProperty( new Property( "radioCallSign" , "upnp" ));
579 pObject->AddProperty( new Property( "radioStationID" , "upnp" ));
580 pObject->AddProperty( new Property( "radioBand" , "upnp" ));
581 pObject->AddProperty( new Property( "channelNr" , "upnp" ));
582
583 return( pObject );
584}
585
587
588CDSObject *CDSObject::CreateAudioBook( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
589{
590 if (pObject == nullptr)
591 {
592 pObject = new CDSObject( sId, sTitle, sParentId );
593 pObject->m_sClass = "object.item.audioItem.audioBook";
594 }
595
596 CreateAudioItem( sId, sTitle, sParentId, pObject );
597
598 pObject->AddProperty( new Property( "storageMedium", "upnp" ));
599 pObject->AddProperty( new Property( "producer" , "upnp" ));
600 pObject->AddProperty( new Property( "contributor" , "dc" ));
601
602 return( pObject );
603}
604
606
607CDSObject *CDSObject::CreateVideoItem( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
608{
609 if (pObject == nullptr)
610 {
611 pObject = new CDSObject( sId, sTitle, sParentId );
612 pObject->m_sClass = "object.item.videoItem";
613 }
614
615 CreateItem( sId, sTitle, sParentId, pObject );
616
617 pObject->AddProperty( new Property( "genre" , "upnp" ));
618 pObject->AddProperty( new Property( "longDescription", "upnp" ));
619 pObject->AddProperty( new Property( "producer" , "upnp" ));
620 pObject->AddProperty( new Property( "rating" , "upnp" ));
621 pObject->AddProperty( new Property( "actor" , "upnp" ));
622 pObject->AddProperty( new Property( "director" , "upnp" ));
623 pObject->AddProperty( new Property( "episodeNumber" , "upnp" ));
624 pObject->AddProperty( new Property( "episodeCount" , "upnp" ));
625 pObject->AddProperty( new Property( "seriesTitle" , "upnp" ));
626 pObject->AddProperty( new Property( "programTitle" , "upnp" ));
627 pObject->AddProperty( new Property( "description" , "dc" ));
628 pObject->AddProperty( new Property( "publisher" , "dc" ));
629 pObject->AddProperty( new Property( "language" , "dc" ));
630 pObject->AddProperty( new Property( "relation" , "dc" ));
631
632 pObject->AddProperty( new Property( "creator" , "dc" ));
633 pObject->AddProperty( new Property( "date" , "dc" ));
634
635 pObject->AddProperty( new Property( "channelID" , "upnp" ));
636 pObject->AddProperty( new Property( "callSign" , "upnp" ));
637 pObject->AddProperty( new Property( "channelNr" , "upnp" ));
638 pObject->AddProperty( new Property( "channelName" , "upnp" ));
639
640 pObject->AddProperty( new Property( "scheduledStartTime", "upnp" ));
641 pObject->AddProperty( new Property( "scheduledEndTime" , "upnp" ));
642 pObject->AddProperty( new Property( "scheduledDuration" , "upnp" ));
643 pObject->AddProperty( new Property( "srsRecordScheduleID" , "upnp" ));
644 pObject->AddProperty( new Property( "recordedStartDateTime" , "upnp" ));
645 pObject->AddProperty( new Property( "recordedDuration" , "upnp" ));
646 pObject->AddProperty( new Property( "recordedDayOfWeek" , "upnp" ));
647
648 pObject->AddProperty( new Property( "programID" , "upnp" ));
649 pObject->AddProperty( new Property( "seriesID" , "upnp" ));
650
651 // Added for Microsoft Media Player Compatibility
652 pObject->AddProperty( new Property( "artist" , "upnp" ));
653 pObject->AddProperty( new Property( "album" , "upnp" ));
654 //
655
656 pObject->AddProperty( new Property( "albumArtURI", "upnp", false, "", true )); // TN
657 pObject->AddProperty( new Property( "albumArtURI", "upnp", false, "", true )); // SM
658 pObject->AddProperty( new Property( "albumArtURI", "upnp", false, "", true )); // MED
659 pObject->AddProperty( new Property( "albumArtURI", "upnp", false, "", true )); // LRG
660 return( pObject );
661}
662
664
665CDSObject *CDSObject::CreateMovie( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
666{
667 if (pObject == nullptr)
668 {
669 pObject = new CDSObject( sId, sTitle, sParentId );
670 pObject->m_sClass = "object.item.videoItem.movie";
671 }
672
673 CreateVideoItem( sId, sTitle, sParentId, pObject );
674
675 pObject->AddProperty( new Property( "storageMedium" , "upnp" ));
676 pObject->AddProperty( new Property( "DVDRegionCode" , "upnp" ));
677
678 return( pObject );
679}
680
682
683CDSObject *CDSObject::CreateVideoBroadcast( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
684{
685 if (pObject == nullptr)
686 {
687 pObject = new CDSObject( sId, sTitle, sParentId );
688 pObject->m_sClass = "object.item.videoItem.videoBroadcast";
689 }
690
691 CreateVideoItem( sId, sTitle, sParentId, pObject );
692
693 pObject->AddProperty( new Property( "icon" , "upnp" ));
694 pObject->AddProperty( new Property( "region" , "upnp" ));
695
696 return( pObject );
697}
698
700
701CDSObject *CDSObject::CreateMusicVideoClip( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
702{
703 if (pObject == nullptr)
704 {
705 pObject = new CDSObject( sId, sTitle, sParentId );
706 pObject->m_sClass = "object.item.videoItem.musicVideoClip";
707 }
708
709 CreateVideoItem( sId, sTitle, sParentId, pObject );
710
711 pObject->AddProperty( new Property( "artist" , "upnp" ));
712 pObject->AddProperty( new Property( "storageMedium" , "upnp" ));
713 pObject->AddProperty( new Property( "album" , "upnp" ));
714 pObject->AddProperty( new Property( "contributor" , "dc" ));
715
716 return( pObject );
717}
718
720
721CDSObject *CDSObject::CreateImageItem( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
722{
723 if (pObject == nullptr)
724 {
725 pObject = new CDSObject( sId, sTitle, sParentId );
726 pObject->m_sClass = "object.item.imageItem";
727 }
728
729 CreateItem( sId, sTitle, sParentId, pObject );
730
731 pObject->AddProperty( new Property( "longDescription", "upnp" ));
732 pObject->AddProperty( new Property( "storageMedium" , "upnp" ));
733 pObject->AddProperty( new Property( "rating" , "upnp" ));
734 pObject->AddProperty( new Property( "description" , "dc" ));
735 pObject->AddProperty( new Property( "publisher" , "dc" ));
736 pObject->AddProperty( new Property( "rights" , "dc" ));
737
738 pObject->AddProperty( new Property( "creator" , "dc" ));
739 pObject->AddProperty( new Property( "date" , "dc" ));
740
741 return( pObject );
742}
743
745
746CDSObject *CDSObject::CreatePhoto( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
747{
748 if (pObject == nullptr)
749 {
750 pObject = new CDSObject( sId, sTitle, sParentId );
751 pObject->m_sClass = "object.item.imageItem.photo";
752 }
753
754 CreateImageItem( sId, sTitle, sParentId, pObject );
755
756 pObject->AddProperty( new Property( "album", "upnp" ));
757
758 return( pObject );
759}
760
762
763CDSObject *CDSObject::CreatePlaylistItem ( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
764{
765 if (pObject == nullptr)
766 {
767 pObject = new CDSObject( sId, sTitle, sParentId );
768 pObject->m_sClass = "object.item.playlistItem";
769 }
770
771 CreateItem( sId, sTitle, sParentId, pObject );
772
773 pObject->AddProperty( new Property( "artist" , "upnp" ));
774 pObject->AddProperty( new Property( "genre" , "upnp" ));
775 pObject->AddProperty( new Property( "longDescription", "upnp" ));
776 pObject->AddProperty( new Property( "storageMedium" , "upnp" ));
777 pObject->AddProperty( new Property( "description" , "dc" ));
778 pObject->AddProperty( new Property( "language" , "dc" ));
779
780 return( pObject );
781}
782
784
785CDSObject *CDSObject::CreateTextItem( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
786{
787 if (pObject == nullptr)
788 {
789 pObject = new CDSObject( sId, sTitle, sParentId );
790 pObject->m_sClass = "object.item.textItem";
791 }
792
793 CreateItem( sId, sTitle, sParentId, pObject );
794
795 pObject->AddProperty( new Property( "author" , "upnp" ));
796 pObject->AddProperty( new Property( "protection" , "upnp" ));
797 pObject->AddProperty( new Property( "longDescription", "upnp" ));
798 pObject->AddProperty( new Property( "storageMedium" , "upnp" ));
799 pObject->AddProperty( new Property( "rating" , "upnp" ));
800 pObject->AddProperty( new Property( "description" , "dc" ));
801 pObject->AddProperty( new Property( "publisher" , "dc" ));
802 pObject->AddProperty( new Property( "contributor" , "dc" ));
803 pObject->AddProperty( new Property( "relation" , "dc" ));
804 pObject->AddProperty( new Property( "language" , "dc" ));
805 pObject->AddProperty( new Property( "rights" , "dc" ));
806
807 return( pObject );
808}
809
811
812CDSObject *CDSObject::CreateAlbum( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
813{
814 if (pObject == nullptr)
815 {
816 pObject = new CDSObject( sId, sTitle, sParentId );
817 pObject->m_sClass = "object.container.album";
818 }
819
820 CreateContainer( sId, sTitle, sParentId, pObject );
821
822 pObject->AddProperty( new Property( "storageMedium" , "upnp" ));
823 pObject->AddProperty( new Property( "publisher" , "dc" ));
824 pObject->AddProperty( new Property( "contributor" , "dc" ));
825 pObject->AddProperty( new Property( "relation" , "dc" ));
826 pObject->AddProperty( new Property( "rights" , "dc" ));
827
828 // Artwork
829 pObject->AddProperty( new Property( "albumArtURI", "upnp", false, "", true)); // TN
830 pObject->AddProperty( new Property( "albumArtURI", "upnp", false, "", true)); // SM
831 pObject->AddProperty( new Property( "albumArtURI", "upnp", false, "", true)); // MED
832 pObject->AddProperty( new Property( "albumArtURI", "upnp", false, "", true)); // LRG
833
834 return( pObject );
835}
836
838
839CDSObject *CDSObject::CreateMusicAlbum( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
840{
841 if (pObject == nullptr)
842 {
843 pObject = new CDSObject( sId, sTitle, sParentId );
844 pObject->m_sClass = "object.container.album.musicAlbum";
845 }
846
847 CreateAlbum( sId, sTitle, sParentId, pObject );
848
849 pObject->AddProperty( new Property( "artist" , "upnp" ));
850 pObject->AddProperty( new Property( "genre" , "upnp" ));
851 pObject->AddProperty( new Property( "producer" , "upnp" ));
852 pObject->AddProperty( new Property( "toc" , "upnp" ));
853
854 return( pObject );
855}
856
858
859CDSObject *CDSObject::CreatePhotoAlbum( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
860{
861 if (pObject == nullptr)
862 {
863 pObject = new CDSObject( sId, sTitle, sParentId );
864 pObject->m_sClass = "object.container.album.photoAlbum";
865 }
866
867 CreateAlbum( sId, sTitle, sParentId, pObject );
868
869 return( pObject );
870}
871
873
874CDSObject *CDSObject::CreateGenre( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
875{
876 if (pObject == nullptr)
877 {
878 pObject = new CDSObject( sId, sTitle, sParentId );
879 pObject->m_sClass = "object.container.genre";
880 }
881
882 CreateContainer( sId, sTitle, sParentId, pObject );
883
884 return( pObject );
885}
886
888
889CDSObject *CDSObject::CreateMusicGenre( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
890{
891 if (pObject == nullptr)
892 {
893 pObject = new CDSObject( sId, sTitle, sParentId );
894 pObject->m_sClass = "object.container.genre.musicGenre";
895 }
896
897 CreateGenre( sId, sTitle, sParentId, pObject );
898
899 return( pObject );
900}
901
903
904CDSObject *CDSObject::CreateMovieGenre( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
905{
906 if (pObject == nullptr)
907 {
908 pObject = new CDSObject( sId, sTitle, sParentId );
909 pObject->m_sClass = "object.container.genre.movieGenre";
910 }
911
912 CreateGenre( sId, sTitle, sParentId, pObject );
913
914 return( pObject );
915}
916
918
919CDSObject *CDSObject::CreatePlaylistContainer( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
920{
921 if (pObject == nullptr)
922 {
923 pObject = new CDSObject( sId, sTitle, sParentId );
924 pObject->m_sClass = "object.container.playlistContainer";
925 }
926
927 CreateContainer( sId, sTitle, sParentId, pObject );
928
929 pObject->AddProperty( new Property( "artist" , "upnp" ));
930 pObject->AddProperty( new Property( "genre" , "upnp" ));
931 pObject->AddProperty( new Property( "producer" , "upnp" ));
932 pObject->AddProperty( new Property( "storageMedium" , "upnp" ));
933 pObject->AddProperty( new Property( "contributor" , "dc" ));
934 pObject->AddProperty( new Property( "language" , "dc" ));
935 pObject->AddProperty( new Property( "rights" , "dc" ));
936
937 return( pObject );
938}
939
941
942CDSObject *CDSObject::CreatePerson( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
943{
944 if (pObject == nullptr)
945 {
946 pObject = new CDSObject( sId, sTitle, sParentId );
947 pObject->m_sClass = "object.container.person";
948 }
949
950 CreateContainer( sId, sTitle, sParentId, pObject );
951
952 pObject->AddProperty( new Property( "language", "dc" ));
953
954 return( pObject );
955}
956
958
959CDSObject *CDSObject::CreateMusicArtist( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
960{
961 if (pObject == nullptr)
962 {
963 pObject = new CDSObject( sId, sTitle, sParentId );
964 pObject->m_sClass = "object.container.person.musicArtist";
965 }
966
967 CreatePerson( sId, sTitle, sParentId, pObject );
968
969 pObject->AddProperty( new Property( "genre" , "upnp" ));
970 pObject->AddProperty( new Property( "artistDiscographyURI", "upnp" ));
971
972 return( pObject );
973}
974
976
977CDSObject *CDSObject::CreateStorageSystem( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
978{
979 if (pObject == nullptr)
980 {
981 pObject = new CDSObject( sId, sTitle, sParentId );
982 pObject->m_sClass = "object.container.storageSystem";
983 }
984
985 CreateContainer( sId, sTitle, sParentId, pObject );
986
987 pObject->AddProperty( new Property( "storageTotal" , "upnp", true, "-1" ));
988 pObject->AddProperty( new Property( "storageUsed" , "upnp", true, "-1" ));
989 pObject->AddProperty( new Property( "storageFree" , "upnp", true, "-1" ));
990 pObject->AddProperty( new Property( "storageMaxPartition", "upnp", true, "-1" ));
991 pObject->AddProperty( new Property( "storageMedium" , "upnp", true, "HDD" ));
992
993 return( pObject );
994}
995
997
998CDSObject *CDSObject::CreateStorageVolume( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
999{
1000 if (pObject == nullptr)
1001 {
1002 pObject = new CDSObject( sId, sTitle, sParentId );
1003 pObject->m_sClass = "object.container.storageVolume";
1004 }
1005
1006 CreateContainer( sId, sTitle, sParentId, pObject );
1007
1008 pObject->AddProperty( new Property( "storageTotal" , "upnp", true, "-1" ));
1009 pObject->AddProperty( new Property( "storageUsed" , "upnp", true, "-1" ));
1010 pObject->AddProperty( new Property( "storageFree" , "upnp", true, "-1" ));
1011 pObject->AddProperty( new Property( "storageMedium", "upnp", true, "HDD" ));
1012
1013 return( pObject );
1014}
1015
1017
1018CDSObject *CDSObject::CreateStorageFolder( const QString& sId, const QString& sTitle, const QString& sParentId, CDSObject *pObject )
1019{
1020 if (pObject == nullptr)
1021 {
1022 pObject = new CDSObject( sId, sTitle, sParentId );
1023 pObject->m_sClass = "object.container.storageFolder";
1024 }
1025
1026 CreateContainer( sId, sTitle, sParentId, pObject );
1027
1028 pObject->AddProperty( new Property( "storageUsed", "upnp", true, "-1" ));
1029
1030 return( pObject );
1031}
1032
1033bool CDSObject::FilterContains(const FilterMap &filter, const QString& name)
1034{
1035 // ContentDirectory Service, 2013 UPnP Forum
1036 // 2.3.18 A_ARG_TYPE_Filter
1037
1038 // Exact match
1039 if (filter.contains(name, Qt::CaseInsensitive))
1040 return true;
1041
1042 // # signfies that this property and all it's children must be returned
1043 // This is presently implemented higher up to save time
1044
1045 // If an attribute is required then it's parent must also be returned
1046 QString dependentAttribute = QString("%1@").arg(name);
1047 QStringList matches = filter.filter(name, Qt::CaseInsensitive);
1048 QStringList::iterator it;
1049 for (it = matches.begin(); it != matches.end(); ++it)
1050 {
1051 if ((*it).startsWith(dependentAttribute))
1052 return true;
1053 }
1054
1055 return false;
1056}
1057
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:80