当前位置: 首页>>代码示例>>C++>>正文


C++ CFileItem::GetVideoInfoTag方法代码示例

本文整理汇总了C++中CFileItem::GetVideoInfoTag方法的典型用法代码示例。如果您正苦于以下问题:C++ CFileItem::GetVideoInfoTag方法的具体用法?C++ CFileItem::GetVideoInfoTag怎么用?C++ CFileItem::GetVideoInfoTag使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在CFileItem的用法示例。


在下文中一共展示了CFileItem::GetVideoInfoTag方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。

示例1: SaveFileState

    bool SaveFileState(const CFileItem& item, const CBookmark& bookmark, const bool updatePlayCount)
    {
        std::string path = item.GetProperty("original_listitem_url").asString();
        if (!item.HasVideoInfoTag() || path.empty())  {
          return false;
        }

        NPT_String curr_value;
        NPT_String new_value;

        if (item.GetVideoInfoTag()->m_resumePoint.timeInSeconds != bookmark.timeInSeconds) {
            CLog::Log(LOGDEBUG, "UPNP: Updating resume point for item %s", path.c_str());
            long time = (long)bookmark.timeInSeconds;
            if (time < 0) time = 0;
            curr_value.Append(NPT_String::Format("<upnp:lastPlaybackPosition>%ld</upnp:lastPlaybackPosition>",
                                                 (long)item.GetVideoInfoTag()->m_resumePoint.timeInSeconds));
            new_value.Append(NPT_String::Format("<upnp:lastPlaybackPosition>%ld</upnp:lastPlaybackPosition>", time));
        }
        if (updatePlayCount) {
            CLog::Log(LOGDEBUG, "UPNP: Marking video item %s as watched", path.c_str());
            if (!curr_value.IsEmpty()) curr_value.Append(",");
            if (!new_value.IsEmpty()) new_value.Append(",");
            curr_value.Append("<upnp:playCount>0</upnp:playCount>");
            new_value.Append("<upnp:playCount>1</upnp:playCount>");
        }

        return InvokeUpdateObject(path.c_str(), (const char*)curr_value, (const char*)new_value);
    }
开发者ID:MrMC,项目名称:mrmc,代码行数:28,代码来源:UPnP.cpp

示例2: DetectAndAddMissingItemData

void CVideoThumbLoader::DetectAndAddMissingItemData(CFileItem &item)
{
  if (item.m_bIsFolder) return;

  std::string stereoMode;
  // detect stereomode for videos
  if (item.HasVideoInfoTag())
    stereoMode = item.GetVideoInfoTag()->m_streamDetails.GetStereoMode();
  if (stereoMode.empty())
  {
    std::string path = item.GetPath();
    if (item.IsVideoDb() && item.HasVideoInfoTag())
      path = item.GetVideoInfoTag()->GetPath();

    // check for custom stereomode setting in video settings
    CVideoSettings itemVideoSettings;
    m_videoDatabase->Open();
    if (m_videoDatabase->GetVideoSettings(path, itemVideoSettings) && itemVideoSettings.m_StereoMode != RENDER_STEREO_MODE_OFF)
      stereoMode = CStereoscopicsManager::Get().ConvertGuiStereoModeToString( (RENDER_STEREO_MODE) itemVideoSettings.m_StereoMode );
    m_videoDatabase->Close();

    // still empty, try grabbing from filename
    // TODO: in case of too many false positives due to using the full path, extract the filename only using string utils
    if (stereoMode.empty())
      stereoMode = CStereoscopicsManager::Get().DetectStereoModeByString( path );
  }
  if (!stereoMode.empty())
    item.SetProperty("stereomode", CStereoscopicsManager::Get().NormalizeStereoMode(stereoMode));
}
开发者ID:7orlum,项目名称:xbmc,代码行数:29,代码来源:VideoThumbLoader.cpp

示例3: FillThumb

