示例#1
0
文件: iputils.cpp 项目: alioxp/vc
bool MatchesFilter(CStdString filter, CStdString ip)
{
	// A single asterix matches all IPs.
	if (filter == _T("*"))
		return true;

	// Check for IP range syntax.
	int pos = filter.Find('/');
	if (pos != -1) {
		// CIDR filter
		int prefixLength = _ttoi(filter.Mid(pos+1));

		if (ip.Find(':') != -1) {
			// IPv6 address
			CStdString left = GetIPV6LongForm(filter.Left(pos));
			if (left.Find(':') == -1)
				return false;
			ip = GetIPV6LongForm(ip);
			LPCTSTR i = ip;
			LPCTSTR f = left;
			while (prefixLength >= 4) {
				if (*i != *f)
					return false;

				if (!*i)
					return true;

				if (*i == ':') {
					++i;
					++f;
				}
				++i;
				++f;

				prefixLength -= 4;
			}
			if (!prefixLength)
				return true;

			int mask;
			if (prefixLength == 1)
				mask = 0x8;
			else if (prefixLength == 2)
				mask = 0xc;
			else
				mask = 0xe;

			return (DigitHexToDecNum(*i) & mask) == (DigitHexToDecNum(*f) & mask);
		}
		else {
			if (prefixLength < 0)
				prefixLength = 0;
			else if (prefixLength > 32)
				prefixLength = 32;

			// IPv4 address
			CStdString left = filter.Left(pos);
			if (left.Find(':') != -1)
				return false;

			unsigned long i = ntohl(inet_addr(ConvToLocal(ip)));
			unsigned long f = ntohl(inet_addr(ConvToLocal(left)));

			i &= prefixMasksV4[prefixLength];
			f &= prefixMasksV4[prefixLength];
			return i == f;
		}
	}
	else {
		// Literal filter
		if (filter.Find(':') != -1)
			return filter == GetIPV6ShortForm(ip);
		else
			return filter == ip;
	}
}
示例#2
0
bool CMythDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items)
{
    m_session = CMythSession::AquireSession(strPath);
    if (!m_session)
        return false;

    m_dll = m_session->GetLibrary();
    if (!m_dll)
        return false;

    CStdString base(strPath);
    URIUtils::RemoveSlashAtEnd(base);

    CURL url(strPath);
    CStdString fileName = url.GetFileName();
    URIUtils::RemoveSlashAtEnd(fileName);

    if (fileName == "")
    {
        /*
         * If we can't get the control then we can't connect to the backend. Don't even show any of the
         * virtual folders as none of them will work. Without this check the "Browse" functionality
         * when adding a myth:// source is way confusing as it shows folders so it looks like it has
         * connected successfully when it in fact hasn't.
         */
        cmyth_conn_t control = m_session->GetControl();
        if (!control)
            return false;

        CFileItemPtr item;

        item.reset(new CFileItem(base + "/recordings/", true));
        item->SetLabel(g_localizeStrings.Get(22015)); // All recordings
        items.Add(item);

        item.reset(new CFileItem(base + "/tvshows/", true));
        item->SetLabel(g_localizeStrings.Get(20343)); // TV shows
        items.Add(item);

        item.reset(new CFileItem(base + "/movies/", true));
        item->SetLabel(g_localizeStrings.Get(20342)); // Movies
        items.Add(item);

        item.reset(new CFileItem(base + "/channels/", true));
        item->SetLabel(g_localizeStrings.Get(22018)); // Live channels
        items.Add(item);

        item.reset(new CFileItem(base + "/guide/", true));
        item->SetLabel(g_localizeStrings.Get(22020)); // Guide
        items.Add(item);

        items.AddSortMethod(SORT_METHOD_NONE, 564 /* Type */, LABEL_MASKS("", "", "%L", "")); // No sorting, as added to list.

        /*
         * Clear the directory cache so the cached sub-folders are guaranteed to be accurate.
         */
        g_directoryCache.ClearSubPaths(base);

        return true;
    }
    else if (fileName == "channels")
        return GetChannels(base, items);
    else if (fileName == "guide")
        return GetGuide(base, items);
    else if (fileName.Left(6) == "guide/")
        return GetGuideForChannel(base, items, atoi(fileName.Mid(6)));
    else if (fileName == "movies")
        return GetRecordings(base, items, MOVIES);
    else if (fileName == "recordings")
        return GetRecordings(base, items);
    else if (fileName == "tvshows")
        return GetTvShowFolders(base, items);
    else if (fileName.Left(8) == "tvshows/")
        return GetRecordings(base, items, TV_SHOWS, fileName.Mid(8));
    return false;
}
示例#3
0
// TODO: Currently no support for "embedded thumb" as there is no easy way to grab it
//       without sending a file that has this as it's album to this class
void CGUIDialogMusicInfo::OnGetThumb()
{
  CFileItemList items;

  // Current thumb
  if (CFile::Exists(m_albumItem->GetArt("thumb")))
  {
    CFileItemPtr item(new CFileItem("thumb://Current", false));
    item->SetArt("thumb", m_albumItem->GetArt("thumb"));
    item->SetLabel(g_localizeStrings.Get(20016));
    items.Add(item);
  }

  // Grab the thumbnail(s) from the web
  vector<CStdString> thumbs;
  if (m_bArtistInfo)
    m_artist.thumbURL.GetThumbURLs(thumbs);
  else
    m_album.thumbURL.GetThumbURLs(thumbs);

  for (unsigned int i = 0; i < thumbs.size(); ++i)
  {
    CStdString strItemPath;
    strItemPath.Format("thumb://Remote%i", i);
    CFileItemPtr item(new CFileItem(strItemPath, false));
    item->SetArt("thumb", thumbs[i]);
    item->SetIconImage("DefaultPicture.png");
    item->SetLabel(g_localizeStrings.Get(20015));
    
    // TODO: Do we need to clear the cached image?
    //    CTextureCache::Get().ClearCachedImage(thumb);
    items.Add(item);
  }

  // local thumb
  CStdString localThumb;
  if (m_bArtistInfo)
  {
    CMusicDatabase database;
    database.Open();
    CStdString strArtistPath;
    if (database.GetArtistPath(m_artist.idArtist,strArtistPath))
      localThumb = URIUtils::AddFileToFolder(strArtistPath, "folder.jpg");
  }
  else
    localThumb = m_albumItem->GetUserMusicThumb();
  if (CFile::Exists(localThumb))
  {
    CFileItemPtr item(new CFileItem("thumb://Local", false));
    item->SetArt("thumb", localThumb);
    item->SetLabel(g_localizeStrings.Get(20017));
    items.Add(item);
  }
  else
  {
    CFileItemPtr item(new CFileItem("thumb://None", false));
    if (m_bArtistInfo)
      item->SetIconImage("DefaultArtist.png");
    else
      item->SetIconImage("DefaultAlbumCover.png");
    item->SetLabel(g_localizeStrings.Get(20018));
    items.Add(item);
  }

  CStdString result;
  bool flip=false;
  VECSOURCES sources(*CMediaSourceSettings::Get().GetSources("music"));
  AddItemPathToFileBrowserSources(sources, *m_albumItem);
  g_mediaManager.GetLocalDrives(sources);
  if (!CGUIDialogFileBrowser::ShowAndGetImage(items, sources, g_localizeStrings.Get(1030), result, &flip))
    return;   // user cancelled

  if (result == "thumb://Current")
    return;   // user chose the one they have

  CStdString newThumb;
  if (result.Left(14) == "thumb://Remote")
  {
    int number = atoi(result.Mid(14));
    newThumb = thumbs[number];
  }
  else if (result == "thumb://Local")
    newThumb = localThumb;
  else if (CFile::Exists(result))
    newThumb = result;
  else // none
    newThumb = "-"; // force local thumbs to be ignored

  // update thumb in the database
  CMusicDatabase db;
  if (db.Open())
  {
    db.SetArtForItem(m_albumItem->GetMusicInfoTag()->GetDatabaseId(), m_albumItem->GetMusicInfoTag()->GetType(), "thumb", newThumb);
    db.Close();
  }

  m_albumItem->SetArt("thumb", newThumb);
  m_hasUpdatedThumb = true;

  // tell our GUI to completely reload all controls (as some of them
  // are likely to have had this image in use so will need refreshing)
  CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_REFRESH_THUMBS);
  g_windowManager.SendMessage(msg);
  // Update our screen
  Update();
}
void CGUIDialogAudioSubtitleSettings::AddAudioStreams(unsigned int id)
{
  SettingInfo setting;
  setting.id = id;
  setting.name = g_localizeStrings.Get(460);
  setting.type = SettingInfo::SPIN;
  setting.min = 0;
  setting.data = &m_audioStream;

  // get the number of audio strams for the current movie
  setting.max = (float)g_application.m_pPlayer->GetAudioStreamCount() - 1;
  m_audioStream = g_application.m_pPlayer->GetAudioStream();

  if( m_audioStream < 0 ) m_audioStream = 0;

  // check if we have a single, stereo stream, and if so, allow us to split into
  // left, right or both
  if (!setting.max)
  {
    CStdString strAudioInfo;
    g_application.m_pPlayer->GetAudioInfo(strAudioInfo);
    int iNumChannels = atoi(strAudioInfo.Right(strAudioInfo.size() - strAudioInfo.Find("chns:") - 5).c_str());
    CStdString strAudioCodec = strAudioInfo.Mid(7, strAudioInfo.Find(") VBR") - 5);
    bool bDTS = strstr(strAudioCodec.c_str(), "DTS") != 0;
    bool bAC3 = strstr(strAudioCodec.c_str(), "AC3") != 0;
    if (iNumChannels == 2 && !(bDTS || bAC3))
    { // ok, enable these options
/*      if (g_stSettings.m_currentVideoSettings.m_AudioStream == -1)
      { // default to stereo stream
        g_stSettings.m_currentVideoSettings.m_AudioStream = 0;
      }*/
      setting.max = 2;
      for (int i = 0; i <= setting.max; i++)
        setting.entry.push_back(g_localizeStrings.Get(13320 + i));
      m_audioStream = -g_stSettings.m_currentVideoSettings.m_AudioStream - 1;
      m_settings.push_back(setting);
      return;
    }
  }

  // cycle through each audio stream and add it to our list control
  for (int i = 0; i <= setting.max; ++i)
  {
    CStdString strItem;
    CStdString strName;
    g_application.m_pPlayer->GetAudioStreamName(i, strName);
    if (strName.length() == 0)
      strName = "Unnamed";

    strItem.Format("%s (%i/%i)", strName.c_str(), i + 1, (int)setting.max + 1);
    setting.entry.push_back(strItem);
  }

  if( setting.max < 0 )
  {
    setting.max = 0;
    setting.entry.push_back(g_localizeStrings.Get(231).c_str());
  }

  m_settings.push_back(setting);
}
示例#5
0
// TODO: Currently no support for "embedded thumb" as there is no easy way to grab it
//       without sending a file that has this as it's album to this class
void CGUIWindowMusicInfo::OnGetThumb()
{
  CFileItemList items;

  // Grab the thumbnail from the web
  CStdString thumbFromWeb;
  CUtil::AddFileToFolder(g_advancedSettings.m_cachePath, "allmusicThumb", thumbFromWeb);
  int iDownloaded=DownloadThumbnail(thumbFromWeb,true);
  if (iDownloaded > 0)
  {
    for (int i=0;i<iDownloaded;++i)
    {
      CStdString strThumb;
      strThumb.Format("thumb://Remote%i",i);
      CFileItem *item = new CFileItem(strThumb, false);
      strThumb.Format("%s%i.tbn",thumbFromWeb,i);
      item->SetThumbnailImage(strThumb);
      item->SetLabel(g_localizeStrings.Get(20055));
      items.Add(item);
    }
  }

  // Current thumb
  if (CFile::Exists(m_albumItem->GetThumbnailImage()))
  {
    CFileItem *item = new CFileItem("thumb://Current", false);
    item->SetThumbnailImage(m_albumItem->GetThumbnailImage());
    item->SetLabel(g_localizeStrings.Get(20016));
    items.Add(item);
  }

  // local thumb
  CStdString cachedLocalThumb;
  CStdString localThumb;
  if (m_bArtistInfo)
  {
    CMusicDatabase database;
    database.Open();
    CStdString strArtistPath;
    database.GetArtistPath(m_artist.idArtist,strArtistPath);
    CUtil::AddFileToFolder(strArtistPath,"folder.jpg",localThumb);
  }
  else
    CStdString localThumb = m_albumItem->GetUserMusicThumb();
  if (CFile::Exists(localThumb))
  {
    CUtil::AddFileToFolder(g_advancedSettings.m_cachePath, "localthumb.jpg", cachedLocalThumb);
    CPicture pic;
    if (pic.DoCreateThumbnail(localThumb, cachedLocalThumb))
    {
      CFileItem *item = new CFileItem("thumb://Local", false);
      item->SetThumbnailImage(cachedLocalThumb);
      item->SetLabel(g_localizeStrings.Get(20017));
      items.Add(item);
    }
  }
  
  CFileItem *item = new CFileItem("thumb://None", false);
  if (m_bArtistInfo)
    item->SetThumbnailImage("defaultArtistBig.png");
  else
    item->SetThumbnailImage("defaultAlbumCover.png");
  item->SetLabel(g_localizeStrings.Get(20018));
  items.Add(item);
  
  CStdString result;
  if (!CGUIDialogFileBrowser::ShowAndGetImage(items, g_settings.m_musicSources, g_localizeStrings.Get(1030), result))
    return;   // user cancelled

  if (result == "thumb://Current")
    return;   // user chose the one they have

  // delete the thumbnail if that's what the user wants, else overwrite with the
  // new thumbnail
  CStdString cachedThumb;
  if (m_bArtistInfo)
    cachedThumb = m_albumItem->GetCachedArtistThumb();
  else
    cachedThumb = CUtil::GetCachedAlbumThumb(m_album.strAlbum, m_album.strArtist);

  if (result == "thumb://None")
  { // cache the default thumb
    CPicture pic;
    pic.CacheSkinImage("defaultAlbumCover.png", cachedThumb);
  }
  else if (result.Left(14).Equals("thumb://Remote"))
    CFile::Cache(thumbFromWeb+result.Mid(14)+".tbn", cachedThumb);
  else if (result == "thumb://Local")
    CFile::Cache(cachedLocalThumb, cachedThumb);
  else if (CFile::Exists(result))
  {
    CPicture pic;
    pic.DoCreateThumbnail(result, cachedThumb);
  }

  m_albumItem->SetThumbnailImage(cachedThumb);
  m_hasUpdatedThumb = true;

  // tell our GUI to completely reload all controls (as some of them
  // are likely to have had this image in use so will need refreshing)
  CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_REFRESH_THUMBS);
  g_graphicsContext.SendMessage(msg);
  // Update our screen
  Update();
}
// Allow user to select a Fanart
void CGUIDialogVideoInfo::OnGetFanart()
{
  CFileItemList items;

  CFileItem item(*m_movieItem->GetVideoInfoTag());
  if (item.HasProperty("fanart_image"))
  {
    CFileItemPtr itemCurrent(new CFileItem("fanart://Current",false));
    itemCurrent->SetThumbnailImage(item.GetProperty("fanart_image").asString());
    itemCurrent->SetLabel(g_localizeStrings.Get(20440));
    items.Add(itemCurrent);
  }

  // ensure the fanart is unpacked
  m_movieItem->GetVideoInfoTag()->m_fanart.Unpack();

  // Grab the thumbnails from the web
  for (unsigned int i = 0; i < m_movieItem->GetVideoInfoTag()->m_fanart.GetNumFanarts(); i++)
  {
    CStdString strItemPath;
    strItemPath.Format("fanart://Remote%i",i);
    CFileItemPtr item(new CFileItem(strItemPath, false));
    CStdString thumb = m_movieItem->GetVideoInfoTag()->m_fanart.GetPreviewURL(i);
    item->SetThumbnailImage(CTextureCache::GetWrappedThumbURL(thumb));
    item->SetIconImage("DefaultPicture.png");
    item->SetLabel(g_localizeStrings.Get(20441));

    // TODO: Do we need to clear the cached image?
//    CTextureCache::Get().ClearCachedImage(thumb);
    items.Add(item);
  }

  CStdString strLocal = item.GetLocalFanart();
  if (!strLocal.IsEmpty())
  {
    CFileItemPtr itemLocal(new CFileItem("fanart://Local",false));
    itemLocal->SetThumbnailImage(strLocal);
    itemLocal->SetLabel(g_localizeStrings.Get(20438));

    // TODO: Do we need to clear the cached image?
    CTextureCache::Get().ClearCachedImage(strLocal);
    items.Add(itemLocal);
  }
  else
  {
    CFileItemPtr itemNone(new CFileItem("fanart://None", false));
    itemNone->SetIconImage("DefaultVideo.png");
    itemNone->SetLabel(g_localizeStrings.Get(20439));
    items.Add(itemNone);
  }

  CStdString result;
  VECSOURCES sources(g_settings.m_videoSources);
  g_mediaManager.GetLocalDrives(sources);
  bool flip=false;
  if (!CGUIDialogFileBrowser::ShowAndGetImage(items, sources, g_localizeStrings.Get(20437), result, &flip, 20445) || result.Equals("fanart://Current"))
    return;   // user cancelled

  if (result.Equals("fanart://Local"))
    result = strLocal;

  if (result.Left(15) == "fanart://Remote")
  {
    int iFanart = atoi(result.Mid(15).c_str());
    // set new primary fanart, and update our database accordingly
    m_movieItem->GetVideoInfoTag()->m_fanart.SetPrimaryFanart(iFanart);
    CVideoDatabase db;
    if (db.Open())
    {
      db.UpdateFanart(*m_movieItem, (VIDEODB_CONTENT_TYPE)m_movieItem->GetVideoContentType());
      db.Close();
    }
    result = m_movieItem->GetVideoInfoTag()->m_fanart.GetImageURL();
  }
  else if (result.Equals("fanart://None") || !CFile::Exists(result))
    result.clear();

  // set the fanart image
  if (flip && !result.IsEmpty())
    result = CTextureCache::GetWrappedImageURL(result, "", "flipped");
  CVideoDatabase db;
  if (db.Open())
  {
    db.SetArtForItem(m_movieItem->GetVideoInfoTag()->m_iDbId, m_movieItem->GetVideoInfoTag()->m_type, "fanart", result);
    db.Close();
  }

  CUtil::DeleteVideoDatabaseDirectoryCache(); // to get them new thumbs to show
  if (!result.IsEmpty())
    m_movieItem->SetProperty("fanart_image", result);
  else
    m_movieItem->ClearProperty("fanart_image");
  m_hasUpdatedThumb = true;

  // Update our screen
  Update();
}
void CExternalPlayer::Process()
{
  SetName("CExternalPlayer");

  CStdString mainFile = m_launchFilename;
  CStdString archiveContent = "";

  if (m_args.find("{0}") == std::string::npos)
  {
    // Unwind archive names
    CURL url(m_launchFilename);
    CStdString protocol = url.GetProtocol();
    if (protocol == "zip" || protocol == "rar"/* || protocol == "iso9660" ??*/)
    {
      mainFile = url.GetHostName();
      archiveContent = url.GetFileName();
    }
    if (protocol == "musicdb")
      mainFile = CFileMusicDatabase::TranslateUrl(url);
  }

  if (m_filenameReplacers.size() > 0) 
  {
    for (unsigned int i = 0; i < m_filenameReplacers.size(); i++)
    {
      std::vector<CStdString> vecSplit;
      StringUtils::SplitString(m_filenameReplacers[i], " , ", vecSplit);

      // something is wrong, go to next substitution
      if (vecSplit.size() != 4)
        continue;

      CStdString strMatch = vecSplit[0];
      strMatch.Replace(",,",",");
      bool bCaseless = vecSplit[3].Find('i') > -1;
      CRegExp regExp(bCaseless);

      if (!regExp.RegComp(strMatch.c_str()))
      { // invalid regexp - complain in logs
        CLog::Log(LOGERROR, "%s: Invalid RegExp:'%s'", __FUNCTION__, strMatch.c_str());
        continue;
      }

      if (regExp.RegFind(mainFile) > -1) 
      {
        CStdString strPat = vecSplit[1];
        strPat.Replace(",,",",");

        if (!regExp.RegComp(strPat.c_str()))
        { // invalid regexp - complain in logs
          CLog::Log(LOGERROR, "%s: Invalid RegExp:'%s'", __FUNCTION__, strPat.c_str());
          continue;
        }

        CStdString strRep = vecSplit[2];
        strRep.Replace(",,",",");
        bool bGlobal = vecSplit[3].Find('g') > -1;
        bool bStop = vecSplit[3].Find('s') > -1;
        int iStart = 0;
        while ((iStart = regExp.RegFind(mainFile, iStart)) > -1)
        {
          int iLength = regExp.GetFindLen();
          mainFile = mainFile.Left(iStart) + regExp.GetReplaceString(strRep.c_str()) + mainFile.Mid(iStart+iLength);
          if (!bGlobal)
            break;
        }
        CLog::Log(LOGINFO, "%s: File matched:'%s' (RE='%s',Rep='%s') new filename:'%s'.", __FUNCTION__, strMatch.c_str(), strPat.c_str(), strRep.c_str(), mainFile.c_str());
        if (bStop) break;
      }
    }
  }

  CLog::Log(LOGNOTICE, "%s: Player : %s", __FUNCTION__, m_filename.c_str());
  CLog::Log(LOGNOTICE, "%s: File   : %s", __FUNCTION__, mainFile.c_str());
  CLog::Log(LOGNOTICE, "%s: Content: %s", __FUNCTION__, archiveContent.c_str());
  CLog::Log(LOGNOTICE, "%s: Args   : %s", __FUNCTION__, m_args.c_str());
  CLog::Log(LOGNOTICE, "%s: Start", __FUNCTION__);

  // make sure we surround the arguments with quotes where necessary
  CStdString strFName;
  CStdString strFArgs;
#if defined(_WIN32)
  // W32 batch-file handline
  if (m_filename.Right(4) == ".bat" || m_filename.Right(4) == ".cmd")
  {
    // MSDN says you just need to do this, but cmd's handing of spaces and
    // quotes is soo broken it seems to work much better if you just omit
    // lpApplicationName and enclose the module in lpCommandLine in quotes
    //strFName = "cmd.exe";
    //strFArgs = "/c ";
  }
  else
#endif
    strFName = m_filename;

  strFArgs.append("\"");
  strFArgs.append(m_filename);
  strFArgs.append("\" ");
  strFArgs.append(m_args);

  int nReplaced = strFArgs.Replace("{0}", mainFile);

  if (!nReplaced)
    nReplaced = strFArgs.Replace("{1}", mainFile) + strFArgs.Replace("{2}", archiveContent);

  if (!nReplaced)
  {
    strFArgs.append(" \"");
    strFArgs.append(mainFile);
    strFArgs.append("\"");
  }

  int iActiveDevice = g_audioContext.GetActiveDevice();
  if (iActiveDevice != CAudioContext::NONE)
  {
    CLog::Log(LOGNOTICE, "%s: Releasing audio device %d", __FUNCTION__, iActiveDevice);
    g_audioContext.SetActiveDevice(CAudioContext::NONE);
  }

  int iActiveDevice2 = g_audioContext2.GetActiveDevice();
  if (iActiveDevice2 != CAudioContext::NONE)
  {
    CLog::Log(LOGNOTICE, "%s: Releasing 2nd audio device %d", __FUNCTION__, iActiveDevice2);
    g_audioContext2.SetActiveDevice(CAudioContext::NONE);
  }

#if defined(_WIN32)
  if (m_warpcursor)
  {
    GetCursorPos(&m_ptCursorpos);
    int x = 0;
    int y = 0;
    switch (m_warpcursor)
    {
      case WARP_BOTTOM_RIGHT:
        x = GetSystemMetrics(SM_CXSCREEN);
      case WARP_BOTTOM_LEFT:
        y = GetSystemMetrics(SM_CYSCREEN);
        break;
      case WARP_TOP_RIGHT:
        x = GetSystemMetrics(SM_CXSCREEN);
        break;
      case WARP_CENTER:
        x = GetSystemMetrics(SM_CXSCREEN) / 2;
        y = GetSystemMetrics(SM_CYSCREEN) / 2;
        break;
    }
    CLog::Log(LOGNOTICE, "%s: Warping cursor to (%d,%d)", __FUNCTION__, x, y);
    SetCursorPos(x,y);
  }

  LONG currentStyle = GetWindowLong(g_hWnd, GWL_EXSTYLE);
#endif

  if (m_hidexbmc && !m_islauncher)
  {
    CLog::Log(LOGNOTICE, "%s: Hiding XBMC window", __FUNCTION__);
    g_Windowing.Hide();
  }
#if defined(_WIN32)
  else if (currentStyle & WS_EX_TOPMOST)
  {
    CLog::Log(LOGNOTICE, "%s: Lowering XBMC window", __FUNCTION__);
    SetWindowPos(g_hWnd,HWND_BOTTOM,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOREDRAW);
  }

  CLog::Log(LOGDEBUG, "%s: Unlocking foreground window", __FUNCTION__);
  LockSetForegroundWindow(LSFW_UNLOCK);
#endif

  m_playbackStartTime = CTimeUtils::GetTimeMS();
  BOOL ret = TRUE;
#if defined(_WIN32)
  ret = ExecuteAppW32(strFName.c_str(),strFArgs.c_str());
#elif defined(_LINUX)
  ret = ExecuteAppLinux(strFArgs.c_str());
#endif
  int64_t elapsedMillis = CTimeUtils::GetTimeMS() - m_playbackStartTime;

  if (ret && (m_islauncher || elapsedMillis < LAUNCHER_PROCESS_TIME))
  {
    if (m_hidexbmc)
    {
      CLog::Log(LOGNOTICE, "%s: XBMC cannot stay hidden for a launcher process", __FUNCTION__);
      g_Windowing.Show(false);
    }

    {
      CSingleLock lock(g_graphicsContext);
      m_dialog = (CGUIDialogOK *)g_windowManager.GetWindow(WINDOW_DIALOG_OK);
      m_dialog->SetHeading(23100);
      m_dialog->SetLine(1, 23104);
      m_dialog->SetLine(2, 23105);
      m_dialog->SetLine(3, 23106);
    }

    if (!m_bAbortRequest) m_dialog->DoModal();
  }

  m_bIsPlaying = false;
  CLog::Log(LOGNOTICE, "%s: Stop", __FUNCTION__);

#if defined(_WIN32)
  g_Windowing.Restore();

  if (currentStyle & WS_EX_TOPMOST)
  {
    CLog::Log(LOGNOTICE, "%s: Showing XBMC window TOPMOST", __FUNCTION__);
    SetWindowPos(g_hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW);
    SetForegroundWindow(g_hWnd);
  }
  else
#endif
  {
    CLog::Log(LOGNOTICE, "%s: Showing XBMC window", __FUNCTION__);
    g_Windowing.Show();
  }

#if defined(_WIN32)
  if (m_warpcursor)
  {
    m_xPos = 0;
    m_yPos = 0;
    if (&m_ptCursorpos != 0)
    {
      m_xPos = (m_ptCursorpos.x);
      m_yPos = (m_ptCursorpos.y);
    }
    CLog::Log(LOGNOTICE, "%s: Restoring cursor to (%d,%d)", __FUNCTION__, m_xPos, m_yPos);
    SetCursorPos(m_xPos,m_yPos);
  }
#endif

  // We don't want to come back to an active screensaver
  g_application.ResetScreenSaver();
  g_application.WakeUpScreenSaverAndDPMS();

  if (iActiveDevice != CAudioContext::NONE)
  {
    CLog::Log(LOGNOTICE, "%s: Reclaiming audio device %d", __FUNCTION__, iActiveDevice);
    g_audioContext.SetActiveDevice(iActiveDevice);
  }

  if (iActiveDevice2 != CAudioContext::NONE)
  {
    CLog::Log(LOGNOTICE, "%s: Reclaiming 2nd audio device %d", __FUNCTION__, iActiveDevice2);
    g_audioContext2.SetActiveDevice(iActiveDevice2);
  }

  if (!ret || (m_playOneStackItem && g_application.CurrentFileItem().IsStack()))
    m_callback.OnPlayBackStopped();
  else
    m_callback.OnPlayBackEnded();
}
示例#8
0
BOOL CServer::ProcessCommand(CAdminSocket *pAdminSocket, int nID, unsigned char *pData, int nDataLength)
{
	switch (nID)
	{
	case 2:
		if (!nDataLength) {
			unsigned char buffer[2];
			buffer[0] = m_nServerState / 256;
			buffer[1] = m_nServerState % 256;
			pAdminSocket->SendCommand(1, 2, buffer, 2);
		}
		else if (nDataLength == 2) {
			ToggleActive(*pData * 256 + pData[1]);
			unsigned char buffer[2];
			buffer[0] = m_nServerState / 256;
			buffer[1] = m_nServerState % 256;
			pAdminSocket->SendCommand(1, 2, buffer, 2);
		}
		else {
			pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length") + 1);
		}
		break;
	case 3:
		if (!nDataLength) {
			pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length") + 1);
		}
		else if (*pData == USERCONTROL_GETLIST) {
			int len = 4;
			std::map<int, t_connectiondata>::iterator iter;
			for (iter = m_UsersList.begin(); iter != m_UsersList.end(); ++iter) {
				const t_connectiondata& data = iter->second;
				auto ip = ConvToNetwork(data.ip);
				auto user = ConvToNetwork(data.user);
				len += 4 + ip.size() + 2 + 4 + user.size() + 2 + 1;
				if (data.transferMode) {
					auto physicalFile = ConvToNetwork(data.physicalFile);
					auto logicalFile = ConvToNetwork(data.logicalFile);
					len += 2 + physicalFile.size() + 2 + logicalFile.size();

					if (data.currentOffset != 0) {
						len += 8;
					}
					if (data.totalSize != -1) {
						len += 8;
					}
				}
			}
			unsigned char *buffer = new unsigned char[len];
			buffer[0] = USERCONTROL_GETLIST;
			buffer[1] = ((m_UsersList.size() / 256) / 256) & 0xff;
			buffer[2] = (m_UsersList.size() / 256) & 0xff;
			buffer[3] = m_UsersList.size() % 256;
			unsigned char *p = buffer + 4;
			for (iter = m_UsersList.begin(); iter != m_UsersList.end(); ++iter) {
				const t_connectiondata& data = iter->second;
				auto ip = ConvToNetwork(data.ip);
				auto user = ConvToNetwork(data.user);

				memcpy(p, &data.userid, 4);
				p += 4;
				*p++ = (ip.size() / 256) & 0xff;
				*p++ = ip.size() % 256;
				memcpy(p, ip.c_str(), ip.size());
				p += ip.size();

				memcpy(p, &data.port, 4);
				p += 4;

				*p++ = (user.size() / 256) & 0xff;
				*p++ = user.size() % 256;
				memcpy(p, user.c_str(), user.size());
				p += user.size();

				*p = data.transferMode;
				if (data.transferMode) {
					// Bit 5 and 6 indicate presence of currentOffset and totalSize.
					if (data.currentOffset != 0) {
						*p |= 0x20;
					}
					if (data.totalSize != -1) {
						*p |= 0x40;
					}
					p++;

					auto physicalFile = ConvToNetwork(data.physicalFile);
					*p++ = (physicalFile.size() / 256) & 0xff;
					*p++ = physicalFile.size() % 256;
					memcpy(p, physicalFile.c_str(), physicalFile.size());
					p += physicalFile.size();

					auto logicalFile = ConvToNetwork(data.logicalFile);
					*p++ = (logicalFile.size() / 256) & 0xff;
					*p++ = logicalFile.size() % 256;
					memcpy(p, logicalFile.c_str(), logicalFile.size());
					p += logicalFile.size();

					if (data.currentOffset != 0) {
						memcpy(p, &data.currentOffset, 8);
						p += 8;
					}
					if (data.totalSize != -1) {
						memcpy(p, &data.totalSize, 8);
						p += 8;
					}
				}
				else {
					p++;
				}
			}
			m_pAdminInterface->SendCommand(1, 3, buffer, len);
			delete [] buffer;
		}
		else if (*pData == USERCONTROL_KICK || *pData == USERCONTROL_BAN) {
			if (nDataLength != 5)
				pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length")+1);
			else {
				int nUserID;
				memcpy(&nUserID, pData+1, 4);

				std::map<int, t_connectiondata>::iterator iter = m_UsersList.find(nUserID);
				if (iter!=m_UsersList.end()) {
					if (*pData == USERCONTROL_BAN) {
						// Get the list of IP filter rules.
						CStdString ips = m_pOptions->GetOption(OPTION_IPFILTER_DISALLOWED);
						if (ips != _T(""))
							ips += _T(" ");

						int pos = ips.Find(' ');
						while (pos != -1) {
							CStdString blockedIP = ips.Left(pos);
							ips = ips.Mid(pos + 1);
							pos = ips.Find(' ');

							if (MatchesFilter(blockedIP, iter->second.ip))
								break;
						}
						if (pos == -1) {
							ips = m_pOptions->GetOption(OPTION_IPFILTER_DISALLOWED);
							if (ips != _T(""))
								ips += _T(" ");
							ips += iter->second.ip;
							m_pOptions->SetOption(OPTION_IPFILTER_DISALLOWED, ips);
						}
					}
					t_controlmessage *msg = new t_controlmessage;
					msg->command = USERCONTROL_KICK;
					msg->socketid = nUserID;
					iter->second.pThread->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_CONTROL, (LPARAM)msg);
					char buffer[2];
					buffer[0] = *pData;
					buffer[1] = 0;
					pAdminSocket->SendCommand(1, 3, &buffer, 2);
				}
				else {
					char buffer[2];
					buffer[0] = USERCONTROL_KICK;
					buffer[1] = 1;
					pAdminSocket->SendCommand(1, 3, &buffer, 2);
				}
			}
		}
		else {
			pAdminSocket->SendCommand(1, 1, "\001Protocol error: Invalid data", strlen("\001Protocol error: Invalid data") + 1);
		}
		break;
	case 5:
		if (!nDataLength) {
			unsigned char *pBuffer = NULL;
			DWORD nBufferLength = 0;
			if (m_pOptions && m_pOptions->GetAsCommand(&pBuffer, &nBufferLength)) {
				pAdminSocket->SendCommand(1, 5, pBuffer, nBufferLength);
				delete [] pBuffer;
			}
		}
		else if (m_pOptions) {
			if (nDataLength < 2) {
				pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length") + 1);
			}
			else {
				CStdString const listenPorts = m_pOptions->GetOption(OPTION_SERVERPORT);
				CStdString const listenPortsSsl = m_pOptions->GetOption(OPTION_TLSPORTS);
				bool const enableSsl = m_pOptions->GetOptionVal(OPTION_ENABLETLS) != 0;
				CStdString const ipBindings = m_pOptions->GetOption(OPTION_IPBINDINGS);
				int const nAdminListenPort = (int)m_pOptions->GetOptionVal(OPTION_ADMINPORT);
				CStdString const adminIpBindings = m_pOptions->GetOption(OPTION_ADMINIPBINDINGS);

				CStdString peerIP;
				UINT port = 0;
				bool bLocal = false;
				if (!pAdminSocket->GetPeerName(peerIP, port)) {
					return FALSE;
				}
				else {
					bLocal = IsLocalhost(peerIP);
				}

				if (!m_pOptions->ParseOptionsCommand(pData, nDataLength, bLocal)) {
					pAdminSocket->SendCommand(1, 1, "\001Protocol error: Invalid data, could not import settings.", strlen("\001Protocol error: Invalid data, could not import settings.")+1);
					char buffer = 1;
					pAdminSocket->SendCommand(1, 5, &buffer, 1);
					break;
				}

				char buffer = 0;
				pAdminSocket->SendCommand(1, 5, &buffer, 1);

				unsigned int threadnum = (int)m_pOptions->GetOptionVal(OPTION_THREADNUM);
				if (m_nServerState & STATE_ONLINE) {
					if (threadnum > m_ThreadArray.size()) {
						while (threadnum > m_ThreadArray.size()) {
							int index = GetNextThreadNotificationID();
							CServerThread *pThread = new CServerThread(WM_FILEZILLA_SERVERMSG + index);
							m_ThreadNotificationIDs[index] = pThread;
							if (pThread->Create(THREAD_PRIORITY_NORMAL, CREATE_SUSPENDED)) {
								pThread->ResumeThread();
								m_ThreadArray.push_back(pThread);
							}
						}
						CStdString str;
						str.Format(_T("Number of threads increased to %d."), threadnum);
						ShowStatus(str, 0);
					}
					else if (threadnum < m_ThreadArray.size()) {
						CStdString str;
						str.Format(_T("Decreasing number of threads to %d."), threadnum);
						ShowStatus(str, 0);
						unsigned int i = 0;
						std::vector<CServerThread *> newList;
						for (auto iter = m_ThreadArray.begin(); iter != m_ThreadArray.end(); iter++, i++) {
							if (i >= threadnum) {
								(*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 2);
								m_ClosedThreads.push_back(*iter);
							}
							else
								newList.push_back(*iter);
						}
						m_ThreadArray.swap(newList);
					}
				}
				if (listenPorts != m_pOptions->GetOption(OPTION_SERVERPORT) ||
					enableSsl != (m_pOptions->GetOptionVal(OPTION_ENABLETLS) != 0) ||
					(m_pOptions->GetOptionVal(OPTION_ENABLETLS) && listenPortsSsl != m_pOptions->GetOption(OPTION_TLSPORTS)) ||
					ipBindings != m_pOptions->GetOption(OPTION_IPBINDINGS))
				{
					if (!m_ListenSocketList.empty()) {
						ShowStatus(_T("Closing all listening sockets"), 0);
						for (std::list<CListenSocket*>::iterator listIter = m_ListenSocketList.begin(); listIter != m_ListenSocketList.end(); ++listIter) {
							(*listIter)->Close();
							delete *listIter;
						}
						m_ListenSocketList.clear();

						if (!CreateListenSocket()) {
							ShowStatus(_T("Failed to create a listen socket on any of the specified ports. Server is not online!"), 1);
							m_nServerState &= ~STATE_ONLINE;
						}
						else {
							ShowStatus(_T("Listen socket port changed"), 0);
							if (!(m_nServerState & STATE_MASK_GOOFFLINE))
								m_nServerState |= STATE_ONLINE;
						}
						SendState();
					}
				}
				if (nAdminListenPort != m_pOptions->GetOptionVal(OPTION_ADMINPORT) || adminIpBindings != m_pOptions->GetOption(OPTION_ADMINIPBINDINGS)) {
					CreateAdminListenSocket();
				}

				VerifyTlsSettings(pAdminSocket);
				VerifyPassiveModeSettings(pAdminSocket);
			}
		}
		break;
	case 6:
		if (!nDataLength) {
			unsigned char *pBuffer = NULL;
			DWORD nBufferLength = 0;
			CPermissions permissions = CPermissions(std::function<void()>());
			permissions.GetAsCommand(&pBuffer, &nBufferLength);
			pAdminSocket->SendCommand(1, 6, pBuffer, nBufferLength);
			delete [] pBuffer;
		}
		else {
			if (nDataLength < 2)
				pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length")+1);
			else {
				CPermissions permissions = CPermissions(std::function<void()>());
				if (!permissions.ParseUsersCommand(pData, nDataLength)) {
					pAdminSocket->SendCommand(1, 1, "\001Protocol error: Invalid data, could not import account settings.", strlen("\001Protocol error: Invalid data, could not import account settings.")+1);
					char buffer = 1;
					pAdminSocket->SendCommand(1, 6, &buffer, 1);
					break;
				}
				char buffer = 0;
				pAdminSocket->SendCommand(1, 6, &buffer, 1);
			}
		}
		break;
	case 8:
		pAdminSocket->SendCommand(1, 8, NULL, 0);
		break;
	default:
		{
			CStdStringA str;
			str.Format("\001Protocol error: Unknown command (%d).", nID);
			pAdminSocket->SendCommand(1, 1, str.c_str(), str.GetLength());
		}
		break;
	}

	return TRUE;
}
示例#9
0
BOOL CServer::CreateAdminListenSocket()
{
	if (!m_pOptions)
		return FALSE;

	m_AdminListenSocketList.clear();

	CStdString ipBindings = m_pOptions->GetOption(OPTION_ADMINIPBINDINGS);
	int nAdminPort = (int)m_pOptions->GetOptionVal(OPTION_ADMINPORT);

	if (!DoCreateAdminListenSocket(nAdminPort, (ipBindings != _T("*")) ? _T("127.0.0.1") : NULL, AF_INET)) {
		int p = DoCreateAdminListenSocket(0, _T("127.0.0.1"), AF_INET);
		if (!p) {
			CStdString str;
			str.Format(_T("Failed to create listen socket for admin interface on port %d for IPv4, the IPv4 admin interface has been disabled."), nAdminPort);
			ShowStatus(str, 1);
		}
		else {
			CStdString str;
			str.Format(_T("Failed to create listen socket for admin interface on port %d for IPv4, for this session the IPv4 admin interface is available on port %u."), p);
			ShowStatus(str, 1);
		}
	}

	if (!m_pOptions->GetOptionVal(OPTION_DISABLE_IPV6)) {
		if (!DoCreateAdminListenSocket(nAdminPort, (ipBindings != _T("*")) ? _T("::1") : NULL, AF_INET6)) {
			int p = DoCreateAdminListenSocket(0, _T("::1"), AF_INET6);
			if (!p) {
				CStdString str;
				str.Format(_T("Failed to create listen socket for admin interface on port %d for IPv6, the IPv6 admin interface has been disabled."), nAdminPort);
				ShowStatus(str, 1);
			}
			else {
				CStdString str;
				str.Format(_T("Failed to create listen socket for admin interface on port %d for IPv6, for this session the IPv6 admin interface is available on port %u."), p);
				ShowStatus(str, 1);
			}
		}
	}

	if (ipBindings != _T("*")) {
		if (ipBindings != _T(""))
			ipBindings += _T(" ");
		while (ipBindings != _T("")) {
			int pos = ipBindings.Find(' ');
			if (pos == -1)
				break;
			CStdString ip = ipBindings.Left(pos);
			ipBindings = ipBindings.Mid(pos+1);
			auto pAdminListenSocket = make_unique<CAdminListenSocket>(*m_pAdminInterface);

			int family;
			if (ip.Find(':') != -1)
				family = AF_INET6;
			else
				family = AF_INET;

			if (!pAdminListenSocket->Create(nAdminPort, SOCK_STREAM, FD_ACCEPT, ip, family) || !pAdminListenSocket->Listen(16)) {
				CStdString str;
				str.Format(_T("Failed to create listen socket for admin interface on port %d for address %s"), nAdminPort, ip);
				ShowStatus(str, 1);
			}
			else
				m_AdminListenSocketList.push_back(std::move(pAdminListenSocket));
		}
	}

	return !m_AdminListenSocketList.empty();
}
示例#10
0
void CGUIDialogVideoInfo::OnGetArt()
{
  map<string, string> currentArt;
  string type = ChooseArtType(*m_movieItem, currentArt);
  if (type.empty())
    return; // cancelled

  if (type == "fanart")
  { // TODO: this can be removed once these are unified.
    OnGetFanart();
    return;
  }

  CFileItemList items;

  // Current thumb
  if (m_movieItem->HasArt(type))
  {
    CFileItemPtr item(new CFileItem("thumb://Current", false));
    item->SetArt("thumb", m_movieItem->GetArt(type));
    item->SetLabel(g_localizeStrings.Get(13512));
    items.Add(item);
  }
  else if ((type == "poster" || type == "banner") && currentArt.find("thumb") != currentArt.end())
  { // add the 'thumb' type in
    CFileItemPtr item(new CFileItem("thumb://Thumb", false));
    item->SetArt("thumb", currentArt["thumb"]);
    item->SetLabel(g_localizeStrings.Get(13512));
    items.Add(item);
  }

  // Grab the thumbnails from the web
  vector<CStdString> thumbs;
  int season = (m_movieItem->GetVideoInfoTag()->m_type == "season") ? m_movieItem->GetVideoInfoTag()->m_iSeason : -1;
  m_movieItem->GetVideoInfoTag()->m_strPictureURL.GetThumbURLs(thumbs, type, season);

  for (unsigned int i = 0; i < thumbs.size(); ++i)
  {
    CStdString strItemPath;
    strItemPath.Format("thumb://Remote%i", i);
    CFileItemPtr item(new CFileItem(strItemPath, false));
    item->SetArt("thumb", thumbs[i]);
    item->SetIconImage("DefaultPicture.png");
    item->SetLabel(g_localizeStrings.Get(13513));

    // TODO: Do we need to clear the cached image?
    //    CTextureCache::Get().ClearCachedImage(thumb);
    items.Add(item);
  }

  CStdString localThumb = CVideoThumbLoader::GetLocalArt(*m_movieItem, type);
  if (!localThumb.empty())
  {
    CFileItemPtr item(new CFileItem("thumb://Local", false));
    item->SetArt("thumb", localThumb);
    item->SetLabel(g_localizeStrings.Get(13514));
    items.Add(item);
  }
  else
  { // no local thumb exists, so we are just using the IMDb thumb or cached thumb
    // which is probably the IMDb thumb.  These could be wrong, so allow the user
    // to delete the incorrect thumb
    CFileItemPtr item(new CFileItem("thumb://None", false));
    item->SetIconImage("DefaultVideo.png");
    item->SetLabel(g_localizeStrings.Get(13515));
    items.Add(item);
  }

  CStdString result;
  VECSOURCES sources(g_settings.m_videoSources);
  g_mediaManager.GetLocalDrives(sources);
  if (!CGUIDialogFileBrowser::ShowAndGetImage(items, sources, g_localizeStrings.Get(13511), result))
    return;   // user cancelled

  if (result == "thumb://Current")
    return;   // user chose the one they have

  CStdString newThumb;
  if (result.Left(14) == "thumb://Remote")
  {
    int number = atoi(result.Mid(14));
    newThumb = thumbs[number];
  }
  else if (result == "thumb://Thumb")
    newThumb = currentArt["thumb"];
  else if (result == "thumb://Local")
    newThumb = localThumb;
  else if (CFile::Exists(result))
    newThumb = result;
  else // none
    newThumb = "-"; // force local thumbs to be ignored

  // update thumb in the database
  CVideoDatabase db;
  if (db.Open())
  {
    db.SetArtForItem(m_movieItem->GetVideoInfoTag()->m_iDbId, m_movieItem->GetVideoInfoTag()->m_type, type, newThumb);
    db.Close();
  }
  CUtil::DeleteVideoDatabaseDirectoryCache(); // to get them new thumbs to show
  m_movieItem->SetArt(type, newThumb);
  if (m_movieItem->HasProperty("set_folder_thumb"))
  { // have a folder thumb to set as well
    VIDEO::CVideoInfoScanner::ApplyThumbToFolder(m_movieItem->GetProperty("set_folder_thumb").asString(), newThumb);
  }
  m_hasUpdatedThumb = true;

  // Update our screen
  Update();
}
bool PVRIptvData::LoadPlayList(void) 
{
  if (m_strM3uUrl.IsEmpty())
  {
    XBMC->Log(LOG_NOTICE, "Playlist file path is not configured. Channels not loaded.");
    return false;
  }

  CStdString strPlaylistContent;
  if (!GetCachedFileContents(M3U_FILE_NAME, m_strM3uUrl, strPlaylistContent, g_bCacheM3U))
  {
    XBMC->Log(LOG_ERROR, "Unable to load playlist file '%s':  file is missing or empty.", m_strM3uUrl.c_str());
    return false;
  }

  std::stringstream stream(strPlaylistContent);

  /* load channels */
  bool bFirst = true;

  int iChannelIndex     = 0;
  int iUniqueGroupId    = 0;
  int iCurrentGroupId   = 0;
  int iChannelNum       = g_iStartNumber;
  int iEPGTimeShift     = 0;

  PVRIptvChannel tmpChannel;
  tmpChannel.strTvgId       = "";
  tmpChannel.strChannelName = "";
  tmpChannel.strTvgName     = "";
  tmpChannel.strTvgLogo     = "";
  tmpChannel.iTvgShift      = 0;

  char szLine[1024];
  while(stream.getline(szLine, 1024)) 
  {
  
    CStdString strLine = "";
    strLine.append(szLine);
    strLine.TrimRight(" \t\r\n");
    strLine.TrimLeft(" \t");

    if (strLine.IsEmpty())
    {
      continue;
    }

    if (bFirst) 
    {
      bFirst = false;
      if (strLine.Left(3) == "\xEF\xBB\xBF")
      {
        strLine.Delete(0, 3);
      }
      if (strLine.Left((int)strlen(M3U_START_MARKER)) == M3U_START_MARKER) 
      {
        double fTvgShift = atof(ReadMarkerValue(strLine, TVG_INFO_SHIFT_MARKER));
        iEPGTimeShift = (int) (fTvgShift * 3600.0);
        continue;
      }
      else
      {
        break;
      }
    }

    if (strLine.Left((int)strlen(M3U_INFO_MARKER)) == M3U_INFO_MARKER) 
    {
      bool        bRadio       = false;
      double      fTvgShift    = 0;
      CStdString  strChnlName  = "";
      CStdString  strTvgId     = "";
      CStdString  strTvgName   = "";
      CStdString  strTvgLogo   = "";
      CStdString  strGroupName = "";
      CStdString  strRadio     = "";

      // parse line
      int iColon = (int)strLine.Find(':');
      int iComma = (int)strLine.ReverseFind(',');
      if (iColon >= 0 && iComma >= 0 && iComma > iColon) 
      {
        // parse name
        iComma++;
        strChnlName = strLine.Right((int)strLine.size() - iComma).Trim();
        tmpChannel.strChannelName = XBMC->UnknownToUTF8(strChnlName);

        // parse info
        CStdString strInfoLine = strLine.Mid(++iColon, --iComma - iColon);

        strTvgId      = ReadMarkerValue(strInfoLine, TVG_INFO_ID_MARKER);
        strTvgName    = ReadMarkerValue(strInfoLine, TVG_INFO_NAME_MARKER);
        strTvgLogo    = ReadMarkerValue(strInfoLine, TVG_INFO_LOGO_MARKER);
        strGroupName  = ReadMarkerValue(strInfoLine, GROUP_NAME_MARKER);
        strRadio      = ReadMarkerValue(strInfoLine, RADIO_MARKER);
        fTvgShift     = atof(ReadMarkerValue(strInfoLine, TVG_INFO_SHIFT_MARKER));

        if (strTvgId.IsEmpty())
        {
          char buff[255];
          sprintf(buff, "%d", atoi(strInfoLine));
          strTvgId.append(buff);
        }
        if (strTvgLogo.IsEmpty())
        {
          strTvgLogo = strChnlName;
        }

        bRadio                = !strRadio.CompareNoCase("true");
        tmpChannel.strTvgId   = strTvgId;
        tmpChannel.strTvgName = XBMC->UnknownToUTF8(strTvgName);
        tmpChannel.strTvgLogo = XBMC->UnknownToUTF8(strTvgLogo);
        tmpChannel.iTvgShift  = (int)(fTvgShift * 3600.0);
        tmpChannel.bRadio     = bRadio;

        if (tmpChannel.iTvgShift == 0 && iEPGTimeShift != 0)
        {
          tmpChannel.iTvgShift = iEPGTimeShift;
        }

        if (!strGroupName.IsEmpty())
        {
          strGroupName = XBMC->UnknownToUTF8(strGroupName);

          PVRIptvChannelGroup * pGroup;
          if ((pGroup = FindGroup(strGroupName)) == NULL)
          {
            PVRIptvChannelGroup group;
            group.strGroupName = strGroupName;
            group.iGroupId = ++iUniqueGroupId;
            group.bRadio = bRadio;

            m_groups.push_back(group);
            iCurrentGroupId = iUniqueGroupId;
          }
          else
          {
            iCurrentGroupId = pGroup->iGroupId;
          }
        }
      }
    } 
    else if (strLine[0] != '#')
    {
      PVRIptvChannel channel;
      channel.iUniqueId         = GetChannelId(tmpChannel.strChannelName.c_str(), strLine);
      channel.iChannelNumber    = iChannelNum++;
      channel.strTvgId          = tmpChannel.strTvgId;
      channel.strChannelName    = tmpChannel.strChannelName;
      channel.strTvgName        = tmpChannel.strTvgName;
      channel.strTvgLogo        = tmpChannel.strTvgLogo;
      channel.iTvgShift         = tmpChannel.iTvgShift;
      channel.bRadio            = tmpChannel.bRadio;
      channel.strStreamURL      = strLine;
      channel.iEncryptionSystem = 0;

      if (iCurrentGroupId > 0) 
      {
        channel.bRadio = m_groups.at(iCurrentGroupId - 1).bRadio;
        m_groups.at(iCurrentGroupId - 1).members.push_back(iChannelIndex);
      }

      m_channels.push_back(channel);
      iChannelIndex++;

      tmpChannel.strTvgId       = "";
      tmpChannel.strChannelName = "";
      tmpChannel.strTvgName     = "";
      tmpChannel.strTvgLogo     = "";
      tmpChannel.iTvgShift      = 0;
      tmpChannel.bRadio         = false;
    }
  }
  
  stream.clear();

  if (m_channels.size() == 0)
  {
    XBMC->Log(LOG_ERROR, "Unable to load channels from file '%s':  file is corrupted.", m_strM3uUrl.c_str());
    return false;
  }

  ApplyChannelsLogos();

  XBMC->Log(LOG_NOTICE, "Loaded %d channels.", m_channels.size());
  return true;
}
示例#12
0
文件: iputils.cpp 项目: alioxp/vc
CStdString GetIPV6ShortForm(const CStdString& ip)
{
	// This could be optimized a lot.

	// First get the long form in a well-known format
	CStdString l = GetIPV6LongForm(ip);
	if (l.IsEmpty())
		return CStdString();

	LPCTSTR p = l;

	TCHAR outbuf[42];
	*outbuf = ':';
	TCHAR* out = outbuf + 1;

	bool segmentStart = true;
	bool readLeadingZero = false;
	while (*p)
	{
		switch (*p)
		{
		case ':':
			if (readLeadingZero)
				*(out++) = '0';
			*out++ = ':';
			readLeadingZero = false;
			segmentStart = true;
			break;
		case '0':
			if (segmentStart)
				readLeadingZero = true;
			else
			{
				*out++ = '0';
				readLeadingZero = false;
			}
			break;
		default:
			readLeadingZero = false;
			segmentStart = false;
			*out++ = *p;
			break;
		}

		++p;
	}
	*(out++) = ':';
	*out = 0;

	// Replace longest run of consecutive zeroes
	CStdString shortIp(outbuf);

	CStdString s = _T(":0:0:0:0:0:0:0:0:");
	while (s.GetLength() > 2)
	{
		int pos = shortIp.Find(s);
		if (pos != -1)
		{
			shortIp = shortIp.Left( pos + 1 ) + shortIp.Mid(pos + s.GetLength() -1);
			break;
		}

		s = s.Mid(2);
	}
	shortIp.Replace(_T(":::"), _T("::"));
	if (shortIp[0] == ':' && shortIp[1] != ':')
		shortIp = shortIp.Mid(1);
	if (shortIp.GetLength() >= 2 && shortIp[shortIp.GetLength()-1] == ':' && shortIp[shortIp.GetLength()-2] != ':')
		shortIp = shortIp.Left(shortIp.GetLength()-1);

	return shortIp;
}
示例#13
0
文件: iputils.cpp 项目: alioxp/vc
bool IsRoutableAddress(const CStdString& address)
{
	if (address.Find(_T(":")) != -1)
	{
		CStdString long_address = GetIPV6LongForm(address);
		if (long_address.IsEmpty())
			return false;
		if (long_address[0] == '0')
		{
			// ::/128
			if (long_address == _T("0000:0000:0000:0000:0000:0000:0000:0000"))
				return false;
			// ::1/128
			if (long_address == _T("0000:0000:0000:0000:0000:0000:0000:0001"))
				return false;

			if (long_address.Left(30) == _T("0000:0000:0000:0000:0000:ffff:"))
			{
				// IPv4 mapped
				CStdString ipv4;
				ipv4.Format(_T("%d.%d.%d.%d"),
						DigitHexToDecNum(long_address[30]) * 16 + DigitHexToDecNum(long_address[31]),
						DigitHexToDecNum(long_address[32]) * 16 + DigitHexToDecNum(long_address[33]),
						DigitHexToDecNum(long_address[35]) * 16 + DigitHexToDecNum(long_address[36]),
						DigitHexToDecNum(long_address[37]) * 16 + DigitHexToDecNum(long_address[38]));
				return IsRoutableAddress(ipv4);
			}

			return true;
		}
		if (long_address[0] == 'f')
		{
			if (long_address[1] == 'e')
			{
				// fe80::/10 (link local)
				const TCHAR& c = long_address[2];
				int v;
				if (c >= 'a')
					v = c - 'a' + 10;
				else
					v = c - '0';
				if ((v & 0xc) == 0x8)
					return false;

				return true;
			}
			else if (long_address[1] == 'c' || long_address[1] == 'd')
			{
				// fc00::/7 (site local)
				return false;
			}
		}

		return true;
	}
	else
	{
		// Assumes address is already a valid IP address
		if (address.Left(3) == _T("127") ||
			address.Left(3) == _T("10.") ||
			address.Left(7) == _T("192.168") ||
			address.Left(7) == _T("169.254"))
			return false;

		if (address.Left(3) == _T("172"))
		{
			CStdString middle = address.Mid(4);
			int pos = address.Find(_T("."));
			if (pos == -1)
				return false;
			int part = _ttoi(middle.Left(pos));

			if (part >= 16 && part <= 31)
				return false;
		}

		return true;
	}
}
示例#14
0
文件: iputils.cpp 项目: alioxp/vc
CStdString GetIPV6LongForm(CStdString short_address)
{
	if (short_address[0] == '[')
	{
		if (short_address[short_address.GetLength() - 1] != ']')
			return _T("");
		short_address = short_address.Mid(1, short_address.GetLength() - 2);
	}
	short_address.MakeLower();

	TCHAR buffer[40] = { '0', '0', '0', '0', ':',
						 '0', '0', '0', '0', ':',
						 '0', '0', '0', '0', ':',
						 '0', '0', '0', '0', ':',
						 '0', '0', '0', '0', ':',
						 '0', '0', '0', '0', ':',
						 '0', '0', '0', '0', ':',
						 '0', '0', '0', '0', 0
					   };
	TCHAR* out = buffer;

	const unsigned int len = short_address.GetLength();
	if (len > 39)
		return _T("");

	// First part, before possible ::
	unsigned int i = 0;
	unsigned int grouplength = 0;
	for (i = 0; i < len + 1; i++)
	{
		const TCHAR& c = short_address[i];
		if (c == ':' || !c)
		{
			if (!grouplength)
			{
				// Empty group length, not valid
				if (!c || short_address[i + 1] != ':')
					return _T("");
				i++;
				break;
			}

			out += 4 - grouplength;
			for (unsigned int j = grouplength; j > 0; j--)
				*out++ = short_address[i - j];
			// End of string...
			if (!c)
			{
				if (!*out)
					// ...on time
					return buffer;
				else
					// ...premature
					return _T("");
			}
			else if (!*out)
			{
				// Too long
				return _T("");
			}

			out++;

			grouplength = 0;
			if (short_address[i + 1] == ':')
			{
				i++;
				break;
			}
			continue;
		}
		else if ((c < '0' || c > '9') &&
				 (c < 'a' || c > 'f'))
		{
			// Invalid character
			return _T("");
		}
		// Too long group
		if (++grouplength > 4)
			return _T("");
	}

	// Second half after ::

	TCHAR* end_first = out;
	out = &buffer[38];
	unsigned int stop = i;
	for (i = len - 1; i > stop; i--)
	{
		if (out < end_first)
		{
			// Too long
			return _T("");
		}

		const TCHAR& c = short_address[i];
		if (c == ':')
		{
			if (!grouplength)
			{
				// Empty group length, not valid
				return _T("");
			}

			out -= 5 - grouplength;

			grouplength = 0;
			continue;
		}
		else if ((c < '0' || c > '9') &&
				 (c < 'a' || c > 'f'))
		{
			// Invalid character
			return _T("");
		}
		// Too long group
		if (++grouplength > 4)
			return _T("");
		*out-- = c;
	}
	if (!grouplength && stop + 1 < len) {
		// Empty group length, not valid
		return _T("");
	}
	out -= 5 - grouplength;
	out += 2;

	int diff = out - end_first;
	if (diff < 0 || diff % 5)
		return _T("");

	return buffer;
}
示例#15
0
void CGUIInfoLabel::Parse(const CStdString &label, int context)
{
  m_info.clear();
  // Step 1: Replace all $LOCALIZE[number] with the real string
  CStdString work = ReplaceLocalize(label);
  // Step 2: Replace all $ADDON[id number] with the real string
  work = ReplaceAddonStrings(work);
  // Step 3: Find all $INFO[info,prefix,postfix] blocks
  EINFOFORMAT format;
  do
  {
    format = NONE;
    int pos1 = work.size();
    int pos2;
    int len = 0;
    for (size_t i = 0; i < sizeof(infoformatmap) / sizeof(infoformat); i++)
    {
      pos2 = work.Find(infoformatmap[i].str);
      if (pos2 != (int)string::npos && pos2 < pos1)
      {
        pos1 = pos2;
        len = strlen(infoformatmap[i].str);
        format = infoformatmap[i].val;
      }
    }

    if (format != NONE)
    {
      if (pos1 > 0)
        m_info.push_back(CInfoPortion(0, work.Left(pos1), ""));

      pos2 = StringUtils::FindEndBracket(work, '[', ']', pos1 + len);
      if (pos2 > pos1)
      {
        // decipher the block
        CStdString block = work.Mid(pos1 + len, pos2 - pos1 - len);
        CStdStringArray params;
        StringUtils::SplitString(block, ",", params);
        int info;
        if (format == FORMATVAR)
        {
          info = g_infoManager.TranslateSkinVariableString(params[0], context);
          if (info == 0)
            info = g_infoManager.RegisterSkinVariableString(g_SkinInfo->CreateSkinVariable(params[0], context));
          if (info == 0) // skinner didn't define this conditional label!
            CLog::Log(LOGWARNING, "Label Formating: $VAR[%s] is not defined", params[0].c_str());
        }
        else
          info = g_infoManager.TranslateString(params[0]);
        CStdString prefix, postfix;
        if (params.size() > 1)
          prefix = params[1];
        if (params.size() > 2)
          postfix = params[2];
        m_info.push_back(CInfoPortion(info, prefix, postfix, format == FORMATESCINFO));
        // and delete it from our work string
        work = work.Mid(pos2 + 1);
      }
      else
      {
        CLog::Log(LOGERROR, "Error parsing label - missing ']' in \"%s\"", label.c_str());
        return;
      }
    }
  }
  while (format != NONE);

  if (!work.IsEmpty())
    m_info.push_back(CInfoPortion(0, work, ""));
}
示例#16
0
int CAirPlayServer::CTCPClient::ProcessRequest( CStdString& responseHeader,
                                                CStdString& responseBody,
                                                CStdString& reverseHeader,
                                                CStdString& reverseBody,
                                                CStdString& sessionId)
{
  CStdString method = m_httpParser->getMethod();
  CStdString uri = m_httpParser->getUri();
  CStdString queryString = m_httpParser->getQueryString();
  CStdString body = m_httpParser->getBody();
  CStdString contentType = m_httpParser->getValue("content-type");
  sessionId = m_httpParser->getValue("x-apple-session-id");
  CStdString authorization = m_httpParser->getValue("authorization");
  int status = AIRPLAY_STATUS_OK;
  bool needAuth = false;

  if (ServerInstance->m_usePassword && !m_bAuthenticated)
  {
    needAuth = true;
  }

  int startQs = uri.Find('?');
  if (startQs != -1)
  {
    uri = uri.Left(startQs);
  }

  // This is the socket which will be used for reverse HTTP
  // negotiate reverse HTTP via upgrade
  if (uri == "/reverse")
  {
    status = AIRPLAY_STATUS_SWITCHING_PROTOCOLS;
    responseHeader = "Upgrade: PTTH/1.0\r\nConnection: Upgrade\r\n";
  }

  // The rate command is used to play/pause media.
  // A value argument should be supplied which indicates media should be played or paused.
  // 0.000000 => pause
  // 1.000000 => play
  else if (uri == "/rate")
  {
      const char* found = strstr(queryString.c_str(), "value=");
      int rate = found ? (int)(atof(found + strlen("value=")) + 0.5f) : 0;

      if (needAuth && !checkAuthorization(authorization, method, uri))
      {
        status = AIRPLAY_STATUS_NEED_AUTH;
      }
      else if (rate == 0)
      {
        if (g_application.m_pPlayer && g_application.m_pPlayer->IsPlaying() && !g_application.m_pPlayer->IsPaused())
        {
          g_application.getApplicationMessenger().MediaPause();
        }
      }
      else
      {
        if (g_application.m_pPlayer && g_application.m_pPlayer->IsPlaying() && g_application.m_pPlayer->IsPaused())
        {
          g_application.getApplicationMessenger().MediaPause();
        }
      }
  }

  // Contains a header like format in the request body which should contain a
  // Content-Location and optionally a Start-Position
  else if (uri == "/play")
  {
    CStdString location;
    float position = 0.0;

    if (needAuth && !checkAuthorization(authorization, method, uri))
    {
      status = AIRPLAY_STATUS_NEED_AUTH;
    }
    else if (contentType == "application/x-apple-binary-plist")
    {

      if (m_pLibPlist->Load())
      {
        m_pLibPlist->EnableDelayedUnload(false);

        const char* bodyChr = m_httpParser->getBody();

        plist_t dict = NULL;
        m_pLibPlist->plist_from_bin(bodyChr, m_httpParser->getContentLength(), &dict);

        if (m_pLibPlist->plist_dict_get_size(dict))
        {
          plist_t tmpNode = m_pLibPlist->plist_dict_get_item(dict, "Start-Position");
          if (tmpNode)
          {
            double tmpDouble = 0;
            m_pLibPlist->plist_get_real_val(tmpNode, &tmpDouble);
            position = tmpDouble;
          }

          tmpNode = m_pLibPlist->plist_dict_get_item(dict, "Content-Location");
          if (tmpNode)
          {
            char *tmpStr = NULL;
            m_pLibPlist->plist_get_string_val(tmpNode, &tmpStr);
            location=tmpStr;
            free(tmpStr);
          }

          if (dict)
          {
            m_pLibPlist->plist_free(dict);
          }
        }
        else
        {
          CLog::Log(LOGERROR, "Error parsing plist");
        }
        m_pLibPlist->Unload();
      }
    }
    else
    {
      // Get URL to play
      int start = body.Find("Content-Location: ");
      if (start == -1)
        return AIRPLAY_STATUS_NOT_IMPLEMENTED;
      start += strlen("Content-Location: ");
      int end = body.Find('\n', start);
      location = body.Mid(start, end - start);

      start = body.Find("Start-Position");
      if (start != -1)
      {
        start += strlen("Start-Position: ");
        int end = body.Find('\n', start);
        CStdString positionStr = body.Mid(start, end - start);
        position = atof(positionStr.c_str());
      }
    }

    if (status != AIRPLAY_STATUS_NEED_AUTH)
    {
      CFileItem fileToPlay(location, false);
      fileToPlay.SetProperty("StartPercent", position*100.0f);
      g_application.getApplicationMessenger().MediaPlay(fileToPlay);
    }
  }

  // Used to perform seeking (POST request) and to retrieve current player position (GET request).
  else if (uri == "/scrub")
  {
    if (needAuth && !checkAuthorization(authorization, method, uri))
    {
      status = AIRPLAY_STATUS_NEED_AUTH;
    }
    else if (method == "GET")
    {
      if (g_application.m_pPlayer && g_application.m_pPlayer->GetTotalTime())
      {
        float position = ((float) g_application.m_pPlayer->GetTime()) / 1000;
        responseBody.Format("duration: %d\r\nposition: %f", g_application.m_pPlayer->GetTotalTime(), position);
      }
    }
    else
    {
      const char* found = strstr(queryString.c_str(), "position=");
      if (found && g_application.m_pPlayer)
      {
        __int64 position = (__int64) (atof(found + strlen("position=")) * 1000.0);
        g_application.m_pPlayer->SeekTime(position);
      }
    }
  }

  // Sent when media playback should be stopped
  else if (uri == "/stop")
  {
    if (needAuth && !checkAuthorization(authorization, method, uri))
    {
      status = AIRPLAY_STATUS_NEED_AUTH;
    }
    else
    {
      g_application.getApplicationMessenger().MediaStop();
    }
  }

  // RAW JPEG data is contained in the request body
  else if (uri == "/photo")
  {
    if (needAuth && !checkAuthorization(authorization, method, uri))
    {
      status = AIRPLAY_STATUS_NEED_AUTH;
    }
    else if (m_httpParser->getContentLength() > 0)
    {
      XFILE::CFile tmpFile;
      if (tmpFile.OpenForWrite("special://temp/airplay_photo.jpg", true))
      {
        int writtenBytes=0;
        writtenBytes = tmpFile.Write(m_httpParser->getBody(), m_httpParser->getContentLength());
        tmpFile.Close();

        if (writtenBytes > 0 && (unsigned int)writtenBytes == m_httpParser->getContentLength())
        {
          g_application.getApplicationMessenger().PictureShow("special://temp/airplay_photo.jpg");
        }
        else
        {
          CLog::Log(LOGERROR,"AirPlayServer: Error writing tmpFile.");
        }
      }
    }
  }

  else if (uri == "/playback-info")
  {
    float position = 0.0f;
    float duration = 0.0f;
    float cacheDuration = 0.0f;
    bool playing = false;

    if (needAuth && !checkAuthorization(authorization, method, uri))
    {
      status = AIRPLAY_STATUS_NEED_AUTH;
    }
    else if (g_application.m_pPlayer)
    {
      if (g_application.m_pPlayer->GetTotalTime())
      {
        position = ((float) g_application.m_pPlayer->GetTime()) / 1000;
        duration = (float) g_application.m_pPlayer->GetTotalTime();
        playing = g_application.m_pPlayer ? !g_application.m_pPlayer->IsPaused() : false;
        cacheDuration = (float) g_application.m_pPlayer->GetTotalTime() * g_application.GetCachePercentage()/100.0f;
      }

      responseBody.Format(PLAYBACK_INFO, duration, cacheDuration, position, (playing ? 1 : 0), duration);
      responseHeader = "Content-Type: text/x-apple-plist+xml\r\n";

      if (g_application.m_pPlayer->IsCaching())
      {
        ComposeReverseEvent(reverseHeader, reverseBody, sessionId, EVENT_LOADING);
      }
      else if (playing)
      {
        ComposeReverseEvent(reverseHeader, reverseBody, sessionId, EVENT_PLAYING);
      }
      else
      {
        ComposeReverseEvent(reverseHeader, reverseBody, sessionId, EVENT_PAUSED);
      }
    }
  }

  else if (uri == "/server-info")
  {
    responseBody.Format(SERVER_INFO, g_application.getNetwork().GetFirstConnectedInterface()->GetMacAddress());
    responseHeader = "Content-Type: text/x-apple-plist+xml\r\n";
  }

  else if (uri == "/slideshow-features")
  {
    // Ignore for now.
  }

  else if (uri == "/authorize")
  {
    // DRM, ignore for now.
  }

  else if (uri == "200") //response OK from the event reverse message
  {
    status = AIRPLAY_STATUS_NO_RESPONSE_NEEDED;
  }
  else
  {
    CLog::Log(LOGERROR, "AIRPLAY Server: unhandled request [%s]\n", uri.c_str());
    status = AIRPLAY_STATUS_NOT_IMPLEMENTED;
  }

  if (status == AIRPLAY_STATUS_NEED_AUTH)
  {
    ComposeAuthRequestAnswer(responseHeader, responseBody);
  }

  return status;
}
// Get Thumb from user choice.
// Options are:
// 1.  Current thumb
// 2.  IMDb thumb
// 3.  Local thumb
// 4.  No thumb (if no Local thumb is available)
void CGUIDialogVideoInfo::OnGetThumb()
{
  CFileItemList items;

  // Current thumb
  if (CFile::Exists(m_movieItem->GetThumbnailImage()))
  {
    CFileItemPtr item(new CFileItem("thumb://Current", false));
    item->SetThumbnailImage(m_movieItem->GetThumbnailImage());
    item->SetLabel(g_localizeStrings.Get(20016));
    items.Add(item);
  }

  // Grab the thumbnails from the web
  vector<CStdString> thumbs;
  m_movieItem->GetVideoInfoTag()->m_strPictureURL.GetThumbURLs(thumbs);

  for (unsigned int i = 0; i < thumbs.size(); ++i)
  {
    CStdString strItemPath;
    strItemPath.Format("thumb://Remote%i", i);
    CFileItemPtr item(new CFileItem(strItemPath, false));
    item->SetThumbnailImage(thumbs[i]);
    item->SetIconImage("DefaultPicture.png");
    item->SetLabel(g_localizeStrings.Get(20015));

    // TODO: Do we need to clear the cached image?
    //    CTextureCache::Get().ClearCachedImage(thumb);
    items.Add(item);
  }

  CStdString localThumb(m_movieItem->GetUserVideoThumb());
  if (CFile::Exists(localThumb))
  {
    CFileItemPtr item(new CFileItem("thumb://Local", false));
    item->SetThumbnailImage(localThumb);
    item->SetLabel(g_localizeStrings.Get(20017));
    items.Add(item);
  }
  else
  { // no local thumb exists, so we are just using the IMDb thumb or cached thumb
    // which is probably the IMDb thumb.  These could be wrong, so allow the user
    // to delete the incorrect thumb
    CFileItemPtr item(new CFileItem("thumb://None", false));
    item->SetIconImage("DefaultVideo.png");
    item->SetLabel(g_localizeStrings.Get(20018));
    items.Add(item);
  }

  CStdString result;
  VECSOURCES sources(g_settings.m_videoSources);
  g_mediaManager.GetLocalDrives(sources);
  if (!CGUIDialogFileBrowser::ShowAndGetImage(items, sources, g_localizeStrings.Get(20019), result))
    return;   // user cancelled

  if (result == "thumb://Current")
    return;   // user chose the one they have

  CStdString newThumb;
  if (result.Left(14) == "thumb://Remote")
  {
    int number = atoi(result.Mid(14));
    newThumb = thumbs[number];
  }
  else if (result == "thumb://Local")
    newThumb = localThumb;
  else if (CFile::Exists(result))
    newThumb = result;
  else // none
    newThumb = "-"; // force local thumbs to be ignored

  // update thumb in the database
  CVideoDatabase db;
  if (db.Open())
  {
    db.SetArtForItem(m_movieItem->GetVideoInfoTag()->m_iDbId, m_movieItem->GetVideoInfoTag()->m_type, "thumb", newThumb);
    db.Close();
  }

  CUtil::DeleteVideoDatabaseDirectoryCache(); // to get them new thumbs to show
  m_movieItem->SetThumbnailImage(newThumb);
  if (m_movieItem->HasProperty("set_folder_thumb"))
  { // have a folder thumb to set as well
    VIDEO::CVideoInfoScanner::ApplyThumbToFolder(m_movieItem->GetProperty("set_folder_thumb").asString(), newThumb);
  }
  m_hasUpdatedThumb = true;

  // Update our screen
  Update();
}
示例#18
0
bool PVRXinFanData::LoadXinFanData(void)
{
  TiXmlDocument xmlDoc;
  string strSettingsFile = GetSettingsFile();

  if (!xmlDoc.LoadFile(strSettingsFile))
  {
    XBMC->Log(LOG_ERROR, "invalid XinFan.TV data (no/invalid data file found at '%s')", strSettingsFile.c_str());
    return false;
  }

  TiXmlElement *pRootElement = xmlDoc.RootElement();
  if (strcmp(pRootElement->Value(), "xinfan") != 0)
  {
    XBMC->Log(LOG_ERROR, "invalid XinFan.TV data (no <xinfan> tag found)");
    return false;
  }

  /* load channels */
  int iUniqueChannelId = 0;
  TiXmlElement *pElement = pRootElement->FirstChildElement("channels");
  if (pElement)
  {
    TiXmlNode *pChannelNode = NULL;
    while ((pChannelNode = pElement->IterateChildren(pChannelNode)) != NULL)
    {
      CStdString strTmp;
      PVRXinFanChannel channel;
      channel.iUniqueId = ++iUniqueChannelId;

      /* channel name */
      if (!XMLUtils::GetString(pChannelNode, "name", strTmp))
        continue;
      channel.strChannelName = strTmp;

      /* radio/TV */
      XMLUtils::GetBoolean(pChannelNode, "radio", channel.bRadio);

      /* channel number */
      if (!XMLUtils::GetInt(pChannelNode, "number", channel.iChannelNumber))
        channel.iChannelNumber = iUniqueChannelId;

      /* sub channel number */
      if (!XMLUtils::GetInt(pChannelNode, "subnumber", channel.iSubChannelNumber))
        channel.iSubChannelNumber = 0;

      /* CAID */
      if (!XMLUtils::GetInt(pChannelNode, "encryption", channel.iEncryptionSystem))
        channel.iEncryptionSystem = 0;

      /* icon path */
      if (!XMLUtils::GetString(pChannelNode, "icon", strTmp))
        channel.strIconPath = m_strDefaultIcon;
      else
        channel.strIconPath = strTmp;

      /* stream url */
      if (!XMLUtils::GetString(pChannelNode, "stream", strTmp))
        channel.strStreamURL = m_strDefaultMovie;
      else
        channel.strStreamURL = strTmp;

      m_channels.push_back(channel);
    }
  }

  /* load channel groups */
  int iUniqueGroupId = 0;
  pElement = pRootElement->FirstChildElement("channelgroups");
  if (pElement)
  {
    TiXmlNode *pGroupNode = NULL;
    while ((pGroupNode = pElement->IterateChildren(pGroupNode)) != NULL)
    {
      CStdString strTmp;
      PVRXinFanChannelGroup group;
      group.iGroupId = ++iUniqueGroupId;

      /* group name */
      if (!XMLUtils::GetString(pGroupNode, "name", strTmp))
        continue;
      group.strGroupName = strTmp;

      /* radio/TV */
      XMLUtils::GetBoolean(pGroupNode, "radio", group.bRadio);
      
      /* sort position */
      XMLUtils::GetInt(pGroupNode, "position", group.iPosition);

      /* members */
      TiXmlNode* pMembers = pGroupNode->FirstChild("members");
      TiXmlNode *pMemberNode = NULL;
      while (pMembers != NULL && (pMemberNode = pMembers->IterateChildren(pMemberNode)) != NULL)
      {
        int iChannelId = atoi(pMemberNode->FirstChild()->Value());
        if (iChannelId > -1)
          group.members.push_back(iChannelId);
      }

      m_groups.push_back(group);
    }
  }

  /* load EPG entries */
  pElement = pRootElement->FirstChildElement("epg");
  if (pElement)
  {
    TiXmlNode *pEpgNode = NULL;
    while ((pEpgNode = pElement->IterateChildren(pEpgNode)) != NULL)
    {
      CStdString strTmp;
      int iTmp;
      PVRXinFanEpgEntry entry;

      /* broadcast id */
      if (!XMLUtils::GetInt(pEpgNode, "broadcastid", entry.iBroadcastId))
        continue;

      /* channel id */
      if (!XMLUtils::GetInt(pEpgNode, "channelid", iTmp))
        continue;
      PVRXinFanChannel &channel = m_channels.at(iTmp - 1);
      entry.iChannelId = channel.iUniqueId;

      /* title */
      if (!XMLUtils::GetString(pEpgNode, "title", strTmp))
        continue;
      entry.strTitle = strTmp;

      /* start */
      if (!XMLUtils::GetInt(pEpgNode, "start", iTmp))
        continue;
      entry.startTime = iTmp;

      /* end */
      if (!XMLUtils::GetInt(pEpgNode, "end", iTmp))
        continue;
      entry.endTime = iTmp;

      /* plot */
      if (XMLUtils::GetString(pEpgNode, "plot", strTmp))
        entry.strPlot = strTmp;

      /* plot outline */
      if (XMLUtils::GetString(pEpgNode, "plotoutline", strTmp))
        entry.strPlotOutline = strTmp;

      /* icon path */
      if (XMLUtils::GetString(pEpgNode, "icon", strTmp))
        entry.strIconPath = strTmp;

      /* genre type */
      XMLUtils::GetInt(pEpgNode, "genretype", entry.iGenreType);

      /* genre subtype */
      XMLUtils::GetInt(pEpgNode, "genresubtype", entry.iGenreSubType);

      XBMC->Log(LOG_DEBUG, "loaded EPG entry '%s' channel '%d' start '%d' end '%d'", entry.strTitle.c_str(), entry.iChannelId, entry.startTime, entry.endTime);
      channel.epg.push_back(entry);
    }
  }

  /* load recordings */
  iUniqueGroupId = 0; // reset unique ids
  pElement = pRootElement->FirstChildElement("recordings");
  if (pElement)
  {
    TiXmlNode *pRecordingNode = NULL;
    while ((pRecordingNode = pElement->IterateChildren(pRecordingNode)) != NULL)
    {
      CStdString strTmp;
      PVRXinFanRecording recording;

      /* recording title */
      if (!XMLUtils::GetString(pRecordingNode, "title", strTmp))
        continue;
      recording.strTitle = strTmp;

      /* recording url */
      if (!XMLUtils::GetString(pRecordingNode, "url", strTmp))
        recording.strStreamURL = m_strDefaultMovie;
      else
        recording.strStreamURL = strTmp;

      /* recording path */
      if (XMLUtils::GetString(pRecordingNode, "directory", strTmp))
        recording.strDirectory = strTmp;

      iUniqueGroupId++;
      strTmp.Format("%d", iUniqueGroupId);
      recording.strRecordingId = strTmp;

      /* channel name */
      if (XMLUtils::GetString(pRecordingNode, "channelname", strTmp))
        recording.strChannelName = strTmp;

      /* plot */
      if (XMLUtils::GetString(pRecordingNode, "plot", strTmp))
        recording.strPlot = strTmp;

      /* plot outline */
      if (XMLUtils::GetString(pRecordingNode, "plotoutline", strTmp))
        recording.strPlotOutline = strTmp;

      /* genre type */
      XMLUtils::GetInt(pRecordingNode, "genretype", recording.iGenreType);

      /* genre subtype */
      XMLUtils::GetInt(pRecordingNode, "genresubtype", recording.iGenreSubType);

      /* duration */
      XMLUtils::GetInt(pRecordingNode, "duration", recording.iDuration);

      /* recording time */
      if (XMLUtils::GetString(pRecordingNode, "time", strTmp))
      {
        time_t timeNow = time(NULL);
        struct tm* now = localtime(&timeNow);

        CStdString::size_type delim = strTmp.Find(':');
        if (delim != CStdString::npos)
        {
          now->tm_hour = (int)strtol(strTmp.Left(delim), NULL, 0);
          now->tm_min  = (int)strtol(strTmp.Mid(delim + 1), NULL, 0);
          now->tm_mday--; // yesterday

          recording.recordingTime = mktime(now);
        }
      }

      m_recordings.push_back(recording);
    }
  }

  /* load deleted recordings */
  pElement = pRootElement->FirstChildElement("recordingsdeleted");
  if (pElement)
  {
    TiXmlNode *pRecordingNode = NULL;
    while ((pRecordingNode = pElement->IterateChildren(pRecordingNode)) != NULL)
    {
      CStdString strTmp;
      PVRXinFanRecording recording;

      /* recording title */
      if (!XMLUtils::GetString(pRecordingNode, "title", strTmp))
        continue;
      recording.strTitle = strTmp;

      /* recording url */
      if (!XMLUtils::GetString(pRecordingNode, "url", strTmp))
        recording.strStreamURL = m_strDefaultMovie;
      else
        recording.strStreamURL = strTmp;

      /* recording path */
      if (XMLUtils::GetString(pRecordingNode, "directory", strTmp))
        recording.strDirectory = strTmp;

      iUniqueGroupId++;
      strTmp.Format("%d", iUniqueGroupId);
      recording.strRecordingId = strTmp;

      /* channel name */
      if (XMLUtils::GetString(pRecordingNode, "channelname", strTmp))
        recording.strChannelName = strTmp;

      /* plot */
      if (XMLUtils::GetString(pRecordingNode, "plot", strTmp))
        recording.strPlot = strTmp;

      /* plot outline */
      if (XMLUtils::GetString(pRecordingNode, "plotoutline", strTmp))
        recording.strPlotOutline = strTmp;

      /* genre type */
      XMLUtils::GetInt(pRecordingNode, "genretype", recording.iGenreType);

      /* genre subtype */
      XMLUtils::GetInt(pRecordingNode, "genresubtype", recording.iGenreSubType);

      /* duration */
      XMLUtils::GetInt(pRecordingNode, "duration", recording.iDuration);

      /* recording time */
      if (XMLUtils::GetString(pRecordingNode, "time", strTmp))
      {
        time_t timeNow = time(NULL);
        struct tm* now = localtime(&timeNow);

        CStdString::size_type delim = strTmp.Find(':');
        if (delim != CStdString::npos)
        {
          now->tm_hour = (int)strtol(strTmp.Left(delim), NULL, 0);
          now->tm_min  = (int)strtol(strTmp.Mid(delim + 1), NULL, 0);
          now->tm_mday--; // yesterday

          recording.recordingTime = mktime(now);
        }
      }

      m_recordingsDeleted.push_back(recording);
    }
  }

  /* load timers */
  pElement = pRootElement->FirstChildElement("timers");
  if (pElement)
  {
    TiXmlNode *pTimerNode = NULL;
    while ((pTimerNode = pElement->IterateChildren(pTimerNode)) != NULL)
    {
      CStdString strTmp;
      int iTmp;
      PVRXinFanTimer timer;
      time_t timeNow = time(NULL);
      struct tm* now = localtime(&timeNow);

      /* channel id */
      if (!XMLUtils::GetInt(pTimerNode, "channelid", iTmp))
        continue;
      PVRXinFanChannel &channel = m_channels.at(iTmp - 1);
      timer.iChannelId = channel.iUniqueId;

      /* state */
      if (XMLUtils::GetInt(pTimerNode, "state", iTmp))
        timer.state = (PVR_TIMER_STATE) iTmp;

      /* title */
      if (!XMLUtils::GetString(pTimerNode, "title", strTmp))
        continue;
      timer.strTitle = strTmp;

      /* summary */
      if (!XMLUtils::GetString(pTimerNode, "summary", strTmp))
        continue;
      timer.strSummary = strTmp;

      /* start time */
      if (XMLUtils::GetString(pTimerNode, "starttime", strTmp))
      {
        CStdString::size_type delim = strTmp.Find(':');
        if (delim != CStdString::npos)
        {
          now->tm_hour = (int)strtol(strTmp.Left(delim), NULL, 0);
          now->tm_min  = (int)strtol(strTmp.Mid(delim + 1), NULL, 0);

          timer.startTime = mktime(now);
        }
      }

      /* end time */
      if (XMLUtils::GetString(pTimerNode, "endtime", strTmp))
      {
        CStdString::size_type delim = strTmp.Find(':');
        if (delim != CStdString::npos)
        {
          now->tm_hour = (int)strtol(strTmp.Left(delim), NULL, 0);
          now->tm_min  = (int)strtol(strTmp.Mid(delim + 1), NULL, 0);

          timer.endTime = mktime(now);
        }
      }

      XBMC->Log(LOG_DEBUG, "loaded timer '%s' channel '%d' start '%d' end '%d'", timer.strTitle.c_str(), timer.iChannelId, timer.startTime, timer.endTime);
      m_timers.push_back(timer);
    }
  }

  return true;
}
示例#19
0
void SSortFileItem::ByStudioNoThe(CFileItemPtr &item)
{
  if (!item) return;
  CStdString studio = item->GetVideoInfoTag()->m_strStudio;
  item->SetSortLabel(studio.Mid(StartsWithToken(studio)));
}
示例#20
0
void CGUITextLayout::ParseText(const CStdString &text, vector<DWORD> &parsedText)
{
  if (!m_font)
    return;

  // run through the string, searching for:
  // [B] or [/B] -> toggle bold on and off
  // [I] or [/I] -> toggle italics on and off
  // [COLOR ffab007f] or [/COLOR] -> toggle color on and off
  // [CAPS <option>] or [/CAPS] -> toggle capatilization on and off

  DWORD currentStyle = m_font->GetStyle(); // start with the default font's style
  DWORD currentColor = 0;

  stack<DWORD> colorStack;
  colorStack.push(0);

  // these aren't independent, but that's probably not too much of an issue
  // eg [UPPERCASE]Glah[LOWERCASE]FReD[/LOWERCASE]Georeg[/UPPERCASE] will work (lower case >> upper case)
  // but [LOWERCASE]Glah[UPPERCASE]FReD[/UPPERCASE]Georeg[/LOWERCASE] won't
#define FONT_STYLE_UPPERCASE 4
#define FONT_STYLE_LOWERCASE 8

  int startPos = 0;
  size_t pos = text.Find('[');
  while (pos != CStdString::npos && pos + 1 < text.size())
  {
    DWORD newStyle = 0;
    DWORD newColor = currentColor;
    bool newLine = false;
    // have a [ - check if it's an ON or OFF switch
    bool on(true);
    int endPos = pos++; // finish of string
    if (text[pos] == '/')
    {
      on = false;
      pos++;
    }
    // check for each type
    if (text.Mid(pos,2) == "B]")
    { // bold - finish the current text block and assign the bold state
      newStyle = FONT_STYLE_BOLD;
      pos += 2;
    }
    else if (text.Mid(pos,2) == "I]")
    { // italics
      newStyle = FONT_STYLE_ITALICS;
      pos += 2;
    }
    else if (text.Mid(pos,10) == "UPPERCASE]")
    {
      newStyle = FONT_STYLE_UPPERCASE;
      pos += 10;
    }
    else if (text.Mid(pos,10) == "LOWERCASE]")
    {
      newStyle = FONT_STYLE_LOWERCASE;
      pos += 10;
    }
    else if (text.Mid(pos,3) == "CR]" && on)
    {
      newLine = true;
      pos += 3;
    }
    else if (text.Mid(pos,5) == "COLOR")
    { // color
      size_t finish = text.Find("]", pos + 5);
      if (on && finish != CStdString::npos)
      { // create new color
        newColor = m_colors.size();
        m_colors.push_back(g_colorManager.GetColor(text.Mid(pos + 5, finish - pos - 5)));
        colorStack.push(newColor);
      }
      else if (!on && finish == pos + 5)
      { // revert to previous color
        if (colorStack.size() > 1)
          colorStack.pop();
        newColor = colorStack.top();
      }
      pos = finish + 1;
    }

    if (newStyle || newColor != currentColor || newLine)
    { // we have a new style or a new color, so format up the previous segment
      CStdString subText = text.Mid(startPos, endPos - startPos);
      if (currentStyle & FONT_STYLE_UPPERCASE)
        subText.ToUpper();
      if (currentStyle & FONT_STYLE_LOWERCASE)
        subText.ToLower();
      AppendToUTF32(subText, ((currentStyle & 3) << 24) | (currentColor << 16), parsedText);
      if (newLine)
        parsedText.push_back(L'\n');

      // and switch to the new style
      startPos = pos;
      currentColor = newColor;
      if (on)
        currentStyle |= newStyle;
      else
        currentStyle &= ~newStyle;
    }
    pos = text.Find('[',pos);
  }
  // now grab the remainder of the string
  CStdString subText = text.Mid(startPos, text.GetLength() - startPos);
  if (currentStyle & FONT_STYLE_UPPERCASE)
    subText.ToUpper();
  if (currentStyle & FONT_STYLE_LOWERCASE)
    subText.ToLower();
  AppendToUTF32(subText, ((currentStyle & 3) << 24) | (currentColor << 16), parsedText);
}
示例#21
0
CStdString CNetworkInterfaceLinux::GetCurrentDefaultGateway(void)
{
   CStdString result = "";

#if defined(TARGET_DARWIN)
  FILE* pipe = popen("echo \"show State:/Network/Global/IPv4\" | scutil | grep Router", "r");
  if (pipe)
  {
    CStdString tmpStr;
    char buffer[256] = {'\0'};
    if (fread(buffer, sizeof(char), sizeof(buffer), pipe) > 0 && !ferror(pipe))
    {
      tmpStr = buffer;
      result = tmpStr.Mid(11);
    }
    else
    {
      CLog::Log(LOGWARNING, "Unable to determine gateway");
    }
    pclose(pipe);
  }
#elif defined(TARGET_FREEBSD)
   size_t needed;
   int mib[6];
   char *buf, *next, *lim;
   char line[16];
   struct rt_msghdr *rtm;
   struct sockaddr *sa;
   struct sockaddr_in *sockin;

   mib[0] = CTL_NET;
   mib[1] = PF_ROUTE;
   mib[2] = 0;
   mib[3] = 0;
   mib[4] = NET_RT_DUMP;
   mib[5] = 0;
   if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
      return result;

   if ((buf = (char *)malloc(needed)) == NULL)
      return result;

   if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
      free(buf);
      return result;
   }

   lim  = buf + needed;
   for (next = buf; next < lim; next += rtm->rtm_msglen) {
      rtm = (struct rt_msghdr *)next;
      sa = (struct sockaddr *)(rtm + 1);
      sa = (struct sockaddr *)(SA_SIZE(sa) + (char *)sa);	
      sockin = (struct sockaddr_in *)sa;
      if (inet_ntop(AF_INET, &sockin->sin_addr.s_addr,
         line, sizeof(line)) == NULL) {
            free(buf);
            return result;
	  }
	  result = line;
      break;
   }
   free(buf);
