예제 #1
0
/*----------------------------------------------------------------------
|   PLT_MediaBrowser::OnDeviceAdded
+---------------------------------------------------------------------*/
NPT_Result
PLT_MediaBrowser::OnDeviceAdded(PLT_DeviceDataReference& device)
{
    // verify the device implements the function we need
    PLT_Service* serviceCDS;
    PLT_Service* serviceCMR;
    NPT_String   type;

    if (!device->GetType().StartsWith("urn:schemas-upnp-org:device:MediaServer"))
        return NPT_FAILURE;
    
    type = "urn:schemas-upnp-org:service:ContentDirectory:*";
    if (NPT_FAILED(device->FindServiceByType(type, serviceCDS))) {
        NPT_LOG_WARNING_2("Service %s not found in device \"%s\"", 
            type.GetChars(),
            device->GetFriendlyName().GetChars());
        return NPT_FAILURE;
    } else {
        // in case it's a newer upnp implementation, force to 1
        serviceCDS->ForceVersion(1);
    }
    
    type = "urn:schemas-upnp-org:service:ConnectionManager:*";
    if (NPT_FAILED(device->FindServiceByType(type, serviceCMR))) {
        NPT_LOG_WARNING_2("Service %s not found in device \"%s\"", 
            type.GetChars(), 
            device->GetFriendlyName().GetChars());
        return NPT_FAILURE;
    } else {
        // in case it's a newer upnp implementation, force to 1
        serviceCMR->ForceVersion(1);
    }
    
    {
        NPT_AutoLock lock(m_MediaServers);

        PLT_DeviceDataReference data;
        NPT_String uuid = device->GetUUID();
        
        // is it a new device?
        if (NPT_SUCCEEDED(NPT_ContainerFind(m_MediaServers, PLT_DeviceDataFinder(uuid), data))) {
            NPT_LOG_WARNING_1("Device (%s) is already in our list!", (const char*)uuid);
            return NPT_FAILURE;
        }

        NPT_LOG_FINE_1("Device Found: %s", (const char*)*device);

        m_MediaServers.Add(device);
    }

    if (m_Delegate && m_Delegate->OnMSAdded(device)) {
        m_CtrlPoint->Subscribe(serviceCDS);
        m_CtrlPoint->Subscribe(serviceCMR);
    }
    
    return NPT_SUCCESS;
}
예제 #2
0
/*----------------------------------------------------------------------
|   CUPnPDirectory::GetFriendlyName
+---------------------------------------------------------------------*/
const char*
CUPnPDirectory::GetFriendlyName(const char* url)
{
    NPT_String path = url;
    if (!path.EndsWith("/")) path += "/";

    if (path.Left(7).Compare("upnp://", true) != 0) {
        return NULL;
    } else if (path.Compare("upnp://", true) == 0) {
        return "UPnP Media Servers (Auto-Discover)";
    }

    // look for nextslash
    int next_slash = path.Find('/', 7);
    if (next_slash == -1)
        return NULL;

    NPT_String uuid = path.SubString(7, next_slash-7);
    NPT_String object_id = path.SubString(next_slash+1, path.GetLength()-next_slash-2);

    // look for device
    PLT_DeviceDataReference device;
    if(!FindDeviceWait(CUPnP::GetInstance(), uuid, device))
        return NULL;

    return (const char*)device->GetFriendlyName();
}
void
PLT_MicroMediaController::SetEmbeddedServer(const char* embeddedServerName){

	NPT_AutoLock lock(m_CurMediaServerLock);
    PopDirectoryStackToRoot();

	NPT_Result res = NPT_FAILURE;
	//const char embeddedServerName[]="Embedded Media Server";


	while(res!=NPT_SUCCESS){
		//printf("waiting for the embedded server to come up!\n");
		const NPT_Lock<PLT_DeviceMap>& deviceList = GetMediaServersMap();
		const NPT_List<PLT_DeviceMapEntry*>& entries = deviceList.GetEntries();
		NPT_List<PLT_DeviceMapEntry*>::Iterator entry = entries.GetFirstItem();

		while (entry) {
			PLT_DeviceDataReference device = (*entry)->GetValue();
			NPT_String              name   = device->GetFriendlyName();

			if(0 == strcmp(embeddedServerName, name)){
				printf("****server discovered and set****\n");
				m_CurMediaServer = device;
				res = NPT_SUCCESS;
				break;
			}
			++entry;
		}
	}

}
/*----------------------------------------------------------------------
|   PLT_MicroMediaController::ChooseDevice
+---------------------------------------------------------------------*/
PLT_DeviceDataReference
PLT_MicroMediaController::ChooseDevice(const NPT_Lock<PLT_DeviceMap>& deviceList)
{
    PLT_StringMap            namesTable;
    PLT_DeviceDataReference* result = NULL;
    NPT_String               chosenUUID;
    NPT_AutoLock             lock(m_MediaServers);

    // create a map with the device UDN -> device Name
    const NPT_List<PLT_DeviceMapEntry*>& entries = deviceList.GetEntries();
    NPT_List<PLT_DeviceMapEntry*>::Iterator entry = entries.GetFirstItem();
    while (entry) {
        PLT_DeviceDataReference device = (*entry)->GetValue();
        NPT_String              name   = device->GetFriendlyName();
        namesTable.Put((*entry)->GetKey(), name);

        ++entry;
    }

    // ask user to choose
    chosenUUID = ChooseIDFromTable(namesTable);
    if (chosenUUID.GetLength()) {
        deviceList.Get(chosenUUID, result);
    }

    return result?*result:PLT_DeviceDataReference(); // return empty reference if not device was selected
}
예제 #5
0
 virtual bool OnMRAdded(PLT_DeviceDataReference& device )
 {
   CPlayerCoreFactory::Get().OnPlayerDiscovered((const char*)device->GetUUID()
                                         ,(const char*)device->GetFriendlyName()
                                         , EPC_UPNPPLAYER);
   return true;
 }
