bool CCPUInfo::getTemperature(CTemperature& temperature) { int value = 0; char scale = 0; #ifdef TARGET_POSIX #if defined(TARGET_DARWIN_OSX) value = SMCGetTemperature(SMC_KEY_CPU_TEMP); scale = 'c'; #else int ret = 0; FILE *p = NULL; CStdString cmd = g_advancedSettings.m_cpuTempCmd; temperature.SetState(CTemperature::invalid); if (cmd.empty() && m_fProcTemperature == NULL) return false; if (!cmd.empty()) { p = popen (cmd.c_str(), "r"); if (p) { ret = fscanf(p, "%d %c", &value, &scale); pclose(p); } } else { // procfs is deprecated in the linux kernel, we should move away from // using it for temperature data. It doesn't seem that sysfs has a // general enough interface to bother implementing ATM. rewind(m_fProcTemperature); fflush(m_fProcTemperature); ret = fscanf(m_fProcTemperature, "temperature: %d %c", &value, &scale); // read from the temperature file of the new kernels if (!ret) { ret = fscanf(m_fProcTemperature, "%d", &value); value = value / 1000; scale = 'c'; ret++; } } if (ret != 2) return false; #endif #endif // TARGET_POSIX if (scale == 'C' || scale == 'c') temperature = CTemperature::CreateFromCelsius(value); else if (scale == 'F' || scale == 'f') temperature = CTemperature::CreateFromFahrenheit(value); else return false; return true; }
void CRssReader::Process() { while (GetQueueSize()) { CSingleLock lock(m_critical); int iFeed = m_vecQueue.front(); m_vecQueue.erase(m_vecQueue.begin()); m_strFeed[iFeed] = ""; m_strColors[iFeed] = ""; CCurlFile http; http.SetUserAgent(g_advancedSettings.m_userAgent); http.SetTimeout(2); CStdString strXML; CStdString strUrl = m_vecUrls[iFeed]; lock.Leave(); int nRetries = 3; CURL url(strUrl); std::string fileCharset; // we wait for the network to come up if ((url.GetProtocol() == "http" || url.GetProtocol() == "https") && !g_application.getNetwork().IsAvailable(true)) { CLog::Log(LOGWARNING, "RSS: No network connection"); strXML = "<rss><item><title>"+g_localizeStrings.Get(15301)+"</title></item></rss>"; } else { XbmcThreads::EndTime timeout(15000); while (!m_bStop && nRetries > 0) { if (timeout.IsTimePast()) { CLog::Log(LOGERROR, "Timeout whilst retrieving %s", strUrl.c_str()); http.Cancel(); break; } nRetries--; if (url.GetProtocol() != "http" && url.GetProtocol() != "https") { CFile file; auto_buffer buffer; if (file.LoadFile(strUrl, buffer)) { strXML.assign(buffer.get(), buffer.length()); break; } } else if (http.Get(strUrl, strXML)) { fileCharset = http.GetServerReportedCharset(); CLog::Log(LOGDEBUG, "Got rss feed: %s", strUrl.c_str()); break; } } http.Cancel(); } if (!strXML.empty() && m_pObserver) { // erase any <content:encoded> tags (also unsupported by tinyxml) size_t iStart = strXML.find("<content:encoded>"); size_t iEnd = 0; while (iStart != std::string::npos) { // get <content:encoded> end position iEnd = strXML.find("</content:encoded>", iStart) + 18; // erase the section strXML = strXML.erase(iStart, iEnd - iStart); iStart = strXML.find("<content:encoded>"); } if (Parse(strXML, iFeed, fileCharset)) CLog::Log(LOGDEBUG, "Parsed rss feed: %s", strUrl.c_str()); } } UpdateObserver(); }
void CAddon::UpdateSetting(const CStdString& key, const CStdString& value) { LoadSettings(); if (key.empty()) return; m_settings[key] = value; }
void COptions::SetOption(int nOptionID, LPCTSTR value, bool save /*=true*/) { CStdString str = value; Init(); switch (nOptionID) { case OPTION_SERVERPORT: case OPTION_TLSPORTS: { std::set<int> portSet; str.TrimLeft(_T(" ,")); int pos = str.FindOneOf(_T(" ,")); while (pos != -1) { int port = _ttoi(str.Left(pos)); if (port >= 1 && port <= 65535) portSet.insert(port); str = str.Mid(pos + 1); str.TrimLeft(_T(" ,")); pos = str.FindOneOf(_T(" ,")); } if (str != _T("")) { int port = _ttoi(str); if (port >= 1 && port <= 65535) portSet.insert(port); } str = _T(""); for (std::set<int>::const_iterator iter = portSet.begin(); iter != portSet.end(); iter++) { CStdString tmp; tmp.Format(_T("%d "), *iter); str += tmp; } str.TrimRight(' '); } break; case OPTION_WELCOMEMESSAGE: { std::vector<CStdString> msgLines; int oldpos = 0; str.Replace(_T("\r\n"), _T("\n")); int pos = str.Find(_T("\n")); CStdString line; while (pos != -1) { if (pos) { line = str.Mid(oldpos, pos - oldpos); line = line.Left(CONST_WELCOMEMESSAGE_LINESIZE); line.TrimRight(_T(" ")); if (msgLines.size() || line != _T("")) msgLines.push_back(line); } oldpos = pos + 1; pos = str.Find(_T("\n"), oldpos); } line = str.Mid(oldpos); if (line != _T("")) { line = line.Left(CONST_WELCOMEMESSAGE_LINESIZE); msgLines.push_back(line); } str = _T(""); for (unsigned int i = 0; i < msgLines.size(); i++) str += msgLines[i] + _T("\r\n"); str.TrimRight(_T("\r\n")); if (str == _T("")) { str = _T("%v"); str += _T("\r\nwritten by Tim Kosse ([email protected])"); str += _T("\r\nPlease visit https://filezilla-project.org/"); } } break; case OPTION_ADMINIPBINDINGS: { CStdString sub; std::list<CStdString> ipBindList; for (unsigned int i = 0; i<_tcslen(value); i++) { TCHAR cur = value[i]; if ((cur < '0' || cur > '9') && cur != '.' && cur != ':') { if (sub == _T("") && cur == '*') { ipBindList.clear(); ipBindList.push_back(_T("*")); break; } if (sub != _T("")) { if (IsIpAddress(sub)) ipBindList.push_back(sub); sub = _T(""); } } else sub += cur; } if (sub != _T("")) { if (IsIpAddress(sub)) ipBindList.push_back(sub); } str = _T(""); for (std::list<CStdString>::iterator iter = ipBindList.begin(); iter!=ipBindList.end(); iter++) if (!IsLocalhost(*iter)) str += *iter + _T(" "); str.TrimRight(_T(" ")); } break; case OPTION_ADMINPASS: if (str != _T("") && str.GetLength() < 6) return; break; case OPTION_MODEZ_DISALLOWED_IPS: case OPTION_IPFILTER_ALLOWED: case OPTION_IPFILTER_DISALLOWED: case OPTION_ADMINIPADDRESSES: { str.Replace('\r', ' '); str.Replace('\n', ' '); str.Replace('\r', ' '); while (str.Replace(_T(" "), _T(" "))); str += _T(" "); CStdString ips; int pos = str.Find(' '); while (pos != -1) { CStdString sub = str.Left(pos); str = str.Mid(pos + 1); str.TrimLeft(' '); if (sub == _T("*")) ips += _T(" ") + sub; else { if (IsValidAddressFilter(sub)) ips += " " + sub; pos = str.Find(' '); } } ips.TrimLeft(' '); str = ips; } break; case OPTION_IPBINDINGS: { std::list<CStdString> ipBindList; str += _T(" "); while (!str.empty()) { int pos = str.Find(' '); if (pos < 0) { break; } CStdString sub = str.Left(pos); str = str.Mid(pos + 1); if (sub == _T("*")) { ipBindList.clear(); ipBindList.push_back(_T("*")); break; } else if (IsIpAddress(sub, true)) { ipBindList.push_back(sub); } } if (ipBindList.empty()) ipBindList.push_back(_T("*")); str.clear(); for (auto const& ip : ipBindList) { str += ip + _T(" "); } str.TrimRight(_T(" ")); } break; case OPTION_CUSTOMPASVIPSERVER: if (str.Find(_T("filezilla.sourceforge.net")) != -1) str = _T("http://ip.filezilla-project.org/ip.php"); break; } { simple_lock lock(m_mutex); m_sOptionsCache[nOptionID-1].bCached = TRUE; m_sOptionsCache[nOptionID-1].nType = 0; m_sOptionsCache[nOptionID-1].str = str; m_OptionsCache[nOptionID-1]=m_sOptionsCache[nOptionID-1]; } if (!save) return; USES_CONVERSION; CStdString xmlFileName = GetExecutableDirectory() + _T("FileZilla Server.xml"); char* bufferA = T2A(xmlFileName); if (!bufferA) return; TiXmlDocument document; if (!document.LoadFile(bufferA)) return; TiXmlElement* pRoot = document.FirstChildElement("FileZillaServer"); if (!pRoot) return; TiXmlElement* pSettings = pRoot->FirstChildElement("Settings"); if (!pSettings) pSettings = pRoot->LinkEndChild(new TiXmlElement("Settings"))->ToElement(); TiXmlElement* pItem; for (pItem = pSettings->FirstChildElement("Item"); pItem; pItem = pItem->NextSiblingElement("Item")) { const char* pName = pItem->Attribute("name"); if (!pName) continue; CStdString name(pName); if (name != m_Options[nOptionID-1].name) continue; break; } if (!pItem) pItem = pSettings->LinkEndChild(new TiXmlElement("Item"))->ToElement(); pItem->Clear(); pItem->SetAttribute("name", ConvToNetwork(m_Options[nOptionID - 1].name).c_str()); pItem->SetAttribute("type", "string"); pItem->LinkEndChild(new TiXmlText(ConvToNetwork(value).c_str())); document.SaveFile(bufferA); }
bool CMusicInfoScanner::DownloadArtistInfo(const CStdString& strPath, const CStdString& strArtist, bool& bCanceled, CGUIDialogProgress* pDialog) { XFILE::MUSICDATABASEDIRECTORY::CQueryParams params; XFILE::MUSICDATABASEDIRECTORY::CDirectoryNode::GetDatabaseInfo(strPath, params); bCanceled = false; CArtist artist; m_musicDatabase.Open(); if (m_musicDatabase.GetArtistInfo(params.GetArtistId(),artist)) // already got the info return true; // find artist info ADDON::ScraperPtr info; if (!m_musicDatabase.GetScraperForPath(strPath, info, ADDON::ADDON_SCRAPER_ARTISTS) || !info) { m_musicDatabase.Close(); return false; } // clear our scraper cache info->ClearCache(); if (m_pObserver) { m_pObserver->OnStateChanged(DOWNLOADING_ARTIST_INFO); m_pObserver->OnDirectoryChanged(strArtist); } CMusicInfoScraper scraper(info); // handle nfo files CStdString strArtistPath, strNfo; m_musicDatabase.GetArtistPath(params.GetArtistId(),strArtistPath); URIUtils::AddFileToFolder(strArtistPath,"artist.nfo",strNfo); CNfoFile::NFOResult result=CNfoFile::NO_NFO; CNfoFile nfoReader; if (XFILE::CFile::Exists(strNfo)) { CLog::Log(LOGDEBUG,"Found matching nfo file: %s", strNfo.c_str()); result = nfoReader.Create(strNfo, info); if (result == CNfoFile::FULL_NFO) { CLog::Log(LOGDEBUG, "%s Got details from nfo", __FUNCTION__); CArtist artist; nfoReader.GetDetails(artist); m_musicDatabase.SetArtistInfo(params.GetArtistId(), artist); map<string, string> artwork = GetArtistArtwork(params.GetArtistId(), &artist); m_musicDatabase.SetArtForItem(params.GetArtistId(), "artist", artwork); m_musicDatabase.Close(); return true; } else if (result == CNfoFile::URL_NFO || result == CNfoFile::COMBINED_NFO) { CScraperUrl scrUrl(nfoReader.ScraperUrl()); CMusicArtistInfo artist("nfo",scrUrl); info = nfoReader.GetScraperInfo(); CLog::Log(LOGDEBUG,"-- nfo-scraper: %s",info->Name().c_str()); CLog::Log(LOGDEBUG,"-- nfo url: %s", scrUrl.m_url[0].m_url.c_str()); scraper.SetScraperInfo(info); scraper.GetArtists().push_back(artist); } else CLog::Log(LOGERROR,"Unable to find an url in nfo file: %s", strNfo.c_str()); } if (!scraper.GetArtistCount()) { scraper.FindArtistInfo(strArtist); while (!scraper.Completed()) { if (m_bStop) { scraper.Cancel(); bCanceled = true; } Sleep(1); } } int iSelectedArtist = 0; if (result == CNfoFile::NO_NFO) { if (scraper.Succeeded() && scraper.GetArtistCount() >= 1) { // now load the first match if (pDialog && scraper.GetArtistCount() > 1) { // if we found more then 1 album, let user choose one CGUIDialogSelect *pDlg = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT); if (pDlg) { pDlg->SetHeading(g_localizeStrings.Get(21890)); pDlg->Reset(); pDlg->EnableButton(true, 413); // manual for (int i = 0; i < scraper.GetArtistCount(); ++i) { // set the label to artist CFileItem item(scraper.GetArtist(i).GetArtist()); CStdString strTemp=scraper.GetArtist(i).GetArtist().strArtist; if (!scraper.GetArtist(i).GetArtist().strBorn.IsEmpty()) strTemp += " ("+scraper.GetArtist(i).GetArtist().strBorn+")"; if (!scraper.GetArtist(i).GetArtist().genre.empty()) { CStdString genres = StringUtils::Join(scraper.GetArtist(i).GetArtist().genre, g_advancedSettings.m_musicItemSeparator); if (!genres.empty()) strTemp.Format("[%s] %s", genres.c_str(), strTemp.c_str()); } item.SetLabel(strTemp); item.m_idepth = i; // use this to hold the index of the album in the scraper pDlg->Add(&item); } pDlg->DoModal(); // and wait till user selects one if (pDlg->GetSelectedLabel() < 0) { // none chosen if (!pDlg->IsButtonPressed()) { bCanceled = true; return false; } // manual button pressed CStdString strNewArtist = strArtist; if (!CGUIKeyboardFactory::ShowAndGetInput(strNewArtist, g_localizeStrings.Get(16025), false)) return false; if (pDialog) { pDialog->SetLine(0, strNewArtist); pDialog->Progress(); } m_musicDatabase.Close(); return DownloadArtistInfo(strPath,strNewArtist,bCanceled,pDialog); } iSelectedArtist = pDlg->GetSelectedItem()->m_idepth; } } } else { m_musicDatabase.Close(); return false; } } scraper.LoadArtistInfo(iSelectedArtist, strArtist); while (!scraper.Completed()) { if (m_bStop) { scraper.Cancel(); bCanceled = true; } Sleep(1); } if (scraper.Succeeded()) { artist = scraper.GetArtist(iSelectedArtist).GetArtist(); if (result == CNfoFile::COMBINED_NFO) nfoReader.GetDetails(artist,NULL,true); m_musicDatabase.SetArtistInfo(params.GetArtistId(), artist); } // check thumb stuff map<string, string> artwork = GetArtistArtwork(params.GetArtistId(), &artist); m_musicDatabase.SetArtForItem(params.GetArtistId(), "artist", artwork); m_musicDatabase.Close(); return true; }
bool CAirTunesServer::Initialize(const CStdString &password) { bool ret = false; Deinitialize(); #if defined(HAVE_LIBSHAIRPLAY) if (m_pLibShairplay->Load()) { raop_callbacks_t ao; ao.cls = m_pPipe; ao.audio_init = AudioOutputFunctions::audio_init; ao.audio_set_volume = AudioOutputFunctions::audio_set_volume; ao.audio_set_metadata = AudioOutputFunctions::audio_set_metadata; ao.audio_set_coverart = AudioOutputFunctions::audio_set_coverart; ao.audio_process = AudioOutputFunctions::audio_process; ao.audio_flush = AudioOutputFunctions::audio_flush; ao.audio_destroy = AudioOutputFunctions::audio_destroy; m_pLibShairplay->EnableDelayedUnload(false); m_pRaop = m_pLibShairplay->raop_init(1, &ao, RSA_KEY);//1 - we handle one client at a time max ret = m_pRaop != NULL; if(ret) { char macAdr[6]; unsigned short port = (unsigned short)m_port; m_pLibShairplay->raop_set_log_level(m_pRaop, RAOP_LOG_WARNING); if(g_advancedSettings.m_logEnableAirtunes) { m_pLibShairplay->raop_set_log_level(m_pRaop, RAOP_LOG_DEBUG); } m_pLibShairplay->raop_set_log_callback(m_pRaop, shairplay_log, NULL); CNetworkInterface *net = g_application.getNetwork().GetFirstConnectedInterface(); if (net) { net->GetMacAddressRaw(macAdr); } ret = m_pLibShairplay->raop_start(m_pRaop, &port, macAdr, 6, password.c_str()) >= 0; } } #else int numArgs = 3; CStdString hwStr; CStdString pwStr; CStdString portStr; hwStr.Format("--mac=%s", m_macAddress.c_str()); pwStr.Format("--password=%s",password.c_str()); portStr.Format("--server_port=%d",m_port); if (!password.empty()) { numArgs++; } char *argv[] = { "--apname=XBMC", (char*) portStr.c_str(), (char*) hwStr.c_str(), (char *)pwStr.c_str(), NULL }; if (m_pLibShairport->Load()) { struct AudioOutput ao; ao.ao_initialize = AudioOutputFunctions::ao_initialize; ao.ao_play = AudioOutputFunctions::ao_play; ao.ao_default_driver_id = AudioOutputFunctions::ao_default_driver_id; ao.ao_open_live = AudioOutputFunctions::ao_open_live; ao.ao_close = AudioOutputFunctions::ao_close; ao.ao_append_option = AudioOutputFunctions::ao_append_option; ao.ao_free_options = AudioOutputFunctions::ao_free_options; ao.ao_get_option = AudioOutputFunctions::ao_get_option; #ifdef HAVE_STRUCT_AUDIOOUTPUT_AO_SET_METADATA ao.ao_set_metadata = AudioOutputFunctions::ao_set_metadata; ao.ao_set_metadata_coverart = AudioOutputFunctions::ao_set_metadata_coverart; #endif #if defined(SHAIRPORT_AUDIOOUTPUT_VERSION) #if SHAIRPORT_AUDIOOUTPUT_VERSION >= 2 ao.ao_set_volume = AudioOutputFunctions::ao_set_volume; #endif #endif struct printfPtr funcPtr; funcPtr.extprintf = shairport_log; m_pLibShairport->EnableDelayedUnload(false); m_pLibShairport->shairport_set_ao(&ao); m_pLibShairport->shairport_set_printf(&funcPtr); m_pLibShairport->shairport_main(numArgs, argv); ret = true; } #endif return ret; }
void CGUIDialogMediaSource::OnPathBrowse(int item) { if (item < 0 || item > m_paths->Size()) return; // Browse is called. Open the filebrowser dialog. // Ignore current path is best at this stage?? CStdString path; bool allowNetworkShares(m_type != "programs"); VECSOURCES extraShares; if (m_name != CUtil::GetTitleFromPath(m_paths->Get(item)->GetPath())) m_bNameChanged=true; if (m_type == "music") { CMediaSource share1; #if defined(TARGET_ANDROID) // add the default android music directory std::string path; if (CXBMCApp::GetExternalStorage(path, "music") && !path.empty() && CFile::Exists(path)) { share1.strPath = path; share1.strName = g_localizeStrings.Get(20240); share1.m_ignore = true; extraShares.push_back(share1); } #endif // add the music playlist location share1.strPath = "special://musicplaylists/"; share1.strName = g_localizeStrings.Get(20011); share1.m_ignore = true; extraShares.push_back(share1); share1.strPath = "sap://"; share1.strName = "SAP Streams"; extraShares.push_back(share1); if (g_guiSettings.GetString("audiocds.recordingpath",false) != "") { share1.strPath = "special://recordings/"; share1.strName = g_localizeStrings.Get(21883); extraShares.push_back(share1); } } else if (m_type == "video") { CMediaSource share1; #if defined(TARGET_ANDROID) // add the default android video directory std::string path; if (CXBMCApp::GetExternalStorage(path, "videos") && !path.empty() && CFile::Exists(path)) { share1.strPath = path; share1.strName = g_localizeStrings.Get(20241); share1.m_ignore = true; extraShares.push_back(share1); } #endif // add the video playlist location share1.m_ignore = true; share1.strPath = "special://videoplaylists/"; share1.strName = g_localizeStrings.Get(20012); extraShares.push_back(share1); share1.strPath = "rtv://*/"; share1.strName = "ReplayTV Devices"; extraShares.push_back(share1); share1.strPath = "hdhomerun://"; share1.strName = "HDHomerun Devices"; extraShares.push_back(share1); share1.strPath = "sap://"; share1.strName = "SAP Streams"; extraShares.push_back(share1); // add the recordings dir as needed if (CPVRDirectory::HasRecordings()) { share1.strPath = "pvr://recordings/"; share1.strName = g_localizeStrings.Get(19017); // TV Recordings extraShares.push_back(share1); } } else if (m_type == "pictures") { CMediaSource share1; #if defined(TARGET_ANDROID) // add the default android music directory std::string path; if (CXBMCApp::GetExternalStorage(path, "pictures") && !path.empty() && CFile::Exists(path)) { share1.strPath = path; share1.strName = g_localizeStrings.Get(20242); share1.m_ignore = true; extraShares.push_back(share1); } path.clear(); if (CXBMCApp::GetExternalStorage(path, "photos") && !path.empty() && CFile::Exists(path)) { share1.strPath = path; share1.strName = g_localizeStrings.Get(20243); share1.m_ignore = true; extraShares.push_back(share1); } #endif share1.m_ignore = true; if (g_guiSettings.GetString("debug.screenshotpath",false)!= "") { share1.strPath = "special://screenshots/"; share1.strName = g_localizeStrings.Get(20008); extraShares.push_back(share1); } } else if (m_type == "programs") { // nothing to add } if (CGUIDialogFileBrowser::ShowAndGetSource(path, allowNetworkShares, extraShares.size()==0?NULL:&extraShares)) { if (item < m_paths->Size()) // if the skin does funky things, m_paths may have been cleared m_paths->Get(item)->SetPath(path); if (!m_bNameChanged || m_name.IsEmpty()) { CURL url(path); m_name = url.GetWithoutUserDetails(); URIUtils::RemoveSlashAtEnd(m_name); m_name = CUtil::GetTitleFromPath(m_name); } UpdateButtons(); } }
void CPeripheralCecAdapter::Process(void) { if (!GetSettingBool("enabled")) { CLog::Log(LOGDEBUG, "%s - CEC adapter is disabled in peripheral settings", __FUNCTION__); m_bStarted = false; return; } CStdString strPort = GetComPort(); if (strPort.empty()) return; // set correct physical address from peripheral settings int iHdmiPort = GetSettingInt("cec_hdmi_port"); SetHdmiPort(iHdmiPort); FlushLog(); // open the CEC adapter CLog::Log(LOGDEBUG, "%s - opening a connection to the CEC adapter: %s", __FUNCTION__, strPort.c_str()); // scanning the CEC bus takes about 5 seconds, so display a notification to inform users that we're busy CStdString strMessage; strMessage.Format(g_localizeStrings.Get(21336), g_localizeStrings.Get(36000)); CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(36000), strMessage); if (!m_cecAdapter->Open(strPort.c_str(), 10000)) { FlushLog(); CLog::Log(LOGERROR, "%s - could not opening a connection to the CEC adapter", __FUNCTION__); CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(36000), g_localizeStrings.Get(36012)); m_bStarted = false; return; } CLog::Log(LOGDEBUG, "%s - connection to the CEC adapter opened", __FUNCTION__); m_bIsReady = true; CAnnouncementManager::AddAnnouncer(this); if (GetSettingBool("cec_power_on_startup")) { PowerOnCecDevices(CECDEVICE_TV); FlushLog(); } if (GetSettingBool("use_tv_menu_language")) { cec_menu_language language; if (m_cecAdapter->GetDeviceMenuLanguage(CECDEVICE_TV, &language)) SetMenuLanguage(language.language); } m_cecAdapter->SetOSDString(CECDEVICE_TV, CEC_DISPLAY_CONTROL_DISPLAY_FOR_DEFAULT_TIME, g_localizeStrings.Get(36016).c_str()); CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(36000), g_localizeStrings.Get(36016)); while (!m_bStop) { FlushLog(); if (!m_bStop) ProcessNextCommand(); if (!m_bStop) Sleep(5); } m_cecAdapter->Close(); CLog::Log(LOGDEBUG, "%s - CEC adapter processor thread ended", __FUNCTION__); m_bStarted = false; }
AddonPtr CAddonMgr::Factory(const cp_extension_t *props) { if (!PlatformSupportsAddon(props->plugin)) return AddonPtr(); /* Check if user directories need to be created */ const cp_cfg_element_t *settings = GetExtElement(props->configuration, "settings"); if (settings) CheckUserDirs(settings); const TYPE type = TranslateType(props->ext_point_id); switch (type) { case ADDON_PLUGIN: case ADDON_SCRIPT: return AddonPtr(new CPluginSource(props)); case ADDON_SCRIPT_LIBRARY: case ADDON_SCRIPT_LYRICS: case ADDON_SCRIPT_SUBTITLES: case ADDON_SCRIPT_MODULE: case ADDON_WEB_INTERFACE: return AddonPtr(new CAddon(props)); case ADDON_SCRIPT_WEATHER: { // Eden (API v2.0) broke old weather add-ons AddonPtr result(new CAddon(props)); AddonVersion ver1 = AddonVersion(GetXbmcApiVersionDependency(result)); AddonVersion ver2 = AddonVersion("2.0"); if (ver1 < ver2) { CLog::Log(LOGINFO,"%s: Weather add-ons for api < 2.0 unsupported (%s)",__FUNCTION__,result->ID().c_str()); return AddonPtr(); } return result; } case ADDON_SERVICE: return AddonPtr(new CService(props)); case ADDON_SCRAPER_ALBUMS: case ADDON_SCRAPER_ARTISTS: case ADDON_SCRAPER_MOVIES: case ADDON_SCRAPER_MUSICVIDEOS: case ADDON_SCRAPER_TVSHOWS: case ADDON_SCRAPER_LIBRARY: return AddonPtr(new CScraper(props)); case ADDON_VIZ: case ADDON_SCREENSAVER: { // begin temporary platform handling for Dlls // ideally platforms issues will be handled by C-Pluff // this is not an attempt at a solution CStdString value; if (type == ADDON_SCREENSAVER && 0 == strnicmp(props->plugin->identifier, "screensaver.xbmc.builtin.", 25)) { // built in screensaver return AddonPtr(new CAddon(props)); } #if defined(_LINUX) && !defined(TARGET_DARWIN) if ((value = GetExtValue(props->plugin->extensions->configuration, "@library_linux")) && value.empty()) break; #elif defined(_WIN32) && defined(HAS_SDL_OPENGL) if ((value = GetExtValue(props->plugin->extensions->configuration, "@library_wingl")) && value.empty()) break; #elif defined(_WIN32) && defined(HAS_DX) if ((value = GetExtValue(props->plugin->extensions->configuration, "@library_windx")) && value.empty()) break; #elif defined(TARGET_DARWIN) if ((value = GetExtValue(props->plugin->extensions->configuration, "@library_osx")) && value.empty()) break; #endif if (type == ADDON_VIZ) { #if defined(HAS_VISUALISATION) return AddonPtr(new CVisualisation(props)); #endif } else return AddonPtr(new CScreenSaver(props)); } case ADDON_SKIN: return AddonPtr(new CSkinInfo(props)); case ADDON_VIZ_LIBRARY: return AddonPtr(new CAddonLibrary(props)); case ADDON_REPOSITORY: return AddonPtr(new CRepository(props)); default: break; } return AddonPtr(); }
void CScreenShot::TakeScreenshot() { static bool savingScreenshots = false; static vector<CStdString> screenShots; bool promptUser = false; CStdString strDir; // check to see if we have a screenshot folder yet CSettingPath *screenshotSetting = (CSettingPath*)CSettings::Get().GetSetting("debug.screenshotpath"); if (screenshotSetting != NULL) { strDir = screenshotSetting->GetValue(); if (strDir.empty()) { if (CGUIControlButtonSetting::GetPath(screenshotSetting)) strDir = screenshotSetting->GetValue(); } } if (strDir.IsEmpty()) { strDir = "special://temp/"; if (!savingScreenshots) { promptUser = true; savingScreenshots = true; screenShots.clear(); } } URIUtils::RemoveSlashAtEnd(strDir); if (!strDir.IsEmpty()) { CStdString file = CUtil::GetNextFilename(URIUtils::AddFileToFolder(strDir, "screenshot%03d.png"), 999); if (!file.IsEmpty()) { TakeScreenshot(file, false); if (savingScreenshots) screenShots.push_back(file); if (promptUser) { // grab the real directory CStdString newDir; if (screenshotSetting != NULL) { newDir = screenshotSetting->GetValue(); if (newDir.empty()) { if (CGUIControlButtonSetting::GetPath(screenshotSetting)) newDir = screenshotSetting->GetValue(); } } if (!newDir.IsEmpty()) { for (unsigned int i = 0; i < screenShots.size(); i++) { CStdString file = CUtil::GetNextFilename(URIUtils::AddFileToFolder(newDir, "screenshot%03d.png"), 999); CFile::Cache(screenShots[i], file); } screenShots.clear(); } savingScreenshots = false; } } else { CLog::Log(LOGWARNING, "Too many screen shots or invalid folder"); } } }
bool CFileOperations::FillFileItemList(const CVariant ¶meterObject, CFileItemList &list) { if (parameterObject.isMember("directory")) { CStdString media = parameterObject["media"].asString(); media = media.ToLower(); CStdString strPath = parameterObject["directory"].asString(); if (!strPath.empty()) { CFileItemList items; CStdString extensions = ""; CStdStringArray regexps; if (media.Equals("video")) { regexps = g_advancedSettings.m_videoExcludeFromListingRegExps; extensions = g_settings.m_videoExtensions; } else if (media.Equals("music")) { regexps = g_advancedSettings.m_audioExcludeFromListingRegExps; extensions = g_settings.m_musicExtensions; } else if (media.Equals("pictures")) { regexps = g_advancedSettings.m_pictureExcludeFromListingRegExps; extensions = g_settings.m_pictureExtensions; } CDirectory directory; if (directory.GetDirectory(strPath, items, extensions)) { items.Sort(SORT_METHOD_FILE, SortOrderAscending); CFileItemList filteredDirectories; for (unsigned int i = 0; i < (unsigned int)items.Size(); i++) { if (CUtil::ExcludeFileOrFolder(items[i]->GetPath(), regexps)) continue; if (items[i]->m_bIsFolder) filteredDirectories.Add(items[i]); else if ((media == "video" && items[i]->HasVideoInfoTag()) || (media == "music" && items[i]->HasMusicInfoTag())) list.Add(items[i]); else { CFileItem fileItem; if (FillFileItem(items[i], fileItem, media, parameterObject)) list.Add(CFileItemPtr(new CFileItem(fileItem))); else if (media == "files") list.Add(items[i]); } } if (parameterObject.isMember("recursive") && parameterObject["recursive"].isBoolean()) { for (int i = 0; i < filteredDirectories.Size(); i++) { CVariant val = parameterObject; val["directory"] = filteredDirectories[i]->GetPath(); FillFileItemList(val, list); } } return true; } } } return false; }
bool CLibraryDirectory::GetDirectory(const CURL& url, CFileItemList &items) { std::string libNode = GetNode(url); if (libNode.empty()) return false; if (URIUtils::HasExtension(libNode, ".xml")) { // a filter or folder node TiXmlElement *node = LoadXML(libNode); if (node) { CStdString type = node->Attribute("type"); if (type == "filter") { CSmartPlaylist playlist; CStdString type, label; XMLUtils::GetString(node, "content", type); if (type.empty()) { CLog::Log(LOGERROR, "<content> tag must not be empty for type=\"filter\" node '%s'", libNode.c_str()); return false; } if (XMLUtils::GetString(node, "label", label)) label = CGUIControlFactory::FilterLabel(label); playlist.SetType(type); playlist.SetName(label); if (playlist.LoadFromXML(node) && CSmartPlaylistDirectory::GetDirectory(playlist, items)) { items.SetProperty("library.filter", "true"); items.SetPath(items.GetProperty("path.db").asString()); return true; } } else if (type == "folder") { CStdString path; XMLUtils::GetPath(node, "path", path); if (!path.empty()) { URIUtils::AddSlashAtEnd(path); return CDirectory::GetDirectory(path, items, m_strFileMask, m_flags); } } } return false; } // just a plain node - read the folder for XML nodes and other folders CFileItemList nodes; if (!CDirectory::GetDirectory(libNode, nodes, ".xml", DIR_FLAG_NO_FILE_DIRS)) return false; // iterate over our nodes std::string basePath = url.Get(); for (int i = 0; i < nodes.Size(); i++) { const TiXmlElement *node = NULL; CStdString xml = nodes[i]->GetPath(); if (nodes[i]->m_bIsFolder) node = LoadXML(URIUtils::AddFileToFolder(xml, "index.xml")); else { node = LoadXML(xml); if (node && URIUtils::GetFileName(xml).Equals("index.xml")) { // set the label on our items CStdString label; if (XMLUtils::GetString(node, "label", label)) label = CGUIControlFactory::FilterLabel(label); items.SetLabel(label); continue; } } if (node) { CStdString label, icon; if (XMLUtils::GetString(node, "label", label)) label = CGUIControlFactory::FilterLabel(label); XMLUtils::GetString(node, "icon", icon); int order = 0; node->Attribute("order", &order); // create item URIUtils::RemoveSlashAtEnd(xml); CStdString folder = URIUtils::GetFileName(xml); CFileItemPtr item(new CFileItem(URIUtils::AddFileToFolder(basePath, folder), true)); item->SetLabel(label); if (!icon.empty() && g_TextureManager.HasTexture(icon)) item->SetIconImage(icon); item->m_iprogramCount = order; items.Add(item); } } items.Sort(SortByPlaylistOrder, SortOrderAscending); return true; }
std::string DatabaseUtils::GetField(Field field, MediaType mediaType, DatabaseQueryPart queryPart) { if (field == FieldNone || mediaType == MediaTypeNone) return ""; if (mediaType == MediaTypeAlbum) { if (field == FieldId) return "albumview.idAlbum"; else if (field == FieldAlbum) return "albumview.strAlbum"; else if (field == FieldArtist || field == FieldAlbumArtist) return "albumview.strArtists"; else if (field == FieldGenre) return "albumview.strGenre"; else if (field == FieldYear) return "albumview.iYear"; else if (field == FieldMoods) return "albumview.strMoods"; else if (field == FieldStyles) return "albumview.strStyles"; else if (field == FieldThemes) return "albumview.strThemes"; else if (field == FieldReview) return "albumview.strReview"; else if (field == FieldMusicLabel) return "albumview.strLabel"; else if (field == FieldAlbumType) return "albumview.strType"; else if (field == FieldRating) return "albumview.iRating"; else if (field == FieldDateAdded && queryPart == DatabaseQueryPartOrderBy) return "albumview.idalbum"; // only used for order clauses else if (field == FieldPlaycount) return "albumview.iTimesPlayed"; } else if (mediaType == MediaTypeSong) { if (field == FieldId) return "songview.idSong"; else if (field == FieldTitle) return "songview.strTitle"; else if (field == FieldTrackNumber) return "songview.iTrack"; else if (field == FieldTime) return "songview.iDuration"; else if (field == FieldYear) return "songview.iYear"; else if (field == FieldFilename) return "songview.strFilename"; else if (field == FieldPlaycount) return "songview.iTimesPlayed"; else if (field == FieldStartOffset) return "songview.iStartOffset"; else if (field == FieldEndOffset) return "songview.iEndOffset"; else if (field == FieldLastPlayed) return "songview.lastPlayed"; else if (field == FieldRating) return "songview.rating"; else if (field == FieldComment) return "songview.comment"; else if (field == FieldAlbum) return "songview.strAlbum"; else if (field == FieldPath) return "songview.strPath"; else if (field == FieldArtist || field == FieldAlbumArtist) return "songview.strArtists"; else if (field == FieldGenre) return "songview.strGenre"; else if (field == FieldDateAdded && queryPart == DatabaseQueryPartOrderBy) return "songview.idSong"; // only used for order clauses } else if (mediaType == MediaTypeArtist) { if (field == FieldId) return "artistview.idArtist"; else if (field == FieldArtist) return "artistview.strArtist"; else if (field == FieldGenre) return "artistview.strGenres"; else if (field == FieldMoods) return "artistview.strMoods"; else if (field == FieldStyles) return "artistview.strStyles"; else if (field == FieldInstruments) return "artistview.strInstruments"; else if (field == FieldBiography) return "artistview.strBiography"; else if (field == FieldBorn) return "artistview.strBorn"; else if (field == FieldBandFormed) return "artistview.strFormed"; else if (field == FieldDisbanded) return "artistview.strDisbanded"; else if (field == FieldDied) return "artistview.strDied"; } else if (mediaType == MediaTypeMusicVideo) { CStdString result; if (field == FieldId) return "musicvideoview.idMVideo"; else if (field == FieldTitle) result.Format("musicvideoview.c%02d",VIDEODB_ID_MUSICVIDEO_TITLE); else if (field == FieldTime) result.Format("musicvideoview.c%02d", VIDEODB_ID_MUSICVIDEO_RUNTIME); else if (field == FieldDirector) result.Format("musicvideoview.c%02d", VIDEODB_ID_MUSICVIDEO_DIRECTOR); else if (field == FieldStudio) result.Format("musicvideoview.c%02d", VIDEODB_ID_MUSICVIDEO_STUDIOS); else if (field == FieldYear) result.Format("musicvideoview.c%02d",VIDEODB_ID_MUSICVIDEO_YEAR); else if (field == FieldPlot) result.Format("musicvideoview.c%02d", VIDEODB_ID_MUSICVIDEO_PLOT); else if (field == FieldAlbum) result.Format("musicvideoview.c%02d",VIDEODB_ID_MUSICVIDEO_ALBUM); else if (field == FieldArtist) result.Format("musicvideoview.c%02d", VIDEODB_ID_MUSICVIDEO_ARTIST); else if (field == FieldGenre) result.Format("musicvideoview.c%02d", VIDEODB_ID_MUSICVIDEO_GENRE); else if (field == FieldTrackNumber) result.Format("musicvideoview.c%02d", VIDEODB_ID_MUSICVIDEO_TRACK); else if (field == FieldFilename) return "musicvideoview.strFilename"; else if (field == FieldPath) return "musicvideoview.strPath"; else if (field == FieldPlaycount) return "musicvideoview.playCount"; else if (field == FieldLastPlayed) return "musicvideoview.lastPlayed"; else if (field == FieldDateAdded) return "musicvideoview.dateAdded"; if (!result.empty()) return result; } else if (mediaType == MediaTypeMovie) { CStdString result; if (field == FieldId) return "movieview.idMovie"; else if (field == FieldTitle) { // We need some extra logic to get the title value if sorttitle isn't set if (queryPart == DatabaseQueryPartOrderBy) result.Format("CASE WHEN length(movieview.c%02d) > 0 THEN movieview.c%02d ELSE movieview.c%02d END", VIDEODB_ID_SORTTITLE, VIDEODB_ID_SORTTITLE, VIDEODB_ID_TITLE); else result.Format("movieview.c%02d", VIDEODB_ID_TITLE); } else if (field == FieldPlot) result.Format("movieview.c%02d", VIDEODB_ID_PLOT); else if (field == FieldPlotOutline) result.Format("movieview.c%02d", VIDEODB_ID_PLOTOUTLINE); else if (field == FieldTagline) result.Format("movieview.c%02d", VIDEODB_ID_TAGLINE); else if (field == FieldVotes) result.Format("movieview.c%02d", VIDEODB_ID_VOTES); else if (field == FieldRating) { if (queryPart == DatabaseQueryPartOrderBy) result.Format("CAST(movieview.c%02d as DECIMAL(5,3))", VIDEODB_ID_RATING); else result.Format("movieview.c%02d", VIDEODB_ID_RATING); } else if (field == FieldWriter) result.Format("movieview.c%02d", VIDEODB_ID_CREDITS); else if (field == FieldYear) result.Format("movieview.c%02d", VIDEODB_ID_YEAR); else if (field == FieldSortTitle) result.Format("movieview.c%02d", VIDEODB_ID_SORTTITLE); else if (field == FieldTime) result.Format("movieview.c%02d", VIDEODB_ID_RUNTIME); else if (field == FieldMPAA) result.Format("movieview.c%02d", VIDEODB_ID_MPAA); else if (field == FieldTop250) result.Format("movieview.c%02d", VIDEODB_ID_TOP250); else if (field == FieldSet) return "movieview.strSet"; else if (field == FieldGenre) result.Format("movieview.c%02d", VIDEODB_ID_GENRE); else if (field == FieldDirector) result.Format("movieview.c%02d", VIDEODB_ID_DIRECTOR); else if (field == FieldStudio) result.Format("movieview.c%02d", VIDEODB_ID_STUDIOS); else if (field == FieldTrailer) result.Format("movieview.c%02d", VIDEODB_ID_TRAILER); else if (field == FieldCountry) result.Format("movieview.c%02d", VIDEODB_ID_COUNTRY); else if (field == FieldFilename) return "movieview.strFilename"; else if (field == FieldPath) return "movieview.strPath"; else if (field == FieldPlaycount) return "movieview.playCount"; else if (field == FieldLastPlayed) return "movieview.lastPlayed"; else if (field == FieldDateAdded) return "movieview.dateAdded"; if (!result.empty()) return result; } else if (mediaType == MediaTypeTvShow) { CStdString result; if (field == FieldId) return "tvshowview.idShow"; else if (field == FieldTitle) { // We need some extra logic to get the title value if sorttitle isn't set if (queryPart == DatabaseQueryPartOrderBy) result.Format("CASE WHEN length(tvshowview.c%02d) > 0 THEN tvshowview.c%02d ELSE tvshowview.c%02d END", VIDEODB_ID_TV_SORTTITLE, VIDEODB_ID_TV_SORTTITLE, VIDEODB_ID_TV_TITLE); else result.Format("tvshowview.c%02d", VIDEODB_ID_TV_TITLE); } else if (field == FieldPlot) result.Format("tvshowview.c%02d", VIDEODB_ID_TV_PLOT); else if (field == FieldTvShowStatus) result.Format("tvshowview.c%02d", VIDEODB_ID_TV_STATUS); else if (field == FieldVotes) result.Format("tvshowview.c%02d", VIDEODB_ID_TV_VOTES); else if (field == FieldRating) result.Format("tvshowview.c%02d", VIDEODB_ID_TV_RATING); else if (field == FieldYear) result.Format("tvshowview.c%02d", VIDEODB_ID_TV_PREMIERED); else if (field == FieldGenre) result.Format("tvshowview.c%02d", VIDEODB_ID_TV_GENRE); else if (field == FieldMPAA) result.Format("tvshowview.c%02d", VIDEODB_ID_TV_MPAA); else if (field == FieldStudio) result.Format("tvshowview.c%02d", VIDEODB_ID_TV_STUDIOS); else if (field == FieldSortTitle) result.Format("tvshowview.c%02d", VIDEODB_ID_TV_SORTTITLE); else if (field == FieldPath) return "tvshowview.strPath"; else if (field == FieldDateAdded) return "tvshowview.dateAdded"; else if (field == FieldLastPlayed) return "tvshowview.lastPlayed"; else if (field == FieldSeason) return "tvshowview.totalSeasons"; else if (field == FieldNumberOfEpisodes) return "tvshowview.totalCount"; else if (field == FieldNumberOfWatchedEpisodes) return "tvshowview.watchedcount"; if (!result.empty()) return result; } else if (mediaType == MediaTypeEpisode) { CStdString result; if (field == FieldId) return "episodeview.idEpisode"; else if (field == FieldTitle) result.Format("episodeview.c%02d", VIDEODB_ID_EPISODE_TITLE); else if (field == FieldPlot) result.Format("episodeview.c%02d", VIDEODB_ID_EPISODE_PLOT); else if (field == FieldVotes) result.Format("episodeview.c%02d", VIDEODB_ID_EPISODE_VOTES); else if (field == FieldRating) result.Format("episodeview.c%02d", VIDEODB_ID_EPISODE_RATING); else if (field == FieldWriter) result.Format("episodeview.c%02d", VIDEODB_ID_EPISODE_CREDITS); else if (field == FieldAirDate) result.Format("episodeview.c%02d", VIDEODB_ID_EPISODE_AIRED); else if (field == FieldTime) result.Format("episodeview.c%02d", VIDEODB_ID_EPISODE_RUNTIME); else if (field == FieldDirector) result.Format("episodeview.c%02d", VIDEODB_ID_EPISODE_DIRECTOR); else if (field == FieldSeason) result.Format("episodeview.c%02d", VIDEODB_ID_EPISODE_SEASON); else if (field == FieldEpisodeNumber) result.Format("episodeview.c%02d", VIDEODB_ID_EPISODE_EPISODE); else if (field == FieldUniqueId) result.Format("episodeview.c%02d", VIDEODB_ID_EPISODE_UNIQUEID); else if (field == FieldEpisodeNumberSpecialSort) result.Format("episodeview.c%02d", VIDEODB_ID_EPISODE_SORTEPISODE); else if (field == FieldSeasonSpecialSort) result.Format("episodeview.c%02d", VIDEODB_ID_EPISODE_SORTSEASON); else if (field == FieldFilename) return "episodeview.strFilename"; else if (field == FieldPath) return "episodeview.strPath"; else if (field == FieldPlaycount) return "episodeview.playCount"; else if (field == FieldLastPlayed) return "episodeview.lastPlayed"; else if (field == FieldDateAdded) return "episodeview.dateAdded"; else if (field == FieldTvShowTitle) return "episodeview.strTitle"; else if (field == FieldYear) return "episodeview.premiered"; else if (field == FieldMPAA) return "episodeview.mpaa"; else if (field == FieldStudio) return "episodeview.strStudio"; if (!result.empty()) return result; } if (field == FieldRandom && queryPart == DatabaseQueryPartOrderBy) return "RANDOM()"; return ""; }
void CPeripherals::GetSettingsFromMappingsFile(TiXmlElement *xmlNode, map<CStdString, PeripheralDeviceSetting> &settings) { TiXmlElement *currentNode = xmlNode->FirstChildElement("setting"); int iMaxOrder = 0; while (currentNode) { CSetting *setting = NULL; CStdString strKey = XMLUtils::GetAttribute(currentNode, "key"); if (strKey.empty()) continue; CStdString strSettingsType = XMLUtils::GetAttribute(currentNode, "type"); int iLabelId = currentNode->Attribute("label") ? atoi(currentNode->Attribute("label")) : -1; const std::string config = XMLUtils::GetAttribute(currentNode, "configurable"); bool bConfigurable = (config.empty() || (config != "no" && config != "false" && config != "0")); if (strSettingsType.Equals("bool")) { const std::string value = XMLUtils::GetAttribute(currentNode, "value"); bool bValue = (value != "no" && value != "false" && value != "0"); setting = new CSettingBool(strKey, iLabelId, bValue); } else if (strSettingsType.Equals("int")) { int iValue = currentNode->Attribute("value") ? atoi(currentNode->Attribute("value")) : 0; int iMin = currentNode->Attribute("min") ? atoi(currentNode->Attribute("min")) : 0; int iStep = currentNode->Attribute("step") ? atoi(currentNode->Attribute("step")) : 1; int iMax = currentNode->Attribute("max") ? atoi(currentNode->Attribute("max")) : 255; setting = new CSettingInt(strKey, iLabelId, iValue, iMin, iStep, iMax); } else if (strSettingsType.Equals("float")) { float fValue = currentNode->Attribute("value") ? (float) atof(currentNode->Attribute("value")) : 0; float fMin = currentNode->Attribute("min") ? (float) atof(currentNode->Attribute("min")) : 0; float fStep = currentNode->Attribute("step") ? (float) atof(currentNode->Attribute("step")) : 0; float fMax = currentNode->Attribute("max") ? (float) atof(currentNode->Attribute("max")) : 0; setting = new CSettingNumber(strKey, iLabelId, fValue, fMin, fStep, fMax); } else if (strSettingsType.Equals("enum")) { CStdString strEnums = XMLUtils::GetAttribute(currentNode, "lvalues"); if (!strEnums.empty()) { vector< pair<int,int> > enums; vector<std::string> valuesVec; StringUtils::Tokenize(strEnums, valuesVec, "|"); for (unsigned int i = 0; i < valuesVec.size(); i++) enums.push_back(make_pair(atoi(valuesVec[i].c_str()), atoi(valuesVec[i].c_str()))); int iValue = currentNode->Attribute("value") ? atoi(currentNode->Attribute("value")) : 0; setting = new CSettingInt(strKey, iLabelId, iValue, enums); } } else { CStdString strValue = XMLUtils::GetAttribute(currentNode, "value"); setting = new CSettingString(strKey, iLabelId, strValue); } if (setting) { //TODO add more types if needed /* set the visibility */ setting->SetVisible(bConfigurable); /* set the order */ int iOrder = 0; currentNode->Attribute("order", &iOrder); /* if the order attribute is invalid or 0, then the setting will be added at the end */ if (iOrder < 0) iOrder = 0; if (iOrder > iMaxOrder) iMaxOrder = iOrder; /* and add this new setting */ PeripheralDeviceSetting deviceSetting = { setting, iOrder }; settings[strKey] = deviceSetting; } currentNode = currentNode->NextSiblingElement("setting"); } /* add the settings without an order attribute or an invalid order attribute set at the end */ for (map<CStdString, PeripheralDeviceSetting>::iterator it = settings.begin(); it != settings.end(); ++it) { if (it->second.m_order == 0) it->second.m_order = ++iMaxOrder; } }
void CMythSession::SetFileItemMetaData(CFileItem &item, cmyth_proginfo_t program) { if (!program) return; /* * Set the FileItem meta-data. */ CStdString title = GetValue(m_dll->proginfo_title(program)); // e.g. Mythbusters CStdString subtitle = GetValue(m_dll->proginfo_subtitle(program)); // e.g. The Pirate Special item.m_strTitle = title; if (!subtitle.empty()) item.m_strTitle += " - \"" + subtitle + "\""; // e.g. Mythbusters - "The Pirate Special" item.m_dateTime = GetValue(m_dll->proginfo_rec_start(program)); item.m_dwSize = m_dll->proginfo_length(program); // size in bytes /* * Set the VideoInfoTag meta-data so it matches the FileItem meta-data where possible. */ CVideoInfoTag* tag = item.GetVideoInfoTag(); tag->m_strTitle = subtitle; // The title is just supposed to be the episode title. tag->m_strShowTitle = title; tag->m_strOriginalTitle = title; tag->m_strPlotOutline = subtitle; tag->m_strPlot = GetValue(m_dll->proginfo_description(program)); /* * TODO: Strip out the subtitle from the description if it is present at the start? OR add the * subtitle to the start of the plot if not already as it used to? Seems strange, should be * handled by skin? * if (tag->m_strPlot.Left(tag->m_strPlotOutline.length()) != tag->m_strPlotOutline && !tag->m_strPlotOutline.empty()) tag->m_strPlot = tag->m_strPlotOutline + '\n' + tag->m_strPlot; */ tag->m_genre = StringUtils::Split(GetValue(m_dll->proginfo_category(program)), g_advancedSettings.m_videoItemSeparator); // e.g. Sports tag->m_strAlbum = GetValue(m_dll->proginfo_chansign(program)); // e.g. TV3 tag->m_duration = m_dll->proginfo_length_sec(program); SetSeasonAndEpisode(program, &tag->m_iSeason, &tag->m_iEpisode); /* * Original air date is used by the VideoInfoScanner to scrape the TV Show information into the * Video Library. If the original air date is empty the date returned will be the epoch. */ CStdString originalairdate = GetValue(m_dll->proginfo_originalairdate(program)).GetAsDBDate(); if (originalairdate != "1970-01-01" && originalairdate != "1969-12-31") tag->m_firstAired.SetFromDateString(originalairdate); /* * Video sort title is the raw title with the date appended on the end in a sortable format so * when the "All Recordings" listing is sorted by "Name" rather than "Date", all of the episodes * for a given show are still presented in date order (even though some may have a subtitle that * would cause it to be shown in a different position if it was indeed strictly sorting by * what is displayed in the list). */ tag->m_strSortTitle = title + " " + item.m_dateTime.GetAsDBDateTime(); // e.g. Mythbusters 2009-12-13 12:23:14 /* * Set further FileItem and VideoInfoTag meta-data based on whether it is LiveTV or not. */ CURL url(item.GetPath()); if (StringUtils::StartsWith(url.GetFileName(), "channels/")) { /* * Prepend the channel number onto the FileItem title for the listing so it's clear what is * playing on each channel without using up as much room as the channel name. */ CStdString number = GetValue(m_dll->proginfo_chanstr(program)); item.m_strTitle = number + " - " + item.m_strTitle; /* * Append the channel name onto the end of the tag title for the OSD so it's clear what LiveTV * channel is currently being watched to give some context for Next or Previous channel. Added * to the end so sorting by title will work, and it's not really as important as the title * within the OSD. */ CStdString name = GetValue(m_dll->proginfo_chansign(program)); if (!name.empty()) tag->m_strTitle += " - " + name; /* * Set the sort title to be the channel number. */ tag->m_strSortTitle = number; /* * Set the status so XBMC treats the content as LiveTV. */ tag->m_strStatus = "livetv"; /* * Update the path and channel icon for LiveTV in case the channel has changed through * NextChannel(), PreviousChannel() or SetChannel(). */ if (!number.empty()) { url.SetFileName("channels/" + number + ".ts"); // e.g. channels/3.ts item.SetPath(url.Get()); } CStdString chanicon = GetValue(m_dll->proginfo_chanicon(program)); if (!chanicon.empty()) { url.SetFileName("files/channels/" + URIUtils::GetFileName(chanicon)); // e.g. files/channels/tv3.jpg item.SetArt("thumb", url.Get()); } } else { /* * MythTV thumbnails aren't generated until a program has finished recording. */ if (m_dll->proginfo_rec_status(program) == RS_RECORDED) { url.SetFileName("files/" + URIUtils::GetFileName(GetValue(m_dll->proginfo_pathname(program))) + ".png"); item.SetArt("thumb", url.Get()); } } }
void CFileItemHandler::HandleFileItem(const char *ID, bool allowFile, const char *resultname, CFileItemPtr item, const CVariant ¶meterObject, const CVariant &validFields, CVariant &result, bool append /* = true */) { CVariant object; bool hasFileField = false; bool hasThumbnailField = false; if (item.get()) { for (unsigned int i = 0; i < validFields.size(); i++) { CStdString field = validFields[i].asString(); if (field == "file") hasFileField = true; if (field == "thumbnail") hasThumbnailField = true; } if (allowFile && hasFileField) { if (item->HasVideoInfoTag() && !item->GetVideoInfoTag()->GetPath().IsEmpty()) object["file"] = item->GetVideoInfoTag()->GetPath().c_str(); if (item->HasMusicInfoTag() && !item->GetMusicInfoTag()->GetURL().IsEmpty()) object["file"] = item->GetMusicInfoTag()->GetURL().c_str(); if (!object.isMember("file")) object["file"] = item->GetPath().c_str(); } if (ID) { if (item->HasMusicInfoTag() && item->GetMusicInfoTag()->GetDatabaseId() > 0) object[ID] = (int)item->GetMusicInfoTag()->GetDatabaseId(); else if (item->HasVideoInfoTag() && item->GetVideoInfoTag()->m_iDbId > 0) object[ID] = item->GetVideoInfoTag()->m_iDbId; if (stricmp(ID, "id") == 0) { if (item->HasMusicInfoTag()) { if (item->m_bIsFolder && item->IsAlbum()) object["type"] = "album"; else object["type"] = "song"; } else if (item->HasVideoInfoTag()) { switch (item->GetVideoContentType()) { case VIDEODB_CONTENT_EPISODES: object["type"] = "episode"; break; case VIDEODB_CONTENT_MUSICVIDEOS: object["type"] = "musicvideo"; break; case VIDEODB_CONTENT_MOVIES: object["type"] = "movie"; break; default: break; } } else if (item->HasPictureInfoTag()) object["type"] = "picture"; if (!object.isMember("type")) object["type"] = "unknown"; } } if (hasThumbnailField) { if (item->HasThumbnail()) object["thumbnail"] = item->GetThumbnailImage().c_str(); else if (item->HasVideoInfoTag()) { CStdString strPath, strFileName; URIUtils::Split(item->GetCachedVideoThumb(), strPath, strFileName); CStdString cachedThumb = strPath + "auto-" + strFileName; if (CFile::Exists(cachedThumb)) object["thumbnail"] = cachedThumb; } else if (item->HasPictureInfoTag()) { CStdString thumb = CTextureCache::Get().CheckAndCacheImage(CTextureCache::GetWrappedThumbURL(item->GetPath())); if (!thumb.empty()) object["thumbnail"] = thumb; } if (!object.isMember("thumbnail")) object["thumbnail"] = ""; } if (item->HasVideoInfoTag()) FillDetails(item->GetVideoInfoTag(), item, validFields, object); if (item->HasMusicInfoTag()) FillDetails(item->GetMusicInfoTag(), item, validFields, object); if (item->HasPictureInfoTag()) FillDetails(item->GetPictureInfoTag(), item, validFields, object); object["label"] = item->GetLabel().c_str(); } else object = CVariant(CVariant::VariantTypeNull); if (resultname) { if (append) result[resultname].append(object); else result[resultname] = object; } }
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.empty() // Can't do anything if the program ID is empty || seriesid.empty()) // Can't figure out the end parsing if the series ID is empty { return; CStdString category = programid.substr(0, 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.substr(category.length(), seriesid.length()) != seriesid) // Series ID does not follow the category return; CStdString remainder = programid.substr(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[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.substr(0, 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.substr(1, 1).c_str()); // TODO: Fix for base 36 in Myth 0.24. Assume season < 10 *episode = atoi(remainder.substr(0, 1).c_str()); } 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[2] == '0') // e.g. 610. Unlikely to have a season of 0 (specials) with more than 9 special episodes. { *season = atoi(remainder.substr(1, 2).c_str()); *episode = atoi(remainder.substr(0, 1).c_str()); } else if (remainder[1] == '0') // e.g. 203. Can't have a season start with 0. Must be end of episode. { *season = atoi(remainder.substr(2, 1).c_str()); // TODO: Fix for base 36 in Myth 0.24. Assume season < 10 *episode = atoi(remainder.substr(0, 2).c_str()); } else if (atoi(remainder.substr(0, 1).c_str()) > 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.substr(1, 2).c_str()); *episode = atoi(remainder.substr(0, 1).c_str()); } else // e.g. 129. Assume season is < 10 or Myth 0.24 Base 36 season. { *season = atoi(remainder.substr(2, 1).c_str()); // TODO: Fix for base 36 in Myth 0.24. Assume season < 10 *episode = atoi(remainder.substr(0, 2).c_str()); } } 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.substr(2, 2).c_str()); *episode = atoi(remainder.substr(0, 2).c_str()); } return; }
bool CAirPlayServer::CTCPClient::checkAuthorization(const CStdString& authStr, const CStdString& method, const CStdString& uri) { bool authValid = true; CStdString username; if (authStr.empty()) return false; //first get username - we allow all usernames for airplay (usually it is AirPlay) username = getFieldFromString(authStr, "username"); if (username.empty()) { authValid = false; } //second check realm if (authValid) { if (getFieldFromString(authStr, "realm") != AUTH_REALM) { authValid = false; } } //third check nonce if (authValid) { if (getFieldFromString(authStr, "nonce") != m_authNonce) { authValid = false; } } //forth check uri if (authValid) { if (getFieldFromString(authStr, "uri") != uri) { authValid = false; } } //last check response if (authValid) { CStdString realm = AUTH_REALM; CStdString ourResponse = calcResponse(username, ServerInstance->m_password, realm, method, uri, m_authNonce); CStdString theirResponse = getFieldFromString(authStr, "response"); if (!theirResponse.Equals(ourResponse, false)) { authValid = false; CLog::Log(LOGDEBUG,"AirAuth: response mismatch - our: %s theirs: %s",ourResponse.c_str(), theirResponse.c_str()); } else { CLog::Log(LOGDEBUG, "AirAuth: successfull authentication from AirPlay client"); } } m_bAuthenticated = authValid; return m_bAuthenticated; }
// This *looks* like a copy function, therefor the name "Cache" is misleading bool CFile::Cache(const CStdString& strFileName, const CStdString& strDest, XFILE::IFileCallback* pCallback, void* pContext) { CFile file; if (strFileName.empty() || strDest.empty()) return false; // special case for zips - ignore caching CURL url(strFileName); if (URIUtils::IsInZIP(strFileName) || URIUtils::IsInAPK(strFileName)) url.SetOptions("?cache=no"); if (file.Open(url.Get(), READ_TRUNCATED)) { CFile newFile; if (URIUtils::IsHD(strDest)) // create possible missing dirs { vector<CStdString> tokens; CStdString strDirectory; URIUtils::GetDirectory(strDest,strDirectory); URIUtils::RemoveSlashAtEnd(strDirectory); // for the test below if (!(strDirectory.size() == 2 && strDirectory[1] == ':')) { CURL url(strDirectory); CStdString pathsep; #ifndef _LINUX pathsep = "\\"; #else pathsep = "/"; #endif CUtil::Tokenize(url.GetFileName(),tokens,pathsep.c_str()); CStdString strCurrPath; // Handle special if (!url.GetProtocol().IsEmpty()) { pathsep = "/"; strCurrPath += url.GetProtocol() + "://"; } // If the directory has a / at the beginning, don't forget it else if (strDirectory[0] == pathsep[0]) strCurrPath += pathsep; for (vector<CStdString>::iterator iter=tokens.begin();iter!=tokens.end();++iter) { strCurrPath += *iter+pathsep; CDirectory::Create(strCurrPath); } } } if (CFile::Exists(strDest)) CFile::Delete(strDest); if (!newFile.OpenForWrite(strDest, true)) // overwrite always { file.Close(); return false; } int iBufferSize = 128 * 1024; CAutoBuffer buffer(iBufferSize); int iRead, iWrite; UINT64 llFileSize = file.GetLength(); UINT64 llPos = 0; CStopWatch timer; timer.StartZero(); float start = 0.0f; while (true) { g_application.ResetScreenSaver(); iRead = file.Read(buffer.get(), iBufferSize); if (iRead == 0) break; else if (iRead < 0) { CLog::Log(LOGERROR, "%s - Failed read from file %s", __FUNCTION__, strFileName.c_str()); llFileSize = (uint64_t)-1; break; } /* write data and make sure we managed to write it all */ iWrite = 0; while(iWrite < iRead) { int iWrite2 = newFile.Write(buffer.get()+iWrite, iRead-iWrite); if(iWrite2 <=0) break; iWrite+=iWrite2; } if (iWrite != iRead) { CLog::Log(LOGERROR, "%s - Failed write to file %s", __FUNCTION__, strDest.c_str()); llFileSize = (uint64_t)-1; break; } llPos += iRead; // calculate the current and average speeds float end = timer.GetElapsedSeconds(); if (pCallback && end - start > 0.5 && end) { start = end; float averageSpeed = llPos / end; int ipercent = 0; if(llFileSize) ipercent = 100 * llPos / llFileSize; if(!pCallback->OnFileCallback(pContext, ipercent, averageSpeed)) { CLog::Log(LOGERROR, "%s - User aborted copy", __FUNCTION__); llFileSize = (uint64_t)-1; break; } } } /* close both files */ newFile.Close(); file.Close(); /* verify that we managed to completed the file */ if (llFileSize && llPos != llFileSize) { CFile::Delete(strDest); return false; } return true; } return false; }
bool CGUIWindowAddonBrowser::GetDirectory(const CStdString& strDirectory, CFileItemList& items) { bool result; if (strDirectory.Equals("addons://downloading/")) { VECADDONS addons; CAddonInstaller::Get().GetInstallList(addons); CURL url(strDirectory); CAddonsDirectory::GenerateListing(url,addons,items); result = true; items.SetProperty("reponame",g_localizeStrings.Get(24067)); items.SetPath(strDirectory); if (m_guiState.get() && !m_guiState->HideParentDirItems()) { CFileItemPtr pItem(new CFileItem("..")); pItem->SetPath(m_history.GetParentPath()); pItem->m_bIsFolder = true; pItem->m_bIsShareOrDrive = false; items.AddFront(pItem, 0); } } else { result = CGUIMediaWindow::GetDirectory(strDirectory,items); if (CSettings::Get().GetBool("general.addonforeignfilter")) { int i=0; while (i < items.Size()) { if (!FilterVar(CSettings::Get().GetBool("general.addonforeignfilter"), items[i]->GetProperty("Addon.Language"), "en") || !FilterVar(CSettings::Get().GetBool("general.addonforeignfilter"), items[i]->GetProperty("Addon.Language"), g_langInfo.GetLanguageLocale())) { i++; } else items.Remove(i); } } } if (strDirectory.empty() && CAddonInstaller::Get().IsDownloading()) { CFileItemPtr item(new CFileItem("addons://downloading/",true)); item->SetLabel(g_localizeStrings.Get(24067)); item->SetLabelPreformated(true); item->SetIconImage("DefaultNetwork.png"); items.Add(item); } items.SetContent("addons"); for (int i=0; i<items.Size(); ++i) SetItemLabel2(items[i]); return result; }
// 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(); }
int CGUIWindowAddonBrowser::SelectAddonID(const vector<ADDON::TYPE> &types, CStdStringArray &addonIDs, bool showNone /*= false*/, bool multipleSelection /*= true*/) { CGUIDialogSelect *dialog = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT); if (!dialog) return 0; CFileItemList items; CStdString heading; int iTypes = 0; for (vector<ADDON::TYPE>::const_iterator it = types.begin(); it != types.end(); ++it) { if (*it == ADDON_UNKNOWN) continue; ADDON::VECADDONS addons; iTypes++; if (*it == ADDON_AUDIO) CAddonsDirectory::GetScriptsAndPlugins("audio",addons); else if (*it == ADDON_EXECUTABLE) CAddonsDirectory::GetScriptsAndPlugins("executable",addons); else if (*it == ADDON_IMAGE) CAddonsDirectory::GetScriptsAndPlugins("image",addons); else if (*it == ADDON_VIDEO) CAddonsDirectory::GetScriptsAndPlugins("video",addons); else CAddonMgr::Get().GetAddons(*it, addons); for (ADDON::IVECADDONS it2 = addons.begin() ; it2 != addons.end() ; ++it2) { CFileItemPtr item(CAddonsDirectory::FileItemFromAddon(*it2, "")); if (!items.Contains(item->GetPath())) items.Add(item); } if (!heading.empty()) heading += ", "; heading += TranslateType(*it, true); } if (iTypes == 0) return 0; dialog->SetHeading(heading); dialog->Reset(); dialog->SetUseDetails(true); if (multipleSelection) showNone = false; if (multipleSelection || iTypes > 1) dialog->EnableButton(true, 186); else dialog->EnableButton(true, 21452); if (showNone) { CFileItemPtr item(new CFileItem("", false)); item->SetLabel(g_localizeStrings.Get(231)); item->SetLabel2(g_localizeStrings.Get(24040)); item->SetIconImage("DefaultAddonNone.png"); item->SetSpecialSort(SortSpecialOnTop); items.Add(item); } items.Sort(SortByLabel, SortOrderAscending); if (addonIDs.size() > 0) { for (CStdStringArray::const_iterator it = addonIDs.begin(); it != addonIDs.end() ; it++) { CFileItemPtr item = items.Get(*it); if (item) item->Select(true); } } dialog->SetItems(&items); dialog->SetMultiSelection(multipleSelection); dialog->DoModal(); if (!multipleSelection && iTypes == 1 && dialog->IsButtonPressed()) { // switch to the addons browser. vector<CStdString> params; params.push_back("addons://all/"+TranslateType(types[0],false)+"/"); params.push_back("return"); g_windowManager.ActivateWindow(WINDOW_ADDON_BROWSER, params); return 2; } if (!dialog->IsConfirmed()) return 0; addonIDs.clear(); const CFileItemList& list = dialog->GetSelectedItems(); for (int i = 0 ; i < list.Size() ; i++) addonIDs.push_back(list.Get(i)->GetPath()); return 1; }
void GUIFontManager::LoadFonts(const CStdString& strFontSet) { CXBMCTinyXML xmlDoc; if (!OpenFontFile(xmlDoc)) return; TiXmlElement* pRootElement = xmlDoc.RootElement(); const TiXmlNode *pChild = pRootElement->FirstChild(); // If there are no fontset's defined in the XML (old skin format) run in backward compatibility // and ignore the fontset request CStdString strValue = pChild->Value(); if (strValue == "fontset") { CStdString foundTTF; while (pChild) { strValue = pChild->Value(); if (strValue == "fontset") { const char* idAttr = ((TiXmlElement*) pChild)->Attribute("id"); const char* unicodeAttr = ((TiXmlElement*) pChild)->Attribute("unicode"); if (foundTTF.empty() && idAttr != NULL && unicodeAttr != NULL && stricmp(unicodeAttr, "true") == 0) foundTTF = idAttr; // Check if this is the fontset that we want if (idAttr != NULL && stricmp(strFontSet.c_str(), idAttr) == 0) { m_fontsetUnicode=false; // Check if this is the a ttf fontset if (unicodeAttr != NULL && stricmp(unicodeAttr, "true") == 0) m_fontsetUnicode=true; if (m_fontsetUnicode) { LoadFonts(pChild->FirstChild()); break; } } } pChild = pChild->NextSibling(); } // If no fontset was loaded if (pChild == NULL) { CLog::Log(LOGWARNING, "file doesnt have <fontset> with name '%s', defaulting to first fontset", strFontSet.c_str()); if (!foundTTF.empty()) LoadFonts(foundTTF); } } else { CLog::Log(LOGERROR, "file doesnt have <fontset> in <fonts>, but rather %s", strValue.c_str()); return ; } }
void CGUIDialogVideoInfo::SetMovie(const CFileItem *item) { *m_movieItem = *item; // setup cast list + determine type. We need to do this here as it makes // sure that content type (among other things) is set correctly for the // old fixed id labels that we have floating around (they may be using // content type to determine visibility, so we'll set the wrong label) ClearCastList(); VIDEODB_CONTENT_TYPE type = (VIDEODB_CONTENT_TYPE)m_movieItem->GetVideoContentType(); if (type == VIDEODB_CONTENT_MUSICVIDEOS) { // music video CMusicDatabase database; database.Open(); const std::vector<std::string> &artists = m_movieItem->GetVideoInfoTag()->m_artist; for (std::vector<std::string>::const_iterator it = artists.begin(); it != artists.end(); ++it) { int idArtist = database.GetArtistByName(*it); CStdString thumb = database.GetArtForItem(idArtist, "artist", "thumb"); CFileItemPtr item(new CFileItem(*it)); if (!thumb.empty()) item->SetArt("thumb", thumb); item->SetIconImage("DefaultArtist.png"); m_castList->Add(item); } m_castList->SetContent("musicvideos"); } else { // movie/show/episode for (CVideoInfoTag::iCast it = m_movieItem->GetVideoInfoTag()->m_cast.begin(); it != m_movieItem->GetVideoInfoTag()->m_cast.end(); ++it) { CStdString character; if (it->strRole.IsEmpty()) character = it->strName; else character.Format("%s %s %s", it->strName.c_str(), g_localizeStrings.Get(20347).c_str(), it->strRole.c_str()); CFileItemPtr item(new CFileItem(it->strName)); if (!it->thumb.IsEmpty()) item->SetArt("thumb", it->thumb); else if (g_guiSettings.GetBool("videolibrary.actorthumbs")) { // backward compatibility CStdString thumb = CScraperUrl::GetThumbURL(it->thumbUrl.GetFirstThumb()); if (!thumb.IsEmpty()) { item->SetArt("thumb", thumb); CTextureCache::Get().BackgroundCacheImage(thumb); } } item->SetIconImage("DefaultActor.png"); item->SetLabel(character); m_castList->Add(item); } // determine type: if (type == VIDEODB_CONTENT_TVSHOWS) { m_castList->SetContent("tvshows"); // special case stuff for shows (not currently retrieved from the library in filemode (ref: GetTvShowInfo vs GetTVShowsByWhere) m_movieItem->m_dateTime = m_movieItem->GetVideoInfoTag()->m_premiered; if(m_movieItem->GetVideoInfoTag()->m_iYear == 0 && m_movieItem->m_dateTime.IsValid()) m_movieItem->GetVideoInfoTag()->m_iYear = m_movieItem->m_dateTime.GetYear(); m_movieItem->SetProperty("totalepisodes", m_movieItem->GetVideoInfoTag()->m_iEpisode); m_movieItem->SetProperty("numepisodes", m_movieItem->GetVideoInfoTag()->m_iEpisode); // info view has no concept of current watched/unwatched filter as we could come here from files view, but set for consistency m_movieItem->SetProperty("watchedepisodes", m_movieItem->GetVideoInfoTag()->m_playCount); m_movieItem->SetProperty("unwatchedepisodes", m_movieItem->GetVideoInfoTag()->m_iEpisode - m_movieItem->GetVideoInfoTag()->m_playCount); m_movieItem->GetVideoInfoTag()->m_playCount = (m_movieItem->GetVideoInfoTag()->m_iEpisode == m_movieItem->GetVideoInfoTag()->m_playCount) ? 1 : 0; } else if (type == VIDEODB_CONTENT_EPISODES) { m_castList->SetContent("episodes"); // special case stuff for episodes (not currently retrieved from the library in filemode (ref: GetEpisodeInfo vs GetEpisodesByWhere) m_movieItem->m_dateTime = m_movieItem->GetVideoInfoTag()->m_firstAired; if(m_movieItem->GetVideoInfoTag()->m_iYear == 0 && m_movieItem->m_dateTime.IsValid()) m_movieItem->GetVideoInfoTag()->m_iYear = m_movieItem->m_dateTime.GetYear(); // retrieve the season thumb. // TODO: should we use the thumbloader for this? CVideoDatabase db; if (db.Open()) { if (m_movieItem->GetVideoInfoTag()->m_iSeason > -1) { int seasonID = m_movieItem->GetVideoInfoTag()->m_iIdSeason; if (seasonID < 0) seasonID = db.GetSeasonId(m_movieItem->GetVideoInfoTag()->m_iIdShow, m_movieItem->GetVideoInfoTag()->m_iSeason); CGUIListItem::ArtMap thumbs; if (db.GetArtForItem(seasonID, "season", thumbs)) { for (CGUIListItem::ArtMap::iterator i = thumbs.begin(); i != thumbs.end(); i++) m_movieItem->SetArt("season." + i->first, i->second); } } db.Close(); } } else if (type == VIDEODB_CONTENT_MOVIES) { m_castList->SetContent("movies"); // local trailers should always override non-local, so check // for a local one if the registered trailer is online if (m_movieItem->GetVideoInfoTag()->m_strTrailer.IsEmpty() || URIUtils::IsInternetStream(m_movieItem->GetVideoInfoTag()->m_strTrailer)) { CStdString localTrailer = m_movieItem->FindTrailer(); if (!localTrailer.IsEmpty()) { m_movieItem->GetVideoInfoTag()->m_strTrailer = localTrailer; CVideoDatabase database; if(database.Open()) { database.SetDetail(m_movieItem->GetVideoInfoTag()->m_strTrailer, m_movieItem->GetVideoInfoTag()->m_iDbId, VIDEODB_ID_TRAILER, VIDEODB_CONTENT_MOVIES); database.Close(); CUtil::DeleteVideoDatabaseDirectoryCache(); } } } } } CVideoThumbLoader loader; loader.LoadItem(m_movieItem.get()); }
CStdString CStackDirectory::GetStackedTitlePath(const CStdString &strPath, VECCREGEXP& RegExps) { CStackDirectory stack; CFileItemList files; CStdString strStackTitlePath, strCommonDir = URIUtils::GetParentPath(strPath); stack.GetDirectory(strPath, files); if (files.Size() > 1) { CStdString strStackTitle; CStdString File1 = URIUtils::GetFileName(files[0]->GetPath()); CStdString File2 = URIUtils::GetFileName(files[1]->GetPath()); // Check if source path uses URL encoding if (URIUtils::ProtocolHasEncodedFilename(CURL(strCommonDir).GetProtocol())) { CURL::Decode(File1); CURL::Decode(File2); } std::vector<CRegExp>::iterator itRegExp = RegExps.begin(); int offset = 0; while (itRegExp != RegExps.end()) { if (itRegExp->RegFind(File1, offset) != -1) { CStdString Title1 = itRegExp->GetMatch(1), Volume1 = itRegExp->GetMatch(2), Ignore1 = itRegExp->GetMatch(3), Extension1 = itRegExp->GetMatch(4); if (offset) Title1 = File1.substr(0, itRegExp->GetSubStart(2)); if (itRegExp->RegFind(File2, offset) != -1) { CStdString Title2 = itRegExp->GetMatch(1), Volume2 = itRegExp->GetMatch(2), Ignore2 = itRegExp->GetMatch(3), Extension2 = itRegExp->GetMatch(4); if (offset) Title2 = File2.substr(0, itRegExp->GetSubStart(2)); if (Title1.Equals(Title2)) { if (!Volume1.Equals(Volume2)) { if (Ignore1.Equals(Ignore2) && Extension1.Equals(Extension2)) { // got it strStackTitle = Title1 + Ignore1 + Extension1; // Check if source path uses URL encoding if (URIUtils::ProtocolHasEncodedFilename(CURL(strCommonDir).GetProtocol())) CURL::Encode(strStackTitle); itRegExp = RegExps.end(); break; } else // Invalid stack break; } else // Early match, retry with offset { offset = itRegExp->GetSubStart(3); continue; } } } } offset = 0; itRegExp++; } if (!strCommonDir.empty() && !strStackTitle.empty()) strStackTitlePath = strCommonDir + strStackTitle; } return strStackTitlePath; }
void CGUIDialogVideoInfo::OnGetArt() { map<string, string> currentArt; string type = ChooseArtType(*m_movieItem, currentArt); if (type.empty()) return; // cancelled // TODO: this can be removed once these are unified. if (type == "fanart") OnGetFanart(); else { 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(*CMediaSourceSettings::Get().GetSources("video")); AddItemPathToFileBrowserSources(sources, *m_movieItem); g_mediaManager.GetLocalDrives(sources); if (CGUIDialogFileBrowser::ShowAndGetImage(items, sources, g_localizeStrings.Get(13511), result) && result != "thumb://Current") // user didn't choose 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.clear(); // 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(); // re-open the art selection dialog as we come back from // the image selection dialog OnGetArt(); }
void CDVDPlayerVideo::Process() { CLog::Log(LOGNOTICE, "running thread: video_thread"); DVDVideoPicture picture; CPulldownCorrection pulldown; CDVDVideoPPFFmpeg mPostProcess(""); CStdString sPostProcessType; memset(&picture, 0, sizeof(DVDVideoPicture)); double pts = 0; double frametime = (double)DVD_TIME_BASE / m_fFrameRate; int iDropped = 0; //frames dropped in a row bool bRequestDrop = false; m_videoStats.Start(); while (!m_bStop) { int iQueueTimeOut = (int)(m_stalled ? frametime / 4 : frametime * 10) / 1000; int iPriority = (m_speed == DVD_PLAYSPEED_PAUSE && m_started) ? 1 : 0; CDVDMsg* pMsg; MsgQueueReturnCode ret = m_messageQueue.Get(&pMsg, iQueueTimeOut, iPriority); if (MSGQ_IS_ERROR(ret) || ret == MSGQ_ABORT) { CLog::Log(LOGERROR, "Got MSGQ_ABORT or MSGO_IS_ERROR return true"); break; } else if (ret == MSGQ_TIMEOUT) { // if we only wanted priority messages, this isn't a stall if( iPriority ) continue; //Okey, start rendering at stream fps now instead, we are likely in a stillframe if( !m_stalled ) { if(m_started) CLog::Log(LOGINFO, "CDVDPlayerVideo - Stillframe detected, switching to forced %f fps", m_fFrameRate); m_stalled = true; pts+= frametime*4; } //Waiting timed out, output last picture if( picture.iFlags & DVP_FLAG_ALLOCATED ) { //Remove interlaced flag before outputting //no need to output this as if it was interlaced picture.iFlags &= ~DVP_FLAG_INTERLACED; picture.iFlags |= DVP_FLAG_NOSKIP; OutputPicture(&picture, pts); pts+= frametime; } continue; } if (pMsg->IsType(CDVDMsg::GENERAL_SYNCHRONIZE)) { ((CDVDMsgGeneralSynchronize*)pMsg)->Wait( &m_bStop, SYNCSOURCE_VIDEO ); CLog::Log(LOGDEBUG, "CDVDPlayerVideo - CDVDMsg::GENERAL_SYNCHRONIZE"); pMsg->Release(); /* we may be very much off correct pts here, but next picture may be a still*/ /* make sure it isn't dropped */ m_iNrOfPicturesNotToSkip = 5; continue; } else if (pMsg->IsType(CDVDMsg::GENERAL_RESYNC)) { CDVDMsgGeneralResync* pMsgGeneralResync = (CDVDMsgGeneralResync*)pMsg; if(pMsgGeneralResync->m_timestamp != DVD_NOPTS_VALUE) pts = pMsgGeneralResync->m_timestamp; double delay = m_FlipTimeStamp - m_pClock->GetAbsoluteClock(); if( delay > frametime ) delay = frametime; else if( delay < 0 ) delay = 0; if(pMsgGeneralResync->m_clock) { CLog::Log(LOGDEBUG, "CDVDPlayerVideo - CDVDMsg::GENERAL_RESYNC(%f, 1)", pts); m_pClock->Discontinuity(pts - delay); } else CLog::Log(LOGDEBUG, "CDVDPlayerVideo - CDVDMsg::GENERAL_RESYNC(%f, 0)", pts); pMsgGeneralResync->Release(); continue; } else if (pMsg->IsType(CDVDMsg::GENERAL_DELAY)) { if (m_speed != DVD_PLAYSPEED_PAUSE) { double timeout = static_cast<CDVDMsgDouble*>(pMsg)->m_value; CLog::Log(LOGDEBUG, "CDVDPlayerVideo - CDVDMsg::GENERAL_DELAY(%f)", timeout); timeout *= (double)DVD_PLAYSPEED_NORMAL / abs(m_speed); timeout += CDVDClock::GetAbsoluteClock(); while(!m_bStop && CDVDClock::GetAbsoluteClock() < timeout) Sleep(1); } } else if (pMsg->IsType(CDVDMsg::VIDEO_SET_ASPECT)) { CLog::Log(LOGDEBUG, "CDVDPlayerVideo - CDVDMsg::VIDEO_SET_ASPECT"); m_fForcedAspectRatio = *((CDVDMsgDouble*)pMsg); } else if (pMsg->IsType(CDVDMsg::GENERAL_RESET)) { if(m_pVideoCodec) m_pVideoCodec->Reset(); m_packets.clear(); m_started = false; } else if (pMsg->IsType(CDVDMsg::GENERAL_FLUSH)) // private message sent by (CDVDPlayerVideo::Flush()) { if(m_pVideoCodec) m_pVideoCodec->Reset(); m_packets.clear(); m_pullupCorrection.Flush(); //we need to recalculate the framerate //TODO: this needs to be set on a streamchange instead ResetFrameRateCalc(); m_stalled = true; m_started = false; } else if (pMsg->IsType(CDVDMsg::VIDEO_NOSKIP)) { // libmpeg2 is also returning incomplete frames after a dvd cell change // so the first few pictures are not the correct ones to display in some cases // just display those together with the correct one. // (setting it to 2 will skip some menu stills, 5 is working ok for me). m_iNrOfPicturesNotToSkip = 5; } else if (pMsg->IsType(CDVDMsg::PLAYER_SETSPEED)) { m_speed = static_cast<CDVDMsgInt*>(pMsg)->m_value; if(m_speed == DVD_PLAYSPEED_PAUSE) m_iNrOfPicturesNotToSkip = 0; } else if (pMsg->IsType(CDVDMsg::PLAYER_STARTED)) { if(m_started) m_messageParent.Put(new CDVDMsgInt(CDVDMsg::PLAYER_STARTED, DVDPLAYER_VIDEO)); } else if (pMsg->IsType(CDVDMsg::GENERAL_STREAMCHANGE)) { CDVDMsgVideoCodecChange* msg(static_cast<CDVDMsgVideoCodecChange*>(pMsg)); OpenStream(msg->m_hints, msg->m_codec); msg->m_codec = NULL; picture.iFlags &= ~DVP_FLAG_ALLOCATED; } if (pMsg->IsType(CDVDMsg::DEMUXER_PACKET)) { DemuxPacket* pPacket = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacket(); bool bPacketDrop = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacketDrop(); if (m_stalled) { CLog::Log(LOGINFO, "CDVDPlayerVideo - Stillframe left, switching to normal playback"); m_stalled = false; //don't allow the first frames after a still to be dropped //sometimes we get multiple stills (long duration frames) after each other //in normal mpegs m_iNrOfPicturesNotToSkip = 5; } else if( iDropped*frametime > DVD_MSEC_TO_TIME(100) && m_iNrOfPicturesNotToSkip == 0 ) { // if we dropped too many pictures in a row, insert a forced picture m_iNrOfPicturesNotToSkip = 1; } #ifdef PROFILE bRequestDrop = false; #else if (m_messageQueue.GetDataSize() == 0 || m_speed < 0) { bRequestDrop = false; m_iDroppedRequest = 0; m_iLateFrames = 0; } #endif // if player want's us to drop this packet, do so nomatter what if(bPacketDrop) bRequestDrop = true; // tell codec if next frame should be dropped // problem here, if one packet contains more than one frame // both frames will be dropped in that case instead of just the first // decoder still needs to provide an empty image structure, with correct flags m_pVideoCodec->SetDropState(bRequestDrop); // ask codec to do deinterlacing if possible EINTERLACEMETHOD mInt = g_settings.m_currentVideoSettings.m_InterlaceMethod; unsigned int mFilters = 0; if(mInt == VS_INTERLACEMETHOD_DEINTERLACE) mFilters = CDVDVideoCodec::FILTER_DEINTERLACE_ANY; else if(mInt == VS_INTERLACEMETHOD_DEINTERLACE_HALF) mFilters = CDVDVideoCodec::FILTER_DEINTERLACE_ANY | CDVDVideoCodec::FILTER_DEINTERLACE_HALFED; else if(mInt == VS_INTERLACEMETHOD_AUTO) mFilters = CDVDVideoCodec::FILTER_DEINTERLACE_ANY | CDVDVideoCodec::FILTER_DEINTERLACE_FLAGGED; mFilters = m_pVideoCodec->SetFilters(mFilters); int iDecoderState = m_pVideoCodec->Decode(pPacket->pData, pPacket->iSize, pPacket->dts, pPacket->pts); // buffer packets so we can recover should decoder flush for some reason if(m_pVideoCodec->GetConvergeCount() > 0) { m_packets.push_back(DVDMessageListItem(pMsg, 0)); if(m_packets.size() > m_pVideoCodec->GetConvergeCount() || m_packets.size() * frametime > DVD_SEC_TO_TIME(10)) m_packets.pop_front(); } m_videoStats.AddSampleBytes(pPacket->iSize); // assume decoder dropped a picture if it didn't give us any // picture from a demux packet, this should be reasonable // for libavformat as a demuxer as it normally packetizes // pictures when they come from demuxer if(bRequestDrop && !bPacketDrop && (iDecoderState & VC_BUFFER) && !(iDecoderState & VC_PICTURE)) { m_iDroppedFrames++; iDropped++; } // loop while no error while (!m_bStop) { // if decoder was flushed, we need to seek back again to resume rendering if (iDecoderState & VC_FLUSHED) { CLog::Log(LOGDEBUG, "CDVDPlayerVideo - video decoder was flushed"); while(!m_packets.empty()) { CDVDMsgDemuxerPacket* msg = (CDVDMsgDemuxerPacket*)m_packets.front().message->Acquire(); m_packets.pop_front(); // all packets except the last one should be dropped // if prio packets and current packet should be dropped, this is likely a new reset msg->m_drop = !m_packets.empty() || (iPriority > 0 && bPacketDrop); m_messageQueue.Put(msg, iPriority + 10); } m_pVideoCodec->Reset(); m_packets.clear(); break; } // if decoder had an error, tell it to reset to avoid more problems if (iDecoderState & VC_ERROR) { CLog::Log(LOGDEBUG, "CDVDPlayerVideo - video decoder returned error"); break; } // check for a new picture if (iDecoderState & VC_PICTURE) { // try to retrieve the picture (should never fail!), unless there is a demuxer bug ofcours m_pVideoCodec->ClearPicture(&picture); if (m_pVideoCodec->GetPicture(&picture)) { sPostProcessType.clear(); picture.iGroupId = pPacket->iGroupId; if(picture.iDuration == 0.0) picture.iDuration = frametime; if(bPacketDrop) picture.iFlags |= DVP_FLAG_DROPPED; if (m_iNrOfPicturesNotToSkip > 0) { picture.iFlags |= DVP_FLAG_NOSKIP; m_iNrOfPicturesNotToSkip--; } // validate picture timing, // if both dts/pts invalid, use pts calulated from picture.iDuration // if pts invalid use dts, else use picture.pts as passed if (picture.dts == DVD_NOPTS_VALUE && picture.pts == DVD_NOPTS_VALUE) picture.pts = pts; else if (picture.pts == DVD_NOPTS_VALUE) picture.pts = picture.dts; /* use forced aspect if any */ if( m_fForcedAspectRatio != 0.0f ) picture.iDisplayWidth = (int) (picture.iDisplayHeight * m_fForcedAspectRatio); //Deinterlace if codec said format was interlaced or if we have selected we want to deinterlace //this video if(!(mFilters & CDVDVideoCodec::FILTER_DEINTERLACE_ANY)) { if((mInt == VS_INTERLACEMETHOD_DEINTERLACE) || (mInt == VS_INTERLACEMETHOD_AUTO && (picture.iFlags & DVP_FLAG_INTERLACED) && !g_renderManager.Supports(VS_INTERLACEMETHOD_RENDER_BOB))) { if (!sPostProcessType.empty()) sPostProcessType += ","; sPostProcessType += g_advancedSettings.m_videoPPFFmpegDeint; } } if (g_settings.m_currentVideoSettings.m_PostProcess) { if (!sPostProcessType.empty()) sPostProcessType += ","; // This is what mplayer uses for its "high-quality filter combination" sPostProcessType += g_advancedSettings.m_videoPPFFmpegPostProc; } if (!sPostProcessType.empty()) { mPostProcess.SetType(sPostProcessType); if (mPostProcess.Process(&picture)) mPostProcess.GetPicture(&picture); } /* if frame has a pts (usually originiating from demux packet), use that */ if(picture.pts != DVD_NOPTS_VALUE) { if(pulldown.enabled()) picture.pts += pulldown.pts(); pts = picture.pts; } if(pulldown.enabled()) { picture.iDuration = pulldown.dur(); pulldown.next(); } if (picture.iRepeatPicture) picture.iDuration *= picture.iRepeatPicture + 1; #if 1 int iResult = OutputPicture(&picture, pts); #elif 0 // testing NV12 rendering functions DVDVideoPicture* pTempNV12Picture = CDVDCodecUtils::ConvertToNV12Picture(&picture); int iResult = OutputPicture(pTempNV12Picture, pts); CDVDCodecUtils::FreePicture(pTempNV12Picture); #elif 0 // testing YUY2 or UYVY rendering functions // WARNING: since this scales a full YV12 frame, weaving artifacts will show on interlaced content // even with the deinterlacer on DVDVideoPicture* pTempYUVPackedPicture = CDVDCodecUtils::ConvertToYUV422PackedPicture(&picture, DVDVideoPicture::FMT_UYVY); //DVDVideoPicture* pTempYUVPackedPicture = CDVDCodecUtils::ConvertToYUV422PackedPicture(&picture, DVDVideoPicture::FMT_YUY2); int iResult = OutputPicture(pTempYUVPackedPicture, pts); CDVDCodecUtils::FreePicture(pTempYUVPackedPicture); #endif if(m_started == false) { m_codecname = m_pVideoCodec->GetName(); m_started = true; m_messageParent.Put(new CDVDMsgInt(CDVDMsg::PLAYER_STARTED, DVDPLAYER_VIDEO)); } // guess next frame pts. iDuration is always valid if (m_speed != 0) pts += picture.iDuration * m_speed / abs(m_speed); if( iResult & EOS_ABORT ) { //if we break here and we directly try to decode again wihout //flushing the video codec things break for some reason //i think the decoder (libmpeg2 atleast) still has a pointer //to the data, and when the packet is freed that will fail. iDecoderState = m_pVideoCodec->Decode(NULL, 0, DVD_NOPTS_VALUE, DVD_NOPTS_VALUE); break; } if( (iResult & EOS_DROPPED) && !bPacketDrop ) { m_iDroppedFrames++; iDropped++; } else iDropped = 0; bRequestDrop = (iResult & EOS_VERYLATE) == EOS_VERYLATE; } else { CLog::Log(LOGWARNING, "Decoder Error getting videoPicture."); m_pVideoCodec->Reset(); } } /* if (iDecoderState & VC_USERDATA) { // found some userdata while decoding a frame // could be closed captioning DVDVideoUserData videoUserData; if (m_pVideoCodec->GetUserData(&videoUserData)) { ProcessVideoUserData(&videoUserData, pts); } } */ // if the decoder needs more data, we just break this loop // and try to get more data from the videoQueue if (iDecoderState & VC_BUFFER) break; // the decoder didn't need more data, flush the remaning buffer iDecoderState = m_pVideoCodec->Decode(NULL, 0, DVD_NOPTS_VALUE, DVD_NOPTS_VALUE); } } // all data is used by the decoder, we can safely free it now pMsg->Release(); } }
bool CWIN32Util::XBMCShellExecute(const CStdString &strPath, bool bWaitForScriptExit) { CStdString strCommand = strPath; CStdString strExe = strPath; CStdString strParams; CStdString strWorkingDir; StringUtils::Trim(strCommand); if (strCommand.empty()) { return false; } size_t iIndex = std::string::npos; char split = ' '; if (strCommand[0] == '\"') { split = '\"'; } iIndex = strCommand.find(split, 1); if (iIndex != std::string::npos) { strExe = strCommand.substr(0, iIndex + 1); strParams = strCommand.substr(iIndex + 1); } StringUtils::Replace(strExe, "\"", ""); strWorkingDir = strExe; iIndex = strWorkingDir.rfind('\\'); if(iIndex != std::string::npos) { strWorkingDir[iIndex+1] = '\0'; } CStdStringW WstrExe, WstrParams, WstrWorkingDir; g_charsetConverter.utf8ToW(strExe, WstrExe); g_charsetConverter.utf8ToW(strParams, WstrParams); g_charsetConverter.utf8ToW(strWorkingDir, WstrWorkingDir); bool ret; SHELLEXECUTEINFOW ShExecInfo = {0}; ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFOW); ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; ShExecInfo.hwnd = NULL; ShExecInfo.lpVerb = NULL; ShExecInfo.lpFile = WstrExe.c_str(); ShExecInfo.lpParameters = WstrParams.c_str(); ShExecInfo.lpDirectory = WstrWorkingDir.c_str(); ShExecInfo.nShow = SW_SHOW; ShExecInfo.hInstApp = NULL; g_windowHelper.StopThread(); LockSetForegroundWindow(LSFW_UNLOCK); ShowWindow(g_hWnd,SW_MINIMIZE); ret = ShellExecuteExW(&ShExecInfo) == TRUE; g_windowHelper.SetHANDLE(ShExecInfo.hProcess); // ShellExecute doesn't return the window of the started process // we need to gather it from somewhere to allow switch back to XBMC // when a program is minimized instead of stopped. //g_windowHelper.SetHWND(ShExecInfo.hwnd); g_windowHelper.Create(); if(bWaitForScriptExit) { // Todo: Pause music and video playback WaitForSingleObject(ShExecInfo.hProcess,INFINITE); } return ret; }
void CButtonTranslator::MapWindowActions(TiXmlNode *pWindow, int windowID) { if (!pWindow || windowID == WINDOW_INVALID) return; TiXmlNode* pDevice; const char* types[] = {"gamepad", "remote", "universalremote", "keyboard", "mouse", "appcommand", NULL}; for (int i = 0; types[i]; ++i) { CStdString type(types[i]); if (HasDeviceType(pWindow, type)) { pDevice = pWindow->FirstChild(type); TiXmlElement *pDeviceElement = pDevice->ToElement(); //check if exists, if not use "default" CStdString deviceName = pDeviceElement->Attribute("name"); if (deviceName.empty()) deviceName = "default"; std::map<CStdString, std::map<int, buttonMap> >::iterator deviceMapIt = deviceMappings.find(deviceName); if (deviceMapIt == deviceMappings.end()) { //First time encountering this device, lets initialise the buttonMap for it. deviceMapIt = deviceMappings.insert(pair<CStdString, std::map<int, buttonMap> >(deviceName, std::map<int, buttonMap>())).first; } std::map<int, buttonMap>::iterator windowIt = deviceMapIt->second.find(windowID); if (windowIt == deviceMapIt->second.end()) { //add it now windowIt = deviceMapIt->second.insert(pair<int, buttonMap>(windowID, buttonMap())).first; } buttonMap& windowMap = windowIt->second; TiXmlElement *pButton = pDevice->FirstChildElement(); while (pButton) { uint32_t buttonCode=0; if (type == "gamepad") buttonCode = TranslateGamepadString(pButton->Value()); else if (type == "remote") buttonCode = TranslateRemoteString(pButton->Value()); else if (type == "universalremote") buttonCode = TranslateUniversalRemoteString(pButton->Value()); else if (type == "keyboard") buttonCode = TranslateKeyboardButton(pButton); else if (type == "mouse") buttonCode = TranslateMouseCommand(pButton->Value()); else if (type == "appcommand") buttonCode = TranslateAppCommand(pButton->Value()); if (buttonCode && pButton->FirstChild()) MapAction(buttonCode, pButton->FirstChild()->Value(), windowMap); pButton = pButton->NextSiblingElement(); } } } #if defined(HAS_SDL_JOYSTICK) || defined(HAS_EVENT_SERVER) if ((pDevice = pWindow->FirstChild("joystick")) != NULL) { // map joystick actions while (pDevice) { MapJoystickActions(windowID, pDevice); pDevice = pDevice->NextSibling("joystick"); } } #endif }
LRESULT CALLBACK CWinEventsWin32::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { XBMC_Event newEvent; ZeroMemory(&newEvent, sizeof(newEvent)); static HDEVNOTIFY hDeviceNotify; if (uMsg == WM_CREATE) { g_hWnd = hWnd; SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG)(((LPCREATESTRUCT)lParam)->lpCreateParams)); DIB_InitOSKeymap(); g_uQueryCancelAutoPlay = RegisterWindowMessage(TEXT("QueryCancelAutoPlay")); shcne.pidl = NULL; shcne.fRecursive = TRUE; long fEvents = SHCNE_DRIVEADD | SHCNE_DRIVEREMOVED | SHCNE_MEDIAREMOVED | SHCNE_MEDIAINSERTED; SHChangeNotifyRegister(hWnd, SHCNRF_ShellLevel | SHCNRF_NewDelivery, fEvents, WM_MEDIA_CHANGE, 1, &shcne); RegisterDeviceInterfaceToHwnd(USB_HID_GUID, hWnd, &hDeviceNotify); return 0; } if (uMsg == WM_DESTROY) g_hWnd = NULL; m_pEventFunc = (PHANDLE_EVENT_FUNC)GetWindowLongPtr(hWnd, GWLP_USERDATA); if (!m_pEventFunc) return DefWindowProc(hWnd, uMsg, wParam, lParam); if(g_uQueryCancelAutoPlay != 0 && uMsg == g_uQueryCancelAutoPlay) return S_FALSE; switch (uMsg) { case WM_CLOSE: case WM_QUIT: case WM_DESTROY: if (hDeviceNotify) UnregisterDeviceNotification(hDeviceNotify); newEvent.type = XBMC_QUIT; m_pEventFunc(newEvent); break; case WM_SHOWWINDOW: { bool active = g_application.GetRenderGUI(); g_application.SetRenderGUI(wParam != 0); if (g_application.GetRenderGUI() != active) g_Windowing.NotifyAppActiveChange(g_application.GetRenderGUI()); CLog::Log(LOGDEBUG, __FUNCTION__"Window is %s", g_application.GetRenderGUI() ? "shown" : "hidden"); } break; case WM_ACTIVATE: { if( WA_INACTIVE != wParam ) g_Joystick.Reinitialize(); bool active = g_application.GetRenderGUI(); if (HIWORD(wParam)) { g_application.SetRenderGUI(false); } else { WINDOWPLACEMENT lpwndpl; lpwndpl.length = sizeof(lpwndpl); if (LOWORD(wParam) != WA_INACTIVE) { if (GetWindowPlacement(hWnd, &lpwndpl)) g_application.SetRenderGUI(lpwndpl.showCmd != SW_HIDE); } else { g_application.SetRenderGUI(g_Windowing.WindowedMode()); } } if (g_application.GetRenderGUI() != active) g_Windowing.NotifyAppActiveChange(g_application.GetRenderGUI()); CLog::Log(LOGDEBUG, __FUNCTION__"Window is %s", g_application.GetRenderGUI() ? "active" : "inactive"); } break; case WM_SETFOCUS: case WM_KILLFOCUS: g_application.m_AppFocused = uMsg == WM_SETFOCUS; g_Windowing.NotifyAppFocusChange(g_application.m_AppFocused); if (uMsg == WM_KILLFOCUS) { CStdString procfile; if (CWIN32Util::GetFocussedProcess(procfile)) CLog::Log(LOGDEBUG, __FUNCTION__": Focus switched to process %s", procfile.c_str()); } break; /* needs to be reviewed after frodo. we reset the system idle timer and the display timer directly now (see m_screenSaverTimer). case WM_SYSCOMMAND: switch( wParam&0xFFF0 ) { case SC_MONITORPOWER: if (g_application.IsPlaying() || g_application.IsPaused()) return 0; else if(CSettings::Get().GetInt("powermanagement.displaysoff") == 0) return 0; break; case SC_SCREENSAVE: return 0; } break;*/ case WM_SYSKEYDOWN: switch (wParam) { case VK_F4: //alt-f4, default event quit. return(DefWindowProc(hWnd, uMsg, wParam, lParam)); case VK_RETURN: //alt-return if ((lParam & REPEATED_KEYMASK) == 0) g_graphicsContext.ToggleFullScreenRoot(); return 0; } //deliberate fallthrough case WM_KEYDOWN: { switch (wParam) { case VK_V: if(GetKeyState(VK_CONTROL) & 0x8000) { // CTRL+V if(OpenClipboard(NULL)) { CStdString strtext; HANDLE htext = GetClipboardData(CF_UNICODETEXT); CStdStringW strwtext = (WCHAR*)htext; g_charsetConverter.wToUTF8(strwtext, strtext); if(!strtext.empty()) { CGUIMessage msg(GUI_MSG_INPUT_TEXT, 0, 0); msg.SetLabel(strtext); g_windowManager.SendMessage(msg, g_windowManager.GetFocusedWindow()); } CloseClipboard(); return(0); } } break; case VK_CONTROL: if ( lParam & EXTENDED_KEYMASK ) wParam = VK_RCONTROL; else wParam = VK_LCONTROL; break; case VK_SHIFT: /* EXTENDED trick doesn't work here */ if (GetKeyState(VK_LSHIFT) & 0x8000) wParam = VK_LSHIFT; else if (GetKeyState(VK_RSHIFT) & 0x8000) wParam = VK_RSHIFT; break; case VK_MENU: if ( lParam & EXTENDED_KEYMASK ) wParam = VK_RMENU; else wParam = VK_LMENU; break; } XBMC_keysym keysym; TranslateKey(wParam, HIWORD(lParam), &keysym, 1); newEvent.type = XBMC_KEYDOWN; newEvent.key.keysym = keysym; m_pEventFunc(newEvent); } return(0); case WM_SYSKEYUP: case WM_KEYUP: { switch (wParam) { case VK_CONTROL: if ( lParam&EXTENDED_KEYMASK ) wParam = VK_RCONTROL; else wParam = VK_LCONTROL; break; case VK_SHIFT: { uint32_t scanCodeL = MapVirtualKey(VK_LSHIFT, MAPVK_VK_TO_VSC); uint32_t scanCodeR = MapVirtualKey(VK_RSHIFT, MAPVK_VK_TO_VSC); uint32_t keyCode = (uint32_t)((lParam & 0xFF0000) >> 16); if (keyCode == scanCodeL) wParam = VK_LSHIFT; else if (keyCode == scanCodeR) wParam = VK_RSHIFT; } break; case VK_MENU: if ( lParam&EXTENDED_KEYMASK ) wParam = VK_RMENU; else wParam = VK_LMENU; break; } XBMC_keysym keysym; TranslateKey(wParam, HIWORD(lParam), &keysym, 1); if (wParam == VK_SNAPSHOT) newEvent.type = XBMC_KEYDOWN; else newEvent.type = XBMC_KEYUP; newEvent.key.keysym = keysym; m_pEventFunc(newEvent); } return(0); case WM_APPCOMMAND: // MULTIMEDIA keys are mapped to APPCOMMANDS { CLog::Log(LOGDEBUG, "WinEventsWin32.cpp: APPCOMMAND %d", GET_APPCOMMAND_LPARAM(lParam)); newEvent.appcommand.type = XBMC_APPCOMMAND; newEvent.appcommand.action = GET_APPCOMMAND_LPARAM(lParam); if (m_pEventFunc(newEvent)) return TRUE; else return DefWindowProc(hWnd, uMsg, wParam, lParam); } case WM_GESTURENOTIFY: { OnGestureNotify(hWnd, lParam); return DefWindowProc(hWnd, WM_GESTURENOTIFY, wParam, lParam); } case WM_GESTURE: { OnGesture(hWnd, lParam); return 0; } case WM_SYSCHAR: if (wParam == VK_RETURN) //stop system beep on alt-return return 0; break; case WM_SETCURSOR: if (HTCLIENT != LOWORD(lParam)) g_Windowing.ShowOSMouse(true); break; case WM_MOUSEMOVE: newEvent.type = XBMC_MOUSEMOTION; newEvent.motion.x = GET_X_LPARAM(lParam); newEvent.motion.y = GET_Y_LPARAM(lParam); newEvent.motion.state = 0; m_pEventFunc(newEvent); return(0); case WM_LBUTTONDOWN: case WM_MBUTTONDOWN: case WM_RBUTTONDOWN: newEvent.type = XBMC_MOUSEBUTTONDOWN; newEvent.button.state = XBMC_PRESSED; newEvent.button.x = GET_X_LPARAM(lParam); newEvent.button.y = GET_Y_LPARAM(lParam); newEvent.button.button = 0; if (uMsg == WM_LBUTTONDOWN) newEvent.button.button = XBMC_BUTTON_LEFT; else if (uMsg == WM_MBUTTONDOWN) newEvent.button.button = XBMC_BUTTON_MIDDLE; else if (uMsg == WM_RBUTTONDOWN) newEvent.button.button = XBMC_BUTTON_RIGHT; m_pEventFunc(newEvent); return(0); case WM_LBUTTONUP: case WM_MBUTTONUP: case WM_RBUTTONUP: newEvent.type = XBMC_MOUSEBUTTONUP; newEvent.button.state = XBMC_RELEASED; newEvent.button.x = GET_X_LPARAM(lParam); newEvent.button.y = GET_Y_LPARAM(lParam); newEvent.button.button = 0; if (uMsg == WM_LBUTTONUP) newEvent.button.button = XBMC_BUTTON_LEFT; else if (uMsg == WM_MBUTTONUP) newEvent.button.button = XBMC_BUTTON_MIDDLE; else if (uMsg == WM_RBUTTONUP) newEvent.button.button = XBMC_BUTTON_RIGHT; m_pEventFunc(newEvent); return(0); case WM_MOUSEWHEEL: { // SDL, which our events system is based off, sends a MOUSEBUTTONDOWN message // followed by a MOUSEBUTTONUP message. As this is a momentary event, we just // react on the MOUSEBUTTONUP message, resetting the state after processing. newEvent.type = XBMC_MOUSEBUTTONDOWN; newEvent.button.state = XBMC_PRESSED; // the coordinates in WM_MOUSEWHEEL are screen, not client coordinates POINT point; point.x = GET_X_LPARAM(lParam); point.y = GET_Y_LPARAM(lParam); WindowFromScreenCoords(hWnd, &point); newEvent.button.x = (uint16_t)point.x; newEvent.button.y = (uint16_t)point.y; newEvent.button.button = GET_Y_LPARAM(wParam) > 0 ? XBMC_BUTTON_WHEELUP : XBMC_BUTTON_WHEELDOWN; m_pEventFunc(newEvent); newEvent.type = XBMC_MOUSEBUTTONUP; newEvent.button.state = XBMC_RELEASED; m_pEventFunc(newEvent); } return(0); case WM_SIZE: newEvent.type = XBMC_VIDEORESIZE; newEvent.resize.w = GET_X_LPARAM(lParam); newEvent.resize.h = GET_Y_LPARAM(lParam); CLog::Log(LOGDEBUG, __FUNCTION__": window resize event"); if (!g_Windowing.IsAlteringWindow() && newEvent.resize.w > 0 && newEvent.resize.h > 0) m_pEventFunc(newEvent); return(0); case WM_MOVE: newEvent.type = XBMC_VIDEOMOVE; newEvent.move.x = GET_X_LPARAM(lParam); newEvent.move.y = GET_Y_LPARAM(lParam); CLog::Log(LOGDEBUG, __FUNCTION__": window move event"); if (!g_Windowing.IsAlteringWindow()) m_pEventFunc(newEvent); return(0); case WM_MEDIA_CHANGE: { // This event detects media changes of usb, sd card and optical media. // It only works if the explorer.exe process is started. Because this // isn't the case for all setups we use WM_DEVICECHANGE for usb and // optical media because this event is also triggered without the // explorer process. Since WM_DEVICECHANGE doesn't detect sd card changes // we still use this event only for sd. long lEvent; PIDLIST_ABSOLUTE *ppidl; HANDLE hLock = SHChangeNotification_Lock((HANDLE)wParam, (DWORD)lParam, &ppidl, &lEvent); if (hLock) { char drivePath[MAX_PATH+1]; if (!SHGetPathFromIDList(ppidl[0], drivePath)) break; switch(lEvent) { case SHCNE_DRIVEADD: case SHCNE_MEDIAINSERTED: if (GetDriveType(drivePath) != DRIVE_CDROM) { CLog::Log(LOGDEBUG, __FUNCTION__": Drive %s Media has arrived.", drivePath); CWin32StorageProvider::SetEvent(); } break; case SHCNE_DRIVEREMOVED: case SHCNE_MEDIAREMOVED: if (GetDriveType(drivePath) != DRIVE_CDROM) { CLog::Log(LOGDEBUG, __FUNCTION__": Drive %s Media was removed.", drivePath); CWin32StorageProvider::SetEvent(); } break; } SHChangeNotification_Unlock(hLock); } break; } case WM_POWERBROADCAST: if (wParam==PBT_APMSUSPEND) { CLog::Log(LOGDEBUG,"WM_POWERBROADCAST: PBT_APMSUSPEND event was sent"); CWin32PowerSyscall::SetOnSuspend(); } else if(wParam==PBT_APMRESUMEAUTOMATIC) { CLog::Log(LOGDEBUG,"WM_POWERBROADCAST: PBT_APMRESUMEAUTOMATIC event was sent"); CWin32PowerSyscall::SetOnResume(); } break; case WM_DEVICECHANGE: { switch(wParam) { case DBT_DEVNODES_CHANGED: g_peripherals.TriggerDeviceScan(PERIPHERAL_BUS_USB); break; case DBT_DEVICEARRIVAL: case DBT_DEVICEREMOVECOMPLETE: if (((_DEV_BROADCAST_HEADER*) lParam)->dbcd_devicetype == DBT_DEVTYP_DEVICEINTERFACE) { g_peripherals.TriggerDeviceScan(PERIPHERAL_BUS_USB); g_Joystick.Reinitialize(); } // check if an usb or optical media was inserted or removed if (((_DEV_BROADCAST_HEADER*) lParam)->dbcd_devicetype == DBT_DEVTYP_VOLUME) { PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)((_DEV_BROADCAST_HEADER*) lParam); // optical medium if (lpdbv -> dbcv_flags & DBTF_MEDIA) { CStdString strdrive; strdrive.Format("%c:\\", CWIN32Util::FirstDriveFromMask(lpdbv ->dbcv_unitmask)); if(wParam == DBT_DEVICEARRIVAL) { CLog::Log(LOGDEBUG, __FUNCTION__": Drive %s Media has arrived.", strdrive.c_str()); CJobManager::GetInstance().AddJob(new CDetectDisc(strdrive, true), NULL); } else { CLog::Log(LOGDEBUG, __FUNCTION__": Drive %s Media was removed.", strdrive.c_str()); CMediaSource share; share.strPath = strdrive; share.strName = share.strPath; g_mediaManager.RemoveAutoSource(share); } } else CWin32StorageProvider::SetEvent(); } } break; } case WM_PAINT: //some other app has painted over our window, mark everything as dirty g_windowManager.MarkDirty(); break; case BONJOUR_EVENT: CZeroconf::GetInstance()->ProcessResults(); break; case BONJOUR_BROWSER_EVENT: CZeroconfBrowser::GetInstance()->ProcessResults(); break; } return(DefWindowProc(hWnd, uMsg, wParam, lParam)); }