1 /*****************************************************************
3 | Platinum - Device Data
5 | Copyright (c) 2004-2010, Plutinosoft, LLC.
7 | http://www.plutinosoft.com
9 | This program is free software; you can redistribute it and/or
10 | modify it under the terms of the GNU General Public License
11 | as published by the Free Software Foundation; either version 2
12 | of the License, or (at your option) any later version.
14 | OEMs, ISVs, VARs and other distributors that combine and
15 | distribute commercially licensed software with Platinum software
16 | and do not wish to distribute the source code for the commercially
17 | licensed software under version 2, or (at your option) any later
18 | version, of the GNU General Public License (the "GPL") must enter
19 | into a commercial license agreement with Plutinosoft, LLC.
20 | licensing@plutinosoft.com
22 | This program is distributed in the hope that it will be useful,
23 | but WITHOUT ANY WARRANTY; without even the implied warranty of
24 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 | GNU General Public License for more details.
27 | You should have received a copy of the GNU General Public License
28 | along with this program; see the file LICENSE.txt. If not, write to
29 | the Free Software Foundation, Inc.,
30 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
31 | http://www.gnu.org/licenses/gpl-2.0.html
33 ****************************************************************/
35 /*----------------------------------------------------------------------
37 +---------------------------------------------------------------------*/
38 #include "PltDeviceData.h"
39 #include "PltService.h"
41 #include "PltUtilities.h"
43 NPT_SET_LOCAL_LOGGER("platinum.core.devicedata")
45 /*----------------------------------------------------------------------
46 | PLT_DeviceData::PLT_DeviceData
47 +---------------------------------------------------------------------*/
48 PLT_DeviceData::PLT_DeviceData(NPT_HttpUrl description_url
,
50 NPT_TimeInterval lease_time
,
51 const char* device_type
,
52 const char* friendly_name
) :
53 m_Manufacturer("Plutinosoft LLC"),
54 m_ManufacturerURL("http://www.plutinosoft.com"),
56 m_URLDescription(description_url
),
57 m_DeviceType(device_type
),
58 m_FriendlyName(friendly_name
),
62 if (uuid
== NULL
|| strlen(uuid
) == 0) {
63 PLT_UPnPMessageHelper::GenerateGUID(m_UUID
);
66 SetLeaseTime(lease_time
);
67 SetURLBase(m_URLDescription
);
71 /*----------------------------------------------------------------------
72 | PLT_DeviceData::~PLT_DeviceData
73 +---------------------------------------------------------------------*/
74 PLT_DeviceData::~PLT_DeviceData()
79 /*----------------------------------------------------------------------
80 | PLT_DeviceData::Cleanup
81 +---------------------------------------------------------------------*/
83 PLT_DeviceData::Cleanup()
85 m_Services
.Apply(NPT_ObjectDeleter
<PLT_Service
>());
87 m_EmbeddedDevices
.Clear();
91 /*----------------------------------------------------------------------
92 | PLT_DeviceData::SetDescriptionUrl
93 +---------------------------------------------------------------------*/
95 PLT_DeviceData::SetDescriptionUrl(NPT_HttpUrl
& url
)
97 NPT_CHECK_FATAL(SetURLBase(url
));
98 m_URLDescription
= url
;
102 /*----------------------------------------------------------------------
103 | PLT_DeviceData::GetDescriptionUrl
104 +---------------------------------------------------------------------*/
106 PLT_DeviceData::GetDescriptionUrl(const char* ip_address
)
108 NPT_HttpUrl url
= m_URLDescription
;
110 // replace host with ip address specified
111 if (ip_address
) url
.SetHost(ip_address
);
112 return url
.ToString();
115 /*----------------------------------------------------------------------
116 | PLT_DeviceData::SetURLBase
117 +---------------------------------------------------------------------*/
119 PLT_DeviceData::SetURLBase(NPT_HttpUrl
& url
)
121 // only http scheme supported
122 m_URLBase
.SetScheme(url
.GetScheme());
124 // update port if any
125 if (url
.GetPort() != NPT_URL_INVALID_PORT
) m_URLBase
.SetPort(url
.GetPort());
127 // update host if any
128 if (!url
.GetHost().IsEmpty()) m_URLBase
.SetHost(url
.GetHost());
131 NPT_String path
= url
.GetPath();
133 // remove trailing file according to RFC 2396
134 if (!path
.EndsWith("/")) {
135 int index
= path
.ReverseFind('/');
136 if (index
< 0) return NPT_FAILURE
;
137 path
.SetLength(index
+1);
139 m_URLBase
.SetPath(path
, true);
144 /*----------------------------------------------------------------------
145 | PLT_DeviceData::GetURLBase
146 +---------------------------------------------------------------------*/
148 PLT_DeviceData::GetURLBase()
153 /*----------------------------------------------------------------------
154 | PLT_DeviceData::NormalizeURL
155 +---------------------------------------------------------------------*/
157 PLT_DeviceData::NormalizeURL(const NPT_String
& url
)
159 if (url
.StartsWith("http://")) return NPT_HttpUrl(url
);
161 NPT_HttpUrl norm_url
= m_URLBase
;
162 if (url
.StartsWith("/")) {
163 norm_url
.ParsePathPlus(url
);
165 norm_url
.ParsePathPlus(norm_url
.GetPath() + url
);
171 /*----------------------------------------------------------------------
172 | PLT_DeviceData::GetIconUrl
173 +---------------------------------------------------------------------*/
175 PLT_DeviceData::GetIconUrl(const char* mimetype
,
181 for (NPT_Cardinal i
=0; i
<m_Icons
.GetItemCount(); i
++) {
182 if ((mimetype
&& m_Icons
[i
].m_MimeType
!= mimetype
) ||
183 (maxsize
&& m_Icons
[i
].m_Width
> maxsize
) ||
184 (maxsize
&& m_Icons
[i
].m_Height
> maxsize
) ||
185 (maxdepth
&& m_Icons
[i
].m_Depth
> maxdepth
))
188 // pick the biggest and better resolution we can
189 if (icon
.m_Width
>= m_Icons
[i
].m_Width
||
190 icon
.m_Height
>= m_Icons
[i
].m_Height
||
191 icon
.m_Depth
>= m_Icons
[i
].m_Depth
||
192 m_Icons
[i
].m_UrlPath
.IsEmpty())
198 if (icon
.m_UrlPath
== "") return "";
200 return NormalizeURL(icon
.m_UrlPath
).ToString();
203 /*----------------------------------------------------------------------
204 | PLT_DeviceData::UpdateConfigId
205 +---------------------------------------------------------------------*/
207 PLT_DeviceData::UpdateConfigId()
209 NPT_UInt32 nextConfigId
= NPT_System::GetRandomInteger() & 0xFFFFFF;
210 if (m_ConfigId
== nextConfigId
) {
211 // prevent value to underflow
212 nextConfigId
>0?--nextConfigId
:++nextConfigId
;
215 m_ConfigId
= nextConfigId
;
218 /*----------------------------------------------------------------------
219 | PLT_DeviceData::SetBootId
220 +---------------------------------------------------------------------*/
222 PLT_DeviceData::SetBootId(NPT_UInt32 bootId
)
227 /*----------------------------------------------------------------------
228 | PLT_DeviceData::SetNextBootId
229 +---------------------------------------------------------------------*/
231 PLT_DeviceData::SetNextBootId(NPT_UInt32 nextBootId
)
233 m_NextBootId
= nextBootId
;
236 /*----------------------------------------------------------------------
237 | PLT_DeviceData::GenerateNextBootId
238 +---------------------------------------------------------------------*/
240 PLT_DeviceData::GenerateNextBootId()
243 NPT_System::GetCurrentTimeStamp(now
);
244 NPT_UInt32 value
= (NPT_UInt32
)now
.ToSeconds();
245 if (value
== m_BootId
) ++value
;
249 /*----------------------------------------------------------------------
250 | PLT_DeviceData::SetLeaseTime
251 +---------------------------------------------------------------------*/
253 PLT_DeviceData::SetLeaseTime(NPT_TimeInterval lease_time
, NPT_TimeStamp lease_time_last_update
/* = 0 */)
255 // Enforce 10 seconds min lease time
256 m_LeaseTime
= (lease_time
.ToSeconds()>=10)?lease_time
:*PLT_Constants::GetInstance().GetDefaultDeviceLease();
258 // get current time as last update time if none passed
259 if ((double)lease_time_last_update
== 0.) {
260 NPT_System::GetCurrentTimeStamp(lease_time_last_update
);
262 m_LeaseTimeLastUpdate
= lease_time_last_update
;
266 /*----------------------------------------------------------------------
267 | PLT_DeviceData::GetLeaseTimeLastUpdate
268 +---------------------------------------------------------------------*/
270 PLT_DeviceData::GetLeaseTimeLastUpdate()
272 return m_LeaseTimeLastUpdate
;
275 /*----------------------------------------------------------------------
276 | PLT_DeviceData::operator const char*()
277 +---------------------------------------------------------------------*/
278 PLT_DeviceData::operator const char*()
280 NPT_StringOutputStreamReference
stream(new NPT_StringOutputStream
);
281 stream
->WriteString("Device GUID: ");
282 stream
->WriteString((const char*)m_UUID
);
284 stream
->WriteString("Device Type: ");
285 stream
->WriteString((const char*)m_DeviceType
);
287 stream
->WriteString("Device Base Url: ");
288 stream
->WriteString((const char*)GetURLBase().ToString());
290 stream
->WriteString("Device Friendly Name: ");
291 stream
->WriteString((const char*)m_FriendlyName
);
293 m_Representation
= stream
->GetString();
294 return m_Representation
;
297 /*----------------------------------------------------------------------
298 | PLT_DeviceData::AddEmbeddedDevice
299 +---------------------------------------------------------------------*/
301 PLT_DeviceData::AddEmbeddedDevice(PLT_DeviceDataReference
& device
)
305 device
->m_ParentUUID
= m_UUID
;
306 return m_EmbeddedDevices
.Add(device
);
309 /*----------------------------------------------------------------------
310 | PLT_DeviceData::RemoveEmbeddedDevice
311 +---------------------------------------------------------------------*/
313 PLT_DeviceData::RemoveEmbeddedDevice(PLT_DeviceDataReference
& device
)
315 for (NPT_Cardinal i
=0;
316 i
<m_EmbeddedDevices
.GetItemCount();
318 if (m_EmbeddedDevices
[i
] == device
) {
320 return m_EmbeddedDevices
.Erase(i
);
324 return NPT_ERROR_NO_SUCH_ITEM
;
327 /*----------------------------------------------------------------------
328 | PLT_DeviceData::AddService
329 +---------------------------------------------------------------------*/
331 PLT_DeviceData::AddService(PLT_Service
* service
)
333 if (service
->GetServiceType() == "" ||
334 service
->GetServiceID() == "" ||
335 service
->GetSCPDURL() == "" ||
336 service
->GetControlURL() == "" ||
337 service
->GetEventSubURL() == "") {
338 return NPT_ERROR_INVALID_PARAMETERS
;
341 return m_Services
.Add(service
);
344 /*----------------------------------------------------------------------
345 | PLT_DeviceData::RemoveService
346 +---------------------------------------------------------------------*/
348 PLT_DeviceData::RemoveService(PLT_Service
* service
)
350 for (NPT_Cardinal i
=0;
351 i
<m_Services
.GetItemCount();
353 if (m_Services
[i
] == service
) {
355 return m_Services
.Erase(i
);
359 return NPT_ERROR_NO_SUCH_ITEM
;
362 /*----------------------------------------------------------------------
363 | PLT_GetDescriptionIterator class
364 +---------------------------------------------------------------------*/
366 class PLT_GetDescriptionIterator
369 PLT_GetDescriptionIterator(NPT_XmlElementNode
* parent
) :
372 NPT_Result
operator()(T
& data
) const {
373 return data
->GetDescription(m_Parent
);
377 NPT_XmlElementNode
* m_Parent
;
380 /*----------------------------------------------------------------------
381 | PLT_DeviceData::GetDescription
382 +---------------------------------------------------------------------*/
384 PLT_DeviceData::GetDescription(NPT_XmlElementNode
* root
, NPT_XmlElementNode
** device_out
)
386 NPT_XmlElementNode
* device
= new NPT_XmlElementNode("device");
387 if (device_out
) *device_out
= device
;
389 NPT_CHECK_SEVERE(root
->AddChild(device
));
392 NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device
, "deviceType", m_DeviceType
));
393 NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device
, "friendlyName", m_FriendlyName
));
394 NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device
, "manufacturer", m_Manufacturer
));
395 NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device
, "manufacturerURL", m_ManufacturerURL
));
396 NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device
, "modelDescription", m_ModelDescription
));
397 NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device
, "modelName", m_ModelName
));
398 if (!m_ModelNumber
.IsEmpty()) NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device
, "modelNumber", m_ModelNumber
));
399 if (!m_SerialNumber
.IsEmpty()) NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device
, "serialNumber", m_SerialNumber
));
400 NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device
, "modelURL", m_ModelURL
)); // moved after modelNumber to go around a bug in UCTT
401 NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device
, "UDN", "uuid:" + m_UUID
));
403 if (!m_PresentationURL
.IsEmpty()) {
404 NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(device
, "presentationURL", m_PresentationURL
));
407 // Extra info not in UPnP specs
408 NPT_CHECK(OnAddExtraInfo(device
));
411 if (!m_DlnaDoc
.IsEmpty()) {
412 NPT_XmlElementNode
* dlnadoc
= new NPT_XmlElementNode("dlna", "X_DLNADOC");
413 NPT_CHECK_SEVERE(dlnadoc
->SetNamespaceUri("dlna", "urn:schemas-dlna-org:device-1-0"));
414 dlnadoc
->AddText(m_DlnaDoc
);
415 device
->AddChild(dlnadoc
);
417 if (!m_DlnaCap
.IsEmpty()) {
418 NPT_XmlElementNode
* dlnacap
= new NPT_XmlElementNode("dlna", "X_DLNACAP");
419 NPT_CHECK_SEVERE(dlnacap
->SetNamespaceUri("dlna", "urn:schemas-dlna-org:device-1-0"));
420 dlnacap
->AddText(m_DlnaCap
);
421 device
->AddChild(dlnacap
);
425 if (m_Icons
.GetItemCount()) {
426 NPT_XmlElementNode
* icons
= new NPT_XmlElementNode("iconList");
427 NPT_CHECK_SEVERE(device
->AddChild(icons
));
428 for (NPT_Cardinal i
=0; i
<m_Icons
.GetItemCount(); i
++) {
429 NPT_XmlElementNode
* icon
= new NPT_XmlElementNode("icon");
430 NPT_CHECK_SEVERE(icons
->AddChild(icon
));
431 NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(icon
, "mimetype", m_Icons
[i
].m_MimeType
));
432 NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(icon
, "width", NPT_String::FromInteger(m_Icons
[i
].m_Width
)));
433 NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(icon
, "height", NPT_String::FromInteger(m_Icons
[i
].m_Height
)));
434 NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(icon
, "depth", NPT_String::FromInteger(m_Icons
[i
].m_Depth
)));
435 NPT_CHECK_SEVERE(PLT_XmlHelper::AddChildText(icon
, "url", m_Icons
[i
].m_UrlPath
));
440 NPT_XmlElementNode
* services
= new NPT_XmlElementNode("serviceList");
441 NPT_CHECK_SEVERE(device
->AddChild(services
));
442 NPT_CHECK_SEVERE(m_Services
.ApplyUntil(PLT_GetDescriptionIterator
<PLT_Service
*>(services
),
443 NPT_UntilResultNotEquals(NPT_SUCCESS
)));
446 if (!m_AggregationFlags
.IsEmpty()) {
447 NPT_XmlElementNode
* aggr
= new NPT_XmlElementNode("av", "aggregationFlags");
448 NPT_CHECK_SEVERE(aggr
->SetNamespaceUri("av", "urn:schemas-sonycom:av"));
449 aggr
->AddText(m_AggregationFlags
);
450 device
->AddChild(aggr
);
454 if (m_EmbeddedDevices
.GetItemCount()) {
455 NPT_XmlElementNode
* deviceList
= new NPT_XmlElementNode("deviceList");
456 NPT_CHECK_SEVERE(device
->AddChild(deviceList
));
458 NPT_CHECK_SEVERE(m_EmbeddedDevices
.ApplyUntil(
459 PLT_GetDescriptionIterator
<PLT_DeviceDataReference
>(deviceList
),
460 NPT_UntilResultNotEquals(NPT_SUCCESS
)));
466 /*----------------------------------------------------------------------
467 | PLT_DeviceData::GetDescription
468 +---------------------------------------------------------------------*/
470 PLT_DeviceData::GetDescription(NPT_String
& desc
)
473 NPT_XmlElementNode
* spec
= NULL
;
474 NPT_XmlElementNode
* root
= new NPT_XmlElementNode("root");
476 NPT_CHECK_LABEL_SEVERE(res
= root
->SetNamespaceUri("", "urn:schemas-upnp-org:device-1-0"), cleanup
);
477 NPT_CHECK_LABEL_SEVERE(res
= root
->SetNamespaceUri("dlna", "urn:schemas-dlna-org:device-1-0"), cleanup
);
478 NPT_CHECK_LABEL_SEVERE(res
= root
->SetAttribute("", "configId", NPT_String::FromInteger(m_ConfigId
)), cleanup
);
481 spec
= new NPT_XmlElementNode("specVersion");
482 NPT_CHECK_LABEL_SEVERE(res
= root
->AddChild(spec
), cleanup
);
483 NPT_CHECK_LABEL_SEVERE(res
= PLT_XmlHelper::AddChildText(spec
, "major", "1"), cleanup
);
484 NPT_CHECK_LABEL_SEVERE(res
= PLT_XmlHelper::AddChildText(spec
, "minor", "1"), cleanup
);
487 NPT_CHECK_LABEL_SEVERE(res
= GetDescription(root
), cleanup
);
490 NPT_CHECK_LABEL_SEVERE(res
= PLT_XmlHelper::Serialize(*root
, desc
, true, 2), cleanup
);
497 /*----------------------------------------------------------------------
498 | PLT_DeviceData::SetDescription
499 +---------------------------------------------------------------------*/
501 PLT_DeviceData::SetDescription(PLT_DeviceDataReference
& root_device
,
502 NPT_TimeInterval leasetime
,
503 NPT_HttpUrl description_url
,
504 const char* description
,
505 const NPT_HttpRequestContext
& context
)
507 NPT_XmlParser parser
;
508 NPT_XmlNode
* tree
= NULL
;
510 NPT_XmlElementNode
* root
= NULL
;
514 // create new device if none passed
515 if (root_device
.IsNull()) {
516 root_device
= new PLT_DeviceData(description_url
, "", leasetime
);
519 res
= parser
.Parse(description
, tree
);
520 NPT_CHECK_LABEL_SEVERE(res
, cleanup
);
522 root
= tree
->AsElementNode();
524 root
->GetTag() != "root" ||
525 !root
->GetNamespace() ||
526 *root
->GetNamespace() != "urn:schemas-upnp-org:device-1-0") {
527 NPT_LOG_INFO_1("root namespace is invalid: %s",
528 (root
&&root
->GetNamespace())?root
->GetNamespace()->GetChars():"null");
529 NPT_CHECK_LABEL_SEVERE(NPT_FAILURE
, cleanup
);
532 // look for optional URLBase element
533 if (NPT_SUCCEEDED(PLT_XmlHelper::GetChildText(root
, "URLBase", URLBase
))) {
534 NPT_HttpUrl
url(URLBase
);
535 // Some devices like Connect360 try to be funny - not so
536 if (url
.GetHost().ToLowercase() == "localhost" ||
537 url
.GetHost().ToLowercase() == "127.0.0.1") {
538 url
.SetHost(context
.GetRemoteAddress().GetIpAddress().ToString());
540 root_device
->SetURLBase(url
);
542 // No URLBase, derive from description url
543 root_device
->SetURLBase(description_url
);
546 // at least one root device child element is required
547 NPT_XmlElementNode
* device
;
548 if (!(device
= PLT_XmlHelper::GetChild(root
, "device"))) {
549 NPT_CHECK_LABEL_SEVERE(NPT_FAILURE
, cleanup
);
552 res
= SetDescriptionDevice(root_device
, device
, context
);
554 // reset configId if and set it back from root attribute
555 root_device
->m_ConfigId
= 0;
556 if (NPT_SUCCEEDED(PLT_XmlHelper::GetAttribute(root
, "configId", configId
))) {
558 if (NPT_SUCCEEDED(configId
.ToInteger32(value
))) {
559 root_device
->m_ConfigId
= value
;
569 /*----------------------------------------------------------------------
570 | PLT_DeviceData::SetDescriptionDevice
571 +---------------------------------------------------------------------*/
573 PLT_DeviceData::SetDescriptionDevice(PLT_DeviceDataReference
& device
,
574 NPT_XmlElementNode
* device_node
,
575 const NPT_HttpRequestContext
& context
)
579 device
->m_LocalIfaceIp
= context
.GetLocalAddress().GetIpAddress();
581 NPT_CHECK_SEVERE(PLT_XmlHelper::GetChildText(device_node
, "deviceType", device
->m_DeviceType
));
582 NPT_CHECK_SEVERE(PLT_XmlHelper::GetChildText(device_node
, "UDN", device
->m_UUID
));
584 // remove uuid: prefix
585 if (device
->m_UUID
.StartsWith("uuid:")) {
586 device
->m_UUID
= ((const char*)device
->m_UUID
)+5;
589 // optional attributes
590 PLT_XmlHelper::GetChildText(device_node
, "friendlyName", device
->m_FriendlyName
);
591 PLT_XmlHelper::GetChildText(device_node
, "manufacturer", device
->m_Manufacturer
);
592 PLT_XmlHelper::GetChildText(device_node
, "manufacturerURL", device
->m_ManufacturerURL
);
593 PLT_XmlHelper::GetChildText(device_node
, "modelDescription", device
->m_ModelDescription
);
594 PLT_XmlHelper::GetChildText(device_node
, "modelName", device
->m_ModelName
);
595 PLT_XmlHelper::GetChildText(device_node
, "modelURL", device
->m_ModelURL
);
596 PLT_XmlHelper::GetChildText(device_node
, "modelNumber", device
->m_ModelNumber
);
597 PLT_XmlHelper::GetChildText(device_node
, "serialNumber", device
->m_SerialNumber
);
598 PLT_XmlHelper::GetChildText(device_node
, "presentationURL", device
->m_PresentationURL
);
601 NPT_XmlElementNode
* iconList
= PLT_XmlHelper::GetChild(device_node
, "iconList");
603 NPT_Array
<NPT_XmlElementNode
*> icons
;
604 PLT_XmlHelper::GetChildren(iconList
, icons
, "icon");
606 for (NPT_Cardinal k
=0 ; k
<icons
.GetItemCount(); k
++) {
608 NPT_String integer
, height
, depth
;
610 PLT_XmlHelper::GetChildText(icons
[k
], "mimetype", icon
.m_MimeType
);
611 PLT_XmlHelper::GetChildText(icons
[k
], "url", icon
.m_UrlPath
);
613 if(NPT_SUCCEEDED(PLT_XmlHelper::GetChildText(icons
[k
], "width", integer
)))
614 NPT_ParseInteger32(integer
, icon
.m_Width
);
615 if(NPT_SUCCEEDED(PLT_XmlHelper::GetChildText(icons
[k
], "height", integer
)))
616 NPT_ParseInteger32(integer
, icon
.m_Height
);
617 if(NPT_SUCCEEDED(PLT_XmlHelper::GetChildText(icons
[k
], "depth", integer
)))
618 NPT_ParseInteger32(integer
, icon
.m_Depth
);
620 device
->m_Icons
.Add(icon
);
624 // enumerate device services
625 NPT_XmlElementNode
* serviceList
= PLT_XmlHelper::GetChild(device_node
, "serviceList");
627 NPT_Array
<NPT_XmlElementNode
*> services
;
628 PLT_XmlHelper::GetChildren(serviceList
, services
, "service");
629 for( int k
= 0 ; k
< (int)services
.GetItemCount(); k
++) {
630 NPT_String type
, id
, url
;
631 PLT_XmlHelper::GetChildText(services
[k
], "serviceType", type
);
632 PLT_XmlHelper::GetChildText(services
[k
], "serviceId", id
);
633 PLT_Service
* service
= new PLT_Service(device
.AsPointer(), type
, id
, NULL
);
635 PLT_XmlHelper::GetChildText(services
[k
], "SCPDURL", url
);
636 service
->SetSCPDURL(url
);
638 PLT_XmlHelper::GetChildText(services
[k
], "controlURL", url
);
639 service
->SetControlURL(url
);
641 PLT_XmlHelper::GetChildText(services
[k
], "eventSubURL", url
);
642 service
->SetEventSubURL(url
);
644 if (NPT_FAILED(res
= device
->AddService(service
))) {
651 // enumerate embedded devices
652 NPT_XmlElementNode
* deviceList
= PLT_XmlHelper::GetChild(device_node
, "deviceList");
654 NPT_Array
<NPT_XmlElementNode
*> devices
;
655 PLT_XmlHelper::GetChildren(deviceList
, devices
, "device");
656 for (int k
= 0; k
<(int)devices
.GetItemCount(); k
++) {
657 // create an embedded device with same url base and leasetime as parent
658 PLT_DeviceDataReference
embedded_device(new PLT_DeviceData(device
->m_URLDescription
, "", device
->m_LeaseTime
));
659 NPT_CHECK_SEVERE(PLT_DeviceData::SetDescriptionDevice(embedded_device
, devices
[k
], context
));
660 device
->AddEmbeddedDevice(embedded_device
);
664 // TODO: Parse extra DLNA stuff
670 /*----------------------------------------------------------------------
671 | PLT_DeviceData::FindEmbeddedDevice
672 +---------------------------------------------------------------------*/
674 PLT_DeviceData::FindEmbeddedDevice(const char* uuid
,
675 PLT_DeviceDataReference
& device
)
677 NPT_Result res
= NPT_ContainerFind(m_EmbeddedDevices
,
678 PLT_DeviceDataFinder(uuid
),
680 if (NPT_SUCCEEDED(res
)) return res
;
682 for (int i
=0; i
<(int)m_EmbeddedDevices
.GetItemCount(); i
++) {
683 res
= m_EmbeddedDevices
[i
]->FindEmbeddedDevice(
686 if (NPT_SUCCEEDED(res
)) return res
;
692 /*----------------------------------------------------------------------
693 | PLT_DeviceData::FindEmbeddedDeviceByType
694 +---------------------------------------------------------------------*/
696 PLT_DeviceData::FindEmbeddedDeviceByType(const char* type
,
697 PLT_DeviceDataReference
& device
)
699 NPT_Result res
= NPT_ContainerFind(m_EmbeddedDevices
,
700 PLT_DeviceDataFinderByType(type
),
702 if (NPT_SUCCEEDED(res
)) return res
;
704 for (int i
=0; i
<(int)m_EmbeddedDevices
.GetItemCount(); i
++) {
705 res
= m_EmbeddedDevices
[i
]->FindEmbeddedDeviceByType(
708 if (NPT_SUCCEEDED(res
)) return res
;
714 /*----------------------------------------------------------------------
715 | PLT_DeviceData::FindServiceById
716 +---------------------------------------------------------------------*/
718 PLT_DeviceData::FindServiceById(const char* id
, PLT_Service
*& service
)
720 // do not try to find it within embedded devices, since different
721 // embedded devices could have an identical service
722 return NPT_ContainerFind(m_Services
,
723 PLT_ServiceIDFinder(id
),
727 /*----------------------------------------------------------------------
728 | PLT_DeviceData::FindServiceByType
729 +---------------------------------------------------------------------*/
731 PLT_DeviceData::FindServiceByType(const char* type
, PLT_Service
*& service
)
733 // do not try to find it within embedded devices, since different
734 // embedded devices could have an identical service
735 return NPT_ContainerFind(m_Services
,
736 PLT_ServiceTypeFinder(type
),
740 /*----------------------------------------------------------------------
741 | PLT_DeviceData::FindServiceByName
742 +---------------------------------------------------------------------*/
744 PLT_DeviceData::FindServiceByName(const char* name
, PLT_Service
*& service
)
746 // do not try to find it within embedded devices, since different
747 // embedded devices could have an identical service
748 return NPT_ContainerFind(m_Services
,
749 PLT_ServiceNameFinder(name
),
753 /*----------------------------------------------------------------------
754 | PLT_DeviceData::FindServiceBySCPDURL
755 +---------------------------------------------------------------------*/
757 PLT_DeviceData::FindServiceBySCPDURL(const char* url
,
758 PLT_Service
*& service
,
759 bool recursive
/* = false */)
761 NPT_Result res
= NPT_ContainerFind(
763 PLT_ServiceSCPDURLFinder(url
),
765 if (NPT_SUCCEEDED(res
)) return res
;
768 for (int i
=0; i
<(int)m_EmbeddedDevices
.GetItemCount(); i
++) {
769 res
= m_EmbeddedDevices
[i
]->FindServiceBySCPDURL(
773 if (NPT_SUCCEEDED(res
)) return res
;
780 /*----------------------------------------------------------------------
781 | PLT_DeviceData::FindServiceByControlURL
782 +---------------------------------------------------------------------*/
784 PLT_DeviceData::FindServiceByControlURL(const char* url
,
785 PLT_Service
*& service
,
786 bool recursive
/* = false */)
788 NPT_Result res
= NPT_ContainerFind(m_Services
,
789 PLT_ServiceControlURLFinder(url
),
791 if (NPT_SUCCEEDED(res
)) return res
;
794 for (int i
=0; i
<(int)m_EmbeddedDevices
.GetItemCount(); i
++) {
795 res
= m_EmbeddedDevices
[i
]->FindServiceByControlURL(
799 if (NPT_SUCCEEDED(res
)) return res
;
806 /*----------------------------------------------------------------------
807 | PLT_DeviceData::FindServiceByEventSubURL
808 +---------------------------------------------------------------------*/
810 PLT_DeviceData::FindServiceByEventSubURL(const char* url
,
811 PLT_Service
*& service
,
812 bool recursive
/* = false */)
814 NPT_Result res
= NPT_ContainerFind(m_Services
,
815 PLT_ServiceEventSubURLFinder(url
),
817 if (NPT_SUCCEEDED(res
)) return res
;
820 for (int i
=0; i
<(int)m_EmbeddedDevices
.GetItemCount(); i
++) {
821 res
= m_EmbeddedDevices
[i
]->FindServiceByEventSubURL(
825 if (NPT_SUCCEEDED(res
)) return res
;