/*----------------------------------------------------------------------
|   PLT_MicroMediaController::HandleCmd_getmr
+---------------------------------------------------------------------*/
void
PLT_MicroMediaController::HandleCmd_getmr()
{
    PLT_DeviceDataReference device;
    GetCurMediaRenderer(device);
    if (!device.IsNull()) {
        printf("Current media renderer: %s\n", (const char*)device->GetFriendlyName());
    } else {
        // this output is taken care of by the GetCurMediaRenderer call
    }
}
예제 #7
0
파일: UPnP.cpp 프로젝트: MrMC/mrmc
  virtual bool OnMRAdded(PLT_DeviceDataReference& device )
  {
    if (device->GetUUID().IsEmpty() || device->GetUUID().GetChars() == NULL)
      return false;

    CPlayerCoreFactory::GetInstance().OnPlayerDiscovered((const char*)device->GetUUID()
                                          ,(const char*)device->GetFriendlyName()
                                          , EPC_UPNPPLAYER);
    m_registeredRenderers.insert(std::string(device->GetUUID().GetChars()));
    return true;
  }
예제 #8
0
/*----------------------------------------------------------------------
|   CUPnPDirectory::GetDirectory
+---------------------------------------------------------------------*/
bool
CUPnPDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items)
{
    CUPnP* upnp = CUPnP::GetInstance();

    /* upnp should never be cached, it has internal cache */
    items.SetCacheToDisc(CFileItemList::CACHE_NEVER);

    // We accept upnp://devuuid/[item_id/]
    NPT_String path = strPath.c_str();
    if (!path.StartsWith("upnp://", true)) {
        return false;
    }

    if (path.Compare("upnp://", true) == 0) {
        upnp->StartClient();

        // root -> get list of devices
        const NPT_Lock<PLT_DeviceDataReferenceList>& devices = upnp->m_MediaBrowser->GetMediaServers();
        NPT_List<PLT_DeviceDataReference>::Iterator device = devices.GetFirstItem();
        while (device) {
            NPT_String name = (*device)->GetFriendlyName();
            NPT_String uuid = (*device)->GetUUID();

            CFileItemPtr pItem(new CFileItem((const char*)name));
            pItem->SetPath(CStdString((const char*) "upnp://" + uuid + "/"));
            pItem->m_bIsFolder = true;
            pItem->SetArt("thumb", (const char*)(*device)->GetIconUrl("image/png"));

            items.Add(pItem);

            ++device;
        }
    } else {
        if (!path.EndsWith("/")) path += "/";

        // look for nextslash
        int next_slash = path.Find('/', 7);

        NPT_String uuid = (next_slash==-1)?path.SubString(7):path.SubString(7, next_slash-7);
        NPT_String object_id = (next_slash==-1)?"":path.SubString(next_slash+1);
        object_id.TrimRight("/");
        if (object_id.GetLength()) {
            CStdString tmp = (char*) object_id;
            CURL::Decode(tmp);
            object_id = tmp;
        }

        // try to find the device with wait on startup
        PLT_DeviceDataReference device;
        if (!FindDeviceWait(upnp, uuid, device))
            goto failure;

        // issue a browse request with object_id
        // if object_id is empty use "0" for root
        object_id = object_id.IsEmpty()?"0":object_id;

        // remember a count of object classes
        std::map<NPT_String, int> classes;

        // just a guess as to what types of files we want
        bool video = true;
        bool audio = true;
        bool image = true;
        m_strFileMask.TrimLeft("/");
        if (!m_strFileMask.IsEmpty()) {
            video = m_strFileMask.Find(".wmv") >= 0;
            audio = m_strFileMask.Find(".wma") >= 0;
            image = m_strFileMask.Find(".jpg") >= 0;
        }

        // special case for Windows Media Connect and WMP11 when looking for root
        // We can target which root subfolder we want based on directory mask
        if (object_id == "0" && ((device->GetFriendlyName().Find("Windows Media Connect", 0, true) >= 0) ||
                                 (device->m_ModelName == "Windows Media Player Sharing"))) {

            // look for a specific type to differentiate which folder we want
            if (audio && !video && !image) {
                // music
                object_id = "1";
            } else if (!audio && video && !image) {
                // video
                object_id = "2";
            } else if (!audio && !video && image) {
                // pictures
                object_id = "3";
            }
        }

#ifdef DISABLE_SPECIALCASE
        // same thing but special case for XBMC
        if (object_id == "0" && ((device->m_ModelName.Find("XBMC", 0, true) >= 0) ||
                                 (device->m_ModelName.Find("Xbox Media Center", 0, true) >= 0))) {
            // look for a specific type to differentiate which folder we want
            if (audio && !video && !image) {
                // music
                object_id = "virtualpath://upnpmusic";
            } else if (!audio && video && !image) {
                // video
                object_id = "virtualpath://upnpvideo";
            } else if (!audio && !video && image) {
                // pictures
                object_id = "virtualpath://upnppictures";
            }
        }
#endif

        // if error, return now, the device could have gone away
        // this will make us go back to the sources list
        PLT_MediaObjectListReference list;
        NPT_Result res = upnp->m_MediaBrowser->BrowseSync(device, object_id, list);
        if (NPT_FAILED(res)) goto failure;

        // empty list is ok
        if (list.IsNull()) goto cleanup;

        PLT_MediaObjectList::Iterator entry = list->GetFirstItem();
        while (entry) {
            // disregard items with wrong class/type
            if( (!video && (*entry)->m_ObjectClass.type.CompareN("object.item.videoitem", 21,true) == 0)
             || (!audio && (*entry)->m_ObjectClass.type.CompareN("object.item.audioitem", 21,true) == 0)
             || (!image && (*entry)->m_ObjectClass.type.CompareN("object.item.imageitem", 21,true) == 0) )
            {
                ++entry;
                continue;
            }

            // never show empty containers in media views
            if((*entry)->IsContainer()) {
                if( (audio || video || image)
                 && ((PLT_MediaContainer*)(*entry))->m_ChildrenCount == 0) {
                    ++entry;
                    continue;
                }
            }


            // keep count of classes
            classes[(*entry)->m_ObjectClass.type]++;
            CFileItemPtr pItem = BuildObject(*entry);
            if(!pItem) {
                ++entry;
                continue;
            }

            CStdString id = (char*) (*entry)->m_ObjectID;
            CURL::Encode(id);
            URIUtils::AddSlashAtEnd(id);
            pItem->SetPath(CStdString((const char*) "upnp://" + uuid + "/" + id.c_str()));

            items.Add(pItem);

            ++entry;
        }

        NPT_String max_string = "";
        int        max_count  = 0;
        for(std::map<NPT_String, int>::iterator it = classes.begin(); it != classes.end(); it++)
        {
          if(it->second > max_count)
          {
            max_string = it->first;
            max_count  = it->second;
          }
        }
        std::string content = GetContentMapping(max_string);
        items.SetContent(content);
        if (content == "unknown")
        {
          items.AddSortMethod(SORT_METHOD_UNSORTED, 571, LABEL_MASKS("%L", "%I", "%L", ""));
          items.AddSortMethod(SORT_METHOD_LABEL_IGNORE_FOLDERS, 551, LABEL_MASKS("%L", "%I", "%L", ""));
          items.AddSortMethod(SORT_METHOD_SIZE, 553, LABEL_MASKS("%L", "%I", "%L", "%I"));
          items.AddSortMethod(SORT_METHOD_DATE, 552, LABEL_MASKS("%L", "%J", "%L", "%J"));
        }
    }

cleanup:
    return true;

failure:
    return false;
}
예제 #9
0
/*----------------------------------------------------------------------
|   CUPnPDirectory::GetDirectory
+---------------------------------------------------------------------*/
bool
CUPnPDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items)
{
    CUPnP* upnp = CUPnP::GetInstance();

    /* upnp should never be cached, it has internal cache */
    items.SetCacheToDisc(CFileItemList::CACHE_NEVER);

    // We accept upnp://devuuid/[item_id/]
    NPT_String path = strPath.c_str();
    if (!path.StartsWith("upnp://", true)) {
        return false;
    }

    if (path.Compare("upnp://", true) == 0) {
        upnp->StartClient();

        // root -> get list of devices
        const NPT_Lock<PLT_DeviceDataReferenceList>& devices = upnp->m_MediaBrowser->GetMediaServers();
        NPT_List<PLT_DeviceDataReference>::Iterator device = devices.GetFirstItem();
        while (device) {
            NPT_String name = (*device)->GetFriendlyName();
            NPT_String uuid = (*device)->GetUUID();

            CFileItemPtr pItem(new CFileItem((const char*)name));
            pItem->SetPath(CStdString((const char*) "upnp://" + uuid + "/"));
            pItem->m_bIsFolder = true;
            pItem->SetThumbnailImage((const char*)(*device)->GetIconUrl("image/jpeg"));

            items.Add(pItem);

            ++device;
        }
    } else {
        if (!path.EndsWith("/")) path += "/";

        // look for nextslash
        int next_slash = path.Find('/', 7);

        NPT_String uuid = (next_slash==-1)?path.SubString(7):path.SubString(7, next_slash-7);
        NPT_String object_id = (next_slash==-1)?"":path.SubString(next_slash+1);
        object_id.TrimRight("/");
        if (object_id.GetLength()) {
            CStdString tmp = (char*) object_id;
            CURL::Decode(tmp);
            object_id = tmp;
        }

        // try to find the device with wait on startup
        PLT_DeviceDataReference device;
        if (!FindDeviceWait(upnp, uuid, device))
            goto failure;

        // issue a browse request with object_id
        // if object_id is empty use "0" for root
        object_id = object_id.IsEmpty()?"0":object_id;

        // remember a count of object classes
        std::map<NPT_String, int> classes;

        // just a guess as to what types of files we want
        bool video = true;
        bool audio = true;
        bool image = true;
        m_strFileMask.TrimLeft("/");
        if (!m_strFileMask.IsEmpty()) {
            video = m_strFileMask.Find(".wmv") >= 0;
            audio = m_strFileMask.Find(".wma") >= 0;
            image = m_strFileMask.Find(".jpg") >= 0;
        }

        // special case for Windows Media Connect and WMP11 when looking for root
        // We can target which root subfolder we want based on directory mask
        if (object_id == "0" && ((device->GetFriendlyName().Find("Windows Media Connect", 0, true) >= 0) ||
                                 (device->m_ModelName == "Windows Media Player Sharing"))) {

            // look for a specific type to differentiate which folder we want
            if (audio && !video && !image) {
                // music
                object_id = "1";
            } else if (!audio && video && !image) {
                // video
                object_id = "2";
            } else if (!audio && !video && image) {
                // pictures
                object_id = "3";
            }
        }

#ifdef DISABLE_SPECIALCASE
        // same thing but special case for XBMC
        if (object_id == "0" && ((device->m_ModelName.Find("XBMC", 0, true) >= 0) ||
                                 (device->m_ModelName.Find("Xbox Media Center", 0, true) >= 0))) {
            // look for a specific type to differentiate which folder we want
            if (audio && !video && !image) {
                // music
                object_id = "virtualpath://upnpmusic";
            } else if (!audio && video && !image) {
                // video
                object_id = "virtualpath://upnpvideo";
            } else if (!audio && !video && image) {
                // pictures
                object_id = "virtualpath://upnppictures";
            }
        }
#endif

        // if error, return now, the device could have gone away
        // this will make us go back to the sources list
        PLT_MediaObjectListReference list;
        NPT_Result res = upnp->m_MediaBrowser->BrowseSync(device, object_id, list);
        if (NPT_FAILED(res)) goto failure;

        // empty list is ok
        if (list.IsNull()) goto cleanup;

        PLT_MediaObjectList::Iterator entry = list->GetFirstItem();
        while (entry) {
            // disregard items with wrong class/type
            if( (!video && (*entry)->m_ObjectClass.type.CompareN("object.item.videoitem", 21,true) == 0)
                    || (!audio && (*entry)->m_ObjectClass.type.CompareN("object.item.audioitem", 21,true) == 0)
                    || (!image && (*entry)->m_ObjectClass.type.CompareN("object.item.imageitem", 21,true) == 0) )
            {
                ++entry;
                continue;
            }

            // never show empty containers in media views
            if((*entry)->IsContainer()) {
                if( (audio || video || image)
                        && ((PLT_MediaContainer*)(*entry))->m_ChildrenCount == 0) {
                    ++entry;
                    continue;
                }
            }

            NPT_String ObjectClass = (*entry)->m_ObjectClass.type.ToLowercase();

            // keep count of classes
            classes[(*entry)->m_ObjectClass.type]++;

            CFileItemPtr pItem(new CFileItem((const char*)(*entry)->m_Title));
            pItem->SetLabelPreformated(true);
            pItem->m_strTitle = (const char*)(*entry)->m_Title;
            pItem->m_bIsFolder = (*entry)->IsContainer();

            CStdString id = (char*) (*entry)->m_ObjectID;
            CURL::Encode(id);
            pItem->SetPath(CStdString((const char*) "upnp://" + uuid + "/" + id.c_str()));

            // if it's a container, format a string as upnp://uuid/object_id
            if (pItem->m_bIsFolder) {
                pItem->SetPath(pItem->GetPath() + "/");

                // look for metadata
                if( ObjectClass.StartsWith("object.container.album.videoalbum") ) {
                    pItem->SetLabelPreformated(false);
                    CUPnP::PopulateTagFromObject(*pItem->GetVideoInfoTag(), *(*entry), NULL);

                } else if( ObjectClass.StartsWith("object.container.album.photoalbum")) {
                    //CPictureInfoTag* tag = pItem->GetPictureInfoTag();

                } else if( ObjectClass.StartsWith("object.container.album") ) {
                    pItem->SetLabelPreformated(false);
                    CUPnP::PopulateTagFromObject(*pItem->GetMusicInfoTag(), *(*entry), NULL);
                }

            } else {

                // set a general content type
                if (ObjectClass.StartsWith("object.item.videoitem"))
                    pItem->SetMimeType("video/octet-stream");
                else if(ObjectClass.StartsWith("object.item.audioitem"))
                    pItem->SetMimeType("audio/octet-stream");
                else if(ObjectClass.StartsWith("object.item.imageitem"))
                    pItem->SetMimeType("image/octet-stream");

                if ((*entry)->m_Resources.GetItemCount()) {
                    PLT_MediaItemResource& resource = (*entry)->m_Resources[0];

                    // set metadata
                    if (resource.m_Size != (NPT_LargeSize)-1) {
                        pItem->m_dwSize  = resource.m_Size;
                    }

                    // look for metadata
                    if( ObjectClass.StartsWith("object.item.videoitem") ) {
                        pItem->SetLabelPreformated(false);
                        CUPnP::PopulateTagFromObject(*pItem->GetVideoInfoTag(), *(*entry), &resource);

                    } else if( ObjectClass.StartsWith("object.item.audioitem") ) {
                        pItem->SetLabelPreformated(false);
                        CUPnP::PopulateTagFromObject(*pItem->GetMusicInfoTag(), *(*entry), &resource);

                    } else if( ObjectClass.StartsWith("object.item.imageitem") ) {
                        //CPictureInfoTag* tag = pItem->GetPictureInfoTag();

                    }
                }
            }

            // look for date?
            if((*entry)->m_Description.date.GetLength()) {
                SYSTEMTIME time = {};
                sscanf((*entry)->m_Description.date, "%hu-%hu-%huT%hu:%hu:%hu",
                       &time.wYear, &time.wMonth, &time.wDay, &time.wHour, &time.wMinute, &time.wSecond);
                pItem->m_dateTime = time;
            }

            // if there is a thumbnail available set it here
            if((*entry)->m_ExtraInfo.album_art_uri.GetLength())
                pItem->SetThumbnailImage((const char*) (*entry)->m_ExtraInfo.album_art_uri);
            else if((*entry)->m_Description.icon_uri.GetLength())
                pItem->SetThumbnailImage((const char*) (*entry)->m_Description.icon_uri);

            PLT_ProtocolInfo fanart_mask("xbmc.org", "*", "fanart", "*");
            for(unsigned i = 0; i < (*entry)->m_Resources.GetItemCount(); ++i) {
                PLT_MediaItemResource& res = (*entry)->m_Resources[i];
                if(res.m_ProtocolInfo.Match(fanart_mask)) {
                    pItem->SetProperty("fanart_image", (const char*)res.m_Uri);
                    break;
                }
            }
            items.Add(pItem);

            ++entry;
        }

        NPT_String max_string = "";
        int        max_count  = 0;
        for(std::map<NPT_String, int>::iterator it = classes.begin(); it != classes.end(); it++)
        {
            if(it->second > max_count)
            {
                max_string = it->first;
                max_count  = it->second;
            }
        }
        items.SetContent(GetContentMapping(max_string));
    }

cleanup:
    return true;

failure:
    return false;
}
예제 #10
0
/*----------------------------------------------------------------------
|   CUPnPDirectory::GetDirectory
+---------------------------------------------------------------------*/
bool
CUPnPDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items)
{
    CGUIDialogProgress* dlgProgress = NULL;

    CUPnP* upnp = CUPnP::GetInstance();

    /* upnp should never be cached, it has internal cache */
    items.SetCacheToDisc(CFileItemList::CACHE_NEVER);

    // start client if it hasn't been done yet
    bool client_started = upnp->IsClientStarted();
    upnp->StartClient();

    // We accept upnp://devuuid/[item_id/]
    NPT_String path = strPath.c_str();
    if (!path.StartsWith("upnp://", true)) {
        return false;
    }

    if (path.Compare("upnp://", true) == 0) {
        // root -> get list of devices
        const NPT_Lock<PLT_DeviceMap>& devices = upnp->m_MediaBrowser->GetMediaServers();
        const NPT_List<PLT_DeviceMapEntry*>& entries = devices.GetEntries();
        NPT_List<PLT_DeviceMapEntry*>::Iterator entry = entries.GetFirstItem();
        while (entry) {
            PLT_DeviceDataReference device = (*entry)->GetValue();
            NPT_String name = device->GetFriendlyName();
            NPT_String uuid = (*entry)->GetKey();

            CFileItemPtr pItem(new CFileItem((const char*)name));
            pItem->m_strPath = (const char*) "upnp://" + uuid + "/";
            pItem->m_bIsFolder = true;
            pItem->SetThumbnailImage((const char*)device->GetIconUrl("image/jpeg"));

            items.Add(pItem);

            ++entry;
        }
    } else {
        if (!path.EndsWith("/")) path += "/";

        // look for nextslash
        int next_slash = path.Find('/', 7);

        NPT_String uuid = (next_slash==-1)?path.SubString(7):path.SubString(7, next_slash-7);
        NPT_String object_id = (next_slash==-1)?"":path.SubString(next_slash+1);
        object_id.TrimRight("/");
        if (object_id.GetLength()) {
            CStdString tmp = (char*) object_id;
            CUtil::UrlDecode(tmp);
            object_id = tmp;
        }

        // look for device in our list
        // (and wait for it to respond for 5 secs if we're just starting upnp client)
        NPT_TimeStamp watchdog;
        NPT_System::GetCurrentTimeStamp(watchdog);
        watchdog += 5.f;

        PLT_DeviceDataReference* device;
        for (;;) {
            const NPT_Lock<PLT_DeviceMap>& devices = upnp->m_MediaBrowser->GetMediaServers();
            if (NPT_SUCCEEDED(devices.Get(uuid, device)) && device)
                break;

            // fail right away if device not found and upnp client was already running
            if (client_started)
                goto failure;

            // otherwise check if we've waited long enough without success
            NPT_TimeStamp now;
            NPT_System::GetCurrentTimeStamp(now);
            if (now > watchdog)
                goto failure;

            // sleep a bit and try again
            NPT_System::Sleep(NPT_TimeInterval(1, 0));
        }

        // issue a browse request with object_id
        // if object_id is empty use "0" for root
        object_id = object_id.IsEmpty()?"0":object_id;

        // just a guess as to what types of files we want
        bool video = true;
        bool audio = true;
        bool image = true;
        m_strFileMask.TrimLeft("/");
        if (!m_strFileMask.IsEmpty()) {
            video = m_strFileMask.Find(".wmv") >= 0;
            audio = m_strFileMask.Find(".wma") >= 0;
            image = m_strFileMask.Find(".jpg") >= 0;
        }

        // special case for Windows Media Connect and WMP11 when looking for root
        // We can target which root subfolder we want based on directory mask
        if (object_id == "0" && (((*device)->GetFriendlyName().Find("Windows Media Connect", 0, true) >= 0) ||
                                 ((*device)->m_ModelName == "Windows Media Player Sharing"))) {

            // look for a specific type to differentiate which folder we want
            if (audio && !video && !image) {
                // music
                object_id = "1";
            } else if (!audio && video && !image) {
                // video
                object_id = "2";
            } else if (!audio && !video && image) {
                // pictures
                object_id = "3";
            }
        }

#ifdef DISABLE_SPECIALCASE
        // same thing but special case for XBMC
        if (object_id == "0" && (((*device)->m_ModelName.Find("XBMC", 0, true) >= 0) ||
                                 ((*device)->m_ModelName.Find("Xbox Media Center", 0, true) >= 0))) {
            // look for a specific type to differentiate which folder we want
            if (audio && !video && !image) {
                // music
                object_id = "virtualpath://upnpmusic";
            } else if (!audio && video && !image) {
                // video
                object_id = "virtualpath://upnpvideo";
            } else if (!audio && !video && image) {
                // pictures
                object_id = "virtualpath://upnppictures";
            }
        }
#endif
        // bring up dialog if object is not cached
        if (!upnp->m_MediaBrowser->IsCached(uuid, object_id)) {
            dlgProgress = (CGUIDialogProgress*)m_gWindowManager.GetWindow(WINDOW_DIALOG_PROGRESS);
            if (dlgProgress) {
                dlgProgress->ShowProgressBar(false);
                dlgProgress->SetCanCancel(false);
                dlgProgress->SetHeading(20334);
                dlgProgress->SetLine(0, 194);
                dlgProgress->SetLine(1, "");
                dlgProgress->SetLine(2, "");
                dlgProgress->StartModal();
            }
        }

        // if error, return now, the device could have gone away
        // this will make us go back to the sources list
        PLT_MediaObjectListReference list;
        NPT_Result res = upnp->m_MediaBrowser->Browse(*device, object_id, list);
        if (NPT_FAILED(res)) goto failure;

        // empty list is ok
        if (list.IsNull()) goto cleanup;

        PLT_MediaObjectList::Iterator entry = list->GetFirstItem();
        while (entry) {
            // disregard items with wrong class/type
            if( (!video && (*entry)->m_ObjectClass.type.CompareN("object.item.videoitem", 21,true) == 0)
             || (!audio && (*entry)->m_ObjectClass.type.CompareN("object.item.audioitem", 21,true) == 0)
             || (!image && (*entry)->m_ObjectClass.type.CompareN("object.item.imageitem", 21,true) == 0) )
            {
                ++entry;
                continue;
            }

            // never show empty containers in media views
            if((*entry)->IsContainer()) {
                if( (audio || video || image)
                 && ((PLT_MediaContainer*)(*entry))->m_ChildrenCount == 0) {
                    ++entry;
                    continue;
                }
            }

            CFileItemPtr pItem(new CFileItem((const char*)(*entry)->m_Title));
            pItem->SetLabelPreformated(true);
            pItem->m_bIsFolder = (*entry)->IsContainer();

            // if it's a container, format a string as upnp://uuid/object_id
            if (pItem->m_bIsFolder) {
                CStdString id = (char*) (*entry)->m_ObjectID;
                CUtil::URLEncode(id);
                pItem->m_strPath = (const char*) "upnp://" + uuid + "/" + id.c_str() + "/";
            } else {
                if ((*entry)->m_Resources.GetItemCount()) {
                    PLT_MediaItemResource& resource = (*entry)->m_Resources[0];

                    // look for a resource with "xbmc-get" protocol
                    // if we can't find one, keep the first resource
                    NPT_ContainerFind((*entry)->m_Resources,
                                      CProtocolFinder("xbmc-get"),
                                      resource);

                    CLog::Log(LOGDEBUG, "CUPnPDirectory::GetDirectory - resource protocol info '%s'", (const char*)(resource.m_ProtocolInfo));

                    // if it's an item, path is the first url to the item
                    // we hope the server made the first one reachable for us
                    // (it could be a format we dont know how to play however)
                    pItem->m_strPath = (const char*) resource.m_Uri;

                    // set metadata
                    if (resource.m_Size > 0) {
                        pItem->m_dwSize  = resource.m_Size;
                    }

                    // set a general content type
                    CStdString type = (const char*)(*entry)->m_ObjectClass.type.Left(21);
                    if     (type.Equals("object.item.videoitem"))
                        pItem->SetContentType("video/octet-stream");
                    else if(type.Equals("object.item.audioitem"))
                        pItem->SetContentType("audio/octet-stream");
                    else if(type.Equals("object.item.imageitem"))
                        pItem->SetContentType("image/octet-stream");

                    // look for content type in protocol info
                    if (resource.m_ProtocolInfo.GetLength()) {
                        char proto[1024];
                        char dummy1[1024];
                        char ct[1204];
                        char dummy2[1024];
                        int fields = sscanf(resource.m_ProtocolInfo, "%[^:]:%[^:]:%[^:]:%[^:]", proto, dummy1, ct, dummy2);
                        if (fields == 4) {
                            if (strcmp(ct, "application/octet-stream") != 0) {
                                pItem->SetContentType(ct);
                            }
                        } else {
                            CLog::Log(LOGERROR, "CUPnPDirectory::GetDirectory - invalid protocol info '%s'", (const char*)(resource.m_ProtocolInfo));
                        }
                    }

                    // look for date?
                    if((*entry)->m_Description.date.GetLength()) {
                        SYSTEMTIME time = {};
                        sscanf((*entry)->m_Description.date, "%hu-%hu-%huT%hu:%hu:%hu",
                               &time.wYear, &time.wMonth, &time.wDay, &time.wHour, &time.wMinute, &time.wSecond);
                        pItem->m_dateTime = time;
                    }

                    // look for metadata
                    if( (*entry)->m_ObjectClass.type.CompareN("object.item.videoitem", 21,true) == 0 ) {
                        pItem->SetLabelPreformated(false);
                        CUPnP::PopulateTagFromObject(*pItem->GetVideoInfoTag(), *(*entry), &resource);
                    } else if( (*entry)->m_ObjectClass.type.CompareN("object.item.audioitem", 21,true) == 0 ) {
                        pItem->SetLabelPreformated(false);
                        CUPnP::PopulateTagFromObject(*pItem->GetMusicInfoTag(), *(*entry), &resource);
                    } else if( (*entry)->m_ObjectClass.type.CompareN("object.item.imageitem", 21,true) == 0 ) {
                      //CPictureInfoTag* tag = pItem->GetPictureInfoTag();
                    }
                }
            }

            // if there is a thumbnail available set it here
            if((*entry)->m_ExtraInfo.album_art_uri.GetLength())
                pItem->SetThumbnailImage((const char*) (*entry)->m_ExtraInfo.album_art_uri);
            else if((*entry)->m_Description.icon_uri.GetLength())
                pItem->SetThumbnailImage((const char*) (*entry)->m_Description.icon_uri);

            items.Add(pItem);

            ++entry;
        }
    }

cleanup:
    if (dlgProgress) dlgProgress->Close();
    return true;

failure:
    if (dlgProgress) dlgProgress->Close();
    return false;
}
예제 #11
0
/*----------------------------------------------------------------------
|   CMediaCrawler::OnBrowseRoot
+---------------------------------------------------------------------*/
NPT_Result
CMediaCrawler::OnBrowseRoot(PLT_ActionReference& action)
{
    NPT_String browseFlagValue;
    if (NPT_FAILED(action->GetArgumentValue("BrowseFlag", browseFlagValue))) {
        NPT_LOG_WARNING("PLT_FileMediaServer::OnBrowse - invalid arguments.");
        return NPT_FAILURE;
    }

    /* extract browseFlag */
    BrowseFlags browseFlag;
    if (NPT_FAILED(GetBrowseFlag(browseFlagValue, browseFlag))) {
        /* error */
        NPT_LOG_WARNING("PLT_FileMediaServer::OnBrowseRoot - BrowseFlag value not allowed.");
        action->SetError(402,"Invalid BrowseFlag arg.");
        return NPT_FAILURE;
    }

    if (browseFlag == BROWSEMETADATA) {
        PLT_MediaContainer item;
        item.m_Title = "Root";
        item.m_ParentID = "-1";
        item.m_ObjectID = "0";
        item.m_ChildrenCount = GetMediaServers().GetItemCount();
        item.m_ObjectClass.type = "object.container";

        /* convert item to didl */
        NPT_String filter;
        action->GetArgumentValue("Filter", filter);
        NPT_String tmp;
        NPT_CHECK_SEVERE(PLT_Didl::ToDidl(item, filter, tmp));

        /* add didl header and footer */
        NPT_String didl = didl_header + tmp + didl_footer;

        action->SetArgumentValue("Result", didl);
        action->SetArgumentValue("NumberReturned", "1");
        action->SetArgumentValue("TotalMatches", "1");

        // update ID may be wrong here, it should be the one of the container?
        action->SetArgumentValue("UpdateId", "1");
        // TODO: We need to keep track of the overall updateID of the CDS
    } else {
        NPT_String startingInd;
        NPT_String reqCount;
        NPT_String filter;

        NPT_CHECK_SEVERE(action->GetArgumentValue("StartingIndex", startingInd));
        NPT_CHECK_SEVERE(action->GetArgumentValue("RequestedCount", reqCount));   
        NPT_CHECK_SEVERE(action->GetArgumentValue("Filter", filter));

        unsigned long start_index, req_count;
        if (NPT_FAILED(startingInd.ToInteger(start_index)) ||
            NPT_FAILED(reqCount.ToInteger(req_count))) {
            return NPT_FAILURE;
        }   
                    
        unsigned long cur_index = 0;
        unsigned long num_returned = 0;
        unsigned long total_matches = 0;
        //unsigned long update_id = 0;
        PLT_MediaContainer item;
        NPT_String tmp;
        NPT_String didl = didl_header;

        // populate a list of containers (one container per known servers)
        const NPT_Lock<PLT_DeviceDataReferenceList>& devices = GetMediaServers();
        NPT_Lock<PLT_DeviceDataReferenceList>::Iterator entry = devices.GetFirstItem();
        while (entry) {
            PLT_DeviceDataReference device = (*entry);
            item.m_Title = device->GetFriendlyName();
            item.m_ObjectID = FormatObjectId(device->GetUUID(), "0");
            item.m_ParentID = "0";
            item.m_ObjectClass.type = "object.container";

            if ((cur_index >= start_index) && ((num_returned < req_count) || (req_count == 0))) {
                NPT_CHECK_SEVERE(PLT_Didl::ToDidl(item, filter, tmp));

                didl += tmp;
                num_returned++;
            }
            cur_index++;
            total_matches++;  

            ++entry;
        }

        didl += didl_footer;

        action->SetArgumentValue("Result", didl);
        action->SetArgumentValue("NumberReturned", NPT_String::FromInteger(num_returned));
        action->SetArgumentValue("TotalMatches", NPT_String::FromInteger(total_matches));
        action->SetArgumentValue("UpdateId", "1");
    }

    return NPT_SUCCESS;
}