bool CVideoThumbLoader::FillThumb(CFileItem &item)
{
  if (item.HasArt("thumb"))
    return true;
  std::string thumb = GetCachedImage(item, "thumb");
  if (thumb.empty())
  {
    thumb = GetLocalArt(item, "thumb");
    if (!thumb.empty())
      SetCachedImage(item, "thumb", thumb);
  }
  if (!thumb.empty())
    item.SetArt("thumb", thumb);
  else
  {
    // If nothing was found, try embedded art
    if (item.HasVideoInfoTag() && !item.GetVideoInfoTag()->m_coverArt.empty())
    {
      for (auto& it : item.GetVideoInfoTag()->m_coverArt)
      {
        if (it.m_type == "thumb")
        {
          thumb = CTextureUtils::GetWrappedImageURL(item.GetPath(), "video_" + it.m_type);
          item.SetArt(it.m_type, thumb);
        }
      }
    }
  }

  return !thumb.empty();
}
开发者ID:68foxboris,项目名称:xbmc,代码行数:31,代码来源:VideoThumbLoader.cpp

示例4: ChooseArtType

string CGUIDialogVideoInfo::ChooseArtType(const CFileItem &videoItem, map<string, string> &currentArt)
{
  // prompt for choice
  CGUIDialogSelect *dialog = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT);
  if (!dialog || !videoItem.HasVideoInfoTag())
    return "";

  CFileItemList items;
  dialog->SetHeading(13511);
  dialog->Reset();
  dialog->SetUseDetails(true);
  dialog->EnableButton(true, 13516);

  CVideoDatabase db;
  db.Open();

  vector<string> artTypes = CVideoThumbLoader::GetArtTypes(videoItem.GetVideoInfoTag()->m_type);

  // add in any stored art for this item that is non-empty.
  db.GetArtForItem(videoItem.GetVideoInfoTag()->m_iDbId, videoItem.GetVideoInfoTag()->m_type, currentArt);
  for (CGUIListItem::ArtMap::iterator i = currentArt.begin(); i != currentArt.end(); ++i)
  {
    if (!i->second.empty() && find(artTypes.begin(), artTypes.end(), i->first) == artTypes.end())
      artTypes.push_back(i->first);
  }

  // add any art types that exist for other media items of the same type
  vector<string> dbArtTypes;
  db.GetArtTypes(videoItem.GetVideoInfoTag()->m_type, dbArtTypes);
  for (vector<string>::const_iterator it = dbArtTypes.begin(); it != dbArtTypes.end(); it++)
  {
    if (find(artTypes.begin(), artTypes.end(), *it) == artTypes.end())
      artTypes.push_back(*it);
  }

  for (vector<string>::const_iterator i = artTypes.begin(); i != artTypes.end(); ++i)
  {
    string type = *i;
    CFileItemPtr item(new CFileItem(type, "false"));
    item->SetLabel(type);
    if (videoItem.HasArt(type))
      item->SetArt("thumb", videoItem.GetArt(type));
    items.Add(item);
  }

  dialog->SetItems(&items);
  dialog->DoModal();

  if (dialog->IsButtonPressed())
  {
    // Get the new artwork name
    CStdString strArtworkName;
    if (!CGUIKeyboardFactory::ShowAndGetInput(strArtworkName, g_localizeStrings.Get(13516), false))
      return "";

    return strArtworkName;
  }

  return dialog->GetSelectedItem()->GetLabel();
}
开发者ID:crckmc,项目名称:xbmc-boblight,代码行数:60,代码来源:GUIDialogVideoInfo.cpp

示例5: GetCachedEpisodeThumb

CStdString CEdenVideoArtUpdater::GetCachedEpisodeThumb(const CFileItem &item)
{
  // get the locally cached thumb
  CStdString strCRC = StringUtils::Format("%sepisode%i",
                                          item.GetVideoInfoTag()->m_strFileNameAndPath.c_str(),
                                          item.GetVideoInfoTag()->m_iEpisode);
  return GetThumb(strCRC, CProfilesManager::Get().GetVideoThumbFolder(), true);
}
开发者ID:Avbrella,项目名称:xbmc,代码行数:8,代码来源:EdenVideoArtUpdater.cpp

示例6: GetCachedFanart

