|
a/libupnpp/control/cdirectory.cxx |
|
b/libupnpp/control/cdirectory.cxx |
|
... |
|
... |
37 |
#include "libupnpp/soaphelp.hxx" // for SoapOutgoing, SoapOutgoing, etc
|
37 |
#include "libupnpp/soaphelp.hxx" // for SoapOutgoing, SoapOutgoing, etc
|
38 |
#include "libupnpp/upnpp_p.hxx" // for csvToStrings
|
38 |
#include "libupnpp/upnpp_p.hxx" // for csvToStrings
|
39 |
|
39 |
|
40 |
using namespace std;
|
40 |
using namespace std;
|
41 |
using namespace std::placeholders;
|
41 |
using namespace std::placeholders;
|
|
|
42 |
using namespace UPnPP;
|
42 |
|
43 |
|
43 |
namespace UPnPClient {
|
44 |
namespace UPnPClient {
|
44 |
|
45 |
|
45 |
// The service type string for Content Directories:
|
46 |
// The service type string for Content Directories:
|
46 |
const string ContentDirectory::SType("urn:schemas-upnp-org:service:ContentDirectory:1");
|
47 |
const string ContentDirectory::SType("urn:schemas-upnp-org:service:ContentDirectory:1");
|
|
... |
|
... |
90 |
ContentDirectory::ContentDirectory(const UPnPDeviceDesc& device,
|
91 |
ContentDirectory::ContentDirectory(const UPnPDeviceDesc& device,
|
91 |
const UPnPServiceDesc& service)
|
92 |
const UPnPServiceDesc& service)
|
92 |
: Service(device, service), m_rdreqcnt(200), m_serviceKind(CDSKIND_UNKNOWN)
|
93 |
: Service(device, service), m_rdreqcnt(200), m_serviceKind(CDSKIND_UNKNOWN)
|
93 |
{
|
94 |
{
|
94 |
LOGERR("ContentDirectory::ContentDirectory: manufacturer: " <<
|
95 |
LOGERR("ContentDirectory::ContentDirectory: manufacturer: " <<
|
95 |
m_manufacturer << " model " << m_modelName << endl);
|
96 |
getManufacturer() << " model " << getModelName() << endl);
|
96 |
|
97 |
|
97 |
if (bubble_rx(m_modelName)) {
|
98 |
if (bubble_rx(getModelName())) {
|
98 |
m_serviceKind = CDSKIND_BUBBLE;
|
99 |
m_serviceKind = CDSKIND_BUBBLE;
|
99 |
LOGDEB1("ContentDirectory::ContentDirectory: BUBBLE" << endl);
|
100 |
LOGDEB1("ContentDirectory::ContentDirectory: BUBBLE" << endl);
|
100 |
} else if (mediatomb_rx(m_modelName)) {
|
101 |
} else if (mediatomb_rx(getModelName())) {
|
101 |
// Readdir by 200 entries is good for most, but MediaTomb likes
|
102 |
// Readdir by 200 entries is good for most, but MediaTomb likes
|
102 |
// them really big. Actually 1000 is better but I don't dare
|
103 |
// them really big. Actually 1000 is better but I don't dare
|
103 |
m_rdreqcnt = 500;
|
104 |
m_rdreqcnt = 500;
|
104 |
m_serviceKind = CDSKIND_MEDIATOMB;
|
105 |
m_serviceKind = CDSKIND_MEDIATOMB;
|
105 |
LOGDEB1("ContentDirectory::ContentDirectory: MEDIATOMB" << endl);
|
106 |
LOGDEB1("ContentDirectory::ContentDirectory: MEDIATOMB" << endl);
|
106 |
} else if (minidlna_rx(m_modelName)) {
|
107 |
} else if (minidlna_rx(getModelName())) {
|
107 |
m_serviceKind = CDSKIND_MINIDLNA;
|
108 |
m_serviceKind = CDSKIND_MINIDLNA;
|
108 |
LOGDEB1("ContentDirectory::ContentDirectory: MINIDLNA" << endl);
|
109 |
LOGDEB1("ContentDirectory::ContentDirectory: MINIDLNA" << endl);
|
109 |
} else if (minim_rx(m_modelName)) {
|
110 |
} else if (minim_rx(getModelName())) {
|
110 |
m_serviceKind = CDSKIND_MINIM;
|
111 |
m_serviceKind = CDSKIND_MINIM;
|
111 |
LOGDEB1("ContentDirectory::ContentDirectory: MINIM" << endl);
|
112 |
LOGDEB1("ContentDirectory::ContentDirectory: MINIM" << endl);
|
112 |
} else if (twonky_rx(m_modelName)) {
|
113 |
} else if (twonky_rx(getModelName())) {
|
113 |
m_serviceKind = CDSKIND_TWONKY;
|
114 |
m_serviceKind = CDSKIND_TWONKY;
|
114 |
LOGDEB1("ContentDirectory::ContentDirectory: TWONKY" << endl);
|
115 |
LOGDEB1("ContentDirectory::ContentDirectory: TWONKY" << endl);
|
115 |
}
|
116 |
}
|
116 |
registerCallback();
|
117 |
registerCallback();
|
117 |
}
|
118 |
}
|
|
... |
|
... |
177 |
ixmlwPrintDoc(act->ActionRequest) << endl <<
|
178 |
ixmlwPrintDoc(act->ActionRequest) << endl <<
|
178 |
" actionresult " << ixmlwPrintDoc(act->ActionResult) << endl);
|
179 |
" actionresult " << ixmlwPrintDoc(act->ActionResult) << endl);
|
179 |
return 0;
|
180 |
return 0;
|
180 |
}
|
181 |
}
|
181 |
int ret =
|
182 |
int ret =
|
182 |
UpnpSendActionAsync(hdl, m_actionURL.c_str(), m_serviceType.c_str(),
|
183 |
UpnpSendActionAsync(hdl, getActionURL().c_str(), getServiceType().c_str(),
|
183 |
0 /*devUDN*/, request, asyncReaddirCB, 0);
|
184 |
0 /*devUDN*/, request, asyncReaddirCB, 0);
|
184 |
sleep(10);
|
185 |
sleep(10);
|
185 |
return -1;
|
186 |
return -1;
|
186 |
#endif
|
187 |
#endif
|
187 |
|
188 |
|
|
... |
|
... |
203 |
LOGDEB("CDService::readDirSlice: objId [" << objectId << "] offset " <<
|
204 |
LOGDEB("CDService::readDirSlice: objId [" << objectId << "] offset " <<
|
204 |
offset << " count " << count << endl);
|
205 |
offset << " count " << count << endl);
|
205 |
|
206 |
|
206 |
// Create request
|
207 |
// Create request
|
207 |
// Some devices require an empty SortCriteria, else bad params
|
208 |
// Some devices require an empty SortCriteria, else bad params
|
208 |
SoapOutgoing args(m_serviceType, "Browse");
|
209 |
SoapOutgoing args(getServiceType(), "Browse");
|
209 |
args("ObjectID", objectId)
|
210 |
args("ObjectID", objectId)
|
210 |
("BrowseFlag", "BrowseDirectChildren")
|
211 |
("BrowseFlag", "BrowseDirectChildren")
|
211 |
("Filter", "*")
|
212 |
("Filter", "*")
|
212 |
("SortCriteria", "")
|
213 |
("SortCriteria", "")
|
213 |
("StartingIndex", SoapHelp::i2s(offset))
|
214 |
("StartingIndex", SoapHelp::i2s(offset))
|
|
... |
|
... |
218 |
if (ret != UPNP_E_SUCCESS) {
|
219 |
if (ret != UPNP_E_SUCCESS) {
|
219 |
return ret;
|
220 |
return ret;
|
220 |
}
|
221 |
}
|
221 |
|
222 |
|
222 |
string tbuf;
|
223 |
string tbuf;
|
223 |
if (!data.getInt("NumberReturned", didread) ||
|
224 |
if (!data.get("NumberReturned", didread) ||
|
224 |
!data.getInt("TotalMatches", total) ||
|
225 |
!data.get("TotalMatches", total) ||
|
225 |
!data.getString("Result", &tbuf)) {
|
226 |
!data.get("Result", &tbuf)) {
|
226 |
LOGERR("CDService::readDir: missing elts in response" << endl);
|
227 |
LOGERR("CDService::readDir: missing elts in response" << endl);
|
227 |
return UPNP_E_BAD_RESPONSE;
|
228 |
return UPNP_E_BAD_RESPONSE;
|
228 |
}
|
229 |
}
|
229 |
|
230 |
|
230 |
if (*didread <= 0) {
|
231 |
if (*didread <= 0) {
|
|
... |
|
... |
245 |
}
|
246 |
}
|
246 |
|
247 |
|
247 |
int ContentDirectory::readDir(const string& objectId,
|
248 |
int ContentDirectory::readDir(const string& objectId,
|
248 |
UPnPDirContent& dirbuf)
|
249 |
UPnPDirContent& dirbuf)
|
249 |
{
|
250 |
{
|
250 |
LOGDEB("CDService::readDir: url [" << m_actionURL << "] type [" <<
|
251 |
LOGDEB("CDService::readDir: url [" << getActionURL() << "] type [" <<
|
251 |
m_serviceType << "] udn [" << m_deviceId << "] objId [" <<
|
252 |
getServiceType() << "] udn [" << getDeviceId() << "] objId [" <<
|
252 |
objectId << endl);
|
253 |
objectId << endl);
|
253 |
|
254 |
|
254 |
int offset = 0;
|
255 |
int offset = 0;
|
255 |
int total = 1000;// Updated on first read.
|
256 |
int total = 1000;// Updated on first read.
|
256 |
|
257 |
|
|
... |
|
... |
274 |
{
|
275 |
{
|
275 |
LOGDEB("CDService::searchSlice: objId [" << objectId << "] offset " <<
|
276 |
LOGDEB("CDService::searchSlice: objId [" << objectId << "] offset " <<
|
276 |
offset << " count " << count << endl);
|
277 |
offset << " count " << count << endl);
|
277 |
|
278 |
|
278 |
// Create request
|
279 |
// Create request
|
279 |
SoapOutgoing args(m_serviceType, "Search");
|
280 |
SoapOutgoing args(getServiceType(), "Search");
|
280 |
args("ContainerID", objectId)
|
281 |
args("ContainerID", objectId)
|
281 |
("SearchCriteria", ss)
|
282 |
("SearchCriteria", ss)
|
282 |
("Filter", "*")
|
283 |
("Filter", "*")
|
283 |
("SortCriteria", "")
|
284 |
("SortCriteria", "")
|
284 |
("StartingIndex", SoapHelp::i2s(offset))
|
285 |
("StartingIndex", SoapHelp::i2s(offset))
|
|
... |
|
... |
292 |
UpnpGetErrorMessage(ret) << endl);
|
293 |
UpnpGetErrorMessage(ret) << endl);
|
293 |
return ret;
|
294 |
return ret;
|
294 |
}
|
295 |
}
|
295 |
|
296 |
|
296 |
string tbuf;
|
297 |
string tbuf;
|
297 |
if (!data.getInt("NumberReturned", didread) ||
|
298 |
if (!data.get("NumberReturned", didread) ||
|
298 |
!data.getInt("TotalMatches", total) ||
|
299 |
!data.get("TotalMatches", total) ||
|
299 |
!data.getString("Result", &tbuf)) {
|
300 |
!data.get("Result", &tbuf)) {
|
300 |
LOGERR("CDService::search: missing elts in response" << endl);
|
301 |
LOGERR("CDService::search: missing elts in response" << endl);
|
301 |
return UPNP_E_BAD_RESPONSE;
|
302 |
return UPNP_E_BAD_RESPONSE;
|
302 |
}
|
303 |
}
|
303 |
if (*didread <= 0) {
|
304 |
if (*didread <= 0) {
|
304 |
LOGINF("CDService::search: got -1 or 0 entries" << endl);
|
305 |
LOGINF("CDService::search: got -1 or 0 entries" << endl);
|
|
... |
|
... |
312 |
|
313 |
|
313 |
int ContentDirectory::search(const string& objectId,
|
314 |
int ContentDirectory::search(const string& objectId,
|
314 |
const string& ss,
|
315 |
const string& ss,
|
315 |
UPnPDirContent& dirbuf)
|
316 |
UPnPDirContent& dirbuf)
|
316 |
{
|
317 |
{
|
317 |
LOGDEB("CDService::search: url [" << m_actionURL << "] type [" <<
|
318 |
LOGDEB("CDService::search: url [" << getActionURL() << "] type [" <<
|
318 |
m_serviceType << "] udn [" << m_deviceId << "] objid [" <<
|
319 |
getServiceType() << "] udn [" << getDeviceId() << "] objid [" <<
|
319 |
objectId << "] search [" << ss << "]" << endl);
|
320 |
objectId << "] search [" << ss << "]" << endl);
|
320 |
|
321 |
|
321 |
int offset = 0;
|
322 |
int offset = 0;
|
322 |
int total = 1000;// Updated on first read.
|
323 |
int total = 1000;// Updated on first read.
|
323 |
|
324 |
|
|
... |
|
... |
336 |
|
337 |
|
337 |
int ContentDirectory::getSearchCapabilities(set<string>& result)
|
338 |
int ContentDirectory::getSearchCapabilities(set<string>& result)
|
338 |
{
|
339 |
{
|
339 |
LOGDEB("CDService::getSearchCapabilities:" << endl);
|
340 |
LOGDEB("CDService::getSearchCapabilities:" << endl);
|
340 |
|
341 |
|
341 |
SoapOutgoing args(m_serviceType, "GetSearchCapabilities");
|
342 |
SoapOutgoing args(getServiceType(), "GetSearchCapabilities");
|
342 |
SoapIncoming data;
|
343 |
SoapIncoming data;
|
343 |
int ret = runAction(args, data);
|
344 |
int ret = runAction(args, data);
|
344 |
if (ret != UPNP_E_SUCCESS) {
|
345 |
if (ret != UPNP_E_SUCCESS) {
|
345 |
LOGINF("CDService::getSearchCapa: UpnpSendAction failed: " <<
|
346 |
LOGINF("CDService::getSearchCapa: UpnpSendAction failed: " <<
|
346 |
UpnpGetErrorMessage(ret) << endl);
|
347 |
UpnpGetErrorMessage(ret) << endl);
|
347 |
return ret;
|
348 |
return ret;
|
348 |
}
|
349 |
}
|
349 |
string tbuf;
|
350 |
string tbuf;
|
350 |
if (!data.getString("SearchCaps", &tbuf)) {
|
351 |
if (!data.get("SearchCaps", &tbuf)) {
|
351 |
LOGERR("CDService::getSearchCaps: missing Result in response" << endl);
|
352 |
LOGERR("CDService::getSearchCaps: missing Result in response" << endl);
|
352 |
cerr << tbuf << endl;
|
353 |
cerr << tbuf << endl;
|
353 |
return UPNP_E_BAD_RESPONSE;
|
354 |
return UPNP_E_BAD_RESPONSE;
|
354 |
}
|
355 |
}
|
355 |
|
356 |
|
|
... |
|
... |
366 |
}
|
367 |
}
|
367 |
|
368 |
|
368 |
int ContentDirectory::getMetadata(const string& objectId,
|
369 |
int ContentDirectory::getMetadata(const string& objectId,
|
369 |
UPnPDirContent& dirbuf)
|
370 |
UPnPDirContent& dirbuf)
|
370 |
{
|
371 |
{
|
371 |
LOGDEB("CDService::getMetadata: url [" << m_actionURL << "] type [" <<
|
372 |
LOGDEB("CDService::getMetadata: url [" << getActionURL() << "] type [" <<
|
372 |
m_serviceType << "] udn [" << m_deviceId << "] objId [" <<
|
373 |
getServiceType() << "] udn [" << getDeviceId() << "] objId [" <<
|
373 |
objectId << "]" << endl);
|
374 |
objectId << "]" << endl);
|
374 |
|
375 |
|
375 |
SoapOutgoing args(m_serviceType, "Browse");
|
376 |
SoapOutgoing args(getServiceType(), "Browse");
|
376 |
SoapIncoming data;
|
377 |
SoapIncoming data;
|
377 |
args("ObjectID", objectId)
|
378 |
args("ObjectID", objectId)
|
378 |
("BrowseFlag", "BrowseMetadata")
|
379 |
("BrowseFlag", "BrowseMetadata")
|
379 |
("Filter", "*")
|
380 |
("Filter", "*")
|
380 |
("SortCriteria", "")
|
381 |
("SortCriteria", "")
|
|
... |
|
... |
385 |
LOGINF("CDService::getmetadata: UpnpSendAction failed: " <<
|
386 |
LOGINF("CDService::getmetadata: UpnpSendAction failed: " <<
|
386 |
UpnpGetErrorMessage(ret) << endl);
|
387 |
UpnpGetErrorMessage(ret) << endl);
|
387 |
return ret;
|
388 |
return ret;
|
388 |
}
|
389 |
}
|
389 |
string tbuf;
|
390 |
string tbuf;
|
390 |
if (!data.getString("Result", &tbuf)) {
|
391 |
if (!data.get("Result", &tbuf)) {
|
391 |
LOGERR("CDService::getmetadata: missing Result in response" << endl);
|
392 |
LOGERR("CDService::getmetadata: missing Result in response" << endl);
|
392 |
return UPNP_E_BAD_RESPONSE;
|
393 |
return UPNP_E_BAD_RESPONSE;
|
393 |
}
|
394 |
}
|
394 |
|
395 |
|
395 |
if (dirbuf.parse(tbuf))
|
396 |
if (dirbuf.parse(tbuf))
|