Merge pull request #26354 from ksooo/pvr-fix-listitem-titleextrainfo
[xbmc.git] / lib / libUPnP / Platinum / Source / Devices / MediaServer / PltMediaBrowser.cpp
blob24784411e583d27f97ba29d3c3a0ae4d98c6c92b
1 /*****************************************************************
3 | Platinum - AV Media Browser (Media Server Control Point)
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 "Neptune.h"
39 #include "PltMediaBrowser.h"
40 #include "PltDidl.h"
42 NPT_SET_LOCAL_LOGGER("platinum.media.server.browser")
44 /*----------------------------------------------------------------------
45 | PLT_MediaBrowser::PLT_MediaBrowser
46 +---------------------------------------------------------------------*/
47 PLT_MediaBrowser::PLT_MediaBrowser(PLT_CtrlPointReference& ctrl_point,
48 PLT_MediaBrowserDelegate* delegate /* = NULL */) :
49 m_CtrlPoint(ctrl_point),
50 m_Delegate(delegate)
52 m_CtrlPoint->AddListener(this);
55 /*----------------------------------------------------------------------
56 | PLT_MediaBrowser::~PLT_MediaBrowser
57 +---------------------------------------------------------------------*/
58 PLT_MediaBrowser::~PLT_MediaBrowser()
60 m_CtrlPoint->RemoveListener(this);
63 /*----------------------------------------------------------------------
64 | PLT_MediaBrowser::OnDeviceAdded
65 +---------------------------------------------------------------------*/
66 NPT_Result
67 PLT_MediaBrowser::OnDeviceAdded(PLT_DeviceDataReference& device)
69 // verify the device implements the function we need
70 PLT_Service* serviceCDS;
71 PLT_Service* serviceCMR;
72 NPT_String type;
74 if (!device->GetType().StartsWith("urn:schemas-upnp-org:device:MediaServer"))
75 return NPT_FAILURE;
77 type = "urn:schemas-upnp-org:service:ContentDirectory:*";
78 if (NPT_FAILED(device->FindServiceByType(type, serviceCDS))) {
79 NPT_LOG_WARNING_2("Service %s not found in device \"%s\"",
80 type.GetChars(),
81 device->GetFriendlyName().GetChars());
82 return NPT_FAILURE;
83 } else {
84 // in case it's a newer upnp implementation, force to 1
85 serviceCDS->ForceVersion(1);
88 type = "urn:schemas-upnp-org:service:ConnectionManager:*";
89 if (NPT_FAILED(device->FindServiceByType(type, serviceCMR))) {
90 NPT_LOG_WARNING_2("Service %s not found in device \"%s\"",
91 type.GetChars(),
92 device->GetFriendlyName().GetChars());
93 return NPT_FAILURE;
94 } else {
95 // in case it's a newer upnp implementation, force to 1
96 serviceCMR->ForceVersion(1);
100 NPT_AutoLock lock(m_MediaServers);
102 PLT_DeviceDataReference data;
103 NPT_String uuid = device->GetUUID();
105 // is it a new device?
106 if (NPT_SUCCEEDED(NPT_ContainerFind(m_MediaServers, PLT_DeviceDataFinder(uuid), data))) {
107 NPT_LOG_WARNING_1("Device (%s) is already in our list!", (const char*)uuid);
108 return NPT_FAILURE;
111 NPT_LOG_FINE_1("Device Found: %s", (const char*)*device);
113 m_MediaServers.Add(device);
116 if (m_Delegate && m_Delegate->OnMSAdded(device)) {
117 m_CtrlPoint->Subscribe(serviceCDS);
118 m_CtrlPoint->Subscribe(serviceCMR);
121 return NPT_SUCCESS;
124 /*----------------------------------------------------------------------
125 | PLT_MediaBrowser::OnDeviceRemoved
126 +---------------------------------------------------------------------*/
127 NPT_Result
128 PLT_MediaBrowser::OnDeviceRemoved(PLT_DeviceDataReference& device)
130 if (!device->GetType().StartsWith("urn:schemas-upnp-org:device:MediaServer"))
131 return NPT_FAILURE;
134 NPT_AutoLock lock(m_MediaServers);
136 // only release if we have kept it around
137 PLT_DeviceDataReference data;
138 NPT_String uuid = device->GetUUID();
140 // Have we seen that device?
141 if (NPT_FAILED(NPT_ContainerFind(m_MediaServers, PLT_DeviceDataFinder(uuid), data))) {
142 NPT_LOG_WARNING_1("Device (%s) not found in our list!", (const char*)uuid);
143 return NPT_FAILURE;
146 NPT_LOG_FINE_1("Device Removed: %s", (const char*)*device);
148 m_MediaServers.Remove(device);
151 if (m_Delegate) {
152 m_Delegate->OnMSRemoved(device);
155 return NPT_SUCCESS;
158 /*----------------------------------------------------------------------
159 | PLT_MediaBrowser::FindServer
160 +---------------------------------------------------------------------*/
161 NPT_Result
162 PLT_MediaBrowser::FindServer(const char* uuid, PLT_DeviceDataReference& device)
164 NPT_AutoLock lock(m_MediaServers);
166 if (NPT_FAILED(NPT_ContainerFind(m_MediaServers, PLT_DeviceDataFinder(uuid), device))) {
167 NPT_LOG_FINE_1("Device (%s) not found in our list of servers", (const char*)uuid);
168 return NPT_FAILURE;
171 return NPT_SUCCESS;
174 /*----------------------------------------------------------------------
175 | PLT_MediaBrowser::Search
176 +---------------------------------------------------------------------*/
177 NPT_Result
178 PLT_MediaBrowser::Search(PLT_DeviceDataReference& device,
179 const char* container_id,
180 const char* search_criteria,
181 NPT_UInt32 start_index,
182 NPT_UInt32 count,
183 const char* filter,
184 void* userdata)
186 // verify device still in our list
187 PLT_DeviceDataReference device_data;
188 NPT_CHECK_WARNING(FindServer(device->GetUUID(), device_data));
190 // create action
191 PLT_ActionReference action;
192 NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(
193 device,
194 "urn:schemas-upnp-org:service:ContentDirectory:1",
195 "Search",
196 action));
198 // Set the container id
199 PLT_Arguments args;
200 if (NPT_FAILED(action->SetArgumentValue("ContainerID", container_id))) {
201 return NPT_ERROR_INVALID_PARAMETERS;
204 // set the Search Criteria
205 if (NPT_FAILED(action->SetArgumentValue("SearchCriteria", search_criteria))) {
206 return NPT_ERROR_INVALID_PARAMETERS;
210 // set the Filter
211 if (NPT_FAILED(action->SetArgumentValue("Filter", filter))) {
212 return NPT_ERROR_INVALID_PARAMETERS;
215 // set the Starting Index
216 if (NPT_FAILED(action->SetArgumentValue("StartingIndex",
217 NPT_String::FromInteger(start_index)))) {
218 return NPT_ERROR_INVALID_PARAMETERS;
221 // set the Requested Count
222 if (NPT_FAILED(action->SetArgumentValue("RequestedCount",
223 NPT_String::FromInteger(count)))) {
224 return NPT_ERROR_INVALID_PARAMETERS;
227 // set the Requested Count
228 if (NPT_FAILED(action->SetArgumentValue("SortCriteria", ""))) {
229 return NPT_ERROR_INVALID_PARAMETERS;
232 // invoke the action
233 if (NPT_FAILED(m_CtrlPoint->InvokeAction(action, userdata))) {
234 return NPT_ERROR_INVALID_PARAMETERS;
237 return NPT_SUCCESS;
240 /*----------------------------------------------------------------------
241 | PLT_MediaBrowser::Browse
242 +---------------------------------------------------------------------*/
243 NPT_Result
244 PLT_MediaBrowser::Browse(PLT_DeviceDataReference& device,
245 const char* obj_id,
246 NPT_UInt32 start_index,
247 NPT_UInt32 count,
248 bool browse_metadata,
249 const char* filter,
250 const char* sort_criteria,
251 void* userdata)
253 // verify device still in our list
254 PLT_DeviceDataReference device_data;
255 NPT_CHECK_WARNING(FindServer(device->GetUUID(), device_data));
257 // create action
258 PLT_ActionReference action;
259 NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(
260 device,
261 "urn:schemas-upnp-org:service:ContentDirectory:1",
262 "Browse",
263 action));
265 // Set the object id
266 PLT_Arguments args;
267 if (NPT_FAILED(action->SetArgumentValue("ObjectID", obj_id))) {
268 return NPT_ERROR_INVALID_PARAMETERS;
271 // set the browse_flag
272 if (NPT_FAILED(action->SetArgumentValue("BrowseFlag",
273 browse_metadata?"BrowseMetadata":"BrowseDirectChildren"))) {
274 return NPT_ERROR_INVALID_PARAMETERS;
277 // set the Filter
278 if (NPT_FAILED(action->SetArgumentValue("Filter", filter))) {
279 return NPT_ERROR_INVALID_PARAMETERS;
282 // set the Starting Index
283 if (NPT_FAILED(action->SetArgumentValue("StartingIndex",
284 NPT_String::FromInteger(start_index)))) {
285 return NPT_ERROR_INVALID_PARAMETERS;
288 // set the Requested Count
289 if (NPT_FAILED(action->SetArgumentValue("RequestedCount",
290 NPT_String::FromInteger(count)))) {
291 return NPT_ERROR_INVALID_PARAMETERS;
294 // set the Requested Count
295 if (NPT_FAILED(action->SetArgumentValue("SortCriteria", sort_criteria))) {
296 return NPT_ERROR_INVALID_PARAMETERS;
299 // invoke the action
300 if (NPT_FAILED(m_CtrlPoint->InvokeAction(action, userdata))) {
301 return NPT_ERROR_INVALID_PARAMETERS;
304 return NPT_SUCCESS;
307 /*----------------------------------------------------------------------
308 | PLT_MediaBrowser::GetSearchCapabilities
309 +---------------------------------------------------------------------*/
310 NPT_Result
311 PLT_MediaBrowser::GetSearchCapabilities(PLT_DeviceDataReference& device,
312 void* userdata)
314 // verify device still in our list
315 PLT_DeviceDataReference device_data;
316 NPT_CHECK_WARNING(FindServer(device->GetUUID(), device_data));
318 // create action
319 PLT_ActionReference action;
320 NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(
321 device,
322 "urn:schemas-upnp-org:service:ContentDirectory:1",
323 "GetSearchCapabilities",
324 action));
326 // invoke the action
327 if (NPT_FAILED(m_CtrlPoint->InvokeAction(action, userdata))) {
328 return NPT_ERROR_INVALID_PARAMETERS;
331 return NPT_SUCCESS;
334 /*----------------------------------------------------------------------
335 | PLT_MediaBrowser::GetSortCapabilities
336 +---------------------------------------------------------------------*/
337 NPT_Result
338 PLT_MediaBrowser::GetSortCapabilities(PLT_DeviceDataReference& device,
339 void* userdata)
341 // verify device still in our list
342 PLT_DeviceDataReference device_data;
343 NPT_CHECK_WARNING(FindServer(device->GetUUID(), device_data));
345 // create action
346 PLT_ActionReference action;
347 NPT_CHECK_SEVERE(m_CtrlPoint->CreateAction(
348 device,
349 "urn:schemas-upnp-org:service:ContentDirectory:1",
350 "GetSortCapabilities",
351 action));
353 // invoke the action
354 if (NPT_FAILED(m_CtrlPoint->InvokeAction(action, userdata))) {
355 return NPT_ERROR_INVALID_PARAMETERS;
358 return NPT_SUCCESS;
361 /*----------------------------------------------------------------------
362 | PLT_MediaBrowser::OnActionResponse
363 +---------------------------------------------------------------------*/
364 NPT_Result
365 PLT_MediaBrowser::OnActionResponse(NPT_Result res,
366 PLT_ActionReference& action,
367 void* userdata)
369 // look for device in our list first
370 PLT_DeviceDataReference device;
371 NPT_String uuid = action->GetActionDesc().GetService()->GetDevice()->GetUUID();
372 if (NPT_FAILED(FindServer(uuid, device))) res = NPT_FAILURE;
374 NPT_String actionName = action->GetActionDesc().GetName();
375 if (actionName.Compare("Browse", true) == 0) {
376 return OnBrowseResponse(res, device, action, userdata);
377 } else if (actionName.Compare("Search", true) == 0) {
378 return OnSearchResponse(res, device, action, userdata);
379 } else if (actionName.Compare("GetSearchCapabilities", true) == 0) {
380 return OnGetSearchCapabilitiesResponse(res, device, action, userdata);
381 } else if (actionName.Compare("GetSortCapabilities", true) == 0) {
382 return OnGetSortCapabilitiesResponse(res, device, action, userdata);
385 return NPT_SUCCESS;
388 /*----------------------------------------------------------------------
389 | PLT_MediaBrowser::OnBrowseResponse
390 +---------------------------------------------------------------------*/
391 NPT_Result
392 PLT_MediaBrowser::OnBrowseResponse(NPT_Result res,
393 PLT_DeviceDataReference& device,
394 PLT_ActionReference& action,
395 void* userdata)
397 NPT_String value;
398 PLT_BrowseInfo info;
399 NPT_String unescaped;
401 if (!m_Delegate) return NPT_SUCCESS;
403 if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
404 goto bad_action;
407 if (NPT_FAILED(action->GetArgumentValue("ObjectID", info.object_id))) {
408 goto bad_action;
410 if (NPT_FAILED(action->GetArgumentValue("UpdateID", value)) ||
411 value.GetLength() == 0 ||
412 NPT_FAILED(value.ToInteger(info.uid))) {
413 goto bad_action;
415 if (NPT_FAILED(action->GetArgumentValue("NumberReturned", value)) ||
416 value.GetLength() == 0 ||
417 NPT_FAILED(value.ToInteger(info.nr))) {
418 goto bad_action;
420 if (NPT_FAILED(action->GetArgumentValue("TotalMatches", value)) ||
421 value.GetLength() == 0 ||
422 NPT_FAILED(value.ToInteger(info.tm))) {
423 goto bad_action;
425 if (NPT_FAILED(action->GetArgumentValue("Result", value)) ||
426 value.GetLength() == 0) {
427 goto bad_action;
430 if (NPT_FAILED(PLT_Didl::FromDidl(value, info.items))) {
431 goto bad_action;
434 m_Delegate->OnBrowseResult(NPT_SUCCESS, device, &info, userdata);
435 return NPT_SUCCESS;
437 bad_action:
438 m_Delegate->OnBrowseResult(NPT_FAILURE, device, NULL, userdata);
439 return NPT_FAILURE;
442 /*----------------------------------------------------------------------
443 | PLT_MediaBrowser::OnSearchResponse
444 +---------------------------------------------------------------------*/
445 NPT_Result
446 PLT_MediaBrowser::OnSearchResponse(NPT_Result res,
447 PLT_DeviceDataReference& device,
448 PLT_ActionReference& action,
449 void* userdata)
451 NPT_String value;
452 PLT_BrowseInfo info;
453 NPT_String unescaped;
455 if (!m_Delegate) return NPT_SUCCESS;
457 if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
458 goto bad_action;
461 if (NPT_FAILED(action->GetArgumentValue("ContainerId", info.object_id))) {
462 goto bad_action;
464 if (NPT_FAILED(action->GetArgumentValue("UpdateID", value)) ||
465 value.GetLength() == 0 ||
466 NPT_FAILED(value.ToInteger(info.uid))) {
467 goto bad_action;
469 if (NPT_FAILED(action->GetArgumentValue("NumberReturned", value)) ||
470 value.GetLength() == 0 ||
471 NPT_FAILED(value.ToInteger(info.nr))) {
472 goto bad_action;
474 if (NPT_FAILED(action->GetArgumentValue("TotalMatches", value)) ||
475 value.GetLength() == 0 ||
476 NPT_FAILED(value.ToInteger(info.tm))) {
477 goto bad_action;
479 if (NPT_FAILED(action->GetArgumentValue("Result", value)) ||
480 value.GetLength() == 0) {
481 goto bad_action;
484 if (NPT_FAILED(PLT_Didl::FromDidl(value, info.items))) {
485 goto bad_action;
488 m_Delegate->OnSearchResult(NPT_SUCCESS, device, &info, userdata);
489 return NPT_SUCCESS;
491 bad_action:
492 m_Delegate->OnSearchResult(NPT_FAILURE, device, NULL, userdata);
493 return NPT_FAILURE;
496 /*----------------------------------------------------------------------
497 | PLT_MediaBrowser::OnGetSearchCapabilitiesResponse
498 +---------------------------------------------------------------------*/
499 NPT_Result
500 PLT_MediaBrowser::OnGetSearchCapabilitiesResponse(NPT_Result res,
501 PLT_DeviceDataReference& device,
502 PLT_ActionReference& action,
503 void* userdata)
505 NPT_String value;
507 if (!m_Delegate) return NPT_SUCCESS;
509 if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
510 goto bad_action;
513 if (NPT_FAILED(action->GetArgumentValue("SearchCaps", value))) {
514 goto bad_action;
517 m_Delegate->OnGetSearchCapabilitiesResult(NPT_SUCCESS, device, value, userdata);
518 return NPT_SUCCESS;
520 bad_action:
521 m_Delegate->OnGetSearchCapabilitiesResult(NPT_FAILURE, device, value, userdata);
522 return NPT_FAILURE;
525 /*----------------------------------------------------------------------
526 | PLT_MediaBrowser::OnGetSearchCapabilitiesResponse
527 +---------------------------------------------------------------------*/
528 NPT_Result
529 PLT_MediaBrowser::OnGetSortCapabilitiesResponse(NPT_Result res,
530 PLT_DeviceDataReference& device,
531 PLT_ActionReference& action,
532 void* userdata)
534 NPT_String value;
536 if (!m_Delegate) return NPT_SUCCESS;
538 if (NPT_FAILED(res) || action->GetErrorCode() != 0) {
539 goto bad_action;
542 if (NPT_FAILED(action->GetArgumentValue("SortCaps", value))) {
543 goto bad_action;
546 m_Delegate->OnGetSortCapabilitiesResult(NPT_SUCCESS, device, value, userdata);
547 return NPT_SUCCESS;
549 bad_action:
550 m_Delegate->OnGetSortCapabilitiesResult(NPT_FAILURE, device, value, userdata);
551 return NPT_FAILURE;
554 /*----------------------------------------------------------------------
555 | PLT_MediaBrowser::OnEventNotify
556 +---------------------------------------------------------------------*/
557 NPT_Result
558 PLT_MediaBrowser::OnEventNotify(PLT_Service* service, NPT_List<PLT_StateVariable*>* vars)
560 if (!service->GetDevice()->GetType().StartsWith("urn:schemas-upnp-org:device:MediaServer"))
561 return NPT_FAILURE;
563 if (!m_Delegate) return NPT_SUCCESS;
565 /* make sure device associated to service is still around */
566 PLT_DeviceDataReference data;
567 NPT_CHECK_WARNING(FindServer(service->GetDevice()->GetUUID(), data));
569 m_Delegate->OnMSStateVariablesChanged(service, vars);
570 return NPT_SUCCESS;