void CFileRar::InitFromUrl(const CURL& url) { url.GetURL(m_strUrl); m_strCacheDir = g_advancedSettings.m_cachePath;//url.GetDomain(); if (!CUtil::HasSlashAtEnd(m_strCacheDir)) m_strCacheDir += "/"; // should work local and remote.. m_strRarPath = url.GetHostName(); m_strPassword = url.GetUserName(); m_strPathInRar = url.GetFileName(); std::vector<CStdString> options; CUtil::Tokenize(url.GetOptions().Mid(1), options, "&"); m_bFileOptions = 0; m_bRarOptions = 0; for( std::vector<CStdString>::iterator it = options.begin();it != options.end(); it++) { int iEqual = (*it).Find('='); if( iEqual >= 0 ) { CStdString strOption = (*it).Left(iEqual); CStdString strValue = (*it).Mid(iEqual+1); if( strOption.Equals("flags") ) m_bFileOptions = atoi(strValue.c_str()); else if( strOption.Equals("cache") ) m_strCacheDir = strValue; } } }
CFileItemPtr BuildFileItem(const CURL& url, TiXmlElement& el) { CFileItemPtr pItem(new CFileItem()); pItem->m_bIsFolder = true; const char* key = el.Attribute("key"); if (key == 0 || strlen(key) == 0) return CFileItemPtr(); string src = key; CStdString parentPath; url.GetURL(parentPath); // Compute the new path. pItem->m_strPath = CPlexDirectory::ProcessUrl(parentPath, src, true); // Let subclass finish. DoBuildFileItem(pItem, string(parentPath), el); // Date. const char* date = el.Attribute("subtitle"); if (date && strlen(date) > 0) pItem->SetProperty("subtitle", date); try { // Thumb. const char* thumb = el.Attribute("thumb"); if (thumb && strlen(thumb) > 0) { string strThumb = CPlexDirectory::ProcessUrl(parentPath, thumb, false); pItem->SetThumbnailImage(strThumb); } // Fanart. const char* fanart = el.Attribute("art"); string strFanart; if (fanart && strlen(fanart) > 0) { strFanart = CPlexDirectory::ProcessUrl(parentPath, fanart, false); pItem->SetQuickFanart(strFanart); } } catch (...) { printf("ERROR: Exception setting directory thumbnail.\n"); } // Make sure we have the trailing slash. if (pItem->m_bIsFolder == true && pItem->m_strPath[pItem->m_strPath.size()-1] != '/') pItem->m_strPath += "/"; return pItem; }
void CPlexDirectory::Parse(const CURL& url, TiXmlElement* root, CFileItemList &items, string& strFileLabel, string& strDirLabel, string& strSecondDirLabel) { PlexMediaNode* mediaNode = 0; for (TiXmlElement* element = root->FirstChildElement(); element; element=element->NextSiblingElement()) { mediaNode = PlexMediaNode::Create(element->Value()); if (mediaNode != 0) { CFileItemPtr item = mediaNode->BuildFileItem(url, *element); if (item) items.Add(item); } } if (mediaNode != 0) { CStdString strURL; url.GetURL(strURL); mediaNode->ComputeLabels(strURL, strFileLabel, strDirLabel, strSecondDirLabel); } }
bool CShoutcastDirectory::ParseGenres(TiXmlElement *root, CFileItemList &items, CURL &url) { TiXmlElement *element = root->FirstChildElement("genre"); if(element == NULL) { CLog::Log(LOGWARNING, "%s - No genres found", __FUNCTION__); return false; } items.m_idepth = 1; /* genre list */ CStdString genre, path; while(element != NULL) { genre = element->Attribute("name"); path = genre; /* genre must be urlencoded */ CUtil::URLEncode(path); url.SetOptions("?genre=" + path); url.GetURL(path); CFileItem* pItem = new CFileItem; pItem->m_bIsFolder = true; pItem->SetLabel(genre); pItem->GetMusicInfoTag()->SetGenre(genre); pItem->m_strPath = path; items.Add(pItem); element = element->NextSiblingElement("genre"); } return true; }
//********************************************************************************************* int CFileRar::Stat(const CURL& url, struct __stat64* buffer) { if (Open(url, true)) { buffer->st_size = GetLength(); buffer->st_mode = _S_IFREG; Close(); errno = 0; return 0; } CStdString strURL; url.GetURL(strURL); if (CDirectory::Exists(strURL)) { buffer->st_mode = _S_IFDIR; return 0; } errno = ENOENT; return -1; }
bool CLastFmManager::ChangeStation(const CURL& stationUrl) { DWORD start = timeGetTime(); CStdString strUrl; stationUrl.GetURL(strUrl); InitProgressDialog(strUrl); StopRadio(false); if (!RadioHandShake()) { CloseProgressDialog(); CGUIDialogOK::ShowAndGetInput(15200, 15206, 0, 0); return false; } UpdateProgressDialog(15252); // Selecting station... CHTTP http; CStdString url; CStdString html; url.Format("http://" + m_RadioBaseUrl + m_RadioBasePath + "/adjust.php?session=%s&url=%s&debug=%i", m_RadioSession, strUrl, 0); if (!http.Get(url, html)) { CLog::Log(LOGERROR, "Connect to Last.fm to change station failed."); CloseProgressDialog(); return false; } //CLog::DebugLog("ChangeStation: %s", html.c_str()); CStdString strErrorCode; Parameter("error", html, strErrorCode); if (strErrorCode != "") { CLog::Log(LOGERROR, "Last.fm returned an error (%s) response for change station request.", strErrorCode.c_str()); CloseProgressDialog(); return false; } UpdateProgressDialog(261); //Waiting for start.... g_playlistPlayer.ClearPlaylist(PLAYLIST_MUSIC); g_playlistPlayer.SetShuffle(PLAYLIST_MUSIC, false); g_playlistPlayer.SetRepeat(PLAYLIST_MUSIC, PLAYLIST::REPEAT_NONE); RequestRadioTracks(); CacheTrackThumb(XBMC_LASTFM_MINTRACKS); AddToPlaylist(XBMC_LASTFM_MINTRACKS); Create(); //start thread SetEvent(m_hWorkerEvent); //kickstart the thread CSingleLock lock(m_lockPlaylist); CPlayList& playlist = g_playlistPlayer.GetPlaylist(PLAYLIST_MUSIC); if ((int)playlist.size()) { g_application.m_strPlayListFile = strUrl; //needed to highlight the playing item g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_MUSIC); g_playlistPlayer.Play(0); CLog::Log(LOGDEBUG, "%s: Done (time: %i ms)", __FUNCTION__, (int)(timeGetTime() - start)); CloseProgressDialog(); return true; } CloseProgressDialog(); return false; }
bool CShoutcastDirectory::ParseStations(TiXmlElement *root, CFileItemList &items, CURL &url) { TiXmlElement *element = NULL; CStdString path; items.m_idepth = 2; /* station list */ element = root->FirstChildElement("tunein"); if(element == NULL) { CLog::Log(LOGWARNING, "%s - No tunein base found", __FUNCTION__); return false; } path = element->Attribute("base"); path.TrimLeft("/"); url.SetFileName(path); element = root->FirstChildElement("station"); if(element == NULL) { CLog::Log(LOGWARNING, "%s - No stations found", __FUNCTION__); return false; } int stations = 0; while(element != NULL && stations < 1000) { CStdString name = element->Attribute("name"); CStdString id = element->Attribute("id"); CStdString bitrate = element->Attribute("br"); CStdString genre = element->Attribute("genre"); CStdString listeners = element->Attribute("lc"); CStdString content = element->Attribute("mt"); CStdString label = name; url.SetOptions("?id=" + id); url.GetURL(path); //printf("%s: %s\n", name.c_str(), path.c_str()); CFileItem* pItem = new CFileItem; pItem->m_bIsFolder = false; /* we highjack the music tag for this stuff, they will be used by */ /* viewstates to sort and display proper information */ pItem->GetMusicInfoTag()->SetArtist(listeners); pItem->GetMusicInfoTag()->SetAlbum(bitrate); pItem->GetMusicInfoTag()->SetGenre(genre); /* this is what will be sorted upon */ pItem->GetVideoInfoTag()->m_fRating = (float)atoi(listeners.c_str()); pItem->m_dwSize = atoi(bitrate.c_str()); pItem->SetLabel(label); /* content type is known before hand, should save later lookup */ /* wonder if we could combine the contentype of the playlist and of the real stream */ pItem->SetContentType("audio/x-scpls"); pItem->m_strPath = path; items.Add(pItem); stations++; element = element->NextSiblingElement("station"); } return true; }
//********************************************************************************************* bool CFileRar::Open(const CURL& url, bool bBinary) { CStdString strFile; url.GetURL(strFile); InitFromUrl(url); CFileItemList items; g_RarManager.GetFilesInRar(items,m_strRarPath,false); int i; for (i=0;i<items.Size();++i) { if (items[i]->GetLabel() == m_strPathInRar) break; } if (i<items.Size()) if (items[i]->m_idepth == 0x30) // stored { if (!OpenInArchive()) return false; m_iFileSize = items[i]->m_dwSize; m_bOpen = true; // perform 'noidx' check CFileInfo* pFile = g_RarManager.GetFileInRar(m_strRarPath,m_strPathInRar); if (pFile) if (pFile->m_iIsSeekable == -1) { if (Seek(-1,SEEK_END) == -1) { m_bSeekable = false; pFile->m_iIsSeekable = 0; } } else m_bSeekable = (pFile->m_iIsSeekable == 1); return true; } else { #ifdef HAS_XBOX_HARDWARE if (items[i]->m_dwSize > ((__int64)4)*1024*1024*1024) // 4 gig limit of fat-x { CGUIDialogOK::ShowAndGetInput(257,21395,-1,-1); CLog::Log(LOGERROR,"CFileRar::Open: Can't cache files bigger than 4GB due to fat-x limits."); return false; } #endif m_bUseFile = true; CStdString strPathInCache; if (!g_RarManager.CacheRarredFile(strPathInCache, m_strRarPath, m_strPathInRar, EXFILE_AUTODELETE | m_bFileOptions, m_strCacheDir, items[i]->m_dwSize)) { CLog::Log(LOGERROR,"filerar::open failed to cache file %s",m_strPathInRar.c_str()); return false; } if (!m_File.Open( strPathInCache, bBinary)) { CLog::Log(LOGERROR,"filerar::open failed to open file in cache: %s",strPathInCache.c_str()); return false; } m_bOpen = true; return true; } return false; }
bool CFileShoutcast::Open(const CURL& url, bool bBinary) { m_dwLastTime = timeGetTime(); int ret; CGUIDialogProgress* dlgProgress = (CGUIDialogProgress*)m_gWindowManager.GetWindow(WINDOW_DIALOG_PROGRESS); set_rip_manager_options_defaults(&m_opt); strcpy(m_opt.output_directory, "./"); m_opt.proxyurl[0] = '\0'; // Use a proxy, if the GUI was configured as such bool bProxyEnabled = g_guiSettings.GetBool("network.usehttpproxy"); if (bProxyEnabled) { const CStdString &strProxyServer = g_guiSettings.GetString("network.httpproxyserver"); const CStdString &strProxyPort = g_guiSettings.GetString("network.httpproxyport"); // Should we check for valid strings here #ifndef _LINUX _snprintf( m_opt.proxyurl, MAX_URL_LEN, "http://%s:%s", strProxyServer.c_str(), strProxyPort.c_str() ); #else snprintf( m_opt.proxyurl, MAX_URL_LEN, "http://%s:%s", strProxyServer.c_str(), strProxyPort.c_str() ); #endif } CStdString strUrl; url.GetURL(strUrl); strUrl.Replace("shout://", "http://"); printf("Opening url: %s\n", strUrl.c_str()); strncpy(m_opt.url, strUrl.c_str(), MAX_URL_LEN); sprintf(m_opt.useragent, "x%s", url.GetFileName().c_str()); if (dlgProgress) { dlgProgress->SetHeading(260); dlgProgress->SetLine(0, 259); dlgProgress->SetLine(1, strUrl); dlgProgress->SetLine(2, ""); if (!dlgProgress->IsDialogRunning()) dlgProgress->StartModal(); dlgProgress->Progress(); } if ((ret = rip_manager_start(rip_callback, &m_opt)) != SR_SUCCESS) { if (dlgProgress) dlgProgress->Close(); return false; } int iShoutcastTimeout = 10 * SHOUTCASTTIMEOUT; //i.e: 10 * 10 = 100 * 100ms = 10s int iCount = 0; while (!m_fileState.bRipDone && !m_fileState.bRipStarted && !m_fileState.bRipError && (!dlgProgress || !dlgProgress->IsCanceled())) { if (iCount <= iShoutcastTimeout) //Normally, this isn't the problem, //because if RIP_MANAGER fails, this would be here //with m_fileState.bRipError { Sleep(100); } else { if (dlgProgress) { dlgProgress->SetLine(1, 257); dlgProgress->SetLine(2, "Connection timed out..."); Sleep(1500); dlgProgress->Close(); } return false; } iCount++; } if (dlgProgress && dlgProgress->IsCanceled()) { Close(); dlgProgress->Close(); return false; } /* store content type of stream */ m_contenttype = rip_manager_get_content_type(); //CHANGED CODE: Don't reset timer anymore. while (!m_fileState.bRipDone && !m_fileState.bRipError && m_fileState.bBuffering && (!dlgProgress || !dlgProgress->IsCanceled())) { if (iCount <= iShoutcastTimeout) //Here is the real problem: Sometimes the buffer fills just to //slowly, thus the quality of the stream will be bad, and should be //aborted... { Sleep(100); char szTmp[1024]; //g_dialog.SetCaption(0, "Shoutcast" ); sprintf(szTmp, "Buffering %i bytes", m_ringbuf.GetMaxReadSize()); if (dlgProgress) { dlgProgress->SetLine(2, szTmp ); dlgProgress->Progress(); } sprintf(szTmp, "%s", m_ripInfo.filename); for (int i = 0; i < (int)strlen(szTmp); i++) szTmp[i] = tolower((unsigned char)szTmp[i]); szTmp[50] = 0; if (dlgProgress) { dlgProgress->SetLine(1, szTmp ); dlgProgress->Progress(); } } else //it's not really a connection timeout, but it's here, //where things get boring, if connection is slow. //trust me, i did a lot of testing... Doesn't happen often, //but if it does it sucks to wait here forever. //CHANGED: Other message here { if (dlgProgress) { dlgProgress->SetLine(1, 257); dlgProgress->SetLine(2, "Connection to server too slow..."); dlgProgress->Close(); } return false; } iCount++; } if (dlgProgress && dlgProgress->IsCanceled()) { Close(); dlgProgress->Close(); return false; } if ( m_fileState.bRipError ) { if (dlgProgress) { dlgProgress->SetLine(1, 257); dlgProgress->SetLine(2, m_errorInfo.error_str); dlgProgress->Progress(); Sleep(1500); dlgProgress->Close(); } return false; } if (dlgProgress) { dlgProgress->SetLine(2, 261); dlgProgress->Progress(); dlgProgress->Close(); } return true; }