/*---------------------------------------------------------------------- | PLT_SyncMediaBrowser::BrowseSync +---------------------------------------------------------------------*/ NPT_Result PLT_SyncMediaBrowser::BrowseSync(PLT_DeviceDataReference& device, const char* object_id, PLT_MediaObjectListReference& list, bool metadata, /* = false */ NPT_Int32 start, /* = 0 */ NPT_Cardinal max_results /* = 0 */) { NPT_Result res = NPT_FAILURE; NPT_Int32 index = start; // reset output params list = NULL; // look into cache first if (m_UseCache && NPT_SUCCEEDED(m_Cache.Get(device->GetUUID(), object_id, list))) return NPT_SUCCESS; do { PLT_BrowseDataReference browse_data(new PLT_BrowseData()); // send off the browse packet. Note that this will // not block. There is a call to WaitForResponse in order // to block until the response comes back. res = BrowseSync( browse_data, device, (const char*)object_id, index, metadata?1:30, // DLNA recommendations for browsing children is no more than 30 at a time metadata); NPT_CHECK_LABEL_WARNING(res, done); if (NPT_FAILED(browse_data->res)) { res = browse_data->res; NPT_CHECK_LABEL_WARNING(res, done); } if (browse_data->info.items->GetItemCount() == 0) break; if (list.IsNull()) { list = browse_data->info.items; } else { list->Add(*browse_data->info.items); // clear the list items so that the data inside is not // cleaned up by PLT_MediaItemList dtor since we copied // each pointer into the new list. browse_data->info.items->Clear(); } // stop now if our list contains exactly what the server said it had. // Note that the server could return 0 if it didn't know how many items were // available. In this case we have to continue browsing until // nothing is returned back by the server. // Unless we were told to stop after reaching a certain amount to avoid // length delays if ((browse_data->info.tm && browse_data->info.tm == list->GetItemCount()) || (max_results && list->GetItemCount() >= max_results)) break; // ask for the next chunk of entries index = list->GetItemCount(); } while(1); done: // cache the result if (m_UseCache && NPT_SUCCEEDED(res) && !list.IsNull() && list->GetItemCount()) { m_Cache.Put(device->GetUUID(), object_id, list); } // clear entire cache data for device if failed, the device could be gone if (NPT_FAILED(res) && m_UseCache) m_Cache.Clear(device->GetUUID()); return res; }
/*---------------------------------------------------------------------- | PLT_Didl::FromDidl +---------------------------------------------------------------------*/ NPT_Result PLT_Didl::FromDidl(const char* xml, PLT_MediaObjectListReference& objects) { NPT_String str; PLT_MediaObject* object = NULL; NPT_XmlNode* node = NULL; NPT_XmlElementNode* didl = NULL; NPT_XmlParser parser; NPT_LOG_FINE("Parsing Didl..."); NPT_CHECK_LABEL_SEVERE(parser.Parse(xml, node), cleanup); if (!node || !node->AsElementNode()) { NPT_LOG_SEVERE("Invalid node type"); goto cleanup; } didl = node->AsElementNode(); if (didl->GetTag().Compare("DIDL-Lite", true)) { NPT_LOG_SEVERE("Invalid node tag"); goto cleanup; } // create entry list objects = new PLT_MediaObjectList(); // for each child, find out if it's a container or not // and then invoke the FromDidl on it for (NPT_List<NPT_XmlNode*>::Iterator children = didl->GetChildren().GetFirstItem(); children; children++) { NPT_XmlElementNode* child = (*children)->AsElementNode(); if (!child) continue; if (child->GetTag().Compare("Container", true) == 0) { object = new PLT_MediaContainer(); } else if (child->GetTag().Compare("item", true) == 0) { object = new PLT_MediaItem(); } else { NPT_LOG_WARNING("Invalid node tag"); continue; } if (NPT_FAILED(object->FromDidl(child))) { NPT_LOG_WARNING_1("Invalid didl for object: %s", (const char*) PLT_XmlHelper::Serialize(*child, false)); continue; } objects->Add(object); object = NULL; // reset to make sure it doesn't get deleted twice in case of error } delete node; return NPT_SUCCESS; cleanup: objects = NULL; delete node; delete object; return NPT_FAILURE; }
/*---------------------------------------------------------------------- | PLT_SyncMediaBrowser::Browse +---------------------------------------------------------------------*/ NPT_Result PLT_SyncMediaBrowser::Browse(PLT_DeviceDataReference& device, const char* object_id, PLT_MediaObjectListReference& list) { NPT_Result res = NPT_FAILURE; NPT_Int32 index = 0; // reset output params list = NULL; // look into cache first if (m_UseCache && NPT_SUCCEEDED(m_Cache.Get(device->GetUUID(), object_id, list))) return NPT_SUCCESS; do { PLT_BrowseDataReference browse_data(new PLT_BrowseData()); // send off the browse packet. Note that this will // not block. There is a call to WaitForResponse in order // to block until the response comes back. res = Browse(browse_data, device, (const char*)object_id, index, 1024, false, "*", ""); NPT_CHECK_LABEL_WARNING(res, done); if (NPT_FAILED(browse_data->res)) { res = browse_data->res; NPT_CHECK_LABEL_WARNING(res, done); } if (browse_data->info.items->GetItemCount() == 0) break; if (list.IsNull()) { list = browse_data->info.items; } else { list->Add(*browse_data->info.items); // clear the list items so that the data inside is not // cleaned up by PLT_MediaItemList dtor since we copied // each pointer into the new list. browse_data->info.items->Clear(); } // stop now if our list contains exactly what the server said it had if (browse_data->info.tm && browse_data->info.tm == list->GetItemCount()) break; // ask for the next chunk of entries index = list->GetItemCount(); } while(1); done: // cache the result if (m_UseCache && NPT_SUCCEEDED(res) && !list.IsNull() && list->GetItemCount()) { m_Cache.Put(device->GetUUID(), object_id, list); } // clear entire cache data for device if failed, the device could be gone if (NPT_FAILED(res) && m_UseCache) m_Cache.Clear(device->GetUUID()); return res; }