Merge pull request #25959 from neo1973/TagLib_deprecation_warnings
[xbmc.git] / lib / libUPnP / Platinum / Source / Core / PltDeviceData.cpp
bloba322bc44345d8afb2c4b9b83c99eb2486b814362
1 /*****************************************************************
3 | Platinum - Device Data
5 | Copyright (c) 2004-2010, Plutinosoft, LLC.
6 | All rights reserved.
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 /*----------------------------------------------------------------------
36 | includes
37 +---------------------------------------------------------------------*/
38 #include "PltDeviceData.h"
39 #include "PltService.h"
40 #include "PltUPnP.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,
49 const char* uuid,
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"),
55 m_UUID(uuid),
56 m_URLDescription(description_url),
57 m_DeviceType(device_type),
58 m_FriendlyName(friendly_name),
59 m_BootId(0),
60 m_NextBootId(0)
62 if (uuid == NULL || strlen(uuid) == 0) {
63 PLT_UPnPMessageHelper::GenerateGUID(m_UUID);
66 SetLeaseTime(lease_time);
67 SetURLBase(m_URLDescription);
68 UpdateConfigId();
71 /*----------------------------------------------------------------------
72 | PLT_DeviceData::~PLT_DeviceData
73 +---------------------------------------------------------------------*/
74 PLT_DeviceData::~PLT_DeviceData()
76 Cleanup();
79 /*----------------------------------------------------------------------
80 | PLT_DeviceData::Cleanup
81 +---------------------------------------------------------------------*/
82 void
83 PLT_DeviceData::Cleanup()
85 m_Services.Apply(NPT_ObjectDeleter<PLT_Service>());
86 m_Services.Clear();
87 m_EmbeddedDevices.Clear();
88 m_Icons.Clear();
91 /*----------------------------------------------------------------------
92 | PLT_DeviceData::SetDescriptionUrl
93 +---------------------------------------------------------------------*/
94 NPT_Result
95 PLT_DeviceData::SetDescriptionUrl(NPT_HttpUrl& url)
97 NPT_CHECK_FATAL(SetURLBase(url));
98 m_URLDescription = url;
99 return NPT_SUCCESS;
102 /*----------------------------------------------------------------------
103 | PLT_DeviceData::GetDescriptionUrl
104 +---------------------------------------------------------------------*/
105 NPT_String
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 +---------------------------------------------------------------------*/
118 NPT_Result
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());
130 // update path
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);
141 return NPT_SUCCESS;
144 /*----------------------------------------------------------------------
145 | PLT_DeviceData::GetURLBase
146 +---------------------------------------------------------------------*/
147 NPT_HttpUrl
148 PLT_DeviceData::GetURLBase()
150 return m_URLBase;
153 /*----------------------------------------------------------------------
154 | PLT_DeviceData::NormalizeURL
155 +---------------------------------------------------------------------*/
156 NPT_HttpUrl
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);
164 } else {
165 norm_url.ParsePathPlus(norm_url.GetPath() + url);
168 return norm_url;
171 /*----------------------------------------------------------------------
172 | PLT_DeviceData::GetIconUrl
173 +---------------------------------------------------------------------*/
174 NPT_String
175 PLT_DeviceData::GetIconUrl(const char* mimetype,
176 NPT_Int32 maxsize,
177 NPT_Int32 maxdepth)
179 PLT_DeviceIcon icon;
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))
186 continue;
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())
193 continue;
195 icon = m_Icons[i];
198 if (icon.m_UrlPath == "") return "";
200 return NormalizeURL(icon.m_UrlPath).ToString();
203 /*----------------------------------------------------------------------
204 | PLT_DeviceData::UpdateConfigId
205 +---------------------------------------------------------------------*/
206 void
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 +---------------------------------------------------------------------*/
221 void
222 PLT_DeviceData::SetBootId(NPT_UInt32 bootId)
224 m_BootId = bootId;
227 /*----------------------------------------------------------------------
228 | PLT_DeviceData::SetNextBootId
229 +---------------------------------------------------------------------*/
230 void
231 PLT_DeviceData::SetNextBootId(NPT_UInt32 nextBootId)
233 m_NextBootId = nextBootId;
236 /*----------------------------------------------------------------------
237 | PLT_DeviceData::GenerateNextBootId
238 +---------------------------------------------------------------------*/
239 NPT_UInt32
240 PLT_DeviceData::GenerateNextBootId()
242 NPT_TimeStamp now;
243 NPT_System::GetCurrentTimeStamp(now);
244 NPT_UInt32 value = (NPT_UInt32)now.ToSeconds();
245 if (value == m_BootId) ++value;
246 return value;
249 /*----------------------------------------------------------------------
250 | PLT_DeviceData::SetLeaseTime
251 +---------------------------------------------------------------------*/
252 NPT_Result
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;
263 return NPT_SUCCESS;
266 /*----------------------------------------------------------------------
267 | PLT_DeviceData::GetLeaseTimeLastUpdate
268 +---------------------------------------------------------------------*/
269 NPT_TimeStamp
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 +---------------------------------------------------------------------*/
300 NPT_Result
301 PLT_DeviceData::AddEmbeddedDevice(PLT_DeviceDataReference& device)
303 UpdateConfigId();
305 device->m_ParentUUID = m_UUID;
306 return m_EmbeddedDevices.Add(device);
309 /*----------------------------------------------------------------------
310 | PLT_DeviceData::RemoveEmbeddedDevice
311 +---------------------------------------------------------------------*/
312 NPT_Result
313 PLT_DeviceData::RemoveEmbeddedDevice(PLT_DeviceDataReference& device)
315 for (NPT_Cardinal i=0;
316 i<m_EmbeddedDevices.GetItemCount();
317 i++) {
318 if (m_EmbeddedDevices[i] == device) {
319 UpdateConfigId();
320 return m_EmbeddedDevices.Erase(i);
324 return NPT_ERROR_NO_SUCH_ITEM;
327 /*----------------------------------------------------------------------
328 | PLT_DeviceData::AddService
329 +---------------------------------------------------------------------*/
330 NPT_Result
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;
340 UpdateConfigId();
341 return m_Services.Add(service);
344 /*----------------------------------------------------------------------
345 | PLT_DeviceData::RemoveService
346 +---------------------------------------------------------------------*/
347 NPT_Result
348 PLT_DeviceData::RemoveService(PLT_Service* service)
350 for (NPT_Cardinal i=0;
351 i<m_Services.GetItemCount();
352 i++) {
353 if (m_Services[i] == service) {
354 UpdateConfigId();
355 return m_Services.Erase(i);
359 return NPT_ERROR_NO_SUCH_ITEM;
362 /*----------------------------------------------------------------------
363 | PLT_GetDescriptionIterator class
364 +---------------------------------------------------------------------*/
365 template <class T>
366 class PLT_GetDescriptionIterator
368 public:
369 PLT_GetDescriptionIterator(NPT_XmlElementNode* parent) :
370 m_Parent(parent) {}
372 NPT_Result operator()(T& data) const {
373 return data->GetDescription(m_Parent);
376 private:
377 NPT_XmlElementNode* m_Parent;
380 /*----------------------------------------------------------------------
381 | PLT_DeviceData::GetDescription
382 +---------------------------------------------------------------------*/
383 NPT_Result
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));
391 // device properties
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));
410 // DLNA support
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);
424 // icons
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));
439 // services
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)));
445 // PS3 support
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);
453 // embedded devices
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)));
463 return NPT_SUCCESS;
466 /*----------------------------------------------------------------------
467 | PLT_DeviceData::GetDescription
468 +---------------------------------------------------------------------*/
469 NPT_Result
470 PLT_DeviceData::GetDescription(NPT_String& desc)
472 NPT_Result res;
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);
480 // add spec version
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);
486 // get device xml
487 NPT_CHECK_LABEL_SEVERE(res = GetDescription(root), cleanup);
489 // serialize node
490 NPT_CHECK_LABEL_SEVERE(res = PLT_XmlHelper::Serialize(*root, desc, true, 2), cleanup);
492 cleanup:
493 delete root;
494 return res;
497 /*----------------------------------------------------------------------
498 | PLT_DeviceData::SetDescription
499 +---------------------------------------------------------------------*/
500 NPT_Result
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;
509 NPT_Result res;
510 NPT_XmlElementNode* root = NULL;
511 NPT_String URLBase;
512 NPT_String configId;
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();
523 if (!root ||
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);
541 } else {
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))) {
557 NPT_UInt32 value;
558 if (NPT_SUCCEEDED(configId.ToInteger32(value))) {
559 root_device->m_ConfigId = value;
563 cleanup:
564 // delete the tree
565 delete tree;
566 return res;
569 /*----------------------------------------------------------------------
570 | PLT_DeviceData::SetDescriptionDevice
571 +---------------------------------------------------------------------*/
572 NPT_Result
573 PLT_DeviceData::SetDescriptionDevice(PLT_DeviceDataReference& device,
574 NPT_XmlElementNode* device_node,
575 const NPT_HttpRequestContext& context)
577 NPT_Result res;
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);
600 // enumerate icons
601 NPT_XmlElementNode* iconList = PLT_XmlHelper::GetChild(device_node, "iconList");
602 if (iconList) {
603 NPT_Array<NPT_XmlElementNode*> icons;
604 PLT_XmlHelper::GetChildren(iconList, icons, "icon");
606 for (NPT_Cardinal k=0 ; k<icons.GetItemCount(); k++) {
607 PLT_DeviceIcon icon;
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");
626 if (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))) {
645 delete service;
646 return res;
651 // enumerate embedded devices
652 NPT_XmlElementNode* deviceList = PLT_XmlHelper::GetChild(device_node, "deviceList");
653 if (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
666 return NPT_SUCCESS;
670 /*----------------------------------------------------------------------
671 | PLT_DeviceData::FindEmbeddedDevice
672 +---------------------------------------------------------------------*/
673 NPT_Result
674 PLT_DeviceData::FindEmbeddedDevice(const char* uuid,
675 PLT_DeviceDataReference& device)
677 NPT_Result res = NPT_ContainerFind(m_EmbeddedDevices,
678 PLT_DeviceDataFinder(uuid),
679 device);
680 if (NPT_SUCCEEDED(res)) return res;
682 for (int i=0; i<(int)m_EmbeddedDevices.GetItemCount(); i++) {
683 res = m_EmbeddedDevices[i]->FindEmbeddedDevice(
684 uuid,
685 device);
686 if (NPT_SUCCEEDED(res)) return res;
689 return NPT_FAILURE;
692 /*----------------------------------------------------------------------
693 | PLT_DeviceData::FindEmbeddedDeviceByType
694 +---------------------------------------------------------------------*/
695 NPT_Result
696 PLT_DeviceData::FindEmbeddedDeviceByType(const char* type,
697 PLT_DeviceDataReference& device)
699 NPT_Result res = NPT_ContainerFind(m_EmbeddedDevices,
700 PLT_DeviceDataFinderByType(type),
701 device);
702 if (NPT_SUCCEEDED(res)) return res;
704 for (int i=0; i<(int)m_EmbeddedDevices.GetItemCount(); i++) {
705 res = m_EmbeddedDevices[i]->FindEmbeddedDeviceByType(
706 type,
707 device);
708 if (NPT_SUCCEEDED(res)) return res;
711 return NPT_FAILURE;
714 /*----------------------------------------------------------------------
715 | PLT_DeviceData::FindServiceById
716 +---------------------------------------------------------------------*/
717 NPT_Result
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),
724 service);
727 /*----------------------------------------------------------------------
728 | PLT_DeviceData::FindServiceByType
729 +---------------------------------------------------------------------*/
730 NPT_Result
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),
737 service);
740 /*----------------------------------------------------------------------
741 | PLT_DeviceData::FindServiceByName
742 +---------------------------------------------------------------------*/
743 NPT_Result
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),
750 service);
753 /*----------------------------------------------------------------------
754 | PLT_DeviceData::FindServiceBySCPDURL
755 +---------------------------------------------------------------------*/
756 NPT_Result
757 PLT_DeviceData::FindServiceBySCPDURL(const char* url,
758 PLT_Service*& service,
759 bool recursive /* = false */)
761 NPT_Result res = NPT_ContainerFind(
762 m_Services,
763 PLT_ServiceSCPDURLFinder(url),
764 service);
765 if (NPT_SUCCEEDED(res)) return res;
767 if (recursive) {
768 for (int i=0; i<(int)m_EmbeddedDevices.GetItemCount(); i++) {
769 res = m_EmbeddedDevices[i]->FindServiceBySCPDURL(
770 url,
771 service,
772 recursive);
773 if (NPT_SUCCEEDED(res)) return res;
777 return NPT_FAILURE;
780 /*----------------------------------------------------------------------
781 | PLT_DeviceData::FindServiceByControlURL
782 +---------------------------------------------------------------------*/
783 NPT_Result
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),
790 service);
791 if (NPT_SUCCEEDED(res)) return res;
793 if (recursive) {
794 for (int i=0; i<(int)m_EmbeddedDevices.GetItemCount(); i++) {
795 res = m_EmbeddedDevices[i]->FindServiceByControlURL(
796 url,
797 service,
798 recursive);
799 if (NPT_SUCCEEDED(res)) return res;
803 return NPT_FAILURE;
806 /*----------------------------------------------------------------------
807 | PLT_DeviceData::FindServiceByEventSubURL
808 +---------------------------------------------------------------------*/
809 NPT_Result
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),
816 service);
817 if (NPT_SUCCEEDED(res)) return res;
819 if (recursive) {
820 for (int i=0; i<(int)m_EmbeddedDevices.GetItemCount(); i++) {
821 res = m_EmbeddedDevices[i]->FindServiceByEventSubURL(
822 url,
823 service,
824 recursive);
825 if (NPT_SUCCEEDED(res)) return res;
829 return NPT_FAILURE;