CStdString CEdenVideoArtUpdater::GetCachedFanart(const CFileItem &item)
{
  if (!item.GetVideoInfoTag()->m_artist.empty())
    return GetThumb(StringUtils::Join(item.GetVideoInfoTag()->m_artist, g_advancedSettings.m_videoItemSeparator), URIUtils::AddFileToFolder(CProfilesManager::Get().GetThumbnailsFolder(), "Music/Fanart/"), false);
  CStdString path = item.GetVideoInfoTag()->GetPath();
  if (path.empty())
    return "";
  return GetThumb(path, URIUtils::AddFileToFolder(CProfilesManager::Get().GetVideoThumbFolder(), "Fanart/"), false);
}
开发者ID:Avbrella,项目名称:xbmc,代码行数:9,代码来源:EdenVideoArtUpdater.cpp

示例7: DetectAndAddMissingItemData

void CVideoThumbLoader::DetectAndAddMissingItemData(CFileItem &item)
{
  if (item.m_bIsFolder) return;

  if (item.HasVideoInfoTag())
  {
    CStreamDetails& details = item.GetVideoInfoTag()->m_streamDetails;

    // add audio language properties
    for (int i = 1; i <= details.GetAudioStreamCount(); i++)
    {
      std::string index = StringUtils::Format("%i", i);
      item.SetProperty("AudioChannels." + index, details.GetAudioChannels(i));
      item.SetProperty("AudioCodec."    + index, details.GetAudioCodec(i).c_str());
      item.SetProperty("AudioLanguage." + index, details.GetAudioLanguage(i).c_str());
    }

    // add subtitle language properties
    for (int i = 1; i <= details.GetSubtitleStreamCount(); i++)
    {
      std::string index = StringUtils::Format("%i", i);
      item.SetProperty("SubtitleLanguage." + index, details.GetSubtitleLanguage(i).c_str());
    }
  }

  const CStereoscopicsManager &stereoscopicsManager = CServiceBroker::GetGUI()->GetStereoscopicsManager();

  std::string stereoMode;

  // detect stereomode for videos
  if (item.HasVideoInfoTag())
    stereoMode = item.GetVideoInfoTag()->m_streamDetails.GetStereoMode();

  if (stereoMode.empty())
  {
    std::string path = item.GetPath();
    if (item.IsVideoDb() && item.HasVideoInfoTag())
      path = item.GetVideoInfoTag()->GetPath();

    // check for custom stereomode setting in video settings
    CVideoSettings itemVideoSettings;
    m_videoDatabase->Open();
    if (m_videoDatabase->GetVideoSettings(item, itemVideoSettings) && itemVideoSettings.m_StereoMode != RENDER_STEREO_MODE_OFF)
    {
      stereoMode = CStereoscopicsManager::ConvertGuiStereoModeToString(static_cast<RENDER_STEREO_MODE>(itemVideoSettings.m_StereoMode));
    }
    m_videoDatabase->Close();

    // still empty, try grabbing from filename
    //! @todo in case of too many false positives due to using the full path, extract the filename only using string utils
    if (stereoMode.empty())
      stereoMode = stereoscopicsManager.DetectStereoModeByString(path);
  }

  if (!stereoMode.empty())
    item.SetProperty("stereomode", CStereoscopicsManager::NormalizeStereoMode(stereoMode));
}
开发者ID:68foxboris,项目名称:xbmc,代码行数:57,代码来源:VideoThumbLoader.cpp

示例8: GetMimeType

std::string CMime::GetMimeType(const CFileItem &item)
{
  std::string path = item.GetPath();
  if (item.HasVideoInfoTag() && !item.GetVideoInfoTag()->GetPath().empty())
    path = item.GetVideoInfoTag()->GetPath();
  else if (item.HasMusicInfoTag() && !item.GetMusicInfoTag()->GetURL().empty())
    path = item.GetMusicInfoTag()->GetURL();

  return GetMimeType(URIUtils::GetExtension(path));
}
开发者ID:0xheart0,项目名称:xbmc,代码行数:10,代码来源:Mime.cpp

示例9: onNewIntent