#else
   FILE* fp = fopen("/proc/net/route", "r");
   if (!fp)
   {
     // TBD: Error
     return result;
   }

   char* line = NULL;
   char iface[16];
   char dst[128];
   char gateway[128];
   size_t linel = 0;
   int n;
   int linenum = 0;
   while (getdelim(&line, &linel, '\n', fp) > 0)
   {
      // skip first two lines
      if (linenum++ < 1)
         continue;

      // search where the word begins
      n = sscanf(line,  "%16s %128s %128s",
         iface, dst, gateway);

      if (n < 3)
         continue;

      if (strcmp(iface, m_interfaceName.c_str()) == 0 &&
          strcmp(dst, "00000000") == 0 &&
          strcmp(gateway, "00000000") != 0)
      {
         unsigned char gatewayAddr[4];
         int len = CNetwork::ParseHex(gateway, gatewayAddr);
         if (len == 4)
         {
            struct in_addr in;
            in.s_addr = (gatewayAddr[0] << 24) | (gatewayAddr[1] << 16) |
                        (gatewayAddr[2] << 8) | (gatewayAddr[3]);
            result = inet_ntoa(in);
            break;
         }
      }
   }
   free(line);
   fclose(fp);
#endif

   return result;
}
void CDateTimeSpan::SetFromTimeString(const CStdString& time) // hh:mm
{
  int hour    = atoi(time.Mid(0,2).c_str());
  int minutes = atoi(time.Mid(3,2).c_str());
  SetDateTimeSpan(0,hour,minutes,0);
}
示例#23
0
////////////////////////////////////////////////////////////////////////////////////
// Function: Parse()
// Opens the .cue file for reading, and constructs the track database information
////////////////////////////////////////////////////////////////////////////////////
bool CCueDocument::Parse(const CStdString &strFile)
{
  if (!m_file.Open(strFile))
    return false;

  CStdString strLine;
  m_iTotalTracks = -1;
  CStdString strCurrentFile = "";
  bool bCurrentFileChanged = false;
  int time;

  // Run through the .CUE file and extract the tracks...
  while (true)
  {
    if (!ReadNextLine(strLine))
      break;
    if (strLine.Left(7) == "INDEX 0")
    {
      // find the end of the number section
      time = ExtractTimeFromIndex(strLine);
      if (time == -1)
      { // Error!
        OutputDebugString("Mangled Time in INDEX 0x tag in CUE file!\n");
        return false;
      }
      if (m_iTotalTracks > 0)  // Set the end time of the last track
        m_Track[m_iTotalTracks - 1].iEndTime = time;

      m_Track[m_iTotalTracks].iStartTime = time; // start time of the next track
    }
    else if (strLine.Left(5) == "TITLE")
    {
      if (m_iTotalTracks == -1) // No tracks yet
        ExtractQuoteInfo(strLine, m_strAlbum);
      else if (!ExtractQuoteInfo(strLine, m_Track[m_iTotalTracks].strTitle))
      {
        // lets manage tracks titles without quotes
        CStdString titleNoQuote = strLine.Mid(5);
        titleNoQuote.TrimLeft();
        if (!titleNoQuote.IsEmpty())
        {
          g_charsetConverter.stringCharsetToUtf8(titleNoQuote);
          m_Track[m_iTotalTracks].strTitle = titleNoQuote;
        }
      }
    }
    else if (strLine.Left(9) == "PERFORMER")
    {
      if (m_iTotalTracks == -1) // No tracks yet
        ExtractQuoteInfo(strLine, m_strArtist);
      else // New Artist for this track
        ExtractQuoteInfo(strLine, m_Track[m_iTotalTracks].strArtist);
    }
    else if (strLine.Left(5) == "TRACK")
    {
      int iTrackNumber = ExtractNumericInfo(strLine.c_str() + 5);
 
      m_iTotalTracks++;

      CCueTrack track;
      m_Track.push_back(track);
      m_Track[m_iTotalTracks].strFile = strCurrentFile;

      if (iTrackNumber > 0)
        m_Track[m_iTotalTracks].iTrackNumber = iTrackNumber;
      else
        m_Track[m_iTotalTracks].iTrackNumber = m_iTotalTracks + 1;

      bCurrentFileChanged = false;
    }
    else if (strLine.Left(4) == "FILE")
    {
      // already a file name? then the time computation will be changed
      if(strCurrentFile.size() > 0)
        bCurrentFileChanged = true;

      ExtractQuoteInfo(strLine, strCurrentFile);

      // Resolve absolute paths (if needed).
      if (strCurrentFile.length() > 0)
        ResolvePath(strCurrentFile, strFile);
    }
    else if (strLine.Left(25) == "REM REPLAYGAIN_ALBUM_GAIN")
      m_replayGainAlbumGain = (float)atof(strLine.Mid(26));
    else if (strLine.Left(25) == "REM REPLAYGAIN_ALBUM_PEAK")
      m_replayGainAlbumPeak = (float)atof(strLine.Mid(26));
    else if (strLine.Left(25) == "REM REPLAYGAIN_TRACK_GAIN" && m_iTotalTracks >= 0)
      m_Track[m_iTotalTracks].replayGainTrackGain = (float)atof(strLine.Mid(26));
    else if (strLine.Left(25) == "REM REPLAYGAIN_TRACK_PEAK" && m_iTotalTracks >= 0)
      m_Track[m_iTotalTracks].replayGainTrackPeak = (float)atof(strLine.Mid(26));
  }

  // reset track counter to 0, and fill in the last tracks end time
  m_iTrack = 0;
  if (m_iTotalTracks > 0)
    m_Track[m_iTotalTracks].iEndTime = 0;
  else
    OutputDebugString("No INDEX 01 tags in CUE file!\n");
  m_file.Close();
  if (m_iTotalTracks > 0)
  {
    m_iTotalTracks++;
  }
  return (m_iTotalTracks > 0);
}
示例#24
0
CLinuxTimezone::CLinuxTimezone() : m_IsDST(0)
{
   char* line = NULL;
   size_t linelen = 0;
   CStdString s;
   vector<CStdString> tokens;
   
   // Load timezones
   FILE* fp = fopen("/usr/share/zoneinfo/zone.tab", "r");
   if (fp)
   {
      CStdString countryCode;
      CStdString timezoneName;

      while (getdelim(&line, &linelen, '\n', fp) > 0)
      {
         tokens.clear();
         s = line;
         s.TrimLeft(" \t").TrimRight(" \n");

         if (s.length() == 0)
            continue;

         if (s[0] == '#')
            continue;

         CUtil::Tokenize(s, tokens, " \t");
         if (tokens.size() < 3)
            continue;

         countryCode = tokens[0];
         timezoneName = tokens[2];

         if (m_timezonesByCountryCode.count(countryCode) == 0)
         {
            vector<CStdString> timezones;
            timezones.push_back(timezoneName);
            m_timezonesByCountryCode[countryCode] = timezones;
         }
         else
         {
            vector<CStdString>& timezones = m_timezonesByCountryCode[countryCode];
            timezones.push_back(timezoneName);
         }

         m_countriesByTimezoneName[timezoneName] = countryCode;
      }
      fclose(fp);
   }

   if (line)
   {
     free(line);
     line = NULL;
     linelen = 0;
   }

   // Load countries
   fp = fopen("/usr/share/zoneinfo/iso3166.tab", "r");
   if (fp)
   {
      CStdString countryCode;
      CStdString countryName;

      while (getdelim(&line, &linelen, '\n', fp) > 0)
      {
         s = line;
         s.TrimLeft(" \t").TrimRight(" \n");

         if (s.length() == 0)
            continue;

         if (s[0] == '#')
            continue;

         // Search for the first non space from the 2nd character and on
         int i = 2;
         while (s[i] == ' ' || s[i] == '\t') i++;

         countryCode = s.Left(2);
         countryName = s.Mid(i);

         m_counties.push_back(countryName);
         m_countryByCode[countryCode] = countryName;
         m_countryByName[countryName] = countryCode;
      }
      sort(m_counties.begin(), m_counties.end(), sortstringbyname());
      fclose(fp);
   }
     free(line);
}
示例#25
0
CStdString CSpecialProtocol::TranslatePath(const CURL &url)
{
  // check for special-protocol, if not, return
  if (!url.GetProtocol().Equals("special"))
  {
#if defined(TARGET_POSIX) && defined(_DEBUG)
    CStdString path(url.Get());
    if (path.length() >= 2 && path[1] == ':')
    {
      CLog::Log(LOGWARNING, "Trying to access old style dir: %s\n", path.c_str());
     // printf("Trying to access old style dir: %s\n", path.c_str());
    }
#endif

    return url.Get();
  }

  CStdString FullFileName = url.GetFileName();

  CStdString translatedPath;
  CStdString FileName;
  CStdString RootDir;

  // Split up into the special://root and the rest of the filename
  int pos = FullFileName.Find('/');
  if (pos != -1 && pos > 1)
  {
    RootDir = FullFileName.Left(pos);

    if (pos < FullFileName.GetLength())
      FileName = FullFileName.Mid(pos + 1);
  }
  else
    RootDir = FullFileName;

  if (RootDir.Equals("subtitles"))
    translatedPath = URIUtils::AddFileToFolder(CSettings::Get().GetString("subtitles.custompath"), FileName);
  else if (RootDir.Equals("userdata"))
    translatedPath = URIUtils::AddFileToFolder(CProfilesManager::Get().GetUserDataFolder(), FileName);
  else if (RootDir.Equals("database"))
    translatedPath = URIUtils::AddFileToFolder(CProfilesManager::Get().GetDatabaseFolder(), FileName);
  else if (RootDir.Equals("thumbnails"))
    translatedPath = URIUtils::AddFileToFolder(CProfilesManager::Get().GetThumbnailsFolder(), FileName);
  else if (RootDir.Equals("recordings") || RootDir.Equals("cdrips"))
    translatedPath = URIUtils::AddFileToFolder(CSettings::Get().GetString("audiocds.recordingpath"), FileName);
  else if (RootDir.Equals("screenshots"))
    translatedPath = URIUtils::AddFileToFolder(CSettings::Get().GetString("debug.screenshotpath"), FileName);
  else if (RootDir.Equals("musicplaylists"))
    translatedPath = URIUtils::AddFileToFolder(CUtil::MusicPlaylistsLocation(), FileName);
  else if (RootDir.Equals("videoplaylists"))
    translatedPath = URIUtils::AddFileToFolder(CUtil::VideoPlaylistsLocation(), FileName);
  else if (RootDir.Equals("skin"))
    translatedPath = URIUtils::AddFileToFolder(g_graphicsContext.GetMediaDir(), FileName);
  else if (RootDir.Equals("logpath"))
    translatedPath = URIUtils::AddFileToFolder(g_advancedSettings.m_logFolder, FileName);


  // from here on, we have our "real" special paths
  else if (RootDir.Equals("xbmc") ||
           RootDir.Equals("xbmcbin") ||
           RootDir.Equals("home") ||
           RootDir.Equals("userhome") ||
           RootDir.Equals("temp") ||
           RootDir.Equals("profile") ||
           RootDir.Equals("masterprofile") ||
           RootDir.Equals("frameworks"))
  {
    CStdString basePath = GetPath(RootDir);
    if (!basePath.IsEmpty())
      translatedPath = URIUtils::AddFileToFolder(basePath, FileName);
    else
      translatedPath.clear();
  }

  // check if we need to recurse in
  if (URIUtils::IsSpecial(translatedPath))
  { // we need to recurse in, as there may be multiple translations required
    return TranslatePath(translatedPath);
  }

  // Validate the final path, just in case
  return CUtil::ValidatePath(translatedPath);
}
示例#26
0
//-------------------------------------------------------------------------------------------------------------------
void Xcddb::parseData(const char *buffer)
{
  //writeLog("parseData Start");

  std::map<CStdString, CStdString> keywords;
  std::list<CStdString> keywordsOrder; // remember order of keywords as it appears in data received from CDDB

  // Collect all the keywords and put them in map. 
  // Multiple occurrences of the same keyword indicate that 
  // the data contained on those lines should be concatenated
  char *line;
  const char trenner[3] = {'\n', '\r', '\0'};
  line = strtok((char*)buffer, trenner); // skip first line
  while ((line = strtok(0, trenner)))
  {
    // Lines that begin with # are comments, should be ignored
    if (line[0] != '#')
    {
      char *s = strstr(line, "=");
      if (s != NULL)
      {
        CStdString strKeyword(line, s - line);
        strKeyword.TrimRight(" ");

        CStdString strValue(s+1);
        strValue.Replace("\\n", "\n"); 
        strValue.Replace("\\t", "\t"); 
        strValue.Replace("\\\\", "\\"); 
        g_charsetConverter.unknownToUTF8(strValue);

        std::map<CStdString, CStdString>::const_iterator it = keywords.find(strKeyword);
        if (it != keywords.end())
          strValue = it->second + strValue; // keyword occured before, concatenate
        else
          keywordsOrder.push_back(strKeyword);

        keywords[strKeyword] = strValue;
      }
    }
  }

  // parse keywords 
  for (std::list<CStdString>::const_iterator it = keywordsOrder.begin(); it != keywordsOrder.end(); ++it)
  {
    CStdString strKeyword = *it;
    CStdString strValue = keywords[strKeyword];

    if (strKeyword == "DTITLE")
    {
      // DTITLE may contain artist and disc title, separated with " / ",
      // for example: DTITLE=Modern Talking / Album: Victory (The 11th Album)
      bool found = false;
      for (int i = 0; i < strValue.GetLength() - 2; i++)
      {
        if (strValue[i] == ' ' && strValue[i + 1] == '/' && strValue[i + 2] == ' ')
        {
          m_strDisk_artist = TrimToUTF8(strValue.Left(i));
          m_strDisk_title = TrimToUTF8(strValue.Mid(i+3));
          found = true;
          break;
        }
      }

      if (!found)
        m_strDisk_title = TrimToUTF8(strValue);
    }
    else if (strKeyword == "DYEAR")
      m_strYear = TrimToUTF8(strValue);
    else if (strKeyword== "DGENRE")
      m_strGenre = TrimToUTF8(strValue);
    else if (strKeyword.Left(6) == "TTITLE")
      addTitle(strKeyword + "=" + strValue);
    else if (strKeyword == "EXTD")
    {
      CStdString strExtd(strValue);

      if (m_strYear.IsEmpty())
      {
        // Extract Year from extended info
        // as a fallback
        int iPos = strExtd.Find("YEAR:");
        if (iPos > -1) // You never know if you really get UTF-8 strings from cddb
          g_charsetConverter.unknownToUTF8(strExtd.Mid(iPos + 6, 4), m_strYear);
      }

      if (m_strGenre.IsEmpty())
      {
        // Extract ID3 Genre
        // as a fallback
        int iPos = strExtd.Find("ID3G:");
        if (iPos > -1)
        {
          CStdString strGenre = strExtd.Mid(iPos + 5, 4);
          strGenre.TrimLeft(' ');
          if (StringUtils::IsNaturalNumber(strGenre))
          {
            CID3Tag tag;
            m_strGenre=tag.ParseMP3Genre(strGenre);
          }
        }
      }
    }
    else if (strKeyword.Left(4) == "EXTT")
      addExtended(strKeyword + "=" + strValue);
  }

  //writeLog("parseData Ende");
}
示例#27
0
文件: URL.cpp 项目: AdolphHuan/xbmc
void CURL::Parse(const CStdString& strURL1)
{
  Reset();
  // start by validating the path
  CStdString strURL = CUtil::ValidatePath(strURL1);

  // strURL can be one of the following:
  // format 1: protocol://[username:password]@hostname[:port]/directoryandfile
  // format 2: protocol://file
  // format 3: drive:directoryandfile
  //
  // first need 2 check if this is a protocol or just a normal drive & path
  if (!strURL.size()) return ;
  if (strURL.Equals("?", true)) return;

  // form is format 1 or 2
  // format 1: protocol://[domain;][username:password]@hostname[:port]/directoryandfile
  // format 2: protocol://file

  // decode protocol
  int iPos = strURL.Find("://");
  if (iPos < 0)
  {
    // This is an ugly hack that needs some work.
    // example: filename /foo/bar.zip/alice.rar/bob.avi
    // This should turn into zip://rar:///foo/bar.zip/alice.rar/bob.avi
    iPos = 0;
    bool is_apk = (strURL.Find(".apk/", iPos) > 0);
    while (1)
    {
      if (is_apk)
        iPos = strURL.Find(".apk/", iPos);
      else
        iPos = strURL.Find(".zip/", iPos);

      int extLen = 3;
      if (iPos < 0)
      {
        /* set filename and update extension*/
        SetFileName(strURL);
        return ;
      }
      iPos += extLen + 1;
      CStdString archiveName = strURL.Left(iPos);
      struct __stat64 s;
      if (XFILE::CFile::Stat(archiveName, &s) == 0)
      {
#ifdef _LINUX
        if (!S_ISDIR(s.st_mode))
#else
        if (!(s.st_mode & S_IFDIR))
#endif
        {
          Encode(archiveName);
          if (is_apk)
          {
            CURL c((CStdString)"apk" + "://" + archiveName + '/' + strURL.Right(strURL.size() - iPos - 1));
            *this = c;
          }
          else
          {
            CURL c((CStdString)"zip" + "://" + archiveName + '/' + strURL.Right(strURL.size() - iPos - 1));
            *this = c;
          }
          return;
        }
      }
    }
  }
  else
  {
    SetProtocol(strURL.Left(iPos));
    iPos += 3;
  }

  // virtual protocols
  // why not handle all format 2 (protocol://file) style urls here?
  // ones that come to mind are iso9660, cdda, musicdb, etc.
  // they are all local protocols and have no server part, port number, special options, etc.
  // this removes the need for special handling below.
  if (
    m_strProtocol.Equals("stack") ||
    m_strProtocol.Equals("virtualpath") ||
    m_strProtocol.Equals("multipath") ||
    m_strProtocol.Equals("filereader") ||
    m_strProtocol.Equals("special")
    )
  {
    SetFileName(strURL.Mid(iPos));
    return;
  }

  // check for username/password - should occur before first /
  if (iPos == -1) iPos = 0;

  // for protocols supporting options, chop that part off here
  // maybe we should invert this list instead?
  int iEnd = strURL.length();
  const char* sep = NULL;

  //TODO fix all Addon paths
  CStdString strProtocol2 = GetTranslatedProtocol();
  if(m_strProtocol.Equals("rss") ||
     m_strProtocol.Equals("rar") ||
     m_strProtocol.Equals("addons") ||
     m_strProtocol.Equals("image") ||
     m_strProtocol.Equals("videodb") ||
     m_strProtocol.Equals("musicdb") ||
     m_strProtocol.Equals("androidapp"))
    sep = "?";
  else
  if(strProtocol2.Equals("http")
    || strProtocol2.Equals("https")
    || strProtocol2.Equals("plugin")
    || strProtocol2.Equals("addons")
    || strProtocol2.Equals("hdhomerun")
    || strProtocol2.Equals("rtsp")
    || strProtocol2.Equals("apk")
    || strProtocol2.Equals("zip"))
    sep = "?;#|";
  else if(strProtocol2.Equals("ftp")
       || strProtocol2.Equals("ftps"))
    sep = "?;";

  if(sep)
  {
    int iOptions = strURL.find_first_of(sep, iPos);
    if (iOptions >= 0 )
    {
      // we keep the initial char as it can be any of the above
      int iProto = strURL.find_first_of("|",iOptions);
      if (iProto >= 0)
      {
        m_strProtocolOptions = strURL.substr(iProto+1);
        m_strOptions = strURL.substr(iOptions,iProto-iOptions);
      }
      else
        m_strOptions = strURL.substr(iOptions);
      iEnd = iOptions;
      m_options.AddOptions(m_strOptions);
    }
  }

  int iSlash = strURL.Find("/", iPos);
  if(iSlash >= iEnd)
    iSlash = -1; // was an invalid slash as it was contained in options

  if( !m_strProtocol.Equals("iso9660") )
  {
    int iAlphaSign = strURL.Find("@", iPos);
    if (iAlphaSign >= 0 && iAlphaSign < iEnd && (iAlphaSign < iSlash || iSlash < 0))
    {
      // username/password found
      CStdString strUserNamePassword = strURL.Mid(iPos, iAlphaSign - iPos);

      // first extract domain, if protocol is smb
      if (m_strProtocol.Equals("smb"))
      {
        int iSemiColon = strUserNamePassword.Find(";");

        if (iSemiColon >= 0)
        {
          m_strDomain = strUserNamePassword.Left(iSemiColon);
          strUserNamePassword.Delete(0, iSemiColon + 1);
        }
      }

      // username:password
      int iColon = strUserNamePassword.Find(":");
      if (iColon >= 0)
      {
        m_strUserName = strUserNamePassword.Left(iColon);
        iColon++;
        m_strPassword = strUserNamePassword.Right(strUserNamePassword.size() - iColon);
      }
      // username
      else
      {
        m_strUserName = strUserNamePassword;
      }

      iPos = iAlphaSign + 1;
      iSlash = strURL.Find("/", iAlphaSign);

      if(iSlash >= iEnd)
        iSlash = -1;
    }
  }

  // detect hostname:port/
  if (iSlash < 0)
  {
    CStdString strHostNameAndPort = strURL.Mid(iPos, iEnd - iPos);
    int iColon = strHostNameAndPort.Find(":");
    if (iColon >= 0)
    {
      m_strHostName = strHostNameAndPort.Left(iColon);
      iColon++;
      CStdString strPort = strHostNameAndPort.Right(strHostNameAndPort.size() - iColon);
      m_iPort = atoi(strPort.c_str());
    }
    else
    {
      m_strHostName = strHostNameAndPort;
    }

  }
  else
  {
    CStdString strHostNameAndPort = strURL.Mid(iPos, iSlash - iPos);
    int iColon = strHostNameAndPort.Find(":");
    if (iColon >= 0)
    {
      m_strHostName = strHostNameAndPort.Left(iColon);
      iColon++;
      CStdString strPort = strHostNameAndPort.Right(strHostNameAndPort.size() - iColon);
      m_iPort = atoi(strPort.c_str());
    }
    else
    {
      m_strHostName = strHostNameAndPort;
    }
    iPos = iSlash + 1;
    if (iEnd > iPos)
    {
      m_strFileName = strURL.Mid(iPos, iEnd - iPos);

      iSlash = m_strFileName.Find("/");
      if(iSlash < 0)
        m_strShareName = m_strFileName;
      else
        m_strShareName = m_strFileName.Left(iSlash);
    }
  }

  // iso9960 doesnt have an hostname;-)
  if (m_strProtocol.CompareNoCase("iso9660") == 0
    || m_strProtocol.CompareNoCase("musicdb") == 0
    || m_strProtocol.CompareNoCase("videodb") == 0
    || m_strProtocol.CompareNoCase("sources") == 0
    || m_strProtocol.CompareNoCase("lastfm") == 0
    || m_strProtocol.CompareNoCase("pvr") == 0
    || m_strProtocol.Left(3).CompareNoCase("mem") == 0)
  {
    if (m_strHostName != "" && m_strFileName != "")
    {
      CStdString strFileName = m_strFileName;
      m_strFileName.Format("%s/%s", m_strHostName.c_str(), strFileName.c_str());
      m_strHostName = "";
    }
    else
    {
      if (!m_strHostName.IsEmpty() && strURL[iEnd-1]=='/')
        m_strFileName = m_strHostName + "/";
      else
        m_strFileName = m_strHostName;
      m_strHostName = "";
    }
  }

  m_strFileName.Replace("\\", "/");

  /* update extension */
  SetFileName(m_strFileName);

  /* decode urlencoding on this stuff */
  if(URIUtils::ProtocolHasEncodedHostname(m_strProtocol))
  {
    Decode(m_strHostName);
    // Validate it as it is likely to contain a filename
    SetHostName(CUtil::ValidatePath(m_strHostName));
  }

  Decode(m_strUserName);
  Decode(m_strPassword);
}
示例#28
0
void CMythSession::SetSeasonAndEpisode(const cmyth_proginfo_t &program, int *season, int *episode) {
  /*
   * A valid programid generated from an XMLTV source should look like:
   * [EP|MV|SH|SP][seriesid][episode][season]([partnumber][parttotal])
   * mythtv/trunk/programs/mytfilldatabaseline/xmltvparser.cpp - Line 522 onwards.
   * 
   * Season changed to a base36 character for XMLTV in Myth 0.24. http://svn.mythtv.org/trac/changeset/24724
   * 
   * A valid SchedulesDirect programid appears to have a similar format to the XMLTV programid but
   * doesn't have any obvious way to parse out the season and episode information. The number at the
   * end of the programid could possibly be the completely sequential number for the episode, but
   * even that doesn't seem to match up with TVDB. SchedulesDirect data does seem to have a valid
   * original air date though, so if we identify a SchedulesDirect programid, leave the season and
   * episode as 0. 
   */
  CStdString programid = GetValue(m_dll->proginfo_programid(program));
  CStdString seriesid = GetValue(m_dll->proginfo_seriesid(program));

  /*
   * Default the season and episode to 0 so XBMC treats the content as an episode and displays tag
   * information. If the season and episode can be parsed from the programid these will be
   * overwritten.
   */
  *season  = 0;
  *episode = 0;
  
  if (programid.IsEmpty() // Can't do anything if the program ID is empty
  ||  seriesid.IsEmpty()) // Can't figure out the end parsing if the series ID is empty  {
    return;
  
  CStdString category = programid.Left(2); // Valid for both XMLTV and SchedulesDirect sources
  if (category != "MV"  // Movie
  &&  category != "EP"  // Series
  &&  category != "SH"  // TV Show
  &&  category != "SP") // Sports
    return;
  
  if (programid.Mid(category.length(), seriesid.length()) != seriesid) // Series ID does not follow the category
    return;
  
  CStdString remainder = programid.Mid(category.length() + seriesid.length()); // Whatever is after series ID
  
  /*
   * All SchedulesDirect remainders appear to be 4 characters and start with a 0. If the assumption
   * is correct that the number somehow relates to the sequential episode number across all seasons
   * then we can ignore remainders that start with 0. It will be very unlikely for a sequential
   * episode number for a series to be > 999.
   */
  if (remainder.length() == 4     // All SchedulesDirect codes seem to be 4 characters
  &&  remainder.Left(0)  == "0")  // Padded with 0's for low number. No valid XMLTV remainder will start with 0.
    return;
  
  /*
   * If the remainder is more than 5 characters, it must include the optional part number and total
   * number of parts. Strip off the last 2 characters assuming that there are ridiculously few
   * cases where the number of parts for a single episode is > 9.
   */
  if (remainder.length() >= 5) // Must include optional part number and total number of parts
    remainder = remainder.Left(remainder.length() - 2); // Assumes part number and total are both < 10
  
  /*
   * Now for some heuristic black magic.
   */
  if (remainder.length() == 2)  // Single character season and episode.
  {
    *season = atoi(remainder.Right(1)); // TODO: Fix for base 36 in Myth 0.24. Assume season < 10
    *episode = atoi(remainder.Left(1));
  }
  else if (remainder.length() == 3) // Ambiguous in Myth 0.23. Single character season in Myth 0.24
  {
    /*
     * Following heuristics are intended to work with largest possible number of cases. It won't be
     * perfect, but way better than just assuming the season is < 10.
     */
    if (remainder.Right(1) == "0") // e.g. 610. Unlikely to have a season of 0 (specials) with more than 9 special episodes.
    {
      *season = atoi(remainder.Right(2));
      *episode = atoi(remainder.Left(1));
    }
    else if (remainder.Mid(2, 1) == "0") // e.g. 203. Can't have a season start with 0. Must be end of episode.
    {
      *season = atoi(remainder.Right(1)); // TODO: Fix for base 36 in Myth 0.24. Assume season < 10
      *episode = atoi(remainder.Left(2));
    }
    else if (atoi(remainder.Left(1)) > 3) // e.g. 412. Very unlikely to have more than 39 episodes per season if season > 9.
    {
      /*
       * TODO: See if a check for > 2 is better, e.g. is it still unlike to have more than 29 episodes
       * per season if season > 9?
       */
      *season = atoi(remainder.Right(2));
      *episode = atoi(remainder.Left(1));
    }
    else // e.g. 129. Assume season is < 10 or Myth 0.24 Base 36 season.
    {
      *season = atoi(remainder.Right(1)); // TODO: Fix for base 36 in Myth 0.24. Assume season < 10
      *episode = atoi(remainder.Left(2));
    }
  }
  else if (remainder.length() == 4) // Double digit season and episode in Myth 0.23 OR TODO: has part number and total number of parts
  {
    *season = atoi(remainder.Right(2));
    *episode = atoi(remainder.Left(2));
  }
  return;
}
示例#29
0
// Allow user to select a Fanart
void CGUIDialogMusicInfo::OnGetFanart()
{
  CFileItemList items;

  if (m_albumItem->HasArt("fanart"))
  {
    CFileItemPtr itemCurrent(new CFileItem("fanart://Current",false));
    itemCurrent->SetArt("thumb", m_albumItem->GetArt("fanart"));
    itemCurrent->SetLabel(g_localizeStrings.Get(20440));
    items.Add(itemCurrent);
  }

  // Grab the thumbnails from the web
  for (unsigned int i = 0; i < m_artist.fanart.GetNumFanarts(); i++)
  {
    CStdString strItemPath;
    strItemPath.Format("fanart://Remote%i",i);
    CFileItemPtr item(new CFileItem(strItemPath, false));
    CStdString thumb = m_artist.fanart.GetPreviewURL(i);
    item->SetArt("thumb", CTextureCache::GetWrappedThumbURL(thumb));
    item->SetIconImage("DefaultPicture.png");
    item->SetLabel(g_localizeStrings.Get(20441));

    // TODO: Do we need to clear the cached image?
    //    CTextureCache::Get().ClearCachedImage(thumb);
    items.Add(item);
  }

  // Grab a local thumb
  CMusicDatabase database;
  database.Open();
  CStdString strArtistPath;
  database.GetArtistPath(m_artist.idArtist,strArtistPath);
  CFileItem item(strArtistPath,true);
  CStdString strLocal = item.GetLocalFanart();
  if (!strLocal.IsEmpty())
  {
    CFileItemPtr itemLocal(new CFileItem("fanart://Local",false));
    itemLocal->SetArt("thumb", strLocal);
    itemLocal->SetLabel(g_localizeStrings.Get(20438));

    // TODO: Do we need to clear the cached image?
    CTextureCache::Get().ClearCachedImage(strLocal);
    items.Add(itemLocal);
  }
  else
  {
    CFileItemPtr itemNone(new CFileItem("fanart://None", false));
    itemNone->SetIconImage("DefaultArtist.png");
    itemNone->SetLabel(g_localizeStrings.Get(20439));
    items.Add(itemNone);
  }

  CStdString result;
  VECSOURCES sources = *CMediaSourceSettings::Get().GetSources("music");
  g_mediaManager.GetLocalDrives(sources);
  bool flip=false;
  if (!CGUIDialogFileBrowser::ShowAndGetImage(items, sources, g_localizeStrings.Get(20437), result, &flip, 20445))
    return;   // user cancelled

  // delete the thumbnail if that's what the user wants, else overwrite with the
  // new thumbnail
  if (result.Equals("fanart://Current"))
   return;

  if (result.Equals("fanart://Local"))
    result = strLocal;

  if (result.Left(15)  == "fanart://Remote")
  {
    int iFanart = atoi(result.Mid(15).c_str());
    m_artist.fanart.SetPrimaryFanart(iFanart);
    result = m_artist.fanart.GetImageURL();
  }
  else if (result.Equals("fanart://None") || !CFile::Exists(result))
    result.clear();

  if (flip && !result.empty())
    result = CTextureCache::GetWrappedImageURL(result, "", "flipped");

  // update thumb in the database
  CMusicDatabase db;
  if (db.Open())
  {
    db.SetArtForItem(m_albumItem->GetMusicInfoTag()->GetDatabaseId(), m_albumItem->GetMusicInfoTag()->GetType(), "fanart", result);
    db.Close();
  }

  m_albumItem->SetArt("fanart", result);
  m_hasUpdatedThumb = true;
  // tell our GUI to completely reload all controls (as some of them
  // are likely to have had this image in use so will need refreshing)
  CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_REFRESH_THUMBS);
  g_windowManager.SendMessage(msg);
  // Update our screen
  Update();
}
// Allow user to select a Fanart
void CGUIWindowVideoInfo::OnGetFanart()
{
  CFileItemList items;

  // ensure the fanart is unpacked
  m_movieItem->GetVideoInfoTag()->m_fanart.Unpack();

  // Grab the thumbnails from the web
  CStdString strPath;
  CUtil::AddFileToFolder(g_advancedSettings.m_cachePath,"fanartthumbs",strPath);
  CUtil::WipeDir(strPath);
  DIRECTORY::CDirectory::Create(strPath);
  for (unsigned int i = 0; i < m_movieItem->GetVideoInfoTag()->m_fanart.GetNumFanarts(); i++)
  {
    CStdString strItemPath;
    strItemPath.Format("fanart://Remote%i",i);
    CFileItemPtr item(new CFileItem(strItemPath, false));
    item->SetThumbnailImage("http://this.is/a/thumb/from/the/web");
    item->SetIconImage("defaultPicture.png");
    item->GetVideoInfoTag()->m_fanart = m_movieItem->GetVideoInfoTag()->m_fanart;
    item->SetProperty("fanart_number", (int)i);
    item->SetLabel(g_localizeStrings.Get(415));
    item->SetProperty("labelonthumbload", g_localizeStrings.Get(20015));

    // make sure any previously cached thumb is removed
    if (CFile::Exists(item->GetCachedPictureThumb()))
      CFile::Delete(item->GetCachedPictureThumb());
    items.Add(item);
  }

  CFileItem item(*m_movieItem->GetVideoInfoTag());
  CStdString cachedThumb(item.GetCachedFanart());

  CStdString strLocal = item.CacheFanart(true);
  if (!strLocal.IsEmpty())
  {
    CFileItemPtr itemLocal(new CFileItem("fanart://Local",false));
    itemLocal->SetThumbnailImage(strLocal);
    itemLocal->SetLabel(g_localizeStrings.Get(20017));
    items.Add(itemLocal);
  }

  if (CFile::Exists(cachedThumb))
  {
    CFileItemPtr itemCurrent(new CFileItem("fanart://Current",false));
    itemCurrent->SetThumbnailImage(cachedThumb);
    itemCurrent->SetLabel(g_localizeStrings.Get(20016));
    items.Add(itemCurrent);
  }

  CFileItemPtr itemNone(new CFileItem("fanart://None", false));
  itemNone->SetThumbnailImage("defaultVideoBig.png");
  itemNone->SetLabel(g_localizeStrings.Get(20018));
  items.Add(itemNone);

  CStdString result;
  VECSOURCES sources(g_settings.m_videoSources);
  g_mediaManager.GetLocalDrives(sources);
  bool flip=false;
  if (!CGUIDialogFileBrowser::ShowAndGetImage(items, sources, g_localizeStrings.Get(20019), result, &flip) || result.Equals("fanart://Current"))
    return;   // user cancelled

  if (CFile::Exists(cachedThumb))
    CFile::Delete(cachedThumb);

  if (result.Equals("fanart://Local"))
    result = strLocal;

  if (result.Left(15) == "fanart://Remote")
  {
    int iFanart = atoi(result.Mid(15).c_str());
    // set new primary fanart, and update our database accordingly
    m_movieItem->GetVideoInfoTag()->m_fanart.SetPrimaryFanart(iFanart);
    CVideoDatabase db;
    if (db.Open())
    {
      db.UpdateFanart(*m_movieItem, GetContentType(m_movieItem.get()));
      db.Close();
    }

    // download the fullres fanart image
    CStdString tempFile = "special://temp/fanart_download.jpg";
    CAsyncFileCopy downloader;
    bool succeeded = downloader.Copy(m_movieItem->GetVideoInfoTag()->m_fanart.GetImageURL(), tempFile, g_localizeStrings.Get(13413));
    if (succeeded)
    {
      CPicture pic;
      if (flip)
        pic.ConvertFile(tempFile, cachedThumb,0,1920,-1,100,true);
      else
        pic.CacheImage(tempFile, cachedThumb);
    }
    CFile::Delete(tempFile);
    if (!succeeded)
      return; // failed or cancelled download, so don't do anything
  }
  else if (CFile::Exists(result))
  { // local file
    CPicture pic;
    if (flip)
      pic.ConvertFile(result, cachedThumb,0,1920,-1,100,true);
    else
      pic.CacheImage(result, cachedThumb);
  }

  CUtil::DeleteVideoDatabaseDirectoryCache(); // to get them new thumbs to show
  if (CFile::Exists(cachedThumb))
    m_movieItem->SetProperty("fanart_image", cachedThumb);
  else
    m_movieItem->ClearProperty("fanart_image");
  m_hasUpdatedThumb = true;

  // Update our screen
  Update();
}