void CXBMCApp::onNewIntent(CJNIIntent intent)
{
  std::string action = intent.getAction();
  CLog::Log(LOGDEBUG, "CXBMCApp::onNewIntent - Got intent. Action: %s", action.c_str());
  std::string targetFile = GetFilenameFromIntent(intent);
  if (!targetFile.empty() &&  (action == "android.intent.action.VIEW" || action == "android.intent.action.GET_CONTENT"))
  {
    CLog::Log(LOGDEBUG, "-- targetFile: %s", targetFile.c_str());

    CURL targeturl(targetFile);
    std::string value;
    if (action == "android.intent.action.GET_CONTENT" || (targeturl.GetOption("showinfo", value) && value == "true"))
    {
      if (targeturl.IsProtocol("videodb")
          || (targeturl.IsProtocol("special") && targetFile.find("playlists/video") != std::string::npos)
          || (targeturl.IsProtocol("special") && targetFile.find("playlists/mixed") != std::string::npos)
          )
      {
        std::vector<std::string> params;
        params.push_back(targeturl.Get());
        params.push_back("return");
        CApplicationMessenger::GetInstance().PostMsg(TMSG_GUI_ACTIVATE_WINDOW, WINDOW_VIDEO_NAV, 0, nullptr, "", params);
      }
      else if (targeturl.IsProtocol("musicdb")
               || (targeturl.IsProtocol("special") && targetFile.find("playlists/music") != std::string::npos))
      {
        std::vector<std::string> params;
        params.push_back(targeturl.Get());
        params.push_back("return");
        CApplicationMessenger::GetInstance().PostMsg(TMSG_GUI_ACTIVATE_WINDOW, WINDOW_MUSIC_NAV, 0, nullptr, "", params);
      }
    }
    else
    {
      CFileItem* item = new CFileItem(targetFile, false);
      if (item->IsVideoDb())
      {
        *(item->GetVideoInfoTag()) = XFILE::CVideoDatabaseFile::GetVideoTag(CURL(item->GetPath()));
        item->SetPath(item->GetVideoInfoTag()->m_strFileNameAndPath);
      }
      CApplicationMessenger::GetInstance().PostMsg(TMSG_MEDIA_PLAY, 0, 0, static_cast<void*>(item));
    }
  }
  else if (action == ACTION_XBMC_RESUME)
  {
    if (m_playback_state != PLAYBACK_STATE_STOPPED)
    {
      if (m_playback_state & PLAYBACK_STATE_VIDEO)
        RequestVisibleBehind(true);
      if (!(m_playback_state & PLAYBACK_STATE_PLAYING))
        CApplicationMessenger::GetInstance().SendMsg(TMSG_GUI_ACTION, WINDOW_INVALID, -1, static_cast<void*>(new CAction(ACTION_PAUSE)));
    }
  }
}
开发者ID:HitcherUK,项目名称:xbmc,代码行数:54,代码来源:XBMCApp.cpp

示例10: PlayTrailer

void CGUIWindowVideoInfo::PlayTrailer()
{
  CFileItem item;
  item.m_strPath = m_movieItem->GetVideoInfoTag()->m_strTrailer;
  *item.GetVideoInfoTag() = *m_movieItem->GetVideoInfoTag();
  item.GetVideoInfoTag()->m_strTitle.Format("%s (%s)",m_movieItem->GetVideoInfoTag()->m_strTitle.c_str(),g_localizeStrings.Get(20410));
  item.SetThumbnailImage(m_movieItem->GetThumbnailImage());
  
  // Close the dialog.
  Close(true);
  g_application.getApplicationMessenger().PlayFile(item);
}
开发者ID:jimmyswimmy,项目名称:plex,代码行数:12,代码来源:GUIWindowVideoInfo.cpp

示例11: ShowAndGetInput

bool CGUIDialogPlayEject::ShowAndGetInput(const CFileItem & item,
  unsigned int uiAutoCloseTime /* = 0 */)
{
  // Make sure we're actually dealing with a Disc Stub
  if (!item.IsDiscStub())
    return false;

  // Create the dialog
  CGUIDialogPlayEject * pDialog = (CGUIDialogPlayEject *)g_windowManager.
    GetWindow(WINDOW_DIALOG_PLAY_EJECT);
  if (!pDialog)
    return false;

  // Figure out Line 1 of the dialog
  CStdString strLine1;
  if (item.GetVideoInfoTag())
  {
    strLine1 = item.GetVideoInfoTag()->m_strTitle;
  }
  else
  {
    strLine1 = URIUtils::GetFileName(item.GetPath());
    URIUtils::RemoveExtension(strLine1);
  }

  // Figure out Line 2 of the dialog
  CStdString strLine2;
  CXBMCTinyXML discStubXML;
  if (discStubXML.LoadFile(item.GetPath()))
  {
    TiXmlElement * pRootElement = discStubXML.RootElement();
    if (!pRootElement || strcmpi(pRootElement->Value(), "discstub") != 0)
      CLog::Log(LOGERROR, "Error loading %s, no <discstub> node", item.GetPath().c_str());
    else
      XMLUtils::GetString(pRootElement, "message", strLine2);
  }

  // Setup dialog parameters
  pDialog->SetHeading(219);
  pDialog->SetLine(0, 429);
  pDialog->SetLine(1, strLine1);
  pDialog->SetLine(2, strLine2);
  pDialog->SetChoice(ID_BUTTON_PLAY - 10, 208);
  pDialog->SetChoice(ID_BUTTON_EJECT - 10, 13391);
  if (uiAutoCloseTime)
    pDialog->SetAutoClose(uiAutoCloseTime);

  // Display the dialog
  pDialog->DoModal();

  return pDialog->IsConfirmed();
}
开发者ID:Gemini88,项目名称:xbmc-1,代码行数:52,代码来源:GUIDialogPlayEject.cpp

示例12: GetCachedVideoThumb

CStdString CEdenVideoArtUpdater::GetCachedVideoThumb(const CFileItem &item)
{
  if (item.m_bIsFolder && !item.GetVideoInfoTag()->m_strPath.empty())
    return GetThumb(item.GetVideoInfoTag()->m_strPath, CProfilesManager::Get().GetVideoThumbFolder(), true);
  else if (!item.GetVideoInfoTag()->m_strFileNameAndPath.empty())
  {
    CStdString path = item.GetVideoInfoTag()->m_strFileNameAndPath;
    if (URIUtils::IsStack(path))
      path = CStackDirectory::GetFirstStackedFile(path);
    return GetThumb(path, CProfilesManager::Get().GetVideoThumbFolder(), true);
  }
  return GetThumb(item.GetPath(), CProfilesManager::Get().GetVideoThumbFolder(), true);
}
开发者ID:Avbrella,项目名称:xbmc,代码行数:13,代码来源:EdenVideoArtUpdater.cpp

示例13: DoSearch

/// \brief Make the actual search for the OnSearch function.
/// \param strSearch The search string
/// \param items Items Found
void CGUIWindowVideoInfo::DoSearch(CStdString& strSearch, CFileItemList& items)
{
  VECMOVIES movies;
  m_database.GetMoviesByActor(strSearch, movies);
  for (int i = 0; i < (int)movies.size(); ++i)
  {
    CStdString strItem;
    strItem.Format("[%s] %s (%i)", g_localizeStrings.Get(20338), movies[i].m_strTitle, movies[i].m_iYear);  // Movie
    CFileItem *pItem = new CFileItem(strItem);
    *pItem->GetVideoInfoTag() = movies[i];
    pItem->m_strPath = movies[i].m_strFileNameAndPath;
    items.Add(pItem);
  }
  movies.clear();
  m_database.GetTvShowsByActor(strSearch, movies);
  for (int i = 0; i < (int)movies.size(); ++i)
  {
    CStdString strItem;
    strItem.Format("[%s] %s", g_localizeStrings.Get(20364), movies[i].m_strTitle);  // Movie
    CFileItem *pItem = new CFileItem(strItem);
    *pItem->GetVideoInfoTag() = movies[i];
    pItem->m_strPath.Format("videodb://1/%u",movies[i].m_iDbId);
    items.Add(pItem);
  }
  movies.clear();
  m_database.GetEpisodesByActor(strSearch, movies);
  for (int i = 0; i < (int)movies.size(); ++i)
  {
    CStdString strItem;
    strItem.Format("[%s] %s", g_localizeStrings.Get(20359), movies[i].m_strTitle);  // Movie
    CFileItem *pItem = new CFileItem(strItem);
    *pItem->GetVideoInfoTag() = movies[i];
    pItem->m_strPath = movies[i].m_strFileNameAndPath;
    items.Add(pItem);
  }

  CFileItemList mvids;
  m_database.GetMusicVideosByArtist(strSearch, mvids);
  for (int i = 0; i < (int)mvids.Size(); ++i)
  {
    CStdString strItem;
    strItem.Format("[%s] %s", g_localizeStrings.Get(20391), mvids[i]->GetVideoInfoTag()->m_strTitle);  // Movie
    CFileItem *pItem = new CFileItem(strItem);
    *pItem->GetVideoInfoTag() = *mvids[i]->GetVideoInfoTag();
    pItem->m_strPath = mvids[i]->GetVideoInfoTag()->m_strFileNameAndPath;
    items.Add(pItem);
  }
}
开发者ID:jimmyswimmy,项目名称:plex,代码行数:51,代码来源:GUIWindowVideoInfo.cpp

示例14: GetExecutePath

std::string CFavouritesDirectory::GetExecutePath(const CFileItem &item, const std::string &contextWindow)
{
  std::string execute;
  if (item.m_bIsFolder && (g_advancedSettings.m_playlistAsFolders ||
                            !(item.IsSmartPlayList() || item.IsPlayList())))
  {
    if (!contextWindow.empty())
      execute = StringUtils::Format("ActivateWindow(%s,%s,return)", contextWindow.c_str(), StringUtils::Paramify(item.GetPath()).c_str());
  }
  /* TODO:STRING_CLEANUP */
  else if (item.IsAndroidApp() && item.GetPath().size() > 26) // androidapp://sources/apps/<foo>
    execute = StringUtils::Format("StartAndroidActivity(%s)", StringUtils::Paramify(item.GetPath().substr(26)).c_str());
  else  // assume a media file
  {
    if (item.IsVideoDb() && item.HasVideoInfoTag())
      execute = StringUtils::Format("PlayMedia(%s)", StringUtils::Paramify(item.GetVideoInfoTag()->m_strFileNameAndPath).c_str());
    else if (item.IsMusicDb() && item.HasMusicInfoTag())
      execute = StringUtils::Format("PlayMedia(%s)", StringUtils::Paramify(item.GetMusicInfoTag()->GetURL()).c_str());
    else if (item.IsPicture())
      execute = StringUtils::Format("ShowPicture(%s)", StringUtils::Paramify(item.GetPath()).c_str());
    else
      execute = StringUtils::Format("PlayMedia(%s)", StringUtils::Paramify(item.GetPath()).c_str());
  }
  return execute;
}
开发者ID:sandalsoft,项目名称:mrmc,代码行数:25,代码来源:FavouritesDirectory.cpp

示例15: ShowPlaySelection

bool CGUIDialogSimpleMenu::ShowPlaySelection(CFileItem& item)
{
  /* if asked to resume somewhere, we should not show anything */
  if (item.m_lStartOffset || (item.HasVideoInfoTag() && item.GetVideoInfoTag()->m_iBookmarkId > 0))
    return true;

  if (CSettings::GetInstance().GetInt(CSettings::SETTING_DISC_PLAYBACK) != BD_PLAYBACK_SIMPLE_MENU)
    return true;

  std::string path;
  if (item.IsVideoDb())
    path = item.GetVideoInfoTag()->m_strFileNameAndPath;
  else
    path = item.GetPath();

  if (item.IsBDFile())
  {
    std::string root = URIUtils::GetParentPath(path);
    URIUtils::RemoveSlashAtEnd(root);
    if (URIUtils::GetFileName(root) == "BDMV")
    {
      CURL url("bluray://");
      url.SetHostName(URIUtils::GetParentPath(root));
      url.SetFileName("root");
      return ShowPlaySelection(item, url.Get());
    }
  }

  if (item.IsDiscImage())
  {
    CURL url2("udf://");
    url2.SetHostName(item.GetPath());
    url2.SetFileName("BDMV/index.bdmv");
    if (XFILE::CFile::Exists(url2.Get()))
    {
      url2.SetFileName("");

      CURL url("bluray://");
      url.SetHostName(url2.Get());
      url.SetFileName("root");
      return ShowPlaySelection(item, url.Get());
    }
  }
  return true;
}
开发者ID:Karlson2k,项目名称:xbmc,代码行数:45,代码来源:GUIDialogSimpleMenu.cpp


注:本文中的CFileItem::GetVideoInfoTag方法示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。