From 6d08978f94856b2c7599ebe3814ca4f7868e4e29 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 22 Aug 2012 18:17:49 -0400 Subject: [PATCH 001/180] [aml] add makefile for building against buildroot --- tools/amlogic/depends/xbmc/Makefile | 5 ++ tools/amlogic/depends/xbmc/buildroot-sdk.mk | 54 +++++++++++++++++++++ tools/amlogic/depends/xbmc/xbmc.mk | 21 ++++++++ 3 files changed, 80 insertions(+) create mode 100644 tools/amlogic/depends/xbmc/Makefile create mode 100644 tools/amlogic/depends/xbmc/buildroot-sdk.mk create mode 100644 tools/amlogic/depends/xbmc/xbmc.mk diff --git a/tools/amlogic/depends/xbmc/Makefile b/tools/amlogic/depends/xbmc/Makefile new file mode 100644 index 0000000000000..5f8341ba4056f --- /dev/null +++ b/tools/amlogic/depends/xbmc/Makefile @@ -0,0 +1,5 @@ +include ../../Makefile.include +export BUILDROOT +export SOURCE=$(CURDIR)/../../../.. +all: + $(MAKE) -I $(BUILDROOT) -f xbmc.mk \ No newline at end of file diff --git a/tools/amlogic/depends/xbmc/buildroot-sdk.mk b/tools/amlogic/depends/xbmc/buildroot-sdk.mk new file mode 100644 index 0000000000000..1e3509116c594 --- /dev/null +++ b/tools/amlogic/depends/xbmc/buildroot-sdk.mk @@ -0,0 +1,54 @@ +qstrip=$(strip $(subst ",,$(1)))#")) +-include $(BUILDROOT)/.config +-include $(BUILDROOT)/toolchain/gcc/Makefile.in +BASE_DIR=$(BUILDROOT)/output +TOOLCHAIN_EXTERNAL_DIR=$(BASE_DIR)/external-toolchain +ARCH=$(call qstrip,$(BR2_ARCH)) +HOST_DIR=$(call qstrip,$(BR2_HOST_DIR)) +HOST=$(call qstrip,$(BR2_TOOLCHAIN_EXTERNAL_PREFIX)) +PKG_CONFIG_HOST_BINARY=$(HOST_DIR)/usr/bin/pkg-config + +ifndef HOSTAR +HOSTAR:=ar +endif +ifndef HOSTAS +HOSTAS:=as +endif +ifndef HOSTCC +HOSTCC:=gcc +HOSTCC:=$(shell which $(HOSTCC) || type -p $(HOSTCC) || echo gcc) +HOSTCC_NOCCACHE:=$(HOSTCC) +endif +ifndef HOSTCXX +HOSTCXX:=g++ +HOSTCXX:=$(shell which $(HOSTCXX) || type -p $(HOSTCXX) || echo g++) +HOSTCXX_NOCCACHE:=$(HOSTCXX) +endif +ifndef HOSTFC +HOSTFC:=gfortran +endif +ifndef HOSTCPP +HOSTCPP:=cpp +endif +ifndef HOSTLD +HOSTLD:=ld +endif +ifndef HOSTLN +HOSTLN:=ln +endif +ifndef HOSTNM +HOSTNM:=nm +endif +HOSTAR:=$(shell which $(HOSTAR) || type -p $(HOSTAR) || echo ar) +HOSTAS:=$(shell which $(HOSTAS) || type -p $(HOSTAS) || echo as) +HOSTFC:=$(shell which $(HOSTLD) || type -p $(HOSTLD) || echo || which g77 || type -p g77 || echo gfortran) +HOSTCPP:=$(shell which $(HOSTCPP) || type -p $(HOSTCPP) || echo cpp) +HOSTLD:=$(shell which $(HOSTLD) || type -p $(HOSTLD) || echo ld) +HOSTLN:=$(shell which $(HOSTLN) || type -p $(HOSTLN) || echo ln) +HOSTNM:=$(shell which $(HOSTNM) || type -p $(HOSTNM) || echo nm) + +all: +-include $(BUILDROOT)/package/Makefile.in +-include $(BUILDROOT)/package/Makefile.autotools.in +-include $(BUILDROOT)/package/Makefile.cmake.in +-include $(BUILDROOT)/package/Makefile.package.in diff --git a/tools/amlogic/depends/xbmc/xbmc.mk b/tools/amlogic/depends/xbmc/xbmc.mk new file mode 100644 index 0000000000000..da2ae74b1bc6e --- /dev/null +++ b/tools/amlogic/depends/xbmc/xbmc.mk @@ -0,0 +1,21 @@ +all: $(SOURCE)/xbmc.bin + +include buildroot-sdk.mk +-include $(BUILDROOT)/package/python/python.mk +-include $(BUILDROOT)/package/thirdparty/xbmc/xbmc.mk +$(SOURCE)/xbmc.bin: $(SOURCE)/Makefile + cd $(SOURCE); $(MAKE) + +$(SOURCE)/Makefile: $(SOURCE)/configure + cd $(SOURCE); $(TARGET_CONFIGURE_OPTS) $(TARGET_CONFIGURE_ARGS) $(XBMC_CONF_ENV) \ + ./configure --target=$(GNU_TARGET_NAME) --host=$(GNU_TARGET_NAME) --build=$(GNU_HOST_NAME) \ + --prefix=/usr --exec-prefix=/usr --sysconfdir=/etc $(XBMC_CONF_OPT) --disable-external-ffmpeg + +$(SOURCE)/configure: $(BUILDROOT)/package/thirdparty/xbmc/xbmc.mk $(GCC) + cd $(SOURCE); ./bootstrap + +$(GCC): + $(error gcc does not exist. Have you built Buildroot?) + +$(BUILDROOT)/package/thirdparty/xbmc/xbmc.mk: + $(error BUILDROOT must be defined in buildroot-sdk.mk) From d6780d93391250ac40cc81fdb1dd54603ddae41f Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 22 Aug 2012 18:03:22 -0400 Subject: [PATCH 002/180] [aml] silence compiler spew from gcc 4.4 --- configure.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure.in b/configure.in index 476931559a212..67543121046e9 100644 --- a/configure.in +++ b/configure.in @@ -626,6 +626,8 @@ case $host in ARCH="arm" use_arch="arm" AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_LINUX") + CFLAGS="$CFLAGS -Wno-psabi -Wa,-mno-warn-deprecated" + CXXFLAGS="$CXXFLAGS -Wno-psabi -Wa,-mno-warn-deprecated" ;; arm*-*linux-android*) target_platform=target_android From 2acc323b3aec3cb4b09eedcf6444989f1947f428 Mon Sep 17 00:00:00 2001 From: theuni Date: Wed, 12 Oct 2011 17:56:18 -0400 Subject: [PATCH 003/180] [aml] dvdnav: fix cross-compile remove cflags that aren't safe --- lib/libdvd/libdvdnav/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/libdvd/libdvdnav/Makefile b/lib/libdvd/libdvdnav/Makefile index 85245b7a4d764..8b743463d7397 100644 --- a/lib/libdvd/libdvdnav/Makefile +++ b/lib/libdvd/libdvdnav/Makefile @@ -21,7 +21,7 @@ CFLAGS += -DHAVE_CONFIG_H -DHAVE_DLFCN_H L=libdvdnav MINI_L=libdvdnavmini -CFLAGS += $(DVDREAD_CFLAGS) +#CFLAGS += $(DVDREAD_CFLAGS) LIB = $(L).a SHLIB = $(L).so From e20b663738ff62f04c71eeb053b6a9556cd0cf1a Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 22 Aug 2012 20:37:35 -0400 Subject: [PATCH 004/180] [aml] don't define byte. it interferes with kernel headers --- xbmc/filesystem/ISOFile.cpp | 4 ++-- xbmc/filesystem/iso9660.cpp | 8 ++++---- xbmc/filesystem/iso9660.h | 4 ++-- xbmc/linux/PlatformDefs.h | 1 - 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/xbmc/filesystem/ISOFile.cpp b/xbmc/filesystem/ISOFile.cpp index 9baa95d81e01a..52a556cc85c71 100644 --- a/xbmc/filesystem/ISOFile.cpp +++ b/xbmc/filesystem/ISOFile.cpp @@ -87,7 +87,7 @@ unsigned int CISOFile::Read(void *lpBuf, int64_t uiBufSize) if (m_cache.getMaxWriteSize() > 5000) { - byte buffer[5000]; + BYTE buffer[5000]; long lBytesRead = m_isoReader.ReadFile( m_hFile, buffer, sizeof(buffer)); if (lBytesRead > 0) m_cache.WriteData((char*)buffer, lBytesRead); @@ -97,7 +97,7 @@ unsigned int CISOFile::Read(void *lpBuf, int64_t uiBufSize) } return lTotalBytesRead; } - int iResult = m_isoReader.ReadFile( m_hFile, (byte*)pData, (long)uiBufSize); + int iResult = m_isoReader.ReadFile( m_hFile, (BYTE*)pData, (long)uiBufSize); if (iResult == -1) return 0; return iResult; diff --git a/xbmc/filesystem/iso9660.cpp b/xbmc/filesystem/iso9660.cpp index 7f2ad2f8dd0d2..d2417cd8901ad 100644 --- a/xbmc/filesystem/iso9660.cpp +++ b/xbmc/filesystem/iso9660.cpp @@ -752,7 +752,7 @@ HANDLE iso9660::OpenFile(const char *filename) pContext->m_dwCurrentBlock = m_searchpointer->Location; pContext->m_dwFileSize = m_info.curr_filesize = fileinfo.nFileSizeLow; - pContext->m_pBuffer = new byte[CIRC_BUFFER_SIZE * BUFFER_SIZE]; + pContext->m_pBuffer = new BYTE[CIRC_BUFFER_SIZE * BUFFER_SIZE]; pContext->m_dwStartBlock = pContext->m_dwCurrentBlock; pContext->m_dwFilePos = 0; pContext->m_dwCircBuffBegin = 0; @@ -791,7 +791,7 @@ void iso9660::CloseFile(HANDLE hFile) FreeFileContext(hFile); } //************************************************************************************ -bool iso9660::ReadSectorFromCache(iso9660::isofile* pContext, DWORD sector, byte** ppBuffer) +bool iso9660::ReadSectorFromCache(iso9660::isofile* pContext, DWORD sector, BYTE** ppBuffer) { DWORD StartSectorInCircBuff = pContext->m_dwCircBuffSectorStart; @@ -891,7 +891,7 @@ void iso9660::ReleaseSectorFromCache(iso9660::isofile* pContext, DWORD sector) } } //************************************************************************************ -long iso9660::ReadFile(HANDLE hFile, byte *pBuffer, long lSize) +long iso9660::ReadFile(HANDLE hFile, BYTE *pBuffer, long lSize) { bool bError; long iBytesRead = 0; @@ -912,7 +912,7 @@ long iso9660::ReadFile(HANDLE hFile, byte *pBuffer, long lSize) //sprintf(szBuf,"pos:%i cblk:%i sblk:%i off:%i",(long)m_dwFilePos, (long)m_dwCurrentBlock,(long)m_dwStartBlock,(long)iOffsetInBuffer); //DBG(szBuf); - byte* pSector; + BYTE* pSector; bError = !ReadSectorFromCache(pContext, pContext->m_dwCurrentBlock, &pSector); if (!bError) { diff --git a/xbmc/filesystem/iso9660.h b/xbmc/filesystem/iso9660.h index e2989c8dfb787..bd3dbbc2000ca 100644 --- a/xbmc/filesystem/iso9660.h +++ b/xbmc/filesystem/iso9660.h @@ -185,7 +185,7 @@ class iso9660 int64_t GetFilePosition(HANDLE hFile); int64_t Seek(HANDLE hFile, int64_t lOffset, int whence); HANDLE OpenFile( const char* filename ); - long ReadFile(HANDLE fd, byte *pBuffer, long lSize); + long ReadFile(HANDLE fd, BYTE *pBuffer, long lSize); void CloseFile(HANDLE hFile); void Reset(); void Scan(); @@ -196,7 +196,7 @@ class iso9660 struct iso_dirtree* ReadRecursiveDirFromSector( DWORD sector, const char * ); struct iso_dirtree* FindFolder( char *Folder ); std::string GetThinText(BYTE* strTxt, int iLen ); - bool ReadSectorFromCache(iso9660::isofile* pContext, DWORD sector, byte** ppBuffer); + bool ReadSectorFromCache(iso9660::isofile* pContext, DWORD sector, BYTE** ppBuffer); void ReleaseSectorFromCache(iso9660::isofile* pContext, DWORD sector); const std::string ParseName(struct iso9660_Directory& isodir); HANDLE AllocFileContext(); diff --git a/xbmc/linux/PlatformDefs.h b/xbmc/linux/PlatformDefs.h index a66ef0adee49e..07f91e1bba67e 100644 --- a/xbmc/linux/PlatformDefs.h +++ b/xbmc/linux/PlatformDefs.h @@ -155,7 +155,6 @@ #define ZeroMemory(dst,size) memset(dst, 0, size) #define VOID void -#define byte unsigned char #define __int8 char #define __int16 short #define __int32 int From 8a9d87d202d2f1c6e34bc49b9cfa63ccacbbb6b1 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Mon, 10 Sep 2012 19:12:46 -0400 Subject: [PATCH 005/180] [aml] rename byte to avoid system conflicts --- xbmc/filesystem/RarFile.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xbmc/filesystem/RarFile.h b/xbmc/filesystem/RarFile.h index 5163c49e2be7f..de47391fbc4c2 100644 --- a/xbmc/filesystem/RarFile.h +++ b/xbmc/filesystem/RarFile.h @@ -104,8 +104,8 @@ namespace XFILE CmdExtract* m_pExtract; CRarFileExtractThread* m_pExtractThread; #endif - byte* m_szBuffer; - byte* m_szStartOfBuffer; + BYTE* m_szBuffer; + BYTE* m_szStartOfBuffer; int64_t m_iDataInBuffer; int64_t m_iBufferStart; }; From e2cad40464bdbfd4b4f96b2fcb2975f39b2b4d0b Mon Sep 17 00:00:00 2001 From: theuni Date: Fri, 16 Mar 2012 15:49:18 -0400 Subject: [PATCH 006/180] [aml] set focus to the first non-disabled control --- xbmc/settings/GUIDialogSettings.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/xbmc/settings/GUIDialogSettings.cpp b/xbmc/settings/GUIDialogSettings.cpp index 0c8b22f1bb0a2..c80711e60280b 100644 --- a/xbmc/settings/GUIDialogSettings.cpp +++ b/xbmc/settings/GUIDialogSettings.cpp @@ -665,6 +665,15 @@ void CGUIDialogSettings::OnInitWindow() SetupPage(); // set the default focus control m_lastControlID = CONTROL_START; + + for (unsigned int i = 0; i < m_settings.size(); i++) + { + if (m_settings.at(i).enabled) + { + m_lastControlID = CONTROL_START + i; + break; + } + } CGUIDialog::OnInitWindow(); } From 7d240aab5e76665e510cbb2559053ae7b26ead1b Mon Sep 17 00:00:00 2001 From: theuni Date: Fri, 16 Mar 2012 15:51:30 -0400 Subject: [PATCH 007/180] [aml] disable spin controls with only one entry --- xbmc/settings/GUIDialogSettings.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xbmc/settings/GUIDialogSettings.cpp b/xbmc/settings/GUIDialogSettings.cpp index c80711e60280b..e4b0caa10c57f 100644 --- a/xbmc/settings/GUIDialogSettings.cpp +++ b/xbmc/settings/GUIDialogSettings.cpp @@ -600,6 +600,8 @@ void CGUIDialogSettings::AddSpin(unsigned int id, int label, int *current, vecto setting.type = SettingInfo::SPIN; setting.data = current; setting.entry = values; + if (values.size() <= 1) + setting.enabled = false; m_settings.push_back(setting); } From c6e72e87bf1071cd2ea78b9a6375f9e3a718ce53 Mon Sep 17 00:00:00 2001 From: theuni Date: Fri, 16 Mar 2012 21:41:36 -0400 Subject: [PATCH 008/180] [aml] introduce guisettings overrides (v2) This is useful for packagers as they can override menu defaults in as.xml rather than patching xbmc code. Usage example: lookandfeel.soundskin videoplayer.rendermethod --- xbmc/settings/AdvancedSettings.cpp | 21 +++++++++++++++++++++ xbmc/settings/AdvancedSettings.h | 1 + xbmc/settings/GUISettings.cpp | 21 +++++++++++++++++++++ xbmc/settings/GUISettings.h | 3 ++- xbmc/settings/Settings.cpp | 4 +--- 5 files changed, 46 insertions(+), 4 deletions(-) diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp index 16800b7596b32..ede6f184671f9 100644 --- a/xbmc/settings/AdvancedSettings.cpp +++ b/xbmc/settings/AdvancedSettings.cpp @@ -317,6 +317,7 @@ void CAdvancedSettings::Initialize() m_airTunesPort = 36666; m_airPlayPort = 36667; m_initialized = true; + m_settingsHidden.clear(); m_databaseMusic.Reset(); m_databaseVideo.Reset(); @@ -919,6 +920,26 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file) } } + TiXmlElement* pHideSettings = pRootElement->FirstChildElement("hidesettings"); + if (pHideSettings) + { + m_settingsHidden.clear(); + CLog::Log(LOGDEBUG,"Configuring hidden settings"); + TiXmlNode* pSetting = pHideSettings->FirstChildElement("setting"); + CStdString hiddenSetting; + while (pSetting) + { + hiddenSetting = pSetting->FirstChild()->Value(); + if (!hiddenSetting.IsEmpty()) + { + CLog::Log(LOGNOTICE,"Hiding: [%s]", hiddenSetting.c_str()); + m_settingsHidden.push_back(hiddenSetting); + } + // get next one + pSetting = pSetting->NextSiblingElement("setting"); + } + } + XMLUtils::GetInt(pRootElement, "remotedelay", m_remoteDelay, 1, 20); XMLUtils::GetFloat(pRootElement, "controllerdeadzone", m_controllerDeadzone, 0.0f, 1.0f); XMLUtils::GetUInt(pRootElement, "fanartres", m_fanartRes, 0, 1080); diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h index 27887d40615d7..d944c6aa85a50 100644 --- a/xbmc/settings/AdvancedSettings.h +++ b/xbmc/settings/AdvancedSettings.h @@ -206,6 +206,7 @@ class CAdvancedSettings SETTINGS_TVSHOWLIST m_tvshowEnumRegExps; CStdString m_tvshowMultiPartEnumRegExp; typedef std::vector< std::pair > StringMapping; + CStdStringArray m_settingsHidden; StringMapping m_pathSubstitutions; int m_remoteDelay; ///< \brief number of remote messages to ignore before repeating float m_controllerDeadzone; diff --git a/xbmc/settings/GUISettings.cpp b/xbmc/settings/GUISettings.cpp index 76ec0cccda751..b98af7c7e1453 100644 --- a/xbmc/settings/GUISettings.cpp +++ b/xbmc/settings/GUISettings.cpp @@ -1351,6 +1351,17 @@ void CGUISettings::GetSettingsGroup(CSettingsCategory* cat, vecSettings &setting } } +bool CGUISettings::CheckHiddenOverride(CSetting *setting) +{ + for (CStdStringArray::iterator i = g_advancedSettings.m_settingsHidden.begin(); + i != g_advancedSettings.m_settingsHidden.end(); i++) + { + if (strncmp(setting->GetSetting(), i->c_str(), i->size()) == 0) + return true; + } + return false; +} + void CGUISettings::LoadXML(TiXmlElement *pRootElement, bool hideSettings /* = false */) { // load our stuff... bool updated = false; @@ -1476,6 +1487,16 @@ void CGUISettings::LoadFromXML(TiXmlElement *pRootElement, mapIter &it, bool adv { CStdStringArray strSplit; StringUtils::SplitString((*it).first, ".", strSplit); + + // Look for 'hidden' entries in as.xml and treat them as Advanced + // Be sure to disable advanced if it's not in the overrides list, else + // it may remain hidden which switching to a profile where it should not be. + + if (CheckHiddenOverride((*it).second)) + (*it).second->SetAdvanced(true); + else + (*it).second->SetAdvanced(false); + if (strSplit.size() > 1) { const TiXmlNode *pChild = pRootElement->FirstChild(strSplit[0].c_str()); diff --git a/xbmc/settings/GUISettings.h b/xbmc/settings/GUISettings.h index a2893c01802b8..d85106ca6a536 100644 --- a/xbmc/settings/GUISettings.h +++ b/xbmc/settings/GUISettings.h @@ -252,7 +252,7 @@ class CSetting int GetLabel() const { return m_iLabel; }; int GetOrder() const { return m_iOrder; }; void SetOrder(int iOrder) { m_iOrder = iOrder; }; - void SetAdvanced() { m_advanced = true; }; + void SetAdvanced(bool advanced = true) { m_advanced = advanced; }; bool IsAdvanced() const { return m_advanced; }; // A setting might be invisible in the current session, yet carried over // in the config file. @@ -525,6 +525,7 @@ class CGUISettings : public Observable std::map settingsMap; std::vector settingsGroups; void LoadFromXML(TiXmlElement *pRootElement, mapIter &it, bool advanced = false); + bool CheckHiddenOverride(CSetting *setting); }; XBMC_GLOBAL_REF(CGUISettings, g_guiSettings); diff --git a/xbmc/settings/Settings.cpp b/xbmc/settings/Settings.cpp index 8a430adf98087..0704bc16e263b 100644 --- a/xbmc/settings/Settings.cpp +++ b/xbmc/settings/Settings.cpp @@ -168,6 +168,7 @@ bool CSettings::Reset() bool CSettings::Load() { CSpecialProtocol::SetProfilePath(GetProfileUserDataFolder()); + g_advancedSettings.Load(); CLog::Log(LOGNOTICE, "loading %s", GetSettingsFile().c_str()); if (!LoadSettings(GetSettingsFile())) { @@ -792,9 +793,6 @@ bool CSettings::LoadSettings(const CStdString& strSettingsFile) LoadPlayerCoreFactorySettings("special://xbmc/system/playercorefactory.xml", true); LoadPlayerCoreFactorySettings(GetUserDataItem("playercorefactory.xml"), false); - // Advanced settings - g_advancedSettings.Load(); - // Add the list of disc stub extensions (if any) to the list of video extensions if (!m_discStubExtensions.IsEmpty()) g_settings.m_videoExtensions += "|" + m_discStubExtensions; From 7464da50b1caffc2c9bded423df3482834a515e7 Mon Sep 17 00:00:00 2001 From: theuni Date: Mon, 26 Mar 2012 04:36:33 -0400 Subject: [PATCH 009/180] [aml] allow packager to provide a base guisettings.xml place a guisettings.xml in system with any default values needed. These values will only be used when user's guisettings.xml is generated. This way, packager can set a default value (for ex, disable rss). Each profile will default to this setting, but user's changes will take precedence. --- xbmc/settings/Settings.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/xbmc/settings/Settings.cpp b/xbmc/settings/Settings.cpp index 0704bc16e263b..abea97b219379 100644 --- a/xbmc/settings/Settings.cpp +++ b/xbmc/settings/Settings.cpp @@ -161,6 +161,7 @@ bool CSettings::Reset() { CLog::Log(LOGINFO, "Resetting settings"); CFile::Delete(GetSettingsFile()); + LoadSettings("special://xbmc/system/guisettings.xml"); Save(); return LoadSettings(GetSettingsFile()); } From f523e23982ea4629ed20c170e694085733a80b50 Mon Sep 17 00:00:00 2001 From: theuni Date: Tue, 10 Apr 2012 02:37:27 -0400 Subject: [PATCH 010/180] [aml] Fix slow gui during fullscreen playback If we're using bypass mode for playback, we aren't rendering ourselves, so don't try to wait for render events. --- xbmc/Application.cpp | 2 +- xbmc/cores/VideoRenderers/RenderManager.cpp | 8 ++++++++ xbmc/cores/VideoRenderers/RenderManager.h | 3 +++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp index c6f0a14361e12..99b8c21aa4e93 100644 --- a/xbmc/Application.cpp +++ b/xbmc/Application.cpp @@ -2280,7 +2280,7 @@ void CApplication::Render() bool extPlayerActive = m_eCurrentPlayer == EPC_EXTPLAYER && IsPlaying() && !m_AppFocused; m_bPresentFrame = false; - if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !IsPaused()) + if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !IsPaused() && g_renderManager.RendererHandlesPresent()) { CSingleLock lock(m_frameMutex); diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp index d22287dbfbb1c..65400b3ba07bc 100644 --- a/xbmc/cores/VideoRenderers/RenderManager.cpp +++ b/xbmc/cores/VideoRenderers/RenderManager.cpp @@ -256,6 +256,9 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi CApplicationMessenger::Get().SwitchToFullscreen(); lock.Enter(); } + if( flags & CONF_FLAGS_FORMAT_BYPASS ) + m_presentmethod = PRESENT_METHOD_BYPASS; + m_pRenderer->Update(false); m_bIsStarted = true; m_bReconfigured = true; @@ -266,6 +269,11 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi return result; } +bool CXBMCRenderManager::RendererHandlesPresent() +{ + return IsConfigured() && m_presentmethod != PRESENT_METHOD_BYPASS; +} + bool CXBMCRenderManager::IsConfigured() { if (!m_pRenderer) diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h index 7fe6bb234c5df..1d05bb419d39b 100644 --- a/xbmc/cores/VideoRenderers/RenderManager.h +++ b/xbmc/cores/VideoRenderers/RenderManager.h @@ -110,6 +110,8 @@ class CXBMCRenderManager void UpdateResolution(); + bool RendererHandlesPresent(); + #ifdef HAS_GL CLinuxRendererGL *m_pRenderer; #elif HAS_GLES == 2 @@ -164,6 +166,7 @@ class CXBMCRenderManager PRESENT_METHOD_BLEND, PRESENT_METHOD_WEAVE, PRESENT_METHOD_BOB, + PRESENT_METHOD_BYPASS, }; double m_displayLatency; From e3f4cc6a73975b4c3d967b538b3b93e327a08c12 Mon Sep 17 00:00:00 2001 From: theuni Date: Tue, 10 Apr 2012 02:39:08 -0400 Subject: [PATCH 011/180] [aml] frame-limit during fullscreen playback to avoid running at 100fps --- xbmc/Application.cpp | 6 ++++++ xbmc/cores/VideoRenderers/RenderManager.cpp | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp index 99b8c21aa4e93..9c75230393d0d 100644 --- a/xbmc/Application.cpp +++ b/xbmc/Application.cpp @@ -2291,6 +2291,12 @@ void CApplication::Render() decrement = m_bPresentFrame; hasRendered = true; } + else if(!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !g_renderManager.RendererHandlesPresent()) + { + //Whether we're paused or not, if the renderer isn't in charge of presenting and we're fullscreen, we limit + singleFrameTime = 30; + limitFrames = true; + } else { // engage the frame limiter as needed diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp index 65400b3ba07bc..bbdfd35c03ab2 100644 --- a/xbmc/cores/VideoRenderers/RenderManager.cpp +++ b/xbmc/cores/VideoRenderers/RenderManager.cpp @@ -256,7 +256,7 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi CApplicationMessenger::Get().SwitchToFullscreen(); lock.Enter(); } - if( flags & CONF_FLAGS_FORMAT_BYPASS ) + if( format & RENDER_FMT_BYPASS ) m_presentmethod = PRESENT_METHOD_BYPASS; m_pRenderer->Update(false); From 6386bf59f9f373e0dfc8644a2c921ea2cff3f62a Mon Sep 17 00:00:00 2001 From: theuni Date: Sun, 27 Nov 2011 11:57:56 -0500 Subject: [PATCH 012/180] [aml] speed up blending (texture * color) costs us an extra operation on Mali when sent as varying. Instead, since textures use the same color for the entire render, send it as a uniform instead. This does not apply to fonts, since the font and its shadow are rendered together, and may not share a color (tested and looks bad). This increases fps anywhere heavy blending is done. --- system/shaders/guishader_frag_multi_blendcolor.glsl | 4 ++-- system/shaders/guishader_frag_texture.glsl | 4 ++-- xbmc/cores/VideoRenderers/OverlayRendererGL.cpp | 2 ++ xbmc/guilib/GUIShader.cpp | 4 ++++ xbmc/guilib/GUIShader.h | 2 ++ xbmc/guilib/GUITextureGLES.cpp | 5 +++++ xbmc/pictures/SlideShowPicture.cpp | 2 ++ xbmc/rendering/gles/RenderSystemGLES.cpp | 8 ++++++++ xbmc/rendering/gles/RenderSystemGLES.h | 1 + 9 files changed, 28 insertions(+), 4 deletions(-) diff --git a/system/shaders/guishader_frag_multi_blendcolor.glsl b/system/shaders/guishader_frag_multi_blendcolor.glsl index b311350ff96fa..24a838c513d53 100644 --- a/system/shaders/guishader_frag_multi_blendcolor.glsl +++ b/system/shaders/guishader_frag_multi_blendcolor.glsl @@ -24,10 +24,10 @@ uniform sampler2D m_samp0; uniform sampler2D m_samp1; varying vec4 m_cord0; varying vec4 m_cord1; -varying lowp vec4 m_colour; +uniform lowp vec4 m_unicol; // SM_MULTI shader void main () { - gl_FragColor.rgba = (texture2D(m_samp0, m_cord0.xy) * texture2D(m_samp1, m_cord1.xy)).rgba * m_colour; + gl_FragColor.rgba = (texture2D(m_samp0, m_cord0.xy) * texture2D(m_samp1, m_cord1.xy)).rgba * m_unicol; } diff --git a/system/shaders/guishader_frag_texture.glsl b/system/shaders/guishader_frag_texture.glsl index 16bb84e442d0c..fbce8a3166296 100644 --- a/system/shaders/guishader_frag_texture.glsl +++ b/system/shaders/guishader_frag_texture.glsl @@ -21,11 +21,11 @@ precision mediump float; uniform sampler2D m_samp0; +uniform lowp vec4 m_unicol; varying vec4 m_cord0; -varying lowp vec4 m_colour; // SM_TEXTURE shader void main () { - gl_FragColor.rgba = vec4(texture2D(m_samp0, m_cord0.xy).rgba * m_colour); + gl_FragColor.rgba = vec4(texture2D(m_samp0, m_cord0.xy).rgba * m_unicol); } diff --git a/xbmc/cores/VideoRenderers/OverlayRendererGL.cpp b/xbmc/cores/VideoRenderers/OverlayRendererGL.cpp index 4375d19caeb1b..28b821bdb029b 100644 --- a/xbmc/cores/VideoRenderers/OverlayRendererGL.cpp +++ b/xbmc/cores/VideoRenderers/OverlayRendererGL.cpp @@ -521,6 +521,7 @@ void COverlayTextureGL::Render(SRenderState& state) GLint posLoc = g_Windowing.GUIShaderGetPos(); GLint colLoc = g_Windowing.GUIShaderGetCol(); GLint tex0Loc = g_Windowing.GUIShaderGetCoord0(); + GLint uniColLoc= g_Windowing.GUIShaderGetUniCol(); glVertexAttribPointer(posLoc, 2, GL_FLOAT, 0, 0, ver); glVertexAttribPointer(colLoc, 4, GL_FLOAT, 0, 0, col); @@ -536,6 +537,7 @@ void COverlayTextureGL::Render(SRenderState& state) col[i][0] = col[i][1] = col[i][2] = col[i][3] = 1.0f; } + glUniform4f(uniColLoc,(col[0][0]), (col[0][1]), (col[0][2]), (col[0][3])); // Setup vertex position values ver[0][0] = ver[3][0] = rd.left; ver[0][1] = ver[1][1] = rd.top; diff --git a/xbmc/guilib/GUIShader.cpp b/xbmc/guilib/GUIShader.cpp index 8d04313047eee..7a96095f5903f 100644 --- a/xbmc/guilib/GUIShader.cpp +++ b/xbmc/guilib/GUIShader.cpp @@ -38,6 +38,7 @@ CGUIShader::CGUIShader( const char *shader ) : CGLSLShaderProgram("guishader_ver m_hCol = 0; m_hCord0 = 0; m_hCord1 = 0; + m_hUniCol = 0; m_proj = NULL; m_model = NULL; @@ -50,6 +51,8 @@ void CGUIShader::OnCompiledAndLinked() // Variables passed directly to the Fragment shader m_hTex0 = glGetUniformLocation(ProgramHandle(), "m_samp0"); m_hTex1 = glGetUniformLocation(ProgramHandle(), "m_samp1"); + m_hUniCol = glGetUniformLocation(ProgramHandle(), "m_unicol"); + // Variables passed directly to the Vertex shader m_hProj = glGetUniformLocation(ProgramHandle(), "m_proj"); m_hModel = glGetUniformLocation(ProgramHandle(), "m_model"); @@ -62,6 +65,7 @@ void CGUIShader::OnCompiledAndLinked() glUseProgram( ProgramHandle() ); glUniform1i(m_hTex0, 0); glUniform1i(m_hTex1, 1); + glUniform4f(m_hUniCol, 1.0, 1.0, 1.0, 1.0); glUseProgram( 0 ); } diff --git a/xbmc/guilib/GUIShader.h b/xbmc/guilib/GUIShader.h index d84e25158a0b2..95de7585e6656 100644 --- a/xbmc/guilib/GUIShader.h +++ b/xbmc/guilib/GUIShader.h @@ -39,10 +39,12 @@ class CGUIShader : public CGLSLShaderProgram GLint GetColLoc() { return m_hCol; } GLint GetCord0Loc() { return m_hCord0; } GLint GetCord1Loc() { return m_hCord1; } + GLint GetUniColLoc() { return m_hUniCol; } protected: GLint m_hTex0; GLint m_hTex1; + GLint m_hUniCol; GLint m_hProj; GLint m_hModel; GLint m_hPos; diff --git a/xbmc/guilib/GUITextureGLES.cpp b/xbmc/guilib/GUITextureGLES.cpp index 86fb6bb3aaf1d..3c729fa997c05 100644 --- a/xbmc/guilib/GUITextureGLES.cpp +++ b/xbmc/guilib/GUITextureGLES.cpp @@ -91,7 +91,9 @@ void CGUITextureGLES::Begin(color_t color) GLint posLoc = g_Windowing.GUIShaderGetPos(); GLint colLoc = g_Windowing.GUIShaderGetCol(); GLint tex0Loc = g_Windowing.GUIShaderGetCoord0(); + GLint uniColLoc= g_Windowing.GUIShaderGetUniCol(); + glUniform4f(uniColLoc,(m_col[0][0] / 255.0), (m_col[0][1] / 255.0), (m_col[0][2] / 255.0), (m_col[0][3] / 255.0)); glVertexAttribPointer(posLoc, 3, GL_FLOAT, 0, 0, m_vert); if(colLoc >= 0) glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, m_col); @@ -234,6 +236,7 @@ void CGUITextureGLES::DrawQuad(const CRect &rect, color_t color, CBaseTexture *t GLint posLoc = g_Windowing.GUIShaderGetPos(); GLint colLoc = g_Windowing.GUIShaderGetCol(); GLint tex0Loc = g_Windowing.GUIShaderGetCoord0(); + GLint uniColLoc= g_Windowing.GUIShaderGetUniCol(); glVertexAttribPointer(posLoc, 3, GL_FLOAT, 0, 0, ver); if(colLoc >= 0) @@ -256,6 +259,8 @@ void CGUITextureGLES::DrawQuad(const CRect &rect, color_t color, CBaseTexture *t col[i][3] = (GLubyte)GET_A(color); } + glUniform4f(uniColLoc,col[0][0] / 255, col[0][1] / 255, col[0][2] / 255, col[0][3] / 255); + // Setup vertex position values #define ROUND_TO_PIXEL(x) (float)(MathUtils::round_int(x)) ver[0][0] = ROUND_TO_PIXEL(g_graphicsContext.ScaleFinalXCoord(rect.x1, rect.y1)); diff --git a/xbmc/pictures/SlideShowPicture.cpp b/xbmc/pictures/SlideShowPicture.cpp index 055806b4f6f54..a8aa160bb6e5b 100644 --- a/xbmc/pictures/SlideShowPicture.cpp +++ b/xbmc/pictures/SlideShowPicture.cpp @@ -859,6 +859,7 @@ void CSlideShowPic::Render(float *x, float *y, CBaseTexture* pTexture, color_t c GLint posLoc = g_Windowing.GUIShaderGetPos(); GLint colLoc = g_Windowing.GUIShaderGetCol(); GLint tex0Loc = g_Windowing.GUIShaderGetCoord0(); + GLint uniColLoc= g_Windowing.GUIShaderGetUniCol(); glVertexAttribPointer(posLoc, 3, GL_FLOAT, 0, 0, ver); glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, col); @@ -887,6 +888,7 @@ void CSlideShowPic::Render(float *x, float *y, CBaseTexture* pTexture, color_t c tex[1][0] = tex[2][0] = u2; tex[2][1] = tex[3][1] = v2; + glUniform4f(uniColLoc,(col[0][0] / 255.0), (col[0][1] / 255.0), (col[0][2] / 255.0), (col[0][3] / 255.0)); glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx); glDisableVertexAttribArray(posLoc); diff --git a/xbmc/rendering/gles/RenderSystemGLES.cpp b/xbmc/rendering/gles/RenderSystemGLES.cpp index 5c1207632d4ce..e38bd14687e00 100644 --- a/xbmc/rendering/gles/RenderSystemGLES.cpp +++ b/xbmc/rendering/gles/RenderSystemGLES.cpp @@ -631,4 +631,12 @@ GLint CRenderSystemGLES::GUIShaderGetCoord1() return -1; } +GLint CRenderSystemGLES::GUIShaderGetUniCol() +{ + if (m_pGUIshader[m_method]) + return m_pGUIshader[m_method]->GetUniColLoc(); + + return -1; +} + #endif diff --git a/xbmc/rendering/gles/RenderSystemGLES.h b/xbmc/rendering/gles/RenderSystemGLES.h index 6c3783468fc67..f78b4b45c1b25 100644 --- a/xbmc/rendering/gles/RenderSystemGLES.h +++ b/xbmc/rendering/gles/RenderSystemGLES.h @@ -85,6 +85,7 @@ class CRenderSystemGLES : public CRenderSystemBase GLint GUIShaderGetCol(); GLint GUIShaderGetCoord0(); GLint GUIShaderGetCoord1(); + GLint GUIShaderGetUniCol(); protected: virtual void SetVSyncImpl(bool enable) = 0; From 4b534644fd884a82ef5a392b2806417fc43f3b1c Mon Sep 17 00:00:00 2001 From: theuni Date: Tue, 10 Apr 2012 17:44:08 -0400 Subject: [PATCH 013/180] [aml] cut diffuse+blend render time by 1/3 Mainly seen when we're fading in/out. Mali likes this ordering better for some reason, ops go from 3 to 2 (according to their profiler). Verified with PVR's compiler that there is no change, it's 2 there either way. --- system/shaders/guishader_frag_multi_blendcolor.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/shaders/guishader_frag_multi_blendcolor.glsl b/system/shaders/guishader_frag_multi_blendcolor.glsl index 24a838c513d53..58c3e55801291 100644 --- a/system/shaders/guishader_frag_multi_blendcolor.glsl +++ b/system/shaders/guishader_frag_multi_blendcolor.glsl @@ -29,5 +29,5 @@ uniform lowp vec4 m_unicol; // SM_MULTI shader void main () { - gl_FragColor.rgba = (texture2D(m_samp0, m_cord0.xy) * texture2D(m_samp1, m_cord1.xy)).rgba * m_unicol; + gl_FragColor.rgba = m_unicol * texture2D(m_samp0, m_cord0.xy) * texture2D(m_samp1, m_cord1.xy); } From 3b419cd8c60dc31ec5fe0a02513ca77ba10e867b Mon Sep 17 00:00:00 2001 From: theuni Date: Mon, 2 Jan 2012 22:29:23 -0500 Subject: [PATCH 014/180] [aml] Batch textures and their borders Gives a considerable speedup in scenes with many bordered images (like settings). --- xbmc/guilib/GUITextureGLES.cpp | 134 ++++++++++++++++++--------------- xbmc/guilib/GUITextureGLES.h | 14 +++- 2 files changed, 86 insertions(+), 62 deletions(-) diff --git a/xbmc/guilib/GUITextureGLES.cpp b/xbmc/guilib/GUITextureGLES.cpp index 3c729fa997c05..9621a89b56d6b 100644 --- a/xbmc/guilib/GUITextureGLES.cpp +++ b/xbmc/guilib/GUITextureGLES.cpp @@ -72,9 +72,6 @@ void CGUITextureGLES::Begin(color_t color) m_diffuse.m_textures[0]->BindToUnit(1); - GLint tex1Loc = g_Windowing.GUIShaderGetCoord1(); - glVertexAttribPointer(tex1Loc, 2, GL_FLOAT, 0, 0, m_tex1); - glEnableVertexAttribArray(tex1Loc); } else { @@ -88,22 +85,6 @@ void CGUITextureGLES::Begin(color_t color) } } - GLint posLoc = g_Windowing.GUIShaderGetPos(); - GLint colLoc = g_Windowing.GUIShaderGetCol(); - GLint tex0Loc = g_Windowing.GUIShaderGetCoord0(); - GLint uniColLoc= g_Windowing.GUIShaderGetUniCol(); - - glUniform4f(uniColLoc,(m_col[0][0] / 255.0), (m_col[0][1] / 255.0), (m_col[0][2] / 255.0), (m_col[0][3] / 255.0)); - glVertexAttribPointer(posLoc, 3, GL_FLOAT, 0, 0, m_vert); - if(colLoc >= 0) - glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, m_col); - glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, 0, 0, m_tex0); - - glEnableVertexAttribArray(posLoc); - if(colLoc >= 0) - glEnableVertexAttribArray(colLoc); - glEnableVertexAttribArray(tex0Loc); - if ( hasAlpha ) { glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE); @@ -113,101 +94,136 @@ void CGUITextureGLES::Begin(color_t color) { glDisable(GL_BLEND); } + m_packedVertices.clear(); } void CGUITextureGLES::End() { + GLint posLoc = g_Windowing.GUIShaderGetPos(); + GLint tex0Loc = g_Windowing.GUIShaderGetCoord0(); + GLint tex1Loc = g_Windowing.GUIShaderGetCoord1(); + GLint uniColLoc = g_Windowing.GUIShaderGetUniCol(); + + if(uniColLoc >= 0) + { + glUniform4f(uniColLoc,(m_col[0][0] / 255.0), (m_col[0][1] / 255.0), (m_col[0][2] / 255.0), (m_col[0][3] / 255.0)); + } + + if(m_diffuse.size()) + { + glVertexAttribPointer(tex1Loc, 2, GL_FLOAT, 0, sizeof(PackedVertex), (char*)&m_packedVertices[0] + offsetof(PackedVertex, u2)); + glEnableVertexAttribArray(tex1Loc); + } + glVertexAttribPointer(posLoc, 3, GL_FLOAT, 0, sizeof(PackedVertex), (char*)&m_packedVertices[0] + offsetof(PackedVertex, x)); + glEnableVertexAttribArray(posLoc); + glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, 0, sizeof(PackedVertex), (char*)&m_packedVertices[0] + offsetof(PackedVertex, u1)); + glEnableVertexAttribArray(tex0Loc); + + GLushort *idx; + idx = new GLushort[m_packedVertices.size()*6 / 4]; + for (unsigned int i=0, size=0; i < m_packedVertices.size(); i+=4, size+=6) + { + idx[size+0] = i+0; + idx[size+1] = i+1; + idx[size+2] = i+2; + idx[size+3] = i+2; + idx[size+4] = i+3; + idx[size+5] = i+0; + } + + glDrawElements(GL_TRIANGLES, m_packedVertices.size()*6 / 4, GL_UNSIGNED_SHORT, idx); + if (m_diffuse.size()) { - glDisableVertexAttribArray(g_Windowing.GUIShaderGetCoord1()); + glDisableVertexAttribArray(tex1Loc); glActiveTexture(GL_TEXTURE0); } - glDisableVertexAttribArray(g_Windowing.GUIShaderGetPos()); - GLint colLoc = g_Windowing.GUIShaderGetCol(); - if(colLoc >= 0) - glDisableVertexAttribArray(g_Windowing.GUIShaderGetCol()); - glDisableVertexAttribArray(g_Windowing.GUIShaderGetCoord0()); + glDisableVertexAttribArray(posLoc); + glDisableVertexAttribArray(tex0Loc); glEnable(GL_BLEND); g_Windowing.DisableGUIShader(); + delete [] idx; } void CGUITextureGLES::Draw(float *x, float *y, float *z, const CRect &texture, const CRect &diffuse, int orientation) { - GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip - - // Setup vertex position values - for (int i=0; i<4; i++) - { - m_vert[i][0] = x[i]; - m_vert[i][1] = y[i]; - m_vert[i][2] = z[i]; - } + PackedVertex vertices[4]; // Setup texture coordinates //TopLeft - m_tex0[0][0] = texture.x1; - m_tex0[0][1] = texture.y1; + vertices[0].u1 = texture.x1; + vertices[0].v1 = texture.y1; //TopRight if (orientation & 4) { - m_tex0[1][0] = texture.x1; - m_tex0[1][1] = texture.y2; + vertices[1].u1 = texture.x1; + vertices[1].v1 = texture.y2; } else { - m_tex0[1][0] = texture.x2; - m_tex0[1][1] = texture.y1; + vertices[1].u1 = texture.x2; + vertices[1].v1 = texture.y1; } //BottomRight - m_tex0[2][0] = texture.x2; - m_tex0[2][1] = texture.y2; + vertices[2].u1 = texture.x2; + vertices[2].v1 = texture.y2; //BottomLeft if (orientation & 4) { - m_tex0[3][0] = texture.x2; - m_tex0[3][1] = texture.y1; + vertices[3].u1 = texture.x2; + vertices[3].v1 = texture.y1; } else { - m_tex0[3][0] = texture.x1; - m_tex0[3][1] = texture.y2; + vertices[3].u1 = texture.x1; + vertices[3].v1 = texture.y2; } if (m_diffuse.size()) { //TopLeft - m_tex1[0][0] = diffuse.x1; - m_tex1[0][1] = diffuse.y1; + vertices[0].u2 = diffuse.x1; + vertices[0].v2 = diffuse.y1; //TopRight if (m_info.orientation & 4) { - m_tex1[1][0] = diffuse.x1; - m_tex1[1][1] = diffuse.y2; + vertices[1].u2 = diffuse.x1; + vertices[1].v2 = diffuse.y2; } else { - m_tex1[1][0] = diffuse.x2; - m_tex1[1][1] = diffuse.y1; + vertices[1].u2 = diffuse.x2; + vertices[1].v2 = diffuse.y1; } //BottomRight - m_tex1[2][0] = diffuse.x2; - m_tex1[2][1] = diffuse.y2; + vertices[2].u2 = diffuse.x2; + vertices[2].v2 = diffuse.y2; //BottomLeft if (m_info.orientation & 4) { - m_tex1[3][0] = diffuse.x2; - m_tex1[3][1] = diffuse.y1; + vertices[3].u2 = diffuse.x2; + vertices[3].v2 = diffuse.y1; } else { - m_tex1[3][0] = diffuse.x1; - m_tex1[3][1] = diffuse.y2; + vertices[3].u2 = diffuse.x1; + vertices[3].v2 = diffuse.y2; } } - glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx); + for (int i=0; i<4; i++) + { + vertices[i].x = x[i]; + vertices[i].y = y[i]; + vertices[i].z = z[i]; + vertices[i].r = m_col[i][0]; + vertices[i].g = m_col[i][1]; + vertices[i].b = m_col[i][2]; + vertices[i].a = m_col[i][3]; + m_packedVertices.push_back(vertices[i]); + } } void CGUITextureGLES::DrawQuad(const CRect &rect, color_t color, CBaseTexture *texture, const CRect *texCoords) diff --git a/xbmc/guilib/GUITextureGLES.h b/xbmc/guilib/GUITextureGLES.h index d0d38dfc08a4a..206d9d6427280 100644 --- a/xbmc/guilib/GUITextureGLES.h +++ b/xbmc/guilib/GUITextureGLES.h @@ -32,6 +32,15 @@ #include "system_gl.h" +struct PackedVertex +{ + float x, y, z; + unsigned char r, g, b, a; + float u1, v1; + float u2, v2; +}; +typedef std::vector PackedVertices; + class CGUITextureGLES : public CGUITextureBase { public: @@ -43,9 +52,8 @@ class CGUITextureGLES : public CGUITextureBase void End(); GLubyte m_col [4][4]; - GLfloat m_vert[4][3]; - GLfloat m_tex0[4][2]; - GLfloat m_tex1[4][2]; + + PackedVertices m_packedVertices; }; #endif From 66e5944da337dd786d6a138a0f37aa435da8821e Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 5 Sep 2012 23:41:30 -0400 Subject: [PATCH 015/180] [aml] use native texturepacker for linux arm --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 67543121046e9..598256a1a6b97 100644 --- a/configure.in +++ b/configure.in @@ -622,7 +622,7 @@ case $host in AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_LINUX -D_POWERPC64") ;; arm*-*-linux-gnu*) - use_texturepacker=no + use_texturepacker_native=yes ARCH="arm" use_arch="arm" AC_SUBST(ARCH_DEFINES, "-DTARGET_POSIX -DTARGET_LINUX -D_LINUX") From a6ff4f441c7faeda19ed1878bf37b263f02a5b75 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 5 Sep 2012 23:42:33 -0400 Subject: [PATCH 016/180] [aml] skip dxt compression on all arm boards The only chipset I'm aware of that can do dxt on arm is Tegra, and that's not worth slowing everyone else down --- addons/skin.confluence/media/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/skin.confluence/media/Makefile.in b/addons/skin.confluence/media/Makefile.in index 3cf7d1bcd30c5..bfb18c54537fd 100644 --- a/addons/skin.confluence/media/Makefile.in +++ b/addons/skin.confluence/media/Makefile.in @@ -10,7 +10,7 @@ all: $(TARGET) .PHONY: force $(TARGET): $(XBMCTEX) $(IMAGES) -ifeq (@USE_ANDROID@,1) +ifeq (@ARCH@,arm) $(XBMCTEX) -use_none -input . -output $(TARGET) else $(XBMCTEX) -input . -output $(TARGET) From 7688b3131d1f6f3f25b01a6baf1565333390a643 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 14 Sep 2012 14:44:48 -0400 Subject: [PATCH 017/180] [aml] don't mark video control dirty for hardware players With d-r on, speeds up video playback+gui nav very significantly. We still do the fake render, so the player still receives its render callbacks. --- xbmc/guilib/GUIVideoControl.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xbmc/guilib/GUIVideoControl.cpp b/xbmc/guilib/GUIVideoControl.cpp index f9c7090729785..49e1a0fe7b69d 100644 --- a/xbmc/guilib/GUIVideoControl.cpp +++ b/xbmc/guilib/GUIVideoControl.cpp @@ -40,7 +40,8 @@ CGUIVideoControl::~CGUIVideoControl(void) void CGUIVideoControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions) { // TODO Proper processing which marks when its actually changed. Just mark always for now. - MarkDirtyRegion(); + if (g_renderManager.RendererHandlesPresent()) + MarkDirtyRegion(); CGUIControl::Process(currentTime, dirtyregions); } From c09656322ea1adae15311d07aa1af21306850b7b Mon Sep 17 00:00:00 2001 From: davilla Date: Sat, 15 Sep 2012 11:45:34 -0400 Subject: [PATCH 018/180] [aml] add network Manager --- .gitignore | 1 + Makefile.in | 1 + .../720p/DialogAccessPoints.xml | 179 ++++ addons/skin.confluence/media/ap-lock.png | Bin 0 -> 749 bytes addons/skin.confluence/media/ap-signal1.png | Bin 0 -> 2982 bytes addons/skin.confluence/media/ap-signal2.png | Bin 0 -> 2961 bytes addons/skin.confluence/media/ap-signal3.png | Bin 0 -> 3180 bytes addons/skin.confluence/media/ap-signal4.png | Bin 0 -> 3282 bytes addons/skin.confluence/media/ap-signal5.png | Bin 0 -> 3395 bytes addons/skin.confluence/media/connected.png | Bin 0 -> 1226 bytes addons/skin.confluence/media/connecting.png | Bin 0 -> 1215 bytes addons/skin.confluence/media/disconnected.png | Bin 0 -> 1192 bytes configure.in | 1 + language/English/strings.po | 18 +- tools/amlogic/depends/xbmc/Makefile | 4 +- xbmc/Application.cpp | 57 +- xbmc/Application.h | 10 +- xbmc/ApplicationMessenger.cpp | 3 +- xbmc/GUIInfoManager.cpp | 40 +- xbmc/Util.cpp | 3 +- xbmc/dialogs/GUIDialogFileBrowser.cpp | 3 +- xbmc/filesystem/DirectoryFactory.cpp | 3 +- xbmc/filesystem/FileFactory.cpp | 3 +- xbmc/guilib/Key.h | 2 +- xbmc/interfaces/Builtins.cpp | 5 +- xbmc/interfaces/legacy/ModuleXbmc.cpp | 9 +- xbmc/music/MusicDatabase.cpp | 3 +- xbmc/network/AirPlayServer.cpp | 3 +- xbmc/network/AirTunesServer.cpp | 17 +- xbmc/network/ConnectionJob.cpp | 102 ++ xbmc/network/ConnectionJob.h | 43 + xbmc/network/GUIDialogAccessPoints.cpp | 300 ++++-- xbmc/network/GUIDialogAccessPoints.h | 47 +- xbmc/network/IConnection.h | 209 ++++ xbmc/network/INetworkManager.h | 66 ++ xbmc/network/IPassphraseStorage.h | 63 ++ xbmc/network/Makefile.in | 5 +- xbmc/network/Network.cpp | 345 ------- xbmc/network/Network.h | 130 --- xbmc/network/NetworkManager.cpp | 452 +++++++++ xbmc/network/NetworkManager.h | 80 ++ xbmc/network/NetworkUtils.cpp | 31 + xbmc/network/NetworkUtils.h | 29 + xbmc/network/NullNetworkManager.cpp | 117 +++ xbmc/network/NullNetworkManager.h | 55 ++ xbmc/network/UdpClient.cpp | 1 - xbmc/network/linux/ConnmanConnection.cpp | 269 +++++ xbmc/network/linux/ConnmanConnection.h | 77 ++ xbmc/network/linux/ConnmanNetworkManager.cpp | 173 ++++ xbmc/network/linux/ConnmanNetworkManager.h | 51 + xbmc/network/linux/Makefile | 8 - xbmc/network/linux/Makefile.in | 11 + xbmc/network/linux/NetworkLinux.cpp | 930 ------------------ xbmc/network/linux/NetworkLinux.h | 89 -- xbmc/network/linux/PosixConnection.cpp | 712 ++++++++++++++ xbmc/network/linux/PosixConnection.h | 78 ++ xbmc/network/linux/PosixNetworkManager.cpp | 486 +++++++++ xbmc/network/linux/PosixNetworkManager.h | 46 + xbmc/network/upnp/UPnP.cpp | 5 +- xbmc/network/upnp/UPnPRenderer.cpp | 6 +- xbmc/network/windows/WinConnection.cpp | 104 ++ xbmc/network/windows/WinConnection.h | 51 + xbmc/network/windows/WinNetworkManager.cpp | 88 ++ xbmc/network/windows/WinNetworkManager.h | 41 + xbmc/security/IKeyringManager.h | 61 ++ xbmc/security/KeyringManager.cpp | 78 ++ xbmc/security/KeyringManager.h | 67 ++ xbmc/security/Makefile | 8 + xbmc/security/MemoryKeyringManager.cpp | 61 ++ xbmc/security/MemoryKeyringManager.h | 38 + xbmc/security/XMLKeyringManager.cpp | 118 +++ xbmc/security/XMLKeyringManager.h | 40 + xbmc/settings/AdvancedSettings.cpp | 6 + xbmc/settings/AdvancedSettings.h | 4 + xbmc/settings/GUISettings.cpp | 46 +- xbmc/settings/GUIWindowSettingsCategory.cpp | 337 +++---- xbmc/settings/GUIWindowSettingsCategory.h | 3 +- xbmc/settings/GUIWindowSettingsProfile.cpp | 3 +- xbmc/utils/Makefile | 2 + xbmc/utils/MathUtils.h | 4 +- xbmc/utils/RssReader.cpp | 3 +- xbmc/utils/SystemInfo.cpp | 12 - xbmc/utils/SystemInfo.h | 1 - xbmc/utils/URIUtils.cpp | 3 +- xbmc/utils/Weather.cpp | 3 +- xbmc/utils/XMLVariantParser.cpp | 80 ++ xbmc/utils/XMLVariantParser.h | 32 + xbmc/utils/XMLVariantWriter.cpp | 96 ++ xbmc/utils/XMLVariantWriter.h | 33 + xbmc/windows/GUIMediaWindow.cpp | 7 +- xbmc/windows/GUIWindowFileManager.cpp | 3 +- xbmc/windows/GUIWindowLoginScreen.cpp | 6 +- 92 files changed, 4822 insertions(+), 1998 deletions(-) create mode 100644 addons/skin.confluence/720p/DialogAccessPoints.xml create mode 100644 addons/skin.confluence/media/ap-lock.png create mode 100644 addons/skin.confluence/media/ap-signal1.png create mode 100644 addons/skin.confluence/media/ap-signal2.png create mode 100644 addons/skin.confluence/media/ap-signal3.png create mode 100644 addons/skin.confluence/media/ap-signal4.png create mode 100644 addons/skin.confluence/media/ap-signal5.png create mode 100644 addons/skin.confluence/media/connected.png create mode 100644 addons/skin.confluence/media/connecting.png create mode 100644 addons/skin.confluence/media/disconnected.png create mode 100644 xbmc/network/ConnectionJob.cpp create mode 100644 xbmc/network/ConnectionJob.h create mode 100644 xbmc/network/IConnection.h create mode 100644 xbmc/network/INetworkManager.h create mode 100644 xbmc/network/IPassphraseStorage.h delete mode 100644 xbmc/network/Network.cpp delete mode 100644 xbmc/network/Network.h create mode 100644 xbmc/network/NetworkManager.cpp create mode 100644 xbmc/network/NetworkManager.h create mode 100644 xbmc/network/NetworkUtils.cpp create mode 100644 xbmc/network/NetworkUtils.h create mode 100644 xbmc/network/NullNetworkManager.cpp create mode 100644 xbmc/network/NullNetworkManager.h create mode 100644 xbmc/network/linux/ConnmanConnection.cpp create mode 100644 xbmc/network/linux/ConnmanConnection.h create mode 100644 xbmc/network/linux/ConnmanNetworkManager.cpp create mode 100644 xbmc/network/linux/ConnmanNetworkManager.h delete mode 100644 xbmc/network/linux/Makefile create mode 100644 xbmc/network/linux/Makefile.in delete mode 100644 xbmc/network/linux/NetworkLinux.cpp delete mode 100644 xbmc/network/linux/NetworkLinux.h create mode 100644 xbmc/network/linux/PosixConnection.cpp create mode 100644 xbmc/network/linux/PosixConnection.h create mode 100644 xbmc/network/linux/PosixNetworkManager.cpp create mode 100644 xbmc/network/linux/PosixNetworkManager.h create mode 100644 xbmc/network/windows/WinConnection.cpp create mode 100644 xbmc/network/windows/WinConnection.h create mode 100644 xbmc/network/windows/WinNetworkManager.cpp create mode 100644 xbmc/network/windows/WinNetworkManager.h create mode 100644 xbmc/security/IKeyringManager.h create mode 100644 xbmc/security/KeyringManager.cpp create mode 100644 xbmc/security/KeyringManager.h create mode 100644 xbmc/security/Makefile create mode 100644 xbmc/security/MemoryKeyringManager.cpp create mode 100644 xbmc/security/MemoryKeyringManager.h create mode 100644 xbmc/security/XMLKeyringManager.cpp create mode 100644 xbmc/security/XMLKeyringManager.h create mode 100644 xbmc/utils/XMLVariantParser.cpp create mode 100644 xbmc/utils/XMLVariantParser.h create mode 100644 xbmc/utils/XMLVariantWriter.cpp create mode 100644 xbmc/utils/XMLVariantWriter.h diff --git a/.gitignore b/.gitignore index 9b4f7f0373cd9..d5a19a1ec6832 100644 --- a/.gitignore +++ b/.gitignore @@ -1099,6 +1099,7 @@ lib/cmyth/Makefile # /xbmc/network/ /xbmc/network/Makefile +/xbmc/network/linux/Makefile /xbmc/network/upnp/Makefile # /lib/libRTV/ diff --git a/Makefile.in b/Makefile.in index 39dc6f9000ff0..4d438d93b3cb4 100644 --- a/Makefile.in +++ b/Makefile.in @@ -77,6 +77,7 @@ DIRECTORY_ARCHIVES=$(DVDPLAYER_ARCHIVES) \ xbmc/pvr/timers/pvrtimers.a \ xbmc/pvr/windows/pvrwindows.a \ xbmc/rendering/rendering.a \ + xbmc/security/security.a \ xbmc/settings/settings.a \ xbmc/storage/storage.a \ xbmc/utils/utils.a \ diff --git a/addons/skin.confluence/720p/DialogAccessPoints.xml b/addons/skin.confluence/720p/DialogAccessPoints.xml new file mode 100644 index 0000000000000..8da2799a7f910 --- /dev/null +++ b/addons/skin.confluence/720p/DialogAccessPoints.xml @@ -0,0 +1,179 @@ + + 3 + dialogeffect + + + 340 + 110 + 600 + 500 + + background image + 0 + 0 + 600 + 500 + DialogBack.png + ![Window.IsVisible(FullscreenVideo) | Window.IsVisible(Visualisation)] + + + background image + 0 + 0 + 600 + 500 + DialogBack2.png + Window.IsVisible(FullscreenVideo) | Window.IsVisible(Visualisation) + + + Dialog Header image + 40 + 16 + 520 + 40 + dialogheader.png + + + heading label + 40 + 20 + 520 + 30 + font13_title + + center + center + selected + black + + + Close Window button + 510 + 15 + 64 + 32 + + - + PreviousMenu + DialogCloseButton-focus.png + DialogCloseButton.png + 3 + 3 + 3 + 3 + system.getbool(input.enablemouse) + + + 20 + 70 + 530 + 400 + 3 + 3 + 61 + 61 + 61 + 200 + + + 0 + 0 + 530 + 40 + MenuItemNF.png + + + 475 + 10 + 20 + 20 + !IsEmpty(ListItem.Property(encryption)) + ap-lock.png + + + 440 + 5 + 30 + 30 + ap-signal$INFO[ListItem.Property(signal)].png + + + 0 + 0 + 40 + 40 + $INFO[ListItem.Property(state)].png + + + 40 + 0 + 490 + 40 + font13 + grey2 + left + center + + + + + + 0 + 0 + 530 + 40 + MenuItemFO.png + + + 475 + 10 + 20 + 20 + !IsEmpty(ListItem.Property(encryption)) + ap-lock.png + + + 440 + 5 + 30 + 30 + ap-signal$INFO[ListItem.Property(signal)].png + + + 0 + 0 + 40 + 40 + $INFO[ListItem.Property(state)].png + + + 40 + 0 + 490 + 40 + font13 + selected + left + center + + + + + + 555 + 70 + 25 + 400 + ScrollBarV.png + ScrollBarV_bar.png + ScrollBarV_bar_focus.png + ScrollBarNib.png + ScrollBarNib.png + 3 + 3 + false + vertical + + + + diff --git a/addons/skin.confluence/media/ap-lock.png b/addons/skin.confluence/media/ap-lock.png new file mode 100644 index 0000000000000000000000000000000000000000..2ebc4f6f9663e32cad77d67ef93ab8843dfea3c0 GIT binary patch literal 749 zcmVe|tv9>?g+k#9o0pTxd@;_sq{kwlU;^VvV*?BV8P@}BoaZTQUROpWV6|-M`|^n&)=+8tHo3*<<$NU zU`%V~ZF;?hBSYsjJ6%JzV}E(D{pOLqQklliUf9um_tGl-wty`y*p?eYNW56P>X@1s zZs7KrRZKtmV7Lqj^5Fgr7_`LjhdJK@ltF&O`j7?*NUM$KvmNGz)3WjM?V$vHlPT0AFyF?kLE<#HZabCSW3-oa*6;Z zrXD`Ulwd<^2glP%1Y1Kc1Ij%DU^=ME(jKf6APNlA$Uu;J4bVilQHSWX5uJ$9Zsp4M z0%!@LvyTxz=Z6stxlichODIY+yNGt%RM;m`>H4LOKLFs9Y%b5aUN|2|{0Zw|<_~i} fmXz*V19AKYaKLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=00004XF*Lt006O$eEU(80000WV@Og>004R=004l4008;_004mL004C` z008P>0026e000+nl3&F}0002NNkl6cU z0{{R3|Nmk{*NbA#bp}S9vH$=80RR8Ouaf}}U|M=q=mAdIYyTPk|NsA=0UHJY00960 z!fPj9D;dZHOjj5f|6joq47dOQ009608UUx#U*nP^f)DUUCa%D_{GZ`J0|Ntt4#R&& zQZ%wKlj&3d00030{~|j&=pLw}7UGQjt7!R9o5a*ZvW5TX?Zfj&INu|CN!Nz976JeO c0RR630Q7}JzO%2mP5=M^07*qoM6N<$f}TNwl>h($ literal 0 HcmV?d00001 diff --git a/addons/skin.confluence/media/ap-signal2.png b/addons/skin.confluence/media/ap-signal2.png new file mode 100644 index 0000000000000000000000000000000000000000..d760d5b333d2f6784b791de6cba8f331075acd7c GIT binary patch literal 2961 zcmV;C3vTp@P)Oz@Z0f2-7z;ux~O9+4z06=<WDR*FRcSTFz- zW=q650N5=6FiBTtNC2?60Km==3$g$R3;-}uh=nNt1bYBr$Ri_o0EC$U6h`t_Jn<{8 z5a%iY0C<_QJh>z}MS)ugEpZ1|S1ukX&Pf+56gFW3VVXcL!g-k)GJ!M?;PcD?0HBc- z5#WRK{dmp}uFlRjj{U%*%WZ25jX z{P*?XzTzZ-GF^d31o+^>%=Ap99M6&ogks$0k4OBs3;+Bb(;~!4V!2o<6ys46agIcq zjPo+3B8fthDa9qy|77CdEc*jK-!%ZRYCZvbku9iQV*~a}ClFY4z~c7+0P?$U!PF=S z1Au6Q;m>#f??3%Vpd|o+W=WE9003S@Bra6Svp>fO002awfhw>;8}z{#EWidF!3EsG z3;bXU&9EIRU@z1_9W=mEXoiz;4lcq~xDGvV5BgyU zp1~-*fe8db$Osc*A=-!mVv1NJjtCc-h4>-CNCXm#Bp}I%6j35eku^v$Qi@a{RY)E3 zJ#qp$hg?Rwkvqr$GJ^buyhkyVfwECO)C{#lxu`c9ghrwZ&}4KmnvWKso6vH!8a<3Q zq36)6Xb;+tK10Vaz~~qUGsJ8#F2=(`u{bOVlVi)VBCHIn#u~6ztOL7=^<&SmcLWlF zMZgI*1b0FpVIDz9SWH+>*hr`#93(Um+6gxa1B6k+CnA%mOSC4s5&6UzVlpv@SV$}* z))J2sFA#f(L&P^E5{W}HC%KRUNwK6<(h|}}(r!{C=`5+6G)NjFlgZj-YqAG9lq?`C z$c5yc>d>VnA`E_*3F2Qp##d8RZb=H01_mm@+|Cqnc9PsG(F5HIG_C zt)aG3uTh7n6Et<2In9F>NlT@zqLtGcXcuVrX|L#Xx)I%#9!{6gSJKPrN9dR61N3(c z4Tcqi$B1Vr8Jidf7-t!G7_XR2rWwr)$3XQ?}=hpK0&Z&W{| zep&sA23f;Q!%st`QJ}G3cbou<7-yIK2z4nfCCCtN2-XOGSWo##{8Q{ATurxr~;I`ytDs%xbip}RzP zziy}Qn4Z2~fSycmr`~zJ=lUFdFa1>gZThG6M+{g7vkW8#+YHVaJjFF}Z#*3@$J_By zLtVo_L#1JrVVB{Ak-5=4qt!-@Mh}c>#$4kh<88)m#-k<%CLtzEP3leVno>={htGUuD;o7bD)w_sX$S}eAxwzy?UvgBH(S?;#HZiQMoS*2K2 zT3xe7t(~nU*1N5{rxB;QPLocnp4Ml>u<^FZwyC!nu;thW+pe~4wtZn|Vi#w(#jeBd zlf9FDx_yoPJqHbk*$%56S{;6Kv~mM9!g3B(KJ}#RZ#@)!hR|78Dq|Iq-afF%KE1Brn_fm;Im z_u$xr8UFki1L{Ox>G0o)(&RAZ;=|I=wN2l97;cLaHH6leTB-XXa*h%dBOEvi`+x zi?=Txl?TadvyiL>SuF~-LZ;|cS}4~l2eM~nS7yJ>iOM;atDY;(?aZ^v+mJV$@1Ote z62cPUlD4IWOIIx&SmwQ~YB{nzae3Pc;}r!fhE@iwJh+OsDs9zItL;~pu715HdQEGA zUct(O!LkCy1<%NCg+}G`0PgpNm-?d@-hMgNe6^V+j6x$b<6@S<$+<4_1hi}Ti zncS4LsjI}fWY1>OX6feMEuLErma3QLmkw?X+1j)X-&VBk_4Y;EFPF_I+q;9dL%E~B zJh;4Nr^(LEJ3myURP{Rblsw%57T)g973R8o)DE9*xN#~;4_o$q%o z4K@u`jhx2fBXC4{U8Qn{*%*B$Ge=nny$HAYq{=vy|sI0 z_vss+H_qMky?OB#|JK!>IX&II^LlUh#rO5!7TtbwC;iULyV-Xq?ybB}ykGP{?LpZ? z-G|jbTmIbG@7#ZCz;~eY(cDM(28Dyq{*m>M4?_iynUBkc4TkHUI6gT!;y-fz>HMcd z&t%Ugo)`Y2{>!cx7B7DI)$7;J(U{Spm-3gBzioV_{p!H$8L!*M!p0uH$#^p{Ui4P` z?ZJ24cOCDe-w#jZd?0@)|7iKK^;6KN`;!@ylm7$*nDhK&GcDTy000JJOGiWi{{a60 z|De66lK=n!32;bRa{vGi5C8xU5CQqnP&ohq00(qQO+^RX0|6ElBtr!CrE$3Ah~NWAoIrdMZT(Jxfq{YH zFAfcq=2{j*n-B7|Fc_zWq#DdfD+^h1h_g}Xdlp=&=F3+!zi>mS=dYMi!dzXPL<>(J z;e3y5w5AP&KCzeU6C*qf85vA`A>!u`b22a@WqkV}(kui38Ga|3hvM(600000NkvXX Hu0mjf)e?JP literal 0 HcmV?d00001 diff --git a/addons/skin.confluence/media/ap-signal3.png b/addons/skin.confluence/media/ap-signal3.png new file mode 100644 index 0000000000000000000000000000000000000000..39fb84e29307abf2a13fc6ed55b19bdee7b24901 GIT binary patch literal 3180 zcmV-y43qPTP)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=00004XF*Lt006O$eEU(80000WV@Og>004R=004l4008;_004mL004C` z008P>0026e000+nl3&F}0004pNkl|NsA=;lK-2I{^Ry0RR8OYbQQ{ z;-2-FdH-*?%=e#xfq~&B1LOajNFjv|SYW}Z!|s0RR91|No+nQ>mhH z`ew0bGq#97Bg(1kFZ2FqWME_n(EY>+3mA2V|BP4zXUP%42aJr24AIu_6jYG{=NAE| zvKZKWkcV-QgNc!lMrI_=&#zGB+zbqFUok^W634C)00030{~|j&s2&@%0xYCz*#Dg4 zKP=E085kHGBz`bb#lq`o`AHL+d_*OGQs%>}Xa;LT4gP~e1En#}@(+guD-LmX3N2+h ze}wZrawO>5KKLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=00004XF*Lt006O$eEU(80000WV@Og>004R=004l4008;_004mL004C` z008P>0026e000+nl3&F}0005)NklMnJL|BSFO(PjA02oEe+FzPV;XH?Ps0ypG0l8r133=HV*0ssI2 z|NkP&sRV-#pC6}hl6Xy&jng-aJ!52KWXSM&DFurMZ6rUEA2>^n2tHtBWMqi8ey5;{ z6ga;KIG@G9=7T(pgY0NVBsMcPjmUyOp{ay{n}Ol&D`tpE;tUM;Zn7~jF#KoGQb(u- z00030{~|j&$OSCaGHCM+p8v40VPs%n@KOK5NEHkBKj%O(*g@h4BLf2igNnvi%6xbo zIj=J?Fla)PjHu*Ktm^*|8>Cm!42C6QTn11Y<1GJhNU-7%XUAbFE0K<2Ie&!nJ#y^o z+Cb<%o47wQ!ZQdXgN83eeA`-{uZ#=~42)25^&p7&)|I?JkkxC3VYd)40O4=AWS1Fe Q?EnA(07*qoM6N<$f|BGD&;S4c literal 0 HcmV?d00001 diff --git a/addons/skin.confluence/media/ap-signal5.png b/addons/skin.confluence/media/ap-signal5.png new file mode 100644 index 0000000000000000000000000000000000000000..5b833bd44b327773a0f92dda9b8863b27cbdc9b1 GIT binary patch literal 3395 zcmX9=cRbXO|9^|l9@#=UJJ~avJI*GYoRIC5%#^LWaL)LUWM?INWQ2sAk(m>+S9S<- zL>c!zzu)umcs*W^*YmX=uh;9JSL|I=J$jn!Gynk58|dp;kTefT7^px1KxV{h{EB2y z`|8^~A#qHXLiYFDU1b2EF?$Gw-o5ML6X5g2!^fA;01D;v_4jdq_}C2qf@X3ok#NgR zcJR;_1ehCf{lvL0uqm6O%@gdQ!^Q2!3EQ7<{j5`bt$;}^0DNJiKqlNb8)&j znkmXv@Y}@5LTuc?=~8H+=S1uA`p`wgq{c=iA*X(r5=TXsrY~o%fTAmd+_?55vbVcu zX;o4SO(WHr?9K;`hgI9&iC4Y0Z!bt?l?5`eUUwYxr0(*)q~Otf_X6&)aLj*Y$rP=o@G zeF6eOKvX8c3Ole?+rM4Sv>`^?RA!x8v!Jpr+LlVfkJ8#&@`fnhfa5l+qSF2%;Z-sU#JRZ>IKRu3juVd6|0P;6ytO>rCyU{Ip**rbHwz@iH*bT9D8n6z( zKz2Idtj{0+jZix~KKk)_Sr9F2kJh6&`O*3H(71?a_!V`O^W1up-dPhZ@r-wjzuUmM z86n2HV$STBsFRgIkS*emg}l1;MQD`hy1XcUO0Kb}0MtCvAPY^FD7AMX|6?S=gb2Vb z9|OQai%-XQQ7UqjN959QAaPIgTrXb;K)D;d@&kYeI)ak$fqKneDge;QM~l^Hb02na zisL{$9arZ%XwMuKqacFaoe(AnjVp@B-|<%E3y3IYsD@X}QR=%EuRPA&1C!#*AlYg4 zkwM*;@t+e_Zii?qnwmnpkBY?!JcA{3jzb6}QgLKPpMX2`DVXC0`TDV}=KMy<3i>h@ zad18>ecl6g|0~KdcCb&$s(pa$i!)5Cp3G}>ow@pVx&~--snYc**jw6ft^qPxN$mOA z-~2yZS5HtZ*!WiA!8nto0qvE>{p6&S>wYXP+0zB7y(3PY;xbsvUrATdbG_zXC3#Ei zk;`yxAO$m87e}o~5eVUPx}mL)Fh-b8>6h~H2+CiZp;n?Mk23ER;ZG?w`XK!2+TU(Y zXIYsTgub}I1alIL6jLY`+N~tW91E2dX?}Udp!OYnlz9|3>TMygDPEQ>uYX-2rGLiN zvyM{vwK(7HzUbAQ)vi^!Rqj>rfh|prvzFhx6U${$i-AXmTx(2g@@pWs3|Vcf!YqsV z(gOH3g{1qCs)9y~_vSIBEb>pYl!qeO4UCGa-lmRS_u%k2e)#@pz^7~TsW(j1zgdqC zZtDF^|4DurNJo!hi|oZBMY*y$DLIi`ft>F%jElL(;<Ph85^05nLbtsu|}~l zw&VetRKrx^RBkaTcv*RI`9e9Z6~Sr{o>cb0GQ1jQC1<%(M*Tgl!m2#y?zSbjC9+Jl zG^QL`>I2t&7h!WA3$p1l?lObEGtaMeSZVFyqjlk`4-yA^(pO-fq7}M@Ylo)8o{6<& zob$HCtCyD*C`088<*e&12(R5WDOWQ5PTmBVQg4Wsq!S|I7FhRgE#KlUmN#yeakKL* zPfJfjROnZjSLkiGDOT^4CquT^>l)uSvowY+7|^s zA2nX7-r0R~sC}0fw8$ydDSas_xp_pba2)m@j4|P1kKKykidTe5+X1Sk<_9=A4$h+(GT zDY=zKmcd)y4|6QD$MldK$mS=J1Z;e)(ThRJbPdUD?wT4P_>+;EUh+c#~7a+P4Lx>|l2}+0z zNgj*VM%!LFJqZZ|wtz-Acq0R!jDN@w zeK+Fg#5YQ(b*K2Q2s)AIm}qN^W}+_^aeYK4T_JE}4*FzK=buiR&O$a)#!UIWgrS0% zM!Do8wHc*P@}D$&B;9Skjw5mq29J$+lqJQg6}=ySUOd|P75)2@VaWJvYd`vw=_ zI}f8v*vllD#Z}U@jIpM7UjNo+5-Vj-5ISH96iTEC?&R%6@=J{lvSyth!2@OysNNmwu3Put`cIatpcc z{%o+)ExPXFi+6mJ)Qwcie$V=sl~-*fXc{5KKjHU9C&ei1kZ#uQ?L)Bx%4rq3w}*DV z)(_0SRC=?QN8DlVWL|pJScEaMmf%IKw^cq;u2b_1o~2n~yLuaQ4^*l4F|JX}Yuv12 z$2z?_qD?rs9XW8g(c1DWSGtrg8$boln%DA)&p>~9`4Bqt9Gau*|?|s-g`lCB5 zl|Cdo+Y;FbZ7ytA``GGM(vKff)r7x;AHx5^6?aGH8=NLjyhnDqLtFpI{~DjQZ9P8M z=>I%xMP_9(?mq5zYH(VAtXUmfzIl>%>SbSL>gBi7OFl||PAS09INAJtoOe_mZjm%` zds~m8_vYt|oV`E^dPRDx|K9X03;5~;uWlYwFCO2ZSDAU15L&rJId=0IFOpa45hUv% z3zlt}b!zKu`^oI9#>m9hLdcok>`lfu@@h80h6H&3!JsBOR9jW?b_X8=4(evtSgb!VCY*ovVbOKWq!$XD3dK=PIkuw-G{oj=vlqEwax?_=}w52V15C zMRu!N%~~A}wRW_pq4P20nzk2nQ+spIAK?P?2_tiQ$DruQ;fv&>Bu41fq|Bs23_WH$ z_l}0L^0KD?`Q}*(bl7!RIG5w%?Zsd<2fI|n$@umpek5b0ApIacrQIv6=zI&e&Gmk^ zr?cnA=l&o$nFojWPIo#2=K^{63Ktp8R>Sz7ixNHl)*e}YD>+T!N=YG7kY^CiT;wEX zN&hAVQrkou0BRG%PR&zDHlK^Wg$V$J2mt^p5&-@ZNqQ3io=OA2mLmYDWB>q%&nt&7 zFaWsnz(7YE9yH^8LL_RE)0x>w{mFCMcS2L96Xni`B(AH7NJk_i6(tg#NdzgTMw$dW zcgM3~91cfvTza%7RJ~Gu){_$C?EVh_CLTP;5XC3CIEkLJXGk?d>SlYIG7C8gUFX@4 z>GCvXW&S@AG7_6m;>`qQ%lK?_IL%h-DM>`04A-n;`QiwY;M&ZD%EdwA$v_{e6Ylq} zkX%q2hkUpq6p%*h>t==Q%_t`)PSSs1s=@e$mfOy}z4=!j~Lryn3a@}#o-17&@V zTcCYnLP7$a&S^3U;IX}{b4hm;Oc%xfBwX5E8%5u(N&`QT3U{_*<@An42JR84x}m9M-$>v1RJ`?8hwS?J(ts9yWL^V^_}wkv=>pu%ph+Nrs;hK zSU6Trdai{!mO|nw2t!+Phw~Buzp{${RnK99wz#9KtK+-k=xm?gXED+A0_5b8N&h%t zAP@+{UBi>`rpkcqH1A11=P$nf$YeAct*yIq``%Ieh`_b!?b;{M-x|3||QMD86u z#|B6bTFFN?6o6J_QQxT?b(((PWQeZ3(>?8n7>I+OF=h?g;BPL4CHPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igh( z0~wCS<{002mIMObu0Z*6U5Zgc=BV<{jqFfcYCN?~htVjxp=Wod3@ataD#a%Ew3 zWn>_CX>@2HbZBKDM@dakAUZlAXmoUNIxjD0X>D*WZ*pfN|5!i(00Z_(L_t(o!|j$& zXk0}c$GmQg|t?h);1}aCQTdD&F&`I&F*Hi@6EiKpNEa<$ z{^mWPPMtdc4c0#muo@>40Ac_<03PFT$shpWZ&eY1u4Ten1VkA}XU8eL*7gh=Z63f= z_I`@X6_zbbqL~fUrTp{bKbmvNQ^!Gnf>LPBNNH7jyEi042mj; zw0|4EF2m!E7>7k6h0#l|<}TAzkVT4!f;~CF7_+^Y^Z3YD^5?gYpH8$|Ni0=v zA|wR>AQ%u44AWr5(ACh3vM%7$$@kO0y>5;9MLA2f_3&;Sa9uZXXhNSJKl#$g6R~4_ zwmbzzJ`B?^2%({1m_`T*MG|W&g|0{sj3eC@YazD&tC-YU@0bU^WA9j&7a!NBjpBJ040;hy3Sxj=Mj=ZceEFgCbz+BkQ8!s7u;}EFAIzVj4=>1;GBa@)e&P1EI0_HPo^x2L}Xmok=a!n3L!Wvdh5Z!trw0bU$nAv z5r&6bZ_Kt`AXLNX@d%DIK8LgO-}rMM^Y_+g)s&Rd-}O15lnTUZEG2r2!(ON99&8!q zWwVZo*#HLzfj~rn0h&bu0}UrIy>?MwKf7>l`HRR$g+gI<&quLRDxlfctL46%Cki6n zG#r24ii>VUcoQNlin#qS4mka2w-4g{o$vhVYd7YWK4^VwEuCM~TI)Rv&|2$YBP_`C zZQqt;0e2D?hBo}7vMonMMGGrb@@6hG?O#~>QO|v@&ZN#XPpqVJe+EGiJkZav5JI%H zw6ruOy)LgO81#DOQSUL;@6X%Q{;YGw|HHjf%KE8XE|)XLn1ADcU|Wdmx~}6mju67q oT8C0f83aLaKbF_2Q|EujU*aVAd}tS*dH?_b07*qoM6N<$fPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igh( z0~;RBw+&+e002mIMObu0Z*6U5Zgc=BV<{jqFfcYCN?~htVjxp=Wod3@ataD#a%Ew3 zWn>_CX>@2HbZBKDM@dakAUZlAXmoUNIxjD0X>D*WZ*pfN|5!i(00ZkuL_t(o!|hf} zY+FSXJ@a|**|F=!X_DH8q)llQiUdM}H4An~*;YbAUGQ0z1uHg{ zSg@c-6`uuvRUn0eL|WRUA}&o*lDf8&I1!WRA;$bWLMCN~lQVgNz_LY%>~gaClQVkH2knGKsE5akT16OZGiCl0cs{XKYS zM~ph=i!47rgWrCg41F--d~{@ZB$0gJ6={uy_6zV! zGcdXW?nKbhGbFov`r41~`sKx6(=?V}LWYQfO)0<_b7E2V{*O0Gb76bw#0|G-!ycb3lG5YzN*_YpzL#47x6OrDq0-on}j=W$_4L|eTky!FkUdfMv ztPchQP#qu*Mg|}SG77qyK{&n-u27y-)3Ki?#i%i6-Fo2b_KuXHV-K4XJNF)w)rCud zt%6JdSifPU0P8pANCBpb<+*Q==sx5OA2!cBjuYB&e{#-cqKzlRk?kIrEvQ$sV2pt= z1`u0G5di?KT7>a)Fu@|oYD9PRVq3&(Y2VH}Yc)P+t*tjrKnUUPP1!y#lB(4C_uonGCBHFXeCBQ=b{1d9mA?lJqjZXL|bi*YGsn^G#@6agZ#H6@m{s(`G9 z^)rCt0Ow##tg69a!8r#JfrwzO1-J{Pe5wSZL`2r}Jg$^#t_F-TYC7j!r6A`?uN7Rl zYe5+U=X_->{x)Xd!i98WFtuCmbk3PD#;8iAl5e^QiO5z16z7*Hr>i-*u|19aqY(^@ zgY$-g@l~H2+XG$AA-}{kzQQsQSt7C0SNiQZ?WF5dtnvl4hs1)x!k zT(%&Rd=l3$ed51&j=zzf)niI2f5Z2H);d_I#4^2!(j%!h+a2#7N3DMfR(%x zAi|w!Ne<%n>;?1f==AvyzYo7#EEX3weHCl1gLJO#QeVflL7}tTI(nXxGSUU^#K2?} zPNWNN>j5~?-MBIFnSXiw>K|{NZF?=7U;NV;V>V5|7-P!Sdhv(f+s~<55uNO(fm*es zrF4bx;;dF)w7I!)e{S+?bLLBZ`t+x*Bbi)bHVA^?u0F>?2oaCRPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igh( z0~#{rbWp(n002mIMObu0Z*6U5Zgc=BV<{jqFfcYCN?~htVjxp=Wod3@ataD#a%Ew3 zWn>_CX>@2HbZBKDM@dakAUZlAXmoUNIxjD0X>D*WZ*pfN|5!i(00Y!XL_t(o!|j$& zXk0}c$GYrCzFnM~mQ1 zJa}j*w4_idG}J?z+D)Ko{#4Uu^J4Ov-Rz$?@4cCyhfRzMsof@uhyB18-XECxyqVvR zc|eUCHU1l{onEji2ND2M0Ac`Q9FPW30Q}A50qAN5tVSTof!5Q&yKgc!bOdjR8LxU>QJRPX!ob%^jS-dd`@ykM#E+YCUyII_>SS8XFOdwT({KuSs^oucfiOAg(0nT~-QO-xcvaAb-&zz~-H#o>tHVd84Ll=wSQbHsWkZo-! zW-@f|{Q1&{LGb=vW5$g!xm^h`#_W{i^n4!#R|iK&o2-@=l<(gMMG-($i7|lIAjVMF z(*wP}jvJ$+%kNp%TN^}71fSNDVxq}{mI)WPri{lc8nKq-2y2ErZo^n+X+KJ zDFlxmA>P#msgx883#p%kxS_RvVmT@f4M7mBR3$(}rYyupR4f8v2$RhMoP#(A;~b2! zN{GNY2N8h)7-PU32chp%Nr*fV87UgW=V`F||U;sRk`0FZcX6s%g5{UQrWB$@5|3V^hPAOG* zn!{yB!Z1{;snk+;KL2{FG41K$VQz9cm_nh_4FIUJS`aNQs2du>+RdB#>cYac@8a># zbGh8=t^~FuW*QnM56{jHi{<5g2aX@Ntb+%^Qz`I70#`jcKx?fFQIxyh*!ZK$<GetHostName().c_str()); + CLog::Log(LOGNOTICE, "Local hostname: %s", m_network.GetDefaultConnectionName().c_str()); CLog::Log(LOGNOTICE, "Log File is located: %sxbmc.log", g_settings.m_logFolder.c_str()); CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------"); @@ -744,6 +732,8 @@ bool CApplication::Create() CAEFactory::SetMute (g_settings.m_bMute); CAEFactory::SetSoundMode(g_guiSettings.GetInt("audiooutput.guisoundmode")); + m_network.Initialize(); + // initialize the addon database (must be before the addon manager is init'd) CDatabaseManager::Get().Initialize(true); @@ -1280,10 +1270,8 @@ bool CApplication::Initialize() g_windowManager.Add(new CGUIDialogBusy); g_windowManager.Add(new CGUIDialogPictureInfo); g_windowManager.Add(new CGUIDialogAddonInfo); - g_windowManager.Add(new CGUIDialogAddonSettings); -#ifdef HAS_LINUX_NETWORK - g_windowManager.Add(new CGUIDialogAccessPoints); -#endif + g_windowManager.Add(new CGUIDialogAddonSettings); // window id = 140 + g_windowManager.Add(new CGUIDialogAccessPoints); // window id = 141 g_windowManager.Add(new CGUIDialogLockSettings); @@ -1411,6 +1399,7 @@ bool CApplication::Initialize() // reset our screensaver (starts timers etc.) ResetScreenSaver(); + m_keyringManager.Initialize(); #ifdef HAS_SDL_JOYSTICK g_Joystick.SetEnabled(g_guiSettings.GetBool("input.enablejoystick") && @@ -1517,7 +1506,7 @@ bool CApplication::StartServer(enum ESERVERS eServer, bool bStart, bool bWait/* bool CApplication::StartWebServer() { #ifdef HAS_WEB_SERVER - if (g_guiSettings.GetBool("services.webserver") && m_network->IsAvailable()) + if (g_guiSettings.GetBool("services.webserver") && m_network.IsAvailable()) { int webPort = atoi(g_guiSettings.GetString("services.webserverport")); CLog::Log(LOGNOTICE, "Webserver: Starting..."); @@ -1573,7 +1562,7 @@ bool CApplication::StartAirplayServer() { bool ret = false; #ifdef HAS_AIRPLAY - if (g_guiSettings.GetBool("services.airplay") && m_network->IsAvailable()) + if (g_guiSettings.GetBool("services.airplay") && m_network.IsAvailable()) { int listenPort = g_advancedSettings.m_airPlayPort; CStdString password = g_guiSettings.GetString("services.airplaypassword"); @@ -1583,15 +1572,9 @@ bool CApplication::StartAirplayServer() { CAirPlayServer::SetCredentials(usePassword, password); std::map txt; - CNetworkInterface* iface = g_application.getNetwork().GetFirstConnectedInterface(); - if (iface) - { - txt["deviceid"] = iface->GetMacAddress(); - } - else - { + txt["deviceid"] = m_network.GetDefaultConnectionMacAddress(); + if (txt["deviceid"].empty()) txt["deviceid"] = "FF:FF:FF:FF:FF:F2"; - } txt["features"] = "0x77"; txt["model"] = "AppleTV2,1"; txt["srcvers"] = AIRPLAY_SERVER_VERSION_STR; @@ -1603,7 +1586,7 @@ bool CApplication::StartAirplayServer() #endif { #ifdef HAS_AIRTUNES - if (g_guiSettings.GetBool("services.airplay") && m_network->IsAvailable()) + if (g_guiSettings.GetBool("services.airplay") && m_network.IsAvailable()) { int listenPort = g_advancedSettings.m_airTunesPort; CStdString password = g_guiSettings.GetString("services.airplaypassword"); @@ -1866,8 +1849,6 @@ void CApplication::StartServices() void CApplication::StopServices() { - m_network->NetworkMessage(CNetwork::SERVICES_DOWN, 0); - #if !defined(_WIN32) && defined(HAS_DVD_DRIVE) CLog::Log(LOGNOTICE, "stop dvd detect media"); m_DetectDVDType.StopThread(); @@ -3490,9 +3471,6 @@ bool CApplication::Cleanup() while(1); // execution ends #endif - delete m_network; - m_network = NULL; - return true; } catch (...) @@ -3628,6 +3606,8 @@ void CApplication::Stop(int exitCode) } #endif + m_network.StopServices(); + g_Windowing.DestroyRenderSystem(); g_Windowing.DestroyWindow(); g_Windowing.DestroyWindowSystem(); @@ -5119,6 +5099,7 @@ void CApplication::Process() void CApplication::ProcessSlow() { g_powerManager.ProcessEvents(); + m_network.PumpNetworkEvents(); #if defined(TARGET_DARWIN_OSX) // There is an issue on OS X that several system services ask the cursor to become visible @@ -5892,9 +5873,14 @@ void CApplication::SetRenderGUI(bool renderGUI) m_renderGUI = renderGUI; } -CNetwork& CApplication::getNetwork() +CNetworkManager& CApplication::getNetworkManager() { - return *m_network; + return m_network; +} + +CKeyringManager& CApplication::getKeyringManager() +{ + return m_keyringManager; } #ifdef HAS_PERFORMANCE_SAMPLE CPerformanceStats &CApplication::GetPerformanceStats() @@ -5902,4 +5888,3 @@ CPerformanceStats &CApplication::GetPerformanceStats() return m_perfStats; } #endif - diff --git a/xbmc/Application.h b/xbmc/Application.h index 69609fae744d1..3fbb499e54128 100644 --- a/xbmc/Application.h +++ b/xbmc/Application.h @@ -53,6 +53,8 @@ namespace MEDIA_DETECT #ifdef _WIN32 #include "win32/WIN32Util.h" #endif +#include "network/NetworkManager.h" +#include "security/KeyringManager.h" #include "utils/Stopwatch.h" #include "utils/CharsetConverter.h" #ifdef HAS_PERFORMANCE_SAMPLE @@ -265,7 +267,10 @@ class CApplication : public CXBApplicationEx, public IPlayerCallback, public IMs static bool OnEvent(XBMC_Event& newEvent); - CNetwork& getNetwork(); + CNetworkManager& getNetworkManager(); + + CKeyringManager& getKeyringManager(); + #ifdef HAS_PERFORMANCE_SAMPLE CPerformanceStats &GetPerformanceStats(); #endif @@ -460,7 +465,8 @@ class CApplication : public CXBApplicationEx, public IPlayerCallback, public IMs CSeekHandler *m_seekHandler; CInertialScrollingHandler *m_pInertialScrollingHandler; - CNetwork *m_network; + CNetworkManager m_network; + CKeyringManager m_keyringManager; #ifdef HAS_PERFORMANCE_SAMPLE CPerformanceStats m_perfStats; #endif diff --git a/xbmc/ApplicationMessenger.cpp b/xbmc/ApplicationMessenger.cpp index 59c2ee23e33e5..724073436dd83 100644 --- a/xbmc/ApplicationMessenger.cpp +++ b/xbmc/ApplicationMessenger.cpp @@ -29,7 +29,6 @@ #endif #include "pictures/GUIWindowSlideShow.h" #include "interfaces/Builtins.h" -#include "network/Network.h" #include "utils/log.h" #include "utils/URIUtils.h" #include "utils/Variant.h" @@ -646,7 +645,7 @@ void CApplicationMessenger::ProcessMessage(ThreadMessage *pMsg) case TMSG_NETWORKMESSAGE: { - g_application.getNetwork().NetworkMessage((CNetwork::EMESSAGE)pMsg->dwParam1, (int)pMsg->dwParam2); + g_application.getNetworkManager().NetworkMessage((CNetworkManager::EMESSAGE)pMsg->dwParam1, (int)pMsg->dwParam2); } break; diff --git a/xbmc/GUIInfoManager.cpp b/xbmc/GUIInfoManager.cpp index a4098e00f3d2b..e50194174f3a9 100644 --- a/xbmc/GUIInfoManager.cpp +++ b/xbmc/GUIInfoManager.cpp @@ -18,7 +18,6 @@ * */ -#include "network/Network.h" #include "system.h" #include "GUIInfoManager.h" #include "windows/GUIMediaWindow.h" @@ -1513,7 +1512,6 @@ CStdString CGUIInfoManager::GetLabel(int info, int contextWindow, CStdString *fa break; case SYSTEM_VIDEO_ENCODER_INFO: - case NETWORK_MAC_ADDRESS: case SYSTEM_KERNEL_VERSION: case SYSTEM_CPUFREQUENCY: case SYSTEM_INTERNET_STATE: @@ -1712,7 +1710,7 @@ CStdString CGUIInfoManager::GetLabel(int info, int contextWindow, CStdString *fa { CStdString friendlyName = g_guiSettings.GetString("services.devicename"); if (friendlyName.Equals("XBMC")) - strLabel.Format("%s (%s)", friendlyName.c_str(), g_application.getNetwork().GetHostName().c_str()); + strLabel.Format("%s (%s)", friendlyName.c_str(), g_application.getNetworkManager().GetDefaultConnectionName().c_str()); else strLabel = friendlyName; } @@ -1759,39 +1757,20 @@ CStdString CGUIInfoManager::GetLabel(int info, int contextWindow, CStdString *fa break; #endif case NETWORK_IP_ADDRESS: - { - CNetworkInterface* iface = g_application.getNetwork().GetFirstConnectedInterface(); - if (iface) - return iface->GetCurrentIPAddress(); - } + return g_application.getNetworkManager().GetDefaultConnectionAddress(); break; case NETWORK_SUBNET_MASK: - { - CNetworkInterface* iface = g_application.getNetwork().GetFirstConnectedInterface(); - if (iface) - return iface->GetCurrentNetmask(); - } + return g_application.getNetworkManager().GetDefaultConnectionNetmask(); + break; + case NETWORK_MAC_ADDRESS: + return g_application.getNetworkManager().GetDefaultConnectionMacAddress(); break; case NETWORK_GATEWAY_ADDRESS: - { - CNetworkInterface* iface = g_application.getNetwork().GetFirstConnectedInterface(); - if (iface) - return iface->GetCurrentDefaultGateway(); - } + return g_application.getNetworkManager().GetDefaultConnectionGateway(); break; case NETWORK_DNS1_ADDRESS: - { - vector nss = g_application.getNetwork().GetNameServers(); - if (nss.size() >= 1) - return nss[0]; - } - break; case NETWORK_DNS2_ADDRESS: - { - vector nss = g_application.getNetwork().GetNameServers(); - if (nss.size() >= 2) - return nss[1]; - } + return g_application.getNetworkManager().GetDefaultConnectionNameServer(); break; case NETWORK_DHCP_ADDRESS: { @@ -1803,8 +1782,7 @@ CStdString CGUIInfoManager::GetLabel(int info, int contextWindow, CStdString *fa { CStdString linkStatus = g_localizeStrings.Get(151); linkStatus += " "; - CNetworkInterface* iface = g_application.getNetwork().GetFirstConnectedInterface(); - if (iface && iface->IsConnected()) + if (g_application.getNetworkManager().IsConnected()) linkStatus += g_localizeStrings.Get(15207); else linkStatus += g_localizeStrings.Get(15208); diff --git a/xbmc/Util.cpp b/xbmc/Util.cpp index 241bc9a62e740..4385d0cf8f87c 100644 --- a/xbmc/Util.cpp +++ b/xbmc/Util.cpp @@ -17,7 +17,6 @@ * . * */ -#include "network/Network.h" #include "threads/SystemClock.h" #include "system.h" #if defined(TARGET_DARWIN) @@ -1899,7 +1898,7 @@ void CUtil::ScanForExternalSubtitles(const CStdString& strMovie, std::vectorGetCurrentIPAddress(); - - return cTitleIP; + return g_application.getNetworkManager().GetDefaultConnectionAddress().c_str(); } long getDVDState() diff --git a/xbmc/music/MusicDatabase.cpp b/xbmc/music/MusicDatabase.cpp index bdee61aca872d..c387ddea5eeab 100644 --- a/xbmc/music/MusicDatabase.cpp +++ b/xbmc/music/MusicDatabase.cpp @@ -18,7 +18,6 @@ * */ -#include "network/Network.h" #include "threads/SystemClock.h" #include "system.h" #include "MusicDatabase.h" @@ -2390,7 +2389,7 @@ bool CMusicDatabase::LookupCDDBInfo(bool bRequery/*=false*/) return false; // check network connectivity - if (!g_application.getNetwork().IsAvailable()) + if (!g_application.getNetworkManager().IsAvailable()) return false; // Get information for the inserted disc diff --git a/xbmc/network/AirPlayServer.cpp b/xbmc/network/AirPlayServer.cpp index fd7f755a558a2..7fb58faca3407 100644 --- a/xbmc/network/AirPlayServer.cpp +++ b/xbmc/network/AirPlayServer.cpp @@ -17,7 +17,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "network/Network.h" #include "AirPlayServer.h" #ifdef HAS_AIRPLAY @@ -960,7 +959,7 @@ int CAirPlayServer::CTCPClient::ProcessRequest( CStdString& responseHeader, else if (uri == "/server-info") { CLog::Log(LOGDEBUG, "AIRPLAY: got request %s", uri.c_str()); - responseBody.Format(SERVER_INFO, g_application.getNetwork().GetFirstConnectedInterface()->GetMacAddress()); + responseBody.Format(SERVER_INFO, g_application.getNetworkManager().GetDefaultConnectionMacAddress()); responseHeader = "Content-Type: text/x-apple-plist+xml\r\n"; } diff --git a/xbmc/network/AirTunesServer.cpp b/xbmc/network/AirTunesServer.cpp index 8af8319ee5a7c..0c92ceacc5775 100644 --- a/xbmc/network/AirTunesServer.cpp +++ b/xbmc/network/AirTunesServer.cpp @@ -17,7 +17,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "network/Network.h" #if !defined(TARGET_WINDOWS) #pragma GCC diagnostic ignored "-Wwrite-strings" #endif @@ -468,21 +467,13 @@ bool CAirTunesServer::StartServer(int port, bool nonlocal, bool usePassword, con { bool success = false; CStdString pw = password; - CNetworkInterface *net = g_application.getNetwork().GetFirstConnectedInterface(); StopServer(true); - if (net) + m_macAddress = g_application.getNetworkManager().GetDefaultConnectionMacAddress(); + m_macAddress.Replace(":",""); + while (m_macAddress.size() < 12) { - m_macAddress = net->GetMacAddress(); - m_macAddress.Replace(":",""); - while (m_macAddress.size() < 12) - { - m_macAddress = CStdString("0") + m_macAddress; - } - } - else - { - m_macAddress = "000102030405"; + m_macAddress = CStdString("0") + m_macAddress; } if (!usePassword) diff --git a/xbmc/network/ConnectionJob.cpp b/xbmc/network/ConnectionJob.cpp new file mode 100644 index 0000000000000..c46ac336cb761 --- /dev/null +++ b/xbmc/network/ConnectionJob.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "ConnectionJob.h" +#include "Application.h" +#include "utils/log.h" +#include "dialogs/GUIDialogOK.h" +#include "dialogs/GUIDialogBusy.h" +#include "guilib/GUIKeyboardFactory.h" +#include "guilib/GUIWindowManager.h" +#include "security/KeyringManager.h" +#include "settings/GUISettings.h" +#include "settings/AdvancedSettings.h" + +CConnectionJob::CConnectionJob(CConnectionPtr connection, const CIPConfig &ipconfig, CKeyringManager *keyringManager) +{ + m_ipconfig = ipconfig; + m_connection = connection; + m_keyringManager = keyringManager; +} + +bool CConnectionJob::DoWork() +{ + bool result; + + CGUIDialogBusy *busy_dialog = (CGUIDialogBusy*)g_windowManager.GetWindow(WINDOW_DIALOG_BUSY); + busy_dialog->Show(); + + // we need to shutdown network services before changing the connection. + // The Network Manager's PumpNetworkEvents will take care of starting them back up. + g_application.getNetworkManager().OnConnectionStateChange(NETWORK_CONNECTION_STATE_DISCONNECTED); + result = m_connection->Connect((IPassphraseStorage*)this, m_ipconfig); + if (!result) + { + // the connect failed, pop a failed dialog + // and revert to the previous connection. + // Not connected. Check network settings. + CGUIDialogOK::ShowAndGetInput(0, 13297, 0, 0); + } + + busy_dialog->Close(); + return result; +} + +void CConnectionJob::InvalidatePassphrase(const std::string &uuid) +{ + m_keyringManager->EraseSecret("network", uuid); + g_guiSettings.SetString("network.passphrase", ""); +} + +bool CConnectionJob::GetPassphrase(const std::string &uuid, std::string &passphrase) +{ + passphrase = g_guiSettings.GetString("network.passphrase"); + if (passphrase.size() > 0) + return true; + /* + CVariant secret; + if (m_keyringManager->FindSecret("network", uuid, secret) && secret.isString()) + { + passphrase = secret.asString(); + return true; + } + */ + else + { + bool result; + CStdString utf8; + if (g_advancedSettings.m_showNetworkPassPhrase) + result = CGUIKeyboardFactory::ShowAndGetInput(utf8, 12340, false); + else + result = CGUIKeyboardFactory::ShowAndGetNewPassword(utf8); + + passphrase = utf8; + StorePassphrase(uuid, passphrase); + return result; + } +} + +void CConnectionJob::StorePassphrase(const std::string &uuid, const std::string &passphrase) +{ + m_keyringManager->StoreSecret("network", uuid, CVariant(passphrase)); + // hack until we get keyring storage working + g_guiSettings.SetString("network.passphrase", passphrase.c_str()); +} diff --git a/xbmc/network/ConnectionJob.h b/xbmc/network/ConnectionJob.h new file mode 100644 index 0000000000000..687a4fa681510 --- /dev/null +++ b/xbmc/network/ConnectionJob.h @@ -0,0 +1,43 @@ +#pragma once +/* + * Copyright (C) 2005-2010 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "system.h" +#include "IConnection.h" +#include "utils/Job.h" + +class CKeyringManager; + +class CConnectionJob : public CJob, public IPassphraseStorage +{ +public: + CConnectionJob(CConnectionPtr connection, const CIPConfig &ipconfig, CKeyringManager *keyringManager); + + virtual bool DoWork(); + + virtual void InvalidatePassphrase(const std::string &uuid); + virtual bool GetPassphrase(const std::string &uuid, std::string &passphrase); + virtual void StorePassphrase(const std::string &uuid, const std::string &passphrase); +private: + CIPConfig m_ipconfig; + CConnectionPtr m_connection; + CKeyringManager *m_keyringManager; +}; diff --git a/xbmc/network/GUIDialogAccessPoints.cpp b/xbmc/network/GUIDialogAccessPoints.cpp index e04d276357a81..e454e73bc3791 100644 --- a/xbmc/network/GUIDialogAccessPoints.cpp +++ b/xbmc/network/GUIDialogAccessPoints.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2012 Team XBMC + * Copyright (C) 2011-2012 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify @@ -13,120 +13,298 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html * */ #include "GUIDialogAccessPoints.h" -#include "guilib/GUIKeyboardFactory.h" -#ifdef _LINUX -#include "linux/NetworkLinux.h" -#endif +#include "dialogs/GUIDialogKeyboardGeneric.h" #include "Application.h" +#include "ApplicationMessenger.h" #include "FileItem.h" #include "guilib/LocalizeStrings.h" +#include "guilib/GUIWindowManager.h" +#include "utils/JobManager.h" +#include "ConnectionJob.h" -#define CONTROL_ACCESS_POINTS 3 +// defines for the controls +#define ACCESS_POINT_LABEL 1 +#define ACCESS_POINT_LIST 3 +//-------------------------------------------------------------- +const std::string EncodeAccessPointParam(const std::string name, const CIPConfig &ipconfig) +{ + // encode CIPConfig structure into a string based ip connect param. + std::string method("dhcp"); + if (ipconfig.m_method == IP_CONFIG_STATIC) + method = "static"; + + // '+' and '\t' are invalid essid characters, + // a ' ' is valid so watch out for those in the name. + const std::string param("name+" + name + "\t" + + "method+" + method + "\t" + + "address+" + ipconfig.m_address + "\t" + + "netmask+" + ipconfig.m_netmask + "\t" + + "gateway+" + ipconfig.m_gateway + "\t" + + "nameserver+" + ipconfig.m_nameserver + "\t"); + return param; +} + +//-------------------------------------------------------------- +//-------------------------------------------------------------- CGUIDialogAccessPoints::CGUIDialogAccessPoints(void) : CGUIDialog(WINDOW_DIALOG_ACCESS_POINTS, "DialogAccessPoints.xml") { - m_accessPoints = new CFileItemList; + m_connectionsFileList = new CFileItemList; } CGUIDialogAccessPoints::~CGUIDialogAccessPoints(void) { - delete m_accessPoints; + delete m_connectionsFileList; } bool CGUIDialogAccessPoints::OnAction(const CAction &action) { if (action.GetID() == ACTION_SELECT_ITEM) { - CGUIMessage msg(GUI_MSG_ITEM_SELECTED, GetID(), CONTROL_ACCESS_POINTS); - OnMessage(msg); - int iItem = msg.GetParam1(); + // block users from doing another connection + // while we are already trying to connect. + if (!m_doing_connection) + { + // fetch the current selected item (access point) + CGUIMessage msg(GUI_MSG_ITEM_SELECTED, GetID(), ACCESS_POINT_LIST); + OnMessage(msg); + int iItem = msg.GetParam1(); + + ConnectionList connections = g_application.getNetworkManager().GetConnections(); + CConnectionJob *connection = new CConnectionJob(connections[iItem], + m_ipconfig, &g_application.getKeyringManager()); + CJobManager::GetInstance().AddJob(connection, this); + m_doing_connection = true; + } + return true; + } + else if (action.GetID() == ACTION_CONNECTIONS_REFRESH) + { + // msg from Network Manager when the network connection changes. + // this is for future support for scanning for new access points. + UpdateConnectionList(); + return true; + } - if (iItem == (int) m_aps.size()) + return CGUIDialog::OnAction(action); +} + +bool CGUIDialogAccessPoints::OnMessage(CGUIMessage& message) +{ + bool result = CGUIDialog::OnMessage(message); + switch (message.GetMessage()) + { + case GUI_MSG_WINDOW_INIT: { - m_selectedAPEssId = ""; - if (CGUIKeyboardFactory::ShowAndGetInput(m_selectedAPEssId, g_localizeStrings.Get(789), false)) - { - m_selectedAPEncMode = m_aps[iItem].getEncryptionMode(); - m_wasItemSelected = true; - Close(); - return true; - } + m_use_ipconfig = false; + m_doing_connection = false; + // fetch the param list + std::string param(message.GetStringParam()); + + // network apply vs network connect + if (param.find("name+") != std::string::npos) + { + m_use_ipconfig = true; + // network apply, param contains a description for connecting + // to an access point. we want to find this access point, + // disable the others, then inject a OnAction msg to select it. + DecodeAccessPointParam(param); + // change the label to show we are doing a connection. + CGUIMessage msg(GUI_MSG_LABEL_SET, GetID(), ACCESS_POINT_LABEL); + // Connecting + msg.SetLabel(g_localizeStrings.Get(33203)); + OnMessage(msg); + } + UpdateConnectionList(); + // if we are doing an 'apply', then inject a click on the "selected" item. + if (m_use_ipconfig) + CApplicationMessenger::Get().SendAction(CAction(ACTION_SELECT_ITEM), GetID()); + break; } - else + case GUI_MSG_WINDOW_DEINIT: { - m_selectedAPEssId = m_aps[iItem].getEssId(); - m_selectedAPEncMode = m_aps[iItem].getEncryptionMode(); - m_wasItemSelected = true; - Close(); - return true; } } - return CGUIDialog::OnAction(action); + return result; } -void CGUIDialogAccessPoints::OnInitWindow() +bool CGUIDialogAccessPoints::OnBack(int actionID) { - m_wasItemSelected = false; + // block the user from closing us if we are trying to connect. + if (m_doing_connection) + return false; + else + return CGUIDialog::OnBack(actionID); +} - CGUIDialog::OnInitWindow(); +//-------------------------------------------------------------- +//-------------------------------------------------------------- +void CGUIDialogAccessPoints::OnJobComplete(unsigned int jobID, bool success, CJob *job) +{ + // auto-close when connection job completes + m_doing_connection = false; + if (success) + { + Close(true); + } +} - CGUIMessage msgReset(GUI_MSG_LABEL_RESET, GetID(), CONTROL_ACCESS_POINTS); - OnMessage(msgReset); +void CGUIDialogAccessPoints::UpdateConnectionList() +{ + m_connectionsFileList->Clear(); - m_accessPoints->Clear(); + CGUIMessage msgReset(GUI_MSG_LABEL_RESET, GetID(), ACCESS_POINT_LIST); + OnMessage(msgReset); - CStdString ifaceName(m_interfaceName); - CNetworkInterface* iface = g_application.getNetwork().GetInterfaceByName(ifaceName); - m_aps = iface->GetAccessPoints(); + int connectedItem = 0; + ConnectionList connections = g_application.getNetworkManager().GetConnections(); - for (int i = 0; i < (int) m_aps.size(); i++) + std::string connection_name; + for (size_t i = 0; i < connections.size(); i++) { - CFileItemPtr item(new CFileItem(m_aps[i].getEssId())); + connection_name = connections[i]->GetName(); + CFileItemPtr item(new CFileItem(connection_name)); - int q = m_aps[i].getQuality(); - if (q <= 20) item->SetArt("thumb", "ap-signal1.png"); - else if (q <= 40) item->SetArt("thumb", "ap-signal2.png"); - else if (q <= 60) item->SetArt("thumb", "ap-signal3.png"); - else if (q <= 80) item->SetArt("thumb", "ap-signal4.png"); - else if (q <= 100) item->SetArt("thumb", "ap-signal5.png"); + if (m_use_ipconfig) + { + if (connection_name.find(m_ipname) != std::string::npos) + connectedItem = i; + } + else + { + if (connections[i]->GetState() == NETWORK_CONNECTION_STATE_CONNECTED) + connectedItem = i; + } + if (connections[i]->GetType() == NETWORK_CONNECTION_TYPE_WIFI) + { + int signal, strength = connections[i]->GetStrength(); + if (strength == 0 || strength < 20) + signal = 1; + else if (strength == 20 || strength < 40) + signal = 2; + else if (strength == 40 || strength < 60) + signal = 3; + else if (strength == 60 || strength < 80) + signal = 4; + else + signal = 5; - if (m_aps[i].getEncryptionMode() != ENC_NONE) - item->SetIconImage("ap-lock.png"); + if (strength <= 20) item->SetArt("thumb", "ap-signal1.png"); + else if (strength <= 40) item->SetArt("thumb", "ap-signal2.png"); + else if (strength <= 60) item->SetArt("thumb", "ap-signal3.png"); + else if (strength <= 80) item->SetArt("thumb", "ap-signal4.png"); + else if (strength <= 100) item->SetArt("thumb", "ap-signal5.png"); - m_accessPoints->Add(item); - } + item->SetProperty("signal", signal); + item->SetProperty("encryption", EncryptionToString(connections[i]->GetEncryption())); + } - CFileItemPtr item(new CFileItem(g_localizeStrings.Get(1047))); - m_accessPoints->Add(item); + item->SetProperty("type", ConnectionTypeToString(connections[i]->GetType())); + item->SetProperty("state", ConnectionStateToString(connections[i]->GetState())); + + m_connectionsFileList->Add(item); + } - CGUIMessage msg(GUI_MSG_LABEL_BIND, GetID(), CONTROL_ACCESS_POINTS, 0, 0, m_accessPoints); + CGUIMessage msg(GUI_MSG_LABEL_BIND, GetID(), ACCESS_POINT_LIST, connectedItem, 0, m_connectionsFileList); OnMessage(msg); } -void CGUIDialogAccessPoints::SetInterfaceName(CStdString interfaceName) +void CGUIDialogAccessPoints::DecodeAccessPointParam(const std::string ¶m) { - m_interfaceName = interfaceName; + // decode a string based ip connect param into a CIPConfig structure. + std::string::size_type start; + std::string::size_type end; + + start = param.find("name+") + sizeof("name"); + end = param.find("\t", start); + m_ipname = param.substr(start, end - start); + // + start = param.find("method+") + sizeof("method"); + end = param.find("\t", start); + m_ipconfig.m_method = IP_CONFIG_DHCP; + if (param.find("static", start) != std::string::npos) + m_ipconfig.m_method = IP_CONFIG_STATIC; + // + start = param.find("address+") + sizeof("address"); + end = param.find("\t", start); + m_ipconfig.m_address = param.substr(start, end - start); + // + start = param.find("netmask+") + sizeof("netmask"); + end = param.find("\t", start); + m_ipconfig.m_netmask = param.substr(start, end - start); + // + start = param.find("gateway+") + sizeof("gateway"); + end = param.find("\t", start); + m_ipconfig.m_gateway = param.substr(start, end - start); + // + start = param.find("nameserver+") + sizeof("nameserver"); + end = param.find("\t", start); + m_ipconfig.m_nameserver = param.substr(start, end - start); } -CStdString CGUIDialogAccessPoints::GetSelectedAccessPointEssId() +const char *CGUIDialogAccessPoints::ConnectionStateToString(ConnectionState state) { - return m_selectedAPEssId; + switch (state) + { + case NETWORK_CONNECTION_STATE_DISCONNECTED: + return "disconnected"; + case NETWORK_CONNECTION_STATE_CONNECTING: + return "connecting"; + case NETWORK_CONNECTION_STATE_CONNECTED: + return "connected"; + case NETWORK_CONNECTION_STATE_FAILURE: + return "failure"; + case NETWORK_CONNECTION_STATE_UNKNOWN: + default: + return "unknown"; + } + + return ""; } -EncMode CGUIDialogAccessPoints::GetSelectedAccessPointEncMode() +const char *CGUIDialogAccessPoints::ConnectionTypeToString(ConnectionType type) { - return m_selectedAPEncMode; + switch (type) + { + case NETWORK_CONNECTION_TYPE_WIRED: + return "wired"; + case NETWORK_CONNECTION_TYPE_WIFI: + return "wifi"; + case NETWORK_CONNECTION_TYPE_UNKNOWN: + default: + return "unknown"; + } + + return ""; } -bool CGUIDialogAccessPoints::WasItemSelected() +const char *CGUIDialogAccessPoints::EncryptionToString(EncryptionType type) { - return m_wasItemSelected; + switch (type) + { + case NETWORK_CONNECTION_ENCRYPTION_NONE: + return ""; + case NETWORK_CONNECTION_ENCRYPTION_WEP: + return "wep"; + case NETWORK_CONNECTION_ENCRYPTION_WPA: + return "wpa"; + case NETWORK_CONNECTION_ENCRYPTION_WPA2: + return "wpa2"; + case NETWORK_CONNECTION_ENCRYPTION_IEEE8021x: + return "wpa-rsn"; + case NETWORK_CONNECTION_ENCRYPTION_UNKNOWN: + default: + return "unknown"; + } + + return ""; } diff --git a/xbmc/network/GUIDialogAccessPoints.h b/xbmc/network/GUIDialogAccessPoints.h index f76d8b1bf311c..5ada50280b325 100644 --- a/xbmc/network/GUIDialogAccessPoints.h +++ b/xbmc/network/GUIDialogAccessPoints.h @@ -1,8 +1,6 @@ -#ifndef GUI_DIALOG_ACCES_POINTS -#define GUI_DIALOG_ACCES_POINTS - +#pragma once /* - * Copyright (C) 2005-2012 Team XBMC + * Copyright (C) 2005-2011 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify @@ -16,8 +14,9 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html * */ @@ -25,29 +24,35 @@ #include #include "guilib/GUIDialog.h" -#include "Network.h" +#include "IConnection.h" +#include "utils/Job.h" + + +const std::string EncodeAccessPointParam(const std::string name, const CIPConfig &ipconfig); class CFileItemList; -class CGUIDialogAccessPoints : public CGUIDialog +class CGUIDialogAccessPoints : public CGUIDialog, public IJobCallback { public: CGUIDialogAccessPoints(void); virtual ~CGUIDialogAccessPoints(void); - virtual void OnInitWindow(); virtual bool OnAction(const CAction &action); - void SetInterfaceName(CStdString interfaceName); - CStdString GetSelectedAccessPointEssId(); - EncMode GetSelectedAccessPointEncMode(); - bool WasItemSelected(); + virtual bool OnMessage(CGUIMessage& message); + virtual bool OnBack(int actionID); + virtual void OnJobComplete(unsigned int jobID, bool success, CJob *job); private: - std::vector m_aps; - CStdString m_interfaceName; - CStdString m_selectedAPEssId; - EncMode m_selectedAPEncMode; - bool m_wasItemSelected; - CFileItemList *m_accessPoints; -}; + void UpdateConnectionList(); + void DecodeAccessPointParam(const std::string ¶m); + + static const char *ConnectionStateToString(ConnectionState state); + static const char *ConnectionTypeToString(ConnectionType type); + static const char *EncryptionToString(EncryptionType type); -#endif + std::string m_ipname; + CIPConfig m_ipconfig; + bool m_use_ipconfig; + bool m_doing_connection; + CFileItemList *m_connectionsFileList; +}; diff --git a/xbmc/network/IConnection.h b/xbmc/network/IConnection.h new file mode 100644 index 0000000000000..fd337e98854c9 --- /dev/null +++ b/xbmc/network/IConnection.h @@ -0,0 +1,209 @@ +#pragma once +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ +#include +#include +#include "IPassphraseStorage.h" +#include + +enum ConnectionType +{ + NETWORK_CONNECTION_TYPE_UNKNOWN = 0, + NETWORK_CONNECTION_TYPE_WIRED, + NETWORK_CONNECTION_TYPE_WIFI +}; + +enum ConnectionState +{ + NETWORK_CONNECTION_STATE_UNKNOWN = 0, + NETWORK_CONNECTION_STATE_FAILURE, + NETWORK_CONNECTION_STATE_DISCONNECTED, + NETWORK_CONNECTION_STATE_CONNECTING, + NETWORK_CONNECTION_STATE_CONNECTED +}; + +enum EncryptionType +{ + NETWORK_CONNECTION_ENCRYPTION_UNKNOWN = 0, // This should be used to flag accesspoints which have some encryption which we cannot connect to. + NETWORK_CONNECTION_ENCRYPTION_NONE, + NETWORK_CONNECTION_ENCRYPTION_WEP, + NETWORK_CONNECTION_ENCRYPTION_WPA, + NETWORK_CONNECTION_ENCRYPTION_WPA2, + NETWORK_CONNECTION_ENCRYPTION_IEEE8021x +}; + +enum IPConfigMethod +{ + IP_CONFIG_DHCP, + IP_CONFIG_STATIC, + IP_CONFIG_DISABLED +}; + +class CIPConfig +{ +public: + CIPConfig() + { + reset(); + } + + CIPConfig(IPConfigMethod method, + const std::string &address, const std::string &netmask, + const std::string &gateway, const std::string &nameserver) + { + m_method = method; + m_address = address; + m_netmask = netmask; + m_gateway = gateway; + m_nameserver = nameserver; + } + + void reset() + { + m_method = IP_CONFIG_DISABLED; + m_address = ""; + m_netmask = ""; + m_gateway = ""; + m_nameserver = ""; + } + + IPConfigMethod m_method; + std::string m_address; + std::string m_netmask; + std::string m_gateway; + std::string m_nameserver; +}; + +class IConnection +{ +public: + virtual ~IConnection() { } + + /*! + \brief Get the name of the connection + + \return The name of the connection + \sa IConnection + */ + virtual std::string GetName() const = 0; + + /*! + \brief Get the IP of the connection + + \return The IP of the connection + \sa IConnection + */ + virtual std::string GetAddress() const = 0; + + /*! + \brief Get the netmask of the connection + + \return The netmask of the connection + \sa IConnection + */ + virtual std::string GetNetmask() const = 0; + + /*! + \brief Get the gateway address of the connection + + \return The gateway address of the connection + \sa IConnection + */ + virtual std::string GetGateway() const = 0; + + /*! + \brief Get the name server of the connection + + \return The name server of the connection + \sa IConnection + */ + + virtual std::string GetNameServer() const = 0; + + /*! + \brief Get the mac address of the connection + + \return The mac address of the connection + \sa IConnection + */ + virtual std::string GetMacAddress() const = 0; + + /*! + \brief Get the connection type + + \return The connection type + \sa ConnectionType + */ + virtual ConnectionType GetType() const = 0; + + /*! + \brief Get the state of the connection + + \return The state the connection is currently in. + \sa ConnectionState + */ + virtual ConnectionState GetState() const = 0; + + /*! + \brief Get the speed of the connection + + \return The speed of the connection + \sa IConnection + */ + virtual unsigned int GetSpeed() const = 0; + + /*! + \brief Get the connection type + + \return The connection method + \sa IPConfigMethod + */ + virtual IPConfigMethod GetMethod() const = 0; + + /*! + \brief The signal strength of the connection + + \return The signal strength of the connection + \sa IConnection + */ + virtual unsigned int GetStrength() const = 0; + + /*! + \brief Get the encryption used by the connection + + \return The encryption used by the connection + \sa EncryptionType + */ + virtual EncryptionType GetEncryption() const = 0; + + /*! + \brief Connect to connection + + \param storage a passphrase provider + \param ipconfig a network configuration + \returns true if connected, false if not. + \sa IPassphraseStorage CIPConfig + */ + virtual bool Connect(IPassphraseStorage *storage, const CIPConfig &ipconfig) = 0; +}; + +typedef boost::shared_ptr CConnectionPtr; +typedef std::vector ConnectionList; diff --git a/xbmc/network/INetworkManager.h b/xbmc/network/INetworkManager.h new file mode 100644 index 0000000000000..6666e40f2836f --- /dev/null +++ b/xbmc/network/INetworkManager.h @@ -0,0 +1,66 @@ +#pragma once +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "IConnection.h" + +/*! + \ingroup network + \brief Callback interface for network events. + + Used by subsystems of the network manager to receive events about the subsystem. + It will be called relatively often from application thread to allow thread safe updates + of the network states. + + \sa INetworkManager + */ +class INetworkEventsCallback +{ +public: + virtual ~INetworkEventsCallback() { } + + virtual void OnConnectionStateChange(ConnectionState state) = 0; + virtual void OnConnectionChange(CConnectionPtr connection) = 0; + virtual void OnConnectionListChange(ConnectionList list) = 0; +}; + + +/*! + \ingroup network + \brief Interface for the network subsystems context + + Used by subsystems of the network manager to receive events about the subsystem. + It will be called relatively often from application thread to allow thread safe updates + of the network states. + + \sa INetworkManager + */ +class INetworkManager +{ +public: + virtual ~INetworkManager() { } + + virtual bool CanManageConnections() = 0; + + virtual ConnectionList GetConnections() = 0; + + virtual bool PumpNetworkEvents(INetworkEventsCallback *callback) = 0; +}; diff --git a/xbmc/network/IPassphraseStorage.h b/xbmc/network/IPassphraseStorage.h new file mode 100644 index 0000000000000..894b7ee66a714 --- /dev/null +++ b/xbmc/network/IPassphraseStorage.h @@ -0,0 +1,63 @@ +#pragma once +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +class IPassphraseStorage +{ +public: + virtual ~IPassphraseStorage() { } + + /*! + \brief Invalidate passphrase + + While a connection is connecting it may invalidate any stored passphrase. This is used + if the subsystem is not able to store passwords but the connection may have changed passphrase + + \param uuid the unique id of the connection associated with the passphrase + \sa IConnection + */ + virtual void InvalidatePassphrase(const std::string &uuid) = 0; + + /*! + \brief Get passphrase + + While a connection is connecting it may need to acquire a passphrase. This is used + if the subsystem has no stored passphrase. + + \param uuid the unique id of the connection. + \param passphrase a string which the passphrase storage will fill in the passphrase. + \return true if the passphrase was filled and false if it was some form of failure acquiring it. + \sa IConnection + */ + virtual bool GetPassphrase(const std::string &uuid, std::string &passphrase) = 0; + + /*! + \brief Store passphrase + + While a connection is connecting it may need to store a passphrase. This is used + if the subsystem is not capable of storing the passphrase itself. + + \param uuid the unique id of the connection. + \param passphrase is the passphrase to be stored + \sa IConnection + */ + virtual void StorePassphrase(const std::string &uuid, const std::string &passphrase) = 0; +}; diff --git a/xbmc/network/Makefile.in b/xbmc/network/Makefile.in index e2ffb0bce9454..ecef3a8bec4b6 100644 --- a/xbmc/network/Makefile.in +++ b/xbmc/network/Makefile.in @@ -5,13 +5,16 @@ SRCS += EventPacket.cpp SRCS += EventServer.cpp SRCS += GUIDialogAccessPoints.cpp SRCS += GUIDialogNetworkSetup.cpp -SRCS += Network.cpp SRCS += Socket.cpp SRCS += TCPServer.cpp SRCS += UdpClient.cpp SRCS += WebServer.cpp SRCS += ZeroconfBrowser.cpp SRCS += Zeroconf.cpp +SRCS += NetworkManager.cpp +SRCS += NetworkUtils.cpp +SRCS += NullNetworkManager.cpp +SRCS += ConnectionJob.cpp ifeq (@USE_AIRPLAY@, 1) SRCS += AirPlayServer.cpp diff --git a/xbmc/network/Network.cpp b/xbmc/network/Network.cpp deleted file mode 100644 index 9c569582b99d6..0000000000000 --- a/xbmc/network/Network.cpp +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Copyright (C) 2005-2012 Team XBMC - * http://www.xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ - -#include "system.h" -#include "Network.h" -#include "Application.h" -#include "ApplicationMessenger.h" -#include "libscrobbler/lastfmscrobbler.h" -#include "libscrobbler/librefmscrobbler.h" -#include "utils/RssReader.h" -#include "utils/log.h" -#include "guilib/LocalizeStrings.h" -#include "dialogs/GUIDialogKaiToast.h" - -#include -#include -#include - -using namespace std; - -/* slightly modified in_ether taken from the etherboot project (http://sourceforge.net/projects/etherboot) */ -bool in_ether (const char *bufp, unsigned char *addr) -{ - if (strlen(bufp) != 17) - return false; - - char c; - const char *orig; - unsigned char *ptr = addr; - unsigned val; - - int i = 0; - orig = bufp; - - while ((*bufp != '\0') && (i < 6)) - { - val = 0; - c = *bufp++; - - if (isdigit(c)) - val = c - '0'; - else if (c >= 'a' && c <= 'f') - val = c - 'a' + 10; - else if (c >= 'A' && c <= 'F') - val = c - 'A' + 10; - else - return false; - - val <<= 4; - c = *bufp; - if (isdigit(c)) - val |= c - '0'; - else if (c >= 'a' && c <= 'f') - val |= c - 'a' + 10; - else if (c >= 'A' && c <= 'F') - val |= c - 'A' + 10; - else if (c == ':' || c == '-' || c == 0) - val >>= 4; - else - return false; - - if (c != 0) - bufp++; - - *ptr++ = (unsigned char) (val & 0377); - i++; - - if (*bufp == ':' || *bufp == '-') - bufp++; - } - - if (bufp - orig != 17) - return false; - - return true; -} - -CNetwork::CNetwork() -{ - CApplicationMessenger::Get().NetworkMessage(SERVICES_UP, 0); -} - -CNetwork::~CNetwork() -{ - CApplicationMessenger::Get().NetworkMessage(SERVICES_DOWN, 0); -} - -int CNetwork::ParseHex(char *str, unsigned char *addr) -{ - int len = 0; - - while (*str) - { - int tmp; - if (str[1] == 0) - return -1; - if (sscanf(str, "%02x", (unsigned int *)&tmp) != 1) - return -1; - addr[len] = tmp; - len++; - str += 2; - } - - return len; -} - -CStdString CNetwork::GetHostName(void) -{ - char hostName[128]; - if (gethostname(hostName, sizeof(hostName))) - return CStdString("unknown"); - else - return CStdString(hostName); -} - - -CNetworkInterface* CNetwork::GetFirstConnectedInterface() -{ - vector& ifaces = GetInterfaceList(); - vector::const_iterator iter = ifaces.begin(); - while (iter != ifaces.end()) - { - CNetworkInterface* iface = *iter; - if (iface && iface->IsConnected()) - return iface; - ++iter; - } - - return NULL; -} - -bool CNetwork::HasInterfaceForIP(unsigned long address) -{ - unsigned long subnet; - unsigned long local; - vector& ifaces = GetInterfaceList(); - vector::const_iterator iter = ifaces.begin(); - while (iter != ifaces.end()) - { - CNetworkInterface* iface = *iter; - if (iface && iface->IsConnected()) - { - subnet = ntohl(inet_addr(iface->GetCurrentNetmask())); - local = ntohl(inet_addr(iface->GetCurrentIPAddress())); - if( (address & subnet) == (local & subnet) ) - return true; - } - ++iter; - } - - return false; -} - -bool CNetwork::IsAvailable(bool wait /*= false*/) -{ - if (wait) - { - // NOTE: Not implemented in linuxport branch as 99.9% of the time - // we have the network setup already. Trunk code has a busy - // wait for 5 seconds here. - } - - vector& ifaces = GetInterfaceList(); - return (ifaces.size() != 0); -} - -bool CNetwork::IsConnected() -{ - return GetFirstConnectedInterface() != NULL; -} - -CNetworkInterface* CNetwork::GetInterfaceByName(CStdString& name) -{ - vector& ifaces = GetInterfaceList(); - vector::const_iterator iter = ifaces.begin(); - while (iter != ifaces.end()) - { - CNetworkInterface* iface = *iter; - if (iface && iface->GetName().Equals(name)) - return iface; - ++iter; - } - - return NULL; -} - -void CNetwork::NetworkMessage(EMESSAGE message, int param) -{ - switch( message ) - { - case SERVICES_UP: - { - CLog::Log(LOGDEBUG, "%s - Starting network services",__FUNCTION__); - StartServices(); - } - break; - case SERVICES_DOWN: - { - CLog::Log(LOGDEBUG, "%s - Signaling network services to stop",__FUNCTION__); - StopServices(false); //tell network services to stop, but don't wait for them yet - CLog::Log(LOGDEBUG, "%s - Waiting for network services to stop",__FUNCTION__); - StopServices(true); //wait for network services to stop - } - break; - } -} - -bool CNetwork::WakeOnLan(const char* mac) -{ - int i, j, packet; - unsigned char ethaddr[8]; - unsigned char buf [128]; - unsigned char *ptr; - - // Fetch the hardware address - if (!in_ether(mac, ethaddr)) - { - CLog::Log(LOGERROR, "%s - Invalid hardware address specified (%s)", __FUNCTION__, mac); - return false; - } - - // Setup the socket - if ((packet = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) - { - CLog::Log(LOGERROR, "%s - Unable to create socket (%s)", __FUNCTION__, strerror (errno)); - return false; - } - - // Set socket options - struct sockaddr_in saddr; - saddr.sin_family = AF_INET; - saddr.sin_addr.s_addr = htonl(INADDR_BROADCAST); - saddr.sin_port = htons(9); - - unsigned int value = 1; - if (setsockopt (packet, SOL_SOCKET, SO_BROADCAST, (char*) &value, sizeof( unsigned int ) ) == SOCKET_ERROR) - { - CLog::Log(LOGERROR, "%s - Unable to set socket options (%s)", __FUNCTION__, strerror (errno)); - closesocket(packet); - return false; - } - - // Build the magic packet (6 x 0xff + 16 x MAC address) - ptr = buf; - for (i = 0; i < 6; i++) - *ptr++ = 0xff; - - for (j = 0; j < 16; j++) - for (i = 0; i < 6; i++) - *ptr++ = ethaddr[i]; - - // Send the magic packet - if (sendto (packet, (char *)buf, 102, 0, (struct sockaddr *)&saddr, sizeof (saddr)) < 0) - { - CLog::Log(LOGERROR, "%s - Unable to send magic packet (%s)", __FUNCTION__, strerror (errno)); - closesocket(packet); - return false; - } - - closesocket(packet); - CLog::Log(LOGINFO, "%s - Magic packet send to '%s'", __FUNCTION__, mac); - return true; -} - -void CNetwork::StartServices() -{ -#ifdef HAS_TIME_SERVER - g_application.StartTimeServer(); -#endif -#ifdef HAS_WEB_SERVER - if (!g_application.StartWebServer()) - CGUIDialogKaiToast::QueueNotification("DefaultIconWarning.png", g_localizeStrings.Get(33101), g_localizeStrings.Get(33100)); -#endif -#ifdef HAS_UPNP - g_application.StartUPnP(); -#endif -#ifdef HAS_EVENT_SERVER - if (!g_application.StartEventServer()) - CGUIDialogKaiToast::QueueNotification("DefaultIconWarning.png", g_localizeStrings.Get(33102), g_localizeStrings.Get(33100)); -#endif -#ifdef HAS_JSONRPC - if (!g_application.StartJSONRPCServer()) - CGUIDialogKaiToast::QueueNotification("DefaultIconWarning.png", g_localizeStrings.Get(33103), g_localizeStrings.Get(33100)); -#endif -#ifdef HAS_ZEROCONF - g_application.StartZeroconf(); -#endif -#ifdef HAS_AIRPLAY - g_application.StartAirplayServer(); -#endif - CLastfmScrobbler::GetInstance()->Init(); - CLibrefmScrobbler::GetInstance()->Init(); - g_rssManager.Start(); -} - -void CNetwork::StopServices(bool bWait) -{ - if (bWait) - { -#ifdef HAS_TIME_SERVER - g_application.StopTimeServer(); -#endif -#ifdef HAS_UPNP - g_application.StopUPnP(bWait); -#endif -#ifdef HAS_ZEROCONF - g_application.StopZeroconf(); -#endif -#ifdef HAS_WEB_SERVER - g_application.StopWebServer(); -#endif - CLastfmScrobbler::GetInstance()->Term(); - CLibrefmScrobbler::GetInstance()->Term(); - // smb.Deinit(); if any file is open over samba this will break. - - g_rssManager.Stop(); - } - -#ifdef HAS_EVENT_SERVER - g_application.StopEventServer(bWait, false); -#endif -#ifdef HAS_JSONRPC - g_application.StopJSONRPCServer(bWait); -#endif -#if defined(HAS_AIRPLAY) || defined(HAS_AIRTUNES) - g_application.StopAirplayServer(bWait); -#endif -} diff --git a/xbmc/network/Network.h b/xbmc/network/Network.h deleted file mode 100644 index 1aaa764cea179..0000000000000 --- a/xbmc/network/Network.h +++ /dev/null @@ -1,130 +0,0 @@ -#ifndef NETWORK_H_ -#define NETWORK_H_ - -/* - * Copyright (C) 2005-2012 Team XBMC - * http://www.xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ - -#include -#include "utils/StdString.h" -#include "system.h" - -enum EncMode { ENC_NONE = 0, ENC_WEP = 1, ENC_WPA = 2, ENC_WPA2 = 3 }; -enum NetworkAssignment { NETWORK_DASH = 0, NETWORK_DHCP = 1, NETWORK_STATIC = 2, NETWORK_DISABLED = 3 }; - -class NetworkAccessPoint -{ -public: - NetworkAccessPoint(CStdString& essId, int quality, EncMode encryption) - { - m_essId = essId; - m_quality = quality; - m_encryptionMode = encryption; - } - - CStdString getEssId() { return m_essId; } - int getQuality() { return m_quality; } - EncMode getEncryptionMode() { return m_encryptionMode; } - -private: - CStdString m_essId; - int m_quality; - EncMode m_encryptionMode; -}; - -class CNetworkInterface -{ -public: - virtual ~CNetworkInterface() {}; - - virtual CStdString& GetName(void) = 0; - - virtual bool IsEnabled(void) = 0; - virtual bool IsConnected(void) = 0; - virtual bool IsWireless(void) = 0; - - virtual CStdString GetMacAddress(void) = 0; - virtual void GetMacAddressRaw(char rawMac[6]) = 0; - - virtual CStdString GetCurrentIPAddress() = 0; - virtual CStdString GetCurrentNetmask() = 0; - virtual CStdString GetCurrentDefaultGateway(void) = 0; - virtual CStdString GetCurrentWirelessEssId(void) = 0; - - // Returns the list of access points in the area - virtual std::vector GetAccessPoints(void) = 0; - - virtual void GetSettings(NetworkAssignment& assignment, CStdString& ipAddress, CStdString& networkMask, CStdString& defaultGateway, CStdString& essId, CStdString& key, EncMode& encryptionMode) = 0; - virtual void SetSettings(NetworkAssignment& assignment, CStdString& ipAddress, CStdString& networkMask, CStdString& defaultGateway, CStdString& essId, CStdString& key, EncMode& encryptionMode) = 0; -}; - - - -class CNetwork -{ -public: - enum EMESSAGE - { - SERVICES_UP, - SERVICES_DOWN - }; - - CNetwork(); - virtual ~CNetwork(); - - // Return our hostname - virtual CStdString GetHostName(void); - - // Return the list of interfaces - virtual std::vector& GetInterfaceList(void) = 0; - CNetworkInterface* GetInterfaceByName(CStdString& name); - - // Return the first interface which is active - virtual CNetworkInterface* GetFirstConnectedInterface(void); - - // Return true if there is a interface for the same network as address - bool HasInterfaceForIP(unsigned long address); - - // Return true if there's at least one defined network interface - bool IsAvailable(bool wait = false); - - // Return true if there's at least one interface which is connected - bool IsConnected(void); - - // Return true if the magic packet was send - bool WakeOnLan(const char *mac); - - // Get/set the nameserver(s) - virtual std::vector GetNameServers(void) = 0; - virtual void SetNameServers(std::vector nameServers) = 0; - - // callback from application controlled thread to handle any setup - void NetworkMessage(EMESSAGE message, int param); - - void StartServices(); - void StopServices(bool bWait); - - static int ParseHex(char *str, unsigned char *addr); -}; -#ifdef HAS_LINUX_NETWORK -#include "linux/NetworkLinux.h" -#else -#include "windows/NetworkWin32.h" -#endif -#endif diff --git a/xbmc/network/NetworkManager.cpp b/xbmc/network/NetworkManager.cpp new file mode 100644 index 0000000000000..2abebc50fde40 --- /dev/null +++ b/xbmc/network/NetworkManager.cpp @@ -0,0 +1,452 @@ +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "NetworkManager.h" +#include "NullNetworkManager.h" +#include "Application.h" +#include "ApplicationMessenger.h" +#include "dialogs/GUIDialogKaiToast.h" +#include "guilib/LocalizeStrings.h" +#include "guilib/GUIWindowManager.h" +#include "libscrobbler/lastfmscrobbler.h" +#include "libscrobbler/librefmscrobbler.h" +#include "linux/ConnmanNetworkManager.h" +#include "linux/PosixNetworkManager.h" +#include "windows/WinNetworkManager.h" +#include "utils/log.h" +#include "utils/RssReader.h" + +/* slightly modified in_ether taken from the etherboot project (http://sourceforge.net/projects/etherboot) */ +bool in_ether(const char *bufp, unsigned char *addr) +{ + if (strlen(bufp) != 17) + return false; + + char c; + const char *orig; + unsigned char *ptr = addr; + unsigned val; + + int i = 0; + orig = bufp; + + while ((*bufp != '\0') && (i < 6)) + { + val = 0; + c = *bufp++; + + if (isdigit(c)) + val = c - '0'; + else if (c >= 'a' && c <= 'f') + val = c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + val = c - 'A' + 10; + else + return false; + + val <<= 4; + c = *bufp; + if (isdigit(c)) + val |= c - '0'; + else if (c >= 'a' && c <= 'f') + val |= c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + val |= c - 'A' + 10; + else if (c == ':' || c == '-' || c == 0) + val >>= 4; + else + return false; + + if (c != 0) + bufp++; + + *ptr++ = (unsigned char) (val & 0377); + i++; + + if (*bufp == ':' || *bufp == '-') + bufp++; + } + + if (bufp - orig != 17) + return false; + + return true; +} + +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +CNetworkManager::CNetworkManager() +{ + m_instance = NULL; + m_state = NETWORK_CONNECTION_STATE_UNKNOWN; +} + +CNetworkManager::~CNetworkManager() +{ + delete m_instance; +} + +void CNetworkManager::Initialize() +{ +#ifdef HAS_DBUS +// if (CConnmanNetworkManager::HasConnman()) +// m_instance = new CConnmanNetworkManager(); +#endif + +#if defined(TARGET_POSIX) + if (m_instance == NULL) + m_instance = new CPosixNetworkManager(); +#endif + +#ifdef TARGET_WINDOWS + if (m_instance == NULL) + m_instance = new CWinNetworkManager(); +#endif + + if (m_instance == NULL) + m_instance = new CNullNetworkManager(); + + m_defaultConnection = CConnectionPtr(new CNullConnection()); + OnConnectionListChange(m_instance->GetConnections()); +} + +bool CNetworkManager::PumpNetworkEvents() +{ + return m_instance->PumpNetworkEvents(this); +} + +std::string CNetworkManager::GetDefaultConnectionName() +{ + if (m_defaultConnection) + return m_defaultConnection->GetName(); + else + return std::string("opps"); +} + +std::string CNetworkManager::GetDefaultConnectionAddress() +{ + if (m_defaultConnection) + return m_defaultConnection->GetAddress(); + else + return std::string("opps"); +} + +std::string CNetworkManager::GetDefaultConnectionNetmask() +{ + if (m_defaultConnection) + return m_defaultConnection->GetNetmask(); + else + return std::string("opps"); +} + +std::string CNetworkManager::GetDefaultConnectionMacAddress() +{ + if (m_defaultConnection) + return m_defaultConnection->GetMacAddress(); + else + return std::string("opps"); +} + +std::string CNetworkManager::GetDefaultConnectionGateway() +{ + if (m_defaultConnection) + return m_defaultConnection->GetGateway(); + else + return std::string("opps"); +} + +std::string CNetworkManager::GetDefaultConnectionNameServer() +{ + if (m_defaultConnection) + return m_defaultConnection->GetNameServer(); + else + return std::string("127.0.0.1"); +} + +ConnectionType CNetworkManager::GetDefaultConnectionType() +{ + if (m_defaultConnection) + return m_defaultConnection->GetType(); + else + return NETWORK_CONNECTION_TYPE_UNKNOWN; +} + +IPConfigMethod CNetworkManager::GetDefaultConnectionMethod() +{ + if (m_defaultConnection) + return m_defaultConnection->GetMethod(); + else + return IP_CONFIG_DISABLED; +} + +ConnectionState CNetworkManager::GetDefaultConnectionState() +{ + return m_state; +} + +bool CNetworkManager::IsConnected() +{ + return GetDefaultConnectionState() == NETWORK_CONNECTION_STATE_CONNECTED; +} + +bool CNetworkManager::IsAvailable(bool wait) +{ + return true; +} + +bool CNetworkManager::CanManageConnections() +{ + return m_instance->CanManageConnections(); +} + +ConnectionList CNetworkManager::GetConnections() +{ + return m_connections; +} + +void CNetworkManager::OnConnectionStateChange(ConnectionState state) +{ + ConnectionState oldState = m_state; + m_state = state; + + if (m_state != oldState) + CLog::Log(LOGDEBUG, "NetworkManager: State changed to %s", ConnectionStateToString(m_state)); + + if (oldState != NETWORK_CONNECTION_STATE_CONNECTED && m_state == NETWORK_CONNECTION_STATE_CONNECTED) + StartServices(); + else if (oldState == NETWORK_CONNECTION_STATE_CONNECTED && oldState != m_state) + StopServices(); +} + +void CNetworkManager::OnConnectionChange(CConnectionPtr connection) +{ + if (connection->GetState() == NETWORK_CONNECTION_STATE_CONNECTED) + m_defaultConnection = connection; + + if (g_windowManager.GetWindow(WINDOW_DIALOG_ACCESS_POINTS)) + { + CAction action(ACTION_CONNECTIONS_REFRESH); + CApplicationMessenger::Get().SendAction(action, WINDOW_DIALOG_ACCESS_POINTS); + } +} + +void CNetworkManager::OnConnectionListChange(ConnectionList list) +{ + m_connections = list; + + for (unsigned int i = 0; i < m_connections.size(); i++) + { + if (m_connections[i]->GetState() == NETWORK_CONNECTION_STATE_CONNECTED) + { + m_defaultConnection = m_connections[i]; + OnConnectionStateChange(NETWORK_CONNECTION_STATE_CONNECTED); + break; + } + } + + if (g_windowManager.GetWindow(WINDOW_DIALOG_ACCESS_POINTS)) + { + CAction action(ACTION_CONNECTIONS_REFRESH); + CApplicationMessenger::Get().SendAction(action, WINDOW_DIALOG_ACCESS_POINTS); + } +} + +void CNetworkManager::NetworkMessage(EMESSAGE message, int param) +{ + switch( message ) + { + case SERVICES_UP: + { + CLog::Log(LOGDEBUG, "%s - Starting network services",__FUNCTION__); + StartServices(); + } + break; + case SERVICES_DOWN: + { + CLog::Log(LOGDEBUG, "%s - Signaling network services to stop",__FUNCTION__); + StopServices(false); //tell network services to stop, but don't wait for them yet + CLog::Log(LOGDEBUG, "%s - Waiting for network services to stop",__FUNCTION__); + StopServices(true); //wait for network services to stop + } + break; + } +} + +bool CNetworkManager::WakeOnLan(const char *mac) +{ +/* + int i, j, packet; + unsigned char ethaddr[8]; + unsigned char buf [128]; + unsigned char *ptr; + + // Fetch the hardware address + if (!in_ether(mac, ethaddr)) + { + CLog::Log(LOGERROR, "%s - Invalid hardware address specified (%s)", __FUNCTION__, mac); + return false; + } + + // Setup the socket + if ((packet = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) + { + CLog::Log(LOGERROR, "%s - Unable to create socket (%s)", __FUNCTION__, strerror (errno)); + return false; + } + + // Set socket options + struct sockaddr_in saddr; + saddr.sin_family = AF_INET; + saddr.sin_addr.s_addr = htonl(INADDR_BROADCAST); + saddr.sin_port = htons(9); + + unsigned int value = 1; + if (setsockopt(packet, SOL_SOCKET, SO_BROADCAST, (char*) &value, sizeof( unsigned int ) ) == SOCKET_ERROR) + { + CLog::Log(LOGERROR, "%s - Unable to set socket options (%s)", __FUNCTION__, strerror (errno)); + closesocket(packet); + return false; + } + + // Build the magic packet (6 x 0xff + 16 x MAC address) + ptr = buf; + for (i = 0; i < 6; i++) + *ptr++ = 0xff; + + for (j = 0; j < 16; j++) + for (i = 0; i < 6; i++) + *ptr++ = ethaddr[i]; + + // Send the magic packet + if (sendto(packet, (char *)buf, 102, 0, (struct sockaddr *)&saddr, sizeof (saddr)) < 0) + { + CLog::Log(LOGERROR, "%s - Unable to send magic packet (%s)", __FUNCTION__, strerror (errno)); + closesocket(packet); + return false; + } + + closesocket(packet); + CLog::Log(LOGINFO, "%s - Magic packet send to '%s'", __FUNCTION__, mac); +*/ + return true; +} + +void CNetworkManager::StartServices() +{ + CLog::Log(LOGDEBUG, "NetworkManager: Starting network services"); + + // TODO: fix properly + system("/etc/init.d/S49ntp restart"); + +#ifdef HAS_TIME_SERVER + g_application.StartTimeServer(); +#endif +#ifdef HAS_WEB_SERVER + if (!g_application.StartWebServer()) + CGUIDialogKaiToast::QueueNotification("DefaultIconWarning.png", g_localizeStrings.Get(33101), g_localizeStrings.Get(33100)); +#endif +#ifdef HAS_UPNP + g_application.StartUPnP(); +#endif +#ifdef HAS_EVENT_SERVER + if (!g_application.StartEventServer()) + CGUIDialogKaiToast::QueueNotification("DefaultIconWarning.png", g_localizeStrings.Get(33102), g_localizeStrings.Get(33100)); +#endif +#ifdef HAS_DBUS_SERVER + g_application.StartDbusServer(); +#endif +#ifdef HAS_JSONRPC + if (!g_application.StartJSONRPCServer()) + CGUIDialogKaiToast::QueueNotification("DefaultIconWarning.png", g_localizeStrings.Get(33103), g_localizeStrings.Get(33100)); +#endif +#ifdef HAS_ZEROCONF + g_application.StartZeroconf(); +#endif +#ifdef HAS_AIRPLAY + g_application.StartAirplayServer(); +#endif + CLastfmScrobbler::GetInstance()->Init(); + CLibrefmScrobbler::GetInstance()->Init(); + g_rssManager.Start(); +} + +void CNetworkManager::StopServices() +{ + CLog::Log(LOGDEBUG, "NetworkManager: Stopping network services"); + StopServices(false); + CLog::Log(LOGDEBUG, "NetworkManager: Waiting for network services to stop"); + StopServices(true); +} + +void CNetworkManager::StopServices(bool wait) +{ + if (wait) + { +#ifdef HAS_TIME_SERVER + g_application.StopTimeServer(); +#endif +#ifdef HAS_UPNP + g_application.StopUPnP(wait); +#endif +#ifdef HAS_ZEROCONF + g_application.StopZeroconf(); +#endif +#ifdef HAS_WEB_SERVER + g_application.StopWebServer(); +#endif + CLastfmScrobbler::GetInstance()->Term(); + CLibrefmScrobbler::GetInstance()->Term(); + // smb.Deinit(); if any file is open over samba this will break. + + g_rssManager.Stop(); + } + +#ifdef HAS_EVENT_SERVER + g_application.StopEventServer(wait, false); +#endif +#ifdef HAS_DBUS_SERVER + g_application.StopDbusServer(wait); +#endif +#ifdef HAS_JSONRPC + g_application.StopJSONRPCServer(wait); +#endif +#if defined(HAS_AIRPLAY) || defined(HAS_AIRTUNES) + g_application.StopAirplayServer(wait); +#endif +} + +const char *CNetworkManager::ConnectionStateToString(ConnectionState state) +{ + switch (state) + { + case NETWORK_CONNECTION_STATE_FAILURE: + return "failure"; + case NETWORK_CONNECTION_STATE_DISCONNECTED: + return "disconnect"; + case NETWORK_CONNECTION_STATE_CONNECTING: + return "connecting"; + case NETWORK_CONNECTION_STATE_CONNECTED: + return "connected"; + case NETWORK_CONNECTION_STATE_UNKNOWN: + default: + return "unknown"; + } +} diff --git a/xbmc/network/NetworkManager.h b/xbmc/network/NetworkManager.h new file mode 100644 index 0000000000000..0680d776349ba --- /dev/null +++ b/xbmc/network/NetworkManager.h @@ -0,0 +1,80 @@ +#pragma once +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "INetworkManager.h" + +class CNetworkManager : public INetworkEventsCallback +{ +public: + enum EMESSAGE + { + SERVICES_UP, + SERVICES_DOWN + }; + + CNetworkManager(); + virtual ~CNetworkManager(); + + void Initialize(); + + bool PumpNetworkEvents(); + + std::string GetDefaultConnectionName(); + std::string GetDefaultConnectionAddress(); + std::string GetDefaultConnectionNetmask(); + std::string GetDefaultConnectionGateway(); + std::string GetDefaultConnectionNameServer(); + std::string GetDefaultConnectionMacAddress(); + + ConnectionType GetDefaultConnectionType(); + ConnectionState GetDefaultConnectionState(); + IPConfigMethod GetDefaultConnectionMethod(); + + bool IsConnected(); + + bool IsAvailable(bool wait = false); + + bool CanManageConnections(); + + ConnectionList GetConnections(); + + virtual void OnConnectionStateChange(ConnectionState state); + virtual void OnConnectionChange(CConnectionPtr connection); + virtual void OnConnectionListChange(ConnectionList list); + + // Return true if the magic packet was send + bool WakeOnLan(const char *mac); + + // callback from application controlled thread to handle any setup + void NetworkMessage(EMESSAGE message, int param); + + void StartServices(); + void StopServices(); +private: + void StopServices(bool wait); + const char* ConnectionStateToString(ConnectionState state); + + INetworkManager *m_instance; + CConnectionPtr m_defaultConnection; + ConnectionList m_connections; + ConnectionState m_state; +}; diff --git a/xbmc/network/NetworkUtils.cpp b/xbmc/network/NetworkUtils.cpp new file mode 100644 index 0000000000000..ba3a6c236513e --- /dev/null +++ b/xbmc/network/NetworkUtils.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "NetworkUtils.h" +#include + +std::string CNetworkUtils::IPTotring(unsigned int ip) +{ + char buffer[16]; + sprintf(buffer, "%i:%i:%i:%i", ip & 0xff, (ip & (0xff << 8)) >> 8, (ip & (0xff << 16)) >> 16, (ip & (0xff << 24)) >> 24); + std::string returnString = buffer; + return returnString; +} diff --git a/xbmc/network/NetworkUtils.h b/xbmc/network/NetworkUtils.h new file mode 100644 index 0000000000000..e9d5fbf85ccfe --- /dev/null +++ b/xbmc/network/NetworkUtils.h @@ -0,0 +1,29 @@ +#pragma once +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include + +class CNetworkUtils +{ +public: + static std::string IPTotring(unsigned int ip); +}; diff --git a/xbmc/network/NullNetworkManager.cpp b/xbmc/network/NullNetworkManager.cpp new file mode 100644 index 0000000000000..98c84b33671f1 --- /dev/null +++ b/xbmc/network/NullNetworkManager.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "NullNetworkManager.h" + +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +CNullConnection::~CNullConnection() +{ +} + +std::string CNullConnection::GetName() const +{ + return "no connection"; +} + +std::string CNullConnection::GetAddress() const +{ + return "127.0.0.1"; +} + +std::string CNullConnection::GetNetmask() const +{ + return "255.255.255.0"; +} + +std::string CNullConnection::GetGateway() const +{ + return "127.0.0.1"; +} + +std::string CNullConnection::GetNameServer() const +{ + return "127.0.0.1"; +} + +std::string CNullConnection::GetMacAddress() const +{ + return "00:00:00:00:00:00"; +} + +ConnectionType CNullConnection::GetType() const +{ + return NETWORK_CONNECTION_TYPE_UNKNOWN; +} + +unsigned int CNullConnection::GetSpeed() const +{ + return 100; +} + +ConnectionState CNullConnection::GetState() const +{ + return NETWORK_CONNECTION_STATE_DISCONNECTED; +} + +IPConfigMethod CNullConnection::GetMethod() const +{ + return IP_CONFIG_DISABLED; +} + +unsigned int CNullConnection::GetStrength() const +{ + return 100; +} + +EncryptionType CNullConnection::GetEncryption() const +{ + return NETWORK_CONNECTION_ENCRYPTION_NONE; +} + +bool CNullConnection::Connect(IPassphraseStorage *storage, const CIPConfig &ipconfig) +{ + return false; +} + + +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +CNullNetworkManager::~CNullNetworkManager() +{ +} + +bool CNullNetworkManager::CanManageConnections() +{ + return false; +} + +ConnectionList CNullNetworkManager::GetConnections() +{ + ConnectionList list; + list.push_back(CConnectionPtr(new CNullConnection())); + return list; +} + +bool CNullNetworkManager::PumpNetworkEvents(INetworkEventsCallback *callback) +{ + return true; +} diff --git a/xbmc/network/NullNetworkManager.h b/xbmc/network/NullNetworkManager.h new file mode 100644 index 0000000000000..7268bd4e1da92 --- /dev/null +++ b/xbmc/network/NullNetworkManager.h @@ -0,0 +1,55 @@ +#pragma once +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "INetworkManager.h" + +class CNullConnection : public IConnection +{ +public: + virtual ~CNullConnection(); + + virtual std::string GetName() const; + virtual std::string GetAddress() const; + virtual std::string GetNetmask() const; + virtual std::string GetGateway() const; + virtual std::string GetNameServer() const; + virtual std::string GetMacAddress() const; + + virtual ConnectionType GetType() const; + virtual ConnectionState GetState() const; + virtual unsigned int GetSpeed() const; + virtual IPConfigMethod GetMethod() const; + virtual unsigned int GetStrength() const; + virtual EncryptionType GetEncryption() const; + + virtual bool Connect(IPassphraseStorage *storage, const CIPConfig &ipconfig); +}; + +class CNullNetworkManager : public INetworkManager +{ + virtual ~CNullNetworkManager(); + + virtual bool CanManageConnections(); + + virtual ConnectionList GetConnections(); + virtual bool PumpNetworkEvents(INetworkEventsCallback *callback); +}; diff --git a/xbmc/network/UdpClient.cpp b/xbmc/network/UdpClient.cpp index 8fad6579df6e5..0aa581d61aea9 100644 --- a/xbmc/network/UdpClient.cpp +++ b/xbmc/network/UdpClient.cpp @@ -23,7 +23,6 @@ #ifdef _LINUX #include #endif -#include "Network.h" #include "guilib/GraphicContext.h" #include "utils/log.h" #include "utils/TimeUtils.h" diff --git a/xbmc/network/linux/ConnmanConnection.cpp b/xbmc/network/linux/ConnmanConnection.cpp new file mode 100644 index 0000000000000..9f1dc9aac6c44 --- /dev/null +++ b/xbmc/network/linux/ConnmanConnection.cpp @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "ConnmanConnection.h" + +#ifdef HAS_DBUS +#include "linux/DBusUtil.h" +#include "linux/DBusMessage.h" +#include "utils/log.h" + +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +CConnmanConnection::CConnmanConnection(const char *serviceObject) +{ + m_serviceObject = serviceObject; + + // should use CONNMAN_SERVICE here (in connman/dbus.h) + CDBusMessage message("net.connman", serviceObject, "net.connman.Service", "GetProperties"); + CDBusReplyPtr reply = message.SendSystem(); + m_properties = reply->GetNextArgument(); + + UpdateConnection(); + + dbus_error_init (&m_error); + + // TODO: do not use dbus_connection_pop_message() that requires the use of a + // private connection + m_connection = dbus_bus_get_private(DBUS_BUS_SYSTEM, &m_error); + if (m_connection) + { + dbus_connection_set_exit_on_disconnect(m_connection, false); + + dbus_bus_add_match(m_connection, "type='signal',interface='net.connman.Service'", &m_error); + dbus_connection_flush(m_connection); + if (dbus_error_is_set(&m_error)) + { + CLog::Log(LOGERROR, "ConnmanConnection: %s Failed to attach to signal %s", serviceObject, m_error.message); + dbus_connection_close(m_connection); + dbus_connection_unref(m_connection); + m_connection = NULL; + } + } + else + CLog::Log(LOGERROR, "ConnmanConnection: %s Failed to get a DBus connection %s", serviceObject, m_error.message); +} + +CConnmanConnection::~CConnmanConnection() +{ + if (m_connection) + { + dbus_connection_close(m_connection); + dbus_connection_unref(m_connection); + m_connection = NULL; + } + + dbus_error_free (&m_error); +} + +std::string CConnmanConnection::GetName() const +{ + return m_name; +} + +std::string CConnmanConnection::GetAddress() const +{ + return m_address; +} + +std::string CConnmanConnection::GetNetmask() const +{ + return m_netmask; +} + +std::string CConnmanConnection::GetGateway() const +{ + return m_gateway; +} + +std::string CConnmanConnection::GetNameServer() const +{ + return "127.0.0.1"; +} + +std::string CConnmanConnection::GetMacAddress() const +{ + return m_macaddress; +} + +ConnectionType CConnmanConnection::GetType() const +{ + return m_type; +} + +ConnectionState CConnmanConnection::GetState() const +{ + return m_state; +} + +unsigned int CConnmanConnection::GetSpeed() const +{ + return m_speed; +} + +IPConfigMethod CConnmanConnection::GetMethod() const +{ + if (m_method.find("dhcp") != std::string::npos) + return IP_CONFIG_DHCP; + else if (m_method.find("manual") != std::string::npos) + return IP_CONFIG_STATIC; + else + return IP_CONFIG_DISABLED; +} + +unsigned int CConnmanConnection::GetStrength() const +{ + return m_strength;; +} + +EncryptionType CConnmanConnection::GetEncryption() const +{ + return m_encryption; +} + +bool CConnmanConnection::Connect(IPassphraseStorage *storage, const CIPConfig &ipconfig) +{ + if (m_encryption != NETWORK_CONNECTION_ENCRYPTION_NONE) + { + if (!storage->GetPassphrase(m_serviceObject, m_passphrase)) + return false; + + CDBusMessage message("net.connman", m_serviceObject.c_str(), "net.connman.Service", "SetProperty"); + message.AppendArgument("Passphrase"); + message.AppendArgument(m_passphrase.c_str()); + + CDBusReplyPtr reply = message.SendSystem(); + if (reply->IsErrorSet()) + { + CLog::Log(LOGERROR, "ConnmanConnection: Failed to set passphrase"); + return false; + } + } + + CLog::Log(LOGDEBUG, "CConnmanConnection::Connect:m_serviceObject(%s)", m_serviceObject.c_str()); + CDBusMessage message("net.connman", m_serviceObject.c_str(), "net.connman.Service", "Connect"); + return message.SendAsyncSystem(); +} + +//----------------------------------------------------------------------- +bool CConnmanConnection::PumpNetworkEvents() +{ + bool result = false; + + if (m_connection) + { + dbus_connection_read_write(m_connection, 0); + DBusMessage *msg = dbus_connection_pop_message(m_connection); + + if (msg) + { + CDBusReplyPtr reply = CDBusReplyPtr(new CDBusReply(msg)); + + if (dbus_message_is_signal(msg, "net.connman.Service", "PropertyChanged")) + { + CVariant key = reply->GetNextArgument(); + m_properties[key.asString()] = reply->GetNextArgument(); + + UpdateConnection(); + result = true; + } + + dbus_message_unref(msg); + } + } + + return result; +} + +ConnectionState CConnmanConnection::ParseConnectionState(const char *stateString) +{ + if (strcmp(stateString, "online") == 0) + return NETWORK_CONNECTION_STATE_CONNECTED; + else if (strcmp(stateString, "association") == 0) + return NETWORK_CONNECTION_STATE_CONNECTING; + else if (strcmp(stateString, "configuration") == 0) + return NETWORK_CONNECTION_STATE_CONNECTING; + else if (strcmp(stateString, "failure") == 0) + return NETWORK_CONNECTION_STATE_FAILURE; + else + { + // The state can be ready which means that the connection have been setup and is ready to be used. + // Perhaps we want to differentiate this in GUI? Its not used but might be in case the active connection is lost. + return NETWORK_CONNECTION_STATE_DISCONNECTED; + } +} + +void CConnmanConnection::UpdateConnection() +{ + m_name = m_properties["Name"].asString(); + + m_state = ParseConnectionState(m_properties["State"].asString().c_str()); + + if (strcmp(m_properties["Type"].asString().c_str(), "ethernet") == 0) + m_type = NETWORK_CONNECTION_TYPE_WIRED; + else if (strcmp(m_properties["Type"].asString().c_str(), "wifi") == 0) + m_type = NETWORK_CONNECTION_TYPE_WIFI; + else + m_type = NETWORK_CONNECTION_TYPE_UNKNOWN; + + m_address = m_properties["IPv4"]["Address"].asString(); + m_netmask = m_properties["IPv4"]["Netmask"].asString(); + m_macaddress = m_properties["Ethernet"]["Address"].asString(); + m_gateway = m_properties["IPv4"]["Gateway"].asString(); + m_method = m_properties["IPv4"]["Method"].asString(); + + if (m_type == NETWORK_CONNECTION_TYPE_WIFI) + { + m_strength = m_properties["Strength"].asInteger(); + m_speed = m_properties["Ethernet"]["Speed"].asInteger(); + + m_encryption = NETWORK_CONNECTION_ENCRYPTION_NONE; + if (strcmp(m_properties["PassphraseRequired"].asString().c_str(), "true") == 0) + { + if (m_properties["Security"].asString().empty()) + m_encryption = NETWORK_CONNECTION_ENCRYPTION_NONE; + else if (strcmp(m_properties["Security"].asString().c_str(), "none") == 0) + m_encryption = NETWORK_CONNECTION_ENCRYPTION_NONE; + else if (strcmp(m_properties["Security"].asString().c_str(), "wep") == 0) + m_encryption = NETWORK_CONNECTION_ENCRYPTION_WEP; + else if (strcmp(m_properties["Security"].asString().c_str(), "wpa") == 0) + m_encryption = NETWORK_CONNECTION_ENCRYPTION_WPA; + else if (strcmp(m_properties["Security"].asString().c_str(), "psk") == 0) + m_encryption = NETWORK_CONNECTION_ENCRYPTION_WPA; + else if (strcmp(m_properties["Security"].asString().c_str(), "rsn") == 0) + m_encryption = NETWORK_CONNECTION_ENCRYPTION_WPA; + else if (strcmp(m_properties["Security"].asString().c_str(), "ieee8021x") == 0) + m_encryption = NETWORK_CONNECTION_ENCRYPTION_IEEE8021x; + else + { + CLog::Log(LOGWARNING, "Connman: unknown connection encryption %s", m_properties["Security"].asString().c_str()); + m_encryption = NETWORK_CONNECTION_ENCRYPTION_UNKNOWN; + } + } + } + else + { + m_strength = 100; + m_speed = m_properties["Ethernet"]["Speed"].asInteger(); + m_encryption = NETWORK_CONNECTION_ENCRYPTION_NONE; + } +} +#endif diff --git a/xbmc/network/linux/ConnmanConnection.h b/xbmc/network/linux/ConnmanConnection.h new file mode 100644 index 0000000000000..9da5e615ba24f --- /dev/null +++ b/xbmc/network/linux/ConnmanConnection.h @@ -0,0 +1,77 @@ +#pragma once +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "system.h" +#ifdef HAS_DBUS +#include "network/IConnection.h" +#include "linux/DBusUtil.h" +#include + +class CConnmanConnection : public IConnection +{ +public: + CConnmanConnection(const char *serviceObject); + virtual ~CConnmanConnection(); + + virtual std::string GetName() const; + virtual std::string GetAddress() const; + virtual std::string GetNetmask() const; + virtual std::string GetGateway() const; + virtual std::string GetNameServer() const; + virtual std::string GetMacAddress() const; + + virtual ConnectionType GetType() const; + virtual ConnectionState GetState() const; + virtual unsigned int GetSpeed() const; + virtual IPConfigMethod GetMethod() const; + virtual unsigned int GetStrength() const; + virtual EncryptionType GetEncryption() const; + + virtual bool Connect(IPassphraseStorage *storage, const CIPConfig &ipconfig); + + bool PumpNetworkEvents(); + static ConnectionState ParseConnectionState(const char *stateString); + +private: + void UpdateConnection(); + + std::string m_name; + std::string m_address; + std::string m_netmask; + std::string m_gateway; + std::string m_macaddress; + + ConnectionType m_type; + ConnectionState m_state; + unsigned int m_speed; + std::string m_method; + unsigned int m_strength; + EncryptionType m_encryption; + std::string m_passphrase; + + CVariant m_properties; + std::string m_serviceObject; + + DBusConnection *m_connection; + DBusError m_error; +}; +#endif diff --git a/xbmc/network/linux/ConnmanNetworkManager.cpp b/xbmc/network/linux/ConnmanNetworkManager.cpp new file mode 100644 index 0000000000000..0b6d22b21d85e --- /dev/null +++ b/xbmc/network/linux/ConnmanNetworkManager.cpp @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "ConnmanNetworkManager.h" + +#ifdef HAS_DBUS +#include "ConnmanConnection.h" +#include "linux/DBusUtil.h" +#include "linux/DBusMessage.h" +#include "utils/log.h" + +using namespace std; + +CConnmanNetworkManager::CConnmanNetworkManager() +{ + // should use CONNMAN_SERVICE here (in connman/dbus.h) + CDBusMessage message("net.connman", "/", "net.connman.Manager", "GetProperties"); + CDBusReplyPtr reply = message.SendSystem(); + m_properties = reply->GetNextArgument(); + + UpdateNetworkManager(); + + dbus_error_init (&m_error); + // TODO: do not use dbus_connection_pop_message() that requires the use of a + // private connection + m_connection = dbus_bus_get_private(DBUS_BUS_SYSTEM, &m_error); + if (m_connection) + { + dbus_connection_set_exit_on_disconnect(m_connection, false); + + dbus_bus_add_match(m_connection, "type='signal',interface='net.connman.Manager'", &m_error); + dbus_connection_flush(m_connection); + if (dbus_error_is_set(&m_error)) + { + CLog::Log(LOGERROR, "ConnmanNetworkManager: Failed to attach to signal %s", m_error.message); + dbus_connection_close(m_connection); + dbus_connection_unref(m_connection); + m_connection = NULL; + } + } + else + CLog::Log(LOGERROR, "ConnmanNetworkManager: Failed to get a DBus connection %s", m_error.message); +} + +CConnmanNetworkManager::~CConnmanNetworkManager() +{ + if (m_connection) + { + dbus_connection_close(m_connection); + dbus_connection_unref(m_connection); + m_connection = NULL; + } + + dbus_error_free (&m_error); +} + +bool CConnmanNetworkManager::CanManageConnections() +{ + // TODO Only return true if we are registered as agent + return true; +} + +ConnectionList CConnmanNetworkManager::GetConnections() +{ + return m_connections; +} + +bool CConnmanNetworkManager::PumpNetworkEvents(INetworkEventsCallback *callback) +{ + bool result = false; + + if (m_connection) + { + dbus_connection_read_write(m_connection, 0); + DBusMessage *msg = dbus_connection_pop_message(m_connection); + + if (msg) + { + CDBusReplyPtr reply = CDBusReplyPtr(new CDBusReply(msg)); + + if (dbus_message_is_signal(msg, "net.connman.Manager", "PropertyChanged")) + { + CVariant key = reply->GetNextArgument(); + m_properties[key.asString()] = reply->GetNextArgument(); + + UpdateNetworkManager(); + + if (strcmp(key.asString().c_str(), "Services") == 0) + callback->OnConnectionListChange(m_connections); + + result = true; + } + else if (dbus_message_is_signal(msg, "net.connman.Manager", "StateChanged")) + { + CVariant stateString = reply->GetNextArgument(); + result = true; + callback->OnConnectionStateChange(CConnmanConnection::ParseConnectionState(stateString.asString().c_str())); + } + else if (dbus_message_is_signal(msg, "net.connman.Manager", "NameAcquired")) + { + } + else + CLog::Log(LOGINFO, "ConnmanNetworkManager: Recieved an unknown signal %s", dbus_message_get_member(msg)); + + dbus_message_unref(msg); + } + } + + for (size_t i = 0; i < m_connections.size(); i++) + { + if (((CConnmanConnection *)m_connections[i].get())->PumpNetworkEvents()) + { + callback->OnConnectionChange(m_connections[i]); + result = true; + } + } + + return result; +} + +bool CConnmanNetworkManager::HasConnman() +{ + CDBusMessage message("net.connman", "/", "net.connman.Manager", "GetProperties"); + + DBusError error; + dbus_error_init (&error); + DBusConnection *connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); + + message.Send(connection, &error); + + if (!dbus_error_is_set(&error)) + return true; + else + { + CLog::Log(LOGDEBUG, "ConnmanNetworkManager: %s - %s", error.name, error.message); + return false; + } +} + +void CConnmanNetworkManager::UpdateNetworkManager() +{ + m_connections.clear(); + + CVariant services = m_properties["Services"]; + + for (unsigned int i = 0; i < services.size(); i++) + { + if (strcmp(services[i].asString().c_str(), "") == 0) + continue; + + IConnection *connection = new CConnmanConnection(services[i].asString().c_str()); + m_connections.push_back(CConnectionPtr(connection)); + } +} +#endif diff --git a/xbmc/network/linux/ConnmanNetworkManager.h b/xbmc/network/linux/ConnmanNetworkManager.h new file mode 100644 index 0000000000000..a7a9388c0498d --- /dev/null +++ b/xbmc/network/linux/ConnmanNetworkManager.h @@ -0,0 +1,51 @@ +#pragma once +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "system.h" +#ifdef HAS_DBUS +#include "network/INetworkManager.h" +#include "utils/Variant.h" +#include + +class CConnmanNetworkManager : public INetworkManager +{ +public: + CConnmanNetworkManager(); + virtual ~CConnmanNetworkManager(); + + + virtual bool CanManageConnections(); + + virtual ConnectionList GetConnections(); + + virtual bool PumpNetworkEvents(INetworkEventsCallback *callback); + + static bool HasConnman(); +private: + void UpdateNetworkManager(); + + ConnectionList m_connections; + CVariant m_properties; + DBusConnection *m_connection; + DBusError m_error; +}; +#endif diff --git a/xbmc/network/linux/Makefile b/xbmc/network/linux/Makefile deleted file mode 100644 index 207ecda33b307..0000000000000 --- a/xbmc/network/linux/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -SRCS=NetworkLinux.cpp \ - ZeroconfAvahi.cpp \ - ZeroconfBrowserAvahi.cpp \ - -LIB=network_linux.a - -include ../../../Makefile.include --include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS))) diff --git a/xbmc/network/linux/Makefile.in b/xbmc/network/linux/Makefile.in new file mode 100644 index 0000000000000..a4b76f8a90336 --- /dev/null +++ b/xbmc/network/linux/Makefile.in @@ -0,0 +1,11 @@ +#SRCS = ConnmanConnection.cpp +#SRCS += ConnmanNetworkManager.cpp +SRCS += PosixConnection.cpp +SRCS += PosixNetworkManager.cpp +SRCS += ZeroconfAvahi.cpp +SRCS += ZeroconfBrowserAvahi.cpp + +LIB = network_linux.a + +include ../../../Makefile.include +-include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS))) \ No newline at end of file diff --git a/xbmc/network/linux/NetworkLinux.cpp b/xbmc/network/linux/NetworkLinux.cpp deleted file mode 100644 index 582d3e3852182..0000000000000 --- a/xbmc/network/linux/NetworkLinux.cpp +++ /dev/null @@ -1,930 +0,0 @@ -/* - * Copyright (C) 2005-2012 Team XBMC - * http://www.xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ - -#include -#include -#include -#include -#if defined(TARGET_LINUX) - #include - #include - #include -#endif -#ifdef TARGET_ANDROID -#include "android/bionic_supplement/bionic_supplement.h" -#include "sys/system_properties.h" -#endif -#include -#include -#if defined(TARGET_DARWIN) - #include - #include - #include - #include -#elif defined(TARGET_FREEBSD) - #include - #include - #include - #include - #include -#else - #include -#endif -#include "PlatformDefs.h" -#include "NetworkLinux.h" -#include "Util.h" -#include "utils/log.h" - -using namespace std; - -CNetworkInterfaceLinux::CNetworkInterfaceLinux(CNetworkLinux* network, CStdString interfaceName, char interfaceMacAddrRaw[6]) - -{ - m_network = network; - m_interfaceName = interfaceName; - m_interfaceMacAdr.Format("%02X:%02X:%02X:%02X:%02X:%02X", - (uint8_t)interfaceMacAddrRaw[0], - (uint8_t)interfaceMacAddrRaw[1], - (uint8_t)interfaceMacAddrRaw[2], - (uint8_t)interfaceMacAddrRaw[3], - (uint8_t)interfaceMacAddrRaw[4], - (uint8_t)interfaceMacAddrRaw[5]); - memcpy(m_interfaceMacAddrRaw, interfaceMacAddrRaw, sizeof(m_interfaceMacAddrRaw)); -} - -CNetworkInterfaceLinux::~CNetworkInterfaceLinux(void) -{ -} - -CStdString& CNetworkInterfaceLinux::GetName(void) -{ - return m_interfaceName; -} - -bool CNetworkInterfaceLinux::IsWireless() -{ -#if defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) - return false; -#else - struct iwreq wrq; - strcpy(wrq.ifr_name, m_interfaceName.c_str()); - if (ioctl(m_network->GetSocket(), SIOCGIWNAME, &wrq) < 0) - return false; -#endif - - return true; -} - -bool CNetworkInterfaceLinux::IsEnabled() -{ - struct ifreq ifr; - strcpy(ifr.ifr_name, m_interfaceName.c_str()); - if (ioctl(m_network->GetSocket(), SIOCGIFFLAGS, &ifr) < 0) - return false; - - return ((ifr.ifr_flags & IFF_UP) == IFF_UP); -} - -bool CNetworkInterfaceLinux::IsConnected() -{ - struct ifreq ifr; - int zero = 0; - memset(&ifr,0,sizeof(struct ifreq)); - strcpy(ifr.ifr_name, m_interfaceName.c_str()); - if (ioctl(m_network->GetSocket(), SIOCGIFFLAGS, &ifr) < 0) - return false; - - // ignore loopback - int iRunning = ( (ifr.ifr_flags & IFF_RUNNING) && (!(ifr.ifr_flags & IFF_LOOPBACK))); - - if (ioctl(m_network->GetSocket(), SIOCGIFADDR, &ifr) < 0) - return false; - - // return only interfaces which has ip address - return iRunning && (0 != memcmp(ifr.ifr_addr.sa_data+sizeof(short), &zero, sizeof(int))); -} - -CStdString CNetworkInterfaceLinux::GetMacAddress() -{ - return m_interfaceMacAdr; -} - -void CNetworkInterfaceLinux::GetMacAddressRaw(char rawMac[6]) -{ - memcpy(rawMac, m_interfaceMacAddrRaw, 6); -} - -CStdString CNetworkInterfaceLinux::GetCurrentIPAddress(void) -{ - CStdString result = ""; - - struct ifreq ifr; - strcpy(ifr.ifr_name, m_interfaceName.c_str()); - ifr.ifr_addr.sa_family = AF_INET; - if (ioctl(m_network->GetSocket(), SIOCGIFADDR, &ifr) >= 0) - { - result = inet_ntoa((*((struct sockaddr_in *)&ifr.ifr_addr)).sin_addr); - } - - return result; -} - -CStdString CNetworkInterfaceLinux::GetCurrentNetmask(void) -{ - CStdString result = ""; - - struct ifreq ifr; - strcpy(ifr.ifr_name, m_interfaceName.c_str()); - ifr.ifr_addr.sa_family = AF_INET; - if (ioctl(m_network->GetSocket(), SIOCGIFNETMASK, &ifr) >= 0) - { - result = inet_ntoa((*((struct sockaddr_in*)&ifr.ifr_addr)).sin_addr); - } - - return result; -} - -CStdString CNetworkInterfaceLinux::GetCurrentWirelessEssId(void) -{ - CStdString result = ""; - -#if defined(TARGET_LINUX) - char essid[IW_ESSID_MAX_SIZE + 1]; - memset(&essid, 0, sizeof(essid)); - - struct iwreq wrq; - strcpy(wrq.ifr_name, m_interfaceName.c_str()); - wrq.u.essid.pointer = (caddr_t) essid; - wrq.u.essid.length = IW_ESSID_MAX_SIZE; - wrq.u.essid.flags = 0; - if (ioctl(m_network->GetSocket(), SIOCGIWESSID, &wrq) >= 0) - { - result = essid; - } -#endif - - return result; -} - -CStdString CNetworkInterfaceLinux::GetCurrentDefaultGateway(void) -{ - CStdString result = ""; - -#if defined(TARGET_DARWIN) - FILE* pipe = popen("echo \"show State:/Network/Global/IPv4\" | scutil | grep Router", "r"); - if (pipe) - { - CStdString tmpStr; - char buffer[256] = {'\0'}; - if (fread(buffer, sizeof(char), sizeof(buffer), pipe) > 0 && !ferror(pipe)) - { - tmpStr = buffer; - result = tmpStr.Mid(11); - } - else - { - CLog::Log(LOGWARNING, "Unable to determine gateway"); - } - pclose(pipe); - } -#elif defined(TARGET_FREEBSD) - size_t needed; - int mib[6]; - char *buf, *next, *lim; - char line[16]; - struct rt_msghdr *rtm; - struct sockaddr *sa; - struct sockaddr_in *sockin; - - mib[0] = CTL_NET; - mib[1] = PF_ROUTE; - mib[2] = 0; - mib[3] = 0; - mib[4] = NET_RT_DUMP; - mib[5] = 0; - if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) - return result; - - if ((buf = (char *)malloc(needed)) == NULL) - return result; - - if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { - free(buf); - return result; - } - - lim = buf + needed; - for (next = buf; next < lim; next += rtm->rtm_msglen) { - rtm = (struct rt_msghdr *)next; - sa = (struct sockaddr *)(rtm + 1); - sa = (struct sockaddr *)(SA_SIZE(sa) + (char *)sa); - sockin = (struct sockaddr_in *)sa; - if (inet_ntop(AF_INET, &sockin->sin_addr.s_addr, - line, sizeof(line)) == NULL) { - free(buf); - return result; - } - result = line; - break; - } - free(buf); -#else - FILE* fp = fopen("/proc/net/route", "r"); - if (!fp) - { - // TBD: Error - return result; - } - - char* line = NULL; - char iface[16]; - char dst[128]; - char gateway[128]; - size_t linel = 0; - int n; - int linenum = 0; - while (getdelim(&line, &linel, '\n', fp) > 0) - { - // skip first two lines - if (linenum++ < 1) - continue; - - // search where the word begins - n = sscanf(line, "%16s %128s %128s", - iface, dst, gateway); - - if (n < 3) - continue; - - if (strcmp(iface, m_interfaceName.c_str()) == 0 && - strcmp(dst, "00000000") == 0 && - strcmp(gateway, "00000000") != 0) - { - unsigned char gatewayAddr[4]; - int len = CNetwork::ParseHex(gateway, gatewayAddr); - if (len == 4) - { - struct in_addr in; - in.s_addr = (gatewayAddr[0] << 24) | (gatewayAddr[1] << 16) | - (gatewayAddr[2] << 8) | (gatewayAddr[3]); - result = inet_ntoa(in); - break; - } - } - } - free(line); - fclose(fp); -#endif - - return result; -} - -CNetworkLinux::CNetworkLinux(void) -{ - m_sock = socket(AF_INET, SOCK_DGRAM, 0); - queryInterfaceList(); -} - -CNetworkLinux::~CNetworkLinux(void) -{ - if (m_sock != -1) - close(CNetworkLinux::m_sock); - - vector::iterator it = m_interfaces.begin(); - while(it != m_interfaces.end()) - { - CNetworkInterface* nInt = *it; - delete nInt; - it = m_interfaces.erase(it); - } -} - -std::vector& CNetworkLinux::GetInterfaceList(void) -{ - return m_interfaces; -} - -// Overwrite the GetFirstConnectedInterface and requery -// the interface list if no connected device is found -// this fixes a bug when no network is available after first start of xbmc -// and the interface comes up during runtime -CNetworkInterface* CNetworkLinux::GetFirstConnectedInterface(void) -{ - CNetworkInterface *pNetIf=CNetwork::GetFirstConnectedInterface(); - - // no connected Interfaces found? - requeryInterfaceList - if (!pNetIf) - { - CLog::Log(LOGDEBUG,"%s no connected interface found - requery list",__FUNCTION__); - queryInterfaceList(); - //retry finding a connected if - pNetIf = CNetwork::GetFirstConnectedInterface(); - } - - return pNetIf; -} - - -void CNetworkLinux::GetMacAddress(CStdString interfaceName, char rawMac[6]) -{ - memset(rawMac, 0, 6); -#if defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) - -#if !defined(IFT_ETHER) -#define IFT_ETHER 0x6/* Ethernet CSMACD */ -#endif - const struct sockaddr_dl* dlAddr = NULL; - const uint8_t * base = NULL; - // Query the list of interfaces. - struct ifaddrs *list; - struct ifaddrs *interface; - - if( getifaddrs(&list) < 0 ) - { - return; - } - - for(interface = list; interface != NULL; interface = interface->ifa_next) - { - if(CStdString(interface->ifa_name).Equals(interfaceName)) - { - if ( (interface->ifa_addr->sa_family == AF_LINK) && (((const struct sockaddr_dl *) interface->ifa_addr)->sdl_type == IFT_ETHER) ) - { - dlAddr = (const struct sockaddr_dl *) interface->ifa_addr; - base = (const uint8_t *) &dlAddr->sdl_data[dlAddr->sdl_nlen]; - - if( dlAddr->sdl_alen > 5 ) - { - memcpy(rawMac, base, 6); - } - } - break; - } - } - - freeifaddrs(list); - -#else - - struct ifreq ifr; - strcpy(ifr.ifr_name, interfaceName.c_str()); - if (ioctl(GetSocket(), SIOCGIFHWADDR, &ifr) >= 0) - { - memcpy(rawMac, ifr.ifr_hwaddr.sa_data, 6); - } -#endif -} - -void CNetworkLinux::queryInterfaceList() -{ - char macAddrRaw[6]; - m_interfaces.clear(); - -#if defined(TARGET_DARWIN) || defined(TARGET_FREEBSD) - - // Query the list of interfaces. - struct ifaddrs *list; - if (getifaddrs(&list) < 0) - return; - - struct ifaddrs *cur; - for(cur = list; cur != NULL; cur = cur->ifa_next) - { - if(cur->ifa_addr->sa_family != AF_INET) - continue; - - GetMacAddress(cur->ifa_name, macAddrRaw); - // Add the interface. - m_interfaces.push_back(new CNetworkInterfaceLinux(this, cur->ifa_name, macAddrRaw)); - } - - freeifaddrs(list); - -#else - FILE* fp = fopen("/proc/net/dev", "r"); - if (!fp) - { - // TBD: Error - return; - } - - char* line = NULL; - size_t linel = 0; - int n; - char* p; - int linenum = 0; - while (getdelim(&line, &linel, '\n', fp) > 0) - { - // skip first two lines - if (linenum++ < 2) - continue; - - // search where the word begins - p = line; - while (isspace(*p)) - ++p; - - // read word until : - n = strcspn(p, ": \t"); - p[n] = 0; - - // save the result - CStdString interfaceName = p; - GetMacAddress(interfaceName, macAddrRaw); - m_interfaces.push_back(new CNetworkInterfaceLinux(this, interfaceName, macAddrRaw)); - } - free(line); - fclose(fp); -#endif -} - -std::vector CNetworkLinux::GetNameServers(void) -{ - std::vector result; - -#if defined(TARGET_DARWIN) - //only finds the primary dns (0 :) - FILE* pipe = popen("scutil --dns | grep \"nameserver\\[0\\]\" | tail -n1", "r"); - if (pipe) - { - CStdString tmpStr; - char buffer[256] = {'\0'}; - if (fread(buffer, sizeof(char), sizeof(buffer), pipe) > 0 && !ferror(pipe)) - { - tmpStr = buffer; - result.push_back(tmpStr.Mid(17)); - } - else - { - CLog::Log(LOGWARNING, "Unable to determine nameserver"); - } - pclose(pipe); - } -#elif defined(TARGET_ANDROID) - char nameserver[PROP_VALUE_MAX]; - - if (__system_property_get("net.dns1",nameserver)) - result.push_back(nameserver); - if (__system_property_get("net.dns2",nameserver)) - result.push_back(nameserver); - if (__system_property_get("net.dns3",nameserver)) - result.push_back(nameserver); - - if (!result.size()) - CLog::Log(LOGWARNING, "Unable to determine nameserver"); -#else - res_init(); - - for (int i = 0; i < _res.nscount; i ++) - { - CStdString ns = inet_ntoa(((struct sockaddr_in *)&_res.nsaddr_list[i])->sin_addr); - result.push_back(ns); - } -#endif - return result; -} - -void CNetworkLinux::SetNameServers(std::vector nameServers) -{ -#if !defined(__ANDROID__) - FILE* fp = fopen("/etc/resolv.conf", "w"); - if (fp != NULL) - { - for (unsigned int i = 0; i < nameServers.size(); i++) - { - fprintf(fp, "nameserver %s\n", nameServers[i].c_str()); - } - fclose(fp); - } - else - { - // TODO: - } -#endif -} - -std::vector CNetworkInterfaceLinux::GetAccessPoints(void) -{ - std::vector result; - - if (!IsWireless()) - return result; - -#if defined(TARGET_LINUX) - // Query the wireless extentsions version number. It will help us when we - // parse the resulting events - struct iwreq iwr; - char rangebuffer[sizeof(iw_range) * 2]; /* Large enough */ - struct iw_range* range = (struct iw_range*) rangebuffer; - - memset(rangebuffer, 0, sizeof(rangebuffer)); - iwr.u.data.pointer = (caddr_t) rangebuffer; - iwr.u.data.length = sizeof(rangebuffer); - iwr.u.data.flags = 0; - strncpy(iwr.ifr_name, GetName().c_str(), IFNAMSIZ); - if (ioctl(m_network->GetSocket(), SIOCGIWRANGE, &iwr) < 0) - { - CLog::Log(LOGWARNING, "%-8.16s Driver has no Wireless Extension version information.", - GetName().c_str()); - return result; - } - - // Scan for wireless access points - memset(&iwr, 0, sizeof(iwr)); - strncpy(iwr.ifr_name, GetName().c_str(), IFNAMSIZ); - if (ioctl(m_network->GetSocket(), SIOCSIWSCAN, &iwr) < 0) - { - CLog::Log(LOGWARNING, "Cannot initiate wireless scan: ioctl[SIOCSIWSCAN]: %s", strerror(errno)); - return result; - } - - // Get the results of the scanning. Three scenarios: - // 1. There's not enough room in the result buffer (E2BIG) - // 2. The scanning is not complete (EAGAIN) and we need to try again. We cap this with 15 seconds. - // 3. Were'e good. - int duration = 0; // ms - unsigned char* res_buf = NULL; - int res_buf_len = IW_SCAN_MAX_DATA; - while (duration < 15000) - { - if (!res_buf) - res_buf = (unsigned char*) malloc(res_buf_len); - - if (res_buf == NULL) - { - CLog::Log(LOGWARNING, "Cannot alloc memory for wireless scanning"); - return result; - } - - strncpy(iwr.ifr_name, GetName().c_str(), IFNAMSIZ); - iwr.u.data.pointer = res_buf; - iwr.u.data.length = res_buf_len; - iwr.u.data.flags = 0; - int x = ioctl(m_network->GetSocket(), SIOCGIWSCAN, &iwr); - if (x == 0) - break; - - if (errno == E2BIG && res_buf_len < 100000) - { - free(res_buf); - res_buf = NULL; - res_buf_len *= 2; - CLog::Log(LOGDEBUG, "Scan results did not fit - trying larger buffer (%lu bytes)", - (unsigned long) res_buf_len); - } - else if (errno == EAGAIN) - { - usleep(250000); // sleep for 250ms - duration += 250; - } - else - { - CLog::Log(LOGWARNING, "Cannot get wireless scan results: ioctl[SIOCGIWSCAN]: %s", strerror(errno)); - free(res_buf); - return result; - } - } - - size_t len = iwr.u.data.length; - char* pos = (char *) res_buf; - char* end = (char *) res_buf + len; - char* custom; - struct iw_event iwe_buf, *iwe = &iwe_buf; - - CStdString essId; - int quality = 0; - EncMode encryption = ENC_NONE; - bool first = true; - - while (pos + IW_EV_LCP_LEN <= end) - { - /* Event data may be unaligned, so make a local, aligned copy - * before processing. */ - memcpy(&iwe_buf, pos, IW_EV_LCP_LEN); - if (iwe->len <= IW_EV_LCP_LEN) - break; - - custom = pos + IW_EV_POINT_LEN; - if (range->we_version_compiled > 18 && - (iwe->cmd == SIOCGIWESSID || - iwe->cmd == SIOCGIWENCODE || - iwe->cmd == IWEVGENIE || - iwe->cmd == IWEVCUSTOM)) - { - /* Wireless extentsions v19 removed the pointer from struct iw_point */ - char *dpos = (char *) &iwe_buf.u.data.length; - int dlen = dpos - (char *) &iwe_buf; - memcpy(dpos, pos + IW_EV_LCP_LEN, sizeof(struct iw_event) - dlen); - } - else - { - memcpy(&iwe_buf, pos, sizeof(struct iw_event)); - custom += IW_EV_POINT_OFF; - } - - switch (iwe->cmd) - { - case SIOCGIWAP: - if (first) - first = false; - else - result.push_back(NetworkAccessPoint(essId, quality, encryption)); - encryption = ENC_NONE; - break; - - case SIOCGIWESSID: - { - char essid[IW_ESSID_MAX_SIZE+1]; - memset(essid, '\0', sizeof(essid)); - if ((custom) && (iwe->u.essid.length)) - { - memcpy(essid, custom, iwe->u.essid.length); - essId = essid; - } - break; - } - - case IWEVQUAL: - quality = iwe->u.qual.qual; - break; - - case SIOCGIWENCODE: - if (!(iwe->u.data.flags & IW_ENCODE_DISABLED) && encryption == ENC_NONE) - encryption = ENC_WEP; - break; - - case IWEVGENIE: - { - int offset = 0; - while (offset <= iwe_buf.u.data.length) - { - switch ((unsigned char)custom[offset]) - { - case 0xdd: /* WPA1 */ - if (encryption != ENC_WPA2) - encryption = ENC_WPA; - break; - case 0x30: /* WPA2 */ - encryption = ENC_WPA2; - } - - offset += custom[offset+1] + 2; - } - } - } - - pos += iwe->len; - } - - if (!first) - result.push_back(NetworkAccessPoint(essId, quality, encryption)); - - free(res_buf); - res_buf = NULL; -#endif - - return result; -} - -void CNetworkInterfaceLinux::GetSettings(NetworkAssignment& assignment, CStdString& ipAddress, CStdString& networkMask, CStdString& defaultGateway, CStdString& essId, CStdString& key, EncMode& encryptionMode) -{ - ipAddress = "0.0.0.0"; - networkMask = "0.0.0.0"; - defaultGateway = "0.0.0.0"; - essId = ""; - key = ""; - encryptionMode = ENC_NONE; - assignment = NETWORK_DISABLED; - -#if defined(TARGET_LINUX) - FILE* fp = fopen("/etc/network/interfaces", "r"); - if (!fp) - { - // TODO - return; - } - - char* line = NULL; - size_t linel = 0; - CStdString s; - bool foundInterface = false; - - while (getdelim(&line, &linel, '\n', fp) > 0) - { - vector tokens; - - s = line; - s.TrimLeft(" \t").TrimRight(" \n"); - - // skip comments - if (s.length() == 0 || s.GetAt(0) == '#') - continue; - - // look for "iface inet" - CUtil::Tokenize(s, tokens, " "); - if (!foundInterface && - tokens.size() >=3 && - tokens[0].Equals("iface") && - tokens[1].Equals(GetName()) && - tokens[2].Equals("inet")) - { - if (tokens[3].Equals("dhcp")) - { - assignment = NETWORK_DHCP; - foundInterface = true; - } - if (tokens[3].Equals("static")) - { - assignment = NETWORK_STATIC; - foundInterface = true; - } - } - - if (foundInterface && tokens.size() == 2) - { - if (tokens[0].Equals("address")) ipAddress = tokens[1]; - else if (tokens[0].Equals("netmask")) networkMask = tokens[1]; - else if (tokens[0].Equals("gateway")) defaultGateway = tokens[1]; - else if (tokens[0].Equals("wireless-essid")) essId = tokens[1]; - else if (tokens[0].Equals("wireless-key")) - { - key = tokens[1]; - if (key.length() > 2 && key[0] == 's' && key[1] == ':') - key.erase(0, 2); - encryptionMode = ENC_WEP; - } - else if (tokens[0].Equals("wpa-ssid")) essId = tokens[1]; - else if (tokens[0].Equals("wpa-proto") && tokens[1].Equals("WPA")) encryptionMode = ENC_WPA; - else if (tokens[0].Equals("wpa-proto") && tokens[1].Equals("WPA2")) encryptionMode = ENC_WPA2; - else if (tokens[0].Equals("wpa-psk")) key = tokens[1]; - else if (tokens[0].Equals("auto") || tokens[0].Equals("iface") || tokens[0].Equals("mapping")) break; - } - } - free(line); - - // Fallback in case wpa-proto is not set - if (key != "" && encryptionMode == ENC_NONE) - encryptionMode = ENC_WPA; - - fclose(fp); -#endif -} - -void CNetworkInterfaceLinux::SetSettings(NetworkAssignment& assignment, CStdString& ipAddress, CStdString& networkMask, CStdString& defaultGateway, CStdString& essId, CStdString& key, EncMode& encryptionMode) -{ -#if defined(TARGET_LINUX) - FILE* fr = fopen("/etc/network/interfaces", "r"); - if (!fr) - { - // TODO - return; - } - - FILE* fw = fopen("/tmp/interfaces.temp", "w"); - if (!fw) - { - // TODO - fclose(fr); - return; - } - - char* line = NULL; - size_t linel = 0; - CStdString s; - bool foundInterface = false; - bool dataWritten = false; - - while (getdelim(&line, &linel, '\n', fr) > 0) - { - vector tokens; - - s = line; - s.TrimLeft(" \t").TrimRight(" \n"); - - // skip comments - if (!foundInterface && (s.length() == 0 || s.GetAt(0) == '#')) - { - fprintf(fw, "%s", line); - continue; - } - - // look for "iface inet" - CUtil::Tokenize(s, tokens, " "); - if (tokens.size() == 2 && - tokens[0].Equals("auto") && - tokens[1].Equals(GetName())) - { - continue; - } - else if (!foundInterface && - tokens.size() == 4 && - tokens[0].Equals("iface") && - tokens[1].Equals(GetName()) && - tokens[2].Equals("inet")) - { - foundInterface = true; - WriteSettings(fw, assignment, ipAddress, networkMask, defaultGateway, essId, key, encryptionMode); - dataWritten = true; - } - else if (foundInterface && - tokens.size() == 4 && - tokens[0].Equals("iface")) - { - foundInterface = false; - fprintf(fw, "%s", line); - } - else if (!foundInterface) - { - fprintf(fw, "%s", line); - } - } - free(line); - - if (!dataWritten && assignment != NETWORK_DISABLED) - { - fprintf(fw, "\n"); - WriteSettings(fw, assignment, ipAddress, networkMask, defaultGateway, essId, key, encryptionMode); - } - - fclose(fr); - fclose(fw); - - // Rename the file - if (rename("/tmp/interfaces.temp", "/etc/network/interfaces") < 0) - { - // TODO - return; - } - - std::string cmd = "/sbin/ifdown " + GetName(); - if (system(cmd.c_str()) != 0) - CLog::Log(LOGERROR, "Unable to stop interface %s", GetName().c_str()); - else - CLog::Log(LOGINFO, "Stopped interface %s", GetName().c_str()); - - if (assignment != NETWORK_DISABLED) - { - cmd = "/sbin/ifup " + GetName(); - if (system(cmd.c_str()) != 0) - CLog::Log(LOGERROR, "Unable to start interface %s", GetName().c_str()); - else - CLog::Log(LOGINFO, "Started interface %s", GetName().c_str()); - } -#endif -} - -void CNetworkInterfaceLinux::WriteSettings(FILE* fw, NetworkAssignment assignment, CStdString& ipAddress, CStdString& networkMask, CStdString& defaultGateway, CStdString& essId, CStdString& key, EncMode& encryptionMode) -{ - if (assignment == NETWORK_DHCP) - { - fprintf(fw, "iface %s inet dhcp\n", GetName().c_str()); - } - else if (assignment == NETWORK_STATIC) - { - fprintf(fw, "iface %s inet static\n", GetName().c_str()); - fprintf(fw, " address %s\n", ipAddress.c_str()); - fprintf(fw, " netmask %s\n", networkMask.c_str()); - fprintf(fw, " gateway %s\n", defaultGateway.c_str()); - } - - if (assignment != NETWORK_DISABLED && IsWireless()) - { - if (encryptionMode == ENC_NONE) - { - fprintf(fw, " wireless-essid %s\n", essId.c_str()); - } - else if (encryptionMode == ENC_WEP) - { - fprintf(fw, " wireless-essid %s\n", essId.c_str()); - fprintf(fw, " wireless-key s:%s\n", key.c_str()); - } - else if (encryptionMode == ENC_WPA || encryptionMode == ENC_WPA2) - { - fprintf(fw, " wpa-ssid %s\n", essId.c_str()); - fprintf(fw, " wpa-psk %s\n", key.c_str()); - fprintf(fw, " wpa-proto %s\n", encryptionMode == ENC_WPA ? "WPA" : "WPA2"); - } - } - - if (assignment != NETWORK_DISABLED) - fprintf(fw, "auto %s\n\n", GetName().c_str()); -} - - diff --git a/xbmc/network/linux/NetworkLinux.h b/xbmc/network/linux/NetworkLinux.h deleted file mode 100644 index df094983a84b5..0000000000000 --- a/xbmc/network/linux/NetworkLinux.h +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef NETWORK_LINUX_H_ -#define NETWORK_LINUX_H_ - -/* - * Copyright (C) 2005-2012 Team XBMC - * http://www.xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, see - * . - * - */ - -#include -#include "utils/StdString.h" -#include "network/Network.h" - -class CNetworkLinux; - -class CNetworkInterfaceLinux : public CNetworkInterface -{ -public: - CNetworkInterfaceLinux(CNetworkLinux* network, CStdString interfaceName, char interfaceMacAddrRaw[6]); - ~CNetworkInterfaceLinux(void); - - virtual CStdString& GetName(void); - - virtual bool IsEnabled(void); - virtual bool IsConnected(void); - virtual bool IsWireless(void); - - virtual CStdString GetMacAddress(void); - virtual void GetMacAddressRaw(char rawMac[6]); - - virtual CStdString GetCurrentIPAddress(); - virtual CStdString GetCurrentNetmask(); - virtual CStdString GetCurrentDefaultGateway(void); - virtual CStdString GetCurrentWirelessEssId(void); - - virtual void GetSettings(NetworkAssignment& assignment, CStdString& ipAddress, CStdString& networkMask, CStdString& defaultGateway, CStdString& essId, CStdString& key, EncMode& encryptionMode); - virtual void SetSettings(NetworkAssignment& assignment, CStdString& ipAddress, CStdString& networkMask, CStdString& defaultGateway, CStdString& essId, CStdString& key, EncMode& encryptionMode); - - // Returns the list of access points in the area - virtual std::vector GetAccessPoints(void); - -private: - void WriteSettings(FILE* fw, NetworkAssignment assignment, CStdString& ipAddress, CStdString& networkMask, CStdString& defaultGateway, CStdString& essId, CStdString& key, EncMode& encryptionMode); - CStdString m_interfaceName; - CStdString m_interfaceMacAdr; - char m_interfaceMacAddrRaw[6]; - CNetworkLinux* m_network; -}; - -class CNetworkLinux : public CNetwork -{ -public: - CNetworkLinux(void); - virtual ~CNetworkLinux(void); - - // Return the list of interfaces - virtual std::vector& GetInterfaceList(void); - virtual CNetworkInterface* GetFirstConnectedInterface(void); - - // Get/set the nameserver(s) - virtual std::vector GetNameServers(void); - virtual void SetNameServers(std::vector nameServers); - - friend class CNetworkInterfaceLinux; - -private: - int GetSocket() { return m_sock; } - void GetMacAddress(CStdString interfaceName, char macAddrRaw[6]); - void queryInterfaceList(); - std::vector m_interfaces; - int m_sock; -}; - -#endif - diff --git a/xbmc/network/linux/PosixConnection.cpp b/xbmc/network/linux/PosixConnection.cpp new file mode 100644 index 0000000000000..d4006d0597520 --- /dev/null +++ b/xbmc/network/linux/PosixConnection.cpp @@ -0,0 +1,712 @@ +/* + * Copyright (C) 2011-2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "PosixConnection.h" +#include "Util.h" +#include "linux/XTimeUtils.h" +#include "utils/StdString.h" +#include "utils/log.h" + +// temp until keychainManager is working +#include "settings/GUISettings.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(TARGET_LINUX) + #include + #include + #include + #include +#endif + +#ifdef TARGET_ANDROID + #include "android/bionic_supplement/bionic_supplement.h" + #include "sys/system_properties.h" +#endif + +//----------------------------------------------------------------------- +int PosixParseHex(char *str, unsigned char *addr) +{ + int len = 0; + + while (*str) + { + int tmp; + if (str[1] == 0) + return -1; + if (sscanf(str, "%02x", (unsigned int *)&tmp) != 1) + return -1; + addr[len] = tmp; + len++; + str += 2; + } + + return len; +} + +bool PosixCheckHex(const std::string &passphrase) +{ + // we could get fooled by strings that only + // have 0-9, A, B, C, D, E, F in them :) + for (size_t i = 0; i < passphrase.size(); i++) + { + switch (passphrase[i]) + { + default: + return false; + break; + case '0':case '1':case '2':case '3':case '4': + case '5':case '6':case '7':case '8':case '9': + case 'a':case 'A':case 'b':case 'B': + case 'c':case 'C':case 'd':case 'D': + case 'e':case 'E':case 'f':case 'F': + break; + } + } + + return true; +} + +bool PosixGuessIsHexPassPhrase(const std::string &passphrase, EncryptionType encryption) +{ + if (encryption == NETWORK_CONNECTION_ENCRYPTION_WEP) + { + // wep hex 256-bit is 58 characters. + if (passphrase.size() == 58) + return true; + + // wep hex 152-bit is 32 characters. + if (passphrase.size() == 32) + return true; + + // wep hex 128-bit is 26 characters. + if (passphrase.size() == 26) + return true; + + // wep hex 64-bit is 10 characters. + if (passphrase.size() == 10) + return true; + } + else + { + // wap/wpa2 hex has a length of 64. + if (passphrase.size() == 64) + return true; + } + + // anthing else is wep/wap/wpa2 ascii + return false; +} + +bool IsWireless(int socket, const char *interface) +{ + struct iwreq wrq; + memset(&wrq, 0x00, sizeof(iwreq)); + + strcpy(wrq.ifr_name, interface); + if (ioctl(socket, SIOCGIWNAME, &wrq) < 0) + return false; + + return true; +} + +bool PosixCheckInterfaceUp(const std::string &interface) +{ + std::string iface_state; + std::string sysclasspath("/sys/class/net/" + interface + "/operstate"); + + int fd = open(sysclasspath.c_str(), O_RDONLY); + if (fd >= 0) + { + char buffer[256] = {0}; + read(fd, buffer, 255); + close(fd); + // make sure we can treat this as a c-str. + buffer[255] = 0; + iface_state = buffer; + } + if (iface_state.find("up") != std::string::npos) + return true; + else + return false; +} + +std::string PosixGetDefaultGateway(const std::string &interface) +{ + std::string result = ""; + + FILE* fp = fopen("/proc/net/route", "r"); + if (!fp) + return result; + + char* line = NULL; + size_t linel = 0; + int n, linenum = 0; + char dst[128], iface[16], gateway[128]; + while (getdelim(&line, &linel, '\n', fp) > 0) + { + // skip first two lines + if (linenum++ < 1) + continue; + + // search where the word begins + n = sscanf(line, "%16s %128s %128s", iface, dst, gateway); + + if (n < 3) + continue; + + if (strcmp(iface, interface.c_str()) == 0 && + strcmp(dst, "00000000") == 0 && + strcmp(gateway, "00000000") != 0) + { + unsigned char gatewayAddr[4]; + int len = PosixParseHex(gateway, gatewayAddr); + if (len == 4) + { + struct in_addr in; + in.s_addr = (gatewayAddr[0] << 24) | + (gatewayAddr[1] << 16) | + (gatewayAddr[2] << 8) | + (gatewayAddr[3]); + result = inet_ntoa(in); + break; + } + } + } + free(line); + fclose(fp); + + return result; +} + +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +CPosixConnection::CPosixConnection(bool managed, + int socket, const char *interface, const char *macaddress, + const char *essid, ConnectionType type, EncryptionType encryption, int signal) +{ + m_managed = managed; + m_socket = socket; + + m_type = type; + m_essid = essid; + m_signal = signal; + m_interface = interface; + m_macaddress = macaddress; + m_encryption = encryption; + + m_state = GetState(); +} + +CPosixConnection::~CPosixConnection() +{ +} + +std::string CPosixConnection::GetName() const +{ + return m_essid; +} + +std::string CPosixConnection::GetAddress() const +{ + struct ifreq ifr; + strcpy(ifr.ifr_name, m_interface.c_str()); + ifr.ifr_addr.sa_family = AF_INET; + + if (ioctl(m_socket, SIOCGIFADDR, &ifr) >= 0) + return inet_ntoa((*((struct sockaddr_in*)&ifr.ifr_addr)).sin_addr); + else + return ""; +} + +std::string CPosixConnection::GetNetmask() const +{ + struct ifreq ifr; + strcpy(ifr.ifr_name, m_interface.c_str()); + ifr.ifr_addr.sa_family = AF_INET; + + if (ioctl(m_socket, SIOCGIFNETMASK, &ifr) >= 0) + return inet_ntoa((*((struct sockaddr_in*)&ifr.ifr_addr)).sin_addr); + else + return ""; +} + +std::string CPosixConnection::GetGateway() const +{ + return PosixGetDefaultGateway(m_interface); +} + +std::string CPosixConnection::GetNameServer() const +{ + std::string nameserver("127.0.0.1"); + +#if defined(TARGET_ANDROID) + char ns[PROP_VALUE_MAX]; + + if (__system_property_get("net.dns1", ns)) + nameserver = ns; +#else + res_init(); + for (int i = 0; i < _res.nscount; i ++) + { + nameserver = inet_ntoa(((struct sockaddr_in *)&_res.nsaddr_list[0])->sin_addr); + break; + } +#endif + return nameserver; +} + +std::string CPosixConnection::GetMacAddress() const +{ + CStdString result; + result.Format("00:00:00:00:00:00"); + + struct ifreq ifr; + strcpy(ifr.ifr_name, m_interface.c_str()); + if (ioctl(m_socket, SIOCGIFHWADDR, &ifr) >= 0) + { + result.Format("%02X:%02X:%02X:%02X:%02X:%02X", + ifr.ifr_hwaddr.sa_data[0], ifr.ifr_hwaddr.sa_data[1], + ifr.ifr_hwaddr.sa_data[2], ifr.ifr_hwaddr.sa_data[3], + ifr.ifr_hwaddr.sa_data[4], ifr.ifr_hwaddr.sa_data[5]); + } + + return result.c_str(); +} + +ConnectionType CPosixConnection::GetType() const +{ + return m_type; +} + +ConnectionState CPosixConnection::GetState() const +{ + int zero = 0; + struct ifreq ifr; + + memset(&ifr, 0x00, sizeof(struct ifreq)); + // check if the interface is up. + strcpy(ifr.ifr_name, m_interface.c_str()); + if (ioctl(m_socket, SIOCGIFFLAGS, &ifr) < 0) + return NETWORK_CONNECTION_STATE_DISCONNECTED; + + // check for running and not loopback + if (!(ifr.ifr_flags & IFF_RUNNING) || (ifr.ifr_flags & IFF_LOOPBACK)) + return NETWORK_CONNECTION_STATE_DISCONNECTED; + + // check for an ip address + if (ioctl(m_socket, SIOCGIFADDR, &ifr) < 0) + return NETWORK_CONNECTION_STATE_DISCONNECTED; + + if (ifr.ifr_addr.sa_data == NULL) + return NETWORK_CONNECTION_STATE_DISCONNECTED; + + // return only interfaces which have an ip address + if (memcmp(ifr.ifr_addr.sa_data + sizeof(short), &zero, sizeof(int)) == 0) + return NETWORK_CONNECTION_STATE_DISCONNECTED; + + if (m_type == NETWORK_CONNECTION_TYPE_WIFI) + { + // for wifi, we need to check we have a wifi driver name. + struct iwreq wrq; + strcpy(wrq.ifr_name, m_interface.c_str()); + if (ioctl(m_socket, SIOCGIWNAME, &wrq) < 0) + return NETWORK_CONNECTION_STATE_DISCONNECTED; + + // since the wifi interface can be connected to + // any wifi access point, we need to compare the assigned + // essid to our connection essid. If they match, then + // this connection is up. + char essid[IFNAMSIZ]; + memset(&wrq, 0x00, sizeof(struct iwreq)); + wrq.u.essid.pointer = (caddr_t)essid; + wrq.u.essid.length = sizeof(essid); + strncpy(wrq.ifr_name, m_interface.c_str(), IFNAMSIZ); + if (ioctl(m_socket, SIOCGIWESSID, &wrq) < 0) + return NETWORK_CONNECTION_STATE_DISCONNECTED; + + if (wrq.u.essid.length <= 0) + return NETWORK_CONNECTION_STATE_DISCONNECTED; + + std::string test_essid(essid, wrq.u.essid.length); + if (m_essid.find(test_essid) == std::string::npos) + return NETWORK_CONNECTION_STATE_DISCONNECTED; + } + + // finally, we need to see if we have a gateway assigned to our interface. + std::string default_gateway = PosixGetDefaultGateway(m_interface); + if (default_gateway.size() <= 0) + return NETWORK_CONNECTION_STATE_DISCONNECTED; + + // passing the above tests means we are connected. + return NETWORK_CONNECTION_STATE_CONNECTED; +} + +unsigned int CPosixConnection::GetSpeed() const +{ + int speed = 100; + return speed; +} + +IPConfigMethod CPosixConnection::GetMethod() const +{ + return m_method; +} + +unsigned int CPosixConnection::GetStrength() const +{ + /* + int strength = 100; + if (m_type == NETWORK_CONNECTION_TYPE_WIFI) + { + struct iwreq wreq; + // wireless tools says this is large enough + char buffer[sizeof(struct iw_range) * 2]; + int max_qual_level = 0; + double max_qual = 92.0; + + // Fetch the range + memset(buffer, 0x00, sizeof(iw_range) * 2); + memset(&wreq, 0x00, sizeof(struct iwreq)); + wreq.u.data.pointer = (caddr_t)buffer; + wreq.u.data.length = sizeof(buffer); + wreq.u.data.flags = 0; + strncpy(wreq.ifr_name, m_interface.c_str(), IFNAMSIZ); + if (ioctl(m_socket, SIOCGIWRANGE, &wreq) >= 0) + { + struct iw_range *range = (struct iw_range*)buffer; + if (range->max_qual.qual > 0) + max_qual = range->max_qual.qual; + if (range->max_qual.level > 0) + max_qual_level = range->max_qual.level; + } + printf("CPosixConnection::GetStrength, max_qual(%d), qual(%d)\n", max_qual_level, max_qual_level); + + struct iw_statistics stats; + memset(&wreq, 0x00, sizeof(struct iwreq)); + // Fetch the stats + wreq.u.data.pointer = (caddr_t)&stats; + wreq.u.data.length = sizeof(stats); + wreq.u.data.flags = 1; // Clear updated flag + strncpy(wreq.ifr_name, m_interface.c_str(), IFNAMSIZ); + if (ioctl(m_socket, SIOCGIWSTATS, &wreq) < 0) { + return strength; + } + + // this is not correct :) + strength = (100 * wreq.u.qual.qual)/256; + + printf("CPosixConnection::GetStrength, strength(%d), qual(%d)\n", strength, wreq.u.qual.qual); + } + return strength; + */ + return m_signal; +} + +EncryptionType CPosixConnection::GetEncryption() const +{ + return m_encryption; +} + +bool CPosixConnection::Connect(IPassphraseStorage *storage, const CIPConfig &ipconfig) +{ + if (!m_managed) + return true; + + std::string passphrase(""); + + if (storage && m_type == NETWORK_CONNECTION_TYPE_WIFI) + { + if (m_encryption != NETWORK_CONNECTION_ENCRYPTION_NONE) + { + if (!storage->GetPassphrase(m_essid, passphrase)) + return false; + if (passphrase.size() <= 0) + return false; + } + } + else + { + passphrase = g_guiSettings.GetString("network.passphrase"); + /* + CVariant secret; + if (m_keyringManager->FindSecret("network", m_essid, secret) && secret.isString()) + { + passphrase = secret.asString(); + return true; + } + */ + } + + if (DoConnection(ipconfig, passphrase) && GetState() == NETWORK_CONNECTION_STATE_CONNECTED) + { + // if we connect, save out the essid + g_guiSettings.SetString("network.essid", m_essid.c_str()); + // quick update of some internal vars + m_method = ipconfig.m_method; + m_address = ipconfig.m_address; + m_netmask = ipconfig.m_netmask; + m_gateway = ipconfig.m_gateway; + return true; + } + else + { + if (storage) + storage->InvalidatePassphrase(m_essid); + } + + return false; +} + +//----------------------------------------------------------------------- +bool CPosixConnection::PumpNetworkEvents() +{ + bool state_changed = false; + + ConnectionState state = GetState(); + if (m_state != state) + { + m_state = state; + state_changed = true; + } + + return state_changed; +} + +bool CPosixConnection::DoConnection(const CIPConfig &ipconfig, std::string passphrase) +{ + FILE *fr = fopen("/etc/network/interfaces", "r"); + if (!fr) + return false; + + char *line = NULL; + size_t line_length = 0; + std::vector interfaces_lines; + while (getdelim(&line, &line_length, '\n', fr) > 0) + interfaces_lines.push_back(line); + fclose(fr); + + std::vector new_interfaces_lines; + std::vector ifdown_interfaces; + for (size_t i = 0; i < interfaces_lines.size(); i++) + { + //printf("CPosixConnection::SetSettings, interfaces_lines:%s", interfaces_lines[i].c_str()); + + // comments are always skipped and copied over + if (interfaces_lines[i].find("#") != std::string::npos) + { + new_interfaces_lines.push_back(interfaces_lines[i]); + continue; + } + + // always copy the auto section over + if (interfaces_lines[i].find("auto") != std::string::npos) + { + new_interfaces_lines.push_back(interfaces_lines[i]); + continue; + } + + // always copy the loopback iface section over + if (interfaces_lines[i].find("iface lo") != std::string::npos) + { + new_interfaces_lines.push_back(interfaces_lines[i]); + continue; + } + + // look for "iface inet" + if (interfaces_lines[i].find("iface") != std::string::npos) + { + // we will take all interfaces down, then bring up ours. + // so remember all iface names. This could be more robust :) + std::string ifdown_interface = interfaces_lines[i]; + std::string::size_type start = ifdown_interface.find("iface") + sizeof("iface"); + std::string::size_type end = ifdown_interface.find(" inet", start); + ifdown_interfaces.push_back(ifdown_interface.substr(start, end - start)); + + if (interfaces_lines[i].find(m_interface) == std::string::npos) + { + // this is not our interface section (ethX or wlanX). + // we always copy the iface line over. + new_interfaces_lines.push_back(interfaces_lines[i]); + for (size_t j = i + 1; j < interfaces_lines.size(); j++) + { + // if next line is an 'iface', we are done. + if (interfaces_lines[j].find("iface") != std::string::npos) + { + // back up by one so next pass in + // loop starts at correct place. + i = j - 1; + break; + } + else + { + // copy these iface details over, we do not care about them. + new_interfaces_lines.push_back(interfaces_lines[j]); + } + } + continue; + } + else + { + std::string tmp; + // is this our interface section (ethX or wlanX) + // check requested method first. + if (ipconfig.m_method == IP_CONFIG_STATIC) + { + std::string method("static"); + tmp = "iface " + m_interface + " inet " + method + "\n"; + new_interfaces_lines.push_back(tmp); + tmp = " address " + ipconfig.m_address + "\n"; + new_interfaces_lines.push_back(tmp); + tmp = " netmask " + ipconfig.m_netmask + "\n"; + new_interfaces_lines.push_back(tmp); + tmp = " gateway " + ipconfig.m_gateway + "\n"; + new_interfaces_lines.push_back(tmp); + } + else + { + std::string method("dhcp"); + if (m_type == NETWORK_CONNECTION_TYPE_WIFI) + { + // the wpa_action script will take care of + // launching udhcpc after the AP connects. + method = "manual"; + } + tmp = "iface " + m_interface + " inet " + method + "\n"; + new_interfaces_lines.push_back(tmp); + } + + // fill in the wifi details if needed + if (m_type == NETWORK_CONNECTION_TYPE_WIFI) + { + // quote the essid, spaces are legal characters + tmp = " wpa-ssid \"" + m_essid + "\"\n"; + new_interfaces_lines.push_back(tmp); + + tmp = " wpa-ap-scan 1\n"; + new_interfaces_lines.push_back(tmp); + + tmp = " wpa-scan-ssid 1\n"; + new_interfaces_lines.push_back(tmp); + + if (m_encryption == NETWORK_CONNECTION_ENCRYPTION_NONE) + { + tmp = " wpa-key-mgmt NONE\n"; + new_interfaces_lines.push_back(tmp); + } + else if (m_encryption == NETWORK_CONNECTION_ENCRYPTION_WEP) + { + tmp = " wpa-key-mgmt NONE\n"; + new_interfaces_lines.push_back(tmp); + + // if ascii, then quote it, if hex, no quotes + if (PosixGuessIsHexPassPhrase(passphrase, m_encryption)) + tmp = " wpa-wep-key0 " + passphrase + "\n"; + else + tmp = " wpa-wep-key0 \"" + passphrase + "\"\n"; + new_interfaces_lines.push_back(tmp); + tmp = " wpa-wep-tx-keyidx 0\n"; + new_interfaces_lines.push_back(tmp); + } + else if (m_encryption == NETWORK_CONNECTION_ENCRYPTION_WPA || + m_encryption == NETWORK_CONNECTION_ENCRYPTION_WPA2) + { + // if ascii, then quote it, if hex, no quotes + if (PosixGuessIsHexPassPhrase(passphrase, m_encryption)) + tmp = " wpa-psk " + passphrase + "\n"; + else + tmp = " wpa-psk \"" + passphrase + "\"\n"; + new_interfaces_lines.push_back(tmp); + if (m_encryption == NETWORK_CONNECTION_ENCRYPTION_WPA) + tmp = " wpa-proto WPA\n"; + else + tmp = " wpa-proto WPA2\n"; + new_interfaces_lines.push_back(tmp); + } + } + } + } + } + + // write out the new /etc/network/interfaces as a temp file. + // we do a rename on it later as that is atomic. + FILE* fw = fopen("/etc/network/interfaces.temp", "w"); + if (!fw) + return false; + for (size_t i = 0; i < new_interfaces_lines.size(); i++) + { + //printf("CPosixConnection::SetSettings, new_interfaces_lines:%s", new_interfaces_lines[i].c_str()); + fwrite(new_interfaces_lines[i].c_str(), new_interfaces_lines[i].size(), 1, fw); + } + fclose(fw); + + // take down all interfaces using the current /etc/network/interfaces + int rtn_error; + std::string cmd; + for (size_t i = 0; i < ifdown_interfaces.size(); i++) + { + // check if interface is actually 'up' + //if (PosixCheckInterfaceUp(ifdown_interfaces[i])) + { + cmd = "/sbin/ifdown " + ifdown_interfaces[i]; + rtn_error = system(cmd.c_str()); + // ifdown was succesful but we got 'No child processes' which is harmless + if (rtn_error != 0 && errno != ECHILD) + CLog::Log(LOGERROR, "NetworkManager: Unable to stop interface %s, %s", ifdown_interfaces[i].c_str(), strerror(errno)); + else + CLog::Log(LOGDEBUG, "NetworkManager: Stopped interface %s", ifdown_interfaces[i].c_str()); + } + } + + // Rename the file (remember, you can not rename across devices) + if (rename("/etc/network/interfaces.temp", "/etc/network/interfaces") < 0) + return false; + + // bring up this interface using the new /etc/network/interfaces + cmd = "/sbin/ifup " + m_interface; + rtn_error = system(cmd.c_str()); + // ifup was succesful but we got 'No child processes' which is harmless + if (rtn_error != 0 && errno != ECHILD) + CLog::Log(LOGERROR, "NetworkManager: Unable to start interface %s, %s", m_interface.c_str(), strerror(errno)); + else + CLog::Log(LOGDEBUG, "NetworkManager: Started interface %s", m_interface.c_str()); + + // wait for wap to connect to the AP and udhcp to fetch an IP + if (m_type == NETWORK_CONNECTION_TYPE_WIFI) + { + for (int i = 0; i < 60; ++i) + { + if (GetState() == NETWORK_CONNECTION_STATE_CONNECTED) + break; + Sleep(1000); + } + } + + return true; +} diff --git a/xbmc/network/linux/PosixConnection.h b/xbmc/network/linux/PosixConnection.h new file mode 100644 index 0000000000000..8dbd96e031b3d --- /dev/null +++ b/xbmc/network/linux/PosixConnection.h @@ -0,0 +1,78 @@ +#pragma once +/* + * Copyright (C) 2005-2010 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "xbmc/network/IConnection.h" + +int PosixParseHex(char *str, unsigned char *addr); +bool IsWireless(int socket, const char *interface); +bool PosixCheckInterfaceUp(const std::string &interface); +std::string PosixGetDefaultGateway(const std::string &interface); + +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +class CPosixConnection : public IConnection +{ +public: + CPosixConnection(bool managed, + int socket, const char *interface, const char *macaddress, + const char *essid, ConnectionType type, EncryptionType encryption, int signal); + virtual ~CPosixConnection(); + + virtual std::string GetName() const; + virtual std::string GetAddress() const; + virtual std::string GetNetmask() const; + virtual std::string GetGateway() const; + virtual std::string GetNameServer() const; + virtual std::string GetMacAddress() const; + + virtual ConnectionType GetType() const; + virtual ConnectionState GetState() const; + virtual unsigned int GetSpeed() const; + virtual IPConfigMethod GetMethod() const; + virtual unsigned int GetStrength() const; + virtual EncryptionType GetEncryption() const; + + virtual bool Connect(IPassphraseStorage *storage, const CIPConfig &ipconfig); + + bool PumpNetworkEvents(); + + void SetCanManage(bool can_manange); +private: + bool DoConnection(const CIPConfig &ipconfig, std::string passphrase); + + bool m_managed; + + std::string m_essid; + std::string m_address; + std::string m_netmask; + std::string m_gateway; + std::string m_macaddress; + + ConnectionType m_type; + ConnectionState m_state; + IPConfigMethod m_method; + EncryptionType m_encryption; + + int m_signal; + int m_socket; + std::string m_interface; +}; diff --git a/xbmc/network/linux/PosixNetworkManager.cpp b/xbmc/network/linux/PosixNetworkManager.cpp new file mode 100644 index 0000000000000..a1c2d97158ba1 --- /dev/null +++ b/xbmc/network/linux/PosixNetworkManager.cpp @@ -0,0 +1,486 @@ +/* + * Copyright (C) 2005-2010 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "PosixNetworkManager.h" +#include "PosixConnection.h" +#include "dialogs/GUIDialogKaiToast.h" +#include "guilib/Key.h" +#include "guilib/GUIWindowManager.h" +#include "guilib/LocalizeStrings.h" +#include "settings/GUISettings.h" +#include "threads/Thread.h" +#include "utils/log.h" + +#include +#include +#include +#include +#include +#include + +#if defined(TARGET_ANDROID) +#include "android/bionic_supplement/bionic_supplement.h" +#endif + +// CPosixNetworkManager and CPosixConnection rely on the debian/ubuntu method of using +// /etc/network/interfaces and pre-up/post-down scripts to handle bringing connection +// to wired/wireless networks. The pre-up/post-down scripts handle wireless/wpa though +// /etc/network/interfaces extensions "wireless-" and "wpa-". Basically, ifup/ifdown will +// tokenize these as shell vars and passes them to the pre-up/post-down scripts for handling. +// Note: This method,of course, requires root permissions. +// +// /etc/network/interfaces examples: +// auto wlan0 +// iface wlan0 inet dhcp +// wireless-essid [ESSID] +// wireless-mode [MODE] +// +// or +// auto wlan0 +// iface wlan0 inet dhcp +// wpa-ssid mynetworkname +// wpa-psk mysecretpassphrase +// +// Then, 'ifup wlan0' will bring up wlan0 with the proper wifi setup and dhdp fetch. +// +// NOTE: BusyBox will call pre-up/post-down scripts BUT it does not pass $PHASE so the +// if the script is the same for pre-up/post-down it will not be able to tell what to do. +// The simple fix is to add the following to /etc/wpa_supplicant/ifupdown.sh +// +// case $0 in +// *if-up.d*) PHASE="up";; +// *if-down.d*) PHASE="down";; +// *if-pre-up.d*) PHASE="pre-up";; +// *if-post-down.d*) PHASE="post-down";; +// esac +// +// Also you need to merge post-up -> pre-up and pre-down -> post-down as those phases +// do not exist under Busybox. +// +// +// CPosixNetworkManager and CPosixConnection work by detecting the avaliable network +// interfaces, then for wlan0, doing a wifi scan for access points using ioctl calls. +// A CPosixConnection object is created for each wired interface and each wifi access point. +// after creation, the 1st two fields are retained as the internal connection name for +// passphrase look up which is only relevent for wifi conections. +// +// Switching connections is performed by a CPosixConnection method in three steps. +// 1) use ifdown take down every interface except loopback. +// 2) if the desired connection is wifi, then +// rewrite /etc/network/interfaces, only changing "wireless-" or "wpa-" items. +// 3) use ifup to bring up the desired active connection. +// +// TODO: handle static in addition to dhcp settings. +// + +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +CPosixNetworkManager::CPosixNetworkManager() +{ + CLog::Log(LOGDEBUG, "NetworkManager: PosixNetworkManager created"); + m_socket = socket(AF_INET, SOCK_DGRAM, 0); + m_post_failed = false; + FindNetworkInterfaces(); + if (CanManageConnections()) + RestoreSavedConnection(); + else + RestoreSystemConnection(); +} + +CPosixNetworkManager::~CPosixNetworkManager() +{ + if (m_socket != -1) + close(m_socket); +} + +bool CPosixNetworkManager::CanManageConnections() +{ + //return g_advancedSettings.m_enableNetworkManager; + return true; +} + +ConnectionList CPosixNetworkManager::GetConnections() +{ + return m_connections; +} + +bool CPosixNetworkManager::PumpNetworkEvents(INetworkEventsCallback *callback) +{ + bool result = false; + + // check for a failed startup connection + if (m_post_failed) + { + // since network startup happens before windowing and rendering are up + // wait until we can retrive WINDOW_DIALOG_KAI_TOAST before posting. + CGUIDialogKaiToast *toast = (CGUIDialogKaiToast*)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST); + if (toast) + { + CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(13279), g_localizeStrings.Get(1001)); + m_post_failed = false; + } + } + + // pump our connection + for (size_t i = 0; i < m_connections.size(); i++) + { + if (((CPosixConnection*)m_connections[i].get())->PumpNetworkEvents()) + { + //some connection state changed (connected or disconnected) + if (((CPosixConnection*)m_connections[i].get())->GetState() == NETWORK_CONNECTION_STATE_CONNECTED) + { + // callback to CNetworkManager to setup the + // m_defaultConnection and update GUI state if showing. + callback->OnConnectionChange(m_connections[i]); + // callback to start services + callback->OnConnectionStateChange(NETWORK_CONNECTION_STATE_CONNECTED); + result = true; + } + } + } + + return result; +} + +//----------------------------------------------------------------------- +void CPosixNetworkManager::RestoreSavedConnection() +{ + CLog::Log(LOGDEBUG, "NetworkManager: Restoring saved connection"); + + std::string saved_name = g_guiSettings.GetString("network.essid"); + + CIPConfig saved_ipconfig; + saved_ipconfig.m_method = (IPConfigMethod)g_guiSettings.GetInt("network.method"); + saved_ipconfig.m_address = g_guiSettings.GetString("network.address"); + saved_ipconfig.m_netmask = g_guiSettings.GetString("network.netmask"); + saved_ipconfig.m_gateway = g_guiSettings.GetString("network.gateway"); + saved_ipconfig.m_nameserver = g_guiSettings.GetString("network.nameserver"); + + for (size_t i = 0; i < m_connections.size(); i++) + { + std::string connection_name = ((CPosixConnection*)m_connections[i].get())->GetName(); + if (connection_name.find(saved_name) != std::string::npos) + { + if (!((CPosixConnection*)m_connections[i].get())->Connect(NULL, saved_ipconfig)) + { + // best we can do is try an existing system connection + RestoreSystemConnection(); + } + break; + } + } +} + +void CPosixNetworkManager::RestoreSystemConnection() +{ + CLog::Log(LOGDEBUG, "NetworkManager: Defaulting to system connection"); + // nothing to do here, CNetworkManager will activate the first + // connection with a state of NETWORK_CONNECTION_STATE_CONNECTED; + + // humm, how do we check ? + // m_post_failed = true; + +} + +void CPosixNetworkManager::FindNetworkInterfaces() +{ + m_connections.clear(); + + FILE* fp = fopen("/proc/net/dev", "r"); + if (!fp) + return; + + int n, linenum = 0; + char* line = NULL; + size_t linel = 0; + char* interfaceName; + bool managed = CanManageConnections(); + + while (getdelim(&line, &linel, '\n', fp) > 0) + { + // skip first two lines + if (linenum++ < 2) + continue; + + // search where the word begins + interfaceName = line; + while (isspace(*interfaceName)) + ++interfaceName; + + // read word until : + n = strcspn(interfaceName, ": \t"); + interfaceName[n] = 0; + + // make sure the device has ethernet encapsulation + struct ifreq ifr; + memset(&ifr, 0x00, sizeof(ifr)); + strcpy(ifr.ifr_name, interfaceName); + if (ioctl(m_socket, SIOCGIFHWADDR, &ifr) >= 0) + { + if (IsWireless(m_socket, interfaceName)) + { + // get the list of access points on this interface, try this 3 times + int retryCount = 0; + while (!FindWifiConnections(interfaceName) && retryCount < 3) + retryCount++; + } + else + { + // and ignore loopback + if (ifr.ifr_hwaddr.sa_family == ARPHRD_ETHER && !(ifr.ifr_flags & IFF_LOOPBACK)) + { + char macaddress[1024] = {0}; + if (ioctl(m_socket, SIOCGIFHWADDR, &ifr) >= 0) + { + // format up 'wire.. + sprintf(macaddress, "%02X:%02X:%02X:%02X:%02X:%02X", + ifr.ifr_hwaddr.sa_data[0], ifr.ifr_hwaddr.sa_data[1], + ifr.ifr_hwaddr.sa_data[2], ifr.ifr_hwaddr.sa_data[3], + ifr.ifr_hwaddr.sa_data[4], ifr.ifr_hwaddr.sa_data[5]); + } + m_connections.push_back(CConnectionPtr(new CPosixConnection(managed, + m_socket, interfaceName, macaddress, "Wired", + NETWORK_CONNECTION_TYPE_WIRED, NETWORK_CONNECTION_ENCRYPTION_NONE, 100))); + //printf("CPosixNetworkManager::GetConnections access_point(%s) \n", access_point); + } + } + } + } + + free(line); + fclose(fp); +} + +bool CPosixNetworkManager::FindWifiConnections(const char *interfaceName) +{ + bool managed = CanManageConnections(); + // Query the wireless extentsions version number. It will help us when we + // parse the resulting events + struct iwreq iwr; + char rangebuffer[sizeof(iw_range) * 2]; /* Large enough */ + struct iw_range* range = (struct iw_range*) rangebuffer; + + memset(rangebuffer, 0x00, sizeof(rangebuffer)); + iwr.u.data.pointer = (caddr_t) rangebuffer; + iwr.u.data.length = sizeof(rangebuffer); + iwr.u.data.flags = 0; + strncpy(iwr.ifr_name, interfaceName, IFNAMSIZ); + if (ioctl(m_socket, SIOCGIWRANGE, &iwr) < 0) + { + CLog::Log(LOGWARNING, "%-8.16s Driver has no Wireless Extension version information.", + interfaceName); + return false; + } + + // Scan for wireless access points + memset(&iwr, 0x00, sizeof(iwr)); + strncpy(iwr.ifr_name, interfaceName, IFNAMSIZ); + if (ioctl(m_socket, SIOCSIWSCAN, &iwr) < 0) + { + CLog::Log(LOGWARNING, "Cannot initiate wireless scan: ioctl[SIOCSIWSCAN]: %s", strerror(errno)); + return false; + } + + // Get the results of the scanning. Three scenarios: + // 1. There's not enough room in the result buffer (E2BIG) + // 2. The scanning is not complete (EAGAIN) and we need to try again. We cap this with 15 seconds. + // 3. Were'e good. + int duration = 0; // ms + unsigned char* res_buf = NULL; + int res_buf_len = IW_SCAN_MAX_DATA; + while (duration < 15000) + { + if (!res_buf) + res_buf = (unsigned char*) malloc(res_buf_len); + + if (res_buf == NULL) + { + CLog::Log(LOGWARNING, "Cannot alloc memory for wireless scanning"); + return false; + } + + strncpy(iwr.ifr_name, interfaceName, IFNAMSIZ); + iwr.u.data.pointer = res_buf; + iwr.u.data.length = res_buf_len; + iwr.u.data.flags = 0; + int x = ioctl(m_socket, SIOCGIWSCAN, &iwr); + if (x == 0) + break; + + if (errno == E2BIG && res_buf_len < 100000) + { + free(res_buf); + res_buf = NULL; + res_buf_len *= 2; + CLog::Log(LOGDEBUG, "Scan results did not fit - trying larger buffer (%lu bytes)", + (unsigned long) res_buf_len); + } + else if (errno == EAGAIN) + { + usleep(250000); // sleep for 250ms + duration += 250; + } + else + { + CLog::Log(LOGWARNING, "Cannot get wireless scan results: ioctl[SIOCGIWSCAN]: %s", strerror(errno)); + free(res_buf); + return false; + } + } + + size_t len = iwr.u.data.length; // total length of the wireless events from the scan results + unsigned char* pos = res_buf; // pointer to the current event (about 10 per wireless network) + unsigned char* end = res_buf + len; // marks the end of the scan results + unsigned char* custom; // pointer to the event payload + struct iw_event iwe_buf, *iwe = &iwe_buf; // buffer to hold individual events + + bool first = true; + char essid[IW_ESSID_MAX_SIZE+1]; + char macaddress[256]; + int quality = 0, signalLevel = 0; + EncryptionType encryption = NETWORK_CONNECTION_ENCRYPTION_NONE; + + while (pos + IW_EV_LCP_LEN <= end) + { + // Event data may be unaligned, so make a local, aligned copy before processing. + + // copy event prefix (size of event minus IOCTL fixed payload) + memcpy(&iwe_buf, pos, IW_EV_LCP_LEN); + if (iwe->len <= IW_EV_LCP_LEN) + break; + + // if the payload is nontrivial (i.e. > 16 octets) assume it comes after a pointer + custom = pos + IW_EV_POINT_LEN; + if (range->we_version_compiled > 18 && + (iwe->cmd == SIOCGIWESSID || + iwe->cmd == SIOCGIWENCODE || + iwe->cmd == IWEVGENIE || + iwe->cmd == IWEVCUSTOM)) + { + // Wireless extentsions v19 removed the pointer from struct iw_point + char *data_pos = (char*)&iwe_buf.u.data.length; + int data_len = data_pos - (char*)&iwe_buf; + memcpy(data_pos, pos + IW_EV_LCP_LEN, sizeof(struct iw_event) - data_len); + } + else + { + memcpy(&iwe_buf, pos, sizeof(struct iw_event)); + custom += IW_EV_POINT_OFF; + } + + switch (iwe->cmd) + { + + // Get the access point MAC addresses + case SIOCGIWAP: + { + // this is the 1st cmp we get, so we have to play games + // and push back our parsed results on the next one, but + // we need to save the macaddress so we push the right one. + char cur_macaddress[256] = {0}; + // macAddress is big-endian, write in byte chunks + sprintf(cur_macaddress, "%02X:%02X:%02X:%02X:%02X:%02X", + iwe->u.ap_addr.sa_data[0], iwe->u.ap_addr.sa_data[1], + iwe->u.ap_addr.sa_data[2], iwe->u.ap_addr.sa_data[3], + iwe->u.ap_addr.sa_data[4], iwe->u.ap_addr.sa_data[5]); + + if (first) + { + first = false; + memcpy(macaddress, cur_macaddress, sizeof(macaddress)); + } + else + { + m_connections.push_back(CConnectionPtr(new CPosixConnection(managed, + m_socket, interfaceName, macaddress, essid, + NETWORK_CONNECTION_TYPE_WIFI, encryption, quality))); + //printf("CPosixNetworkManager::GetWifiConnections add access_point(%s), quality(%d), signalLevel(%d)\n", + // access_point.c_str(), quality, signalLevel); + memcpy(macaddress, cur_macaddress, sizeof(macaddress)); + } + // reset encryption for parsing next access point + encryption = NETWORK_CONNECTION_ENCRYPTION_NONE; + signalLevel = 0; + break; + } + + // Get ESSID + case SIOCGIWESSID: + { + memset(essid, 0x00, sizeof(essid)); + if ((custom) && (iwe->u.essid.length)) + memcpy(essid, custom, iwe->u.essid.length); + break; + } + + // Quality part of statistics + case IWEVQUAL: + { + quality = iwe->u.qual.qual; + signalLevel = iwe->u.qual.level; + break; + } + + // Get encoding token & mode + case SIOCGIWENCODE: + { + if (!(iwe->u.data.flags & IW_ENCODE_DISABLED) && encryption == NETWORK_CONNECTION_ENCRYPTION_NONE) + encryption = NETWORK_CONNECTION_ENCRYPTION_WEP; + break; + } + + // Generic IEEE 802.11 information element (IE) for WPA, RSN, WMM, ... + case IWEVGENIE: + { + int offset = 0; + // Loop on each IE, each IE is minimum 2 bytes + while (offset <= iwe_buf.u.data.length - 2) + { + switch (custom[offset]) + { + case 0xdd: // WPA1 + if (encryption != NETWORK_CONNECTION_ENCRYPTION_WPA2) + encryption = NETWORK_CONNECTION_ENCRYPTION_WPA; + break; + case 0x30: // WPA2 + encryption = NETWORK_CONNECTION_ENCRYPTION_WPA2; + break; + } + offset += custom[offset+1] + 2; + } + } + } + pos += iwe->len; + } + + if (!first) + { + m_connections.push_back(CConnectionPtr(new CPosixConnection(managed, + m_socket, interfaceName, macaddress, essid, + NETWORK_CONNECTION_TYPE_WIFI, encryption, quality))); + //printf("CPosixNetworkManager::GetWifiConnections add access_point(%s), quality(%d), signalLevel(%d)\n", + // access_point.c_str(), quality, signalLevel); + } + + free(res_buf); + res_buf = NULL; + return true; +} diff --git a/xbmc/network/linux/PosixNetworkManager.h b/xbmc/network/linux/PosixNetworkManager.h new file mode 100644 index 0000000000000..387adf6ea207b --- /dev/null +++ b/xbmc/network/linux/PosixNetworkManager.h @@ -0,0 +1,46 @@ +#pragma once +/* + * Copyright (C) 2005-2010 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "xbmc/network/INetworkManager.h" + +class CPosixNetworkManager : public INetworkManager +{ +public: + CPosixNetworkManager(); + virtual ~CPosixNetworkManager(); + + virtual bool CanManageConnections(); + + virtual ConnectionList GetConnections(); + + virtual bool PumpNetworkEvents(INetworkEventsCallback *callback); +private: + void RestoreSavedConnection(); + void RestoreSystemConnection(); + + void FindNetworkInterfaces(); + bool FindWifiConnections(const char *interfaceName); + + int m_socket; + ConnectionList m_connections; + bool m_post_failed; +}; diff --git a/xbmc/network/upnp/UPnP.cpp b/xbmc/network/upnp/UPnP.cpp index 03fb92d3229e2..71a0d916ae7d5 100644 --- a/xbmc/network/upnp/UPnP.cpp +++ b/xbmc/network/upnp/UPnP.cpp @@ -28,7 +28,6 @@ #include "utils/URIUtils.h" #include "Application.h" #include "ApplicationMessenger.h" -#include "network/Network.h" #include "utils/log.h" #include "Platinum.h" #include "URL.h" @@ -204,9 +203,7 @@ CUPnP::CUPnP() : m_UPnP = new PLT_UPnP(); // keep main IP around - if (g_application.getNetwork().GetFirstConnectedInterface()) { - m_IP = g_application.getNetwork().GetFirstConnectedInterface()->GetCurrentIPAddress().c_str(); - } + m_IP = g_application.getNetworkManager().GetDefaultConnectionAddress().c_str(); NPT_List list; if (NPT_SUCCEEDED(PLT_UPnPMessageHelper::GetIPAddresses(list)) && list.GetItemCount()) { m_IP = (*(list.GetFirstItem())).ToString(); diff --git a/xbmc/network/upnp/UPnPRenderer.cpp b/xbmc/network/upnp/UPnPRenderer.cpp index adde44ca2b782..3e0dc3edcea9f 100644 --- a/xbmc/network/upnp/UPnPRenderer.cpp +++ b/xbmc/network/upnp/UPnPRenderer.cpp @@ -1,4 +1,3 @@ -#include "network/Network.h" #include "UPnPRenderer.h" #include "UPnP.h" #include "UPnPInternal.h" @@ -364,10 +363,7 @@ CUPnPRenderer::GetMetadata(NPT_String& meta) thumb = CTextureCache::GetWrappedImageURL(thumb); - NPT_String ip; - if (g_application.getNetwork().GetFirstConnectedInterface()) { - ip = g_application.getNetwork().GetFirstConnectedInterface()->GetCurrentIPAddress().c_str(); - } + NPT_String ip = g_application.getNetworkManager().GetDefaultConnectionAddress().c_str(); // build url, use the internal device http server to serv the image NPT_HttpUrlQuery query; query.AddField("path", thumb.c_str()); diff --git a/xbmc/network/windows/WinConnection.cpp b/xbmc/network/windows/WinConnection.cpp new file mode 100644 index 0000000000000..c304e11746f44 --- /dev/null +++ b/xbmc/network/windows/WinConnection.cpp @@ -0,0 +1,104 @@ +#pragma once +/* + * Copyright (C) 2005-2010 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "WinConnection.h" +#include "xbmc/utils/StdString.h" + +CWinConnection::CWinConnection(IP_ADAPTER_INFO adapter) +{ + m_adapter = adapter; +} + +CWinConnection::~CWinConnection() +{ +} + +std::string CWinConnection::GetName() const +{ + return adapter.Description; +} + +std::string CWinConnection::GetAddress() const +{ + return m_adapter.IpAddressList.IpAddress.String; +} + +std::string CWinConnection::GetNetmask() const +{ + return m_adapter.IpAddressList.IpMask.String; +} + +std::string CWinConnection::GetGateway() const +{ + return m_adapter.GatewayList.IpAddress.String; +} + +std::string CPosixConnection::GetNameServer() const +{ + std::string nameserver("127.0.0.1"); + return nameserver; +} + +std::string CWinConnection::GetMacAddress() const +{ + return std::string((char*)m_adapter.Address); +} + +ConnectionType CWinConnection::GetType() const +{ + return NETWORK_CONNECTION_TYPE_WIRED; +} + +ConnectionState CWinConnection::GetState() const +{ + CStdString strIP = m_adapter.IpAddressList.IpAddress.String; + + if (strIP != "0.0.0.0") + return NETWORK_CONNECTION_STATE_CONNECTED; + else + return NETWORK_CONNECTION_STATE_DISCONNECTED; +} + +IPConfigMethod CWinConnection::GetMethod() const +{ + return IP_CONFIG_DHCP; +} + +unsigned int CWinConnection::GetStrength() const +{ + return 0; +} + +EncryptionType CWinConnection::GetEncryption() const +{ + return NETWORK_CONNECTION_ENCRYPTION_NONE; +} + +unsigned int CWinConnection::GetConnectionSpeed() const +{ + return 100; +} + +bool CWinConnection::Connect(IPassphraseStorage *storage, const CIPConfig &ipconfig) +{ + return false; +} diff --git a/xbmc/network/windows/WinConnection.h b/xbmc/network/windows/WinConnection.h new file mode 100644 index 0000000000000..013e333d33b06 --- /dev/null +++ b/xbmc/network/windows/WinConnection.h @@ -0,0 +1,51 @@ +#pragma once +/* + * Copyright (C) 2005-2010 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "system.h" +#ifdef _WIN32 +#include "xbmc/network/IConnection.h" +#include "Iphlpapi.h" + +class CWinConnection : public IConnection +{ +public: + CWinConnection(IP_ADAPTER_INFO adapter); + virtual ~CWinConnection(); + + virtual std::string GetName() const; + virtual std::string GetAddress() const; + virtual std::string GetNetmask() const; + virtual std::string GetGateway() const; + virtual std::string GetNameServer() const; + virtual std::string GetMacAddress() const; + + virtual ConnectionType GetType() const; + virtual unsigned int GetSpeed() const; + virtual ConnectionState GetState() const; + virtual IPConfigMethod GetMethod() const; + virtual unsigned int GetStrength() const; + virtual EncryptionType GetEncryption() const; + virtual bool Connect(IPassphraseStorage *storage, const CIPConfig &ipconfig); +private: + IP_ADAPTER_INFO m_adapter; +}; +#endif diff --git a/xbmc/network/windows/WinNetworkManager.cpp b/xbmc/network/windows/WinNetworkManager.cpp new file mode 100644 index 0000000000000..073f2a19f1f6a --- /dev/null +++ b/xbmc/network/windows/WinNetworkManager.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2005-2010 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "WinNetworkManager.h" +#ifdef _WIN32 +#include "WinConnection.h" + +CWinNetworkManager::CWinNetworkManager() +{ +} + +CWinNetworkManager::~CWinNetworkManager() +{ +} + +bool CWinNetworkManager::Connect() +{ + return false; +} + +bool CWinNetworkManager::CanManageConnections() +{ + return false; +} + +ConnectionList CWinNetworkManager::GetConnections() +{ + ConnectionList connections; + + PIP_ADAPTER_INFO adapterInfo; + PIP_ADAPTER_INFO adapter = NULL; + + ULONG ulOutBufLen = sizeof (IP_ADAPTER_INFO); + + adapterInfo = (IP_ADAPTER_INFO *) malloc(sizeof (IP_ADAPTER_INFO)); + if (adapterInfo == NULL) + return; + + if (GetAdaptersInfo(adapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) + { + free(adapterInfo); + adapterInfo = (IP_ADAPTER_INFO *) malloc(ulOutBufLen); + if (adapterInfo == NULL) + { + OutputDebugString("Error allocating memory needed to call GetAdaptersinfo\n"); + return; + } + } + + if ((GetAdaptersInfo(adapterInfo, &ulOutBufLen)) == NO_ERROR) + { + adapter = adapterInfo; + while (adapter) + { + connections.push_back(CConnectionPtr(new CWinConnection(*adapter))); + + adapter = adapter->Next; + } + } + + free(adapterInfo); + + return connections; +} + +bool CWinNetworkManager::PumpNetworkEvents(INetworkEventsCallback *callback) +{ + return false; +} +#endif diff --git a/xbmc/network/windows/WinNetworkManager.h b/xbmc/network/windows/WinNetworkManager.h new file mode 100644 index 0000000000000..48bd027bb47af --- /dev/null +++ b/xbmc/network/windows/WinNetworkManager.h @@ -0,0 +1,41 @@ +#pragma once +/* + * Copyright (C) 2005-2010 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "system.h" +#ifdef _WIN32 +#include "xbmc/network/INetworkManager.h" + +class CWinNetworkManager : public INetworkManager +{ +public: + CWinNetworkManager(); + virtual ~CWinNetworkManager(); + + virtual bool Connect(); + + virtual bool CanManageConnections(); + + virtual ConnectionList GetConnections(); + + virtual bool PumpNetworkEvents(INetworkEventsCallback *callback); +}; +#endif diff --git a/xbmc/security/IKeyringManager.h b/xbmc/security/IKeyringManager.h new file mode 100644 index 0000000000000..49764daf1e3c4 --- /dev/null +++ b/xbmc/security/IKeyringManager.h @@ -0,0 +1,61 @@ +#pragma once +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "utils/Variant.h" + +#define KEYRING_DEFAULT "" +#define KEYRING_SYSTEM "xbmc-system" + +class IKeyringManager +{ +public: + virtual ~IKeyringManager() { } + + /*! + \brief Find a stored secret + + \param keyring to look for secret within + \param key of secret to look for + \param secret will be filled with secret if found + \return true if found, false if not + */ + virtual bool FindSecret(const std::string &keyring, const std::string &key, CVariant &secret) = 0; + + /*! + \brief Erase a stored secret + + \param keyring to look for secret within + \param key of secret to look for + \return true if secret was erased i.e. not existant in keyring, false if failed to do so + */ + virtual bool EraseSecret(const std::string &keyring, const std::string &key) = 0; + + /*! + \brief Store a secret + + \param keyring to store secret within + \param key of secret to store + \param secret to be stored + \return true if stored, false if not + */ + virtual bool StoreSecret(const std::string &keyring, const std::string &key, const CVariant &secret) = 0; +}; diff --git a/xbmc/security/KeyringManager.cpp b/xbmc/security/KeyringManager.cpp new file mode 100644 index 0000000000000..569c561db3edb --- /dev/null +++ b/xbmc/security/KeyringManager.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "KeyringManager.h" +#include "settings/Settings.h" +#include "XMLKeyringManager.h" + +using namespace std; + +CKeyringManager::CKeyringManager() +{ + m_persistantKeyringManager = NULL; +} + +CKeyringManager::~CKeyringManager() +{ + delete m_persistantKeyringManager; +} + +void CKeyringManager::Initialize() +{ + // TODO Platform specific implementation + + if (m_persistantKeyringManager == NULL) + m_persistantKeyringManager = new CXMLKeyringManager(g_settings.GetUserDataItem("secrets.xml").c_str()); +} + +bool CKeyringManager::FindSecret(const string &keyring, const string &key, CVariant &secret) +{ + if (!m_temporaryKeyringManager.FindSecret(keyring, key, secret)) + { + if (m_persistantKeyringManager && m_persistantKeyringManager->FindSecret(keyring, key, secret)) + { + m_temporaryKeyringManager.StoreSecret(keyring, key, secret); + return true; + } + else + return false; + } + else + return true; +} + +bool CKeyringManager::EraseSecret(const string &keyring, const string &key) +{ + bool success = m_temporaryKeyringManager.EraseSecret(keyring, key); + if (m_persistantKeyringManager) + return m_persistantKeyringManager->EraseSecret(keyring, key); + else + return success; +} + +bool CKeyringManager::StoreSecret(const string &keyring, const string &key, const CVariant &secret, bool persistant) +{ + bool success = m_temporaryKeyringManager.StoreSecret(keyring, key, secret); + if (persistant && m_persistantKeyringManager) + return m_persistantKeyringManager->StoreSecret(keyring, key, secret); + else + return success; +} diff --git a/xbmc/security/KeyringManager.h b/xbmc/security/KeyringManager.h new file mode 100644 index 0000000000000..1766860713f46 --- /dev/null +++ b/xbmc/security/KeyringManager.h @@ -0,0 +1,67 @@ +#pragma once +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "IKeyringManager.h" +#include "MemoryKeyringManager.h" + +class CKeyringManager +{ +public: + CKeyringManager(); + ~CKeyringManager(); + + void Initialize(); + + /*! + \brief Find a stored secret + + \param keyring to look for secret within + \param key of secret to look for + \param secret will be filled with secret if found + \return true if found, false if not + */ + bool FindSecret(const std::string &keyring, const std::string &key, CVariant &secret); + + /*! + \brief Erase a stored secret + + \param keyring to look for secret within + \param key of secret to look for + \return true if secret was erased i.e. not existant in keyring, false if failed to do so + */ + bool EraseSecret(const std::string &keyring, const std::string &key); + + /*! + \brief Store a secret + + \param keyring to store secret within + \param key of secret to store + \param secret to be stored + \param persistant true if this secret should be stored to persistant storage + \return true if stored, false if not + */ + bool StoreSecret(const std::string &keyring, const std::string &key, const CVariant &secret, bool persistant = true); + +private: + CMemoryKeyringManager m_temporaryKeyringManager; + IKeyringManager *m_persistantKeyringManager; +}; diff --git a/xbmc/security/Makefile b/xbmc/security/Makefile new file mode 100644 index 0000000000000..137afc58caba7 --- /dev/null +++ b/xbmc/security/Makefile @@ -0,0 +1,8 @@ +SRCS = KeyringManager.cpp +SRCS+= MemoryKeyringManager.cpp +SRCS+= XMLKeyringManager.cpp + +LIB = security.a + +include ../../Makefile.include +-include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(patsubst %.S,,$(SRCS)))) diff --git a/xbmc/security/MemoryKeyringManager.cpp b/xbmc/security/MemoryKeyringManager.cpp new file mode 100644 index 0000000000000..d1732f91c6b39 --- /dev/null +++ b/xbmc/security/MemoryKeyringManager.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "MemoryKeyringManager.h" + +using namespace std; + +bool CMemoryKeyringManager::FindSecret(const string &keyring, const string &key, CVariant &secret) +{ + map::const_iterator keyring_itr = m_keyrings.find(keyring); + + if (keyring_itr != m_keyrings.end()) + { + Keyring::const_iterator itr = keyring_itr->second.find(key); + if (itr != keyring_itr->second.end()) + { + secret = itr->second; + return true; + } + } + + return false; +} + +bool CMemoryKeyringManager::EraseSecret(const string &keyring, const string &key) +{ + map::iterator keyring_itr = m_keyrings.find(keyring); + + if (keyring_itr != m_keyrings.end()) + { + Keyring::iterator itr = keyring_itr->second.find(key); + if (itr != keyring_itr->second.end()) + keyring_itr->second.erase(itr); + } + + return true; +} + +bool CMemoryKeyringManager::StoreSecret(const string &keyring, const string &key, const CVariant &secret) +{ + m_keyrings[keyring][key] = secret; + return true; +} diff --git a/xbmc/security/MemoryKeyringManager.h b/xbmc/security/MemoryKeyringManager.h new file mode 100644 index 0000000000000..f098c18cb9766 --- /dev/null +++ b/xbmc/security/MemoryKeyringManager.h @@ -0,0 +1,38 @@ +#pragma once +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "IKeyringManager.h" +#include + +class CMemoryKeyringManager : public IKeyringManager +{ +public: + virtual ~CMemoryKeyringManager() { } + + virtual bool FindSecret(const std::string &keyring, const std::string &key, CVariant &secret); + virtual bool EraseSecret(const std::string &keyring, const std::string &key); + virtual bool StoreSecret(const std::string &keyring, const std::string &key, const CVariant &secret); + +protected: + typedef std::map Keyring; + std::map m_keyrings; +}; diff --git a/xbmc/security/XMLKeyringManager.cpp b/xbmc/security/XMLKeyringManager.cpp new file mode 100644 index 0000000000000..6c50655c74fc4 --- /dev/null +++ b/xbmc/security/XMLKeyringManager.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "XMLKeyringManager.h" +#include "filesystem/File.h" +#include "utils/XMLUtils.h" +#include "utils/XMLVariantParser.h" +#include "utils/XMLVariantWriter.h" +#include "utils/log.h" + +using namespace std; + +CXMLKeyringManager::CXMLKeyringManager(const char *store) : CMemoryKeyringManager(), m_store(store) +{ + Load(); +} + +bool CXMLKeyringManager::StoreSecret(const std::string &keyring, const std::string &key, const CVariant &secret) +{ + return CMemoryKeyringManager::StoreSecret(keyring, key, secret) && Save(); +} + +bool CXMLKeyringManager::Load() +{ + if (XFILE::CFile::Exists(m_store)) + { + TiXmlDocument doc; + if (!doc.LoadFile(m_store)) + { + CLog::Log(LOGERROR, "XMLKeyringManager: Unable to load: %s, Line %d\n%s", m_store.c_str(), doc.ErrorRow(), doc.ErrorDesc()); + return false; + } + const TiXmlElement *root = doc.RootElement(); + if (root->ValueStr() != "keyrings") + { + CLog::Log(LOGERROR, "XMLKeyringManager: Failed to find root document"); + return false; + } + + const TiXmlElement *keyringNode = root->FirstChildElement("keyring"); + while (keyringNode) + { + const char *keyring = keyringNode->Attribute("name"); + const TiXmlElement *secretNode = keyringNode->FirstChildElement("secret"); + while (secretNode) + { + const char *key = secretNode->Attribute("key"); + CVariant secret; + CXMLVariantParser::Parse(secretNode->FirstChildElement("value"), secret); + + StoreSecret(keyring, key, secret); + + secretNode = secretNode->NextSiblingElement("secret"); + } + + keyringNode = keyringNode->NextSiblingElement("keyring"); + } + } + + return true; +} + +bool CXMLKeyringManager::Save() +{ + TiXmlDocument doc; + TiXmlElement rootElement("passwords"); + TiXmlNode *root = doc.InsertEndChild(TiXmlElement("keyrings")); + if (!root) + return false; + + bool success = true; + + for (map::const_iterator keyring_itr = m_keyrings.begin(); keyring_itr != m_keyrings.end() && success; keyring_itr++) + { + TiXmlElement keyring("keyring"); + keyring.SetAttribute("name", keyring_itr->first.c_str()); + + for (Keyring::const_iterator secret_itr = keyring_itr->second.begin(); secret_itr != keyring_itr->second.end() && success; secret_itr++) + { + TiXmlElement secret("secret"); + secret.SetAttribute("key", secret_itr->first.c_str()); + + success &= CXMLVariantWriter::Write(&secret, secret_itr->second); + + success &= keyring.InsertEndChild(secret) != NULL; + } + + success &= root->InsertEndChild(keyring) != NULL; + } + + if (success) + doc.SaveFile(m_store); + else + { + CLog::Log(LOGERROR, "XMLKeyringManager: Failed to generate xml for storage"); + return false; + } + + return true; +} diff --git a/xbmc/security/XMLKeyringManager.h b/xbmc/security/XMLKeyringManager.h new file mode 100644 index 0000000000000..92ae31ed01417 --- /dev/null +++ b/xbmc/security/XMLKeyringManager.h @@ -0,0 +1,40 @@ +#pragma once +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "MemoryKeyringManager.h" + +class TiXmlElement; + +class CXMLKeyringManager : public CMemoryKeyringManager +{ +public: + CXMLKeyringManager(const char *store); + virtual ~CXMLKeyringManager() { } + + virtual bool StoreSecret(const std::string &keyring, const std::string &key, const CVariant &secret); + +private: + bool Load(); + bool Save(); + + std::string m_store; +}; diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp index ede6f184671f9..3a23a5d884de1 100644 --- a/xbmc/settings/AdvancedSettings.cpp +++ b/xbmc/settings/AdvancedSettings.cpp @@ -313,6 +313,8 @@ void CAdvancedSettings::Initialize() m_guiVisualizeDirtyRegions = false; m_guiAlgorithmDirtyRegions = 3; m_guiDirtyRegionNoFlipTimeout = 0; + m_enableNetworkManager = false; + m_showNetworkPassPhrase = true; m_logEnableAirtunes = false; m_airTunesPort = 36666; m_airPlayPort = 36667; @@ -738,6 +740,10 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file) XMLUtils::GetString(pRootElement, "cddbaddress", m_cddbAddress); + //network manager + XMLUtils::GetBoolean(pRootElement, "enablenetworkmanager" , m_enableNetworkManager); + XMLUtils::GetBoolean(pRootElement, "shownetworkpassphrase", m_showNetworkPassPhrase); + //airtunes + airplay XMLUtils::GetBoolean(pRootElement, "enableairtunesdebuglog", m_logEnableAirtunes); XMLUtils::GetInt(pRootElement, "airtunesport", m_airTunesPort); diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h index d944c6aa85a50..fd6c1a4021e0c 100644 --- a/xbmc/settings/AdvancedSettings.h +++ b/xbmc/settings/AdvancedSettings.h @@ -183,6 +183,10 @@ class CAdvancedSettings int m_logLevelHint; CStdString m_cddbAddress; + // network manager + bool m_enableNetworkManager; + bool m_showNetworkPassPhrase; + //airtunes + airplay bool m_logEnableAirtunes; int m_airTunesPort; diff --git a/xbmc/settings/GUISettings.cpp b/xbmc/settings/GUISettings.cpp index b98af7c7e1453..c091dae20abe7 100644 --- a/xbmc/settings/GUISettings.cpp +++ b/xbmc/settings/GUISettings.cpp @@ -18,7 +18,6 @@ * */ -#include "network/Network.h" #include "GUISettings.h" #include #include @@ -549,36 +548,21 @@ void CGUISettings::Initialize() #endif CSettingsCategory* net = AddCategory(SETTINGS_SYSTEM, "network", 798); - if (g_application.IsStandAlone()) - { -#if !defined(TARGET_DARWIN) - AddString(NULL, "network.interface",775,"", SPIN_CONTROL_TEXT); - - map networkAssignments; - networkAssignments.insert(make_pair(716, NETWORK_DHCP)); - networkAssignments.insert(make_pair(717, NETWORK_STATIC)); - networkAssignments.insert(make_pair(787, NETWORK_DISABLED)); - AddInt(NULL, "network.assignment", 715, NETWORK_DHCP, networkAssignments, SPIN_CONTROL_TEXT); - AddString(NULL, "network.ipaddress", 719, "0.0.0.0", EDIT_CONTROL_IP_INPUT); - AddString(NULL, "network.subnet", 720, "255.255.255.0", EDIT_CONTROL_IP_INPUT); - AddString(NULL, "network.gateway", 721, "0.0.0.0", EDIT_CONTROL_IP_INPUT); - AddString(NULL, "network.dns", 722, "0.0.0.0", EDIT_CONTROL_IP_INPUT); - AddString(NULL, "network.dnssuffix", 22002, "", EDIT_CONTROL_INPUT, true); - AddString(NULL, "network.essid", 776, "0.0.0.0", BUTTON_CONTROL_STANDARD); - - map networkEncapsulations; - networkEncapsulations.insert(make_pair(780, ENC_NONE)); - networkEncapsulations.insert(make_pair(781, ENC_WEP)); - networkEncapsulations.insert(make_pair(782, ENC_WPA)); - networkEncapsulations.insert(make_pair(783, ENC_WPA2)); - AddInt(NULL, "network.enc", 778, ENC_NONE, networkEncapsulations, SPIN_CONTROL_TEXT); - AddString(NULL, "network.key", 777, "0.0.0.0", EDIT_CONTROL_INPUT); -#ifndef _WIN32 - AddString(NULL, "network.save", 779, "", BUTTON_CONTROL_STANDARD); -#endif - AddSeparator(NULL, "network.sep1"); -#endif - } + AddString(net, "network.connection", 714, "", BUTTON_CONTROL_STANDARD); + map networkMethod; + networkMethod.insert(make_pair( 716, IP_CONFIG_DHCP)); + networkMethod.insert(make_pair( 717, IP_CONFIG_STATIC)); + AddInt( net, "network.method", 715, IP_CONFIG_DHCP, networkMethod, SPIN_CONTROL_TEXT); + AddString(net, "network.address", 719, "0.0.0.0", EDIT_CONTROL_IP_INPUT); + AddString(net, "network.netmask", 720, "255.255.255.0", EDIT_CONTROL_IP_INPUT); + AddString(net, "network.gateway", 721, "0.0.0.0", EDIT_CONTROL_IP_INPUT); + AddString(net, "network.nameserver", 722, "0.0.0.0", EDIT_CONTROL_IP_INPUT); + AddString(net, "network.apply", 779, "", BUTTON_CONTROL_STANDARD); + // add hidden essid/passphrase so we can save/restore it + AddString(NULL, "network.essid", 776, "", EDIT_CONTROL_INPUT); + AddString(NULL, "network.passphrase", 777, "", EDIT_CONTROL_INPUT); + // + AddSeparator(net, "network.sep1"); AddBool(net, "network.usehttpproxy", 708, false); AddString(net, "network.httpproxyserver", 706, "", EDIT_CONTROL_INPUT); AddString(net, "network.httpproxyport", 730, "8080", EDIT_CONTROL_NUMBER_INPUT, false, 707); diff --git a/xbmc/settings/GUIWindowSettingsCategory.cpp b/xbmc/settings/GUIWindowSettingsCategory.cpp index 4ac26630489c2..5d68f5f123f77 100644 --- a/xbmc/settings/GUIWindowSettingsCategory.cpp +++ b/xbmc/settings/GUIWindowSettingsCategory.cpp @@ -53,13 +53,12 @@ #include "dialogs/GUIDialogContextMenu.h" #include "dialogs/GUIDialogYesNo.h" #include "dialogs/GUIDialogOK.h" -#include "dialogs/GUIDialogProgress.h" +#include "dialogs/GUIDialogBusy.h" #include "dialogs/GUIDialogKaiToast.h" #include "addons/Visualisation.h" #include "addons/AddonManager.h" #include "addons/AddonInstaller.h" #include "storage/MediaManager.h" -#include "network/Network.h" #include "guilib/GUIControlGroupList.h" #include "guilib/GUIWindowManager.h" #include "guilib/GUIFontManager.h" @@ -436,6 +435,14 @@ void CGUIWindowSettingsCategory::CreateSettings() continue; #endif } + else if (strSetting.Equals("network.connection")) + { + bool canManage = g_application.getNetworkManager().CanManageConnections(); + CLog::Log(LOGDEBUG, "CGUIWindowSettingsCategory::CreateSettings:network.connection canManage(%d)", canManage); + //((CGUIControl*)GetControl(GetSetting("network.connection")->GetID()))->SetVisible(visible); + if (canManage) + FillInNetworkConnection(); + } else if (strSetting.Equals("network.httpproxyport")) { AddSetting(pSetting, group->GetWidth(), iControlID); @@ -553,11 +560,6 @@ void CGUIWindowSettingsCategory::CreateSettings() FillInRegions(pSetting); continue; } - else if (strSetting.Equals("network.interface")) - { - FillInNetworkInterfaces(pSetting, group->GetWidth(), iControlID); - continue; - } else if (strSetting.Equals("audiooutput.audiodevice")) { AddSetting(pSetting, group->GetWidth(), iControlID); @@ -573,9 +575,6 @@ void CGUIWindowSettingsCategory::CreateSettings() AddSetting(pSetting, group->GetWidth(), iControlID); } - if (m_vecSections[m_iSection]->m_strCategory == "network") - NetworkInterfaceChanged(); - // update our settings (turns controls on/off as appropriate) UpdateSettings(); } @@ -823,53 +822,54 @@ void CGUIWindowSettingsCategory::UpdateSettings() } } #endif//HAS_AIRPLAY - else if (strSetting.Equals("network.ipaddress") || strSetting.Equals("network.subnet") || strSetting.Equals("network.gateway") || strSetting.Equals("network.dns")) + else if (strSetting.Equals("network.connection")) { -#ifdef _LINUX - bool enabled = (geteuid() == 0); -#else - bool enabled = false; -#endif - CGUISpinControlEx* pControl1 = (CGUISpinControlEx *)GetControl(GetSetting("network.assignment")->GetID()); - if (pControl1) - enabled = (pControl1->GetValue() == NETWORK_STATIC); + bool canManage = g_application.getNetworkManager().CanManageConnections(); + CGUIButtonControl *pControl = (CGUIButtonControl*)GetControl(GetSetting(strSetting)->GetID()); + pControl->SetEnabled(canManage); - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) pControl->SetEnabled(enabled); + CLog::Log(LOGDEBUG, "CGUIWindowSettingsCategory::UpdateSettings:network.connection canManage(%d)", canManage); + if (canManage) + { + CStdString connection_name; + connection_name = g_application.getNetworkManager().GetDefaultConnectionName(); + pControl->SetLabel2(connection_name); + FillInNetworkConnection(); + } + else + { + // Connected + pControl->SetLabel2(g_localizeStrings.Get(13296)); + } } - else if (strSetting.Equals("network.assignment")) + else if (strSetting.Equals("network.method")) { - CGUISpinControlEx* pControl1 = (CGUISpinControlEx *)GetControl(GetSetting("network.assignment")->GetID()); -#ifdef HAS_LINUX_NETWORK + bool canManage = g_application.getNetworkManager().CanManageConnections(); + CGUISpinControlEx *pControl1 = (CGUISpinControlEx*)GetControl(GetSetting("network.method")->GetID()); if (pControl1) - pControl1->SetEnabled(geteuid() == 0); -#endif + pControl1->SetEnabled(canManage); } - else if (strSetting.Equals("network.essid") || strSetting.Equals("network.enc") || strSetting.Equals("network.key")) + else if (strSetting.Equals("network.address") || + strSetting.Equals("network.netmask") || + strSetting.Equals("network.gateway") || + strSetting.Equals("network.nameserver")) { - // Get network information - CGUISpinControlEx *ifaceControl = (CGUISpinControlEx *)GetControl(GetSetting("network.interface")->GetID()); - CStdString ifaceName = ifaceControl->GetLabel(); - CNetworkInterface* iface = g_application.getNetwork().GetInterfaceByName(ifaceName); - bool bIsWireless = iface->IsWireless(); - -#ifdef HAS_LINUX_NETWORK - bool enabled = bIsWireless && (geteuid() == 0); -#else - bool enabled = bIsWireless; -#endif - CGUISpinControlEx* pControl1 = (CGUISpinControlEx *)GetControl(GetSetting("network.assignment")->GetID()); + bool enabled = false; + bool canManage = g_application.getNetworkManager().CanManageConnections(); + CGUISpinControlEx *pControl1 = (CGUISpinControlEx*)GetControl(GetSetting("network.method")->GetID()); if (pControl1) - enabled &= (pControl1->GetValue() != NETWORK_DISABLED); + enabled = (pControl1->GetValue() == IP_CONFIG_STATIC); - if (strSetting.Equals("network.key")) - { - pControl1 = (CGUISpinControlEx *)GetControl(GetSetting("network.enc")->GetID()); - if (pControl1) enabled &= (pControl1->GetValue() != ENC_NONE); - } - - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) pControl->SetEnabled(enabled); + CGUIControl *pControl = (CGUIControl*)GetControl(pSettingControl->GetID()); + if (pControl) + pControl->SetEnabled(enabled && canManage); + } + else if (strSetting.Equals("network.apply")) + { + bool canManage = g_application.getNetworkManager().CanManageConnections(); + CGUIButtonControl *pControl = (CGUIButtonControl*)GetControl(GetSetting(strSetting)->GetID()); + if (pControl) + pControl->SetEnabled(canManage); } else if (strSetting.Equals("network.httpproxyserver") || strSetting.Equals("network.httpproxyport") || strSetting.Equals("network.httpproxyusername") || strSetting.Equals("network.httpproxypassword")) @@ -877,20 +877,6 @@ void CGUIWindowSettingsCategory::UpdateSettings() CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); if (pControl) pControl->SetEnabled(g_guiSettings.GetBool("network.usehttpproxy")); } -#ifdef HAS_LINUX_NETWORK - else if (strSetting.Equals("network.key")) - { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - CGUISpinControlEx* pControl1 = (CGUISpinControlEx *)GetControl(GetSetting("network.enc")->GetID()); - if (pControl && pControl1) - pControl->SetEnabled(!pControl1->IsDisabled() && pControl1->GetValue() > 0); - } - else if (strSetting.Equals("network.save")) - { - CGUIButtonControl *pControl = (CGUIButtonControl *)GetControl(pSettingControl->GetID()); - pControl->SetEnabled(geteuid() == 0); - } -#endif else if (strSetting.Equals("scrobbler.lastfmusername") || strSetting.Equals("scrobbler.lastfmpass")) { CGUIButtonControl *pControl = (CGUIButtonControl *)GetControl(pSettingControl->GetID()); @@ -1323,19 +1309,46 @@ void CGUIWindowSettingsCategory::OnSettingChanged(BaseSettingControlPtr pSetting g_application.StopAirplayServer(true);//will stop the server before internal #endif//HAS_AIRPLAY } - else if (strSetting.Equals("network.ipaddress")) + else if (strSetting.Equals("network.connection")) { - if (g_guiSettings.GetInt("network.assignment") == NETWORK_STATIC) + CGUIDialogAccessPoints *access_points = (CGUIDialogAccessPoints*)g_windowManager.GetWindow(WINDOW_DIALOG_ACCESS_POINTS); + if (access_points) { - CStdString strDefault = g_guiSettings.GetString("network.ipaddress").Left(g_guiSettings.GetString("network.ipaddress").ReverseFind('.'))+".1"; - if (g_guiSettings.GetString("network.gateway").Equals("0.0.0.0")) - g_guiSettings.SetString("network.gateway",strDefault); - if (g_guiSettings.GetString("network.dns").Equals("0.0.0.0")) - g_guiSettings.SetString("network.dns",strDefault); - + access_points->DoModal(); + FillInNetworkConnection(); + UpdateSettings(); } } + else if (strSetting.Equals("network.apply")) + { + CGUIDialogAccessPoints *access_points = (CGUIDialogAccessPoints*)g_windowManager.GetWindow(WINDOW_DIALOG_ACCESS_POINTS); + if (access_points) + { + // fetch the connection name. + CGUIEditControl* edit_control; + edit_control = (CGUIEditControl*)GetControl(GetSetting("network.connection")->GetID()); + std::string connection_name(edit_control->GetLabel2()); + + CIPConfig ipconfig; + // fetch the current method + CGUISpinControlEx* spin_control = (CGUISpinControlEx*)GetControl(GetSetting("network.method")->GetID()); + ipconfig.m_method = (IPConfigMethod)spin_control->GetValue(); + // fetch the current ip info + edit_control = (CGUIEditControl*)GetControl(GetSetting("network.address")->GetID()); + ipconfig.m_address = edit_control->GetLabel2(); + edit_control = (CGUIEditControl*)GetControl(GetSetting("network.netmask")->GetID()); + ipconfig.m_netmask = edit_control->GetLabel2(); + edit_control = (CGUIEditControl*)GetControl(GetSetting("network.gateway")->GetID()); + ipconfig.m_gateway = edit_control->GetLabel2(); + edit_control = (CGUIEditControl*)GetControl(GetSetting("network.nameserver")->GetID()); + ipconfig.m_nameserver = edit_control->GetLabel2(); + // pass the connection config as an encoded param string + access_points->DoModal(WINDOW_DIALOG_ACCESS_POINTS, EncodeAccessPointParam(connection_name, ipconfig)); + FillInNetworkConnection(); + UpdateSettings(); + } + } else if (strSetting.Equals("network.httpproxyport")) { ValidatePortNumber(pSettingControl, "8080", "8080", false); @@ -1800,85 +1813,6 @@ void CGUIWindowSettingsCategory::OnSettingChanged(BaseSettingControlPtr pSetting // Nothing todo here } } - else if (strSetting.Equals("network.interface")) - { - NetworkInterfaceChanged(); - } -#ifdef HAS_LINUX_NETWORK - else if (strSetting.Equals("network.save")) - { - NetworkAssignment iAssignment; - CStdString sIPAddress; - CStdString sNetworkMask; - CStdString sDefaultGateway; - CStdString sWirelessNetwork; - CStdString sWirelessKey; - CStdString sDns; - EncMode iWirelessEnc; - CStdString ifaceName; - - CGUISpinControlEx *ifaceControl = (CGUISpinControlEx *)GetControl(GetSetting("network.interface")->GetID()); - ifaceName = ifaceControl->GetLabel(); - CNetworkInterface* iface = g_application.getNetwork().GetInterfaceByName(ifaceName); - - // Update controls with information - CGUISpinControlEx* pControl1 = (CGUISpinControlEx *)GetControl(GetSetting("network.assignment")->GetID()); - if (pControl1) iAssignment = (NetworkAssignment) pControl1->GetValue(); - CGUIButtonControl* pControl2 = (CGUIButtonControl *)GetControl(GetSetting("network.ipaddress")->GetID()); - if (pControl2) sIPAddress = pControl2->GetLabel2(); - pControl2 = (CGUIButtonControl *)GetControl(GetSetting("network.subnet")->GetID()); - if (pControl2) sNetworkMask = pControl2->GetLabel2(); - pControl2 = (CGUIButtonControl *)GetControl(GetSetting("network.gateway")->GetID()); - if (pControl2) sDefaultGateway = pControl2->GetLabel2(); - pControl2 = (CGUIButtonControl *)GetControl(GetSetting("network.dns")->GetID()); - if (pControl2) sDns = pControl2->GetLabel2(); - pControl1 = (CGUISpinControlEx *)GetControl(GetSetting("network.enc")->GetID()); - if (pControl1) iWirelessEnc = (EncMode) pControl1->GetValue(); - pControl2 = (CGUIButtonControl *)GetControl(GetSetting("network.essid")->GetID()); - if (pControl2) sWirelessNetwork = pControl2->GetLabel2(); - pControl2 = (CGUIButtonControl *)GetControl(GetSetting("network.key")->GetID()); - if (pControl2) sWirelessKey = pControl2->GetLabel2(); - - CGUIDialogProgress* pDlgProgress = (CGUIDialogProgress*)g_windowManager.GetWindow(WINDOW_DIALOG_PROGRESS); - pDlgProgress->SetLine(0, ""); - pDlgProgress->SetLine(1, g_localizeStrings.Get(784)); - pDlgProgress->SetLine(2, ""); - pDlgProgress->StartModal(); - pDlgProgress->Progress(); - - std::vector nameServers; - nameServers.push_back(sDns); - g_application.getNetwork().SetNameServers(nameServers); - iface->SetSettings(iAssignment, sIPAddress, sNetworkMask, sDefaultGateway, sWirelessNetwork, sWirelessKey, iWirelessEnc); - - pDlgProgress->Close(); - - if (iAssignment == NETWORK_DISABLED) - CGUIDialogOK::ShowAndGetInput(0, 788, 0, 0); - else if (iface->IsConnected()) - CGUIDialogOK::ShowAndGetInput(0, 785, 0, 0); - else - CGUIDialogOK::ShowAndGetInput(0, 786, 0, 0); - } - else if (strSetting.Equals("network.essid")) - { - CGUIDialogAccessPoints *dialog = (CGUIDialogAccessPoints *)g_windowManager.GetWindow(WINDOW_DIALOG_ACCESS_POINTS); - if (dialog) - { - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(GetSetting("network.interface")->GetID()); - dialog->SetInterfaceName(pControl->GetLabel()); - dialog->DoModal(); - - if (dialog->WasItemSelected()) - { - CGUIButtonControl* pControl2 = (CGUIButtonControl *)GetControl(GetSetting("network.essid")->GetID()); - if (pControl2) pControl2->SetLabel2(dialog->GetSelectedAccessPointEssId()); - pControl = (CGUISpinControlEx *)GetControl(GetSetting("network.enc")->GetID()); - if (pControl) pControl->SetValue(dialog->GetSelectedAccessPointEncMode()); - } - } - } -#endif #ifdef _LINUX else if (strSetting.Equals("locale.timezonecountry")) { @@ -2820,28 +2754,6 @@ void CGUIWindowSettingsCategory::FillInSortMethods(CSetting *pSetting, int windo delete state; } -void CGUIWindowSettingsCategory::FillInNetworkInterfaces(CSetting *pSetting, float groupWidth, int &iControlID) -{ - CGUISpinControlEx *pControl = (CGUISpinControlEx *)AddSetting(pSetting, groupWidth, iControlID); - pControl->Clear(); - - // query list of interfaces - vector vecInterfaces; - std::vector& ifaces = g_application.getNetwork().GetInterfaceList(); - std::vector::const_iterator iter = ifaces.begin(); - while (iter != ifaces.end()) - { - CNetworkInterface* iface = *iter; - vecInterfaces.push_back(iface->GetName()); - ++iter; - } - sort(vecInterfaces.begin(), vecInterfaces.end(), sortstringbyname()); - - int iInterface = 0; - for (unsigned int i = 0; i < vecInterfaces.size(); ++i) - pControl->AddLabel(vecInterfaces[i], iInterface++); -} - void CGUIWindowSettingsCategory::FillInEpgGuideView(CSetting *pSetting) { CSettingInt *pSettingInt = (CSettingInt*)pSetting; @@ -2934,62 +2846,35 @@ void CGUIWindowSettingsCategory::FillInAudioDevices(CSetting* pSetting, bool Pas pControl->SetValue(selectedValue); } -void CGUIWindowSettingsCategory::NetworkInterfaceChanged(void) +void CGUIWindowSettingsCategory::FillInNetworkConnection() { -#if 0 - NetworkAssignment iAssignment; - CStdString sIPAddress; - CStdString sNetworkMask; - CStdString sDefaultGateway; - CStdString sWirelessNetwork; - CStdString sWirelessKey; - EncMode iWirelessEnc; - bool bIsWireless; - CStdString ifaceName; - - // Get network information - CGUISpinControlEx *ifaceControl = (CGUISpinControlEx *)GetControl(GetSetting("network.interface")->GetID()); - ifaceName = ifaceControl->GetLabel(); - CNetworkInterface* iface = g_application.getNetwork().GetInterfaceByName(ifaceName); - iface->GetSettings(iAssignment, sIPAddress, sNetworkMask, sDefaultGateway, sWirelessNetwork, sWirelessKey, iWirelessEnc); - bIsWireless = iface->IsWireless(); - - CStdString dns; - std::vector dnss = g_application.getNetwork().GetNameServers(); - if (dnss.size() >= 1) - dns = dnss[0]; - - // Update controls with information - CGUISpinControlEx* pControl1 = (CGUISpinControlEx *)GetControl(GetSetting("network.assignment")->GetID()); - if (pControl1) pControl1->SetValue(iAssignment); - GetSetting("network.dns")->GetSetting()->FromString(dns); - if (iAssignment == NETWORK_STATIC || iAssignment == NETWORK_DISABLED) - { - GetSetting("network.ipaddress")->GetSetting()->FromString(sIPAddress); - GetSetting("network.subnet")->GetSetting()->FromString(sNetworkMask); - GetSetting("network.gateway")->GetSetting()->FromString(sDefaultGateway); - } - else - { - GetSetting("network.ipaddress")->GetSetting()->FromString(iface->GetCurrentIPAddress()); - GetSetting("network.subnet")->GetSetting()->FromString(iface->GetCurrentNetmask()); - GetSetting("network.gateway")->GetSetting()->FromString(iface->GetCurrentDefaultGateway()); - } - - pControl1 = (CGUISpinControlEx *)GetControl(GetSetting("network.enc")->GetID()); - if (pControl1) pControl1->SetValue(iWirelessEnc); - - if (bIsWireless) - { - GetSetting("network.essid")->GetSetting()->FromString(sWirelessNetwork); - GetSetting("network.key")->GetSetting()->FromString(sWirelessKey); - } - else - { - GetSetting("network.essid")->GetSetting()->FromString(""); - GetSetting("network.key")->GetSetting()->FromString(""); - } -#endif + CLog::Log(LOGDEBUG, "CGUIWindowSettingsCategory::FillInNetworkConnection1"); + if (!GetSetting("network.connection")) + return; + + CLog::Log(LOGDEBUG, "CGUIWindowSettingsCategory::FillInNetworkConnection2"); + // run the net pump to clear out any stale info, + // the water gets mighty dirty when the pump + // only runs every 500ms. + for (size_t i = 0; i < 20; i++) + g_application.getNetworkManager().PumpNetworkEvents(); + + CStdString name = g_application.getNetworkManager().GetDefaultConnectionName(); + IPConfigMethod method = g_application.getNetworkManager().GetDefaultConnectionMethod(); + CStdString address = g_application.getNetworkManager().GetDefaultConnectionAddress(); + CStdString netmask = g_application.getNetworkManager().GetDefaultConnectionNetmask(); + CStdString gateway = g_application.getNetworkManager().GetDefaultConnectionGateway(); + CStdString nameserver = g_application.getNetworkManager().GetDefaultConnectionNameServer(); + + // set method (dhcp or static) + CGUISpinControlEx* pControl1 = (CGUISpinControlEx*)GetControl(GetSetting("network.method")->GetID()); + if (pControl1) pControl1->SetValue(method); + + // set network ip information + GetSetting("network.address" )->GetSetting()->FromString(address); + GetSetting("network.netmask" )->GetSetting()->FromString(netmask); + GetSetting("network.gateway" )->GetSetting()->FromString(gateway); + GetSetting("network.nameserver")->GetSetting()->FromString(nameserver); } void CGUIWindowSettingsCategory::ValidatePortNumber(BaseSettingControlPtr pSettingControl, const CStdString& userPort, const CStdString& privPort, bool listening/*=true*/) diff --git a/xbmc/settings/GUIWindowSettingsCategory.h b/xbmc/settings/GUIWindowSettingsCategory.h index 5142c6e466ee6..2def566c9a451 100644 --- a/xbmc/settings/GUIWindowSettingsCategory.h +++ b/xbmc/settings/GUIWindowSettingsCategory.h @@ -64,8 +64,7 @@ class CGUIWindowSettingsCategory : void FillInSkinThemes(CSetting *pSetting); void FillInSkinColors(CSetting *pSetting); - void FillInNetworkInterfaces(CSetting *pSetting, float groupWidth, int &iControlID); - void NetworkInterfaceChanged(void); + void FillInNetworkConnection(); void FillInAudioDevices(CSetting* pSetting, bool Passthrough = false); diff --git a/xbmc/settings/GUIWindowSettingsProfile.cpp b/xbmc/settings/GUIWindowSettingsProfile.cpp index 9d4929b1c9a1c..afe0b9f3114e2 100644 --- a/xbmc/settings/GUIWindowSettingsProfile.cpp +++ b/xbmc/settings/GUIWindowSettingsProfile.cpp @@ -24,7 +24,6 @@ #include "Application.h" #include "dialogs/GUIDialogContextMenu.h" #include "GUIDialogProfileSettings.h" -#include "network/Network.h" #include "utils/URIUtils.h" #include "utils/Weather.h" #include "GUIPassword.h" @@ -79,7 +78,7 @@ void CGUIWindowSettingsProfile::OnPopupMenu(int iItem) g_application.StopPlaying(); CGUIMessage msg2(GUI_MSG_ITEM_SELECTED, g_windowManager.GetActiveWindow(), iCtrlID); g_windowManager.SendMessage(msg2); - g_application.getNetwork().NetworkMessage(CNetwork::SERVICES_DOWN,1); + g_application.getNetworkManager().NetworkMessage(CNetworkManager::SERVICES_DOWN,1); g_settings.LoadMasterForLogin(); CGUIWindowLoginScreen::LoadProfile(iItem); return; diff --git a/xbmc/utils/Makefile b/xbmc/utils/Makefile index d2018846d5824..b9b1bda4a8820 100644 --- a/xbmc/utils/Makefile +++ b/xbmc/utils/Makefile @@ -70,6 +70,8 @@ SRCS=AlarmClock.cpp \ Weather.cpp \ XBMCTinyXML.cpp \ XMLUtils.cpp \ + XMLVariantParser.cpp \ + XMLVariantWriter.cpp \ LIB=utils.a diff --git a/xbmc/utils/MathUtils.h b/xbmc/utils/MathUtils.h index c95171ff4d012..8c7662810c184 100644 --- a/xbmc/utils/MathUtils.h +++ b/xbmc/utils/MathUtils.h @@ -71,8 +71,8 @@ namespace MathUtils */ inline int round_int(double x) { - assert(x > static_cast(INT_MIN / 2) - 1.0); - assert(x < static_cast(INT_MAX / 2) + 1.0); +// assert(x > static_cast(INT_MIN / 2) - 1.0); +// assert(x < static_cast(INT_MAX / 2) + 1.0); const float round_to_nearest = 0.5f; int i; diff --git a/xbmc/utils/RssReader.cpp b/xbmc/utils/RssReader.cpp index 10527b7762be8..2d746155cd041 100644 --- a/xbmc/utils/RssReader.cpp +++ b/xbmc/utils/RssReader.cpp @@ -18,7 +18,6 @@ * */ -#include "network/Network.h" #include "threads/SystemClock.h" #include "RssReader.h" #include "utils/HTMLUtil.h" @@ -139,7 +138,7 @@ void CRssReader::Process() CURL url(strUrl); // we wait for the network to come up - if ((url.GetProtocol() == "http" || url.GetProtocol() == "https") && !g_application.getNetwork().IsAvailable(true)) + if ((url.GetProtocol() == "http" || url.GetProtocol() == "https") && !g_application.getNetworkManager().IsAvailable(true)) strXML = ""+g_localizeStrings.Get(15301)+""; else { diff --git a/xbmc/utils/SystemInfo.cpp b/xbmc/utils/SystemInfo.cpp index 745ad13c188cb..434cc8897b65a 100644 --- a/xbmc/utils/SystemInfo.cpp +++ b/xbmc/utils/SystemInfo.cpp @@ -28,7 +28,6 @@ #endif #include "GUIInfoManager.h" #include "filesystem/CurlFile.h" -#include "network/Network.h" #include "Application.h" #include "windowing/WindowingFactory.h" #include "settings/Settings.h" @@ -60,7 +59,6 @@ bool CSysInfoJob::DoWork() m_info.videoEncoder = GetVideoEncoder(); m_info.cpuFrequency = GetCPUFreqInfo(); m_info.kernelVersion = CSysInfo::GetKernelVersion(); - m_info.macAddress = GetMACAddress(); m_info.batteryLevel = GetBatteryLevel(); return true; } @@ -89,16 +87,6 @@ CSysData::INTERNET_STATE CSysInfoJob::GetInternetState() return CSysData::DISCONNECTED; } -CStdString CSysInfoJob::GetMACAddress() -{ -#if defined(HAS_LINUX_NETWORK) || defined(HAS_WIN32_NETWORK) - CNetworkInterface* iface = g_application.getNetwork().GetFirstConnectedInterface(); - if (iface) - return iface->GetMacAddress(); -#endif - return ""; -} - CStdString CSysInfoJob::GetVideoEncoder() { return "GPU: " + g_Windowing.GetRenderRenderer(); diff --git a/xbmc/utils/SystemInfo.h b/xbmc/utils/SystemInfo.h index 75dc609ccc7d9..9e5ec870fc0d6 100644 --- a/xbmc/utils/SystemInfo.h +++ b/xbmc/utils/SystemInfo.h @@ -69,7 +69,6 @@ class CSysInfoJob : public CJob double GetCPUFrequency(); CStdString GetSystemUpTime(bool bTotalUptime); CStdString GetCPUFreqInfo(); - CStdString GetMACAddress(); CStdString GetVideoEncoder(); CStdString GetBatteryLevel(); diff --git a/xbmc/utils/URIUtils.cpp b/xbmc/utils/URIUtils.cpp index e54c491184d21..d4fdff06c65f9 100644 --- a/xbmc/utils/URIUtils.cpp +++ b/xbmc/utils/URIUtils.cpp @@ -18,7 +18,6 @@ * */ -#include "network/Network.h" #include "URIUtils.h" #include "Application.h" #include "FileItem.h" @@ -484,6 +483,7 @@ bool URIUtils::IsOnLAN(const CStdString& strPath) address = ntohl(inet_addr(ip.c_str())); } +/* if(address != INADDR_NONE) { // check if we are on the local subnet @@ -493,6 +493,7 @@ bool URIUtils::IsOnLAN(const CStdString& strPath) if (g_application.getNetwork().HasInterfaceForIP(address)) return true; } +*/ return false; } diff --git a/xbmc/utils/Weather.cpp b/xbmc/utils/Weather.cpp index 10c1927c7b6a8..d6de0a285c6a5 100644 --- a/xbmc/utils/Weather.cpp +++ b/xbmc/utils/Weather.cpp @@ -26,7 +26,6 @@ #include "XMLUtils.h" #include "utils/POUtils.h" #include "Temperature.h" -#include "network/Network.h" #include "Application.h" #include "settings/GUISettings.h" #include "settings/Settings.h" @@ -74,7 +73,7 @@ CWeatherJob::CWeatherJob(int location) bool CWeatherJob::DoWork() { // wait for the network - if (!g_application.getNetwork().IsAvailable(true)) + if (!g_application.getNetworkManager().IsAvailable(true)) return false; AddonPtr addon; diff --git a/xbmc/utils/XMLVariantParser.cpp b/xbmc/utils/XMLVariantParser.cpp new file mode 100644 index 0000000000000..d8fc1ab741c57 --- /dev/null +++ b/xbmc/utils/XMLVariantParser.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "XMLVariantParser.h" +#include "XMLUtils.h" + +CVariant CXMLVariantParser::Parse(const TiXmlElement *valueNode) +{ + CVariant value; + Parse(valueNode, value); + return value; +} + +void CXMLVariantParser::Parse(const TiXmlElement *valueNode, CVariant &value) +{ + CStdString type = valueNode->Attribute("type"); + if (type.Equals("object")) + { + const TiXmlElement *memberNode = valueNode->FirstChildElement("value"); + while (memberNode) + { + const char *member = memberNode->Attribute("key"); + + if (member) + Parse(memberNode, value[member]); + + memberNode = memberNode->NextSiblingElement("value"); + } + } + else if (type.Equals("array")) + { + const TiXmlElement *memberNode = valueNode->FirstChildElement("value"); + while (memberNode) + { + CVariant member; + Parse(memberNode, member); + value.push_back(member); + memberNode = memberNode->NextSiblingElement("value"); + } + } + else if (type.Equals("integer")) + { + value = (int64_t)atoi(valueNode->FirstChild()->Value()); + } + else if (type.Equals("unsignedinteger")) + { + value = (uint64_t)atol(valueNode->FirstChild()->Value()); + } + else if (type.Equals("boolean")) + { + CStdString boolean = valueNode->FirstChild()->Value(); + value = boolean == "true"; + } + else if (type.Equals("string")) + { + value = valueNode->FirstChild()->Value(); + } + else if (type.Equals("double")) + { + value = (float)atof(valueNode->FirstChild()->Value()); + } +} diff --git a/xbmc/utils/XMLVariantParser.h b/xbmc/utils/XMLVariantParser.h new file mode 100644 index 0000000000000..e0c80933ad503 --- /dev/null +++ b/xbmc/utils/XMLVariantParser.h @@ -0,0 +1,32 @@ +#pragma once +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "Variant.h" + +class TiXmlElement; + +class CXMLVariantParser +{ +public: + static CVariant Parse(const TiXmlElement *valueNode); + static void Parse(const TiXmlElement *valueNode, CVariant &value); +}; diff --git a/xbmc/utils/XMLVariantWriter.cpp b/xbmc/utils/XMLVariantWriter.cpp new file mode 100644 index 0000000000000..34571580feaf2 --- /dev/null +++ b/xbmc/utils/XMLVariantWriter.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "XMLVariantWriter.h" +#include "XMLUtils.h" + +bool CXMLVariantWriter::Write(TiXmlElement *root, const CVariant &value) +{ + TiXmlElement valueNode("value"); + + if (WriteValue(&valueNode, value)) + return root->InsertEndChild(valueNode) != NULL; + else + return false; +} + +bool CXMLVariantWriter::WriteValue(TiXmlElement *valueNode, const CVariant &value) +{ + CStdString strValue; + bool success = true; + switch (value.type()) + { + case CVariant::VariantTypeInteger: + valueNode->SetAttribute("type", "integer"); + strValue.Format("%i", value.asInteger()); + success = valueNode->InsertEndChild(TiXmlText(strValue.c_str())) != NULL; + break; + case CVariant::VariantTypeUnsignedInteger: + valueNode->SetAttribute("type", "unsignedinteger"); + strValue.Format("%i", value.asUnsignedInteger()); + success = valueNode->InsertEndChild(TiXmlText(strValue.c_str())) != NULL; + break; + case CVariant::VariantTypeDouble: + valueNode->SetAttribute("type", "double"); + strValue.Format("%f", value.asFloat()); + success = valueNode->InsertEndChild(TiXmlText(strValue.c_str())) != NULL; + break; + case CVariant::VariantTypeBoolean: + valueNode->SetAttribute("type", "boolean"); + success = valueNode->InsertEndChild(TiXmlText(value.asBoolean() ? "true" : "false")) != NULL; + break; + case CVariant::VariantTypeString: + valueNode->SetAttribute("type", "string"); + success = valueNode->InsertEndChild(TiXmlText(value.asString())) != NULL; + break; + case CVariant::VariantTypeArray: + valueNode->SetAttribute("type", "array"); + for (CVariant::const_iterator_array itr = value.begin_array(); itr != value.end_array() && success; itr++) + { + TiXmlElement memberNode("value"); + if (WriteValue(&memberNode, *itr)) + success &= valueNode->InsertEndChild(memberNode) != NULL; + else + success = false; + } + + break; + case CVariant::VariantTypeObject: + valueNode->SetAttribute("type", "object"); + for (CVariant::const_iterator_map itr = value.begin_map(); itr != value.end_map() && success; itr++) + { + TiXmlElement memberNode("value"); + memberNode.SetAttribute("key", itr->first.c_str()); + if (WriteValue(&memberNode, itr->second)) + success &= valueNode->InsertEndChild(memberNode) != NULL; + else + success = false; + } + break; + case CVariant::VariantTypeConstNull: + case CVariant::VariantTypeNull: + default: + valueNode->SetAttribute("type", "null"); + break; + } + + return success; +} diff --git a/xbmc/utils/XMLVariantWriter.h b/xbmc/utils/XMLVariantWriter.h new file mode 100644 index 0000000000000..0dd66f67eaf17 --- /dev/null +++ b/xbmc/utils/XMLVariantWriter.h @@ -0,0 +1,33 @@ +#pragma once +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "Variant.h" + +class TiXmlElement; + +class CXMLVariantWriter +{ +public: + static bool Write(TiXmlElement *root, const CVariant &value); +private: + static bool WriteValue(TiXmlElement *valueNode, const CVariant &value); +}; diff --git a/xbmc/windows/GUIMediaWindow.cpp b/xbmc/windows/GUIMediaWindow.cpp index 0a37c528c0797..e020f0fa8ca7f 100644 --- a/xbmc/windows/GUIMediaWindow.cpp +++ b/xbmc/windows/GUIMediaWindow.cpp @@ -30,7 +30,6 @@ #include "GUIPassword.h" #include "Application.h" #include "ApplicationMessenger.h" -#include "network/Network.h" #include "utils/RegExp.h" #include "PartyModeManager.h" #include "dialogs/GUIDialogMediaSource.h" @@ -1150,7 +1149,7 @@ bool CGUIMediaWindow::HaveDiscOrConnection(const CStdString& strPath, int iDrive else if (iDriveType==CMediaSource::SOURCE_TYPE_REMOTE) { // TODO: Handle not connected to a remote share - if ( !g_application.getNetwork().IsConnected() ) + if ( !g_application.getNetworkManager().IsConnected() ) { CGUIDialogOK::ShowAndGetInput(220, 221, 0, 0); return false; @@ -1646,7 +1645,7 @@ const CFileItemList& CGUIMediaWindow::CurrentDirectory() const bool CGUIMediaWindow::WaitForNetwork() const { - if (g_application.getNetwork().IsAvailable()) + if (g_application.getNetworkManager().IsAvailable()) return true; CGUIDialogProgress *progress = (CGUIDialogProgress *)g_windowManager.GetWindow(WINDOW_DIALOG_PROGRESS); @@ -1658,7 +1657,7 @@ bool CGUIMediaWindow::WaitForNetwork() const progress->SetLine(1, url.GetWithoutUserDetails()); progress->ShowProgressBar(false); progress->StartModal(); - while (!g_application.getNetwork().IsAvailable()) + while (!g_application.getNetworkManager().IsAvailable()) { progress->Progress(); if (progress->IsCanceled()) diff --git a/xbmc/windows/GUIWindowFileManager.cpp b/xbmc/windows/GUIWindowFileManager.cpp index 1e237891514a0..44865ba312e56 100644 --- a/xbmc/windows/GUIWindowFileManager.cpp +++ b/xbmc/windows/GUIWindowFileManager.cpp @@ -35,7 +35,6 @@ #endif #include "pictures/GUIWindowSlideShow.h" #include "playlists/PlayListFactory.h" -#include "network/Network.h" #include "guilib/GUIWindowManager.h" #include "dialogs/GUIDialogOK.h" #include "dialogs/GUIDialogYesNo.h" @@ -675,7 +674,7 @@ bool CGUIWindowFileManager::HaveDiscOrConnection( CStdString& strPath, int iDriv else if ( iDriveType == CMediaSource::SOURCE_TYPE_REMOTE ) { // TODO: Handle not connected to a remote share - if ( !g_application.getNetwork().IsConnected() ) + if ( !g_application.getNetworkManager().IsConnected() ) { CGUIDialogOK::ShowAndGetInput(220, 221, 0, 0); return false; diff --git a/xbmc/windows/GUIWindowLoginScreen.cpp b/xbmc/windows/GUIWindowLoginScreen.cpp index 494324ffbb5f0..57bff7c3e3004 100644 --- a/xbmc/windows/GUIWindowLoginScreen.cpp +++ b/xbmc/windows/GUIWindowLoginScreen.cpp @@ -34,7 +34,6 @@ #endif #include "interfaces/Builtins.h" #include "utils/Weather.h" -#include "network/Network.h" #include "addons/Skin.h" #include "settings/Profile.h" #include "guilib/GUIMessage.h" @@ -279,7 +278,7 @@ void CGUIWindowLoginScreen::LoadProfile(unsigned int profile) if (profile != 0 || !g_settings.IsMasterUser()) { - g_application.getNetwork().NetworkMessage(CNetwork::SERVICES_DOWN,1); + g_application.getNetworkManager().NetworkMessage(CNetworkManager::SERVICES_DOWN,1); g_settings.LoadProfile(profile); } else @@ -288,7 +287,8 @@ void CGUIWindowLoginScreen::LoadProfile(unsigned int profile) if (pWindow) pWindow->ResetControlStates(); } - g_application.getNetwork().NetworkMessage(CNetwork::SERVICES_UP,1); + + g_application.getNetworkManager().StartServices(); g_settings.UpdateCurrentProfileDate(); g_settings.SaveProfiles(PROFILES_FILE); From 7174ed05d77c7ea4877452e417d1ca3b8621eb7d Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 18 Sep 2012 21:10:32 -0400 Subject: [PATCH 019/180] [aml] rename non-member var --- xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.cpp b/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.cpp index b7a00612696ba..07de6abc7cf7f 100644 --- a/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.cpp +++ b/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.cpp @@ -221,9 +221,9 @@ void CPeripheralBusUSB::Clear(void) bool CPeripheralBusUSB::WaitForUpdate() { - int m_udevFd = udev_monitor_get_fd(m_udevMon); + int udevFd = udev_monitor_get_fd(m_udevMon); - if (m_udevFd < 0) + if (udevFd < 0) { CLog::Log(LOGERROR, "%s - get udev monitor", __FUNCTION__); return false; @@ -231,7 +231,7 @@ bool CPeripheralBusUSB::WaitForUpdate() /* poll for udev changes */ struct pollfd pollFd; - pollFd.fd = m_udevFd; + pollFd.fd = udevFd; pollFd.events = POLLIN; int iPollResult; while (!m_bStop && ((iPollResult = poll(&pollFd, 1, 100)) <= 0)) From 00b29ede166bf087d189363a6c8449011ec43939 Mon Sep 17 00:00:00 2001 From: davilla Date: Sat, 18 Aug 2012 11:19:49 -0400 Subject: [PATCH 020/180] [aml] fixed seeing usb keyboard/mouse devices that are inserted/removed after boot --- .../bus/linux/PeripheralBusUSBLibUdev.cpp | 33 ++++++++++++++++++- .../bus/linux/PeripheralBusUSBLibUdev.h | 1 + 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.cpp b/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.cpp index 07de6abc7cf7f..d25a4b01b0116 100644 --- a/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.cpp +++ b/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.cpp @@ -20,6 +20,11 @@ #include "PeripheralBusUSBLibUdev.h" #include "peripherals/Peripherals.h" + +#if defined(HAS_LINUX_EVENTS) +#include "windowing/WinEventsLinux.h" +#endif + extern "C" { #include } @@ -107,6 +112,7 @@ CPeripheralBusUSB::~CPeripheralBusUSB(void) bool CPeripheralBusUSB::PerformDeviceScan(PeripheralScanResults &results) { + bool rtn = false; struct udev_enumerate *enumerate; struct udev_list_entry *devices, *dev_list_entry; struct udev_device *dev(NULL), *parent(NULL); @@ -173,7 +179,32 @@ bool CPeripheralBusUSB::PerformDeviceScan(PeripheralScanResults &results) /* Free the enumerator object */ udev_enumerate_unref(enumerate); - return true; + // quick check if number of entries changed. + if (m_results.m_results.size() != results.m_results.size()) + { + m_results = results; + rtn = true; + } + else + { + // number of entried are the same, so we have to compare each one. + for (unsigned int iDevicePtr = 0; iDevicePtr < m_results.m_results.size(); iDevicePtr++) + { + if (!results.ContainsResult(m_results.m_results.at(iDevicePtr))) + { + // if anything changes, we flag a new PeripheralScanResults + m_results = results; + rtn = true; + break; + } + } + } +#if defined(HAS_LINUX_EVENTS) + if (rtn) + CWinEvents::RefreshDevices(); +#endif + + return rtn; } const PeripheralType CPeripheralBusUSB::GetType(int iDeviceClass) diff --git a/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.h b/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.h index b93cebee5402d..e5c43de050d7c 100644 --- a/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.h +++ b/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.h @@ -50,5 +50,6 @@ namespace PERIPHERALS struct udev * m_udev; struct udev_monitor *m_udevMon; + PeripheralScanResults m_results; }; } From 8c3c735fa7a98fb76a62455532db9053759faa94 Mon Sep 17 00:00:00 2001 From: davilla Date: Fri, 20 Apr 2012 13:23:19 -0400 Subject: [PATCH 021/180] [aml] fixed, add UDevProvider to handle usb disk add/remove storage handling --- xbmc/storage/linux/LinuxStorageProvider.h | 5 + xbmc/storage/linux/Makefile | 9 +- xbmc/storage/linux/UDevProvider.cpp | 241 ++++++++++++++++++++++ xbmc/storage/linux/UDevProvider.h | 55 +++++ 4 files changed, 306 insertions(+), 4 deletions(-) create mode 100644 xbmc/storage/linux/UDevProvider.cpp create mode 100644 xbmc/storage/linux/UDevProvider.h diff --git a/xbmc/storage/linux/LinuxStorageProvider.h b/xbmc/storage/linux/LinuxStorageProvider.h index 1f145486b8eb0..740b2829940ac 100644 --- a/xbmc/storage/linux/LinuxStorageProvider.h +++ b/xbmc/storage/linux/LinuxStorageProvider.h @@ -21,6 +21,7 @@ #include "storage/IStorageProvider.h" #include "HALProvider.h" #include "DeviceKitDisksProvider.h" +#include "UDevProvider.h" #include "UDisksProvider.h" #include "PosixMountProvider.h" @@ -41,6 +42,10 @@ class CLinuxStorageProvider : public IStorageProvider if (m_instance == NULL) m_instance = new CHALProvider(); #endif +#ifdef HAVE_LIBUDEV + if (m_instance == NULL) + m_instance = new CUDevProvider(); +#endif if (m_instance == NULL) m_instance = new CPosixMountProvider(); diff --git a/xbmc/storage/linux/Makefile b/xbmc/storage/linux/Makefile index 9be601de0ad97..325f84d8e2c92 100644 --- a/xbmc/storage/linux/Makefile +++ b/xbmc/storage/linux/Makefile @@ -1,8 +1,9 @@ -SRCS=DeviceKitDisksProvider.cpp \ - HALProvider.cpp \ - UDisksProvider.cpp \ +SRCS = DeviceKitDisksProvider.cpp +SRCS += UDisksProvider.cpp +SRCS += HALProvider.cpp +SRCS += UDevProvider.cpp -LIB=storage_linux.a +LIB = storage_linux.a include ../../../Makefile.include -include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS))) diff --git a/xbmc/storage/linux/UDevProvider.cpp b/xbmc/storage/linux/UDevProvider.cpp new file mode 100644 index 0000000000000..21b6b506e122e --- /dev/null +++ b/xbmc/storage/linux/UDevProvider.cpp @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2005-2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "UDevProvider.h" + +#ifdef HAVE_LIBUDEV + +#include "linux/PosixMountProvider.h" +#include "utils/log.h" +#include "utils/URIUtils.h" + +extern "C" { +#include +#include +} + +static const char *get_mountpoint(const char *devnode) +{ + static char buf[4096]; + const char *delim = " "; + const char *mountpoint = NULL; + FILE *fp = fopen("/proc/mounts", "r"); + + while (fgets(buf, sizeof (buf), fp)) + { + const char *node = strtok(buf, delim); + if (strcmp(node, devnode) == 0) + { + mountpoint = strtok(NULL, delim); + break; + } + } + + if (mountpoint != NULL) + { + // If mount point contain characters like space, it is converted to + // "\040". This situation should be handled. + char *c1, *c2; + for (c1 = c2 = (char*)mountpoint; *c2; ++c1) + { + if (*c2 == '\\') + { + *c1 = (((c2[1] - '0') << 6) | ((c2[2] - '0') << 3) | (c2[3] - '0')); + c2 += 4; + continue; + } + if (c1 != c2) + *c1 = *c2; + ++c2; + } + *c1 = *c2; + } + + fclose(fp); + return mountpoint; +} + +CUDevProvider::CUDevProvider() +{ + m_udev = NULL; + m_udevMon = NULL; +} + +void CUDevProvider::Initialize() +{ + CLog::Log(LOGDEBUG, "Selected UDev as storage provider"); + + m_udev = udev_new(); + if (!m_udev) + { + CLog::Log(LOGERROR, "%s - failed to allocate udev context", __FUNCTION__); + return; + } + /* set up a devices monitor that listen for any device change */ + m_udevMon = udev_monitor_new_from_netlink(m_udev, "udev"); + udev_monitor_filter_add_match_subsystem_devtype(m_udevMon, "block", "disk"); + udev_monitor_filter_add_match_subsystem_devtype(m_udevMon, "block", "partition"); + udev_monitor_enable_receiving(m_udevMon); + + PumpDriveChangeEvents(NULL); +} + +void CUDevProvider::Stop() +{ + udev_monitor_unref(m_udevMon); + udev_unref(m_udev); +} + +void CUDevProvider::GetDisks(VECSOURCES& disks, bool removable) +{ + // enumerate existing block devices + struct udev_enumerate *u_enum = udev_enumerate_new(m_udev); + if (u_enum == NULL) + { + fprintf(stderr, "Error: udev_enumerate_new(udev)\n"); + return; + } + + udev_enumerate_add_match_subsystem(u_enum, "block"); + udev_enumerate_add_match_property(u_enum, "DEVTYPE", "disk"); + udev_enumerate_add_match_property(u_enum, "DEVTYPE", "partition"); + udev_enumerate_scan_devices(u_enum); + + struct udev_list_entry *u_list_ent; + struct udev_list_entry *u_first_list_ent; + u_first_list_ent = udev_enumerate_get_list_entry(u_enum); + udev_list_entry_foreach(u_list_ent, u_first_list_ent) + { + const char *name = udev_list_entry_get_name(u_list_ent); + struct udev *context = udev_enumerate_get_udev(u_enum); + struct udev_device *device = udev_device_new_from_syspath(context, name); + if (device == NULL) + continue; + + // filter out devices that are not mounted + const char *mountpoint = get_mountpoint(udev_device_get_devnode(device)); + if (!mountpoint) + { + udev_device_unref(device); + continue; + } + + // filter out things mounted on /tmp + if (strstr(mountpoint, "/tmp")) + { + udev_device_unref(device); + continue; + } + + // look for usb devices on the usb bus or mounted on /media/usbX (sdcards) + const char *bus = udev_device_get_property_value(device, "ID_BUS"); + if (removable && + ((bus && strstr(bus, "usb")) || + (mountpoint && strstr(mountpoint, "usb")))) + { + const char *label = udev_device_get_property_value(device, "ID_FS_LABEL"); + if (!label) + label = URIUtils::GetFileName(mountpoint); + + CMediaSource share; + share.strName = label; + share.strPath = mountpoint; + share.m_ignore = true; + share.m_iDriveType = CMediaSource::SOURCE_TYPE_REMOVABLE; + AddOrReplace(disks, share); + } + udev_device_unref(device); + } + udev_enumerate_unref(u_enum); +} + +void CUDevProvider::GetLocalDrives(VECSOURCES &localDrives) +{ + GetDisks(localDrives, false); +} + +void CUDevProvider::GetRemovableDrives(VECSOURCES &removableDrives) +{ + GetDisks(removableDrives, true); +} + +bool CUDevProvider::Eject(CStdString mountpath) +{ + return false; +} + +std::vector CUDevProvider::GetDiskUsage() +{ + CPosixMountProvider legacy; + return legacy.GetDiskUsage(); +} + +bool CUDevProvider::PumpDriveChangeEvents(IStorageEventsCallback *callback) +{ + bool changed = false; + + fd_set readfds; + FD_ZERO(&readfds); + FD_SET(udev_monitor_get_fd(m_udevMon), &readfds); + + // non-blocking, check the file descriptor for received data + struct timeval tv = {0}; + int count = select(udev_monitor_get_fd(m_udevMon) + 1, &readfds, NULL, NULL, &tv); + if (count < 0) + return false; + + if (FD_ISSET(udev_monitor_get_fd(m_udevMon), &readfds)) + { + struct udev_device *dev = udev_monitor_receive_device(m_udevMon); + if (!dev) + return false; + + const char *action = udev_device_get_action(dev); + const char *devtype = udev_device_get_devtype(dev); + if (action) + { + const char *label = udev_device_get_property_value(dev, "ID_FS_LABEL"); + const char *mountpoint = get_mountpoint(udev_device_get_devnode(dev)); + if (!label) + label = URIUtils::GetFileName(mountpoint); + + if (!strcmp(action, "add") && !strcmp(devtype, "partition")) + { + CLog::Log(LOGNOTICE, "UDev: Added %s", mountpoint); + if (callback) + callback->OnStorageAdded(label, mountpoint); + changed = true; + } + if (!strcmp(action, "remove") && !strcmp(devtype, "partition")) + { + CLog::Log(LOGNOTICE, "UDev: Removed %s", mountpoint); + if (callback) + callback->OnStorageSafelyRemoved(label); + changed = true; + } + } + udev_device_unref(dev); + } + + return changed; +} + +#endif diff --git a/xbmc/storage/linux/UDevProvider.h b/xbmc/storage/linux/UDevProvider.h new file mode 100644 index 0000000000000..6b51e2a6056bf --- /dev/null +++ b/xbmc/storage/linux/UDevProvider.h @@ -0,0 +1,55 @@ +#pragma once +/* + * Copyright (C) 2005-2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "storage/IStorageProvider.h" + +#ifdef HAVE_LIBUDEV + +struct udev; +struct udev_monitor; + +class CUDevProvider : public IStorageProvider +{ +public: + CUDevProvider(); + virtual ~CUDevProvider() { } + + virtual void Initialize(); + virtual void Stop(); + + virtual void GetLocalDrives(VECSOURCES &localDrives); + virtual void GetRemovableDrives(VECSOURCES &removableDrives); + + virtual bool Eject(CStdString mountpath); + + virtual std::vector GetDiskUsage(); + + virtual bool PumpDriveChangeEvents(IStorageEventsCallback *callback); + +private: + void GetDisks(VECSOURCES& devices, bool removable); + + struct udev *m_udev; + struct udev_monitor *m_udevMon; +}; + +#endif From 02b029ce8ccb55bc011b3fdad5077dffbab1f96d Mon Sep 17 00:00:00 2001 From: davilla Date: Fri, 20 Apr 2012 13:22:17 -0400 Subject: [PATCH 022/180] [aml] fixed, add exfat to accepted partition types --- xbmc/linux/PosixMountProvider.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/xbmc/linux/PosixMountProvider.cpp b/xbmc/linux/PosixMountProvider.cpp index c91a76e403a7a..2420491534a3b 100644 --- a/xbmc/linux/PosixMountProvider.cpp +++ b/xbmc/linux/PosixMountProvider.cpp @@ -65,6 +65,7 @@ void CPosixMountProvider::GetDrives(VECSOURCES &drives) || strcmp(fs, "ext2") == 0 || strcmp(fs, "ext3") == 0 || strcmp(fs, "reiserfs") == 0 || strcmp(fs, "xfs") == 0 || strcmp(fs, "ntfs-3g") == 0 || strcmp(fs, "iso9660") == 0 + || strcmp(fs, "exfat") == 0 || strcmp(fs, "fusefs") == 0 || strcmp(fs, "hfs") == 0) accepted = true; From 8a04a1536e188724c7ab4dcc6bdd490ac7a692e7 Mon Sep 17 00:00:00 2001 From: davilla Date: Thu, 29 Mar 2012 11:19:53 -0400 Subject: [PATCH 023/180] [aml] changed to handle ALT keys --- xbmc/windowing/WinEventsLinux.cpp | 67 ++++++++++++++++++++++++++++++- xbmc/windowing/WinEventsLinux.h | 11 +++-- 2 files changed, 71 insertions(+), 7 deletions(-) diff --git a/xbmc/windowing/WinEventsLinux.cpp b/xbmc/windowing/WinEventsLinux.cpp index e49ef3a46ffd8..5f166c4a43da1 100644 --- a/xbmc/windowing/WinEventsLinux.cpp +++ b/xbmc/windowing/WinEventsLinux.cpp @@ -34,6 +34,8 @@ PHANDLE_EVENT_FUNC CWinEventsBase::m_pEventFunc = NULL; bool CWinEventsLinux::m_initialized = false; CLinuxInputDevices CWinEventsLinux::m_devices; +std::map CWinEventsLinux::m_altMap; +std::map CWinEventsLinux::m_keyPadMap; CWinEventsLinux::CWinEventsLinux() { @@ -52,9 +54,41 @@ bool CWinEventsLinux::IsRemoteLowBattery() bool CWinEventsLinux::MessagePump() { + static int number; + static bool accumlate; + if (!m_initialized) { m_devices.InitAvailable(); + + // Mapping of ALT-XXX of codepage 437 to unicode + m_altMap[130] = 0x00E9; + m_altMap[225] = 0x00DF; + m_altMap[135] = 0x00E7; + m_altMap[138] = 0x00E8; + m_altMap[149] = 0x00F2; + m_altMap[133] = 0x00E0; + m_altMap[151] = 0x00F9; + m_altMap[129] = 0x00FC; + m_altMap[134] = 0x00E5; + m_altMap[148] = 0x00F6; + m_altMap[162] = 0x00F3; + m_altMap[164] = 0x00F1; + m_altMap[145] = 0x00E6; + m_altMap[132] = 0x00E4; + + // Mapping of keypad scancodes to their numeric values + m_keyPadMap[82] = 0; + m_keyPadMap[79] = 1; + m_keyPadMap[80] = 2; + m_keyPadMap[81] = 3; + m_keyPadMap[75] = 4; + m_keyPadMap[76] = 5; + m_keyPadMap[77] = 6; + m_keyPadMap[71] = 7; + m_keyPadMap[72] = 8; + m_keyPadMap[73] = 9; + m_initialized = true; } @@ -63,7 +97,38 @@ bool CWinEventsLinux::MessagePump() while (1) { event = m_devices.ReadEvent(); - if (event.type != XBMC_NOEVENT) + + // Wait for first left ALT press, then capture numbers pressed, then wait for left ALT release. + // Translate the number into a unicode value. This is to support latin characters. + if (event.key.keysym.sym == XBMCK_LALT && event.type == XBMC_KEYDOWN) + { + accumlate = true; + number = 0; + } + + if (accumlate && (event.type == XBMC_KEYDOWN)) + { + int keyPad = m_keyPadMap.at(event.key.keysym.scancode); + number = number * 10 + keyPad; + } + + if (accumlate && event.key.keysym.sym == XBMCK_LALT && event.type == XBMC_KEYUP) + { + accumlate = false; + event.type = XBMC_KEYDOWN; + event.key.keysym.sym = XBMCK_UNKNOWN;; + + if (m_altMap.find(number) != m_altMap.end()) + { + event.key.keysym.unicode = m_altMap[number]; + } + else + { + event.key.keysym.unicode = number; + } + } + + if ((event.type != XBMC_NOEVENT) && !accumlate) { ret |= g_application.OnEvent(event); } diff --git a/xbmc/windowing/WinEventsLinux.h b/xbmc/windowing/WinEventsLinux.h index f99ae4b09482e..eb71956b92f5f 100644 --- a/xbmc/windowing/WinEventsLinux.h +++ b/xbmc/windowing/WinEventsLinux.h @@ -1,3 +1,4 @@ +#pragma once /* * Copyright (C) 2005-2012 Team XBMC * http://www.xbmc.org @@ -18,13 +19,11 @@ * */ -#ifndef WINDOW_EVENTS_LINUX_H -#define WINDOW_EVENTS_LINUX_H - -#pragma once #include "windowing/WinEvents.h" #include "input/linux/LinuxInputDevices.h" +#include + class CWinEventsLinux : public CWinEventsBase { public: @@ -36,6 +35,6 @@ class CWinEventsLinux : public CWinEventsBase private: static bool m_initialized; static CLinuxInputDevices m_devices; + static std::map m_altMap; + static std::map m_keyPadMap; }; - -#endif From 1987bb3315a3ba358ba48b8d4ab9a2a234d7462b Mon Sep 17 00:00:00 2001 From: davilla Date: Mon, 24 Sep 2012 12:25:57 -0400 Subject: [PATCH 024/180] [aml] check and fail if trying to open .ifo (dvds) --- xbmc/cores/amlplayer/AMLPlayer.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/xbmc/cores/amlplayer/AMLPlayer.cpp b/xbmc/cores/amlplayer/AMLPlayer.cpp index ebf8f1c75f515..de800c89c8235 100644 --- a/xbmc/cores/amlplayer/AMLPlayer.cpp +++ b/xbmc/cores/amlplayer/AMLPlayer.cpp @@ -573,6 +573,9 @@ bool CAMLPlayer::OpenFile(const CFileItem &file, const CPlayerOptions &options) ClearStreamInfos(); + if (m_item.IsDVDFile() || m_item.IsDVD()) + return false; + // setup to spin the busy dialog until we are playing m_ready.Reset(); @@ -1576,7 +1579,7 @@ void CAMLPlayer::Process() case PLAYER_EXIT: if (m_log_level > 5) { - CLog::Log(LOGDEBUG, "CAMLPlayer::Process PLAYER_STOPED"); + CLog::Log(LOGDEBUG, "CAMLPlayer::Process PLAYER_STOPPED"); CLog::Log(LOGDEBUG, "CAMLPlayer::Process: %s", m_dll->player_status2str(pstatus)); } stopPlaying = true; From c58ccd972627fd7591dea6a8c5192be259d0bacc Mon Sep 17 00:00:00 2001 From: davilla Date: Mon, 24 Sep 2012 12:26:42 -0400 Subject: [PATCH 025/180] [aml] amlplayer does not support dvds --- xbmc/cores/amlplayer/amlplayer_advancedsettings.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/xbmc/cores/amlplayer/amlplayer_advancedsettings.xml b/xbmc/cores/amlplayer/amlplayer_advancedsettings.xml index 7199cd47b68fc..310ff9589147d 100644 --- a/xbmc/cores/amlplayer/amlplayer_advancedsettings.xml +++ b/xbmc/cores/amlplayer/amlplayer_advancedsettings.xml @@ -1,6 +1,5 @@ From 26c3c32a715273ba53b0e5295f8d27cb32b65d6e Mon Sep 17 00:00:00 2001 From: davilla Date: Mon, 24 Sep 2012 12:27:45 -0400 Subject: [PATCH 026/180] [aml] remove hdhomerun so other players can get it, add ifo so only dvdplayer gets it --- system/playercorefactory.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/playercorefactory.xml b/system/playercorefactory.xml index 76027b6315ed1..3fdb283d0ea92 100644 --- a/system/playercorefactory.xml +++ b/system/playercorefactory.xml @@ -11,7 +11,7 @@ - + @@ -25,6 +25,7 @@ + From 9f9946ab4c51628f46fd26a675495b50d0598f06 Mon Sep 17 00:00:00 2001 From: davilla Date: Mon, 24 Sep 2012 12:29:25 -0400 Subject: [PATCH 027/180] [aml] add libdvdread hack to force ignore of /root (aml specific) --- lib/libdvd/libdvdread/src/dvd_reader.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/libdvd/libdvdread/src/dvd_reader.c b/lib/libdvd/libdvdread/src/dvd_reader.c index 8849e848e3725..5ea16c4f73ddc 100644 --- a/lib/libdvd/libdvdread/src/dvd_reader.c +++ b/lib/libdvd/libdvdread/src/dvd_reader.c @@ -248,6 +248,7 @@ static dvd_reader_t *DVDOpenImageFile( const char *location, int have_css ) dvdinput_close(dev); return NULL; } + memset( dvd, 0, sizeof( dvd_reader_t ) ); dvd->isImageFile = 1; dvd->dev = dev; dvd->path_root = NULL; @@ -495,6 +496,8 @@ dvd_reader_t *DVDOpen( const char *ppath ) fclose( mntfile ); } #elif defined(__linux__) + /* amlogic/linux hack, tries to use /root as a device, wtf? */ + if (strcmp("/root", path_copy )) { mntfile = fopen( _PATH_MOUNTED, "r" ); if( mntfile ) { struct mntent *me; @@ -513,6 +516,7 @@ dvd_reader_t *DVDOpen( const char *ppath ) } fclose( mntfile ); } + } #elif defined(_MSC_VER) auth_drive = DVDOpenImageFile( path, have_css ); #endif From d39a41a92f3bb47159c404f49b5302865e5f2823 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 3 Oct 2012 16:33:47 -0400 Subject: [PATCH 028/180] [aml] respect the network manager as.xml setting --- xbmc/network/linux/PosixNetworkManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xbmc/network/linux/PosixNetworkManager.cpp b/xbmc/network/linux/PosixNetworkManager.cpp index a1c2d97158ba1..26674d8c0a0e2 100644 --- a/xbmc/network/linux/PosixNetworkManager.cpp +++ b/xbmc/network/linux/PosixNetworkManager.cpp @@ -28,6 +28,7 @@ #include "settings/GUISettings.h" #include "threads/Thread.h" #include "utils/log.h" +#include "settings/AdvancedSettings.h" #include #include @@ -113,8 +114,7 @@ CPosixNetworkManager::~CPosixNetworkManager() bool CPosixNetworkManager::CanManageConnections() { - //return g_advancedSettings.m_enableNetworkManager; - return true; + return g_advancedSettings.m_enableNetworkManager; } ConnectionList CPosixNetworkManager::GetConnections() From 6207b61f5110fa3a5dac7eb9da4763bc636461a2 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 3 Oct 2012 17:45:34 -0400 Subject: [PATCH 029/180] [aml/droid] fix crash loading amlplayer --- xbmc/cores/amlplayer/AMLPlayer.cpp | 2 ++ xbmc/cores/amlplayer/DllLibamplayer.h | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/xbmc/cores/amlplayer/AMLPlayer.cpp b/xbmc/cores/amlplayer/AMLPlayer.cpp index de800c89c8235..b7cc2f34f81c5 100644 --- a/xbmc/cores/amlplayer/AMLPlayer.cpp +++ b/xbmc/cores/amlplayer/AMLPlayer.cpp @@ -887,6 +887,7 @@ void CAMLPlayer::SetAudioStream(int SetAudioStream) void CAMLPlayer::SetAVDelay(float fValue) { CLog::Log(LOGDEBUG, "CAMLPlayer::SetAVDelay (%f)", fValue); +#if !defined(TARGET_ANDROID) m_audio_delay = fValue * 1000.0; if (m_audio_streams.size() && m_dll->check_pid_valid(m_pid)) @@ -894,6 +895,7 @@ void CAMLPlayer::SetAVDelay(float fValue) CSingleLock lock(m_aml_csection); m_dll->audio_set_delay(m_pid, m_audio_delay); } +#endif } float CAMLPlayer::GetAVDelay() diff --git a/xbmc/cores/amlplayer/DllLibamplayer.h b/xbmc/cores/amlplayer/DllLibamplayer.h index 3bde96313d4bc..e6f87d4eb19f3 100644 --- a/xbmc/cores/amlplayer/DllLibamplayer.h +++ b/xbmc/cores/amlplayer/DllLibamplayer.h @@ -63,8 +63,9 @@ class DllLibAmplayerInterface virtual char* player_status2str(player_status status)=0; virtual int audio_set_volume(int pid,float val)=0; +#if !defined(TARGET_ANDROID) virtual int audio_set_delay(int pid, int delay)=0; - +#endif virtual int codec_open_sub_read(void)=0; virtual int codec_close_sub_fd(int sub_fd)=0; virtual int codec_get_sub_size_fd(int sub_fd)=0; @@ -104,7 +105,9 @@ class DllLibAmplayer : public DllDynamic, DllLibAmplayerInterface DEFINE_METHOD1(char*, player_status2str, (player_status p1)) DEFINE_METHOD2(int, audio_set_volume, (int p1, float p2)) +#if !defined(TARGET_ANDROID) DEFINE_METHOD2(int, audio_set_delay, (int p1, int p2)) +#endif DEFINE_METHOD0(int, codec_open_sub_read) DEFINE_METHOD1(int, codec_close_sub_fd, (int p1)) @@ -141,8 +144,9 @@ class DllLibAmplayer : public DllDynamic, DllLibAmplayerInterface RESOLVE_METHOD(player_status2str) RESOLVE_METHOD(audio_set_volume) +#if !defined(TARGET_ANDROID) RESOLVE_METHOD(audio_set_delay) - +#endif RESOLVE_METHOD(codec_open_sub_read) RESOLVE_METHOD(codec_close_sub_fd) RESOLVE_METHOD(codec_get_sub_size_fd) From 298aeeb5f4f26976bc0b2d360976ced7ae1273e2 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 3 Oct 2012 19:41:17 -0400 Subject: [PATCH 030/180] [aml] add macro for optional export resolving --- xbmc/DynamicDll.h | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/xbmc/DynamicDll.h b/xbmc/DynamicDll.h index 8a4972783b9be..739250f867f20 100644 --- a/xbmc/DynamicDll.h +++ b/xbmc/DynamicDll.h @@ -1,5 +1,4 @@ #pragma once - /* * Copyright (C) 2005-2012 Team XBMC * http://www.xbmc.org @@ -356,12 +355,10 @@ public: \ #define BEGIN_METHOD_RESOLVE() \ protected: \ virtual bool ResolveExports() \ - { \ - return ( + { #define END_METHOD_RESOLVE() \ - 1 \ - ); \ + return true; \ } /////////////////////////////////////////////////////////// @@ -374,10 +371,33 @@ public: \ // or DEFINE_METHOD_LINKAGE // #define RESOLVE_METHOD(method) \ - m_dll->ResolveExport( #method , & m_##method##_ptr ) && + if (!m_dll->ResolveExport( #method , & m_##method##_ptr )) \ + return false; #define RESOLVE_METHOD_FP(method) \ - m_dll->ResolveExport( #method , & method##_ptr ) && + if (!m_dll->ResolveExport( #method , & method##_ptr )) \ + return false; + + +/////////////////////////////////////////////////////////// +// +// RESOLVE_METHOD_OPTIONAL +// +// Resolves a method from a dll. does not abort if the +// method is missing +// +// method: Name of the method defined with DEFINE_METHOD +// or DEFINE_METHOD_LINKAGE +// + +#define RESOLVE_METHOD_OPTIONAL(method) \ + m_dll->ResolveExport( #method , & m_##method##_ptr ); + +#define RESOLVE_METHOD_OPTIONAL_FP(method) \ + method##_ptr = NULL; \ + m_dll->ResolveExport( #method , & method##_ptr ); + + /////////////////////////////////////////////////////////// // @@ -390,10 +410,12 @@ public: \ // or DEFINE_METHOD_LINKAGE // #define RESOLVE_METHOD_RENAME(dllmethod, method) \ - m_dll->ResolveExport( #dllmethod , & m_##method##_ptr ) && + if (!m_dll->ResolveExport( #dllmethod , & m_##method##_ptr )) \ + return false; #define RESOLVE_METHOD_RENAME_FP(dllmethod, method) \ - m_dll->ResolveExport( #dllmethod , & method##_ptr ) && + if (!m_dll->ResolveExport( #dllmethod , & method##_ptr )) \ + return false; //////////////////////////////////////////////////////////////////// From f44ed4238a2f704e18bdbe4431a98a732cf173b2 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 3 Oct 2012 22:45:06 -0400 Subject: [PATCH 031/180] [aml/droid] add config files if they exist in tools/android/packaging/config --- tools/android/packaging/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/android/packaging/Makefile b/tools/android/packaging/Makefile index 124be50dc2021..eb76d2cd45feb 100644 --- a/tools/android/packaging/Makefile +++ b/tools/android/packaging/Makefile @@ -65,6 +65,7 @@ extras: libs cd xbmc/assets/python2.6/lib/python2.6/; rm -rf test config lib-dynload mkdir -p tmp/res; $(AAPT) c -S xbmc/res -C tmp/res; cp -r -n xbmc/res tmp/ || true $(AAPT) p -f -I $(SDKROOT)/platforms/$(SDK_PLATFORM)/android.jar -S tmp/res/ -M xbmc/AndroidManifest.xml -F images/xbmcapp-debug-skeleton.apk -J xbmc/src + test -d config && cp -f config/* xbmc/assets/system @rm -rf tmp/ libs: $(PREFIX)/lib/xbmc/libxbmc.so From 4f2a1cc195b33ce4054f802b263984e47a4335b0 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 3 Oct 2012 22:45:30 -0400 Subject: [PATCH 032/180] [aml-noupstream] aml-specific config files for android --- .../packaging/config/advancedsettings.xml | 34 +++++++++++++++++++ .../android/packaging/config/guisettings.xml | 17 ++++++++++ 2 files changed, 51 insertions(+) create mode 100644 tools/android/packaging/config/advancedsettings.xml create mode 100644 tools/android/packaging/config/guisettings.xml diff --git a/tools/android/packaging/config/advancedsettings.xml b/tools/android/packaging/config/advancedsettings.xml new file mode 100644 index 0000000000000..aef3196a44aba --- /dev/null +++ b/tools/android/packaging/config/advancedsettings.xml @@ -0,0 +1,34 @@ + + + + + lookandfeel.soundskin + videoplayer.rendermethod + videoplayer.adjustrefreshrate + videoplayer.pauseafterrefreshchange + videoplayer.usedisplayasclock + videoplayer.synctype + videoplayer.teletextenabled + subtitles.charset + dvds.playerregion + dvds.automenu + audiocds + karaoke + videoscreen.screenmode + videoscreen.screen + videoscreen.vsync + videoscreen.testpattern + audiooutput.mode + audiooutput.channellayout + audiooutput.dontnormalizelevels + audiooutput.audiodevice + audiooutput.customdevice + audiooutput.passthroughdevice + audiooutput.custompassthrough + input.remoteaskeyboard + audiooutput.guisoundmode + + + diff --git a/tools/android/packaging/config/guisettings.xml b/tools/android/packaging/config/guisettings.xml new file mode 100644 index 0000000000000..106d62040e3c7 --- /dev/null +++ b/tools/android/packaging/config/guisettings.xml @@ -0,0 +1,17 @@ + + + false + + + false + false + 2 + + + 2 + + + false + true + + From 5b6b78e2ab03cbc119215d92fc790caa17ded80c Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 5 Oct 2012 01:01:50 -0400 Subject: [PATCH 033/180] [aml] move lirc init before keyboard LIRC's devinput driver requires exclusive access, which conflicts with our evdev input manager. If LIRC is able to grab a device and use it, assume that we want it to, then evdev can't grab it. --- xbmc/Application.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp index 1e8da45a369d0..e945bf8a1e07c 100644 --- a/xbmc/Application.cpp +++ b/xbmc/Application.cpp @@ -744,6 +744,9 @@ bool CApplication::Create() CLog::Log(LOGFATAL, "CApplication::Create: Unable to start CAddonMgr"); return false; } +#if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE) + g_RemoteControl.Initialize(); +#endif g_peripherals.Initialise(); @@ -753,9 +756,6 @@ bool CApplication::Create() g_Mouse.SetEnabled(g_guiSettings.GetBool("input.enablemouse")); g_Keyboard.Initialize(); -#if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE) - g_RemoteControl.Initialize(); -#endif #if defined(TARGET_DARWIN_OSX) // Configure and possible manually start the helper. From 483ed70bcaa4d67a7591cdd0467f0e44fed1f632 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 5 Oct 2012 16:46:49 -0400 Subject: [PATCH 034/180] [aml] clear screen (in the right place) before shutdown --- xbmc/rendering/gles/RenderSystemGLES.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/xbmc/rendering/gles/RenderSystemGLES.cpp b/xbmc/rendering/gles/RenderSystemGLES.cpp index e38bd14687e00..63aec06a64fa7 100644 --- a/xbmc/rendering/gles/RenderSystemGLES.cpp +++ b/xbmc/rendering/gles/RenderSystemGLES.cpp @@ -173,6 +173,15 @@ bool CRenderSystemGLES::DestroyRenderSystem() m_pGUIshader = NULL; } + ResetScissors(); + CDirtyRegionList dirtyRegions; + CDirtyRegion dirtyWindow(g_graphicsContext.GetViewWindow()); + dirtyRegions.push_back(dirtyWindow); + + ClearBuffers(0); + glFinish(); + PresentRenderImpl(dirtyRegions); + m_bRenderCreated = false; return true; From 68ca5a77b9a3ae2ef0ecaa1c72ff9db5f751b755 Mon Sep 17 00:00:00 2001 From: davilla Date: Mon, 8 Oct 2012 13:31:12 -0400 Subject: [PATCH 035/180] [aml] 1) fixed subtitle lang/switching, 2) cosmetic change of __int64 to int64_t. --- xbmc/cores/amlplayer/AMLPlayer.cpp | 43 +++++++++++++++++++++++++----- xbmc/cores/amlplayer/AMLPlayer.h | 8 +++--- 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/xbmc/cores/amlplayer/AMLPlayer.cpp b/xbmc/cores/amlplayer/AMLPlayer.cpp index b7cc2f34f81c5..dd8bf172b4cca 100644 --- a/xbmc/cores/amlplayer/AMLPlayer.cpp +++ b/xbmc/cores/amlplayer/AMLPlayer.cpp @@ -312,6 +312,20 @@ CAMLSubTitleThread::~CAMLSubTitleThread() StopThread(); } +void CAMLSubTitleThread::Flush() +{ + CSingleLock lock(m_subtitle_csection); + if (m_subtitle_strings.size()) + { + // remove any expired subtitles + std::deque::iterator it = m_subtitle_strings.begin(); + while (it != m_subtitle_strings.end()) + { + it = m_subtitle_strings.erase(it); + } + } +} + void CAMLSubTitleThread::UpdateSubtitle(CStdString &subtitle, int64_t elapsed_ms) { CSingleLock lock(m_subtitle_csection); @@ -958,9 +972,15 @@ void CAMLPlayer::GetSubtitleName(int iStream, CStdString &strStreamName) strStreamName = g_localizeStrings.Get(13205); // Unknown } if (m_log_level > 5) - CLog::Log(LOGDEBUG, "CAMLPlayer::GetSubtitleName, iStream(%d)", iStream); + CLog::Log(LOGDEBUG, "CAMLPlayer::GetSubtitleName, iStream(%d), strStreamName(%s)", + iStream, strStreamName.c_str()); } +void CAMLPlayer::GetSubtitleLanguage(int iStream, CStdString &strStreamLang) +{ + GetSubtitleName(iStream, strStreamLang); +} + void CAMLPlayer::SetSubtitle(int iStream) { CSingleLock lock(m_aml_csection); @@ -977,7 +997,12 @@ void CAMLPlayer::SetSubtitle(int iStream) return; if (m_dll->check_pid_valid(m_pid) && m_subtitle_streams[m_subtitle_index]->source == STREAM_SOURCE_NONE) + { m_dll->player_sid(m_pid, m_subtitle_streams[m_subtitle_index]->id); + aml_set_sysfs_int("/sys/class/subtitle/curr", m_subtitle_index); + if (m_subtitle_thread) + m_subtitle_thread->Flush(); + } else { m_dvdPlayerSubtitle->CloseStream(true); @@ -997,12 +1022,19 @@ void CAMLPlayer::SetSubtitleVisible(bool bVisible) if (m_subtitle_show && m_subtitle_count) { + if (g_settings.m_currentVideoSettings.m_SubtitleStream < m_subtitle_count) + m_subtitle_index = g_settings.m_currentVideoSettings.m_SubtitleStream; // on startup, if asked to show subs and SetSubtitle has not // been called, we are expected to switch/show the 1st subtitle if (m_subtitle_index < 0) m_subtitle_index = 0; if (m_dll->check_pid_valid(m_pid) && m_subtitle_streams[m_subtitle_index]->source == STREAM_SOURCE_NONE) + { m_dll->player_sid(m_pid, m_subtitle_streams[m_subtitle_index]->id); + aml_set_sysfs_int("/sys/class/subtitle/curr", m_subtitle_index); + if (m_subtitle_thread) + m_subtitle_thread->Flush(); + } else OpenSubtitleStream(m_subtitle_index); } @@ -1097,7 +1129,7 @@ float CAMLPlayer::GetActualFPS() return video_fps; } -void CAMLPlayer::SeekTime(__int64 seek_ms) +void CAMLPlayer::SeekTime(int64_t seek_ms) { CSingleLock lock(m_aml_csection); @@ -1122,12 +1154,12 @@ void CAMLPlayer::SeekTime(__int64 seek_ms) } } -__int64 CAMLPlayer::GetTime() +int64_t CAMLPlayer::GetTime() { return m_elapsed_ms; } -__int64 CAMLPlayer::GetTotalTime() +int64_t CAMLPlayer::GetTotalTime() { return m_duration_ms; } @@ -1917,11 +1949,10 @@ bool CAMLPlayer::WaitForFormatValid(int timeout_ms) "m_video_index(%d), m_audio_index(%d), m_subtitle_index(%d), m_chapter_count(%d)", media_info.stream_info.cur_video_index, media_info.stream_info.cur_audio_index, -#if !defined(TARGET_ANDROID) media_info.stream_info.cur_sub_index, +#if !defined(TARGET_ANDROID) media_info.stream_info.total_chapter_num); #else - media_info.stream_info.cur_sub_index, 0); #endif } diff --git a/xbmc/cores/amlplayer/AMLPlayer.h b/xbmc/cores/amlplayer/AMLPlayer.h index 2624b61efe784..461f21637663b 100644 --- a/xbmc/cores/amlplayer/AMLPlayer.h +++ b/xbmc/cores/amlplayer/AMLPlayer.h @@ -43,6 +43,7 @@ class CAMLSubTitleThread : public CThread CAMLSubTitleThread(DllLibAmplayer* dll); virtual ~CAMLSubTitleThread(); + void Flush(); void UpdateSubtitle(CStdString &subtitle, int64_t elapsed_ms); protected: virtual void Process(void); @@ -102,6 +103,7 @@ class CAMLPlayer : public IPlayer, public CThread virtual int GetSubtitleCount(); virtual int GetSubtitle(); virtual void GetSubtitleName(int iStream, CStdString &strStreamName); + virtual void GetSubtitleLanguage(int iStream, CStdString &strStreamLang); virtual void SetSubtitle(int iStream); virtual bool GetSubtitleVisible(); virtual void SetSubtitleVisible(bool bVisible); @@ -123,9 +125,9 @@ class CAMLPlayer : public IPlayer, public CThread virtual int SeekChapter(int iChapter); virtual float GetActualFPS(); - virtual void SeekTime(__int64 iTime = 0); - virtual __int64 GetTime(); - virtual __int64 GetTotalTime(); + virtual void SeekTime(int64_t iTime = 0); + virtual int64_t GetTime(); + virtual int64_t GetTotalTime(); virtual int GetAudioBitrate(); virtual int GetVideoBitrate(); virtual int GetSourceBitrate(); From 5f20769be8df31eb279ea982c4adc59760dea3b6 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 9 Oct 2012 00:54:58 -0400 Subject: [PATCH 036/180] [droid] fix libssh --- tools/android/depends/libssh/android.patch | 70 +++++++++++++--------- 1 file changed, 41 insertions(+), 29 deletions(-) diff --git a/tools/android/depends/libssh/android.patch b/tools/android/depends/libssh/android.patch index c76e648f7f31c..b2fc58d11b080 100644 --- a/tools/android/depends/libssh/android.patch +++ b/tools/android/depends/libssh/android.patch @@ -1,49 +1,61 @@ ---- src/connect.c 2011-05-31 10:29:52.000000000 -0400 -+++ src/connect.c 2012-07-25 23:15:22.281514489 -0400 +--- src/connect.c 2011-05-31 10:29:52.000000000 -0400 ++++ src/connect.c 2012-07-25 23:15:22.281514489 -0400 @@ -159,7 +159,7 @@ int timeout_ms; ssh_pollfd_t fds; int rc = 0; - unsigned int len = sizeof(rc); + socklen_t len = sizeof(rc); - + enter_function(); ---- src/misc.c 2011-05-31 10:29:52.000000000 -0400 -+++ src/misc.c 2012-07-25 23:24:46.611514133 -0400 -@@ -207,6 +207,9 @@ - #endif /* NSS_BUFLEN_PASSWD */ +--- src/misc.c 2012-10-08 23:50:23.567426941 -0400 ++++ src/misc.c 2012-10-09 00:19:57.217425822 -0400 +@@ -208,17 +208,12 @@ char *ssh_get_user_home_dir(void) { -+#if defined(__ANDROID__) -+ return NULL; -+#else char *szPath = NULL; - struct passwd pwd; - struct passwd *pwdbuf; -@@ -221,6 +224,7 @@ - szPath = strdup(pwd.pw_dir); +- struct passwd pwd; +- struct passwd *pwdbuf; +- char buf[NSS_BUFLEN_PASSWD]; +- int rc; +- +- rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf); +- if (rc != 0) { ++ struct passwd *pwd = NULL; ++ pwd = getpwuid(getuid()); ++ if ( pwd == NULL) + return NULL; +- } + +- szPath = strdup(pwd.pw_dir); ++ szPath = strdup(pwd->pw_dir); return szPath; -+#endif } - - /* we have read access on file */ -@@ -233,6 +237,9 @@ +@@ -233,20 +228,16 @@ } char *ssh_get_local_username(ssh_session session) { -+#if defined(__ANDROID__) -+ return NULL; -+#else - struct passwd pwd; - struct passwd *pwdbuf; - char buf[NSS_BUFLEN_PASSWD]; -@@ -254,6 +261,7 @@ +- struct passwd pwd; +- struct passwd *pwdbuf; +- char buf[NSS_BUFLEN_PASSWD]; +- char *name; +- int rc; +- +- rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf); +- if (rc != 0) { ++ char *name = NULL; ++ struct passwd *pwd = NULL; ++ pwd = getpwuid(getuid()); ++ if ( pwd == NULL) { + ssh_set_error(session, SSH_FATAL, + "Couldn't retrieve information for current user!"); + return NULL; } - return name; -+#endif - } +- name = strdup(pwd.pw_name); ++ name = strdup(pwd->pw_name); - int ssh_is_ipaddr_v4(const char *str) { + if (name == NULL) { + ssh_set_error_oom(session); From 4efa863126f315b9121c10380417dcdbfef57f8c Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 9 Oct 2012 00:58:11 -0400 Subject: [PATCH 037/180] [droid] sftp: skip saving known hosts for now --- xbmc/filesystem/SFTPFile.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xbmc/filesystem/SFTPFile.cpp b/xbmc/filesystem/SFTPFile.cpp index d176969835a37..a6212dca1fb33 100644 --- a/xbmc/filesystem/SFTPFile.cpp +++ b/xbmc/filesystem/SFTPFile.cpp @@ -275,12 +275,14 @@ bool CSFTPSession::VerifyKnownHost(ssh_session session) CLog::Log(LOGINFO, "SFTPSession: Server file was not found, creating a new one"); case SSH_SERVER_NOT_KNOWN: CLog::Log(LOGINFO, "SFTPSession: Server unkown, we trust it for now"); +#if !defined(TARGET_ANDROID) +//TODO: use a writable path and remove this. if (ssh_write_knownhost(session) < 0) { CLog::Log(LOGERROR, "CSFTPSession: Failed to save host '%s'", strerror(errno)); return false; } - +#endif return true; case SSH_SERVER_ERROR: CLog::Log(LOGERROR, "SFTPSession: Failed to verify host '%s'", ssh_get_error(session)); From ec0b46ed8395b4970221361d64d561fac3b2a633 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 9 Oct 2012 01:49:41 -0400 Subject: [PATCH 038/180] [aml] fix sftp for amlplayer --- xbmc/cores/amlplayer/AMLPlayer.cpp | 7 +++++++ xbmc/cores/amlplayer/FileURLProtocol.cpp | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/xbmc/cores/amlplayer/AMLPlayer.cpp b/xbmc/cores/amlplayer/AMLPlayer.cpp index dd8bf172b4cca..8edf903f3c3b2 100644 --- a/xbmc/cores/amlplayer/AMLPlayer.cpp +++ b/xbmc/cores/amlplayer/AMLPlayer.cpp @@ -1424,6 +1424,13 @@ void CAMLPlayer::Process() vfs_protocol.name = http_name; url = "xb-" + url; } + else if (url.Left(strlen("sftp://")).Equals("sftp://")) + { + // the name string needs to persist + static const char *http_name = "xb-sftp"; + vfs_protocol.name = http_name; + url = "xb-" + url; + } CLog::Log(LOGDEBUG, "CAMLPlayer::Process: URL=%s", url.c_str()); if (m_dll->player_init() != PLAYER_SUCCESS) diff --git a/xbmc/cores/amlplayer/FileURLProtocol.cpp b/xbmc/cores/amlplayer/FileURLProtocol.cpp index ba817b0372cd3..2a7a26dca03e6 100644 --- a/xbmc/cores/amlplayer/FileURLProtocol.cpp +++ b/xbmc/cores/amlplayer/FileURLProtocol.cpp @@ -56,6 +56,10 @@ int CFileURLProtocol::Open(AML_URLContext *h, const char *filename, int flags) { url = url.Right(url.size() - strlen("xb-")); } + else if (url.Left(strlen("xb-sftp://")).Equals("xb-sftp://")) + { + url = url.Right(url.size() - strlen("xb-")); + } else if (url.Left(strlen("xb-hdhomerun://")).Equals("xb-hdhomerun://")) { url = url.Right(url.size() - strlen("xb-")); From 103947d86bc7a4593e3b0a0f727301ade6dd8751 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 9 Oct 2012 02:00:52 -0400 Subject: [PATCH 039/180] [aml/droid] sync gui settings with linux --- tools/android/packaging/config/guisettings.xml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/android/packaging/config/guisettings.xml b/tools/android/packaging/config/guisettings.xml index 106d62040e3c7..1b71e6020c349 100644 --- a/tools/android/packaging/config/guisettings.xml +++ b/tools/android/packaging/config/guisettings.xml @@ -3,15 +3,18 @@ false + 0 false false + false + false> + false 2 2 - false true From 9e7b50485b04b4bedbe3513565cfd1ac0e528f07 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 9 Oct 2012 23:33:06 -0400 Subject: [PATCH 040/180] [aml] fix for crazy videos with >32 subtitles --- xbmc/cores/amlplayer/AMLPlayer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xbmc/cores/amlplayer/AMLPlayer.cpp b/xbmc/cores/amlplayer/AMLPlayer.cpp index 8edf903f3c3b2..057dadbce96b9 100644 --- a/xbmc/cores/amlplayer/AMLPlayer.cpp +++ b/xbmc/cores/amlplayer/AMLPlayer.cpp @@ -2034,7 +2034,7 @@ bool CAMLPlayer::WaitForFormatValid(int timeout_ms) // subtitle info if (media_info.stream_info.has_sub && media_info.stream_info.total_sub_num > 0) { - for (int i = 0; i < media_info.stream_info.total_sub_num; i++) + for (int i = 0; i < media_info.stream_info.total_sub_num && i < MAX_SUB_STREAMS; i++) { AMLPlayerStreamInfo *info = new AMLPlayerStreamInfo; info->Clear(); From acc8d522cc747475f4f8e4e485f45826080ba95f Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 9 Oct 2012 23:42:35 -0400 Subject: [PATCH 041/180] [aml] clamp chapters, audio streams, video streams while we're at it --- xbmc/cores/amlplayer/AMLPlayer.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/xbmc/cores/amlplayer/AMLPlayer.cpp b/xbmc/cores/amlplayer/AMLPlayer.cpp index 057dadbce96b9..fb31af56ef74a 100644 --- a/xbmc/cores/amlplayer/AMLPlayer.cpp +++ b/xbmc/cores/amlplayer/AMLPlayer.cpp @@ -1967,7 +1967,8 @@ bool CAMLPlayer::WaitForFormatValid(int timeout_ms) // video info if (media_info.stream_info.has_video && media_info.stream_info.total_video_num > 0) { - for (int i = 0; i < media_info.stream_info.total_video_num; i++) + for (int i = 0; i < media_info.stream_info.total_video_num && + media_info.stream_info.total_video_num < MAX_VIDEO_STREAMS; i++) { AMLPlayerStreamInfo *info = new AMLPlayerStreamInfo; info->Clear(); @@ -2004,7 +2005,8 @@ bool CAMLPlayer::WaitForFormatValid(int timeout_ms) // audio info if (media_info.stream_info.has_audio && media_info.stream_info.total_audio_num > 0) { - for (int i = 0; i < media_info.stream_info.total_audio_num; i++) + for (int i = 0; i < media_info.stream_info.total_audio_num && + media_info.stream_info.total_audio_num < MAX_AUDIO_STREAMS; i++) { AMLPlayerStreamInfo *info = new AMLPlayerStreamInfo; info->Clear(); @@ -2059,7 +2061,7 @@ bool CAMLPlayer::WaitForFormatValid(int timeout_ms) if (media_info.stream_info.total_chapter_num > 0) { m_chapter_count = media_info.stream_info.total_chapter_num; - for (int i = 0; i < m_chapter_count; i++) + for (int i = 0; i < m_chapter_count && m_chapter_count < MAX_CHAPTERS; i++) { if (media_info.chapter_info[i] != NULL) { From a73ee52635c613d437669175708e6d2627b651b7 Mon Sep 17 00:00:00 2001 From: davilla Date: Fri, 2 Nov 2012 09:19:57 -0400 Subject: [PATCH 042/180] [aml] changed how to detect aml_present --- xbmc/cores/amlplayer/AMLUtils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xbmc/cores/amlplayer/AMLUtils.cpp b/xbmc/cores/amlplayer/AMLUtils.cpp index a127b33fa7ce3..9b62ca7f8e8e3 100644 --- a/xbmc/cores/amlplayer/AMLUtils.cpp +++ b/xbmc/cores/amlplayer/AMLUtils.cpp @@ -85,7 +85,7 @@ bool aml_present() static int has_aml = -1; if (has_aml == -1) { - if (aml_get_sysfs_int("/sys/class/amhdmitx/amhdmitx0/disp_cap") != -1) + if (aml_get_sysfs_int("/sys/class/audiodsp/digital_raw") != -1) has_aml = 1; else has_aml = 0; From 8e032907928051834895af589fb4ac01cbd45b57 Mon Sep 17 00:00:00 2001 From: davilla Date: Fri, 2 Nov 2012 09:53:43 -0400 Subject: [PATCH 043/180] [aml] cosmetics --- xbmc/cores/amlplayer/AMLUtils.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/xbmc/cores/amlplayer/AMLUtils.cpp b/xbmc/cores/amlplayer/AMLUtils.cpp index 9b62ca7f8e8e3..6e7e32b2b642e 100644 --- a/xbmc/cores/amlplayer/AMLUtils.cpp +++ b/xbmc/cores/amlplayer/AMLUtils.cpp @@ -95,11 +95,11 @@ bool aml_present() void aml_cpufreq_limit(bool limit) { - static int audiotrack_cputype = -1; - if (audiotrack_cputype == -1) + static int aml_cputype = -1; + if (aml_cputype == -1) { // defualt to m1 SoC - audiotrack_cputype = 1; + aml_cputype = 1; FILE *cpuinfo_fd = fopen("/proc/cpuinfo", "r"); if (cpuinfo_fd) @@ -110,7 +110,7 @@ void aml_cpufreq_limit(bool limit) std::string stdbuffer(buffer); if (stdbuffer.find("MESON-M3") != std::string::npos) { - audiotrack_cputype = 3; + aml_cputype = 3; break; } } @@ -121,7 +121,7 @@ void aml_cpufreq_limit(bool limit) // or risk hw audio dropouts. AML code does a 2X scaling based off // /sys/class/audiodsp/codec_mips but tests show that this is // seems risky so we just clamp to 600Mhz to be safe. - if (audiotrack_cputype == 3) + if (aml_cputype == 3) return; int cpufreq = 300000; From 686f467090bb346b7b205d31c8a2c6b67187cca9 Mon Sep 17 00:00:00 2001 From: davilla Date: Thu, 8 Nov 2012 05:53:16 -0500 Subject: [PATCH 044/180] [aml] add chapter support --- .../libamplayer/libamplayer/include/player_type.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tools/android/depends/libamplayer/libamplayer/include/player_type.h b/tools/android/depends/libamplayer/libamplayer/include/player_type.h index 2abd1940f3759..37877a4a16753 100644 --- a/tools/android/depends/libamplayer/libamplayer/include/player_type.h +++ b/tools/android/depends/libamplayer/libamplayer/include/player_type.h @@ -5,6 +5,7 @@ #include #define MSG_SIZE 64 +#define MAX_CHAPTERS 64 #define MAX_VIDEO_STREAMS 8 #define MAX_AUDIO_STREAMS 8 #define MAX_SUB_INTERNAL 8 @@ -107,6 +108,7 @@ typedef struct typedef struct { + int index; int id; int channel; int sample_rate; @@ -114,10 +116,12 @@ typedef struct aformat_t aformat; int duration; audio_tag_info *audio_tag; + char audio_language[4]; }maudio_info_t; typedef struct { + int index; char id; char internal_external; //0:internal_sub 1:external_sub unsigned short width; @@ -147,14 +151,23 @@ typedef struct int cur_sub_index; int seekable; int drm_check; + int has_chapter; + int total_chapter_num; }mstream_info_t; +typedef struct +{ + char *name; + int64_t seekto_ms; +} mchapter_info_t; + typedef struct { mstream_info_t stream_info; mvideo_info_t *video_info[MAX_VIDEO_STREAMS]; maudio_info_t *audio_info[MAX_AUDIO_STREAMS]; msub_info_t *sub_info[MAX_SUB_STREAMS]; + mchapter_info_t *chapter_info[MAX_CHAPTERS]; }media_info_t; typedef struct player_info @@ -231,7 +244,7 @@ typedef struct int video_index; //video track, no assigned, please set to -1 int audio_index; //audio track, no assigned, please set to -1 int sub_index; //subtitle track, no assigned, please set to -1 - int t_pos; //start postion, use second as unit + float t_pos; //start postion, use second as unit int read_max_cnt; //read retry maxium counts, if exceed it, return error int avsync_threshold; //for adec av sync threshold in ms union From b19ab48d2a891370d5dcd85c8d2638bd92e500d4 Mon Sep 17 00:00:00 2001 From: davilla Date: Fri, 16 Nov 2012 07:24:52 -0500 Subject: [PATCH 045/180] [aml] fixed beta1 merge, missing --enable-player=amlplayer --- tools/android/depends/xbmc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/android/depends/xbmc/Makefile b/tools/android/depends/xbmc/Makefile index a5c5c3207b36f..afd03c6671098 100644 --- a/tools/android/depends/xbmc/Makefile +++ b/tools/android/depends/xbmc/Makefile @@ -20,7 +20,7 @@ CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) build-aux/ ;\ --enable-neon --enable-gles --enable-debug \ --disable-sdl --disable-x11 --disable-xrandr \ --disable-optical-drive --disable-joystick \ - --enable-shared-lib --disable-alsa + --enable-shared-lib --disable-alsa --enable-player=amlplayer all: $(SOURCE)/libxbmc.so From 9369a418548814304dfa4426a2528b1ae7b5fce0 Mon Sep 17 00:00:00 2001 From: davilla Date: Sat, 13 Oct 2012 09:49:55 -0400 Subject: [PATCH 046/180] changed, log the clamp value --- xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp index 410e20ce41a4f..9f4e50da93ed4 100644 --- a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp +++ b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp @@ -1127,11 +1127,12 @@ bool CSoftAE::FinalizeSamples(float *buffer, unsigned int samples, bool hasAudio /* check if we need to clamp */ bool clamp = false; - float *fbuffer = buffer; + float clamp_value, *fbuffer = buffer; for (unsigned int i = 0; i < samples; i++, fbuffer++) { if (*fbuffer < -1.0f || *fbuffer > 1.0f) { + clamp_value = *fbuffer; clamp = true; break; } @@ -1141,7 +1142,7 @@ bool CSoftAE::FinalizeSamples(float *buffer, unsigned int samples, bool hasAudio if (!clamp) return true; - CLog::Log(LOGDEBUG, "CSoftAE::FinalizeSamples - Clamping buffer of %d samples", samples); + CLog::Log(LOGDEBUG, "CSoftAE::FinalizeSamples - Clamping buffer of %d samples, clamp value(%f)", samples, clamp_value); CAEUtil::ClampArray(buffer, samples); return true; } From 7e298cec0b44b83b1294365121f80a185a7f2d2d Mon Sep 17 00:00:00 2001 From: davilla Date: Sat, 13 Oct 2012 09:50:38 -0400 Subject: [PATCH 047/180] changed, reduce logging spew --- xbmc/input/linux/LinuxInputDevices.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/xbmc/input/linux/LinuxInputDevices.cpp b/xbmc/input/linux/LinuxInputDevices.cpp index f4331658c46af..2817c864b7d49 100644 --- a/xbmc/input/linux/LinuxInputDevices.cpp +++ b/xbmc/input/linux/LinuxInputDevices.cpp @@ -967,7 +967,6 @@ bool CLinuxInputDevices::CheckDevice(const char *device) { int fd; - CLog::Log(LOGDEBUG, "Checking device: %s\n", device); /* Check if we are able to open the device */ fd = open(device, O_RDWR); if (fd < 0) From 8aa3ff647a2446d825be39320916bbdece85469b Mon Sep 17 00:00:00 2001 From: davilla Date: Fri, 16 Nov 2012 07:38:34 -0500 Subject: [PATCH 048/180] [aml] cleanup commented out functions --- xbmc/cores/amlplayer/AMLPlayer.cpp | 85 +++++++----------------------- xbmc/cores/amlplayer/AMLPlayer.h | 8 --- 2 files changed, 20 insertions(+), 73 deletions(-) diff --git a/xbmc/cores/amlplayer/AMLPlayer.cpp b/xbmc/cores/amlplayer/AMLPlayer.cpp index fb31af56ef74a..60a4c42173502 100644 --- a/xbmc/cores/amlplayer/AMLPlayer.cpp +++ b/xbmc/cores/amlplayer/AMLPlayer.cpp @@ -901,7 +901,6 @@ void CAMLPlayer::SetAudioStream(int SetAudioStream) void CAMLPlayer::SetAVDelay(float fValue) { CLog::Log(LOGDEBUG, "CAMLPlayer::SetAVDelay (%f)", fValue); -#if !defined(TARGET_ANDROID) m_audio_delay = fValue * 1000.0; if (m_audio_streams.size() && m_dll->check_pid_valid(m_pid)) @@ -909,7 +908,6 @@ void CAMLPlayer::SetAVDelay(float fValue) CSingleLock lock(m_aml_csection); m_dll->audio_set_delay(m_pid, m_audio_delay); } -#endif } float CAMLPlayer::GetAVDelay() @@ -1664,48 +1662,43 @@ void CAMLPlayer::Process() if (m_log_level > 5) CLog::Log(LOGDEBUG, "CAMLPlayer::Process exit"); } -/* -void CAMLPlayer::GetRenderFeatures(Features* renderFeatures) + +void CAMLPlayer::GetRenderFeatures(std::vector &renderFeatures) { - renderFeatures->push_back(RENDERFEATURE_ZOOM); - renderFeatures->push_back(RENDERFEATURE_CONTRAST); - renderFeatures->push_back(RENDERFEATURE_BRIGHTNESS); - renderFeatures->push_back(RENDERFEATURE_STRETCH); - return; + renderFeatures.push_back(RENDERFEATURE_ZOOM); + renderFeatures.push_back(RENDERFEATURE_CONTRAST); + renderFeatures.push_back(RENDERFEATURE_BRIGHTNESS); + renderFeatures.push_back(RENDERFEATURE_STRETCH); } -void CAMLPlayer::GetDeinterlaceMethods(Features* deinterlaceMethods) +void CAMLPlayer::GetDeinterlaceMethods(std::vector &deinterlaceMethods) { - deinterlaceMethods->push_back(VS_INTERLACEMETHOD_DEINTERLACE); - return; + deinterlaceMethods.push_back(VS_INTERLACEMETHOD_DEINTERLACE); } -void CAMLPlayer::GetDeinterlaceModes(Features* deinterlaceModes) +void CAMLPlayer::GetDeinterlaceModes(std::vector &deinterlaceModes) { - deinterlaceModes->push_back(VS_DEINTERLACEMODE_AUTO); - return; + deinterlaceModes.push_back(VS_DEINTERLACEMODE_AUTO); } -void CAMLPlayer::GetScalingMethods(Features* scalingMethods) +void CAMLPlayer::GetScalingMethods(std::vector &scalingMethods) { - return; } -void CAMLPlayer::GetAudioCapabilities(Features* audioCaps) +void CAMLPlayer::GetAudioCapabilities(std::vector &audioCaps) { - audioCaps->push_back(IPC_AUD_OFFSET); - audioCaps->push_back(IPC_AUD_SELECT_STREAM); - return; + audioCaps.push_back(IPC_AUD_SELECT_STREAM); + audioCaps.push_back(IPC_AUD_SELECT_OUTPUT); + audioCaps.push_back(IPC_AUD_OFFSET); } -void CAMLPlayer::GetSubtitleCapabilities(Features* subCaps) +void CAMLPlayer::GetSubtitleCapabilities(std::vector &subCaps) { - subCaps->push_back(IPC_SUBS_EXTERNAL); - subCaps->push_back(IPC_SUBS_OFFSET); - subCaps->push_back(IPC_SUBS_SELECT); - return; + subCaps.push_back(IPC_SUBS_EXTERNAL); + subCaps.push_back(IPC_SUBS_SELECT); + subCaps.push_back(IPC_SUBS_OFFSET); } -*/ + //////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////// @@ -2369,41 +2362,3 @@ void CAMLPlayer::RenderUpdateCallBack(const void *ctx, const CRect &SrcRect, con player->SetVideoRect(SrcRect, DestRect); } -void CAMLPlayer::GetRenderFeatures(std::vector &renderFeatures) -{ - renderFeatures.push_back(RENDERFEATURE_ZOOM); - renderFeatures.push_back(RENDERFEATURE_CONTRAST); - renderFeatures.push_back(RENDERFEATURE_BRIGHTNESS); - renderFeatures.push_back(RENDERFEATURE_STRETCH); -} - -void CAMLPlayer::GetDeinterlaceMethods(std::vector &deinterlaceMethods) -{ - deinterlaceMethods.push_back(VS_INTERLACEMETHOD_DEINTERLACE); -} - -void CAMLPlayer::GetDeinterlaceModes(std::vector &deinterlaceModes) -{ - deinterlaceModes.push_back(VS_DEINTERLACEMODE_AUTO); -} - -void CAMLPlayer::GetScalingMethods(std::vector &scalingMethods) -{ -} - -void CAMLPlayer::GetAudioCapabilities(std::vector &audioCaps) -{ - audioCaps.push_back(IPC_AUD_SELECT_STREAM); - audioCaps.push_back(IPC_AUD_SELECT_OUTPUT); -#if !defined(TARGET_ANDROID) - audioCaps.push_back(IPC_AUD_OFFSET); -#endif -} - -void CAMLPlayer::GetSubtitleCapabilities(std::vector &subCaps) -{ - subCaps.push_back(IPC_SUBS_EXTERNAL); - subCaps.push_back(IPC_SUBS_SELECT); - subCaps.push_back(IPC_SUBS_OFFSET); -} - diff --git a/xbmc/cores/amlplayer/AMLPlayer.h b/xbmc/cores/amlplayer/AMLPlayer.h index 461f21637663b..a24c858a10116 100644 --- a/xbmc/cores/amlplayer/AMLPlayer.h +++ b/xbmc/cores/amlplayer/AMLPlayer.h @@ -160,14 +160,6 @@ class CAMLPlayer : public IPlayer, public CThread virtual bool SetPlayerState(CStdString state) {return false;}; virtual CStdString GetPlayingTitle() {return "";}; -/* - virtual void GetRenderFeatures(Features* renderFeatures); - virtual void GetDeinterlaceMethods(Features* deinterlaceMethods); - virtual void GetDeinterlaceModes(Features* deinterlaceModes); - virtual void GetScalingMethods(Features* scalingMethods); - virtual void GetAudioCapabilities(Features* audioCaps); - virtual void GetSubtitleCapabilities(Features* subCaps); -*/ virtual void GetRenderFeatures(std::vector &renderFeatures); virtual void GetDeinterlaceMethods(std::vector &deinterlaceMethods); From 5c5cf9bec3ec3c4b59982988698c263f16bb711d Mon Sep 17 00:00:00 2001 From: davilla Date: Sat, 13 Oct 2012 10:10:48 -0400 Subject: [PATCH 049/180] add RegisterRenderFeaturesCallBack so a video codec can control the render features without having to talk through player --- xbmc/cores/VideoRenderers/BaseRenderer.cpp | 6 +++ xbmc/cores/VideoRenderers/BaseRenderer.h | 23 +++-------- .../VideoRenderers/LinuxRendererGLES.cpp | 18 ++++++++- xbmc/cores/VideoRenderers/LinuxRendererGLES.h | 2 +- xbmc/cores/VideoRenderers/RenderFeatures.h | 39 +++++++++++++++++++ xbmc/cores/VideoRenderers/RenderManager.cpp | 6 +++ xbmc/cores/VideoRenderers/RenderManager.h | 1 + 7 files changed, 75 insertions(+), 20 deletions(-) create mode 100644 xbmc/cores/VideoRenderers/RenderFeatures.h diff --git a/xbmc/cores/VideoRenderers/BaseRenderer.cpp b/xbmc/cores/VideoRenderers/BaseRenderer.cpp index a54ff31a62b59..2a502fcafc91f 100644 --- a/xbmc/cores/VideoRenderers/BaseRenderer.cpp +++ b/xbmc/cores/VideoRenderers/BaseRenderer.cpp @@ -66,6 +66,12 @@ void CBaseRenderer::RegisterRenderUpdateCallBack(const void *ctx, RenderUpdateCa m_RenderUpdateCallBackCtx = ctx; } +void CBaseRenderer::RegisterRenderFeaturesCallBack(const void *ctx, RenderFeaturesCallBackFn fn) +{ + m_RenderFeaturesCallBackFn = fn; + m_RenderFeaturesCallBackCtx = ctx; +} + void CBaseRenderer::ChooseBestResolution(float fps) { if (fps == 0.0) return; diff --git a/xbmc/cores/VideoRenderers/BaseRenderer.h b/xbmc/cores/VideoRenderers/BaseRenderer.h index 81d21d86041c0..21952c8cfe6b1 100644 --- a/xbmc/cores/VideoRenderers/BaseRenderer.h +++ b/xbmc/cores/VideoRenderers/BaseRenderer.h @@ -23,6 +23,7 @@ #include "guilib/Resolution.h" #include "guilib/Geometry.h" #include "RenderFormats.h" +#include "RenderFeatures.h" #define MAX_PLANES 3 #define MAX_FIELDS 3 @@ -48,24 +49,8 @@ enum EFIELDSYNC FS_BOT }; -enum ERENDERFEATURE -{ - RENDERFEATURE_GAMMA, - RENDERFEATURE_BRIGHTNESS, - RENDERFEATURE_CONTRAST, - RENDERFEATURE_NOISE, - RENDERFEATURE_SHARPNESS, - RENDERFEATURE_NONLINSTRETCH, - RENDERFEATURE_ROTATION, - RENDERFEATURE_STRETCH, - RENDERFEATURE_CROP, - RENDERFEATURE_ZOOM, - RENDERFEATURE_VERTICAL_SHIFT, - RENDERFEATURE_PIXEL_RATIO, - RENDERFEATURE_POSTPROCESS -}; - typedef void (*RenderUpdateCallBackFn)(const void *ctx, const CRect &SrcRect, const CRect &DestRect); +typedef void (*RenderFeaturesCallBackFn)(const void *ctx, Features &renderFeatures); struct DVDVideoPicture; @@ -91,6 +76,7 @@ class CBaseRenderer std::vector SupportedFormats() { return std::vector(); } virtual void RegisterRenderUpdateCallBack(const void *ctx, RenderUpdateCallBackFn fn); + virtual void RegisterRenderFeaturesCallBack(const void *ctx, RenderFeaturesCallBackFn fn); protected: void ChooseBestResolution(float fps); @@ -131,4 +117,7 @@ class CBaseRenderer const void* m_RenderUpdateCallBackCtx; RenderUpdateCallBackFn m_RenderUpdateCallBackFn; + + const void* m_RenderFeaturesCallBackCtx; + RenderFeaturesCallBackFn m_RenderFeaturesCallBackFn; }; diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp index cb0939fef6c2a..073c0b080d3e7 100644 --- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp +++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp @@ -193,10 +193,22 @@ bool CLinuxRendererGLES::Configure(unsigned int width, unsigned int height, unsi m_RenderUpdateCallBackCtx = NULL; if ((m_format == RENDER_FMT_BYPASS) && g_application.GetCurrentPlayer()) { + m_renderFeatures.clear(); + m_scalingMethods.clear(); + m_deinterlaceModes.clear(); + m_deinterlaceMethods.clear(); + + if (m_RenderFeaturesCallBackFn) + { + (*m_RenderFeaturesCallBackFn)(m_RenderFeaturesCallBackCtx, m_renderFeatures); + // after setting up m_renderFeatures, we are done with the callback + m_RenderFeaturesCallBackFn = NULL; + m_RenderFeaturesCallBackCtx = NULL; + } g_application.m_pPlayer->GetRenderFeatures(m_renderFeatures); - g_application.m_pPlayer->GetDeinterlaceMethods(m_deinterlaceMethods); - g_application.m_pPlayer->GetDeinterlaceModes(m_deinterlaceModes); g_application.m_pPlayer->GetScalingMethods(m_scalingMethods); + g_application.m_pPlayer->GetDeinterlaceModes(m_deinterlaceModes); + g_application.m_pPlayer->GetDeinterlaceMethods(m_deinterlaceMethods); } return true; @@ -749,6 +761,8 @@ void CLinuxRendererGLES::UnInit() m_bConfigured = false; m_RenderUpdateCallBackFn = NULL; m_RenderUpdateCallBackCtx = NULL; + m_RenderFeaturesCallBackFn = NULL; + m_RenderFeaturesCallBackCtx = NULL; } inline void CLinuxRendererGLES::ReorderDrawPoints() diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h index 76b543762b97e..8953de47d72a6 100644 --- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h +++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h @@ -29,6 +29,7 @@ #include "xbmc/guilib/Shader.h" #include "settings/VideoSettings.h" #include "RenderFlags.h" +#include "RenderFeatures.h" #include "guilib/GraphicContext.h" #include "BaseRenderer.h" #include "xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h" @@ -39,7 +40,6 @@ class CBaseTexture; namespace Shaders { class BaseYUV2RGBShader; } namespace Shaders { class BaseVideoFilterShader; } class COpenMaxVideo; -typedef std::vector Features; #define NUM_BUFFERS 3 diff --git a/xbmc/cores/VideoRenderers/RenderFeatures.h b/xbmc/cores/VideoRenderers/RenderFeatures.h new file mode 100644 index 0000000000000..82c2800c70a96 --- /dev/null +++ b/xbmc/cores/VideoRenderers/RenderFeatures.h @@ -0,0 +1,39 @@ +#pragma once +/* + * Copyright (C) 2005-2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +enum ERENDERFEATURE +{ + RENDERFEATURE_GAMMA, + RENDERFEATURE_BRIGHTNESS, + RENDERFEATURE_CONTRAST, + RENDERFEATURE_NOISE, + RENDERFEATURE_SHARPNESS, + RENDERFEATURE_NONLINSTRETCH, + RENDERFEATURE_ROTATION, + RENDERFEATURE_STRETCH, + RENDERFEATURE_CROP, + RENDERFEATURE_ZOOM, + RENDERFEATURE_VERTICAL_SHIFT, + RENDERFEATURE_PIXEL_RATIO, + RENDERFEATURE_POSTPROCESS +}; + +typedef std::vector Features; diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp index bbdfd35c03ab2..86c5a38ef6d15 100644 --- a/xbmc/cores/VideoRenderers/RenderManager.cpp +++ b/xbmc/cores/VideoRenderers/RenderManager.cpp @@ -661,6 +661,12 @@ void CXBMCRenderManager::RegisterRenderUpdateCallBack(const void *ctx, RenderUpd m_pRenderer->RegisterRenderUpdateCallBack(ctx, fn); } +void CXBMCRenderManager::RegisterRenderFeaturesCallBack(const void *ctx, RenderFeaturesCallBackFn fn) +{ + if (m_pRenderer) + m_pRenderer->RegisterRenderFeaturesCallBack(ctx, fn); +} + void CXBMCRenderManager::Render(bool clear, DWORD flags, DWORD alpha) { CSharedLock lock(m_sharedSection); diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h index 1d05bb419d39b..e28001ce13ce9 100644 --- a/xbmc/cores/VideoRenderers/RenderManager.h +++ b/xbmc/cores/VideoRenderers/RenderManager.h @@ -133,6 +133,7 @@ class CXBMCRenderManager CSharedSection& GetSection() { return m_sharedSection; }; void RegisterRenderUpdateCallBack(const void *ctx, RenderUpdateCallBackFn fn); + void RegisterRenderFeaturesCallBack(const void *ctx, RenderFeaturesCallBackFn fn); protected: void Render(bool clear, DWORD flags, DWORD alpha); From f0f9c83e7006b068e9d21fe6bc0d6de06e47eaf8 Mon Sep 17 00:00:00 2001 From: davilla Date: Sat, 13 Oct 2012 10:12:03 -0400 Subject: [PATCH 050/180] add method to access dvdclock used by players without having to talk though the player class --- xbmc/cores/dvdplayer/DVDClock.cpp | 15 +++++++++++++-- xbmc/cores/dvdplayer/DVDClock.h | 3 ++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/xbmc/cores/dvdplayer/DVDClock.cpp b/xbmc/cores/dvdplayer/DVDClock.cpp index 9eb744f170eb9..a523d5b2928b2 100644 --- a/xbmc/cores/dvdplayer/DVDClock.cpp +++ b/xbmc/cores/dvdplayer/DVDClock.cpp @@ -28,8 +28,8 @@ int64_t CDVDClock::m_systemOffset; int64_t CDVDClock::m_systemFrequency; CCriticalSection CDVDClock::m_systemsection; - bool CDVDClock::m_ismasterclock; +CDVDClock *CDVDClock::m_playerclock = NULL;; CDVDClock::CDVDClock() { @@ -45,10 +45,15 @@ CDVDClock::CDVDClock() m_ismasterclock = true; m_startClock = 0; + + m_playerclock = this; } CDVDClock::~CDVDClock() -{} +{ + CSingleLock lock(m_systemsection); + m_playerclock = NULL; +} // Returns the current absolute clock in units of DVD_TIME_BASE (usually microseconds). double CDVDClock::GetAbsoluteClock(bool interpolated /*= true*/) @@ -90,6 +95,12 @@ double CDVDClock::WaitAbsoluteClock(double target) return (double)systemtarget / freq * DVD_TIME_BASE; } +CDVDClock* CDVDClock::GetMasterClock() +{ + CSingleLock lock(m_systemsection); + return m_playerclock; +} + double CDVDClock::GetClock(bool interpolated /*= true*/) { CSharedLock lock(m_critSection); diff --git a/xbmc/cores/dvdplayer/DVDClock.h b/xbmc/cores/dvdplayer/DVDClock.h index dbf431b94d51a..27b9fc5385e41 100644 --- a/xbmc/cores/dvdplayer/DVDClock.h +++ b/xbmc/cores/dvdplayer/DVDClock.h @@ -66,7 +66,7 @@ class CDVDClock //the rendermanager needs to know about that because it can synchronize the videoreferenceclock to the video timestamps static void SetMasterClock(bool ismasterclock) { m_ismasterclock = ismasterclock; } static bool IsMasterClock() { return m_ismasterclock; } - + static CDVDClock* GetMasterClock(); protected: static void CheckSystemClock(); static double SystemToAbsolute(int64_t system); @@ -87,4 +87,5 @@ class CDVDClock bool m_speedadjust; CCriticalSection m_speedsection; static bool m_ismasterclock; + static CDVDClock *m_playerclock; }; From d8ee7db3e80180edafa3f40226c8a5a3be5733cf Mon Sep 17 00:00:00 2001 From: davilla Date: Fri, 16 Nov 2012 09:40:53 -0500 Subject: [PATCH 051/180] [aml] fixed build, audio_set_delay exists in our ics/android --- xbmc/cores/amlplayer/DllLibamplayer.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/xbmc/cores/amlplayer/DllLibamplayer.h b/xbmc/cores/amlplayer/DllLibamplayer.h index e6f87d4eb19f3..200691b42582e 100644 --- a/xbmc/cores/amlplayer/DllLibamplayer.h +++ b/xbmc/cores/amlplayer/DllLibamplayer.h @@ -63,9 +63,8 @@ class DllLibAmplayerInterface virtual char* player_status2str(player_status status)=0; virtual int audio_set_volume(int pid,float val)=0; -#if !defined(TARGET_ANDROID) virtual int audio_set_delay(int pid, int delay)=0; -#endif + virtual int codec_open_sub_read(void)=0; virtual int codec_close_sub_fd(int sub_fd)=0; virtual int codec_get_sub_size_fd(int sub_fd)=0; @@ -105,9 +104,7 @@ class DllLibAmplayer : public DllDynamic, DllLibAmplayerInterface DEFINE_METHOD1(char*, player_status2str, (player_status p1)) DEFINE_METHOD2(int, audio_set_volume, (int p1, float p2)) -#if !defined(TARGET_ANDROID) DEFINE_METHOD2(int, audio_set_delay, (int p1, int p2)) -#endif DEFINE_METHOD0(int, codec_open_sub_read) DEFINE_METHOD1(int, codec_close_sub_fd, (int p1)) @@ -144,9 +141,8 @@ class DllLibAmplayer : public DllDynamic, DllLibAmplayerInterface RESOLVE_METHOD(player_status2str) RESOLVE_METHOD(audio_set_volume) -#if !defined(TARGET_ANDROID) RESOLVE_METHOD(audio_set_delay) -#endif + RESOLVE_METHOD(codec_open_sub_read) RESOLVE_METHOD(codec_close_sub_fd) RESOLVE_METHOD(codec_get_sub_size_fd) From 72a9b8a2ccaa241135e8f4360b97e74cb4f7d5b7 Mon Sep 17 00:00:00 2001 From: davilla Date: Fri, 30 Nov 2012 14:20:23 -0500 Subject: [PATCH 052/180] [aml] fixed, revert mainline thread priority breakage until we fix buildroot --- xbmc/threads/platform/pthreads/ThreadImpl.cpp | 102 +++++------------- 1 file changed, 29 insertions(+), 73 deletions(-) diff --git a/xbmc/threads/platform/pthreads/ThreadImpl.cpp b/xbmc/threads/platform/pthreads/ThreadImpl.cpp index d10628e9846de..50853bf7f24e3 100644 --- a/xbmc/threads/platform/pthreads/ThreadImpl.cpp +++ b/xbmc/threads/platform/pthreads/ThreadImpl.cpp @@ -71,35 +71,10 @@ void CThread::SetThreadInfo() m_ThreadOpaque.LwpId = syscall(SYS_gettid); #endif -#ifdef TARGET_DARWIN -#if(__MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 || __IPHONE_OS_VERSION_MIN_REQUIRED >= 30200) - pthread_setname_np(m_ThreadName.c_str()); -#endif -#endif - -#ifdef RLIMIT_NICE - // get user max prio - struct rlimit limit; - int userMaxPrio; - if (getrlimit(RLIMIT_NICE, &limit) == 0) - { - userMaxPrio = limit.rlim_cur - 20; - if (userMaxPrio < 0) - userMaxPrio = 0; - } - else - userMaxPrio = 0; - - // if the user does not have an entry in limits.conf the following - // call will fail - if (userMaxPrio > 0) - { - // start thread with nice level of appication - int appNice = getpriority(PRIO_PROCESS, getpid()); - if (setpriority(PRIO_PROCESS, m_ThreadOpaque.LwpId, appNice) != 0) - if (logger) logger->Log(LOGERROR, "%s: error %s", __FUNCTION__, strerror(errno)); - } -#endif + // start thread with nice level of appication + int appNice = getpriority(PRIO_PROCESS, getpid()); + if (setpriority(PRIO_PROCESS, m_ThreadOpaque.LwpId, appNice) != 0) + if (logger) logger->Log(LOGERROR, "%s: error %s", __FUNCTION__, strerror(errno)); } ThreadIdentifier CThread::GetCurrentThreadId() @@ -114,24 +89,25 @@ bool CThread::IsCurrentThread(const ThreadIdentifier tid) int CThread::GetMinPriority(void) { - // one level lower than application - return -1; + return -4; + //return THREAD_PRIORITY_IDLE; } int CThread::GetMaxPriority(void) { - // one level higher than application - return 1; + return 4; +// return THREAD_PRIORITY_HIGHEST; } int CThread::GetNormalPriority(void) { - // same level as application return 0; + //return THREAD_PRIORITY_NORMAL; } bool CThread::SetPriority(const int iPriority) { + // iPriority is with respect to that defined in Thread.h bool bReturn = false; // wait until thread is running, it needs to get its lwp id @@ -139,47 +115,25 @@ bool CThread::SetPriority(const int iPriority) CSingleLock lock(m_CriticalSection); - // get min prio for SCHED_RR - int minRR = GetMaxPriority() + 1; - if (!m_ThreadId) - bReturn = false; - else if (iPriority >= minRR) - bReturn = SetPrioritySched_RR(iPriority); -#ifdef RLIMIT_NICE + return false; + + // keep priority in bounds + int prio = iPriority; + if (prio >= GetMaxPriority()) + prio = GetMaxPriority(); + if (prio < GetMinPriority()) + prio = GetMinPriority(); + + // nice level of application + int appNice = getpriority(PRIO_PROCESS, getpid()); + // flip it with respect to the 'nice' levels (-20 to 19) + prio = appNice - prio; + + if (setpriority(PRIO_PROCESS, m_ThreadOpaque.LwpId, prio) == 0) + bReturn = true; else - { - // get user max prio - struct rlimit limit; - int userMaxPrio; - if (getrlimit(RLIMIT_NICE, &limit) == 0) - { - userMaxPrio = limit.rlim_cur - 20; - // is a user has no entry in limits.conf rlim_cur is zero - if (userMaxPrio < 0) - userMaxPrio = 0; - } - else - userMaxPrio = 0; - - // keep priority in bounds - int prio = iPriority; - if (prio >= GetMaxPriority()) - prio = std::min(GetMaxPriority(), userMaxPrio); - if (prio < GetMinPriority()) - prio = GetMinPriority(); - - // nice level of application - int appNice = getpriority(PRIO_PROCESS, getpid()); - if (prio) - prio = prio > 0 ? appNice-1 : appNice+1; - - if (setpriority(PRIO_PROCESS, m_ThreadOpaque.LwpId, prio) == 0) - bReturn = true; - else - if (logger) logger->Log(LOGERROR, "%s: error %s", __FUNCTION__, strerror(errno)); - } -#endif + if (logger) logger->Log(LOGERROR, "%s: error %s", __FUNCTION__, strerror(errno)); return bReturn; } @@ -195,6 +149,8 @@ int CThread::GetPriority() int appNice = getpriority(PRIO_PROCESS, getpid()); int prio = getpriority(PRIO_PROCESS, m_ThreadOpaque.LwpId); + // flip it with respect to the 'nice' levels (-20 to 19), so that + // what is returned is with repect to that defined in Thread.h iReturn = appNice - prio; return iReturn; From d66781acf8d42c8220adf01f865fa517b0ff2c95 Mon Sep 17 00:00:00 2001 From: davilla Date: Mon, 26 Nov 2012 13:43:13 -0500 Subject: [PATCH 053/180] [aml] tmp commit 1548.patch --- xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp index 91218a48c3d4d..7543d8bb65fb7 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp @@ -333,7 +333,7 @@ bool CAESinkALSA::InitializeHW(AEAudioFormat &format) snd_pcm_uframes_t periodSize, bufferSize; snd_pcm_hw_params_get_buffer_size_max(hw_params, &bufferSize); - bufferSize = std::min(bufferSize, (snd_pcm_uframes_t)8192); + bufferSize = std::max(bufferSize, (snd_pcm_uframes_t)8192); periodSize = bufferSize / ALSA_PERIODS; periods = ALSA_PERIODS; From a56a66fa64e363901d50e43aee8c49980165fc3e Mon Sep 17 00:00:00 2001 From: davilla Date: Thu, 11 Oct 2012 11:12:57 -0400 Subject: [PATCH 054/180] [aml] add DVDVideoCodecAmlogic --- configure.in | 29 + tools/amlogic/depends/xbmc/xbmc.mk | 2 +- .../libamplayer/libamplayer/include/codec.h | 93 + .../libamplayer/include/codec_error.h | 37 + .../libamplayer/include/codec_msg.h | 19 + .../libamplayer/include/codec_type.h | 108 + xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 4 +- .../dvdplayer/DVDCodecs/DVDFactoryCodec.cpp | 20 +- .../dvdplayer/DVDCodecs/Video/Amlogic.cpp | 1907 +++++++++++++++++ .../cores/dvdplayer/DVDCodecs/Video/Amlogic.h | 81 + .../DVDCodecs/Video/DVDVideoCodecAmlogic.cpp | 183 ++ .../DVDCodecs/Video/DVDVideoCodecAmlogic.h | 51 + .../dvdplayer/DVDCodecs/Video/Makefile.in | 6 + xbmc/cores/dvdplayer/DVDPlayer.cpp | 2 + 14 files changed, 2538 insertions(+), 4 deletions(-) create mode 100644 tools/android/depends/libamplayer/libamplayer/include/codec.h create mode 100644 tools/android/depends/libamplayer/libamplayer/include/codec_error.h create mode 100644 tools/android/depends/libamplayer/libamplayer/include/codec_msg.h create mode 100644 tools/android/depends/libamplayer/libamplayer/include/codec_type.h create mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.cpp create mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.h create mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp create mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h diff --git a/configure.in b/configure.in index 6087284c462ee..dd6409c9542ac 100644 --- a/configure.in +++ b/configure.in @@ -30,6 +30,21 @@ AC_DEFUN([XB_ADD_PLAYER], esac ]) +# check for enabling additional codecs +AC_DEFUN([XB_ADD_CODEC], +[ + AC_MSG_CHECKING([for $2]) + case $add_codecs in + *$2*) + AC_SUBST([USE_$1], 1) + AC_DEFINE([HAS_$1], 1, [using $2]) + AC_MSG_RESULT([enabling $2]) + ;; + *) + AC_MSG_RESULT([$2 is not enabled]) + esac +]) + # check for library basenames AC_DEFUN([XB_FIND_SONAME], [ @@ -507,6 +522,12 @@ AC_ARG_ENABLE([gtest], [configure_gtest=$enableval], [configure_gtest=no]) +AC_ARG_ENABLE([codec], + [AS_HELP_STRING([--enable-codec], + [enable additional codecs from a list of comma separated names, (default is none, choices are amcodec)])], + [add_codecs=$enableval], + [add_codecs=no]) + ### External libraries options AC_ARG_ENABLE([external-libraries], [AS_HELP_STRING([--enable-external-libraries], @@ -1832,6 +1853,14 @@ case $add_players in ;; esac +# additional internal codecs +case $add_codecs in + *amcodec*) + AC_CHECK_HEADER([amlplayer/codec_error.h],, AC_MSG_ERROR($missing_headers)) + XB_ADD_CODEC([LIBAMCODEC], [amcodec]) + ;; +esac + # platform specific bin utilities if test "$host_vendor" != "apple" ; then AC_CHECK_PROG(HAVE_GAWK,gawk,"yes","no",) diff --git a/tools/amlogic/depends/xbmc/xbmc.mk b/tools/amlogic/depends/xbmc/xbmc.mk index da2ae74b1bc6e..bc3191bfc5ec7 100644 --- a/tools/amlogic/depends/xbmc/xbmc.mk +++ b/tools/amlogic/depends/xbmc/xbmc.mk @@ -9,7 +9,7 @@ $(SOURCE)/xbmc.bin: $(SOURCE)/Makefile $(SOURCE)/Makefile: $(SOURCE)/configure cd $(SOURCE); $(TARGET_CONFIGURE_OPTS) $(TARGET_CONFIGURE_ARGS) $(XBMC_CONF_ENV) \ ./configure --target=$(GNU_TARGET_NAME) --host=$(GNU_TARGET_NAME) --build=$(GNU_HOST_NAME) \ - --prefix=/usr --exec-prefix=/usr --sysconfdir=/etc $(XBMC_CONF_OPT) --disable-external-ffmpeg + --prefix=/usr --exec-prefix=/usr --sysconfdir=/etc $(XBMC_CONF_OPT) --disable-external-ffmpeg --enable-codec=amcodec $(SOURCE)/configure: $(BUILDROOT)/package/thirdparty/xbmc/xbmc.mk $(GCC) cd $(SOURCE); ./bootstrap diff --git a/tools/android/depends/libamplayer/libamplayer/include/codec.h b/tools/android/depends/libamplayer/libamplayer/include/codec.h new file mode 100644 index 0000000000000..187d4d5c82531 --- /dev/null +++ b/tools/android/depends/libamplayer/libamplayer/include/codec.h @@ -0,0 +1,93 @@ +/** +* @file codec.h +* @brief Function prototypes of codec lib +* @author Zhang Chen +* @version 1.0.0 +* @date 2011-02-24 +*/ +/* Copyright (C) 2007-2011, Amlogic Inc. +* All right reserved +* +*/ +#ifndef CODEC_CTRL_H_ +#define CODEC_CTRL_H_ + +#include +#include + + +int codec_init(codec_para_t *); +int codec_close(codec_para_t *); +void codec_audio_basic_init(void); +void codec_close_audio(codec_para_t *); +void codec_resume_audio(codec_para_t *, unsigned int); +int codec_reset(codec_para_t *); +int codec_init_sub(codec_para_t *); +int codec_open_sub_read(void); +int codec_close_sub(codec_para_t *); +int codec_close_sub_fd(CODEC_HANDLE); +int codec_reset_subtile(codec_para_t *pcodec); +int codec_poll_sub(codec_para_t *); +int codec_poll_sub_fd(CODEC_HANDLE, int); +int codec_get_sub_size(codec_para_t *); +int codec_get_sub_size_fd(CODEC_HANDLE); +int codec_read_sub_data(codec_para_t *, char *, unsigned int); +int codec_read_sub_data_fd(CODEC_HANDLE, char *, unsigned int); +int codec_write_sub_data(codec_para_t *, char *, unsigned int); +int codec_init_cntl(codec_para_t *); +int codec_close_cntl(codec_para_t *); +int codec_poll_cntl(codec_para_t *); +int codec_get_cntl_state(codec_para_t *); +int codec_set_cntl_mode(codec_para_t *, unsigned int); +int codec_set_cntl_avthresh(codec_para_t *, unsigned int); +int codec_set_cntl_syncthresh(codec_para_t *pcodec, unsigned int syncthresh); +int codec_reset_audio(codec_para_t *pcodec); +int codec_set_audio_pid(codec_para_t *pcodec); +int codec_set_sub_id(codec_para_t *pcodec); +int codec_set_sub_type(codec_para_t *pcodec); +int codec_audio_reinit(codec_para_t *pcodec); +int codec_set_dec_reset(codec_para_t *pcodec); + +int codec_write(codec_para_t *pcodec, void *buffer, int len); +int codec_checkin_pts(codec_para_t *pcodec, unsigned long pts); +int codec_get_vbuf_state(codec_para_t *, struct buf_status *); +int codec_get_abuf_state(codec_para_t *, struct buf_status *); +int codec_get_vdec_state(codec_para_t *, struct vdec_status *); +int codec_get_adec_state(codec_para_t *, struct adec_status *); + +int codec_pause(codec_para_t *); +int codec_resume(codec_para_t *); +int codec_audio_search(codec_para_t *p); +int codec_set_mute(codec_para_t *p, int mute); +int codec_get_volume_range(codec_para_t *, int *min, int *max); +int codec_set_volume(codec_para_t *, float val); +int codec_get_volume(codec_para_t *, float *val); +int codec_set_lrvolume(codec_para_t *, float lvol,float rvol); +int codec_get_lrvolume(codec_para_t *, float *lvol,float* rvol); +int codec_get_mutesta(codec_para_t *); +int codec_set_volume_balance(codec_para_t *, int); /*left£¨0-100)right*/ +int codec_swap_left_right(codec_para_t *); +int codec_left_mono(codec_para_t *p); +int codec_right_mono(codec_para_t *p); +int codec_stereo(codec_para_t *p); +int codec_get_soundtrack(codec_para_t *p,int* strack); +int codec_audio_automute(void *priv, int auto_mute); +int codec_audio_spectrum_switch(codec_para_t *p, int isStart, int interval); +int codec_audio_isready(codec_para_t *p); +int codec_audio_get_nb_frames(codec_para_t *p); +int codec_audio_set_audioinfo(codec_para_t *p); + +int codec_get_apts(codec_para_t *pcodec); +int codec_get_vpts(codec_para_t *pcodec); +int codec_get_pcrscr(codec_para_t *pcodec); +int codec_set_pcrscr(codec_para_t *pcodec, int val); +int codec_set_syncenable(codec_para_t *pcodec, int enable); +int codec_set_sync_audio_discont(codec_para_t *pcodec, int discontinue); +int codec_get_sync_audio_discont(codec_para_t *pcodec); +int codec_set_sync_video_discont(codec_para_t *pcodec, int discontinue); +int codec_get_sync_video_discont(codec_para_t *pcodec); + +int codec_get_sub_num(codec_para_t *pcodec); +int codec_get_sub_info(codec_para_t *pcodec, subtitle_info_t *sub_info); + +#endif diff --git a/tools/android/depends/libamplayer/libamplayer/include/codec_error.h b/tools/android/depends/libamplayer/libamplayer/include/codec_error.h new file mode 100644 index 0000000000000..0d6df8fdf4ff4 --- /dev/null +++ b/tools/android/depends/libamplayer/libamplayer/include/codec_error.h @@ -0,0 +1,37 @@ +/** +* @file codec_error.h +* @brief Codec error type definitions +* @author Zhang Chen +* @version 1.0.0 +* @date 2011-02-24 +*/ +/* Copyright (C) 2007-2011, Amlogic Inc. +* All right reserved +* +*/ + +#ifndef CODEC_ERROR_H_ +#define CODEC_ERROR_H_ + +#define C_PAE (0x01000000) + +#define CODEC_ERROR_NONE ( 0) +#define CODEC_ERROR_INVAL (C_PAE | 1) +#define CODEC_ERROR_NOMEM (C_PAE | 2) +#define CODEC_ERROR_BUSY (C_PAE | 3) +#define CODEC_ERROR_IO (C_PAE | 4) +#define CODEC_ERROR_PARAMETER (C_PAE | 5) +#define CODEC_ERROR_AUDIO_TYPE_UNKNOW (C_PAE | 6) +#define CODEC_ERROR_VIDEO_TYPE_UNKNOW (C_PAE | 7) +#define CODEC_ERROR_STREAM_TYPE_UNKNOW (C_PAE | 8) +#define CODEC_ERROR_VDEC_TYPE_UNKNOW (C_PAE | 9) + +#define CODEC_ERROR_INIT_FAILED (C_PAE | 10) +#define CODEC_ERROR_SET_BUFSIZE_FAILED (C_PAE | 11) +#define CODEC_OPEN_HANDLE_FAILED (C_PAE | 12) + + + + +#endif + diff --git a/tools/android/depends/libamplayer/libamplayer/include/codec_msg.h b/tools/android/depends/libamplayer/libamplayer/include/codec_msg.h new file mode 100644 index 0000000000000..f898af3756fa6 --- /dev/null +++ b/tools/android/depends/libamplayer/libamplayer/include/codec_msg.h @@ -0,0 +1,19 @@ +/** +* @file codec_msg.h +* @brief Function prototype of codec error +* @author Zhang Chen +* @version 1.0.0 +* @date 2011-02-24 +*/ +/* Copyright (C) 2007-2011, Amlogic Inc. +* All right reserved +* +*/ +#ifndef CODEC_MSG_H +#define CODEC_MSG_H + +const char * codec_error_msg(int error); +int system_error_to_codec_error(int error); +void print_error_msg(int error, int syserr, char *func, int line); + +#endif diff --git a/tools/android/depends/libamplayer/libamplayer/include/codec_type.h b/tools/android/depends/libamplayer/libamplayer/include/codec_type.h new file mode 100644 index 0000000000000..5d61ca8722312 --- /dev/null +++ b/tools/android/depends/libamplayer/libamplayer/include/codec_type.h @@ -0,0 +1,108 @@ +/** +* @file codec_type.h +* @brief Definitions of codec type and structures +* @author Zhang Chen +* @version 1.0.0 +* @date 2011-02-24 +*/ +/* Copyright (C) 2007-2011, Amlogic Inc. +* All right reserved +* +*/ +#ifndef CODEC_TYPE_H_ +#define CODEC_TYPE_H_ + +#include "amports/amstream.h" +#include "amports/vformat.h" +#include "amports/aformat.h" + +typedef int CODEC_HANDLE; + +typedef enum { + STREAM_TYPE_UNKNOW, + STREAM_TYPE_ES_VIDEO, + STREAM_TYPE_ES_AUDIO, + STREAM_TYPE_ES_SUB, + STREAM_TYPE_PS, + STREAM_TYPE_TS, + STREAM_TYPE_RM, +} stream_type_t; + +typedef struct { + unsigned int format; ///< video format, such as H264, MPEG2... + unsigned int width; ///< video source width + unsigned int height; ///< video source height + unsigned int rate; ///< video source frame duration + unsigned int extra; ///< extra data information of video stream + unsigned int status; ///< status of video stream + unsigned int ratio; ///< aspect ratio of video source + void * param; ///< other parameters for video decoder + unsigned long long ratio64; ///< aspect ratio of video source +} dec_sysinfo_t; + +typedef struct { + int valid; ///< audio extradata valid(1) or invalid(0), set by dsp + int sample_rate; ///< audio stream sample rate + int channels; ///< audio stream channels + int bitrate; ///< audio stream bit rate + int codec_id; ///< codec format id + int block_align; ///< audio block align from ffmpeg + int extradata_size; ///< extra data size + char extradata[AUDIO_EXTRA_DATA_SIZE]; ///< extra data information for decoder +} audio_info_t; + +typedef struct { + CODEC_HANDLE handle; ///< codec device handler + CODEC_HANDLE cntl_handle; ///< video control device handler + CODEC_HANDLE sub_handle; ///< subtile device handler + stream_type_t stream_type; ///< stream type(es, ps, rm, ts) + unsigned int has_video:1; ///< stream has video(1) or not(0) + unsigned int has_audio:1; ///< stream has audio(1) or not(0) + unsigned int has_sub:1; ///< stream has subtitle(1) or not(0) + unsigned int noblock:1; ///< codec device is NONBLOCK(1) or not(0) + int video_type; ///< stream video type(H264, VC1...) + int audio_type; ///< stream audio type(PCM, WMA...) + int sub_type; ///< stream subtitle type(TXT, SSA...) + int video_pid; ///< stream video pid + int audio_pid; ///< stream audio pid + int sub_pid; ///< stream subtitle pid + int audio_channels; ///< stream audio channel number + int audio_samplerate; ///< steram audio sample rate + int vbuf_size; ///< video buffer size of codec device + int abuf_size; ///< audio buffer size of codec device + dec_sysinfo_t am_sysinfo; ///< system information for video + audio_info_t audio_info; ///< audio information pass to audiodsp + int packet_size; ///< data size per packet + int avsync_threshold; /// + void * adec_priv; /// +} codec_para_t; + +typedef struct +{ + signed char id; + unsigned char width; + unsigned char height; + unsigned char type; +} subtitle_info_t; +#define MAX_SUB_NUM (32) + +#define IS_VALID_PID(t) (t>=0 && t<=0x1fff) +#define IS_VALID_STREAM(t) (t>0 && t<=0x1fff) +#define IS_VALID_ATYPE(t) (t>=0 && t=0 && t +#include +#include +#include +#include +#include +#include +#include +#include + +// amcodec include +extern "C" { +#include +} // extern "C" + +class DllLibamCodecInterface +{ +public: + virtual ~DllLibamCodecInterface() {}; + + virtual int codec_init(codec_para_t *pcodec)=0; + virtual int codec_close(codec_para_t *pcodec)=0; + virtual int codec_reset(codec_para_t *pcodec)=0; + virtual int codec_pause(codec_para_t *pcodec)=0; + virtual int codec_resume(codec_para_t *pcodec)=0; + virtual int codec_write(codec_para_t *pcodec, void *buffer, int len)=0; + virtual int codec_checkin_pts(codec_para_t *pcodec, unsigned long pts)=0; + virtual int codec_get_vbuf_state(codec_para_t *pcodec, struct buf_status *)=0; + virtual int codec_set_volume(codec_para_t *pcodec, float val)=0; + virtual int codec_get_volume(codec_para_t *pcodec, float *val)=0; + + virtual int codec_init_cntl(codec_para_t *pcodec)=0; + virtual int codec_poll_cntl(codec_para_t *pcodec)=0; + virtual int codec_set_cntl_avthresh(codec_para_t *pcodec, unsigned int)=0; + virtual int codec_set_cntl_syncthresh(codec_para_t *pcodec, unsigned int syncthresh)=0; + + virtual int codec_audio_set_delay(codec_para_t *pcodec, int delay)=0; + + // grab these from libamplayer + virtual int h263vld(unsigned char *inbuf, unsigned char *outbuf, int inbuf_len, int s263)=0; + virtual int decodeble_h263(unsigned char *buf)=0; + + // grab this from amffmpeg so we do not have to load DllAvUtil + virtual AVRational av_d2q(double d, int max)=0; +}; + +class DllLibAmCodec : public DllDynamic, DllLibamCodecInterface +{ + // libamcodec is static linked into libamplayer.so + DECLARE_DLL_WRAPPER(DllLibAmCodec, "libamplayer.so") + + DEFINE_METHOD1(int, codec_init, (codec_para_t *p1)) + DEFINE_METHOD1(int, codec_close, (codec_para_t *p1)) + DEFINE_METHOD1(int, codec_reset, (codec_para_t *p1)) + DEFINE_METHOD1(int, codec_pause, (codec_para_t *p1)) + DEFINE_METHOD1(int, codec_resume, (codec_para_t *p1)) + DEFINE_METHOD3(int, codec_write, (codec_para_t *p1, void *p2, int p3)) + DEFINE_METHOD2(int, codec_checkin_pts, (codec_para_t *p1, unsigned long p2)) + DEFINE_METHOD2(int, codec_get_vbuf_state, (codec_para_t *p1, struct buf_status * p2)) + DEFINE_METHOD2(int, codec_set_volume, (codec_para_t *p1, float p2)) + DEFINE_METHOD2(int, codec_get_volume, (codec_para_t *p1, float *p2)) + + DEFINE_METHOD1(int, codec_init_cntl, (codec_para_t *p1)) + DEFINE_METHOD1(int, codec_poll_cntl, (codec_para_t *p1)) + DEFINE_METHOD2(int, codec_set_cntl_avthresh, (codec_para_t *p1, unsigned int p2)) + DEFINE_METHOD2(int, codec_set_cntl_syncthresh,(codec_para_t *p1, unsigned int p2)) + + DEFINE_METHOD2(int, codec_audio_set_delay, (codec_para_t *p1, int p2)) + + DEFINE_METHOD4(int, h263vld, (unsigned char *p1, unsigned char *p2, int p3, int p4)) + DEFINE_METHOD1(int, decodeble_h263, (unsigned char *p1)) + + DEFINE_METHOD2(AVRational, av_d2q, (double p1, int p2)) + + BEGIN_METHOD_RESOLVE() + RESOLVE_METHOD(codec_init) + RESOLVE_METHOD(codec_close) + RESOLVE_METHOD(codec_reset) + RESOLVE_METHOD(codec_pause) + RESOLVE_METHOD(codec_resume) + RESOLVE_METHOD(codec_write) + RESOLVE_METHOD(codec_checkin_pts) + RESOLVE_METHOD(codec_get_vbuf_state) + RESOLVE_METHOD(codec_set_volume) + RESOLVE_METHOD(codec_get_volume) + + RESOLVE_METHOD(codec_init_cntl) + RESOLVE_METHOD(codec_poll_cntl) + RESOLVE_METHOD(codec_set_cntl_avthresh) + RESOLVE_METHOD(codec_set_cntl_syncthresh) + + RESOLVE_METHOD(codec_audio_set_delay) + + RESOLVE_METHOD(h263vld) + RESOLVE_METHOD(decodeble_h263) + + RESOLVE_METHOD(av_d2q) + END_METHOD_RESOLVE() +}; + +//----------------------------------------------------------------------------------- +//----------------------------------------------------------------------------------- +// AppContext - Application state +#define PTS_FREQ 90000 +#define UNIT_FREQ 96000 +#define AV_SYNC_THRESH PTS_FREQ*30 + +#define TRICKMODE_NONE 0x00 +#define TRICKMODE_I 0x01 +#define TRICKMODE_FFFB 0x02 + +#define INT64_0 INT64_C(0x8000000000000000) + +#define EXTERNAL_PTS (1) +#define SYNC_OUTSIDE (2) + +// missing tags +#define CODEC_TAG_VC_1 (0x312D4356) + +#define RW_WAIT_TIME (20 * 1000) // 20ms + +#define P_PRE (0x02000000) +#define F_PRE (0x03000000) +#define PLAYER_SUCCESS (0) +#define PLAYER_FAILED (-(P_PRE|0x01)) +#define PLAYER_NOMEM (-(P_PRE|0x02)) +#define PLAYER_EMPTY_P (-(P_PRE|0x03)) + +#define PLAYER_WR_FAILED (-(P_PRE|0x21)) +#define PLAYER_WR_EMPTYP (-(P_PRE|0x22)) +#define PLAYER_WR_FINISH (P_PRE|0x1) + +#define PLAYER_PTS_ERROR (-(P_PRE|0x31)) +#define PLAYER_UNSUPPORT (-(P_PRE|0x35)) +#define PLAYER_CHECK_CODEC_ERROR (-(P_PRE|0x39)) + +#define HDR_BUF_SIZE 1024 +typedef struct hdr_buf { + char *data; + int size; +} hdr_buf_t; + +typedef struct am_packet { + AVPacket avpkt; + int64_t avpts; + int64_t avdts; + int avduration; + int isvalid; + int newflag; + int64_t lastpts; + unsigned char *data; + unsigned char *buf; + int data_size; + int buf_size; + hdr_buf_t *hdr; + codec_para_t *codec; +} am_packet_t; + +typedef enum { + AM_STREAM_UNKNOWN = 0, + AM_STREAM_TS, + AM_STREAM_PS, + AM_STREAM_ES, + AM_STREAM_RM, + AM_STREAM_AUDIO, + AM_STREAM_VIDEO, +} pstream_type; + +typedef union { + int64_t total_bytes; + unsigned int vpkt_num; + unsigned int spkt_num; +} read_write_size; + +typedef struct { + unsigned int read_end_flag: 1; + unsigned int end_flag: 1; + unsigned int reset_flag: 1; + int check_lowlevel_eagain_cnt; +} p_ctrl_info_t; + +typedef struct am_private_t +{ + am_packet_t am_pkt; + codec_para_t vcodec; + + pstream_type stream_type; + p_ctrl_info_t playctrl_info; + + read_write_size read_size; + read_write_size write_size; + int check_first_pts; + + vformat_t video_format; + int video_pid; + unsigned int video_codec_id; + unsigned int video_codec_tag; + vdec_type_t video_codec_type; + unsigned int video_width; + unsigned int video_height; + unsigned int video_ratio; + unsigned int video_ratio64; + unsigned int video_rate; + unsigned int video_rotation_degree; + int flv_flag; + int h263_decodable; + int extrasize; + uint8_t *extradata; + DllLibAmCodec *m_dll; +} am_private_t; + +/*************************************************************************/ +static int64_t get_pts_video() +{ + int fd = open("/sys/class/tsync/pts_video", O_RDONLY); + if (fd >= 0) + { + char pts_str[16]; + int size = read(fd, pts_str, sizeof(pts_str)); + close(fd); + if (size > 0) + { + unsigned long pts = strtoul(pts_str, NULL, 16); + return pts; + } + } + + CLog::Log(LOGERROR, "get_pts_video: open /tsync/event error"); + return -1; +} + +static int set_pts_pcrscr(int64_t value) +{ + int fd = open("/sys/class/tsync/pts_pcrscr", O_WRONLY); + if (fd >= 0) + { + char pts_str[64]; + unsigned long pts = (unsigned long)value; + sprintf(pts_str, "0x%lx", pts); + write(fd, pts_str, strlen(pts_str)); + close(fd); + return 0; + } + + CLog::Log(LOGERROR, "set_pts_pcrscr: open pts_pcrscr error"); + return -1; +} + +static vformat_t codecid_to_vformat(enum CodecID id) +{ + vformat_t format; + switch (id) + { + case CODEC_ID_MPEG1VIDEO: + case CODEC_ID_MPEG2VIDEO: + case CODEC_ID_MPEG2VIDEO_XVMC: + format = VFORMAT_MPEG12; + break; + case CODEC_ID_H263: + case CODEC_ID_MPEG4: + case CODEC_ID_H263P: + case CODEC_ID_H263I: + case CODEC_ID_MSMPEG4V2: + case CODEC_ID_MSMPEG4V3: + case CODEC_ID_FLV1: + format = VFORMAT_MPEG4; + break; + case CODEC_ID_RV10: + case CODEC_ID_RV20: + case CODEC_ID_RV30: + case CODEC_ID_RV40: + format = VFORMAT_REAL; + break; + case CODEC_ID_H264: + format = VFORMAT_H264; + break; + /* + case CODEC_ID_H264MVC: + // H264 Multiview Video Coding (3d blurays) + format = VFORMAT_H264MVC; + break; + */ + case CODEC_ID_MJPEG: + format = VFORMAT_MJPEG; + break; + case CODEC_ID_VC1: + case CODEC_ID_WMV3: + format = VFORMAT_VC1; + break; + case CODEC_ID_VP6F: + format = VFORMAT_SW; + break; + default: + format = VFORMAT_UNSUPPORT; + break; + } + + CLog::Log(LOGDEBUG, "codecid_to_vformat, format(%d), id(%d)", format, (int)id); + return format; +} + +static vdec_type_t codec_tag_to_vdec_type(unsigned int codec_tag) +{ + vdec_type_t dec_type; + switch (codec_tag) + { + case CODEC_TAG_XVID: + case CODEC_TAG_xvid: + case CODEC_TAG_XVIX: + dec_type = VIDEO_DEC_FORMAT_MPEG4_5; + break; + case CODEC_TAG_COL1: + case CODEC_TAG_DIV3: + case CODEC_TAG_MP43: + dec_type = VIDEO_DEC_FORMAT_MPEG4_3; + break; + case CODEC_TAG_DIV4: + case CODEC_TAG_DIVX: + dec_type = VIDEO_DEC_FORMAT_MPEG4_4; + break; + case CODEC_TAG_DIV5: + case CODEC_TAG_DX50: + case CODEC_TAG_M4S2: + case CODEC_TAG_FMP4: + dec_type = VIDEO_DEC_FORMAT_MPEG4_5; + break; + case CODEC_TAG_DIV6: + dec_type = VIDEO_DEC_FORMAT_MPEG4_5; + break; + case CODEC_TAG_MP4V: + case CODEC_TAG_RMP4: + case CODEC_TAG_MPG4: + case CODEC_TAG_mp4v: + case CODEC_ID_MPEG4: + dec_type = VIDEO_DEC_FORMAT_MPEG4_5; + break; + case CODEC_ID_H263: + case CODEC_TAG_H263: + case CODEC_TAG_h263: + case CODEC_TAG_s263: + case CODEC_TAG_F263: + dec_type = VIDEO_DEC_FORMAT_H263; + break; + case CODEC_TAG_AVC1: + case CODEC_TAG_avc1: + case CODEC_TAG_H264: + case CODEC_TAG_h264: + dec_type = VIDEO_DEC_FORMAT_H264; + break; + case CODEC_ID_RV30: + dec_type = VIDEO_DEC_FORMAT_REAL_8; + break; + case CODEC_ID_RV40: + dec_type = VIDEO_DEC_FORMAT_REAL_9; + break; + case CODEC_ID_H264: + dec_type = VIDEO_DEC_FORMAT_H264; + break; + /* + case CODEC_ID_H264MVC: + dec_type = VIDEO_DEC_FORMAT_H264; + break; + */ + case CODEC_TAG_WMV3: + dec_type = VIDEO_DEC_FORMAT_WMV3; + break; + case CODEC_ID_VC1: + //case CODEC_TAG_VC_1: + case CODEC_TAG_WVC1: + case CODEC_TAG_WMVA: + dec_type = VIDEO_DEC_FORMAT_WVC1; + break; + case CODEC_ID_VP6F: + dec_type = VIDEO_DEC_FORMAT_SW; + break; + default: + dec_type = VIDEO_DEC_FORMAT_UNKNOW; + break; + } + + CLog::Log(LOGDEBUG, "codec_tag_to_vdec_type, dec_type(%d), codec_tag(%d)", dec_type, codec_tag); + return dec_type; +} + +static void am_packet_init(am_packet_t *pkt) +{ + memset(&pkt->avpkt, 0, sizeof(AVPacket)); + pkt->avpts = 0; + pkt->avdts = 0; + pkt->avduration = 0; + pkt->isvalid = 0; + pkt->newflag = 0; + pkt->lastpts = 0; + pkt->data = NULL; + pkt->buf = NULL; + pkt->data_size = 0; + pkt->buf_size = 0; + pkt->hdr = NULL; + pkt->codec = NULL; +} + +void am_packet_release(am_packet_t *pkt) +{ + if (pkt->buf != NULL) + { + free(pkt->buf); + pkt->buf= NULL; + } + if (pkt->hdr != NULL) + { + free(pkt->hdr->data); + pkt->hdr->data = NULL; + free(pkt->hdr); + pkt->hdr = NULL; + } + pkt->codec = NULL; +} + +int check_in_pts(am_private_t *para, am_packet_t *pkt) +{ + int last_duration = 0; + static int last_v_duration = 0; + int64_t pts = 0; + + last_duration = last_v_duration; + + if (para->stream_type == AM_STREAM_ES) { + if ((int64_t)INT64_0 != pkt->avpts) { + pts = pkt->avpts; + + if (para->m_dll->codec_checkin_pts(pkt->codec, pts) != 0) { + CLog::Log(LOGDEBUG, "ERROR check in pts error!"); + return PLAYER_PTS_ERROR; + } + + } else if ((int64_t)INT64_0 != pkt->avdts) { + pts = pkt->avdts * last_duration; + + if (para->m_dll->codec_checkin_pts(pkt->codec, pts) != 0) { + CLog::Log(LOGDEBUG, "ERROR check in dts error!"); + return PLAYER_PTS_ERROR; + } + + last_v_duration = pkt->avduration ? pkt->avduration : 1; + } else { + if (!para->check_first_pts) { + if (para->m_dll->codec_checkin_pts(pkt->codec, pts) != 0) { + CLog::Log(LOGDEBUG, "ERROR check in 0 to video pts error!"); + return PLAYER_PTS_ERROR; + } + } + } + if (!para->check_first_pts) { + para->check_first_pts = 1; + } + } + if (pts > 0) + pkt->lastpts = pts; + + return PLAYER_SUCCESS; +} + +static int check_write_finish(am_private_t *para, am_packet_t *pkt) +{ + if (para->playctrl_info.read_end_flag) { + if ((para->write_size.vpkt_num == para->read_size.vpkt_num)) { + return PLAYER_WR_FINISH; + } + } + return PLAYER_WR_FAILED; +} + +static int write_header(am_private_t *para, am_packet_t *pkt) +{ + int write_bytes = 0, len = 0; + + if (pkt->hdr && pkt->hdr->size > 0) { + if ((NULL == pkt->codec) || (NULL == pkt->hdr->data)) { + CLog::Log(LOGDEBUG, "[write_header]codec null!"); + return PLAYER_EMPTY_P; + } + while (1) { + write_bytes = para->m_dll->codec_write(pkt->codec, pkt->hdr->data + len, pkt->hdr->size - len); + if (write_bytes < 0 || write_bytes > (pkt->hdr->size - len)) { + if (-errno != AVERROR(EAGAIN)) { + CLog::Log(LOGDEBUG, "ERROR:write header failed!"); + return PLAYER_WR_FAILED; + } else { + continue; + } + } else { + len += write_bytes; + if (len == pkt->hdr->size) { + break; + } + } + } + } + return PLAYER_SUCCESS; +} + +int check_avbuffer_enough(am_private_t *para, am_packet_t *pkt) +{ + return 1; +} + +int write_av_packet(am_private_t *para, am_packet_t *pkt) +{ + int write_bytes = 0, len = 0, ret; + unsigned char *buf; + int size; + + if (pkt->newflag) { + if (pkt->isvalid) { + ret = check_in_pts(para, pkt); + if (ret != PLAYER_SUCCESS) { + CLog::Log(LOGDEBUG, "check in pts failed"); + return PLAYER_WR_FAILED; + } + } + if (write_header(para, pkt) == PLAYER_WR_FAILED) { + CLog::Log(LOGDEBUG, "[%s]write header failed!", __FUNCTION__); + return PLAYER_WR_FAILED; + } + pkt->newflag = 0; + } + + buf = pkt->data; + size = pkt->data_size ; + if (size == 0 && pkt->isvalid) { + para->write_size.vpkt_num++; + pkt->isvalid = 0; + } + while (size > 0 && pkt->isvalid) { + write_bytes = para->m_dll->codec_write(pkt->codec, (char *)buf, size); + if (write_bytes < 0 || write_bytes > size) { + if (-errno != AVERROR(EAGAIN)) { + para->playctrl_info.check_lowlevel_eagain_cnt = 0; + CLog::Log(LOGDEBUG, "write codec data failed!"); + return PLAYER_WR_FAILED; + } else { + // EAGAIN to see if buffer full or write time out too much + if (check_avbuffer_enough(para, pkt)) { + para->playctrl_info.check_lowlevel_eagain_cnt++; + } else { + para->playctrl_info.check_lowlevel_eagain_cnt = 0; + } + + if (para->playctrl_info.check_lowlevel_eagain_cnt > 50) { + // reset decoder + para->playctrl_info.check_lowlevel_eagain_cnt = 0; + para->playctrl_info.reset_flag = 1; + para->playctrl_info.end_flag = 1; + CLog::Log(LOGDEBUG, "$$$$$$ write blocked, need reset decoder!$$$$$$"); + } + pkt->data += len; + pkt->data_size -= len; + usleep(RW_WAIT_TIME); + CLog::Log(LOGDEBUG, "usleep(RW_WAIT_TIME)"); + return PLAYER_SUCCESS; + } + } else { + para->playctrl_info.check_lowlevel_eagain_cnt = 0; + len += write_bytes; + if (len == pkt->data_size) { + para->write_size.vpkt_num++; + pkt->isvalid = 0; + pkt->data_size = 0; + break; + } else if (len < pkt->data_size) { + buf += write_bytes; + size -= write_bytes; + } else { + return PLAYER_WR_FAILED; + } + } + } + if (check_write_finish(para, pkt) == PLAYER_WR_FINISH) { + return PLAYER_WR_FINISH; + } + return PLAYER_SUCCESS; +} + +static int check_size_in_buffer(unsigned char *p, int len) +{ + unsigned int size; + unsigned char *q = p; + while ((q + 4) < (p + len)) { + size = (*q << 24) | (*(q + 1) << 16) | (*(q + 2) << 8) | (*(q + 3)); + if (size & 0xff000000) { + return 0; + } + + if (q + size + 4 == p + len) { + return 1; + } + + q += size + 4; + } + return 0; +} + +static int check_size_in_buffer3(unsigned char *p, int len) +{ + unsigned int size; + unsigned char *q = p; + while ((q + 3) < (p + len)) { + size = (*q << 16) | (*(q + 1) << 8) | (*(q + 2)); + + if (q + size + 3 == p + len) { + return 1; + } + + q += size + 3; + } + return 0; +} + +static int check_size_in_buffer2(unsigned char *p, int len) +{ + unsigned int size; + unsigned char *q = p; + while ((q + 2) < (p + len)) { + size = (*q << 8) | (*(q + 1)); + + if (q + size + 2 == p + len) { + return 1; + } + + q += size + 2; + } + return 0; +} + +/*************************************************************************/ +static int m4s2_dx50_mp4v_add_header(unsigned char *buf, int size, am_packet_t *pkt) +{ + if (size > pkt->hdr->size) { + free(pkt->hdr->data), pkt->hdr->data = NULL; + pkt->hdr->size = 0; + + pkt->hdr->data = (char*)malloc(size); + if (!pkt->hdr->data) { + CLog::Log(LOGDEBUG, "[m4s2_dx50_add_header] NOMEM!"); + return PLAYER_FAILED; + } + } + + pkt->hdr->size = size; + memcpy(pkt->hdr->data, buf, size); + + return PLAYER_SUCCESS; +} + +static int m4s2_dx50_mp4v_write_header(am_private_t *para, am_packet_t *pkt) +{ + CLog::Log(LOGDEBUG, "m4s2_dx50_mp4v_write_header"); + int ret = m4s2_dx50_mp4v_add_header(para->extradata, para->extrasize, pkt); + if (ret == PLAYER_SUCCESS) { + if (1) { + pkt->codec = ¶->vcodec; + } else { + CLog::Log(LOGDEBUG, "[m4s2_dx50_mp4v_add_header]invalid video codec!"); + return PLAYER_EMPTY_P; + } + pkt->newflag = 1; + ret = write_av_packet(para, pkt); + } + return ret; +} + +static int divx3_data_prefeeding(am_packet_t *pkt, unsigned w, unsigned h) +{ + unsigned i = (w << 12) | (h & 0xfff); + unsigned char divx311_add[10] = { + 0x00, 0x00, 0x00, 0x01, + 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00 + }; + divx311_add[5] = (i >> 16) & 0xff; + divx311_add[6] = (i >> 8) & 0xff; + divx311_add[7] = i & 0xff; + + if (pkt->hdr->data) { + memcpy(pkt->hdr->data, divx311_add, sizeof(divx311_add)); + pkt->hdr->size = sizeof(divx311_add); + } else { + CLog::Log(LOGDEBUG, "[divx3_data_prefeeding]No enough memory!"); + return PLAYER_FAILED; + } + return PLAYER_SUCCESS; +} + +static int divx3_write_header(am_private_t *para, am_packet_t *pkt) +{ + CLog::Log(LOGDEBUG, "divx3_write_header"); + divx3_data_prefeeding(pkt, para->video_width, para->video_height); + if (1) { + pkt->codec = ¶->vcodec; + } else { + CLog::Log(LOGDEBUG, "[divx3_write_header]invalid codec!"); + return PLAYER_EMPTY_P; + } + pkt->newflag = 1; + write_av_packet(para, pkt); + return PLAYER_SUCCESS; +} + +static int h264_add_header(unsigned char *buf, int size, am_packet_t *pkt) +{ + char nal_start_code[] = {0x0, 0x0, 0x0, 0x1}; + int nalsize; + unsigned char* p; + int tmpi; + unsigned char* extradata = buf; + int header_len = 0; + char* buffer = pkt->hdr->data; + + p = extradata; + + // h264 annex-b + if ((p[0]==0 && p[1]==0 && p[2]==0 && p[3]==1) && size < HDR_BUF_SIZE) { + CLog::Log(LOGDEBUG, "add 264 header in stream before header len=%d",size); + memcpy(buffer, buf, size); + pkt->hdr->size = size; + return PLAYER_SUCCESS; + } + + if (size < 4) { + return PLAYER_FAILED; + } + + if (size < 10) { + CLog::Log(LOGDEBUG, "avcC too short"); + return PLAYER_FAILED; + } + + // h264 avcC + if (*p != 1) { + CLog::Log(LOGDEBUG, "Unknown avcC version %d", *p); + return PLAYER_FAILED; + } + + int cnt = *(p + 5) & 0x1f; //number of sps + // CLog::Log(LOGDEBUG, "number of sps :%d", cnt); + p += 6; + for (tmpi = 0; tmpi < cnt; tmpi++) { + nalsize = (*p << 8) | (*(p + 1)); + memcpy(&(buffer[header_len]), nal_start_code, 4); + header_len += 4; + memcpy(&(buffer[header_len]), p + 2, nalsize); + header_len += nalsize; + p += (nalsize + 2); + } + + cnt = *(p++); //Number of pps + // CLog::Log(LOGDEBUG, "number of pps :%d", cnt); + for (tmpi = 0; tmpi < cnt; tmpi++) { + nalsize = (*p << 8) | (*(p + 1)); + memcpy(&(buffer[header_len]), nal_start_code, 4); + header_len += 4; + memcpy(&(buffer[header_len]), p + 2, nalsize); + header_len += nalsize; + p += (nalsize + 2); + } + if (header_len >= HDR_BUF_SIZE) { + CLog::Log(LOGDEBUG, "header_len %d is larger than max length", header_len); + return 0; + } + pkt->hdr->size = header_len; + + return PLAYER_SUCCESS; +} +static int h264_write_header(am_private_t *para, am_packet_t *pkt) +{ + // CLog::Log(LOGDEBUG, "h264_write_header"); + int ret = -1; + + ret = h264_add_header(para->extradata, para->extrasize, pkt); + if (ret == PLAYER_SUCCESS) { + //if (ctx->vcodec) { + if (1) { + pkt->codec = ¶->vcodec; + } else { + //CLog::Log(LOGDEBUG, "[pre_header_feeding]invalid video codec!"); + return PLAYER_EMPTY_P; + } + + pkt->newflag = 1; + ret = write_av_packet(para, pkt); + } + return ret; +} + +static int wmv3_write_header(am_private_t *para, am_packet_t *pkt) +{ + CLog::Log(LOGDEBUG, "wmv3_write_header"); + unsigned i, check_sum = 0; + unsigned data_len = para->extrasize + 4; + + pkt->hdr->data[0] = 0; + pkt->hdr->data[1] = 0; + pkt->hdr->data[2] = 1; + pkt->hdr->data[3] = 0x10; + + pkt->hdr->data[4] = 0; + pkt->hdr->data[5] = (data_len >> 16) & 0xff; + pkt->hdr->data[6] = 0x88; + pkt->hdr->data[7] = (data_len >> 8) & 0xff; + pkt->hdr->data[8] = data_len & 0xff; + pkt->hdr->data[9] = 0x88; + + pkt->hdr->data[10] = 0xff; + pkt->hdr->data[11] = 0xff; + pkt->hdr->data[12] = 0x88; + pkt->hdr->data[13] = 0xff; + pkt->hdr->data[14] = 0xff; + pkt->hdr->data[15] = 0x88; + + for (i = 4 ; i < 16 ; i++) { + check_sum += pkt->hdr->data[i]; + } + + pkt->hdr->data[16] = (check_sum >> 8) & 0xff; + pkt->hdr->data[17] = check_sum & 0xff; + pkt->hdr->data[18] = 0x88; + pkt->hdr->data[19] = (check_sum >> 8) & 0xff; + pkt->hdr->data[20] = check_sum & 0xff; + pkt->hdr->data[21] = 0x88; + + pkt->hdr->data[22] = (para->video_width >> 8) & 0xff; + pkt->hdr->data[23] = para->video_width & 0xff; + pkt->hdr->data[24] = (para->video_height >> 8) & 0xff; + pkt->hdr->data[25] = para->video_height & 0xff; + + memcpy(pkt->hdr->data + 26, para->extradata, para->extrasize); + pkt->hdr->size = para->extrasize + 26; + if (1) { + pkt->codec = ¶->vcodec; + } else { + CLog::Log(LOGDEBUG, "[wmv3_write_header]invalid codec!"); + return PLAYER_EMPTY_P; + } + pkt->newflag = 1; + return write_av_packet(para, pkt); +} + +static int wvc1_write_header(am_private_t *para, am_packet_t *pkt) +{ + CLog::Log(LOGDEBUG, "wvc1_write_header"); + memcpy(pkt->hdr->data, para->extradata + 1, para->extrasize - 1); + pkt->hdr->size = para->extrasize - 1; + if (1) { + pkt->codec = ¶->vcodec; + } else { + CLog::Log(LOGDEBUG, "[wvc1_write_header]invalid codec!"); + return PLAYER_EMPTY_P; + } + pkt->newflag = 1; + return write_av_packet(para, pkt); +} + +static int mpeg_add_header(am_private_t *para, am_packet_t *pkt) +{ + CLog::Log(LOGDEBUG, "mpeg_add_header"); +#define STUFF_BYTES_LENGTH (256) + int size; + unsigned char packet_wrapper[] = { + 0x00, 0x00, 0x01, 0xe0, + 0x00, 0x00, /* pes packet length */ + 0x81, 0xc0, 0x0d, + 0x20, 0x00, 0x00, 0x00, 0x00, /* PTS */ + 0x1f, 0xff, 0xff, 0xff, 0xff, /* DTS */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + + size = para->extrasize + sizeof(packet_wrapper); + packet_wrapper[4] = size >> 8 ; + packet_wrapper[5] = size & 0xff ; + memcpy(pkt->hdr->data, packet_wrapper, sizeof(packet_wrapper)); + size = sizeof(packet_wrapper); + //CLog::Log(LOGDEBUG, "[mpeg_add_header:%d]wrapper size=%d\n",__LINE__,size); + memcpy(pkt->hdr->data + size, para->extradata, para->extrasize); + size += para->extrasize; + //CLog::Log(LOGDEBUG, "[mpeg_add_header:%d]wrapper+seq size=%d\n",__LINE__,size); + memset(pkt->hdr->data + size, 0xff, STUFF_BYTES_LENGTH); + size += STUFF_BYTES_LENGTH; + pkt->hdr->size = size; + //CLog::Log(LOGDEBUG, "[mpeg_add_header:%d]hdr_size=%d\n",__LINE__,size); + if (1) { + pkt->codec = ¶->vcodec; + } else { + CLog::Log(LOGDEBUG, "[mpeg_add_header]invalid codec!"); + return PLAYER_EMPTY_P; + } + + pkt->newflag = 1; + return write_av_packet(para, pkt); +} + +int pre_header_feeding(am_private_t *para, am_packet_t *pkt) +{ + int ret; + if (para->stream_type == AM_STREAM_ES) { + if (pkt->hdr == NULL) { + pkt->hdr = (hdr_buf_t*)malloc(sizeof(hdr_buf_t)); + pkt->hdr->data = (char *)malloc(HDR_BUF_SIZE); + if (!pkt->hdr->data) { + //CLog::Log(LOGDEBUG, "[pre_header_feeding] NOMEM!"); + return PLAYER_NOMEM; + } + } + + if (VFORMAT_H264 == para->video_format /*|| VFORMAT_H264MVC == para->video_format*/) { + ret = h264_write_header(para, pkt); + if (ret != PLAYER_SUCCESS) { + return ret; + } + } else if ((VFORMAT_MPEG4 == para->video_format) && (VIDEO_DEC_FORMAT_MPEG4_3 == para->video_codec_type)) { + ret = divx3_write_header(para, pkt); + if (ret != PLAYER_SUCCESS) { + return ret; + } + } else if ((CODEC_TAG_M4S2 == para->video_codec_tag) + || (CODEC_TAG_DX50 == para->video_codec_tag) + || (CODEC_TAG_mp4v == para->video_codec_tag)) { + ret = m4s2_dx50_mp4v_write_header(para, pkt); + if (ret != PLAYER_SUCCESS) { + return ret; + } + /* + } else if ((AVI_FILE == para->file_type) + && (VIDEO_DEC_FORMAT_MPEG4_3 != para->vstream_info.video_codec_type) + && (VFORMAT_H264 != para->vstream_info.video_format) + && (VFORMAT_VC1 != para->vstream_info.video_format)) { + ret = avi_write_header(para); + if (ret != PLAYER_SUCCESS) { + return ret; + } + */ + } else if (CODEC_TAG_WMV3 == para->video_codec_tag) { + CLog::Log(LOGDEBUG, "CODEC_TAG_WMV3 == para->video_codec_tag"); + ret = wmv3_write_header(para, pkt); + if (ret != PLAYER_SUCCESS) { + return ret; + } + } else if ((CODEC_TAG_WVC1 == para->video_codec_tag) + || (CODEC_TAG_VC_1 == para->video_codec_tag) + || (CODEC_TAG_WMVA == para->video_codec_tag)) { + CLog::Log(LOGDEBUG, "CODEC_TAG_WVC1 == para->video_codec_tag"); + ret = wvc1_write_header(para, pkt); + if (ret != PLAYER_SUCCESS) { + return ret; + } + /* + } else if ((MKV_FILE == para->file_type) && + ((VFORMAT_MPEG4 == para->vstream_info.video_format) + || (VFORMAT_MPEG12 == para->vstream_info.video_format))) { + ret = mkv_write_header(para, pkt); + if (ret != PLAYER_SUCCESS) { + return ret; + } + */ + } + + if (pkt->hdr) { + if (pkt->hdr->data) { + free(pkt->hdr->data); + pkt->hdr->data = NULL; + } + free(pkt->hdr); + pkt->hdr = NULL; + } + } + else if (para->stream_type == AM_STREAM_PS) { + if (pkt->hdr == NULL) { + pkt->hdr = (hdr_buf_t*)malloc(sizeof(hdr_buf_t)); + pkt->hdr->data = (char*)malloc(HDR_BUF_SIZE); + if (!pkt->hdr->data) { + CLog::Log(LOGDEBUG, "[pre_header_feeding] NOMEM!"); + return PLAYER_NOMEM; + } + } + if (( CODEC_ID_MPEG1VIDEO == para->video_codec_id) + || (CODEC_ID_MPEG2VIDEO == para->video_codec_id) + || (CODEC_ID_MPEG2VIDEO_XVMC == para->video_codec_id)) { + ret = mpeg_add_header(para, pkt); + if (ret != PLAYER_SUCCESS) { + return ret; + } + } + if (pkt->hdr) { + if (pkt->hdr->data) { + free(pkt->hdr->data); + pkt->hdr->data = NULL; + } + free(pkt->hdr); + pkt->hdr = NULL; + } + } + return PLAYER_SUCCESS; +} + +/*************************************************************************/ +int h264_update_frame_header(am_packet_t *pkt) +{ + int nalsize, size = pkt->data_size; + unsigned char *data = pkt->data; + unsigned char *p = data; + if (p != NULL) { + if (check_size_in_buffer(p, size)) { + while ((p + 4) < (data + size)) { + nalsize = (*p << 24) | (*(p + 1) << 16) | (*(p + 2) << 8) | (*(p + 3)); + *p = 0; + *(p + 1) = 0; + *(p + 2) = 0; + *(p + 3) = 1; + p += (nalsize + 4); + } + return PLAYER_SUCCESS; + } else if (check_size_in_buffer3(p, size)) { + while ((p + 3) < (data + size)) { + nalsize = (*p << 16) | (*(p + 1) << 8) | (*(p + 2)); + *p = 0; + *(p + 1) = 0; + *(p + 2) = 1; + p += (nalsize + 3); + } + return PLAYER_SUCCESS; + } else if (check_size_in_buffer2(p, size)) { + unsigned char *new_data; + int new_len = 0; + + new_data = (unsigned char *)malloc(size + 2 * 1024); + if (!new_data) { + return PLAYER_NOMEM; + } + + while ((p + 2) < (data + size)) { + nalsize = (*p << 8) | (*(p + 1)); + *(new_data + new_len) = 0; + *(new_data + new_len + 1) = 0; + *(new_data + new_len + 2) = 0; + *(new_data + new_len + 3) = 1; + memcpy(new_data + new_len + 4, p + 2, nalsize); + p += (nalsize + 2); + new_len += nalsize + 4; + } + + free(pkt->buf); + + pkt->buf = new_data; + pkt->buf_size = size + 2 * 1024; + pkt->data = pkt->buf; + pkt->data_size = new_len; + } + } else { + CLog::Log(LOGDEBUG, "[%s]invalid pointer!", __FUNCTION__); + return PLAYER_FAILED; + } + return PLAYER_SUCCESS; +} + +int divx3_prefix(am_packet_t *pkt) +{ +#define DIVX311_CHUNK_HEAD_SIZE 13 + const unsigned char divx311_chunk_prefix[DIVX311_CHUNK_HEAD_SIZE] = { + 0x00, 0x00, 0x00, 0x01, 0xb6, 'D', 'I', 'V', 'X', '3', '.', '1', '1' + }; + if ((pkt->hdr != NULL) && (pkt->hdr->data != NULL)) { + free(pkt->hdr->data); + pkt->hdr->data = NULL; + } + + if (pkt->hdr == NULL) { + pkt->hdr = (hdr_buf_t*)malloc(sizeof(hdr_buf_t)); + if (!pkt->hdr) { + CLog::Log(LOGDEBUG, "[divx3_prefix] NOMEM!"); + return PLAYER_FAILED; + } + + pkt->hdr->data = NULL; + pkt->hdr->size = 0; + } + + pkt->hdr->data = (char*)malloc(DIVX311_CHUNK_HEAD_SIZE + 4); + if (pkt->hdr->data == NULL) { + CLog::Log(LOGDEBUG, "[divx3_prefix] NOMEM!"); + return PLAYER_FAILED; + } + + memcpy(pkt->hdr->data, divx311_chunk_prefix, DIVX311_CHUNK_HEAD_SIZE); + + pkt->hdr->data[DIVX311_CHUNK_HEAD_SIZE + 0] = (pkt->data_size >> 24) & 0xff; + pkt->hdr->data[DIVX311_CHUNK_HEAD_SIZE + 1] = (pkt->data_size >> 16) & 0xff; + pkt->hdr->data[DIVX311_CHUNK_HEAD_SIZE + 2] = (pkt->data_size >> 8) & 0xff; + pkt->hdr->data[DIVX311_CHUNK_HEAD_SIZE + 3] = pkt->data_size & 0xff; + + pkt->hdr->size = DIVX311_CHUNK_HEAD_SIZE + 4; + pkt->newflag = 1; + + return PLAYER_SUCCESS; +} + +int set_header_info(am_private_t *para) +{ + am_packet_t *pkt = ¶->am_pkt; + + //if (pkt->newflag) + { + //if (pkt->hdr) + // pkt->hdr->size = 0; + + if ((para->video_format == VFORMAT_H264) /*|| (am_private->video_format == VFORMAT_H264MVC)*/) + { + return h264_update_frame_header(pkt); + } + else if (para->video_format == VFORMAT_MPEG4) + { + if (para->video_codec_type == VIDEO_DEC_FORMAT_MPEG4_3) + { + return divx3_prefix(pkt); + } + else if (para->video_codec_type == VIDEO_DEC_FORMAT_H263) + { + return PLAYER_UNSUPPORT; + unsigned char *vld_buf; + int vld_len, vld_buf_size = para->video_width * para->video_height * 2; + + if (!pkt->data_size) { + return PLAYER_SUCCESS; + } + + if ((pkt->data[0] == 0) && (pkt->data[1] == 0) && (pkt->data[2] == 1) && (pkt->data[3] == 0xb6)) { + return PLAYER_SUCCESS; + } + + vld_buf = (unsigned char*)malloc(vld_buf_size); + if (!vld_buf) { + return PLAYER_NOMEM; + } + + if (para->flv_flag) { + vld_len = para->m_dll->h263vld(pkt->data, vld_buf, pkt->data_size, 1); + } else { + if (0 == para->h263_decodable) { + para->h263_decodable = para->m_dll->decodeble_h263(pkt->data); + if (0 == para->h263_decodable) { + CLog::Log(LOGDEBUG, "[%s]h263 unsupport video and audio, exit", __FUNCTION__); + return PLAYER_UNSUPPORT; + } + } + vld_len = para->m_dll->h263vld(pkt->data, vld_buf, pkt->data_size, 0); + } + + if (vld_len > 0) { + if (pkt->buf) { + free(pkt->buf); + } + pkt->buf = vld_buf; + pkt->buf_size = vld_buf_size; + pkt->data = pkt->buf; + pkt->data_size = vld_len; + } else { + free(vld_buf); + pkt->data_size = 0; + } + } + } else if (para->video_format == VFORMAT_VC1) { + if (para->video_codec_type == VIDEO_DEC_FORMAT_WMV3) { + unsigned i, check_sum = 0, data_len = 0; + + if ((pkt->hdr != NULL) && (pkt->hdr->data != NULL)) { + free(pkt->hdr->data); + pkt->hdr->data = NULL; + } + + if (pkt->hdr == NULL) { + pkt->hdr = (hdr_buf_t*)malloc(sizeof(hdr_buf_t)); + if (!pkt->hdr) { + return PLAYER_FAILED; + } + + pkt->hdr->data = NULL; + pkt->hdr->size = 0; + } + + if (pkt->avpkt.flags) { + pkt->hdr->data = (char*)malloc(para->extrasize + 26 + 22); + if (pkt->hdr->data == NULL) { + return PLAYER_FAILED; + } + + pkt->hdr->data[0] = 0; + pkt->hdr->data[1] = 0; + pkt->hdr->data[2] = 1; + pkt->hdr->data[3] = 0x10; + + data_len = para->extrasize + 4; + pkt->hdr->data[4] = 0; + pkt->hdr->data[5] = (data_len >> 16) & 0xff; + pkt->hdr->data[6] = 0x88; + pkt->hdr->data[7] = (data_len >> 8) & 0xff; + pkt->hdr->data[8] = data_len & 0xff; + pkt->hdr->data[9] = 0x88; + + pkt->hdr->data[10] = 0xff; + pkt->hdr->data[11] = 0xff; + pkt->hdr->data[12] = 0x88; + pkt->hdr->data[13] = 0xff; + pkt->hdr->data[14] = 0xff; + pkt->hdr->data[15] = 0x88; + + for (i = 4 ; i < 16 ; i++) { + check_sum += pkt->hdr->data[i]; + } + + pkt->hdr->data[16] = (check_sum >> 8) & 0xff; + pkt->hdr->data[17] = check_sum & 0xff; + pkt->hdr->data[18] = 0x88; + pkt->hdr->data[19] = (check_sum >> 8) & 0xff; + pkt->hdr->data[20] = check_sum & 0xff; + pkt->hdr->data[21] = 0x88; + + pkt->hdr->data[22] = (para->video_width >> 8) & 0xff; + pkt->hdr->data[23] = para->video_width & 0xff; + pkt->hdr->data[24] = (para->video_height >> 8) & 0xff; + pkt->hdr->data[25] = para->video_height & 0xff; + + memcpy(pkt->hdr->data + 26, para->extradata, para->extrasize); + + check_sum = 0; + data_len = para->extrasize + 26; + } else { + pkt->hdr->data = (char*)malloc(22); + if (pkt->hdr->data == NULL) { + return PLAYER_FAILED; + } + } + + pkt->hdr->data[data_len + 0] = 0; + pkt->hdr->data[data_len + 1] = 0; + pkt->hdr->data[data_len + 2] = 1; + pkt->hdr->data[data_len + 3] = 0xd; + + pkt->hdr->data[data_len + 4] = 0; + pkt->hdr->data[data_len + 5] = (pkt->data_size >> 16) & 0xff; + pkt->hdr->data[data_len + 6] = 0x88; + pkt->hdr->data[data_len + 7] = (pkt->data_size >> 8) & 0xff; + pkt->hdr->data[data_len + 8] = pkt->data_size & 0xff; + pkt->hdr->data[data_len + 9] = 0x88; + + pkt->hdr->data[data_len + 10] = 0xff; + pkt->hdr->data[data_len + 11] = 0xff; + pkt->hdr->data[data_len + 12] = 0x88; + pkt->hdr->data[data_len + 13] = 0xff; + pkt->hdr->data[data_len + 14] = 0xff; + pkt->hdr->data[data_len + 15] = 0x88; + + for (i = data_len + 4 ; i < data_len + 16 ; i++) { + check_sum += pkt->hdr->data[i]; + } + + pkt->hdr->data[data_len + 16] = (check_sum >> 8) & 0xff; + pkt->hdr->data[data_len + 17] = check_sum & 0xff; + pkt->hdr->data[data_len + 18] = 0x88; + pkt->hdr->data[data_len + 19] = (check_sum >> 8) & 0xff; + pkt->hdr->data[data_len + 20] = check_sum & 0xff; + pkt->hdr->data[data_len + 21] = 0x88; + + pkt->hdr->size = data_len + 22; + pkt->newflag = 1; + } else if (para->video_codec_type == VIDEO_DEC_FORMAT_WVC1) { + if ((pkt->hdr != NULL) && (pkt->hdr->data != NULL)) { + free(pkt->hdr->data); + pkt->hdr->data = NULL; + } + + if (pkt->hdr == NULL) { + pkt->hdr = (hdr_buf_t*)malloc(sizeof(hdr_buf_t)); + if (!pkt->hdr) { + CLog::Log(LOGDEBUG, "[wvc1_prefix] NOMEM!"); + return PLAYER_FAILED; + } + + pkt->hdr->data = NULL; + pkt->hdr->size = 0; + } + + pkt->hdr->data = (char*)malloc(4); + if (pkt->hdr->data == NULL) { + CLog::Log(LOGDEBUG, "[wvc1_prefix] NOMEM!"); + return PLAYER_FAILED; + } + + pkt->hdr->data[0] = 0; + pkt->hdr->data[1] = 0; + pkt->hdr->data[2] = 1; + pkt->hdr->data[3] = 0xd; + pkt->hdr->size = 4; + pkt->newflag = 1; + } + } + } + return PLAYER_SUCCESS; +} + +/*************************************************************************/ +CAmlogic::CAmlogic() : CThread("CAmlogic") +{ + am_private = new am_private_t; + memset(am_private, 0, sizeof(am_private_t)); + m_dll = new DllLibAmCodec; + m_dll->Load(); + am_private->m_dll = m_dll; +} + + +CAmlogic::~CAmlogic() +{ + StopThread(); + delete am_private; + am_private = NULL; + delete m_dll, m_dll = NULL; +} + +bool CAmlogic::OpenDecoder(CDVDStreamInfo &hints) +{ + CLog::Log(LOGDEBUG, "CAmlogic::OpenDecoder"); + m_1st_pts = 0; + m_app_pts = 0.0; + m_cur_pts = 0; + m_cur_pictcnt = 0; + m_old_pictcnt = 0; + m_dst_rect.SetRect(0, 0, 0, 0); + m_zoom = -1; + m_contrast = -1; + m_brightness = -1; + + + am_packet_init(&am_private->am_pkt); + // default stream type + am_private->stream_type = AM_STREAM_ES; + // handle hints. + am_private->video_width = hints.width; + am_private->video_height = hints.height; + am_private->video_codec_id = hints.codec; + am_private->video_codec_tag = hints.codec_tag; + //am_private->video_pid = hints.idphysical; + am_private->video_pid = -1; + + AVRational video_ratio = m_dll->av_d2q(1, SHRT_MAX); + //if (!hints.forced_aspect) + // video_ratio = m_dll->av_d2q(hints.aspect, SHRT_MAX); + am_private->video_ratio = ((int32_t)video_ratio.num << 16) | video_ratio.den; + am_private->video_ratio64 = ((int64_t)video_ratio.num << 32) | video_ratio.den; + if (hints.fpsrate > 0 && hints.fpsscale != 0) + am_private->video_rate = 0.5 + (float)UNIT_FREQ * hints.fpsscale / hints.fpsrate; + else + { + // stupid PVR hacks because it does not fill in all of hints. + if (hints.codec == CODEC_ID_MPEG2VIDEO) + { + am_private->video_rate = 0.5 + (float)UNIT_FREQ * 1001 / 30000; + if (hints.codec == 1280) + am_private->video_rate = 0.5 + (float)UNIT_FREQ * 1001 / 60000;; + } + } + + // handle orientation + am_private->video_rotation_degree = 0; + if (hints.orientation == 90) + am_private->video_rotation_degree = 1; + else if (hints.orientation == 180) + am_private->video_rotation_degree = 2; + else if (hints.orientation == 270) + am_private->video_rotation_degree = 3; + // handle extradata + am_private->video_format = codecid_to_vformat(hints.codec); + if (am_private->video_format != VFORMAT_MPEG12) + { + am_private->extrasize = hints.extrasize; + am_private->extradata = (uint8_t*)malloc(hints.extrasize); + memcpy(am_private->extradata, hints.extradata, hints.extrasize); + } + + if (am_private->stream_type == AM_STREAM_ES && am_private->video_codec_tag != 0) + am_private->video_codec_type = codec_tag_to_vdec_type(am_private->video_codec_tag); + else + am_private->video_codec_type = codec_tag_to_vdec_type(am_private->video_codec_id); + + am_private->flv_flag = 0; + if (am_private->video_codec_id == CODEC_ID_FLV1) + { + am_private->video_codec_tag = CODEC_TAG_F263; + am_private->flv_flag = 1; + } + + CLog::Log(LOGDEBUG, "CAmlogic::OpenDecoder hints.fpsrate(%d), hints.fpsscale(%d), video_rate(%d)", + hints.fpsrate, hints.fpsscale, am_private->video_rate); + CLog::Log(LOGDEBUG, "CAmlogic::OpenDecoder hints.aspect(%f), video_ratio.num(%d), video_ratio.den(%d)", + hints.aspect, video_ratio.num, video_ratio.den); + CLog::Log(LOGDEBUG, "CAmlogic::OpenDecoder hints.orientation(%d), hints.forced_aspect(%d)", + hints.orientation, hints.forced_aspect); + + // default video codec params + am_private->vcodec.has_video = 1; + am_private->vcodec.noblock = 0; + am_private->vcodec.video_pid = am_private->video_pid; + am_private->vcodec.video_type = am_private->video_format; + am_private->vcodec.stream_type = STREAM_TYPE_ES_VIDEO; + am_private->vcodec.am_sysinfo.format = am_private->video_codec_type; + am_private->vcodec.am_sysinfo.width = am_private->video_width; + am_private->vcodec.am_sysinfo.height = am_private->video_height; + am_private->vcodec.am_sysinfo.rate = am_private->video_rate; + am_private->vcodec.am_sysinfo.ratio = am_private->video_ratio; + am_private->vcodec.am_sysinfo.ratio64 = am_private->video_ratio64; + am_private->vcodec.am_sysinfo.param = NULL; + + switch(am_private->video_format) + { + default: + break; + case VFORMAT_MPEG4: + am_private->vcodec.am_sysinfo.param = (void*)EXTERNAL_PTS; + break; + case VFORMAT_H264: + case VFORMAT_H264MVC: + am_private->vcodec.am_sysinfo.param = (void*)(EXTERNAL_PTS | SYNC_OUTSIDE); + break; + case VFORMAT_REAL: + { + static unsigned short tbl[9]; + am_private->vcodec.am_sysinfo.ratio = 0x100; + if (VIDEO_DEC_FORMAT_REAL_8 == am_private->video_codec_type) + { + am_private->vcodec.am_sysinfo.extra = am_private->extradata[1] & 7; + tbl[0] = (((am_private->vcodec.am_sysinfo.width >> 2) - 1) << 8) + | (((am_private->vcodec.am_sysinfo.height >> 2) - 1) & 0xff); + unsigned int j; + for (unsigned int i = 1; i <= am_private->vcodec.am_sysinfo.extra; i++) + { + j = 2 * (i - 1); + tbl[i] = ((am_private->extradata[8 + j] - 1) << 8) | ((am_private->extradata[8 + j + 1] - 1) & 0xff); + } + } + am_private->vcodec.am_sysinfo.param = &tbl; + } + am_private->stream_type = AM_STREAM_RM; + am_private->vcodec.stream_type = STREAM_TYPE_RM; + break; + case VFORMAT_VC1: + // vc1 is extension id, from 0xfd55 to 0xfd5f according to ffmpeg + am_private->vcodec.video_pid = am_private->vcodec.video_pid >> 8; + break; + } + am_private->vcodec.am_sysinfo.param = (void *)((unsigned int)am_private->vcodec.am_sysinfo.param | (am_private->video_rotation_degree << 16)); + + int ret = m_dll->codec_init(&am_private->vcodec); + if (ret != CODEC_ERROR_NONE) + { + CLog::Log(LOGDEBUG, "CAmlogic::OpenDecoder codec init failed, ret=-0x%x", -ret); + return false; + } + + float volume; + if (m_dll->codec_get_volume(NULL, &volume) == 0 && volume != 1.0) + m_dll->codec_set_volume(NULL, 1.0); + + m_dll->codec_set_cntl_avthresh(&am_private->vcodec, AV_SYNC_THRESH); + m_dll->codec_set_cntl_syncthresh(&am_private->vcodec, 0); + // disable tsync, we are playing video disconnected from audio. + aml_set_sysfs_int("/sys/class/tsync/enable", 0); + + am_private->am_pkt.codec = &am_private->vcodec; + if (!(am_private->video_format == VFORMAT_VC1 && + am_private->video_codec_type == VIDEO_DEC_FORMAT_WMV3)) + { + pre_header_feeding(am_private, &am_private->am_pkt); + } + + Create(); + + g_renderManager.RegisterRenderUpdateCallBack((const void*)this, RenderUpdateCallBack); + g_renderManager.RegisterRenderFeaturesCallBack((const void*)this, RenderFeaturesCallBack); + + return true; +} + +void CAmlogic::CloseDecoder() +{ + CLog::Log(LOGDEBUG, "CAmlogic::CloseDecoder"); + StopThread(); + + g_renderManager.RegisterRenderUpdateCallBack((const void*)NULL, NULL); + g_renderManager.RegisterRenderFeaturesCallBack((const void*)NULL, NULL); + + m_dll->codec_close(&am_private->vcodec); + am_packet_release(&am_private->am_pkt); + free(am_private->extradata); + am_private->extradata = NULL; + // return tsync to default so external apps work + aml_set_sysfs_int("/sys/class/tsync/enable", 1); +} + +void CAmlogic::Reset() +{ + CLog::Log(LOGDEBUG, "CAmlogic::Reset"); + + // set the system blackout_policy to leave the last frame showing + int blackout_policy = aml_get_sysfs_int("/sys/class/video/blackout_policy"); + aml_set_sysfs_int("/sys/class/video/blackout_policy", 0); + + // reset the decoder + m_dll->codec_reset(&am_private->vcodec); + + // re-init our am_pkt + am_packet_release(&am_private->am_pkt); + am_packet_init(&am_private->am_pkt); + am_private->am_pkt.codec = &am_private->vcodec; + + if (!(am_private->video_format == VFORMAT_VC1 && + am_private->video_codec_type == VIDEO_DEC_FORMAT_WMV3)) + { + pre_header_feeding(am_private, &am_private->am_pkt); + } + + // reset some interal vars + m_1st_pts = 0; + m_app_pts = GetPlayerPtsSeconds(); + m_cur_pts = 0; + m_cur_pictcnt = 0; + m_old_pictcnt = 0; + + // restore the saved system blackout_policy value + aml_set_sysfs_int("/sys/class/video/blackout_policy", blackout_policy); +} + +int CAmlogic::Decode(unsigned char *pData, size_t size, double dts, double pts) +{ + // grr, m_RenderUpdateCallBackFn in g_renderManager is NULL'ed during + // g_renderManager.Configure call by player, which happens after the codec + // OpenDecoder call. So we need to restore it but it does not seem to stick :) + g_renderManager.RegisterRenderUpdateCallBack((const void*)this, RenderUpdateCallBack); + + if (pData) + { + am_private->am_pkt.data = pData; + am_private->am_pkt.data_size = size; + am_private->am_pkt.newflag = 1; + am_private->am_pkt.isvalid = 1; + am_private->am_pkt.avduration = 0; + + if (pts == DVD_NOPTS_VALUE) + am_private->am_pkt.avpts = AV_NOPTS_VALUE; + else + am_private->am_pkt.avpts = 0.5 + (pts * PTS_FREQ) / DVD_TIME_BASE; + if (dts == DVD_NOPTS_VALUE) + am_private->am_pkt.avdts = AV_NOPTS_VALUE; + else + am_private->am_pkt.avdts = 0.5 + (dts * PTS_FREQ) / DVD_TIME_BASE; + + set_header_info(am_private); + write_av_packet(am_private, &am_private->am_pkt); + + // if we seek, then GetTimeSize is wrong as + // reports lastpts - cur_pts and hw decoder has + // not started outputing new pts values yet. + // so we grab the 1st pts sent into driver and + // use that to calc GetTimeSize. + if (m_1st_pts == 0) + m_1st_pts = am_private->am_pkt.lastpts; + } + // keep hw buffered demux above 1 second + if (GetTimeSize() < 1.0) + return VC_BUFFER; + + // wait until we get a new frame or 25ms, + // but only if we have not gotten a new pict. + if (m_old_pictcnt == m_cur_pictcnt) + m_ready_event.WaitMSec(25); + + // we must return VC_BUFFER or VC_PICTURE, + // default to VC_BUFFER. + int rtn = VC_BUFFER; + if (m_old_pictcnt != m_cur_pictcnt) + { + m_old_pictcnt = m_cur_pictcnt; + rtn = VC_PICTURE; + // we got a new pict, try and keep hw buffered demux above 2 seconds. + // this, combined with the above 1 second check, + // keeps hw buffered demux between 1 and 2 seconds. + if (GetTimeSize() < 2.0) + rtn |= VC_BUFFER; + } +/* + CLog::Log(LOGDEBUG, "CAmlogic::Decode: " + "rtn(%d), m_cur_pictcnt(%lld), m_cur_pts(%f), lastpts(%f), GetTimeSize(%f), GetDataSize(%d)", + rtn, m_cur_pictcnt, (float)m_cur_pts/PTS_FREQ, (float)am_private->am_pkt.lastpts/PTS_FREQ, GetTimeSize(), GetDataSize()); +*/ + return rtn; +} + +bool CAmlogic::GetPicture(DVDVideoPicture *pDvdVideoPicture) +{ + pDvdVideoPicture->dts = DVD_NOPTS_VALUE; + pDvdVideoPicture->pts = GetPlayerPtsSeconds() * (double)DVD_TIME_BASE; + //pDvdVideoPicture->pts = (double)m_cur_pts * (double)DVD_TIME_BASE / (double)PTS_FREQ; + pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED; + pDvdVideoPicture->format = RENDER_FMT_BYPASS; + pDvdVideoPicture->iDuration = (double)(am_private->video_rate * DVD_TIME_BASE) / UNIT_FREQ; + + // video pts cannot be late or dvdplayer goes nuts, + // so run it two frames ahead + pDvdVideoPicture->pts += pDvdVideoPicture->iDuration; + + return true; +} + +int CAmlogic::GetDataSize() +{ + struct buf_status vbuf ={0}; + m_dll->codec_get_vbuf_state(&am_private->vcodec, &vbuf); + + return vbuf.data_len; +} + +double CAmlogic::GetTimeSize() +{ + // if m_cur_pts is zero, hw decoder was not started yet + // so we use the pts of the 1st demux packet that was send + // to hw decoder to calc timesize. + if (m_cur_pts == 0) + m_timesize = (double)(am_private->am_pkt.lastpts - m_1st_pts) / PTS_FREQ; + else + m_timesize = (double)(am_private->am_pkt.lastpts - m_cur_pts) / PTS_FREQ; + + // lie to DVDPlayer, it is hardcoded to a max of 8 seconds, + // if you buffer more than 8 seconds, it goes nuts. + double timesize = m_timesize; + if (timesize < 0.0) + timesize = 0.0; + else if (timesize > 7.0) + timesize = 7.0; + + return timesize; +} + +void CAmlogic::Process() +{ + CLog::Log(LOGDEBUG, "CAmlogic::Process Started"); + + // bump our priority to be level with SoftAE + SetPriority(THREAD_PRIORITY_ABOVE_NORMAL); + while (!m_bStop) + { + int64_t cur_pts = 0; + if (am_private->am_pkt.lastpts > 0) + { + // this is a blocking poll that returns every vsync. + // since we are running at a higher priority, make sure + // we sleep if the call fails or does a timeout. + if (m_dll->codec_poll_cntl(&am_private->vcodec) <= 0) + Sleep(10); + + cur_pts = get_pts_video(); + if (m_cur_pts != cur_pts) + { + // other threads look at these, do them first + m_cur_pts = cur_pts; + m_cur_pictcnt++; + m_ready_event.Set(); + + double app_pts = GetPlayerPtsSeconds(); + double pts_error = (double)cur_pts/PTS_FREQ - app_pts; + + double offset = 0.0; + if ((fabs(pts_error) > 0.10) && fabs(m_app_pts - app_pts) > 0.05) + { + offset = (double)am_private->video_rate / UNIT_FREQ; + //CLog::Log(LOGDEBUG, "CAmlogic::SetDropState, offset(%f), pts_error(%f), %f", + // offset, pts_error, fabs(m_app_pts - app_pts)); + } + // little trick here, if we get told to drop, + // we set pts_pcrscr to current pts clock + 1 frame duration, + // else just the current pts clock. + SyncToPlayerPtsSeconds(offset); + } + } + else + { + Sleep(10); + } + } + SetPriority(THREAD_PRIORITY_NORMAL); + CLog::Log(LOGDEBUG, "CAmlogic::Process Stopped"); +} + +void CAmlogic::PauseResume(int state) +{ + static int saved_state = -1; + if (saved_state == state) + return; + + saved_state = state; + if (saved_state == 1) + m_dll->codec_pause(&am_private->vcodec); + else + m_dll->codec_resume(&am_private->vcodec); +} + +double CAmlogic::GetPlayerPtsSeconds() +{ + double clock_pts = 0.0; + CDVDClock *playerclock = CDVDClock::GetMasterClock(); + if (playerclock) + clock_pts = playerclock->GetClock() / DVD_TIME_BASE; + + return clock_pts; +} + +void CAmlogic::SyncToPlayerPtsSeconds(const double offset) +{ + CDVDClock *playerclock = CDVDClock::GetMasterClock(); + if (playerclock) + { + m_app_pts = playerclock->GetClock() / DVD_TIME_BASE; + set_pts_pcrscr((int64_t)((m_app_pts + offset) * PTS_FREQ)); + } +} + +void CAmlogic::ShowMainVideo(const bool show) +{ + static int saved_disable_video = -1; + + int disable_video = show ? 0:1; + if (saved_disable_video == disable_video) + return; + + aml_set_sysfs_int("/sys/class/video/disable_video", disable_video); + saved_disable_video = disable_video; +} + +void CAmlogic::SetVideoZoom(const float zoom) +{ + // input zoom range is 0.5 to 2.0 with a default of 1.0. + // output zoom range is 2 to 300 with default of 100. + // we limit that to a range of 50 to 200 with default of 100. + aml_set_sysfs_int("/sys/class/video/zoom", (int)(100 * zoom)); +} + +void CAmlogic::SetVideoContrast(const int contrast) +{ + // input contrast range is 0 to 100 with default of 50. + // output contrast range is -255 to 255 with default of 0. + int aml_contrast = (255 * (contrast - 50)) / 50; + aml_set_sysfs_int("/sys/class/video/contrast", aml_contrast); +} +void CAmlogic::SetVideoBrightness(const int brightness) +{ + // input brightness range is 0 to 100 with default of 50. + // output brightness range is -127 to 127 with default of 0. + int aml_brightness = (127 * (brightness - 50)) / 50; + aml_set_sysfs_int("/sys/class/video/brightness", aml_brightness); +} +void CAmlogic::SetVideoSaturation(const int saturation) +{ + // output saturation range is -127 to 127 with default of 127. + aml_set_sysfs_int("/sys/class/video/saturation", saturation); +} + +void CAmlogic::GetRenderFeatures(Features &renderFeatures) +{ + renderFeatures.push_back(RENDERFEATURE_ZOOM); + renderFeatures.push_back(RENDERFEATURE_CONTRAST); + renderFeatures.push_back(RENDERFEATURE_BRIGHTNESS); + renderFeatures.push_back(RENDERFEATURE_STRETCH); + renderFeatures.push_back(RENDERFEATURE_PIXEL_RATIO); + return; +} + +void CAmlogic::RenderFeaturesCallBack(const void *ctx, Features &renderFeatures) +{ + CAmlogic *codec = (CAmlogic*)ctx; + if (codec) + codec->GetRenderFeatures(renderFeatures); +} + +void CAmlogic::SetVideoRect(const CRect &SrcRect, const CRect &DestRect) +{ + // this routine gets called every video frame + // and is in the context of the renderer thread so + // do not do anything stupid here. + + // video zoom adjustment. + float zoom = g_settings.m_currentVideoSettings.m_CustomZoomAmount; + if ((int)(zoom * 1000) != (int)(m_zoom * 1000)) + { + m_zoom = zoom; + } + // video contrast adjustment. + int contrast = g_settings.m_currentVideoSettings.m_Contrast; + if (contrast != m_contrast) + { + SetVideoContrast(contrast); + m_contrast = contrast; + } + // video brightness adjustment. + int brightness = g_settings.m_currentVideoSettings.m_Brightness; + if (brightness != m_brightness) + { + SetVideoBrightness(brightness); + m_brightness = brightness; + } + + // check if destination rect or video view mode has changed + if ((m_dst_rect != DestRect) || (m_view_mode != g_settings.m_currentVideoSettings.m_ViewMode)) + { + m_dst_rect = DestRect; + m_view_mode = g_settings.m_currentVideoSettings.m_ViewMode; + } + else + { + // mainvideo 'should' be showing already if we get here, make sure. + ShowMainVideo(true); + return; + } + + CRect gui, display, dst_rect; + gui = g_graphicsContext.GetViewWindow(); + // when display is at 1080p, we have freescale enabled + // and that scales all layers into 1080p display including video, + // so we have to setup video axis for 720p instead of 1080p... Boooo. + display = g_graphicsContext.GetViewWindow(); + //RESOLUTION res = g_graphicsContext.GetVideoResolution(); + //display.SetRect(0, 0, g_settings.m_ResInfo[res].iScreenWidth, g_settings.m_ResInfo[res].iScreenHeight); + dst_rect = m_dst_rect; + if (gui != display) + { + float xscale = display.Width() / gui.Width(); + float yscale = display.Height() / gui.Height(); + dst_rect.x1 *= xscale; + dst_rect.x2 *= xscale; + dst_rect.y1 *= yscale; + dst_rect.y2 *= yscale; + } + + ShowMainVideo(false); + + // goofy 0/1 based difference in aml axis coordinates. + // fix them. + dst_rect.x2--; + dst_rect.y2--; + + char video_axis[256] = {0}; + sprintf(video_axis, "%d %d %d %d", (int)dst_rect.x1, (int)dst_rect.y1, (int)dst_rect.x2, (int)dst_rect.y2); + aml_set_sysfs_str("/sys/class/video/axis", video_axis); + + CStdString rectangle; + rectangle.Format("%i,%i,%i,%i", + (int)dst_rect.x1, (int)dst_rect.y1, + (int)dst_rect.Width(), (int)dst_rect.Height()); + CLog::Log(LOGDEBUG, "CAmlogic::SetVideoRect:dst_rect(%s)", rectangle.c_str()); + + // we only get called once gui has changed to something + // that would show video playback, so show it. + ShowMainVideo(true); +} + +void CAmlogic::RenderUpdateCallBack(const void *ctx, const CRect &SrcRect, const CRect &DestRect) +{ + CAmlogic *codec = (CAmlogic*)ctx; + codec->SetVideoRect(SrcRect, DestRect); +} diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.h new file mode 100644 index 0000000000000..2afaf2831ce1c --- /dev/null +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.h @@ -0,0 +1,81 @@ +#pragma once +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "DVDVideoCodec.h" +#include "cores/dvdplayer/DVDStreamInfo.h" +#include "cores/VideoRenderers/RenderFeatures.h" +#include "guilib/Geometry.h" +#include "threads/Thread.h" + +typedef struct am_private_t am_private_t; + +class DllLibAmCodec; + +class CAmlogic : public CThread +{ +public: + CAmlogic(); + virtual ~CAmlogic(); + + bool OpenDecoder(CDVDStreamInfo &hints); + void CloseDecoder(); + void Reset(); + + int Decode(unsigned char *pData, size_t size, double dts, double pts); + + bool GetPicture(DVDVideoPicture* pDvdVideoPicture); + int GetDataSize(); + double GetTimeSize(); + +protected: + virtual void Process(); + +private: + void PauseResume(int state); + double GetPlayerPtsSeconds(); + void SyncToPlayerPtsSeconds(double offset); + void ShowMainVideo(const bool show); + void SetVideoZoom(const float zoom); + void SetVideoContrast(const int contrast); + void SetVideoBrightness(const int brightness); + void SetVideoSaturation(const int saturation); + void GetRenderFeatures(Features &renderFeatures); + static void RenderFeaturesCallBack(const void *ctx, Features &renderFeatures); + void SetVideoRect(const CRect &SrcRect, const CRect &DestRect); + static void RenderUpdateCallBack(const void *ctx, const CRect &SrcRect, const CRect &DestRect); + + DllLibAmCodec *m_dll; + am_private_t *am_private; + volatile int64_t m_1st_pts; + volatile double m_app_pts; + volatile int64_t m_cur_pts; + volatile int64_t m_cur_pictcnt; + volatile int64_t m_old_pictcnt; + volatile double m_timesize; + CEvent m_ready_event; + + CRect m_dst_rect; + int m_view_mode; + float m_zoom; + int m_contrast; + int m_brightness; +}; diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp new file mode 100644 index 0000000000000..98f3fd04cd98c --- /dev/null +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "DVDVideoCodecAmlogic.h" +#include "DVDClock.h" +#include "DVDStreamInfo.h" +#include "Amlogic.h" +#include "video/VideoThumbLoader.h" +#include "utils/log.h" + +#define __MODULE_NAME__ "DVDVideoCodecAmlogic" + +CDVDVideoCodecAmlogic::CDVDVideoCodecAmlogic() : + m_Codec(NULL), + m_pFormatName("") +{ +} + +CDVDVideoCodecAmlogic::~CDVDVideoCodecAmlogic() +{ + Dispose(); +} + +bool CDVDVideoCodecAmlogic::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) +{ + switch(hints.codec) + { + case CODEC_ID_MPEG1VIDEO: + case CODEC_ID_MPEG2VIDEO: + case CODEC_ID_MPEG2VIDEO_XVMC: + m_pFormatName = "am-mpeg2"; + break; + case CODEC_ID_H264: + m_pFormatName = "am-h264"; + break; + case CODEC_ID_MPEG4: + case CODEC_ID_MSMPEG4V2: + case CODEC_ID_MSMPEG4V3: + m_pFormatName = "am-mpeg4"; + break; + case CODEC_ID_H263: + case CODEC_ID_H263P: + case CODEC_ID_H263I: + m_pFormatName = "am-h263"; + break; + case CODEC_ID_FLV1: + m_pFormatName = "am-flv1"; + break; + case CODEC_ID_RV10: + case CODEC_ID_RV20: + case CODEC_ID_RV30: + case CODEC_ID_RV40: + m_pFormatName = "am-rv"; + break; + case CODEC_ID_VC1: + m_pFormatName = "am-vc1"; + break; + case CODEC_ID_WMV3: + m_pFormatName = "am-wmv3"; + break; + default: + return false; + break; + } + + m_hints = hints; + m_Codec = new CAmlogic(); + if (!m_Codec) + { + CLog::Log(LOGERROR, "%s: Failed to create Amlogic Codec", __MODULE_NAME__); + return false; + } + m_opened = false; + + // allocate a dummy DVDVideoPicture buffer. + // first make sure all properties are reset. + memset(&m_videobuffer, 0, sizeof(DVDVideoPicture)); + + m_videobuffer.dts = DVD_NOPTS_VALUE; + m_videobuffer.pts = DVD_NOPTS_VALUE; + m_videobuffer.format = RENDER_FMT_BYPASS; + m_videobuffer.color_range = 0; + m_videobuffer.color_matrix = 4; + m_videobuffer.iFlags = DVP_FLAG_ALLOCATED; + m_videobuffer.iWidth = hints.width; + m_videobuffer.iHeight = hints.height; + m_videobuffer.iDisplayWidth = hints.width; + m_videobuffer.iDisplayHeight = hints.height; + + CJobManager::GetInstance().Pause(kJobTypeMediaFlags); + if (CJobManager::GetInstance().IsProcessing(kJobTypeMediaFlags) > 0) + { + int timeout_ms = 5000; + // use m_bStop and Sleep so we can get canceled. + while (timeout_ms > 0) + { + if (CJobManager::GetInstance().IsProcessing(kJobTypeMediaFlags) > 0) + { + Sleep(100); + timeout_ms -= 100; + } + else + break; + } + } + + CLog::Log(LOGINFO, "%s: Opened Amlogic Codec", __MODULE_NAME__); + return true; +} + +void CDVDVideoCodecAmlogic::Dispose(void) +{ + if (m_Codec) + { + m_Codec->CloseDecoder(); + m_Codec = NULL; + } + if (m_videobuffer.iFlags & DVP_FLAG_ALLOCATED) + { + m_videobuffer.iFlags = 0; + } + // let thumbgen jobs resume. + CJobManager::GetInstance().UnPause(kJobTypeMediaFlags); +} + +int CDVDVideoCodecAmlogic::Decode(BYTE *pData, int iSize, double dts, double pts) +{ + // Handle Input, add demuxer packet to input queue, we must accept it or + // it will be discarded as DVDPlayerVideo has no concept of "try again". + if (!m_opened) + { + if (m_Codec && !m_Codec->OpenDecoder(m_hints)) + CLog::Log(LOGERROR, "%s: Failed to open Amlogic Codec", __MODULE_NAME__); + m_opened = true; + } + + return m_Codec->Decode(pData, iSize, dts, pts); +} + +void CDVDVideoCodecAmlogic::Reset(void) +{ + m_Codec->Reset(); +} + +bool CDVDVideoCodecAmlogic::GetPicture(DVDVideoPicture* pDvdVideoPicture) +{ + m_Codec->GetPicture(&m_videobuffer); + *pDvdVideoPicture = m_videobuffer; + + return true; +} + +void CDVDVideoCodecAmlogic::SetDropState(bool bDrop) +{ +} + +int CDVDVideoCodecAmlogic::GetDataSize(void) +{ + return m_Codec->GetDataSize(); +} + +double CDVDVideoCodecAmlogic::GetTimeSize(void) +{ + return m_Codec->GetTimeSize(); +} diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h new file mode 100644 index 0000000000000..268acb7711754 --- /dev/null +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h @@ -0,0 +1,51 @@ +#pragma once +/* + * Copyright (C) 2005-2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "DVDVideoCodec.h" +#include "DVDStreamInfo.h" + +class CAmlogic; + +class CDVDVideoCodecAmlogic : public CDVDVideoCodec +{ +public: + CDVDVideoCodecAmlogic(); + virtual ~CDVDVideoCodecAmlogic(); + + // Required overrides + virtual bool Open(CDVDStreamInfo &hints, CDVDCodecOptions &options); + virtual void Dispose(void); + virtual int Decode(BYTE *pData, int iSize, double dts, double pts); + virtual void Reset(void); + virtual bool GetPicture(DVDVideoPicture *pDvdVideoPicture); + virtual void SetDropState(bool bDrop); + virtual int GetDataSize(void); + virtual double GetTimeSize(void); + virtual const char* GetName(void) { return (const char*)m_pFormatName; } + +protected: + CAmlogic *m_Codec; + const char *m_pFormatName; + DVDVideoPicture m_videobuffer; + bool m_opened; + CDVDStreamInfo m_hints; +}; diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in index 176ceff899b83..52438977f236e 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in @@ -23,6 +23,12 @@ SRCS += OpenMaxVideo.cpp SRCS += DVDVideoCodecOpenMax.cpp endif +ifeq (@USE_LIBAMCODEC@,1) +SRCS += Amlogic.cpp +SRCS += DVDVideoCodecAmlogic.cpp +INCLUDES += -I$(prefix)/include/amlplayer +endif + LIB=Video.a include @abs_top_srcdir@/Makefile.include diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp index 0cd2510056a82..191df88afc233 100644 --- a/xbmc/cores/dvdplayer/DVDPlayer.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp @@ -2862,7 +2862,9 @@ bool CDVDPlayer::OpenVideoStream(int iStream, int source, bool reset) hint.aspect = aspect; hint.forced_aspect = true; } +#if !defined(HAS_LIBAMCODEC) hint.software = true; +#endif } boost::shared_ptr client; From 274669302c3d98b60b494383eef9c4f4ebf9aa6c Mon Sep 17 00:00:00 2001 From: davilla Date: Sun, 2 Dec 2012 10:26:30 -0500 Subject: [PATCH 055/180] [aml] fixed pause/resume under DVDVideoCodecAmlogic --- xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.cpp index 47cf4b97083eb..7c0bf9907cf4d 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.cpp @@ -24,6 +24,7 @@ #include "Amlogic.h" #include "DynamicDll.h" +#include "Application.h" #include "cores/dvdplayer/DVDClock.h" #include "cores/amlplayer/AMLUtils.h" #include "cores/VideoRenderers/RenderManager.h" @@ -1696,6 +1697,14 @@ void CAmlogic::Process() if (m_dll->codec_poll_cntl(&am_private->vcodec) <= 0) Sleep(10); + if (g_application.m_pPlayer && g_application.m_pPlayer->IsPlaying()) + { + if (g_application.m_pPlayer->IsPaused()) + PauseResume(1); + else + PauseResume(2); + } + cur_pts = get_pts_video(); if (m_cur_pts != cur_pts) { From 20d089f3a5ced43d791afb8b91bee0c382946395 Mon Sep 17 00:00:00 2001 From: davilla Date: Sun, 2 Dec 2012 11:27:57 -0500 Subject: [PATCH 056/180] [aml] move AMLUtils.cpp to utils dir and conditional build on amcodec or amlplayer set in configure --- .gitignore | 2 + configure.in | 3 +- tools/amlogic/depends/xbmc/xbmc.mk | 2 +- xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 2 +- .../AudioEngine/Sinks/AESinkAUDIOTRACK.cpp | 4 +- xbmc/cores/amlplayer/AMLPlayer.cpp | 2 +- xbmc/cores/amlplayer/Makefile.in | 2 - .../dvdplayer/DVDCodecs/Video/Amlogic.cpp | 2 +- xbmc/{cores/amlplayer => utils}/AMLUtils.cpp | 0 xbmc/{cores/amlplayer => utils}/AMLUtils.h | 0 xbmc/utils/Makefile | 79 ----------------- xbmc/utils/Makefile.in | 84 +++++++++++++++++++ 12 files changed, 94 insertions(+), 88 deletions(-) rename xbmc/{cores/amlplayer => utils}/AMLUtils.cpp (100%) rename xbmc/{cores/amlplayer => utils}/AMLUtils.h (100%) delete mode 100644 xbmc/utils/Makefile create mode 100644 xbmc/utils/Makefile.in diff --git a/.gitignore b/.gitignore index d5a19a1ec6832..c29bcdf3c9361 100644 --- a/.gitignore +++ b/.gitignore @@ -591,6 +591,8 @@ lib/cmyth/Makefile /xbmc/cores/amlplayer/Makefile /xbmc/cores/omxplayer/Makefile +/xbmc/utils/Makefile + # /lib/ffmpeg/ /lib/ffmpeg/config.h /lib/ffmpeg/config.err diff --git a/configure.in b/configure.in index dd6409c9542ac..63d4fd95ab8ca 100644 --- a/configure.in +++ b/configure.in @@ -2419,7 +2419,8 @@ OUTPUT_FILES="Makefile \ xbmc/peripherals/devices/Makefile \ xbmc/android/activity/Makefile \ xbmc/android/loader/Makefile \ - xbmc/main/Makefile" + xbmc/main/Makefile \ + xbmc/utils/Makefile" if test "$use_skin_touched" = "yes"; then OUTPUT_FILES="$OUTPUT_FILES addons/skin.touched/media/Makefile" diff --git a/tools/amlogic/depends/xbmc/xbmc.mk b/tools/amlogic/depends/xbmc/xbmc.mk index bc3191bfc5ec7..da2ae74b1bc6e 100644 --- a/tools/amlogic/depends/xbmc/xbmc.mk +++ b/tools/amlogic/depends/xbmc/xbmc.mk @@ -9,7 +9,7 @@ $(SOURCE)/xbmc.bin: $(SOURCE)/Makefile $(SOURCE)/Makefile: $(SOURCE)/configure cd $(SOURCE); $(TARGET_CONFIGURE_OPTS) $(TARGET_CONFIGURE_ARGS) $(XBMC_CONF_ENV) \ ./configure --target=$(GNU_TARGET_NAME) --host=$(GNU_TARGET_NAME) --build=$(GNU_HOST_NAME) \ - --prefix=/usr --exec-prefix=/usr --sysconfdir=/etc $(XBMC_CONF_OPT) --disable-external-ffmpeg --enable-codec=amcodec + --prefix=/usr --exec-prefix=/usr --sysconfdir=/etc $(XBMC_CONF_OPT) --disable-external-ffmpeg $(SOURCE)/configure: $(BUILDROOT)/package/thirdparty/xbmc/xbmc.mk $(GCC) cd $(SOURCE); ./bootstrap diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp index d72161755cd9b..da79a4d3b7cc1 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp @@ -34,7 +34,7 @@ #include "threads/SingleLock.h" #include "settings/GUISettings.h" #if defined(HAS_AMLPLAYER) || defined(HAS_LIBAMCODEC) -#include "cores/amlplayer/AMLUtils.h" +#include "utils/AMLUtils.h" #endif #define ALSA_OPTIONS (SND_PCM_NONBLOCK | SND_PCM_NO_AUTO_FORMAT | SND_PCM_NO_AUTO_CHANNELS | SND_PCM_NO_AUTO_RESAMPLE) diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp index b885caa99002a..2b345c0934144 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp @@ -23,8 +23,8 @@ #include "Utils/AERingBuffer.h" #include "android/activity/XBMCApp.h" #include "utils/log.h" -#if defined(HAS_AMLPLAYER) -#include "cores/amlplayer/AMLUtils.h" +#if defined(HAS_AMLPLAYER) || defined(HAS_LIBAMCODEC) +#include "utils/AMLUtils.h" #endif #include diff --git a/xbmc/cores/amlplayer/AMLPlayer.cpp b/xbmc/cores/amlplayer/AMLPlayer.cpp index 60a4c42173502..33b318a911184 100644 --- a/xbmc/cores/amlplayer/AMLPlayer.cpp +++ b/xbmc/cores/amlplayer/AMLPlayer.cpp @@ -54,7 +54,7 @@ #include "settings/VideoSettings.h" // amlogic libplayer -#include "AMLUtils.h" +#include "utils/AMLUtils.h" #include "DllLibamplayer.h" struct AMLChapterInfo diff --git a/xbmc/cores/amlplayer/Makefile.in b/xbmc/cores/amlplayer/Makefile.in index 3d16c3daebcf7..93c0103ad6ecd 100644 --- a/xbmc/cores/amlplayer/Makefile.in +++ b/xbmc/cores/amlplayer/Makefile.in @@ -3,7 +3,6 @@ INCLUDES += -I$(prefix)/include/amlplayer SRCS = AMLPlayer.cpp -SRCS+= AMLUtils.cpp SRCS+= FileURLProtocol.cpp LIB = amlplayer.a @@ -13,4 +12,3 @@ LIB = amlplayer.a include @abs_top_srcdir@/Makefile.include -include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS))) - diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.cpp index 7c0bf9907cf4d..dca6dbcf8e3f2 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.cpp @@ -26,9 +26,9 @@ #include "Application.h" #include "cores/dvdplayer/DVDClock.h" -#include "cores/amlplayer/AMLUtils.h" #include "cores/VideoRenderers/RenderManager.h" #include "settings/Settings.h" +#include "utils/AMLUtils.h" #include "utils/log.h" #include "utils/TimeUtils.h" diff --git a/xbmc/cores/amlplayer/AMLUtils.cpp b/xbmc/utils/AMLUtils.cpp similarity index 100% rename from xbmc/cores/amlplayer/AMLUtils.cpp rename to xbmc/utils/AMLUtils.cpp diff --git a/xbmc/cores/amlplayer/AMLUtils.h b/xbmc/utils/AMLUtils.h similarity index 100% rename from xbmc/cores/amlplayer/AMLUtils.h rename to xbmc/utils/AMLUtils.h diff --git a/xbmc/utils/Makefile b/xbmc/utils/Makefile deleted file mode 100644 index b9b1bda4a8820..0000000000000 --- a/xbmc/utils/Makefile +++ /dev/null @@ -1,79 +0,0 @@ -SRCS=AlarmClock.cpp \ - AliasShortcutUtils.cpp \ - Archive.cpp \ - AsyncFileCopy.cpp \ - AutoPtrHandle.cpp \ - Base64.cpp \ - BitstreamConverter.cpp \ - BitstreamStats.cpp \ - CharsetConverter.cpp \ - CPUInfo.cpp \ - Crc32.cpp \ - CryptThreading.cpp \ - DatabaseUtils.cpp \ - DownloadQueue.cpp \ - DownloadQueueManager.cpp \ - EndianSwap.cpp \ - EdenVideoArtUpdater.cpp \ - Fanart.cpp \ - fastmemcpy.c \ - fastmemcpy-arm.S \ - FileOperationJob.cpp \ - FileUtils.cpp \ - fstrcmp.c \ - fft.cpp \ - GLUtils.cpp \ - GroupUtils.cpp \ - HTMLTable.cpp \ - HTMLUtil.cpp \ - HttpHeader.cpp \ - HttpParser.cpp \ - HttpResponse.cpp \ - InfoLoader.cpp \ - JobManager.cpp \ - JSONVariantParser.cpp \ - JSONVariantWriter.cpp \ - LabelFormatter.cpp \ - LangCodeExpander.cpp \ - LCD.cpp \ - LCDFactory.cpp \ - log.cpp \ - md5.cpp \ - Observer.cpp \ - Mime.cpp \ - PerformanceSample.cpp \ - PerformanceStats.cpp \ - POUtils.cpp \ - RecentlyAddedJob.cpp \ - RegExp.cpp \ - RingBuffer.cpp \ - RssReader.cpp \ - ScraperParser.cpp \ - ScraperUrl.cpp \ - Screenshot.cpp \ - SeekHandler.cpp \ - SortUtils.cpp \ - Splash.cpp \ - Stopwatch.cpp \ - StreamDetails.cpp \ - StreamUtils.cpp \ - StringUtils.cpp \ - SystemInfo.cpp \ - TextSearch.cpp \ - TimeSmoother.cpp \ - TimeUtils.cpp \ - TuxBoxUtil.cpp \ - URIUtils.cpp \ - UrlOptions.cpp \ - Variant.cpp \ - Vector.cpp \ - Weather.cpp \ - XBMCTinyXML.cpp \ - XMLUtils.cpp \ - XMLVariantParser.cpp \ - XMLVariantWriter.cpp \ - -LIB=utils.a - -include ../../Makefile.include --include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(patsubst %.S,,$(SRCS)))) diff --git a/xbmc/utils/Makefile.in b/xbmc/utils/Makefile.in new file mode 100644 index 0000000000000..736a5ad85b7a1 --- /dev/null +++ b/xbmc/utils/Makefile.in @@ -0,0 +1,84 @@ +SRCS += AlarmClock.cpp +SRCS += AliasShortcutUtils.cpp +SRCS += Archive.cpp +SRCS += AsyncFileCopy.cpp +ifeq (@USE_LIBAMCODEC@,1) +SRCS += AMLUtils.cpp +else ifeq (@USE_AMLPLAYER@,1) +SRCS += AMLUtils.cpp +endif +SRCS += AutoPtrHandle.cpp +SRCS += Base64.cpp +SRCS += BitstreamConverter.cpp +SRCS += BitstreamStats.cpp +SRCS += CharsetConverter.cpp +SRCS += CPUInfo.cpp +SRCS += Crc32.cpp +SRCS += CryptThreading.cpp +SRCS += DatabaseUtils.cpp +SRCS += DownloadQueue.cpp +SRCS += DownloadQueueManager.cpp +SRCS += EndianSwap.cpp +SRCS += EdenVideoArtUpdater.cpp +SRCS += Fanart.cpp +SRCS += fastmemcpy.c +SRCS += fastmemcpy-arm.S +SRCS += FileOperationJob.cpp +SRCS += FileUtils.cpp +SRCS += fstrcmp.c +SRCS += fft.cpp +SRCS += GLUtils.cpp +SRCS += GroupUtils.cpp +SRCS += HTMLTable.cpp +SRCS += HTMLUtil.cpp +SRCS += HttpHeader.cpp +SRCS += HttpParser.cpp +SRCS += HttpResponse.cpp +SRCS += InfoLoader.cpp +SRCS += JobManager.cpp +SRCS += JSONVariantParser.cpp +SRCS += JSONVariantWriter.cpp +SRCS += LabelFormatter.cpp +SRCS += LangCodeExpander.cpp +SRCS += LCD.cpp +SRCS += LCDFactory.cpp +SRCS += log.cpp +SRCS += md5.cpp +SRCS += Observer.cpp +SRCS += Mime.cpp +SRCS += PerformanceSample.cpp +SRCS += PerformanceStats.cpp +SRCS += POUtils.cpp +SRCS += RecentlyAddedJob.cpp +SRCS += RegExp.cpp +SRCS += RingBuffer.cpp +SRCS += RssReader.cpp +SRCS += ScraperParser.cpp +SRCS += ScraperUrl.cpp +SRCS += Screenshot.cpp +SRCS += SeekHandler.cpp +SRCS += SortUtils.cpp +SRCS += Splash.cpp +SRCS += Stopwatch.cpp +SRCS += StreamDetails.cpp +SRCS += StreamUtils.cpp +SRCS += StringUtils.cpp +SRCS += SystemInfo.cpp +SRCS += TextSearch.cpp +SRCS += TimeSmoother.cpp +SRCS += TimeUtils.cpp +SRCS += TuxBoxUtil.cpp +SRCS += URIUtils.cpp +SRCS += UrlOptions.cpp +SRCS += Variant.cpp +SRCS += Vector.cpp +SRCS += Weather.cpp +SRCS += XBMCTinyXML.cpp +SRCS += XMLUtils.cpp +SRCS += XMLVariantParser.cpp +SRCS += XMLVariantWriter.cpp + +LIB = utils.a + +include @abs_top_srcdir@/Makefile.include +-include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(patsubst %.S,,$(SRCS)))) From aba41259c27f4baadab6ca82df0576e101537dad Mon Sep 17 00:00:00 2001 From: davilla Date: Mon, 3 Dec 2012 14:18:30 -0500 Subject: [PATCH 057/180] [aml] simply a/v sync using DVDVideoCodecAmlogic --- xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.cpp | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.cpp index dca6dbcf8e3f2..6023775385ae7 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.cpp @@ -1714,19 +1714,8 @@ void CAmlogic::Process() m_ready_event.Set(); double app_pts = GetPlayerPtsSeconds(); - double pts_error = (double)cur_pts/PTS_FREQ - app_pts; - - double offset = 0.0; - if ((fabs(pts_error) > 0.10) && fabs(m_app_pts - app_pts) > 0.05) - { - offset = (double)am_private->video_rate / UNIT_FREQ; - //CLog::Log(LOGDEBUG, "CAmlogic::SetDropState, offset(%f), pts_error(%f), %f", - // offset, pts_error, fabs(m_app_pts - app_pts)); - } - // little trick here, if we get told to drop, - // we set pts_pcrscr to current pts clock + 1 frame duration, - // else just the current pts clock. - SyncToPlayerPtsSeconds(offset); + if (fabs((double)cur_pts/PTS_FREQ - app_pts) > 0.10) + SyncToPlayerPtsSeconds(0.0); } } else From 319519f447d6768104b74264baf62d3b2e5e4ab9 Mon Sep 17 00:00:00 2001 From: davilla Date: Tue, 4 Dec 2012 12:54:37 -0500 Subject: [PATCH 058/180] [aml] fixed, do not fill hw video buffer. 2) cosmetic var rename. --- .../dvdplayer/DVDCodecs/Video/Amlogic.cpp | 20 ++++++++++--------- .../cores/dvdplayer/DVDCodecs/Video/Amlogic.h | 1 + 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.cpp index 6023775385ae7..6c5e1720deeb0 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.cpp @@ -1370,6 +1370,7 @@ bool CAmlogic::OpenDecoder(CDVDStreamInfo &hints) m_zoom = -1; m_contrast = -1; m_brightness = -1; + m_vbufsize = 500000 * 2; am_packet_init(&am_private->am_pkt); @@ -1622,9 +1623,9 @@ int CAmlogic::Decode(unsigned char *pData, size_t size, double dts, double pts) m_old_pictcnt = m_cur_pictcnt; rtn = VC_PICTURE; // we got a new pict, try and keep hw buffered demux above 2 seconds. - // this, combined with the above 1 second check, - // keeps hw buffered demux between 1 and 2 seconds. - if (GetTimeSize() < 2.0) + // this, combined with the above 1 second check, keeps hw buffered demux between 1 and 2 seconds. + // we also check to make sure we keep from filling hw buffer. + if (GetTimeSize() < 2.0 && GetDataSize() < m_vbufsize/2) rtn |= VC_BUFFER; } /* @@ -1654,7 +1655,8 @@ bool CAmlogic::GetPicture(DVDVideoPicture *pDvdVideoPicture) int CAmlogic::GetDataSize() { struct buf_status vbuf ={0}; - m_dll->codec_get_vbuf_state(&am_private->vcodec, &vbuf); + if (m_dll->codec_get_vbuf_state(&am_private->vcodec, &vbuf) >= 0) + m_vbufsize = vbuf.size; return vbuf.data_len; } @@ -1688,7 +1690,7 @@ void CAmlogic::Process() SetPriority(THREAD_PRIORITY_ABOVE_NORMAL); while (!m_bStop) { - int64_t cur_pts = 0; + int64_t pts_video = 0; if (am_private->am_pkt.lastpts > 0) { // this is a blocking poll that returns every vsync. @@ -1705,16 +1707,16 @@ void CAmlogic::Process() PauseResume(2); } - cur_pts = get_pts_video(); - if (m_cur_pts != cur_pts) + pts_video = get_pts_video(); + if (m_cur_pts != pts_video) { // other threads look at these, do them first - m_cur_pts = cur_pts; + m_cur_pts = pts_video; m_cur_pictcnt++; m_ready_event.Set(); double app_pts = GetPlayerPtsSeconds(); - if (fabs((double)cur_pts/PTS_FREQ - app_pts) > 0.10) + if (fabs((double)pts_video/PTS_FREQ - app_pts) > 0.10) SyncToPlayerPtsSeconds(0.0); } } diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.h index 2afaf2831ce1c..6badf66d08982 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.h +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.h @@ -71,6 +71,7 @@ class CAmlogic : public CThread volatile int64_t m_cur_pictcnt; volatile int64_t m_old_pictcnt; volatile double m_timesize; + volatile int64_t m_vbufsize; CEvent m_ready_event; CRect m_dst_rect; From 9bfe674d91916851e9add8f4ef4bf51899201306 Mon Sep 17 00:00:00 2001 From: davilla Date: Tue, 4 Dec 2012 14:11:28 -0500 Subject: [PATCH 059/180] [aml] fixed missing checks for HAS_LIBAMCODEC --- xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp | 4 ++-- xbmc/input/linux/LinuxInputDevices.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp index 2b345c0934144..84c9686554c43 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp @@ -72,14 +72,14 @@ CAESinkAUDIOTRACK::CAESinkAUDIOTRACK() { m_sinkbuffer = NULL; m_alignedS16LE = NULL; -#if defined(HAS_AMLPLAYER) +#if defined(HAS_AMLPLAYER) || defined(HAS_LIBAMCODEC) aml_cpufreq_limit(true); #endif } CAESinkAUDIOTRACK::~CAESinkAUDIOTRACK() { -#if defined(HAS_AMLPLAYER) +#if defined(HAS_AMLPLAYER) || defined(HAS_LIBAMCODEC) aml_cpufreq_limit(false); #endif } diff --git a/xbmc/input/linux/LinuxInputDevices.cpp b/xbmc/input/linux/LinuxInputDevices.cpp index 2817c864b7d49..c43fd2bb4283f 100644 --- a/xbmc/input/linux/LinuxInputDevices.cpp +++ b/xbmc/input/linux/LinuxInputDevices.cpp @@ -782,7 +782,7 @@ void CLinuxInputDevice::SetupKeyboardAutoRepeat(int fd) { bool enable = true; -#if defined(HAS_AMLPLAYER) +#if defined(HAS_AMLPLAYER) || defined(HAS_LIBAMCODEC) // ignore the native aml driver named 'key_input', // it is the dedicated power key handler (am_key_input) if (strncmp(m_deviceName, "key_input", strlen("key_input")) == 0) From bde45a14a7e0931120d1466e911e9b7146b9a4c6 Mon Sep 17 00:00:00 2001 From: davilla Date: Wed, 5 Dec 2012 16:59:51 -0500 Subject: [PATCH 060/180] [aml] changed, add iPhysicalId (pid) to hints --- xbmc/cores/dvdplayer/DVDStreamInfo.cpp | 4 ++++ xbmc/cores/dvdplayer/DVDStreamInfo.h | 1 + 2 files changed, 5 insertions(+) diff --git a/xbmc/cores/dvdplayer/DVDStreamInfo.cpp b/xbmc/cores/dvdplayer/DVDStreamInfo.cpp index 36cf79852ff67..4d051753b5731 100644 --- a/xbmc/cores/dvdplayer/DVDStreamInfo.cpp +++ b/xbmc/cores/dvdplayer/DVDStreamInfo.cpp @@ -60,6 +60,7 @@ void CDVDStreamInfo::Clear() ptsinvalid = false; forced_aspect = false; bitsperpixel = 0; + pid = 0; channels = 0; samplerate = 0; @@ -98,6 +99,7 @@ bool CDVDStreamInfo::Equal(const CDVDStreamInfo& right, bool withextradata) || ptsinvalid != right.ptsinvalid || forced_aspect != right.forced_aspect || bitsperpixel != right.bitsperpixel + || pid != right.pid || vfr != right.vfr) return false; // AUDIO @@ -155,6 +157,7 @@ void CDVDStreamInfo::Assign(const CDVDStreamInfo& right, bool withextradata) forced_aspect = right.forced_aspect; orientation = right.orientation; bitsperpixel = right.bitsperpixel; + pid = right.pid; // AUDIO channels = right.channels; @@ -206,6 +209,7 @@ void CDVDStreamInfo::Assign(const CDemuxStream& right, bool withextradata) forced_aspect = stream->bForcedAspect; orientation = stream->iOrientation; bitsperpixel = stream->iBitsPerPixel; + pid = stream->iPhysicalId; } else if( right.type == STREAM_SUBTITLE ) { diff --git a/xbmc/cores/dvdplayer/DVDStreamInfo.h b/xbmc/cores/dvdplayer/DVDStreamInfo.h index e4fec0f047f98..825e7e67e6205 100644 --- a/xbmc/cores/dvdplayer/DVDStreamInfo.h +++ b/xbmc/cores/dvdplayer/DVDStreamInfo.h @@ -78,6 +78,7 @@ class CDVDStreamInfo bool forced_aspect; // aspect is forced from container int orientation; // orientation of the video in degress counter clockwise int bitsperpixel; + int pid; // AUDIO int channels; From e727a1b32bb6ed3ad7a327e92ba41ef0e4483206 Mon Sep 17 00:00:00 2001 From: davilla Date: Wed, 5 Dec 2012 17:00:57 -0500 Subject: [PATCH 061/180] [aml] fixed crash wirh realmedia content --- .../dvdplayer/DVDCodecs/Video/Amlogic.cpp | 45 ++++++++++++------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.cpp index 6c5e1720deeb0..668e9cc7d55cf 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.cpp @@ -150,6 +150,8 @@ class DllLibAmCodec : public DllDynamic, DllLibamCodecInterface // missing tags #define CODEC_TAG_VC_1 (0x312D4356) +#define CODEC_TAG_RV30 (0x30335652) +#define CODEC_TAG_RV40 (0x30345652) #define RW_WAIT_TIME (20 * 1000) // 20ms @@ -329,7 +331,7 @@ static vformat_t codecid_to_vformat(enum CodecID id) break; } - CLog::Log(LOGDEBUG, "codecid_to_vformat, format(%d), id(%d)", format, (int)id); + CLog::Log(LOGDEBUG, "codecid_to_vformat, id(%d) -> vformat(%d)", (int)id, format); return format; } @@ -382,9 +384,11 @@ static vdec_type_t codec_tag_to_vdec_type(unsigned int codec_tag) dec_type = VIDEO_DEC_FORMAT_H264; break; case CODEC_ID_RV30: + case CODEC_TAG_RV30: dec_type = VIDEO_DEC_FORMAT_REAL_8; break; case CODEC_ID_RV40: + case CODEC_TAG_RV40: dec_type = VIDEO_DEC_FORMAT_REAL_9; break; case CODEC_ID_H264: @@ -399,7 +403,7 @@ static vdec_type_t codec_tag_to_vdec_type(unsigned int codec_tag) dec_type = VIDEO_DEC_FORMAT_WMV3; break; case CODEC_ID_VC1: - //case CODEC_TAG_VC_1: + case CODEC_TAG_VC_1: case CODEC_TAG_WVC1: case CODEC_TAG_WMVA: dec_type = VIDEO_DEC_FORMAT_WVC1; @@ -412,7 +416,7 @@ static vdec_type_t codec_tag_to_vdec_type(unsigned int codec_tag) break; } - CLog::Log(LOGDEBUG, "codec_tag_to_vdec_type, dec_type(%d), codec_tag(%d)", dec_type, codec_tag); + CLog::Log(LOGDEBUG, "codec_tag_to_vdec_type, codec_tag(%d) -> vdec_type(%d)", codec_tag, dec_type); return dec_type; } @@ -540,6 +544,9 @@ int check_avbuffer_enough(am_private_t *para, am_packet_t *pkt) int write_av_packet(am_private_t *para, am_packet_t *pkt) { + //CLog::Log(LOGDEBUG, "write_av_packet, pkt->isvalid(%d), pkt->data(%p), pkt->data_size(%d)", + // pkt->isvalid, pkt->data, pkt->data_size); + int write_bytes = 0, len = 0, ret; unsigned char *buf; int size; @@ -1381,8 +1388,8 @@ bool CAmlogic::OpenDecoder(CDVDStreamInfo &hints) am_private->video_height = hints.height; am_private->video_codec_id = hints.codec; am_private->video_codec_tag = hints.codec_tag; - //am_private->video_pid = hints.idphysical; - am_private->video_pid = -1; + am_private->video_pid = hints.pid; + //am_private->video_pid = 0; AVRational video_ratio = m_dll->av_d2q(1, SHRT_MAX); //if (!hints.forced_aspect) @@ -1412,11 +1419,16 @@ bool CAmlogic::OpenDecoder(CDVDStreamInfo &hints) am_private->video_rotation_degree = 3; // handle extradata am_private->video_format = codecid_to_vformat(hints.codec); - if (am_private->video_format != VFORMAT_MPEG12) + switch (am_private->video_format) { - am_private->extrasize = hints.extrasize; - am_private->extradata = (uint8_t*)malloc(hints.extrasize); - memcpy(am_private->extradata, hints.extradata, hints.extrasize); + default: + am_private->extrasize = hints.extrasize; + am_private->extradata = (uint8_t*)malloc(hints.extrasize); + memcpy(am_private->extradata, hints.extradata, hints.extrasize); + break; + case VFORMAT_REAL: + case VFORMAT_MPEG12: + break; } if (am_private->stream_type == AM_STREAM_ES && am_private->video_codec_tag != 0) @@ -1464,9 +1476,12 @@ bool CAmlogic::OpenDecoder(CDVDStreamInfo &hints) am_private->vcodec.am_sysinfo.param = (void*)(EXTERNAL_PTS | SYNC_OUTSIDE); break; case VFORMAT_REAL: + am_private->stream_type = AM_STREAM_RM; + am_private->vcodec.stream_type = STREAM_TYPE_RM; + am_private->vcodec.am_sysinfo.ratio = 0x100; + am_private->vcodec.am_sysinfo.ratio64 = 0; { - static unsigned short tbl[9]; - am_private->vcodec.am_sysinfo.ratio = 0x100; + static unsigned short tbl[9] = {0}; if (VIDEO_DEC_FORMAT_REAL_8 == am_private->video_codec_type) { am_private->vcodec.am_sysinfo.extra = am_private->extradata[1] & 7; @@ -1481,8 +1496,6 @@ bool CAmlogic::OpenDecoder(CDVDStreamInfo &hints) } am_private->vcodec.am_sysinfo.param = &tbl; } - am_private->stream_type = AM_STREAM_RM; - am_private->vcodec.stream_type = STREAM_TYPE_RM; break; case VFORMAT_VC1: // vc1 is extension id, from 0xfd55 to 0xfd5f according to ffmpeg @@ -1494,7 +1507,7 @@ bool CAmlogic::OpenDecoder(CDVDStreamInfo &hints) int ret = m_dll->codec_init(&am_private->vcodec); if (ret != CODEC_ERROR_NONE) { - CLog::Log(LOGDEBUG, "CAmlogic::OpenDecoder codec init failed, ret=-0x%x", -ret); + CLog::Log(LOGDEBUG, "CAmlogic::OpenDecoder codec init failed, ret=0x%x", -ret); return false; } @@ -1655,7 +1668,7 @@ bool CAmlogic::GetPicture(DVDVideoPicture *pDvdVideoPicture) int CAmlogic::GetDataSize() { struct buf_status vbuf ={0}; - if (m_dll->codec_get_vbuf_state(&am_private->vcodec, &vbuf) >= 0) + if (am_private->vcodec.handle && m_dll->codec_get_vbuf_state(&am_private->vcodec, &vbuf) >= 0) m_vbufsize = vbuf.size; return vbuf.data_len; @@ -1691,7 +1704,7 @@ void CAmlogic::Process() while (!m_bStop) { int64_t pts_video = 0; - if (am_private->am_pkt.lastpts > 0) + if (am_private->vcodec.handle && am_private->am_pkt.lastpts > 0) { // this is a blocking poll that returns every vsync. // since we are running at a higher priority, make sure From e2a8156e17fc18af7f745bc4afbc5501d68cd287 Mon Sep 17 00:00:00 2001 From: davilla Date: Wed, 5 Dec 2012 17:01:47 -0500 Subject: [PATCH 062/180] [aml] changed, allow ALSA to suspend --- xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 21 +++++++++++++++++++++ xbmc/cores/AudioEngine/Sinks/AESinkALSA.h | 2 ++ 2 files changed, 23 insertions(+) diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp index da79a4d3b7cc1..2819d984d0779 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp @@ -552,6 +552,27 @@ void CAESinkALSA::HandleError(const char* name, int err) } } +bool CAESinkALSA::SoftSuspend() +{ + /* Sink has been asked to suspend output - we release audio */ + /* device as we are in exclusive mode and thus allow external */ + /* audio sources to play. This requires us to reinitialize */ + /* on resume. */ + + Deinitialize(); + + return true; +} + +bool CAESinkALSA::SoftResume() +{ + /* Sink asked to resume output. To release audio device in */ + /* exclusive mode we release the device context and therefore */ + /* must reinitialize. Return false to force re-init by engine */ + + return false; +} + void CAESinkALSA::Drain() { if (!m_pcm) diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h index db1ba802901f9..7d4ba71fb8224 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h +++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h @@ -48,6 +48,8 @@ class CAESinkALSA : public IAESink virtual double GetCacheTime (); virtual double GetCacheTotal (); virtual unsigned int AddPackets (uint8_t *data, unsigned int frames, bool hasAudio); + virtual bool SoftSuspend (); + virtual bool SoftResume (); virtual void Drain (); static void EnumerateDevicesEx(AEDeviceInfoList &list); From 39d7052e86c3a1839969d03199a5d149dad84ec6 Mon Sep 17 00:00:00 2001 From: davilla Date: Wed, 5 Dec 2012 17:03:57 -0500 Subject: [PATCH 063/180] [aml] changed, if amcodec is enabled, do not use amlplayer for main playback --- xbmc/cores/amlplayer/Makefile.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xbmc/cores/amlplayer/Makefile.in b/xbmc/cores/amlplayer/Makefile.in index 93c0103ad6ecd..1645cf26c2e56 100644 --- a/xbmc/cores/amlplayer/Makefile.in +++ b/xbmc/cores/amlplayer/Makefile.in @@ -7,8 +7,10 @@ SRCS+= FileURLProtocol.cpp LIB = amlplayer.a +ifneq (@USE_LIBAMCODEC@,1) @abs_top_srcdir@/system/advancedsettings.xml: $(LIB) cp -f amlplayer_advancedsettings.xml $@ +endif include @abs_top_srcdir@/Makefile.include -include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS))) From 7bb6c2486fa659a18d42420ba48f729f97ea8982 Mon Sep 17 00:00:00 2001 From: davilla Date: Wed, 5 Dec 2012 17:05:40 -0500 Subject: [PATCH 064/180] [aml] changed, suspend/resume SoftAE audio when amlplayer is used --- xbmc/cores/amlplayer/AMLPlayer.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/xbmc/cores/amlplayer/AMLPlayer.cpp b/xbmc/cores/amlplayer/AMLPlayer.cpp index 33b318a911184..69ae5f93312a3 100644 --- a/xbmc/cores/amlplayer/AMLPlayer.cpp +++ b/xbmc/cores/amlplayer/AMLPlayer.cpp @@ -27,6 +27,7 @@ #include "GUIInfoManager.h" #include "video/VideoThumbLoader.h" #include "Util.h" +#include "cores/AudioEngine/AEFactory.h" #include "cores/VideoRenderers/RenderFlags.h" #include "cores/VideoRenderers/RenderFormats.h" #include "cores/VideoRenderers/RenderManager.h" @@ -533,6 +534,13 @@ CAMLPlayer::CAMLPlayer(IPlayerCallback &callback) // for external subtitles m_dvdOverlayContainer = new CDVDOverlayContainer; m_dvdPlayerSubtitle = new CDVDPlayerSubtitle(m_dvdOverlayContainer); + + // Suspend AE temporarily so exclusive or hog-mode sinks + // don't block external player's access to audio device + if (!CAEFactory::Suspend()) + { + CLog::Log(LOGNOTICE,"%s: Failed to suspend AudioEngine before launching external player", __FUNCTION__); + } } CAMLPlayer::~CAMLPlayer() @@ -542,6 +550,12 @@ CAMLPlayer::~CAMLPlayer() delete m_dvdPlayerSubtitle; delete m_dvdOverlayContainer; delete m_dll, m_dll = NULL; + + // Resume AE processing of XBMC native audio + if (!CAEFactory::Resume()) + { + CLog::Log(LOGFATAL, "%s: Failed to restart AudioEngine after return from external player",__FUNCTION__); + } } bool CAMLPlayer::OpenFile(const CFileItem &file, const CPlayerOptions &options) From 432224d9ef3f2d7cbbceef6fd33e53c632684a9a Mon Sep 17 00:00:00 2001 From: davilla Date: Wed, 5 Dec 2012 17:07:09 -0500 Subject: [PATCH 065/180] [aml] changed, play realmedai using amlplayer, we cannot play it using DVDVideoCodecAmlogic --- system/playercorefactory.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/system/playercorefactory.xml b/system/playercorefactory.xml index 3fdb283d0ea92..badc84f1d75b0 100644 --- a/system/playercorefactory.xml +++ b/system/playercorefactory.xml @@ -36,5 +36,8 @@ + + + From fb837c6e4c57a05e056c5f24d8ff39f845e9ed49 Mon Sep 17 00:00:00 2001 From: davilla Date: Wed, 5 Dec 2012 17:40:42 -0500 Subject: [PATCH 066/180] [aml] rename Amlogic.xxx to AMLCodec.xxx --- .../dvdplayer/DVDCodecs/Video/{Amlogic.cpp => AMLCodec.cpp} | 2 +- xbmc/cores/dvdplayer/DVDCodecs/Video/{Amlogic.h => AMLCodec.h} | 0 xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp | 2 +- xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename xbmc/cores/dvdplayer/DVDCodecs/Video/{Amlogic.cpp => AMLCodec.cpp} (99%) rename xbmc/cores/dvdplayer/DVDCodecs/Video/{Amlogic.h => AMLCodec.h} (100%) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp similarity index 99% rename from xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.cpp rename to xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index 668e9cc7d55cf..50830550d6f70 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -21,7 +21,7 @@ #include "system.h" -#include "Amlogic.h" +#include "AMLCodec.h" #include "DynamicDll.h" #include "Application.h" diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.h similarity index 100% rename from xbmc/cores/dvdplayer/DVDCodecs/Video/Amlogic.h rename to xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.h diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp index 98f3fd04cd98c..204209cf2d46d 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp @@ -22,7 +22,7 @@ #include "DVDVideoCodecAmlogic.h" #include "DVDClock.h" #include "DVDStreamInfo.h" -#include "Amlogic.h" +#include "AMLCodec.h" #include "video/VideoThumbLoader.h" #include "utils/log.h" diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in index 52438977f236e..157b6b325efe8 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in @@ -24,7 +24,7 @@ SRCS += DVDVideoCodecOpenMax.cpp endif ifeq (@USE_LIBAMCODEC@,1) -SRCS += Amlogic.cpp +SRCS += AMLCodec.cpp SRCS += DVDVideoCodecAmlogic.cpp INCLUDES += -I$(prefix)/include/amlplayer endif From 82e3c7524a4e453ff09d935ae23e1196169dcc43 Mon Sep 17 00:00:00 2001 From: davilla Date: Fri, 7 Dec 2012 10:14:50 -0500 Subject: [PATCH 067/180] [aml] changed xbmc/android to support amcodec --- tools/android/depends/xbmc/Makefile | 3 ++- tools/android/packaging/config/advancedsettings.xml | 4 ---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/tools/android/depends/xbmc/Makefile b/tools/android/depends/xbmc/Makefile index afd03c6671098..986b19855143b 100644 --- a/tools/android/depends/xbmc/Makefile +++ b/tools/android/depends/xbmc/Makefile @@ -20,7 +20,8 @@ CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) build-aux/ ;\ --enable-neon --enable-gles --enable-debug \ --disable-sdl --disable-x11 --disable-xrandr \ --disable-optical-drive --disable-joystick \ - --enable-shared-lib --disable-alsa --enable-player=amlplayer + --enable-shared-lib --disable-alsa \ + --enable-codec=amcodec --enable-player=amlplayer all: $(SOURCE)/libxbmc.so diff --git a/tools/android/packaging/config/advancedsettings.xml b/tools/android/packaging/config/advancedsettings.xml index aef3196a44aba..9db825232b7d3 100644 --- a/tools/android/packaging/config/advancedsettings.xml +++ b/tools/android/packaging/config/advancedsettings.xml @@ -1,8 +1,4 @@ - - lookandfeel.soundskin videoplayer.rendermethod From db904ac279e01139086fda81d40bbe4d0ebb5d1a Mon Sep 17 00:00:00 2001 From: davilla Date: Fri, 7 Dec 2012 10:23:14 -0500 Subject: [PATCH 068/180] [aml] fix passthough on android, system volume must be set to max before running xbmc --- .../AudioEngine/Sinks/AESinkAUDIOTRACK.cpp | 54 +++++++++++++++++-- .../AudioEngine/Sinks/AESinkAUDIOTRACK.h | 2 + 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp index 84c9686554c43..ed938de783063 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp @@ -88,6 +88,16 @@ bool CAESinkAUDIOTRACK::Initialize(AEAudioFormat &format, std::string &device) { m_format = format; + if (AE_IS_RAW(format.m_dataFormat)) + m_passthrough = true; + else + m_passthrough = false; + +#if defined(HAS_LIBAMCODEC) + if (aml_present()) + aml_set_audio_passthrough(m_passthrough); +#endif + // default to 44100, all android devices support it. // then check if we can support the requested rate. unsigned int sampleRate = 44100; @@ -231,7 +241,8 @@ bool CAESinkAUDIOTRACK::HasVolume() void CAESinkAUDIOTRACK::SetVolume(float volume) { m_volume = volume; - m_volume_changed = true; + if (!m_passthrough) + m_volume_changed = true; } void CAESinkAUDIOTRACK::EnumerateDevicesEx(AEDeviceInfoList &list) @@ -263,7 +274,38 @@ void CAESinkAUDIOTRACK::Process() JNIEnv *jenv = NULL; CXBMCApp::AttachCurrentThread(&jenv, NULL); - +/* + in Java + AudioManager audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE); + int cur_volume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); + int max_volume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); + mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, max_volume, 0); +*/ + +/* + jobject oActivity = state->activity->clazz; + jclass cActivity = env->GetObjectClass(oActivity); + + jmethodID jmGetSystemService = jenv->GetMethodID(cActivity, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;"); + jstring jsAudioService = jenv->NewStringUTF("audio"); + jobject joAudioManager = jenv->CallObjectMethod(oActivity, jmGetSystemService, jsAudioService); + jclass jcAudioManager = jenv->GetObjectClass(joAudioManager); + + jmethodID jm_getStreamVolume = jenv->GetMethodID(jcAudioManager, "getStreamVolume", "(I)I"); + jmethodID jm_setStreamVolume = jenv->GetMethodID(jcAudioManager, "setStreamVolume", "(III)V"); + jmethodID jm_getStreamMaxVolume = jenv->GetMethodID(jcAudioManager, "getStreamMaxVolume", "(I)I"); + + jint flags = 0; + jint stream_music = GetStaticIntField(jenv, "AudioManager", "STREAM_MUSIC"); + jint stream_system = GetStaticIntField(jenv, "AudioManager", "STREAM_SYSTEM"); + jint cur_volume = jenv->CallIntMethod(joAudioManager, jm_getStreamVolume, stream_music); + jint max_volume = jenv->CallIntMethod(joAudioManager, jm_getStreamMaxVolume, stream_music); + jenv->CallIntMethod(joAudioManager, jm_setStreamVolume, stream_music, max_volume, flags); + + env->DeleteLocalRef(jsAudioService); + env->DeleteLocalRef(joAudioManager); + env->DeleteLocalRef(jcAudioManager); +*/ jclass jcAudioTrack = jenv->FindClass("android/media/AudioTrack"); jmethodID jmInit = jenv->GetMethodID(jcAudioTrack, "", "(IIIIII)V"); @@ -302,6 +344,12 @@ void CAESinkAUDIOTRACK::Process() min_buffer_size, GetStaticIntField(jenv, "AudioTrack", "MODE_STREAM")); + // Set the initial volume + jfloat jvolume = 1.0; + if (!m_passthrough) + jvolume = m_volume; + jenv->CallIntMethod(joAudioTrack, jmSetStereoVolume, jvolume, jvolume); + // The AudioTrack object has been created and waiting to play, m_inited.Set(); // yield to give other threads a chance to do some work. @@ -318,7 +366,7 @@ void CAESinkAUDIOTRACK::Process() while (!m_bStop) { - if (m_volume_changed) + if (m_volume_changed && !m_passthrough) { // check of volume changes and make them, // do it here to keep jni calls local to this thread. diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h index e7ac7fce44802..b92c812078ddd 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h +++ b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h @@ -62,6 +62,8 @@ class CAESinkAUDIOTRACK : public CThread, public IAESink CEvent m_wake; CEvent m_inited; volatile bool m_draining; + bool m_passthrough; + double m_audiotrackbuffer_sec; double m_audiotrack_empty_sec; }; From 49026bc9a27b49f868faa55c22e8c1428b198219 Mon Sep 17 00:00:00 2001 From: davilla Date: Fri, 7 Dec 2012 15:28:55 -0500 Subject: [PATCH 069/180] [aml] cosmetics --- xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index 50830550d6f70..199b990820e61 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -99,7 +99,7 @@ class DllLibAmCodec : public DllDynamic, DllLibamCodecInterface DEFINE_METHOD2(int, codec_set_cntl_avthresh, (codec_para_t *p1, unsigned int p2)) DEFINE_METHOD2(int, codec_set_cntl_syncthresh,(codec_para_t *p1, unsigned int p2)) - DEFINE_METHOD2(int, codec_audio_set_delay, (codec_para_t *p1, int p2)) + DEFINE_METHOD2(int, codec_audio_set_delay, (codec_para_t *p1, int p2)) DEFINE_METHOD4(int, h263vld, (unsigned char *p1, unsigned char *p2, int p3, int p4)) DEFINE_METHOD1(int, decodeble_h263, (unsigned char *p1)) From e509e31fd3ddb43487bd5624eeb3b6992c809222 Mon Sep 17 00:00:00 2001 From: davilla Date: Sat, 8 Dec 2012 10:41:58 -0500 Subject: [PATCH 070/180] [aml] fixed, force system volume to max so passthrough works --- .../packaging/xbmc/src/org/xbmc/xbmc/Splash.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tools/android/packaging/xbmc/src/org/xbmc/xbmc/Splash.java b/tools/android/packaging/xbmc/src/org/xbmc/xbmc/Splash.java index c008c01361b9a..af7946e1db45d 100644 --- a/tools/android/packaging/xbmc/src/org/xbmc/xbmc/Splash.java +++ b/tools/android/packaging/xbmc/src/org/xbmc/xbmc/Splash.java @@ -28,6 +28,7 @@ import android.view.View; import android.widget.ProgressBar; import android.widget.TextView; +import android.media.AudioManager; public class Splash extends Activity { @@ -202,6 +203,17 @@ protected void onPostExecute(Integer result) { } } + private boolean SetSystemVolumeMax() { + // Set the hardware buttons to control the music + //this.setVolumeControlStream(AudioManager.STREAM_MUSIC); + + AudioManager mAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE); + int max_volume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); + mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, max_volume, 0); + + return true; + } + private boolean ParseCpuFeature() { ProcessBuilder cmd; @@ -231,6 +243,9 @@ private boolean CheckCpuFeature(String feat) { } protected void startXBMC() { + // Set the system volume to max so passthrough works + boolean ret = SetSystemVolumeMax(); + // Run XBMC Intent intent = new Intent(); intent.setClass(this, android.app.NativeActivity.class); @@ -268,6 +283,7 @@ public void onCreate(Bundle savedInstanceState) { mState = State.InError; } } + if (mState != State.InError) { sPackagePath = getPackageResourcePath(); fPackagePath = new File(sPackagePath); From 0fc4e964b237dc58f209b742efdc9d7a08dadd5e Mon Sep 17 00:00:00 2001 From: davilla Date: Sat, 8 Dec 2012 10:44:21 -0500 Subject: [PATCH 071/180] [aml] remove unused code --- .../AudioEngine/Sinks/AESinkAUDIOTRACK.cpp | 33 +------------------ 1 file changed, 1 insertion(+), 32 deletions(-) diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp index ed938de783063..e6cdb61a4ebb8 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp @@ -274,38 +274,7 @@ void CAESinkAUDIOTRACK::Process() JNIEnv *jenv = NULL; CXBMCApp::AttachCurrentThread(&jenv, NULL); -/* - in Java - AudioManager audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE); - int cur_volume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); - int max_volume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); - mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, max_volume, 0); -*/ - -/* - jobject oActivity = state->activity->clazz; - jclass cActivity = env->GetObjectClass(oActivity); - - jmethodID jmGetSystemService = jenv->GetMethodID(cActivity, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;"); - jstring jsAudioService = jenv->NewStringUTF("audio"); - jobject joAudioManager = jenv->CallObjectMethod(oActivity, jmGetSystemService, jsAudioService); - jclass jcAudioManager = jenv->GetObjectClass(joAudioManager); - - jmethodID jm_getStreamVolume = jenv->GetMethodID(jcAudioManager, "getStreamVolume", "(I)I"); - jmethodID jm_setStreamVolume = jenv->GetMethodID(jcAudioManager, "setStreamVolume", "(III)V"); - jmethodID jm_getStreamMaxVolume = jenv->GetMethodID(jcAudioManager, "getStreamMaxVolume", "(I)I"); - - jint flags = 0; - jint stream_music = GetStaticIntField(jenv, "AudioManager", "STREAM_MUSIC"); - jint stream_system = GetStaticIntField(jenv, "AudioManager", "STREAM_SYSTEM"); - jint cur_volume = jenv->CallIntMethod(joAudioManager, jm_getStreamVolume, stream_music); - jint max_volume = jenv->CallIntMethod(joAudioManager, jm_getStreamMaxVolume, stream_music); - jenv->CallIntMethod(joAudioManager, jm_setStreamVolume, stream_music, max_volume, flags); - - env->DeleteLocalRef(jsAudioService); - env->DeleteLocalRef(joAudioManager); - env->DeleteLocalRef(jcAudioManager); -*/ + jclass jcAudioTrack = jenv->FindClass("android/media/AudioTrack"); jmethodID jmInit = jenv->GetMethodID(jcAudioTrack, "", "(IIIIII)V"); From 8c22e335b82faf541500b7b5b5c6c1bd288c5ff7 Mon Sep 17 00:00:00 2001 From: davilla Date: Sat, 8 Dec 2012 10:46:35 -0500 Subject: [PATCH 072/180] [aml] fixed, use what we can do, not what we are asked to do --- xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp index e6cdb61a4ebb8..1357e3ed0e4b9 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp @@ -88,7 +88,7 @@ bool CAESinkAUDIOTRACK::Initialize(AEAudioFormat &format, std::string &device) { m_format = format; - if (AE_IS_RAW(format.m_dataFormat)) + if (AE_IS_RAW(m_format.m_dataFormat)) m_passthrough = true; else m_passthrough = false; From a23ec3779f5a01d362ecf986cb35c761319b89a1 Mon Sep 17 00:00:00 2001 From: davilla Date: Sat, 8 Dec 2012 14:21:32 -0500 Subject: [PATCH 073/180] [aml] fixed, am_private->vcodec.handle is valid for >= 0 --- xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index 199b990820e61..66ccca9e8e587 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -1668,7 +1668,7 @@ bool CAmlogic::GetPicture(DVDVideoPicture *pDvdVideoPicture) int CAmlogic::GetDataSize() { struct buf_status vbuf ={0}; - if (am_private->vcodec.handle && m_dll->codec_get_vbuf_state(&am_private->vcodec, &vbuf) >= 0) + if (m_dll->codec_get_vbuf_state(&am_private->vcodec, &vbuf) >= 0) m_vbufsize = vbuf.size; return vbuf.data_len; @@ -1704,7 +1704,7 @@ void CAmlogic::Process() while (!m_bStop) { int64_t pts_video = 0; - if (am_private->vcodec.handle && am_private->am_pkt.lastpts > 0) + if (am_private->am_pkt.lastpts > 0) { // this is a blocking poll that returns every vsync. // since we are running at a higher priority, make sure From 51251ff711e71140ef48a7ca331ea744f14b4790 Mon Sep 17 00:00:00 2001 From: davilla Date: Mon, 10 Dec 2012 22:13:50 -0500 Subject: [PATCH 074/180] [aml] changed, make amcodec a/v sync less sensitive --- xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index 66ccca9e8e587..b43c63ec86b85 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -1729,7 +1729,7 @@ void CAmlogic::Process() m_ready_event.Set(); double app_pts = GetPlayerPtsSeconds(); - if (fabs((double)pts_video/PTS_FREQ - app_pts) > 0.10) + if (fabs((double)pts_video/PTS_FREQ - app_pts) > 0.20) SyncToPlayerPtsSeconds(0.0); } } From 70057ce66dc31e92c84883332e4dda655f47a9f1 Mon Sep 17 00:00:00 2001 From: davilla Date: Tue, 11 Dec 2012 19:55:03 -0500 Subject: [PATCH 075/180] [aml] Changed, give android an additional 100ms audio latency --- xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp index 1357e3ed0e4b9..825d39a274969 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp @@ -172,7 +172,7 @@ double CAESinkAUDIOTRACK::GetDelay() // AudioMixer (if any) and audio hardware driver. double sinkbuffer_seconds_to_empty = m_sinkbuffer_sec_per_byte * (double)m_sinkbuffer->GetReadSize(); - return sinkbuffer_seconds_to_empty + m_audiotrack_empty_sec; + return 0.100 + sinkbuffer_seconds_to_empty + m_audiotrack_empty_sec; } double CAESinkAUDIOTRACK::GetCacheTime() From 22c296b38afbc1712141f7a45ff77dee71fd4bb9 Mon Sep 17 00:00:00 2001 From: davilla Date: Tue, 11 Dec 2012 20:06:22 -0500 Subject: [PATCH 076/180] [aml] fixed, audio delay control --- .../dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 26 ++++++++----------- .../dvdplayer/DVDCodecs/Video/AMLCodec.h | 3 +-- xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 7 +++-- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index b43c63ec86b85..a8c78b2d4111d 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -1369,7 +1369,6 @@ bool CAmlogic::OpenDecoder(CDVDStreamInfo &hints) { CLog::Log(LOGDEBUG, "CAmlogic::OpenDecoder"); m_1st_pts = 0; - m_app_pts = 0.0; m_cur_pts = 0; m_cur_pictcnt = 0; m_old_pictcnt = 0; @@ -1575,7 +1574,6 @@ void CAmlogic::Reset() // reset some interal vars m_1st_pts = 0; - m_app_pts = GetPlayerPtsSeconds(); m_cur_pts = 0; m_cur_pictcnt = 0; m_old_pictcnt = 0; @@ -1653,15 +1651,14 @@ bool CAmlogic::GetPicture(DVDVideoPicture *pDvdVideoPicture) { pDvdVideoPicture->dts = DVD_NOPTS_VALUE; pDvdVideoPicture->pts = GetPlayerPtsSeconds() * (double)DVD_TIME_BASE; - //pDvdVideoPicture->pts = (double)m_cur_pts * (double)DVD_TIME_BASE / (double)PTS_FREQ; + // video pts cannot be late or dvdplayer goes nuts, + // so run it one frame ahead + pDvdVideoPicture->pts += pDvdVideoPicture->iDuration; + pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED; pDvdVideoPicture->format = RENDER_FMT_BYPASS; pDvdVideoPicture->iDuration = (double)(am_private->video_rate * DVD_TIME_BASE) / UNIT_FREQ; - // video pts cannot be late or dvdplayer goes nuts, - // so run it two frames ahead - pDvdVideoPicture->pts += pDvdVideoPicture->iDuration; - return true; } @@ -1729,8 +1726,12 @@ void CAmlogic::Process() m_ready_event.Set(); double app_pts = GetPlayerPtsSeconds(); + // add in audio delay/display latency contribution + double offset = g_renderManager.GetDisplayLatency() - g_settings.m_currentVideoSettings.m_AudioDelay; + // correct video pts by user set delay and rendering delay + app_pts += offset; if (fabs((double)pts_video/PTS_FREQ - app_pts) > 0.20) - SyncToPlayerPtsSeconds(0.0); + SetVideoPtsSeconds(app_pts); } } else @@ -1765,14 +1766,9 @@ double CAmlogic::GetPlayerPtsSeconds() return clock_pts; } -void CAmlogic::SyncToPlayerPtsSeconds(const double offset) +void CAmlogic::SetVideoPtsSeconds(const double pts) { - CDVDClock *playerclock = CDVDClock::GetMasterClock(); - if (playerclock) - { - m_app_pts = playerclock->GetClock() / DVD_TIME_BASE; - set_pts_pcrscr((int64_t)((m_app_pts + offset) * PTS_FREQ)); - } + set_pts_pcrscr((int64_t)(pts * PTS_FREQ)); } void CAmlogic::ShowMainVideo(const bool show) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.h index 6badf66d08982..bff6cd6403fd4 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.h +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.h @@ -52,7 +52,7 @@ class CAmlogic : public CThread private: void PauseResume(int state); double GetPlayerPtsSeconds(); - void SyncToPlayerPtsSeconds(double offset); + void SetVideoPtsSeconds(double pts); void ShowMainVideo(const bool show); void SetVideoZoom(const float zoom); void SetVideoContrast(const int contrast); @@ -66,7 +66,6 @@ class CAmlogic : public CThread DllLibAmCodec *m_dll; am_private_t *am_private; volatile int64_t m_1st_pts; - volatile double m_app_pts; volatile int64_t m_cur_pts; volatile int64_t m_cur_pictcnt; volatile int64_t m_old_pictcnt; diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp index 3008c25f845b8..47282001019bb 100644 --- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp @@ -1189,8 +1189,11 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) pts -= DVD_TIME_BASE * interval; } - // Correct pts by user set delay and rendering delay - pts += m_iVideoDelay - DVD_SEC_TO_TIME(g_renderManager.GetDisplayLatency()); + if (m_output.color_format != RENDER_FMT_BYPASS) + { + // Correct pts by user set delay and rendering delay + pts += m_iVideoDelay - DVD_SEC_TO_TIME(g_renderManager.GetDisplayLatency()); + } // calculate the time we need to delay this picture before displaying double iSleepTime, iClockSleep, iFrameSleep, iPlayingClock, iCurrentClock, iFrameDuration; From 3fd79a8eac25490243365407ef900b9d83c163cb Mon Sep 17 00:00:00 2001 From: davilla Date: Sun, 16 Dec 2012 12:06:24 -0500 Subject: [PATCH 077/180] [aml] unhide teletextenabled, subtitles.charset, dvds.playerregion, dvds.automenu and dontnormalizelevels --- tools/android/packaging/config/advancedsettings.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tools/android/packaging/config/advancedsettings.xml b/tools/android/packaging/config/advancedsettings.xml index 9db825232b7d3..f9270929277ce 100644 --- a/tools/android/packaging/config/advancedsettings.xml +++ b/tools/android/packaging/config/advancedsettings.xml @@ -6,10 +6,6 @@ videoplayer.pauseafterrefreshchange videoplayer.usedisplayasclock videoplayer.synctype - videoplayer.teletextenabled - subtitles.charset - dvds.playerregion - dvds.automenu audiocds karaoke videoscreen.screenmode @@ -18,7 +14,6 @@ videoscreen.testpattern audiooutput.mode audiooutput.channellayout - audiooutput.dontnormalizelevels audiooutput.audiodevice audiooutput.customdevice audiooutput.passthroughdevice From a7b17943239b6a0fd578ff204090b2ac434d6ae5 Mon Sep 17 00:00:00 2001 From: davilla Date: Tue, 18 Dec 2012 15:42:23 -0500 Subject: [PATCH 078/180] [aml] fixed, android wifi --- xbmc/network/linux/PosixConnection.cpp | 6 +++- xbmc/network/linux/PosixNetworkManager.cpp | 37 +++++++++++++++------- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/xbmc/network/linux/PosixConnection.cpp b/xbmc/network/linux/PosixConnection.cpp index d4006d0597520..42493ce37d1e7 100644 --- a/xbmc/network/linux/PosixConnection.cpp +++ b/xbmc/network/linux/PosixConnection.cpp @@ -45,7 +45,7 @@ #include #endif -#ifdef TARGET_ANDROID +#if defined(TARGET_ANDROID) #include "android/bionic_supplement/bionic_supplement.h" #include "sys/system_properties.h" #endif @@ -354,9 +354,13 @@ ConnectionState CPosixConnection::GetState() const if (wrq.u.essid.length <= 0) return NETWORK_CONNECTION_STATE_DISCONNECTED; +#if !defined(TARGET_ANDROID) std::string test_essid(essid, wrq.u.essid.length); + // Since Android cannot SIOCSIWSCAN (permissions error), + // m_essid was defaulted to 'Wifi'. So ignore this check. if (m_essid.find(test_essid) == std::string::npos) return NETWORK_CONNECTION_STATE_DISCONNECTED; +#endif } // finally, we need to see if we have a gateway assigned to our interface. diff --git a/xbmc/network/linux/PosixNetworkManager.cpp b/xbmc/network/linux/PosixNetworkManager.cpp index 26674d8c0a0e2..ef629c0da8df2 100644 --- a/xbmc/network/linux/PosixNetworkManager.cpp +++ b/xbmc/network/linux/PosixNetworkManager.cpp @@ -41,6 +41,8 @@ #include "android/bionic_supplement/bionic_supplement.h" #endif +#define ARPHRD_80211 801 // wifi + // CPosixNetworkManager and CPosixConnection rely on the debian/ubuntu method of using // /etc/network/interfaces and pre-up/post-down scripts to handle bringing connection // to wired/wireless networks. The pre-up/post-down scripts handle wireless/wpa though @@ -204,14 +206,14 @@ void CPosixNetworkManager::FindNetworkInterfaces() { m_connections.clear(); - FILE* fp = fopen("/proc/net/dev", "r"); + FILE *fp = fopen("/proc/net/dev", "r"); if (!fp) return; int n, linenum = 0; - char* line = NULL; + char *line = NULL; size_t linel = 0; - char* interfaceName; + char *interfaceName; bool managed = CanManageConnections(); while (getdelim(&line, &linel, '\n', fp) > 0) @@ -233,8 +235,22 @@ void CPosixNetworkManager::FindNetworkInterfaces() struct ifreq ifr; memset(&ifr, 0x00, sizeof(ifr)); strcpy(ifr.ifr_name, interfaceName); + std::string essid = "Wired"; + ConnectionType connection = NETWORK_CONNECTION_TYPE_WIRED; + EncryptionType encryption = NETWORK_CONNECTION_ENCRYPTION_NONE; + if (ioctl(m_socket, SIOCGIFHWADDR, &ifr) >= 0) { +#if defined(TARGET_ANDROID) + // Android cannot SIOCSIWSCAN (permissions error) + // So just flag as wifi with unknown encryption and use it. + if (IsWireless(m_socket, interfaceName)) + { + essid = "Wifi"; + connection = NETWORK_CONNECTION_TYPE_WIFI; + encryption = NETWORK_CONNECTION_ENCRYPTION_UNKNOWN; + } +#else if (IsWireless(m_socket, interfaceName)) { // get the list of access points on this interface, try this 3 times @@ -243,9 +259,12 @@ void CPosixNetworkManager::FindNetworkInterfaces() retryCount++; } else +#endif { - // and ignore loopback - if (ifr.ifr_hwaddr.sa_family == ARPHRD_ETHER && !(ifr.ifr_flags & IFF_LOOPBACK)) + // and ignore loopback, we also include ARPHRD_80211 but that will only + // apply if we are running on android. + if ((ifr.ifr_hwaddr.sa_family == ARPHRD_ETHER || ifr.ifr_hwaddr.sa_family == ARPHRD_80211) + && !(ifr.ifr_flags & IFF_LOOPBACK)) { char macaddress[1024] = {0}; if (ioctl(m_socket, SIOCGIFHWADDR, &ifr) >= 0) @@ -257,9 +276,7 @@ void CPosixNetworkManager::FindNetworkInterfaces() ifr.ifr_hwaddr.sa_data[4], ifr.ifr_hwaddr.sa_data[5]); } m_connections.push_back(CConnectionPtr(new CPosixConnection(managed, - m_socket, interfaceName, macaddress, "Wired", - NETWORK_CONNECTION_TYPE_WIRED, NETWORK_CONNECTION_ENCRYPTION_NONE, 100))); - //printf("CPosixNetworkManager::GetConnections access_point(%s) \n", access_point); + m_socket, interfaceName, macaddress, essid.c_str(), connection, encryption, 100))); } } } @@ -412,8 +429,6 @@ bool CPosixNetworkManager::FindWifiConnections(const char *interfaceName) m_connections.push_back(CConnectionPtr(new CPosixConnection(managed, m_socket, interfaceName, macaddress, essid, NETWORK_CONNECTION_TYPE_WIFI, encryption, quality))); - //printf("CPosixNetworkManager::GetWifiConnections add access_point(%s), quality(%d), signalLevel(%d)\n", - // access_point.c_str(), quality, signalLevel); memcpy(macaddress, cur_macaddress, sizeof(macaddress)); } // reset encryption for parsing next access point @@ -476,8 +491,6 @@ bool CPosixNetworkManager::FindWifiConnections(const char *interfaceName) m_connections.push_back(CConnectionPtr(new CPosixConnection(managed, m_socket, interfaceName, macaddress, essid, NETWORK_CONNECTION_TYPE_WIFI, encryption, quality))); - //printf("CPosixNetworkManager::GetWifiConnections add access_point(%s), quality(%d), signalLevel(%d)\n", - // access_point.c_str(), quality, signalLevel); } free(res_buf); From 40ed90dd19250a2659301996a1826e2f2870af9c Mon Sep 17 00:00:00 2001 From: davilla Date: Fri, 21 Dec 2012 11:46:12 -0500 Subject: [PATCH 079/180] [aml] 1) restore lost FRAMEBUFFER detect which fixes an error reverting display axis, 2) CEGLNativeTypeAmlogic::DestroyNativeWindow is wrong, if you new, you MUST delete, 3) random attempts to fix no-display on boot --- xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp | 26 +++++++++++++++++---- xbmc/windowing/egl/EGLNativeTypeAmlogic.h | 3 +++ 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp b/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp index d2b580d4befcc..94dfe21e62457 100644 --- a/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp +++ b/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp @@ -24,10 +24,19 @@ #include #include "utils/StringUtils.h" #include "guilib/gui3d.h" -#define m_framebuffer_name "fb0" CEGLNativeTypeAmlogic::CEGLNativeTypeAmlogic() { + const char *env_framebuffer = getenv("FRAMEBUFFER"); + + // default to framebuffer 0 + m_framebuffer_name = "fb0"; + if (env_framebuffer) + { + std::string framebuffer(env_framebuffer); + std::string::size_type start = framebuffer.find("fb"); + m_framebuffer_name = framebuffer.substr(start); + } m_nativeWindow = NULL; } @@ -38,7 +47,9 @@ CEGLNativeTypeAmlogic::~CEGLNativeTypeAmlogic() bool CEGLNativeTypeAmlogic::CheckCompatibility() { char name[256] = {0}; - get_sysfs_str("/sys/class/graphics/fb0/device/modalias", name, 255); + std::string modalias = "/sys/class/graphics/" + m_framebuffer_name + "/device/modalias"; + + get_sysfs_str(modalias.c_str(), name, 255); CStdString strName = name; strName.Trim(); if (strName == "platform:mesonfb") @@ -185,7 +196,7 @@ bool CEGLNativeTypeAmlogic::GetPreferredResolution(RESOLUTION_INFO *res) const bool CEGLNativeTypeAmlogic::ShowWindow(bool show) { - std::string blank_framebuffer = "/sys/class/graphics/fb0/blank"; + std::string blank_framebuffer = "/sys/class/graphics/" + m_framebuffer_name + "/blank"; set_sysfs_int(blank_framebuffer.c_str(), show ? 0 : 1); return true; } @@ -253,7 +264,7 @@ bool CEGLNativeTypeAmlogic::SetDisplayResolution(const char *resolution) CStdString modestr = resolution; // switch display resolution set_sysfs_str("/sys/class/display/mode", modestr.c_str()); - usleep(250 * 1000); + usleep(500 * 1000); // setup gui freescale depending on display resolution DisableFreeScale(); @@ -400,17 +411,22 @@ void CEGLNativeTypeAmlogic::DisableFreeScale() // turn off frame buffer freescale set_sysfs_int("/sys/class/graphics/fb0/free_scale", 0); set_sysfs_int("/sys/class/graphics/fb1/free_scale", 0); + set_sysfs_str("/sys/class/graphics/fb0/free_scale_axis", "0 0 1279 719"); + set_sysfs_str("/sys/class/display/wr_reg", "m 0x1d26 '0x00b1'"); + usleep(60 * 1000); // revert to default video paths set_sysfs_str("/sys/class/vfm/map", "rm all"); set_sysfs_str("/sys/class/vfm/map", "add default_osd osd amvideo"); set_sysfs_str("/sys/class/vfm/map", "add default decoder ppmgr amvideo"); + usleep(60 * 1000); // disable post processing scaler and disable_video special mode set_sysfs_int("/sys/class/ppmgr/ppscaler", 0); set_sysfs_int("/sys/class/video/disable_video", 0); + usleep(60 * 1000); // revert display axis int fd0; - std::string framebuffer = "/dev/fb0"; + std::string framebuffer = "/dev/" + m_framebuffer_name; if ((fd0 = open(framebuffer.c_str(), O_RDWR)) >= 0) { diff --git a/xbmc/windowing/egl/EGLNativeTypeAmlogic.h b/xbmc/windowing/egl/EGLNativeTypeAmlogic.h index 6beb9562a66cc..6a85a1ff78355 100644 --- a/xbmc/windowing/egl/EGLNativeTypeAmlogic.h +++ b/xbmc/windowing/egl/EGLNativeTypeAmlogic.h @@ -58,4 +58,7 @@ class CEGLNativeTypeAmlogic : public CEGLNativeType void EnableFreeScale(); void DisableFreeScale(); void SetCpuMinLimit(bool limit); + +private: + std::string m_framebuffer_name; }; From 31b097b4f4906b9a39d820120e6d79591c6f4011 Mon Sep 17 00:00:00 2001 From: davilla Date: Fri, 21 Dec 2012 12:03:35 -0500 Subject: [PATCH 080/180] [aml] changed, use functions in utils/AMLUtils.h --- xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp | 182 ++++++-------------- xbmc/windowing/egl/EGLNativeTypeAmlogic.h | 6 - 2 files changed, 53 insertions(+), 135 deletions(-) diff --git a/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp b/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp index 94dfe21e62457..0729b965bc7e4 100644 --- a/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp +++ b/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp @@ -17,13 +17,16 @@ * . * */ -#include + #include "EGLNativeTypeAmlogic.h" +#include "guilib/gui3d.h" +#include "utils/AMLUtils.h" +#include "utils/StringUtils.h" + #include #include #include -#include "utils/StringUtils.h" -#include "guilib/gui3d.h" +#include CEGLNativeTypeAmlogic::CEGLNativeTypeAmlogic() { @@ -49,7 +52,7 @@ bool CEGLNativeTypeAmlogic::CheckCompatibility() char name[256] = {0}; std::string modalias = "/sys/class/graphics/" + m_framebuffer_name + "/device/modalias"; - get_sysfs_str(modalias.c_str(), name, 255); + aml_get_sysfs_str(modalias.c_str(), name, 255); CStdString strName = name; strName.Trim(); if (strName == "platform:mesonfb") @@ -59,12 +62,12 @@ bool CEGLNativeTypeAmlogic::CheckCompatibility() void CEGLNativeTypeAmlogic::Initialize() { - SetCpuMinLimit(true); + aml_cpufreq_limit(true); return; } void CEGLNativeTypeAmlogic::Destroy() { - SetCpuMinLimit(false); + aml_cpufreq_limit(false); return; } @@ -122,7 +125,7 @@ bool CEGLNativeTypeAmlogic::DestroyNativeWindow() bool CEGLNativeTypeAmlogic::GetNativeResolution(RESOLUTION_INFO *res) const { char mode[256] = {0}; - get_sysfs_str("/sys/class/display/mode", mode, 255); + aml_get_sysfs_str("/sys/class/display/mode", mode, 255); return ModeToResolution(mode, res); } @@ -162,7 +165,7 @@ bool CEGLNativeTypeAmlogic::SetNativeResolution(const RESOLUTION_INFO &res) bool CEGLNativeTypeAmlogic::ProbeResolutions(std::vector &resolutions) { char valstr[256] = {0}; - get_sysfs_str("/sys/class/amhdmitx/amhdmitx0/disp_cap", valstr, 255); + aml_get_sysfs_str("/sys/class/amhdmitx/amhdmitx0/disp_cap", valstr, 255); std::vector probe_str; StringUtils::SplitString(valstr, "\n", probe_str); @@ -197,73 +200,15 @@ bool CEGLNativeTypeAmlogic::GetPreferredResolution(RESOLUTION_INFO *res) const bool CEGLNativeTypeAmlogic::ShowWindow(bool show) { std::string blank_framebuffer = "/sys/class/graphics/" + m_framebuffer_name + "/blank"; - set_sysfs_int(blank_framebuffer.c_str(), show ? 0 : 1); + aml_set_sysfs_int(blank_framebuffer.c_str(), show ? 0 : 1); return true; } -int CEGLNativeTypeAmlogic::get_sysfs_str(const char *path, char *valstr, const int size) const -{ - int fd = open(path, O_RDONLY); - if (fd >= 0) - { - int len = read(fd, valstr, size - 1); - if (len != -1 ) - valstr[len] = '\0'; - close(fd); - } - else - { - sprintf(valstr, "%s", "fail"); - return -1; - } - return 0; -} - -int CEGLNativeTypeAmlogic::set_sysfs_str(const char *path, const char *val) const -{ - int fd = open(path, O_CREAT | O_RDWR | O_TRUNC, 0644); - if (fd >= 0) - { - write(fd, val, strlen(val)); - close(fd); - return 0; - } - return -1; -} - -int CEGLNativeTypeAmlogic::set_sysfs_int(const char *path, const int val) const -{ - char bcmd[16]; - int fd = open(path, O_CREAT | O_RDWR | O_TRUNC, 0644); - if (fd >= 0) - { - sprintf(bcmd, "%d", val); - write(fd, bcmd, strlen(bcmd)); - close(fd); - return 0; - } - return -1; -} - -int CEGLNativeTypeAmlogic::get_sysfs_int(const char *path) const -{ - int val = 0; - char bcmd[16]; - int fd = open(path, O_RDONLY); - if (fd >= 0) - { - read(fd, bcmd, sizeof(bcmd)); - val = strtol(bcmd, NULL, 16); - close(fd); - } - return val; -} - bool CEGLNativeTypeAmlogic::SetDisplayResolution(const char *resolution) { CStdString modestr = resolution; // switch display resolution - set_sysfs_str("/sys/class/display/mode", modestr.c_str()); + aml_set_sysfs_str("/sys/class/display/mode", modestr.c_str()); usleep(500 * 1000); // setup gui freescale depending on display resolution @@ -361,67 +306,67 @@ bool CEGLNativeTypeAmlogic::ModeToResolution(const char *mode, RESOLUTION_INFO * void CEGLNativeTypeAmlogic::EnableFreeScale() { // remove default OSD and video path (default_osd default) - set_sysfs_str("/sys/class/vfm/map", "rm all"); + aml_set_sysfs_str("/sys/class/vfm/map", "rm all"); usleep(60 * 1000); // add OSD path - set_sysfs_str("/sys/class/vfm/map", "add osdpath osd amvideo"); + aml_set_sysfs_str("/sys/class/vfm/map", "add osdpath osd amvideo"); // enable OSD free scale using frame buffer size of 720p - set_sysfs_int("/sys/class/graphics/fb0/free_scale", 0); - set_sysfs_int("/sys/class/graphics/fb1/free_scale", 0); - set_sysfs_int("/sys/class/graphics/fb0/scale_width", 1280); - set_sysfs_int("/sys/class/graphics/fb0/scale_height", 720); - set_sysfs_int("/sys/class/graphics/fb1/scale_width", 1280); - set_sysfs_int("/sys/class/graphics/fb1/scale_height", 720); - set_sysfs_int("/sys/class/graphics/fb0/free_scale", 1); - set_sysfs_int("/sys/class/graphics/fb1/free_scale", 1); + aml_set_sysfs_int("/sys/class/graphics/fb0/free_scale", 0); + aml_set_sysfs_int("/sys/class/graphics/fb1/free_scale", 0); + aml_set_sysfs_int("/sys/class/graphics/fb0/scale_width", 1280); + aml_set_sysfs_int("/sys/class/graphics/fb0/scale_height", 720); + aml_set_sysfs_int("/sys/class/graphics/fb1/scale_width", 1280); + aml_set_sysfs_int("/sys/class/graphics/fb1/scale_height", 720); + aml_set_sysfs_int("/sys/class/graphics/fb0/free_scale", 1); + aml_set_sysfs_int("/sys/class/graphics/fb1/free_scale", 1); usleep(60 * 1000); // remove OSD path - set_sysfs_int("/sys/class/graphics/fb0/free_scale", 0); - set_sysfs_int("/sys/class/graphics/fb1/free_scale", 0); - set_sysfs_str("/sys/class/vfm/map", "rm osdpath"); + aml_set_sysfs_int("/sys/class/graphics/fb0/free_scale", 0); + aml_set_sysfs_int("/sys/class/graphics/fb1/free_scale", 0); + aml_set_sysfs_str("/sys/class/vfm/map", "rm osdpath"); usleep(60 * 1000); // add video path - set_sysfs_str("/sys/class/vfm/map", "add videopath decoder ppmgr amvideo"); + aml_set_sysfs_str("/sys/class/vfm/map", "add videopath decoder ppmgr amvideo"); // enable video free scale (scaling to 1920x1080 with frame buffer size 1280x720) - set_sysfs_int("/sys/class/ppmgr/ppscaler", 0); - set_sysfs_int("/sys/class/video/disable_video", 1); - set_sysfs_int("/sys/class/ppmgr/ppscaler", 1); - set_sysfs_str("/sys/class/ppmgr/ppscaler_rect", "0 0 1919 1079 0"); - set_sysfs_str("/sys/class/ppmgr/disp", "1280 720"); + aml_set_sysfs_int("/sys/class/ppmgr/ppscaler", 0); + aml_set_sysfs_int("/sys/class/video/disable_video", 1); + aml_set_sysfs_int("/sys/class/ppmgr/ppscaler", 1); + aml_set_sysfs_str("/sys/class/ppmgr/ppscaler_rect", "0 0 1919 1079 0"); + aml_set_sysfs_str("/sys/class/ppmgr/disp", "1280 720"); usleep(60 * 1000); // - set_sysfs_int("/sys/class/graphics/fb0/free_scale", 0); - set_sysfs_int("/sys/class/graphics/fb1/free_scale", 0); - set_sysfs_int("/sys/class/graphics/fb0/scale_width", 1280); - set_sysfs_int("/sys/class/graphics/fb0/scale_height", 720); - set_sysfs_int("/sys/class/graphics/fb1/scale_width", 1280); - set_sysfs_int("/sys/class/graphics/fb1/scale_height", 720); - set_sysfs_int("/sys/class/graphics/fb0/free_scale", 1); - set_sysfs_int("/sys/class/graphics/fb1/free_scale", 1); + aml_set_sysfs_int("/sys/class/graphics/fb0/free_scale", 0); + aml_set_sysfs_int("/sys/class/graphics/fb1/free_scale", 0); + aml_set_sysfs_int("/sys/class/graphics/fb0/scale_width", 1280); + aml_set_sysfs_int("/sys/class/graphics/fb0/scale_height", 720); + aml_set_sysfs_int("/sys/class/graphics/fb1/scale_width", 1280); + aml_set_sysfs_int("/sys/class/graphics/fb1/scale_height", 720); + aml_set_sysfs_int("/sys/class/graphics/fb0/free_scale", 1); + aml_set_sysfs_int("/sys/class/graphics/fb1/free_scale", 1); usleep(60 * 1000); // - set_sysfs_int("/sys/class/video/disable_video", 2); - set_sysfs_str("/sys/class/display/axis", "0 0 1279 719 0 0 0 0"); - set_sysfs_str("/sys/class/ppmgr/ppscaler_rect", "0 0 1279 719 1"); + aml_set_sysfs_int("/sys/class/video/disable_video", 2); + aml_set_sysfs_str("/sys/class/display/axis", "0 0 1279 719 0 0 0 0"); + aml_set_sysfs_str("/sys/class/ppmgr/ppscaler_rect", "0 0 1279 719 1"); } void CEGLNativeTypeAmlogic::DisableFreeScale() { // turn off frame buffer freescale - set_sysfs_int("/sys/class/graphics/fb0/free_scale", 0); - set_sysfs_int("/sys/class/graphics/fb1/free_scale", 0); - set_sysfs_str("/sys/class/graphics/fb0/free_scale_axis", "0 0 1279 719"); - set_sysfs_str("/sys/class/display/wr_reg", "m 0x1d26 '0x00b1'"); + aml_set_sysfs_int("/sys/class/graphics/fb0/free_scale", 0); + aml_set_sysfs_int("/sys/class/graphics/fb1/free_scale", 0); + aml_set_sysfs_str("/sys/class/graphics/fb0/free_scale_axis", "0 0 1279 719"); + aml_set_sysfs_str("/sys/class/display/wr_reg", "m 0x1d26 '0x00b1'"); usleep(60 * 1000); // revert to default video paths - set_sysfs_str("/sys/class/vfm/map", "rm all"); - set_sysfs_str("/sys/class/vfm/map", "add default_osd osd amvideo"); - set_sysfs_str("/sys/class/vfm/map", "add default decoder ppmgr amvideo"); + aml_set_sysfs_str("/sys/class/vfm/map", "rm all"); + aml_set_sysfs_str("/sys/class/vfm/map", "add default_osd osd amvideo"); + aml_set_sysfs_str("/sys/class/vfm/map", "add default decoder ppmgr amvideo"); usleep(60 * 1000); // disable post processing scaler and disable_video special mode - set_sysfs_int("/sys/class/ppmgr/ppscaler", 0); - set_sysfs_int("/sys/class/video/disable_video", 0); + aml_set_sysfs_int("/sys/class/ppmgr/ppscaler", 0); + aml_set_sysfs_int("/sys/class/video/disable_video", 0); usleep(60 * 1000); // revert display axis @@ -435,29 +380,8 @@ void CEGLNativeTypeAmlogic::DisableFreeScale() { char daxis_str[255] = {0}; sprintf(daxis_str, "%d %d %d %d 0 0 0 0", 0, 0, vinfo.xres, vinfo.yres); - set_sysfs_str("/sys/class/display/axis", daxis_str); + aml_set_sysfs_str("/sys/class/display/axis", daxis_str); } close(fd0); } } - -void CEGLNativeTypeAmlogic::SetCpuMinLimit(bool limit) -{ - // when playing hw decoded audio, we cannot drop below 600MHz - // or risk hw audio issues. AML code does a 2X scaling based off - // /sys/class/audiodsp/codec_mips but tests show that this is - // seems risky so we just clamp to 600Mhz to be safe. - - // only adjust if we are running "ondemand" - char scaling_governor[256] = {0}; - get_sysfs_str("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor", scaling_governor, 255); - if (strncmp(scaling_governor, "ondemand", 255)) - return; - - int freq; - if (limit) - freq = 600000; - else - freq = get_sysfs_int("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq"); - set_sysfs_int("/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq", freq); -} diff --git a/xbmc/windowing/egl/EGLNativeTypeAmlogic.h b/xbmc/windowing/egl/EGLNativeTypeAmlogic.h index 6a85a1ff78355..f8e6a903574df 100644 --- a/xbmc/windowing/egl/EGLNativeTypeAmlogic.h +++ b/xbmc/windowing/egl/EGLNativeTypeAmlogic.h @@ -48,16 +48,10 @@ class CEGLNativeTypeAmlogic : public CEGLNativeType virtual bool ShowWindow(bool show); protected: - int get_sysfs_str(const char *path, char *valstr, const int size) const; - int set_sysfs_str(const char *path, const char *val) const; - int set_sysfs_int(const char *path, const int val) const; - int get_sysfs_int(const char *path) const; - bool SetDisplayResolution(const char *resolution); bool ModeToResolution(const char *mode, RESOLUTION_INFO *res) const; void EnableFreeScale(); void DisableFreeScale(); - void SetCpuMinLimit(bool limit); private: std::string m_framebuffer_name; From 5439c89b9e27c73a02a8a9149ae579a1fab352ab Mon Sep 17 00:00:00 2001 From: davilla Date: Fri, 21 Dec 2012 18:57:54 -0500 Subject: [PATCH 081/180] [aml] changed, run CDVDPlayerAudio:: Discontinuity1 with reduced constrains under android --- xbmc/cores/dvdplayer/DVDPlayerAudio.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp index 23899d20c9e90..3c89a03d0dfa0 100644 --- a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp @@ -645,7 +645,11 @@ void CDVDPlayerAudio::HandleSyncError(double duration) double error = m_dvdAudio.GetPlayingPts() - clock; int64_t now; +#if defined(TARGET_ANDROID) + if( fabs(error) > DVD_MSEC_TO_TIME(250) || m_syncclock ) +#else if( fabs(error) > DVD_MSEC_TO_TIME(100) || m_syncclock ) +#endif { m_pClock->Discontinuity(clock+error); if(m_speed == DVD_PLAYSPEED_NORMAL) From f87b9c487b44f3ce10efe5542f5e7fb459a64061 Mon Sep 17 00:00:00 2001 From: davilla Date: Fri, 21 Dec 2012 19:14:39 -0500 Subject: [PATCH 082/180] [aml] fixed, always wait for a new picture to keep from filling hw video debug buffers --- xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index a8c78b2d4111d..f3e0b95132510 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -594,10 +594,10 @@ int write_av_packet(am_private_t *para, am_packet_t *pkt) para->playctrl_info.end_flag = 1; CLog::Log(LOGDEBUG, "$$$$$$ write blocked, need reset decoder!$$$$$$"); } - pkt->data += len; - pkt->data_size -= len; + //pkt->data += len; + //pkt->data_size -= len; usleep(RW_WAIT_TIME); - CLog::Log(LOGDEBUG, "usleep(RW_WAIT_TIME)"); + CLog::Log(LOGDEBUG, "usleep(RW_WAIT_TIME), len(%d)", len); return PLAYER_SUCCESS; } } else { @@ -1621,10 +1621,8 @@ int CAmlogic::Decode(unsigned char *pData, size_t size, double dts, double pts) if (GetTimeSize() < 1.0) return VC_BUFFER; - // wait until we get a new frame or 25ms, - // but only if we have not gotten a new pict. - if (m_old_pictcnt == m_cur_pictcnt) - m_ready_event.WaitMSec(25); + // wait until we get a new frame or 100ms, + m_ready_event.WaitMSec(100); // we must return VC_BUFFER or VC_PICTURE, // default to VC_BUFFER. @@ -1636,7 +1634,7 @@ int CAmlogic::Decode(unsigned char *pData, size_t size, double dts, double pts) // we got a new pict, try and keep hw buffered demux above 2 seconds. // this, combined with the above 1 second check, keeps hw buffered demux between 1 and 2 seconds. // we also check to make sure we keep from filling hw buffer. - if (GetTimeSize() < 2.0 && GetDataSize() < m_vbufsize/2) + if (GetTimeSize() < 2.0 && GetDataSize() < m_vbufsize/3) rtn |= VC_BUFFER; } /* From 81c47b2af2d3ec8b0b2060879bec0fecd63b9cac Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 21 Dec 2012 20:30:20 -0500 Subject: [PATCH 083/180] [droid] bump libass version to match ios --- tools/android/depends/libass/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/android/depends/libass/Makefile b/tools/android/depends/libass/Makefile index c02f5972cbf71..116510847a39e 100644 --- a/tools/android/depends/libass/Makefile +++ b/tools/android/depends/libass/Makefile @@ -3,9 +3,9 @@ DEPS= ../Makefile.include Makefile # lib name, version LIBNAME=libass -VERSION=0.9.11 +VERSION=0.9.13 SOURCE=$(LIBNAME)-$(VERSION) -ARCHIVE=$(SOURCE).tar.bz2 +ARCHIVE=$(SOURCE).tar.gz # configuration settings CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ From 64338e233a5e6005e739a7482617d4def92068ce Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 21 Dec 2012 20:34:09 -0500 Subject: [PATCH 084/180] [droid] package libass --- tools/android/packaging/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/android/packaging/Makefile b/tools/android/packaging/Makefile index eb76d2cd45feb..72d01244fc42c 100644 --- a/tools/android/packaging/Makefile +++ b/tools/android/packaging/Makefile @@ -5,7 +5,7 @@ OBJS = libcurl.so \ libafpclient.so \ libshairport.so libplist.so \ libxbogg.so libxbvorbis.so libxbvorbisfile.so libxbFLAC.so libxbmpeg2.so \ - libxbmpeg2convert.so libnfs.so + libxbmpeg2convert.so libnfs.so libass.so PLATFORM_OBJS = EXCLUDED_ADDONS = screensaver.rsxs.euphoria visualization.dxspectrum visualization.milkdrop visualization.projectm From 657fb882dcc30b212d207923aeccc8752d098ddd Mon Sep 17 00:00:00 2001 From: davilla Date: Sun, 23 Dec 2012 12:39:05 -0500 Subject: [PATCH 085/180] [aml] add PivosPowerSyscall class to handle m3 suspend --- xbmc/powermanagement/PowerManager.cpp | 3 + xbmc/powermanagement/linux/Makefile | 13 +-- .../linux/PivosPowerSyscall.cpp | 93 +++++++++++++++++++ .../powermanagement/linux/PivosPowerSyscall.h | 47 ++++++++++ xbmc/utils/AMLUtils.cpp | 18 ++-- xbmc/utils/AMLUtils.h | 1 + 6 files changed, 162 insertions(+), 13 deletions(-) create mode 100644 xbmc/powermanagement/linux/PivosPowerSyscall.cpp create mode 100644 xbmc/powermanagement/linux/PivosPowerSyscall.h diff --git a/xbmc/powermanagement/PowerManager.cpp b/xbmc/powermanagement/PowerManager.cpp index a5534c9f22435..72722ddd323cf 100644 --- a/xbmc/powermanagement/PowerManager.cpp +++ b/xbmc/powermanagement/PowerManager.cpp @@ -46,6 +46,7 @@ #include "linux/ConsoleDeviceKitPowerSyscall.h" #include "linux/SystemdUPowerSyscall.h" #include "linux/UPowerSyscall.h" +#include "linux/PivosPowerSyscall.h" #ifdef HAS_HAL #include "linux/HALPowerSyscall.h" #endif @@ -83,6 +84,8 @@ void CPowerManager::Initialize() m_instance = new CSystemdUPowerSyscall(); else if (CUPowerSyscall::HasUPower()) m_instance = new CUPowerSyscall(); + else if (CPivosPowerSyscall::HasPivosPowerSyscall()) + m_instance = new CPivosPowerSyscall(); #ifdef HAS_HAL else m_instance = new CHALPowerSyscall(); diff --git a/xbmc/powermanagement/linux/Makefile b/xbmc/powermanagement/linux/Makefile index 11a91b00001fa..f3814c8e25914 100644 --- a/xbmc/powermanagement/linux/Makefile +++ b/xbmc/powermanagement/linux/Makefile @@ -1,10 +1,11 @@ -SRCS=ConsoleDeviceKitPowerSyscall.cpp \ - ConsoleUPowerSyscall.cpp \ - HALPowerSyscall.cpp \ - UPowerSyscall.cpp \ - SystemdUPowerSyscall.cpp +SRCS = ConsoleDeviceKitPowerSyscall.cpp +SRCS += ConsoleUPowerSyscall.cpp +SRCS += HALPowerSyscall.cpp +SRCS += UPowerSyscall.cpp +SRCS += SystemdUPowerSyscall.cpp +SRCS += PivosPowerSyscall.cpp -LIB=powermanagement_linux.a +LIB = powermanagement_linux.a include ../../../Makefile.include -include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS))) diff --git a/xbmc/powermanagement/linux/PivosPowerSyscall.cpp b/xbmc/powermanagement/linux/PivosPowerSyscall.cpp new file mode 100644 index 0000000000000..df76ca958d208 --- /dev/null +++ b/xbmc/powermanagement/linux/PivosPowerSyscall.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#include "system.h" +#include "PivosPowerSyscall.h" +#include "utils/AMLUtils.h" +#include "utils/log.h" + +CPivosPowerSyscall::CPivosPowerSyscall() +{ + if (aml_get_cputype() == 1) + { + m_CanPowerdown = true; + m_CanSuspend = false; + } + else + { + m_CanPowerdown = false; + m_CanSuspend = true; + } + m_CanHibernate = false; + m_CanReboot = true; +} + +bool CPivosPowerSyscall::Powerdown() +{ + return true; +} + +bool CPivosPowerSyscall::Suspend() +{ + CPowerSyscallWithoutEvents::Suspend(); + + aml_set_sysfs_str("/sys/power/state", "mem"); + return true; +} + +bool CPivosPowerSyscall::Hibernate() +{ + return false; +} + +bool CPivosPowerSyscall::Reboot() +{ + return true; +} + +bool CPivosPowerSyscall::CanPowerdown() +{ + return m_CanPowerdown; +} + +bool CPivosPowerSyscall::CanSuspend() +{ + return m_CanSuspend; +} + +bool CPivosPowerSyscall::CanHibernate() +{ + return m_CanHibernate; +} + +bool CPivosPowerSyscall::CanReboot() +{ + return m_CanReboot; +} + +int CPivosPowerSyscall::BatteryLevel() +{ + return 0; +} + +bool CPivosPowerSyscall::HasPivosPowerSyscall() +{ + return aml_present(); +} diff --git a/xbmc/powermanagement/linux/PivosPowerSyscall.h b/xbmc/powermanagement/linux/PivosPowerSyscall.h new file mode 100644 index 0000000000000..e25b0d5e7b98d --- /dev/null +++ b/xbmc/powermanagement/linux/PivosPowerSyscall.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#include "powermanagement/IPowerSyscall.h" + +class CPivosPowerSyscall : public CPowerSyscallWithoutEvents +{ +public: + CPivosPowerSyscall(); + virtual ~CPivosPowerSyscall() {} + + virtual bool Powerdown(); + virtual bool Suspend(); + virtual bool Hibernate(); + virtual bool Reboot(); + + virtual bool CanPowerdown(); + virtual bool CanSuspend(); + virtual bool CanHibernate(); + virtual bool CanReboot(); + virtual int BatteryLevel(); + + static bool HasPivosPowerSyscall(); + +private: + bool m_CanPowerdown; + bool m_CanSuspend; + bool m_CanHibernate; + bool m_CanReboot; +}; diff --git a/xbmc/utils/AMLUtils.cpp b/xbmc/utils/AMLUtils.cpp index 6e7e32b2b642e..a3a9a1859e2cb 100644 --- a/xbmc/utils/AMLUtils.cpp +++ b/xbmc/utils/AMLUtils.cpp @@ -93,7 +93,7 @@ bool aml_present() return has_aml; } -void aml_cpufreq_limit(bool limit) +int aml_get_cputype() { static int aml_cputype = -1; if (aml_cputype == -1) @@ -113,17 +113,21 @@ void aml_cpufreq_limit(bool limit) aml_cputype = 3; break; } + else if (stdbuffer.find("MESON3") != std::string::npos) + { + aml_cputype = 3; + break; + } } fclose(cpuinfo_fd); } } - // On M1 SoCs, when playing hw decoded audio, we cannot drop below 600MHz - // or risk hw audio dropouts. AML code does a 2X scaling based off - // /sys/class/audiodsp/codec_mips but tests show that this is - // seems risky so we just clamp to 600Mhz to be safe. - if (aml_cputype == 3) - return; + return aml_cputype; +} + +void aml_cpufreq_limit(bool limit) +{ int cpufreq = 300000; if (limit) cpufreq = 600000; diff --git a/xbmc/utils/AMLUtils.h b/xbmc/utils/AMLUtils.h index b1558afdbba1a..07e625e81368e 100644 --- a/xbmc/utils/AMLUtils.h +++ b/xbmc/utils/AMLUtils.h @@ -25,5 +25,6 @@ int aml_set_sysfs_int(const char *path, const int val); int aml_get_sysfs_int(const char *path); bool aml_present(); +int aml_get_cputype(); void aml_cpufreq_limit(bool limit); void aml_set_audio_passthrough(bool passthrough); From 7d1b5d81710accf5761d43e38c635c6a102ebb4f Mon Sep 17 00:00:00 2001 From: davilla Date: Sun, 23 Dec 2012 14:44:35 -0500 Subject: [PATCH 086/180] [aml] finish rename of CAmlogic class to match the filename (AMLCodec) --- .../dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 70 +++++++++---------- .../dvdplayer/DVDCodecs/Video/AMLCodec.h | 6 +- .../DVDCodecs/Video/DVDVideoCodecAmlogic.cpp | 2 +- .../DVDCodecs/Video/DVDVideoCodecAmlogic.h | 4 +- 4 files changed, 41 insertions(+), 41 deletions(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index f3e0b95132510..3d246fb5d0bef 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -1347,7 +1347,7 @@ int set_header_info(am_private_t *para) } /*************************************************************************/ -CAmlogic::CAmlogic() : CThread("CAmlogic") +CAMLCodec::CAMLCodec() : CThread("CAMLCodec") { am_private = new am_private_t; memset(am_private, 0, sizeof(am_private_t)); @@ -1357,7 +1357,7 @@ CAmlogic::CAmlogic() : CThread("CAmlogic") } -CAmlogic::~CAmlogic() +CAMLCodec::~CAMLCodec() { StopThread(); delete am_private; @@ -1365,9 +1365,9 @@ CAmlogic::~CAmlogic() delete m_dll, m_dll = NULL; } -bool CAmlogic::OpenDecoder(CDVDStreamInfo &hints) +bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) { - CLog::Log(LOGDEBUG, "CAmlogic::OpenDecoder"); + CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder"); m_1st_pts = 0; m_cur_pts = 0; m_cur_pictcnt = 0; @@ -1442,11 +1442,11 @@ bool CAmlogic::OpenDecoder(CDVDStreamInfo &hints) am_private->flv_flag = 1; } - CLog::Log(LOGDEBUG, "CAmlogic::OpenDecoder hints.fpsrate(%d), hints.fpsscale(%d), video_rate(%d)", + CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder hints.fpsrate(%d), hints.fpsscale(%d), video_rate(%d)", hints.fpsrate, hints.fpsscale, am_private->video_rate); - CLog::Log(LOGDEBUG, "CAmlogic::OpenDecoder hints.aspect(%f), video_ratio.num(%d), video_ratio.den(%d)", + CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder hints.aspect(%f), video_ratio.num(%d), video_ratio.den(%d)", hints.aspect, video_ratio.num, video_ratio.den); - CLog::Log(LOGDEBUG, "CAmlogic::OpenDecoder hints.orientation(%d), hints.forced_aspect(%d)", + CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder hints.orientation(%d), hints.forced_aspect(%d)", hints.orientation, hints.forced_aspect); // default video codec params @@ -1506,7 +1506,7 @@ bool CAmlogic::OpenDecoder(CDVDStreamInfo &hints) int ret = m_dll->codec_init(&am_private->vcodec); if (ret != CODEC_ERROR_NONE) { - CLog::Log(LOGDEBUG, "CAmlogic::OpenDecoder codec init failed, ret=0x%x", -ret); + CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder codec init failed, ret=0x%x", -ret); return false; } @@ -1534,9 +1534,9 @@ bool CAmlogic::OpenDecoder(CDVDStreamInfo &hints) return true; } -void CAmlogic::CloseDecoder() +void CAMLCodec::CloseDecoder() { - CLog::Log(LOGDEBUG, "CAmlogic::CloseDecoder"); + CLog::Log(LOGDEBUG, "CAMLCodec::CloseDecoder"); StopThread(); g_renderManager.RegisterRenderUpdateCallBack((const void*)NULL, NULL); @@ -1550,9 +1550,9 @@ void CAmlogic::CloseDecoder() aml_set_sysfs_int("/sys/class/tsync/enable", 1); } -void CAmlogic::Reset() +void CAMLCodec::Reset() { - CLog::Log(LOGDEBUG, "CAmlogic::Reset"); + CLog::Log(LOGDEBUG, "CAMLCodec::Reset"); // set the system blackout_policy to leave the last frame showing int blackout_policy = aml_get_sysfs_int("/sys/class/video/blackout_policy"); @@ -1582,7 +1582,7 @@ void CAmlogic::Reset() aml_set_sysfs_int("/sys/class/video/blackout_policy", blackout_policy); } -int CAmlogic::Decode(unsigned char *pData, size_t size, double dts, double pts) +int CAMLCodec::Decode(unsigned char *pData, size_t size, double dts, double pts) { // grr, m_RenderUpdateCallBackFn in g_renderManager is NULL'ed during // g_renderManager.Configure call by player, which happens after the codec @@ -1638,14 +1638,14 @@ int CAmlogic::Decode(unsigned char *pData, size_t size, double dts, double pts) rtn |= VC_BUFFER; } /* - CLog::Log(LOGDEBUG, "CAmlogic::Decode: " + CLog::Log(LOGDEBUG, "CAMLCodec::Decode: " "rtn(%d), m_cur_pictcnt(%lld), m_cur_pts(%f), lastpts(%f), GetTimeSize(%f), GetDataSize(%d)", rtn, m_cur_pictcnt, (float)m_cur_pts/PTS_FREQ, (float)am_private->am_pkt.lastpts/PTS_FREQ, GetTimeSize(), GetDataSize()); */ return rtn; } -bool CAmlogic::GetPicture(DVDVideoPicture *pDvdVideoPicture) +bool CAMLCodec::GetPicture(DVDVideoPicture *pDvdVideoPicture) { pDvdVideoPicture->dts = DVD_NOPTS_VALUE; pDvdVideoPicture->pts = GetPlayerPtsSeconds() * (double)DVD_TIME_BASE; @@ -1660,7 +1660,7 @@ bool CAmlogic::GetPicture(DVDVideoPicture *pDvdVideoPicture) return true; } -int CAmlogic::GetDataSize() +int CAMLCodec::GetDataSize() { struct buf_status vbuf ={0}; if (m_dll->codec_get_vbuf_state(&am_private->vcodec, &vbuf) >= 0) @@ -1669,7 +1669,7 @@ int CAmlogic::GetDataSize() return vbuf.data_len; } -double CAmlogic::GetTimeSize() +double CAMLCodec::GetTimeSize() { // if m_cur_pts is zero, hw decoder was not started yet // so we use the pts of the 1st demux packet that was send @@ -1690,9 +1690,9 @@ double CAmlogic::GetTimeSize() return timesize; } -void CAmlogic::Process() +void CAMLCodec::Process() { - CLog::Log(LOGDEBUG, "CAmlogic::Process Started"); + CLog::Log(LOGDEBUG, "CAMLCodec::Process Started"); // bump our priority to be level with SoftAE SetPriority(THREAD_PRIORITY_ABOVE_NORMAL); @@ -1738,10 +1738,10 @@ void CAmlogic::Process() } } SetPriority(THREAD_PRIORITY_NORMAL); - CLog::Log(LOGDEBUG, "CAmlogic::Process Stopped"); + CLog::Log(LOGDEBUG, "CAMLCodec::Process Stopped"); } -void CAmlogic::PauseResume(int state) +void CAMLCodec::PauseResume(int state) { static int saved_state = -1; if (saved_state == state) @@ -1754,7 +1754,7 @@ void CAmlogic::PauseResume(int state) m_dll->codec_resume(&am_private->vcodec); } -double CAmlogic::GetPlayerPtsSeconds() +double CAMLCodec::GetPlayerPtsSeconds() { double clock_pts = 0.0; CDVDClock *playerclock = CDVDClock::GetMasterClock(); @@ -1764,12 +1764,12 @@ double CAmlogic::GetPlayerPtsSeconds() return clock_pts; } -void CAmlogic::SetVideoPtsSeconds(const double pts) +void CAMLCodec::SetVideoPtsSeconds(const double pts) { set_pts_pcrscr((int64_t)(pts * PTS_FREQ)); } -void CAmlogic::ShowMainVideo(const bool show) +void CAMLCodec::ShowMainVideo(const bool show) { static int saved_disable_video = -1; @@ -1781,7 +1781,7 @@ void CAmlogic::ShowMainVideo(const bool show) saved_disable_video = disable_video; } -void CAmlogic::SetVideoZoom(const float zoom) +void CAMLCodec::SetVideoZoom(const float zoom) { // input zoom range is 0.5 to 2.0 with a default of 1.0. // output zoom range is 2 to 300 with default of 100. @@ -1789,27 +1789,27 @@ void CAmlogic::SetVideoZoom(const float zoom) aml_set_sysfs_int("/sys/class/video/zoom", (int)(100 * zoom)); } -void CAmlogic::SetVideoContrast(const int contrast) +void CAMLCodec::SetVideoContrast(const int contrast) { // input contrast range is 0 to 100 with default of 50. // output contrast range is -255 to 255 with default of 0. int aml_contrast = (255 * (contrast - 50)) / 50; aml_set_sysfs_int("/sys/class/video/contrast", aml_contrast); } -void CAmlogic::SetVideoBrightness(const int brightness) +void CAMLCodec::SetVideoBrightness(const int brightness) { // input brightness range is 0 to 100 with default of 50. // output brightness range is -127 to 127 with default of 0. int aml_brightness = (127 * (brightness - 50)) / 50; aml_set_sysfs_int("/sys/class/video/brightness", aml_brightness); } -void CAmlogic::SetVideoSaturation(const int saturation) +void CAMLCodec::SetVideoSaturation(const int saturation) { // output saturation range is -127 to 127 with default of 127. aml_set_sysfs_int("/sys/class/video/saturation", saturation); } -void CAmlogic::GetRenderFeatures(Features &renderFeatures) +void CAMLCodec::GetRenderFeatures(Features &renderFeatures) { renderFeatures.push_back(RENDERFEATURE_ZOOM); renderFeatures.push_back(RENDERFEATURE_CONTRAST); @@ -1819,14 +1819,14 @@ void CAmlogic::GetRenderFeatures(Features &renderFeatures) return; } -void CAmlogic::RenderFeaturesCallBack(const void *ctx, Features &renderFeatures) +void CAMLCodec::RenderFeaturesCallBack(const void *ctx, Features &renderFeatures) { - CAmlogic *codec = (CAmlogic*)ctx; + CAMLCodec *codec = (CAMLCodec*)ctx; if (codec) codec->GetRenderFeatures(renderFeatures); } -void CAmlogic::SetVideoRect(const CRect &SrcRect, const CRect &DestRect) +void CAMLCodec::SetVideoRect(const CRect &SrcRect, const CRect &DestRect) { // this routine gets called every video frame // and is in the context of the renderer thread so @@ -1900,15 +1900,15 @@ void CAmlogic::SetVideoRect(const CRect &SrcRect, const CRect &DestRect) rectangle.Format("%i,%i,%i,%i", (int)dst_rect.x1, (int)dst_rect.y1, (int)dst_rect.Width(), (int)dst_rect.Height()); - CLog::Log(LOGDEBUG, "CAmlogic::SetVideoRect:dst_rect(%s)", rectangle.c_str()); + CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoRect:dst_rect(%s)", rectangle.c_str()); // we only get called once gui has changed to something // that would show video playback, so show it. ShowMainVideo(true); } -void CAmlogic::RenderUpdateCallBack(const void *ctx, const CRect &SrcRect, const CRect &DestRect) +void CAMLCodec::RenderUpdateCallBack(const void *ctx, const CRect &SrcRect, const CRect &DestRect) { - CAmlogic *codec = (CAmlogic*)ctx; + CAMLCodec *codec = (CAMLCodec*)ctx; codec->SetVideoRect(SrcRect, DestRect); } diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.h index bff6cd6403fd4..37f4a9b4030f2 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.h +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.h @@ -30,11 +30,11 @@ typedef struct am_private_t am_private_t; class DllLibAmCodec; -class CAmlogic : public CThread +class CAMLCodec : public CThread { public: - CAmlogic(); - virtual ~CAmlogic(); + CAMLCodec(); + virtual ~CAMLCodec(); bool OpenDecoder(CDVDStreamInfo &hints); void CloseDecoder(); diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp index 204209cf2d46d..b2ac0c5094626 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp @@ -82,7 +82,7 @@ bool CDVDVideoCodecAmlogic::Open(CDVDStreamInfo &hints, CDVDCodecOptions &option } m_hints = hints; - m_Codec = new CAmlogic(); + m_Codec = new CAMLCodec(); if (!m_Codec) { CLog::Log(LOGERROR, "%s: Failed to create Amlogic Codec", __MODULE_NAME__); diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h index 268acb7711754..d372634dfc52e 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h @@ -23,7 +23,7 @@ #include "DVDVideoCodec.h" #include "DVDStreamInfo.h" -class CAmlogic; +class CAMLCodec; class CDVDVideoCodecAmlogic : public CDVDVideoCodec { @@ -43,7 +43,7 @@ class CDVDVideoCodecAmlogic : public CDVDVideoCodec virtual const char* GetName(void) { return (const char*)m_pFormatName; } protected: - CAmlogic *m_Codec; + CAMLCodec *m_Codec; const char *m_pFormatName; DVDVideoPicture m_videobuffer; bool m_opened; From b67bae525daa2146e0471642c12764f81720dabe Mon Sep 17 00:00:00 2001 From: davilla Date: Mon, 24 Dec 2012 19:11:18 -0500 Subject: [PATCH 087/180] [aml] changed, expose pStream->r_frame_rate, fps from pStream->avg_frame_rate can be wrong --- xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.h | 4 ++++ xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp | 12 ++++++++++++ xbmc/cores/dvdplayer/DVDStreamInfo.cpp | 8 ++++++++ xbmc/cores/dvdplayer/DVDStreamInfo.h | 2 ++ 4 files changed, 26 insertions(+) diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.h b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.h index aac0ccec7b2d6..a48a902b25692 100644 --- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.h +++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.h @@ -154,6 +154,8 @@ class CDemuxStreamVideo : public CDemuxStream { iFpsScale = 0; iFpsRate = 0; + irFpsScale = 0; + irFpsRate = 0; iHeight = 0; iWidth = 0; fAspect = 0.0; @@ -168,6 +170,8 @@ class CDemuxStreamVideo : public CDemuxStream virtual ~CDemuxStreamVideo() {} int iFpsScale; // scale of 1000 and a rate of 29970 will result in 29.97 fps int iFpsRate; + int irFpsScale; + int irFpsRate; int iHeight; // height of the stream reported by the demuxer int iWidth; // width of the stream reported by the demuxer float fAspect; // display aspect of stream diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp index 7c0ab03e0052f..159165898fce9 100644 --- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp @@ -995,6 +995,18 @@ void CDVDDemuxFFmpeg::AddStream(int iId) st->iFpsScale = 0; } + // added for aml hw decoder, mkv frame-rate can be wrong. + if (pStream->r_frame_rate.den && pStream->r_frame_rate.num) + { + st->irFpsRate = pStream->r_frame_rate.num; + st->irFpsScale = pStream->r_frame_rate.den; + } + else + { + st->irFpsRate = 0; + st->irFpsScale = 0; + } + if (pStream->codec_info_nb_frames > 0 && pStream->codec_info_nb_frames <= 2 && m_pInput->IsStreamType(DVDSTREAM_TYPE_DVD)) diff --git a/xbmc/cores/dvdplayer/DVDStreamInfo.cpp b/xbmc/cores/dvdplayer/DVDStreamInfo.cpp index 4d051753b5731..6d6c6fa42b4ce 100644 --- a/xbmc/cores/dvdplayer/DVDStreamInfo.cpp +++ b/xbmc/cores/dvdplayer/DVDStreamInfo.cpp @@ -50,6 +50,8 @@ void CDVDStreamInfo::Clear() fpsscale = 0; fpsrate = 0; + rfpsscale= 0; + rfpsrate = 0; height = 0; width = 0; aspect = 0.0; @@ -91,6 +93,8 @@ bool CDVDStreamInfo::Equal(const CDVDStreamInfo& right, bool withextradata) // VIDEO if( fpsscale != right.fpsscale || fpsrate != right.fpsrate + || rfpsscale!= right.rfpsscale + || rfpsrate != right.rfpsrate || height != right.height || width != right.width || stills != right.stills @@ -147,6 +151,8 @@ void CDVDStreamInfo::Assign(const CDVDStreamInfo& right, bool withextradata) // VIDEO fpsscale = right.fpsscale; fpsrate = right.fpsrate; + rfpsscale= right.rfpsscale; + rfpsrate = right.rfpsrate; height = right.height; width = right.width; aspect = right.aspect; @@ -201,6 +207,8 @@ void CDVDStreamInfo::Assign(const CDemuxStream& right, bool withextradata) const CDemuxStreamVideo *stream = static_cast(&right); fpsscale = stream->iFpsScale; fpsrate = stream->iFpsRate; + rfpsscale = stream->irFpsScale; + rfpsrate = stream->irFpsRate; height = stream->iHeight; width = stream->iWidth; aspect = stream->fAspect; diff --git a/xbmc/cores/dvdplayer/DVDStreamInfo.h b/xbmc/cores/dvdplayer/DVDStreamInfo.h index 825e7e67e6205..47e5f73c460de 100644 --- a/xbmc/cores/dvdplayer/DVDStreamInfo.h +++ b/xbmc/cores/dvdplayer/DVDStreamInfo.h @@ -67,6 +67,8 @@ class CDVDStreamInfo // VIDEO int fpsscale; // scale of 1000 and a rate of 29970 will result in 29.97 fps int fpsrate; + int rfpsscale; + int rfpsrate; int height; // height of the stream reported by the demuxer int width; // width of the stream reported by the demuxer float aspect; // display aspect as reported by demuxer From a89eb34be1193fe0399c65137a002c84d7d27057 Mon Sep 17 00:00:00 2001 From: davilla Date: Mon, 24 Dec 2012 19:14:20 -0500 Subject: [PATCH 088/180] [aml] fixed, 1) video_rate can be wrong, use r_frame_rate instead of avg_frame_rate, 2) calc iDuration before using it --- .../dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index 3d246fb5d0bef..58a09d9342a77 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -143,6 +143,7 @@ class DllLibAmCodec : public DllDynamic, DllLibamCodecInterface #define TRICKMODE_I 0x01 #define TRICKMODE_FFFB 0x02 +// same as AV_NOPTS_VALUE #define INT64_0 INT64_C(0x8000000000000000) #define EXTERNAL_PTS (1) @@ -482,7 +483,7 @@ int check_in_pts(am_private_t *para, am_packet_t *pkt) last_v_duration = pkt->avduration ? pkt->avduration : 1; } else { if (!para->check_first_pts) { - if (para->m_dll->codec_checkin_pts(pkt->codec, pts) != 0) { + if (para->m_dll->codec_checkin_pts(pkt->codec, 0) != 0) { CLog::Log(LOGDEBUG, "ERROR check in 0 to video pts error!"); return PLAYER_PTS_ERROR; } @@ -1395,8 +1396,8 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) // video_ratio = m_dll->av_d2q(hints.aspect, SHRT_MAX); am_private->video_ratio = ((int32_t)video_ratio.num << 16) | video_ratio.den; am_private->video_ratio64 = ((int64_t)video_ratio.num << 32) | video_ratio.den; - if (hints.fpsrate > 0 && hints.fpsscale != 0) - am_private->video_rate = 0.5 + (float)UNIT_FREQ * hints.fpsscale / hints.fpsrate; + if (hints.rfpsrate > 0 && hints.rfpsscale != 0) + am_private->video_rate = 0.5 + (float)UNIT_FREQ * hints.rfpsscale / hints.rfpsrate; else { // stupid PVR hacks because it does not fill in all of hints. @@ -1442,8 +1443,8 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) am_private->flv_flag = 1; } - CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder hints.fpsrate(%d), hints.fpsscale(%d), video_rate(%d)", - hints.fpsrate, hints.fpsscale, am_private->video_rate); + CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder hints.fpsrate(%d), hints.fpsscale(%d), hints.rfpsrate(%d), hints.rfpsscale(%d), video_rate(%d)", + hints.fpsrate, hints.fpsscale, hints.rfpsrate, hints.rfpsscale, am_private->video_rate); CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder hints.aspect(%f), video_ratio.num(%d), video_ratio.den(%d)", hints.aspect, video_ratio.num, video_ratio.den); CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder hints.orientation(%d), hints.forced_aspect(%d)", @@ -1601,11 +1602,15 @@ int CAMLCodec::Decode(unsigned char *pData, size_t size, double dts, double pts) am_private->am_pkt.avpts = AV_NOPTS_VALUE; else am_private->am_pkt.avpts = 0.5 + (pts * PTS_FREQ) / DVD_TIME_BASE; + if (dts == DVD_NOPTS_VALUE) am_private->am_pkt.avdts = AV_NOPTS_VALUE; else am_private->am_pkt.avdts = 0.5 + (dts * PTS_FREQ) / DVD_TIME_BASE; + //CLog::Log(LOGDEBUG, "CAMLCodec::Decode: dts(%f), pts(%f), avdts(%llx), avpts(%llx)", + // dts, pts, am_private->am_pkt.avdts, am_private->am_pkt.avpts); + set_header_info(am_private); write_av_packet(am_private, &am_private->am_pkt); @@ -1647,15 +1652,15 @@ int CAMLCodec::Decode(unsigned char *pData, size_t size, double dts, double pts) bool CAMLCodec::GetPicture(DVDVideoPicture *pDvdVideoPicture) { + pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED; + pDvdVideoPicture->format = RENDER_FMT_BYPASS; + pDvdVideoPicture->iDuration = (double)(am_private->video_rate * DVD_TIME_BASE) / UNIT_FREQ; + pDvdVideoPicture->dts = DVD_NOPTS_VALUE; pDvdVideoPicture->pts = GetPlayerPtsSeconds() * (double)DVD_TIME_BASE; // video pts cannot be late or dvdplayer goes nuts, // so run it one frame ahead - pDvdVideoPicture->pts += pDvdVideoPicture->iDuration; - - pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED; - pDvdVideoPicture->format = RENDER_FMT_BYPASS; - pDvdVideoPicture->iDuration = (double)(am_private->video_rate * DVD_TIME_BASE) / UNIT_FREQ; + pDvdVideoPicture->pts += 2 * pDvdVideoPicture->iDuration; return true; } @@ -1718,6 +1723,8 @@ void CAMLCodec::Process() pts_video = get_pts_video(); if (m_cur_pts != pts_video) { + //CLog::Log(LOGDEBUG, "CAMLCodec::Process: pts_video(%lld), pts_video/PTS_FREQ(%f), duration(%f)", + // pts_video, (double)pts_video/PTS_FREQ, 1.0/((double)(pts_video - m_cur_pts)/PTS_FREQ)); // other threads look at these, do them first m_cur_pts = pts_video; m_cur_pictcnt++; @@ -1766,6 +1773,7 @@ double CAMLCodec::GetPlayerPtsSeconds() void CAMLCodec::SetVideoPtsSeconds(const double pts) { + //CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoPtsSeconds: pts(%f)", pts); set_pts_pcrscr((int64_t)(pts * PTS_FREQ)); } From e366a12db4b47bfd01bccaf07a8355bb069e6e00 Mon Sep 17 00:00:00 2001 From: davilla Date: Mon, 24 Dec 2012 19:16:17 -0500 Subject: [PATCH 089/180] [aml] changed, also ignore m_pullupCorrection if RENDER_FMT_BYPASS, it does nothing but waste cpu --- xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp index 47282001019bb..29ee97ffbb37c 100644 --- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp @@ -1174,8 +1174,11 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) limited = true; //correct any pattern in the timestamps - m_pullupCorrection.Add(pts); - pts += m_pullupCorrection.GetCorrection(); + if (m_output.color_format != RENDER_FMT_BYPASS) + { + m_pullupCorrection.Add(pts); + pts += m_pullupCorrection.GetCorrection(); + } //try to calculate the framerate CalcFrameRate(); From a3dfd738936b81b176944d94a0cd2cf94e5e10dc Mon Sep 17 00:00:00 2001 From: davilla Date: Mon, 24 Dec 2012 19:18:42 -0500 Subject: [PATCH 090/180] [aml] changed, temp raise the trip fomr 100ms to 250ms for Discontinuity1 check --- xbmc/cores/dvdplayer/DVDPlayerAudio.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp index 3c89a03d0dfa0..a25cdc61f2ea0 100644 --- a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp @@ -645,7 +645,8 @@ void CDVDPlayerAudio::HandleSyncError(double duration) double error = m_dvdAudio.GetPlayingPts() - clock; int64_t now; -#if defined(TARGET_ANDROID) +//#if defined(TARGET_ANDROID) +#if 1 if( fabs(error) > DVD_MSEC_TO_TIME(250) || m_syncclock ) #else if( fabs(error) > DVD_MSEC_TO_TIME(100) || m_syncclock ) From c5ec86af1105cea6b02f2d2d8628606400c2b9fb Mon Sep 17 00:00:00 2001 From: Yang Huang Date: Tue, 25 Dec 2012 11:04:24 -0500 Subject: [PATCH 091/180] delete context if connect fails --- xbmc/filesystem/NFSFile.cpp | 12 ++++++++++++ xbmc/filesystem/NFSFile.h | 1 + 2 files changed, 13 insertions(+) diff --git a/xbmc/filesystem/NFSFile.cpp b/xbmc/filesystem/NFSFile.cpp index a7b49b3b57845..5e42114326701 100644 --- a/xbmc/filesystem/NFSFile.cpp +++ b/xbmc/filesystem/NFSFile.cpp @@ -140,6 +140,16 @@ void CNfsConnection::destroyOpenContexts() m_openContextMap.clear(); } +void CNfsConnection::destroyContext(const CStdString &exportName) +{ + struct nfs_context *context = getContextFromMap(exportName); + if(context) { + tOpenContextMap::iterator it = m_openContextMap.find(exportName.c_str()); + m_openContextMap.erase(it); + m_pLibNfs->nfs_destroy_context(context); + } +} + struct nfs_context *CNfsConnection::getContextFromMap(const CStdString &exportname, bool forceCacheHit/* = false*/) { struct nfs_context *pRet = NULL; @@ -165,6 +175,7 @@ struct nfs_context *CNfsConnection::getContextFromMap(const CStdString &exportna //context is timed out //destroy it and return NULL CLog::Log(LOGDEBUG, "NFS: Old context timed out - destroying it"); + m_openContextMap.erase(it); m_pLibNfs->nfs_destroy_context(it->second.pContext); } } @@ -288,6 +299,7 @@ bool CNfsConnection::Connect(const CURL& url, CStdString &relativePath) if(nfsRet != 0) { CLog::Log(LOGERROR,"NFS: Failed to mount nfs share: %s (%s)\n", exportPath.c_str(), m_pLibNfs->nfs_get_error(m_pNfsContext)); + destroyContext(url.GetHostName() + exportPath); return false; } CLog::Log(LOGDEBUG,"NFS: Connected to server %s and export %s\n", url.GetHostName().c_str(), exportPath.c_str()); diff --git a/xbmc/filesystem/NFSFile.h b/xbmc/filesystem/NFSFile.h index 7e2db95aa7c19..bd758e7117b2b 100644 --- a/xbmc/filesystem/NFSFile.h +++ b/xbmc/filesystem/NFSFile.h @@ -117,6 +117,7 @@ class CNfsConnection : public CCriticalSection struct nfs_context *getContextFromMap(const CStdString &exportname, bool forceCacheHit = false); int getContextForExport(const CStdString &exportname);//get context for given export and add to open contexts map - sets m_pNfsContext (my return a already mounted cached context) void destroyOpenContexts(); + void destroyContext(const CStdString &exportName); void resolveHost(const CURL &url);//resolve hostname by dnslookup void keepAlive(std::string _exportPath, struct nfsfh *_pFileHandle); }; From 901d03565653750607f8f97133028c0dc4975305 Mon Sep 17 00:00:00 2001 From: Yang Huang Date: Tue, 25 Dec 2012 19:26:53 -0500 Subject: [PATCH 092/180] lock map and change order of delete and context destroy --- xbmc/filesystem/NFSFile.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/xbmc/filesystem/NFSFile.cpp b/xbmc/filesystem/NFSFile.cpp index 5e42114326701..8f61878b8556e 100644 --- a/xbmc/filesystem/NFSFile.cpp +++ b/xbmc/filesystem/NFSFile.cpp @@ -142,12 +142,13 @@ void CNfsConnection::destroyOpenContexts() void CNfsConnection::destroyContext(const CStdString &exportName) { - struct nfs_context *context = getContextFromMap(exportName); - if(context) { - tOpenContextMap::iterator it = m_openContextMap.find(exportName.c_str()); + CSingleLock lock(openContextLock); + tOpenContextMap::iterator it = m_openContextMap.find(exportName.c_str()); + if(it != m_openContextMap.end()) + { + m_pLibNfs->nfs_destroy_context(it->second.pContext); m_openContextMap.erase(it); - m_pLibNfs->nfs_destroy_context(context); - } + } } struct nfs_context *CNfsConnection::getContextFromMap(const CStdString &exportname, bool forceCacheHit/* = false*/) @@ -175,8 +176,8 @@ struct nfs_context *CNfsConnection::getContextFromMap(const CStdString &exportna //context is timed out //destroy it and return NULL CLog::Log(LOGDEBUG, "NFS: Old context timed out - destroying it"); - m_openContextMap.erase(it); m_pLibNfs->nfs_destroy_context(it->second.pContext); + m_openContextMap.erase(it); } } return pRet; From 89f5457f76caded8692158e0f8ede170963ed654 Mon Sep 17 00:00:00 2001 From: davilla Date: Wed, 26 Dec 2012 10:41:51 -0500 Subject: [PATCH 093/180] [aml] remove usless inlines, the compiler will take care of inlining and it is much smarter than us --- xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp | 10 +++++----- xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h | 4 ++-- xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp index 9f4e50da93ed4..6a7fce5ef5877 100644 --- a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp +++ b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp @@ -145,7 +145,7 @@ IAESink *CSoftAE::GetSink(AEAudioFormat &newFormat, bool passthrough, std::strin } /* this method MUST be called while holding m_streamLock */ -inline CSoftAEStream *CSoftAE::GetMasterStream() +CSoftAEStream *CSoftAE::GetMasterStream() { /* remove any destroyed streams first */ for (StreamList::iterator itt = m_streams.begin(); itt != m_streams.end();) @@ -616,7 +616,7 @@ void CSoftAE::VerifySoundDevice(std::string& device, bool passthrough) device = firstDevice; } -inline void CSoftAE::GetDeviceFriendlyName(std::string &device) +void CSoftAE::GetDeviceFriendlyName(std::string &device) { m_deviceFriendlyName = "Device not found"; /* Match the device and find its friendly name */ @@ -1369,7 +1369,7 @@ unsigned int CSoftAE::RunStreamStage(unsigned int channelCount, void *out, bool return mixed; } -inline void CSoftAE::ResumeSlaveStreams(const StreamList &streams) +void CSoftAE::ResumeSlaveStreams(const StreamList &streams) { if (streams.empty()) return; @@ -1384,7 +1384,7 @@ inline void CSoftAE::ResumeSlaveStreams(const StreamList &streams) } } -inline void CSoftAE::RemoveStream(StreamList &streams, CSoftAEStream *stream) +void CSoftAE::RemoveStream(StreamList &streams, CSoftAEStream *stream) { StreamList::iterator f = std::find(streams.begin(), streams.end(), stream); if (f != streams.end()) @@ -1394,7 +1394,7 @@ inline void CSoftAE::RemoveStream(StreamList &streams, CSoftAEStream *stream) m_streamsPlaying = !m_playingStreams.empty(); } -inline void CSoftAE::ProcessSuspend() +void CSoftAE::ProcessSuspend() { bool sinkIsSuspended = false; unsigned int curSystemClock = 0; diff --git a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h index 56fb41712379f..0b9d8390b956c 100644 --- a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h +++ b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h @@ -120,9 +120,9 @@ class CSoftAE : public IThreadedAE bool SetupEncoder(AEAudioFormat &format); void Deinitialize(); - inline void ProcessSuspend(); /* enter suspend state if nothing to play and sink allows */ + void ProcessSuspend(); /* enter suspend state if nothing to play and sink allows */ - inline void GetDeviceFriendlyName(std::string &device); + void GetDeviceFriendlyName(std::string &device); IAESink *GetSink(AEAudioFormat &desiredFormat, bool passthrough, std::string &device); void StopAllSounds(); diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp index 2819d984d0779..3c31aa8834fe0 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp @@ -79,7 +79,7 @@ CAESinkALSA::~CAESinkALSA() Deinitialize(); } -inline CAEChannelInfo CAESinkALSA::GetChannelLayout(AEAudioFormat format) +CAEChannelInfo CAESinkALSA::GetChannelLayout(AEAudioFormat format) { unsigned int count = 0; From be572a7d2694748fc83628917cae6b7a3b60bf73 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 27 Dec 2012 00:42:36 -0500 Subject: [PATCH 094/180] [aml] fix busted locales in linux, probably still broken in android Combined with the newly installed glibc locale data, this fixes i18n issues related to text processing. Fixes, for example, uppercase non-ascii characters at the confluence home screen. --- xbmc/LangInfo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xbmc/LangInfo.cpp b/xbmc/LangInfo.cpp index 5071fe90d43bf..9d273e6247ed4 100644 --- a/xbmc/LangInfo.cpp +++ b/xbmc/LangInfo.cpp @@ -156,7 +156,7 @@ void CLangInfo::CRegion::SetGlobalLocale() // decimal separator is changed depending of the current language // (ie. "," in French or Dutch instead of "."). This breaks atof() and // others similar functions. -#if defined(__FreeBSD__) || defined(TARGET_DARWIN_OSX) +#if defined(__FreeBSD__) || defined(TARGET_DARWIN_OSX) || defined(TARGET_LINUX) // on FreeBSD and darwin libstdc++ is compiled with "generic" locale support if (setlocale(LC_COLLATE, strLocale.c_str()) == NULL || setlocale(LC_CTYPE, strLocale.c_str()) == NULL) From fc919fa3a57fccdfa43a0e8896e20bea01c1e16f Mon Sep 17 00:00:00 2001 From: davilla Date: Fri, 28 Dec 2012 15:32:27 -0500 Subject: [PATCH 095/180] [aml] fixed, 60 fps could be 1280x720/60p --- xbmc/cores/dvdplayer/Edl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xbmc/cores/dvdplayer/Edl.cpp b/xbmc/cores/dvdplayer/Edl.cpp index a07164b09243b..3c27256f3bcd5 100644 --- a/xbmc/cores/dvdplayer/Edl.cpp +++ b/xbmc/cores/dvdplayer/Edl.cpp @@ -79,7 +79,7 @@ bool CEdl::ReadEditDecisionLists(const CStdString& strMovie, const float fFrameR * back frame markers. However, this doesn't seem possible for MythTV. */ float fFramesPerSecond; - if (int(fFrameRate * 100) == 5994) // 59.940 fps = NTSC or 60i content + if (iHeight != 720 && int(fFrameRate * 100) == 5994) // 59.940 fps = NTSC or 60i content except for 1280x720/60 { fFramesPerSecond = fFrameRate / 2; // ~29.97f - division used to retain accuracy of original. CLog::Log(LOGDEBUG, "%s - Assuming NTSC or 60i interlaced content. Adjusted frames per second from %.3f (~59.940 fps) to %.3f", From ed19c333b2b5f82ec1a18c2751af454966453082 Mon Sep 17 00:00:00 2001 From: davilla Date: Fri, 28 Dec 2012 15:34:01 -0500 Subject: [PATCH 096/180] [aml] fixed, rfpsrate/rfpsscale comes from ffmpeg demus but these might be zero, check and defer to fpsrate/fpsscale --- .../dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index 58a09d9342a77..6338d9c6dbdd5 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -1391,23 +1391,38 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) am_private->video_pid = hints.pid; //am_private->video_pid = 0; + // handle video ratio AVRational video_ratio = m_dll->av_d2q(1, SHRT_MAX); //if (!hints.forced_aspect) // video_ratio = m_dll->av_d2q(hints.aspect, SHRT_MAX); am_private->video_ratio = ((int32_t)video_ratio.num << 16) | video_ratio.den; am_private->video_ratio64 = ((int64_t)video_ratio.num << 32) | video_ratio.den; + + // handle video rate if (hints.rfpsrate > 0 && hints.rfpsscale != 0) - am_private->video_rate = 0.5 + (float)UNIT_FREQ * hints.rfpsscale / hints.rfpsrate; + { + // check ffmpeg r_frame_rate 1st + am_private->video_rate = 0.5 + (float)UNIT_FREQ * hints.rfpsscale / hints.rfpsrate; + } + else if (hints.fpsrate > 0 && hints.fpsscale != 0) + { + // then ffmpeg avg_frame_rate next + am_private->video_rate = 0.5 + (float)UNIT_FREQ * hints.fpsscale / hints.fpsrate; + } else { // stupid PVR hacks because it does not fill in all of hints. if (hints.codec == CODEC_ID_MPEG2VIDEO) { am_private->video_rate = 0.5 + (float)UNIT_FREQ * 1001 / 30000; - if (hints.codec == 1280) + if (hints.width == 1280) am_private->video_rate = 0.5 + (float)UNIT_FREQ * 1001 / 60000;; } } + // check for 1920x1080, interlaced, 25 fps + // incorrectly reported as 50 fps (yes, video_rate == 1920) + if (hints.width == 1920 && am_private->video_rate == 1920) + am_private->video_rate = 0.5 + (float)UNIT_FREQ * 1001 / 25000; // handle orientation am_private->video_rotation_degree = 0; @@ -1473,6 +1488,7 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) break; case VFORMAT_H264: case VFORMAT_H264MVC: + am_private->vcodec.am_sysinfo.format = VIDEO_DEC_FORMAT_H264; am_private->vcodec.am_sysinfo.param = (void*)(EXTERNAL_PTS | SYNC_OUTSIDE); break; case VFORMAT_REAL: From 44cc7e928cfabb175e46177fda8420c7cf3988a5 Mon Sep 17 00:00:00 2001 From: davilla Date: Sat, 29 Dec 2012 14:56:02 -0500 Subject: [PATCH 097/180] [aml] restore lost aml_probe_hdmi_audio function --- xbmc/utils/AMLUtils.cpp | 68 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/xbmc/utils/AMLUtils.cpp b/xbmc/utils/AMLUtils.cpp index a3a9a1859e2cb..18b6019680555 100644 --- a/xbmc/utils/AMLUtils.cpp +++ b/xbmc/utils/AMLUtils.cpp @@ -25,6 +25,8 @@ #include #include +#include "utils/StringUtils.h" + int aml_set_sysfs_str(const char *path, const char *val) { int fd = open(path, O_CREAT | O_RDWR | O_TRUNC, 0644); @@ -140,3 +142,69 @@ void aml_set_audio_passthrough(bool passthrough) if (aml_present()) aml_set_sysfs_int("/sys/class/audiodsp/digital_raw", passthrough ? 1:0); } + +void aml_probe_hdmi_audio() +{ + std::vector audio_formats; + // Audio {format, channel, freq, cce} + // {1, 7, 7f, 7} + // {7, 5, 1e, 0} + // {2, 5, 7, 0} + // {11, 7, 7e, 1} + // {10, 7, 6, 0} + // {12, 7, 7e, 0} + + int fd = open("/sys/class/amhdmitx/amhdmitx0/edid", O_RDONLY); + if (fd >= 0) + { + char valstr[1024] = {0}; + + read(fd, valstr, sizeof(valstr) - 1); + valstr[strlen(valstr)] = '\0'; + close(fd); + + std::vector probe_str; + StringUtils::SplitString(valstr, "\n", probe_str); + + for (size_t i = 0; i < probe_str.size(); i++) + { + if (probe_str[i].find("Audio") == std::string::npos) + { + for (size_t j = i+1; j < probe_str.size(); j++) + { + if (probe_str[i].find("{1,") != std::string::npos) + printf(" PCM found {1,\n"); + else if (probe_str[i].find("{2,") != std::string::npos) + printf(" AC3 found {2,\n"); + else if (probe_str[i].find("{3,") != std::string::npos) + printf(" MPEG1 found {3,\n"); + else if (probe_str[i].find("{4,") != std::string::npos) + printf(" MP3 found {4,\n"); + else if (probe_str[i].find("{5,") != std::string::npos) + printf(" MPEG2 found {5,\n"); + else if (probe_str[i].find("{6,") != std::string::npos) + printf(" AAC found {6,\n"); + else if (probe_str[i].find("{7,") != std::string::npos) + printf(" DTS found {7,\n"); + else if (probe_str[i].find("{8,") != std::string::npos) + printf(" ATRAC found {8,\n"); + else if (probe_str[i].find("{9,") != std::string::npos) + printf(" One_Bit_Audio found {9,\n"); + else if (probe_str[i].find("{10,") != std::string::npos) + printf(" Dolby found {10,\n"); + else if (probe_str[i].find("{11,") != std::string::npos) + printf(" DTS_HD found {11,\n"); + else if (probe_str[i].find("{12,") != std::string::npos) + printf(" MAT found {12,\n"); + else if (probe_str[i].find("{13,") != std::string::npos) + printf(" ATRAC found {13,\n"); + else if (probe_str[i].find("{14,") != std::string::npos) + printf(" WMA found {14,\n"); + else + break; + } + break; + } + } + } +} From 206362ef0200cc4c59107215cadb685a17f8d337 Mon Sep 17 00:00:00 2001 From: davilla Date: Mon, 31 Dec 2012 15:45:05 -0500 Subject: [PATCH 098/180] [aml] fixed, always disable video when not playing it or we can get funky green showing on suspend --- xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index 6338d9c6dbdd5..b97de3277f705 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -1379,6 +1379,7 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) m_brightness = -1; m_vbufsize = 500000 * 2; + ShowMainVideo(false); am_packet_init(&am_private->am_pkt); // default stream type @@ -1565,6 +1566,8 @@ void CAMLCodec::CloseDecoder() am_private->extradata = NULL; // return tsync to default so external apps work aml_set_sysfs_int("/sys/class/tsync/enable", 1); + + ShowMainVideo(false); } void CAMLCodec::Reset() From 04228866e0f0574a3b2e0057246af7a2e9e56731 Mon Sep 17 00:00:00 2001 From: davilla Date: Mon, 31 Dec 2012 15:46:07 -0500 Subject: [PATCH 099/180] [aml] rework m3 syspend/resume --- .../linux/PivosPowerSyscall.cpp | 30 +++++++++++++++++-- .../powermanagement/linux/PivosPowerSyscall.h | 6 +++- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/xbmc/powermanagement/linux/PivosPowerSyscall.cpp b/xbmc/powermanagement/linux/PivosPowerSyscall.cpp index df76ca958d208..78642921390ac 100644 --- a/xbmc/powermanagement/linux/PivosPowerSyscall.cpp +++ b/xbmc/powermanagement/linux/PivosPowerSyscall.cpp @@ -37,6 +37,9 @@ CPivosPowerSyscall::CPivosPowerSyscall() } m_CanHibernate = false; m_CanReboot = true; + + m_OnResume = false; + m_OnSuspend = false; } bool CPivosPowerSyscall::Powerdown() @@ -46,9 +49,7 @@ bool CPivosPowerSyscall::Powerdown() bool CPivosPowerSyscall::Suspend() { - CPowerSyscallWithoutEvents::Suspend(); - - aml_set_sysfs_str("/sys/power/state", "mem"); + m_OnSuspend = true; return true; } @@ -87,6 +88,29 @@ int CPivosPowerSyscall::BatteryLevel() return 0; } +bool CPivosPowerSyscall::PumpPowerEvents(IPowerEventsCallback *callback) +{ + if (m_OnSuspend) + { + // do the CPowerManager::OnSleep() callback + callback->OnSleep(); + m_OnResume = true; + m_OnSuspend = false; + // wait for all our threads to do their thing + usleep(1 * 1000 * 1000); + aml_set_sysfs_str("/sys/power/state", "mem"); + usleep(100 * 1000); + } + else if (m_OnResume) + { + // do the CPowerManager::OnWake() callback + callback->OnWake(); + m_OnResume = false; + } + + return true; +} + bool CPivosPowerSyscall::HasPivosPowerSyscall() { return aml_present(); diff --git a/xbmc/powermanagement/linux/PivosPowerSyscall.h b/xbmc/powermanagement/linux/PivosPowerSyscall.h index e25b0d5e7b98d..a6c0ac97f09fe 100644 --- a/xbmc/powermanagement/linux/PivosPowerSyscall.h +++ b/xbmc/powermanagement/linux/PivosPowerSyscall.h @@ -20,7 +20,7 @@ #include "powermanagement/IPowerSyscall.h" -class CPivosPowerSyscall : public CPowerSyscallWithoutEvents +class CPivosPowerSyscall : public IPowerSyscall { public: CPivosPowerSyscall(); @@ -36,6 +36,7 @@ class CPivosPowerSyscall : public CPowerSyscallWithoutEvents virtual bool CanHibernate(); virtual bool CanReboot(); virtual int BatteryLevel(); + virtual bool PumpPowerEvents(IPowerEventsCallback *callback); static bool HasPivosPowerSyscall(); @@ -44,4 +45,7 @@ class CPivosPowerSyscall : public CPowerSyscallWithoutEvents bool m_CanSuspend; bool m_CanHibernate; bool m_CanReboot; + + bool m_OnResume; + bool m_OnSuspend; }; From cba05c5c440ab0582740c49c14b833125d8ba633 Mon Sep 17 00:00:00 2001 From: davilla Date: Mon, 31 Dec 2012 15:47:55 -0500 Subject: [PATCH 100/180] [aml] fixed, m3 1080p display --- xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp b/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp index 0729b965bc7e4..4746069bf124e 100644 --- a/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp +++ b/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp @@ -209,7 +209,6 @@ bool CEGLNativeTypeAmlogic::SetDisplayResolution(const char *resolution) CStdString modestr = resolution; // switch display resolution aml_set_sysfs_str("/sys/class/display/mode", modestr.c_str()); - usleep(500 * 1000); // setup gui freescale depending on display resolution DisableFreeScale(); @@ -307,7 +306,6 @@ void CEGLNativeTypeAmlogic::EnableFreeScale() { // remove default OSD and video path (default_osd default) aml_set_sysfs_str("/sys/class/vfm/map", "rm all"); - usleep(60 * 1000); // add OSD path aml_set_sysfs_str("/sys/class/vfm/map", "add osdpath osd amvideo"); @@ -320,12 +318,10 @@ void CEGLNativeTypeAmlogic::EnableFreeScale() aml_set_sysfs_int("/sys/class/graphics/fb1/scale_height", 720); aml_set_sysfs_int("/sys/class/graphics/fb0/free_scale", 1); aml_set_sysfs_int("/sys/class/graphics/fb1/free_scale", 1); - usleep(60 * 1000); // remove OSD path aml_set_sysfs_int("/sys/class/graphics/fb0/free_scale", 0); aml_set_sysfs_int("/sys/class/graphics/fb1/free_scale", 0); aml_set_sysfs_str("/sys/class/vfm/map", "rm osdpath"); - usleep(60 * 1000); // add video path aml_set_sysfs_str("/sys/class/vfm/map", "add videopath decoder ppmgr amvideo"); // enable video free scale (scaling to 1920x1080 with frame buffer size 1280x720) @@ -334,7 +330,6 @@ void CEGLNativeTypeAmlogic::EnableFreeScale() aml_set_sysfs_int("/sys/class/ppmgr/ppscaler", 1); aml_set_sysfs_str("/sys/class/ppmgr/ppscaler_rect", "0 0 1919 1079 0"); aml_set_sysfs_str("/sys/class/ppmgr/disp", "1280 720"); - usleep(60 * 1000); // aml_set_sysfs_int("/sys/class/graphics/fb0/free_scale", 0); aml_set_sysfs_int("/sys/class/graphics/fb1/free_scale", 0); @@ -342,13 +337,14 @@ void CEGLNativeTypeAmlogic::EnableFreeScale() aml_set_sysfs_int("/sys/class/graphics/fb0/scale_height", 720); aml_set_sysfs_int("/sys/class/graphics/fb1/scale_width", 1280); aml_set_sysfs_int("/sys/class/graphics/fb1/scale_height", 720); - aml_set_sysfs_int("/sys/class/graphics/fb0/free_scale", 1); - aml_set_sysfs_int("/sys/class/graphics/fb1/free_scale", 1); - usleep(60 * 1000); // aml_set_sysfs_int("/sys/class/video/disable_video", 2); aml_set_sysfs_str("/sys/class/display/axis", "0 0 1279 719 0 0 0 0"); aml_set_sysfs_str("/sys/class/ppmgr/ppscaler_rect", "0 0 1279 719 1"); + // + aml_set_sysfs_int("/sys/class/graphics/fb0/free_scale", 1); + aml_set_sysfs_int("/sys/class/graphics/fb1/free_scale", 1); + aml_set_sysfs_str("/sys/class/graphics/fb0/free_scale_axis", "0 0 1279 719"); } void CEGLNativeTypeAmlogic::DisableFreeScale() @@ -357,17 +353,14 @@ void CEGLNativeTypeAmlogic::DisableFreeScale() aml_set_sysfs_int("/sys/class/graphics/fb0/free_scale", 0); aml_set_sysfs_int("/sys/class/graphics/fb1/free_scale", 0); aml_set_sysfs_str("/sys/class/graphics/fb0/free_scale_axis", "0 0 1279 719"); - aml_set_sysfs_str("/sys/class/display/wr_reg", "m 0x1d26 '0x00b1'"); - usleep(60 * 1000); // revert to default video paths aml_set_sysfs_str("/sys/class/vfm/map", "rm all"); aml_set_sysfs_str("/sys/class/vfm/map", "add default_osd osd amvideo"); aml_set_sysfs_str("/sys/class/vfm/map", "add default decoder ppmgr amvideo"); - usleep(60 * 1000); // disable post processing scaler and disable_video special mode aml_set_sysfs_int("/sys/class/ppmgr/ppscaler", 0); aml_set_sysfs_int("/sys/class/video/disable_video", 0); - usleep(60 * 1000); + aml_set_sysfs_int("/sys/class/video/disable_video", 1); // revert display axis int fd0; From 0ab06cdc13ab1358da9c716ae27dabf29c16eb67 Mon Sep 17 00:00:00 2001 From: davilla Date: Mon, 31 Dec 2012 15:53:14 -0500 Subject: [PATCH 101/180] [aml] add suspend/result AE sink logging --- xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp index 3c31aa8834fe0..adbb4c3fa9cf7 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp @@ -558,6 +558,7 @@ bool CAESinkALSA::SoftSuspend() /* device as we are in exclusive mode and thus allow external */ /* audio sources to play. This requires us to reinitialize */ /* on resume. */ + CLog::Log(LOGDEBUG, "CAESinkALSA::SoftSuspend"); Deinitialize(); @@ -569,6 +570,7 @@ bool CAESinkALSA::SoftResume() /* Sink asked to resume output. To release audio device in */ /* exclusive mode we release the device context and therefore */ /* must reinitialize. Return false to force re-init by engine */ + CLog::Log(LOGDEBUG, "CAESinkALSA::SoftResume"); return false; } From 389ece5dfbc5be822eac16bab94c415bbb9510b5 Mon Sep 17 00:00:00 2001 From: davilla Date: Tue, 1 Jan 2013 12:32:54 -0500 Subject: [PATCH 102/180] [aml] fixed, playback of 60 fps video content --- xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index b97de3277f705..575c15e5b75b2 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -1728,8 +1728,11 @@ void CAMLCodec::Process() // this is a blocking poll that returns every vsync. // since we are running at a higher priority, make sure // we sleep if the call fails or does a timeout. - if (m_dll->codec_poll_cntl(&am_private->vcodec) <= 0) + if (m_dll->codec_poll_cntl(&am_private->vcodec) < 0) + { + CLog::Log(LOGDEBUG, "CAMLCodec::Process: codec_poll_cntl failed"); Sleep(10); + } if (g_application.m_pPlayer && g_application.m_pPlayer->IsPlaying()) { From badc8f179cf811d63442a90dddf46de2fa1d1c54 Mon Sep 17 00:00:00 2001 From: davilla Date: Thu, 3 Jan 2013 11:20:22 -0500 Subject: [PATCH 103/180] [aml] fixed context menu 'remove safely' selection --- xbmc/linux/PosixMountProvider.cpp | 10 ++++++++++ xbmc/linux/PosixMountProvider.h | 2 +- xbmc/storage/linux/UDevProvider.cpp | 7 ++++++- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/xbmc/linux/PosixMountProvider.cpp b/xbmc/linux/PosixMountProvider.cpp index 2420491534a3b..27d639eee538a 100644 --- a/xbmc/linux/PosixMountProvider.cpp +++ b/xbmc/linux/PosixMountProvider.cpp @@ -127,6 +127,16 @@ std::vector CPosixMountProvider::GetDiskUsage() return result; } +bool CPosixMountProvider::Eject(CStdString mountpath) +{ + // just go ahead and try to umount the disk + // if it does umount, life is good, if not, no loss. + std::string cmd = "umount " + mountpath; + system(cmd.c_str()); + + return true; +} + bool CPosixMountProvider::PumpDriveChangeEvents(IStorageEventsCallback *callback) { VECSOURCES drives; diff --git a/xbmc/linux/PosixMountProvider.h b/xbmc/linux/PosixMountProvider.h index da0506cdf4316..02ff302172957 100644 --- a/xbmc/linux/PosixMountProvider.h +++ b/xbmc/linux/PosixMountProvider.h @@ -34,7 +34,7 @@ class CPosixMountProvider : public IStorageProvider virtual std::vector GetDiskUsage(); - virtual bool Eject(CStdString mountpath) { return false; } + virtual bool Eject(CStdString mountpath); virtual bool PumpDriveChangeEvents(IStorageEventsCallback *callback); private: diff --git a/xbmc/storage/linux/UDevProvider.cpp b/xbmc/storage/linux/UDevProvider.cpp index 21b6b506e122e..d9e6a4f43728f 100644 --- a/xbmc/storage/linux/UDevProvider.cpp +++ b/xbmc/storage/linux/UDevProvider.cpp @@ -179,7 +179,12 @@ void CUDevProvider::GetRemovableDrives(VECSOURCES &removableDrives) bool CUDevProvider::Eject(CStdString mountpath) { - return false; + // just go ahead and try to umount the disk + // if it does umount, life is good, if not, no loss. + std::string cmd = "umount " + mountpath; + system(cmd.c_str()); + + return true; } std::vector CUDevProvider::GetDiskUsage() From ea965e7df5c67293364a4238cdf3e9611b6f0dcb Mon Sep 17 00:00:00 2001 From: davilla Date: Sat, 5 Jan 2013 10:20:19 -0500 Subject: [PATCH 104/180] [aml] changed, bump up amlplayer udp buffer sizes --- xbmc/cores/amlplayer/AMLPlayer.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/xbmc/cores/amlplayer/AMLPlayer.cpp b/xbmc/cores/amlplayer/AMLPlayer.cpp index 69ae5f93312a3..d5317725445df 100644 --- a/xbmc/cores/amlplayer/AMLPlayer.cpp +++ b/xbmc/cores/amlplayer/AMLPlayer.cpp @@ -1443,6 +1443,26 @@ void CAMLPlayer::Process() vfs_protocol.name = http_name; url = "xb-" + url; } + else if (url.Left(strlen("udp://")).Equals("udp://")) + { + std::string udp_params; + // bump up the default udp params for ffmpeg. + // ffmpeg will strip out 'dummy=10', we only add it + // to make the logic below with prpending '&' work right. + // to watch for udp errors, 'cat /proc/net/udp' + if (url.find("?") == std::string::npos) + udp_params.append("?dummy=10"); + if (url.find("pkt_size=") == std::string::npos) + udp_params.append("&pkt_size=1316"); + if (url.find("buffer_size=") == std::string::npos) + udp_params.append("&buffer_size=1048576"); + // newer ffmpeg uses fifo_size instead of buf_size + if (url.find("buf_size=") == std::string::npos) + udp_params.append("&buf_size=286720"); + + if (udp_params.size() > 0) + url.append(udp_params); + } CLog::Log(LOGDEBUG, "CAMLPlayer::Process: URL=%s", url.c_str()); if (m_dll->player_init() != PLAYER_SUCCESS) From 48fd044a717225122eee60a73b067fd80902cdec Mon Sep 17 00:00:00 2001 From: davilla Date: Sat, 5 Jan 2013 13:24:59 -0500 Subject: [PATCH 105/180] [aml] use amlplayer for udp:// streams --- system/playercorefactory.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/system/playercorefactory.xml b/system/playercorefactory.xml index badc84f1d75b0..9992693a0fdfb 100644 --- a/system/playercorefactory.xml +++ b/system/playercorefactory.xml @@ -38,6 +38,7 @@ + From b8cd8c66be876732f84d3e8d3e2389aed3b44bd3 Mon Sep 17 00:00:00 2001 From: davilla Date: Sun, 6 Jan 2013 08:06:26 -0500 Subject: [PATCH 106/180] [aml] fix h264 SD content in mp4 playback, video_rate is wrong --- xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index 575c15e5b75b2..c56843a55e474 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -1423,7 +1423,18 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) // check for 1920x1080, interlaced, 25 fps // incorrectly reported as 50 fps (yes, video_rate == 1920) if (hints.width == 1920 && am_private->video_rate == 1920) + { + CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder video_rate exception"); am_private->video_rate = 0.5 + (float)UNIT_FREQ * 1001 / 25000; + } + + // check for SD h265 content incorrectly reported as 60 fsp + // mp4/avi containers :( + if (hints.codec == CODEC_ID_H264 && hints.width == 720 && am_private->video_rate == 1602) + { + CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder video_rate exception"); + am_private->video_rate = 0.5 + (float)UNIT_FREQ * 1001 / 24000; + } // handle orientation am_private->video_rotation_degree = 0; From c90b4bc7b907ee34e151580b1570e0a5e6634239 Mon Sep 17 00:00:00 2001 From: davilla Date: Sun, 6 Jan 2013 09:37:30 -0500 Subject: [PATCH 107/180] [aml] fixed typo --- xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index c56843a55e474..eb6aa4f2843bc 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -1428,7 +1428,7 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) am_private->video_rate = 0.5 + (float)UNIT_FREQ * 1001 / 25000; } - // check for SD h265 content incorrectly reported as 60 fsp + // check for SD h264 content incorrectly reported as 60 fsp // mp4/avi containers :( if (hints.codec == CODEC_ID_H264 && hints.width == 720 && am_private->video_rate == 1602) { From 588370520ae072dcc1b09302a16fd1d72e384b58 Mon Sep 17 00:00:00 2001 From: davilla Date: Sun, 6 Jan 2013 12:52:06 -0500 Subject: [PATCH 108/180] [aml] fixed, trim amlplayer spin up/down time. Saves about 1 second or so on spin up and spin down times" --- xbmc/cores/amlplayer/AMLPlayer.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/xbmc/cores/amlplayer/AMLPlayer.cpp b/xbmc/cores/amlplayer/AMLPlayer.cpp index d5317725445df..a7e9fe566ad10 100644 --- a/xbmc/cores/amlplayer/AMLPlayer.cpp +++ b/xbmc/cores/amlplayer/AMLPlayer.cpp @@ -498,12 +498,14 @@ void CAMLSubTitleThread::Process(void) } else { - usleep(100 * 1000); + if (!m_bStop) + usleep(100 * 1000); } } else { - usleep(250 * 1000); + if (!m_bStop) + usleep(250 * 1000); } } m_subtitle_strings.clear(); @@ -1334,7 +1336,6 @@ void CAMLPlayer::OnStartup() void CAMLPlayer::OnExit() { //CLog::Log(LOGNOTICE, "CAMLPlayer::OnExit()"); - Sleep(1000); m_bStop = true; // if we didn't stop playing, advance to the next item in xbmc's playlist @@ -1471,7 +1472,7 @@ void CAMLPlayer::Process() throw "CAMLPlayer::Process:player init failed"; } CLog::Log(LOGDEBUG, "player init......"); - usleep(250 * 1000); + usleep(50 * 1000); // must be after player_init m_dll->av_register_protocol2(&vfs_protocol, sizeof(vfs_protocol)); @@ -1658,7 +1659,8 @@ void CAMLPlayer::Process() stopPlaying = true; break; } - usleep(250 * 1000); + if (!stopPlaying) + usleep(250 * 1000); } } } From 496972fd9d336e2c349068128b1df2604800bf34 Mon Sep 17 00:00:00 2001 From: davilla Date: Mon, 7 Jan 2013 12:40:08 -0500 Subject: [PATCH 109/180] [aml] change upd buffer values and trip levels --- xbmc/cores/amlplayer/AMLPlayer.cpp | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/xbmc/cores/amlplayer/AMLPlayer.cpp b/xbmc/cores/amlplayer/AMLPlayer.cpp index a7e9fe566ad10..27d6310568edc 100644 --- a/xbmc/cores/amlplayer/AMLPlayer.cpp +++ b/xbmc/cores/amlplayer/AMLPlayer.cpp @@ -1454,12 +1454,12 @@ void CAMLPlayer::Process() if (url.find("?") == std::string::npos) udp_params.append("?dummy=10"); if (url.find("pkt_size=") == std::string::npos) - udp_params.append("&pkt_size=1316"); + udp_params.append("&pkt_size=5264"); if (url.find("buffer_size=") == std::string::npos) - udp_params.append("&buffer_size=1048576"); + udp_params.append("&buffer_size=5390336"); // newer ffmpeg uses fifo_size instead of buf_size if (url.find("buf_size=") == std::string::npos) - udp_params.append("&buf_size=286720"); + udp_params.append("&buf_size=5390336"); if (udp_params.size() > 0) url.append(udp_params); @@ -1496,13 +1496,19 @@ void CAMLPlayer::Process() play_control.need_start = 1; // if 0,you can omit player_start_play API. // just play video/audio immediately. // if 1,then need call "player_start_play" API; - //play_control.auto_buffing_enable = 1; - //play_control.buffing_min = 0.2; - //play_control.buffing_middle = 0.5; - //play_control.buffing_max = 0.8; - //play_control.byteiobufsize =; // maps to av_open_input_file buffer size - //play_control.loopbufsize =; - //play_control.enable_rw_on_pause =; + + // tweak player playback buffers for udp + if (url.Left(strlen("udp://")).Equals("udp://")) + { + play_control.auto_buffing_enable = 1; + play_control.buffing_min = 0.01; // default = 0.01 + play_control.buffing_middle = 0.02; // default = 0.02 + play_control.buffing_max = 0.20; // default = 0.80 + play_control.byteiobufsize = 1024 * 128; // maps to av_open_input_file buffer size (1024 * 32) + //play_control.loopbufsize =; + //play_control.enable_rw_on_pause =; + } + m_aml_state.clear(); m_aml_state.push_back(0); m_pid = m_dll->player_start(&play_control, 0); From 7fce7901efe311261f5a0e88b7b18ac0985006af Mon Sep 17 00:00:00 2001 From: davilla Date: Mon, 7 Jan 2013 14:41:29 -0500 Subject: [PATCH 110/180] [aml] fixed, include width <= 720 in video rate exception --- xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index eb6aa4f2843bc..892c7e98f7a76 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -1430,7 +1430,7 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) // check for SD h264 content incorrectly reported as 60 fsp // mp4/avi containers :( - if (hints.codec == CODEC_ID_H264 && hints.width == 720 && am_private->video_rate == 1602) + if (hints.codec == CODEC_ID_H264 && hints.width <= 720 && am_private->video_rate == 1602) { CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder video_rate exception"); am_private->video_rate = 0.5 + (float)UNIT_FREQ * 1001 / 24000; From 074af1244b58a5d2943795f9051fd1a43bba0732 Mon Sep 17 00:00:00 2001 From: davilla Date: Fri, 11 Jan 2013 10:28:43 -0500 Subject: [PATCH 111/180] [aml] fixed, SD h264 reporting as 30fps should be 24fps --- xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index 892c7e98f7a76..9e862ea4f9960 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -1436,6 +1436,14 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) am_private->video_rate = 0.5 + (float)UNIT_FREQ * 1001 / 24000; } + // check for SD h264 content incorrectly reported as 30 fsp + // mp4/avi containers :( + if (hints.codec == CODEC_ID_H264 && hints.width <= 720 && am_private->video_rate == 3203) + { + CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder video_rate exception"); + am_private->video_rate = 0.5 + (float)UNIT_FREQ * 1001 / 24000; + } + // handle orientation am_private->video_rotation_degree = 0; if (hints.orientation == 90) From 3bb2de7ce13010f0935c9fab8729dda2b0983dbb Mon Sep 17 00:00:00 2001 From: davilla Date: Fri, 11 Jan 2013 17:25:41 -0500 Subject: [PATCH 112/180] [droid] bump librtmp from 2.3 to 2.4 --- tools/android/depends/librtmp/Makefile | 29 +- .../librtmp/librtmp-60-second-fix.patch | 1913 +++++++++++++++++ 2 files changed, 1934 insertions(+), 8 deletions(-) create mode 100644 tools/android/depends/librtmp/librtmp-60-second-fix.patch diff --git a/tools/android/depends/librtmp/Makefile b/tools/android/depends/librtmp/Makefile index 02a8ea2e3a1b3..2537929afef26 100644 --- a/tools/android/depends/librtmp/Makefile +++ b/tools/android/depends/librtmp/Makefile @@ -3,9 +3,13 @@ DEPS= ../Makefile.include Makefile prefix.patch # lib name, version LIBNAME=rtmpdump -VERSION=2.3 +VERSION=e0056c51cc1710c9a44d2a2c4e2f344fa9cabcf4 +GIT_DIR=$(TARBALLS_LOCATION)/$(LIBNAME).git +BASE_URL=git://git.ffmpeg.org/$(LIBNAME).git SOURCE=$(LIBNAME)-$(VERSION) -ARCHIVE=$(SOURCE).tgz +#tell git to use the addons repo rather than xbmc's repo +export GIT_DIR +export GIT_WORK_TREE=$(PLATFORM) # configuration settings @@ -15,16 +19,25 @@ CLEAN_FILES=$(ARCHIVE) $(PLATFORM) all: .installed-$(PLATFORM) -$(TARBALLS_LOCATION)/$(ARCHIVE): - $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) +$(GIT_DIR)/HEAD: + cd $(TARBALLS_LOCATION); git clone --bare $(BASE_URL) -$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS) - rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM) - $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) +$(GIT_DIR)/current/$(VERSION): $(GIT_DIR)/HEAD $(DEPS) + git rev-list -1 $(VERSION) >/dev/null || git fetch origin "+refs/heads/*:refs/remotes/origin/*" + git rev-list -1 $(VERSION) >/dev/null + rm -rf $(GIT_DIR)/current; mkdir -p $(GIT_DIR)/current + touch $@ + +$(PLATFORM)/bootstrap: $(GIT_DIR)/current/$(VERSION) + rm -rf $(PLATFORM); mkdir -p $(PLATFORM) + git checkout $(VERSION) -- . + +$(PLATFORM): $(PLATFORM)/bootstrap + cd $(PLATFORM); patch -p1 < ../librtmp-60-second-fix.patch cd $(PLATFORM); patch -p0 < ../prefix.patch $(LIBDYLIB): $(PLATFORM) - $(MAKE) -C $(PLATFORM)/librtmp CROSS_COMPILE=$(CROSSTOOLS) PREFIX=$(PREFIX) + $(MAKE) -C $(PLATFORM)/librtmp CROSS_COMPILE=$(CROSSTOOLS) PREFIX=$(PREFIX) XCFLAGS="$(CFLAGS)" XLDFLAGS="$(LDFLAGS) -lm" .installed-$(PLATFORM): $(LIBDYLIB) $(MAKE) -C $(PLATFORM)/librtmp install PREFIX=$(PREFIX) diff --git a/tools/android/depends/librtmp/librtmp-60-second-fix.patch b/tools/android/depends/librtmp/librtmp-60-second-fix.patch new file mode 100644 index 0000000000000..2914fc1b8eb20 --- /dev/null +++ b/tools/android/depends/librtmp/librtmp-60-second-fix.patch @@ -0,0 +1,1913 @@ +diff --git a/librtmp/amf.c b/librtmp/amf.c +index ce84f81..a25bc04 100644 +--- a/librtmp/amf.c ++++ b/librtmp/amf.c +@@ -610,6 +610,9 @@ AMFProp_Decode(AMFObjectProperty *prop, const char *pBuffer, int nSize, + return -1; + } + ++ if (*pBuffer == AMF_NULL) ++ bDecodeName = 0; ++ + if (bDecodeName && nSize < 4) + { /* at least name (length + at least 1 byte) and 1 byte of data */ + RTMP_Log(RTMP_LOGDEBUG, +@@ -801,8 +804,8 @@ AMFProp_Dump(AMFObjectProperty *prop) + } + else + { +- name.av_val = "no-name."; +- name.av_len = sizeof("no-name.") - 1; ++ name.av_val = "no-name"; ++ name.av_len = sizeof("no-name") - 1; + } + if (name.av_len > 18) + name.av_len = 18; +diff --git a/librtmp/dh.h b/librtmp/dh.h +index 9959532..e29587b 100644 +--- a/librtmp/dh.h ++++ b/librtmp/dh.h +@@ -61,7 +61,7 @@ static int MDH_generate_key(MDH *dh) + MP_set(&dh->ctx.P, dh->p); + MP_set(&dh->ctx.G, dh->g); + dh->ctx.len = 128; +- dhm_make_public(&dh->ctx, 1024, out, 1, havege_rand, &RTMP_TLS_ctx->hs); ++ dhm_make_public(&dh->ctx, 1024, out, 1, havege_random, &RTMP_TLS_ctx->hs); + MP_new(dh->pub_key); + MP_new(dh->priv_key); + MP_set(dh->pub_key, &dh->ctx.GX); +diff --git a/librtmp/handshake.h b/librtmp/handshake.h +index 0438486..102ba82 100644 +--- a/librtmp/handshake.h ++++ b/librtmp/handshake.h +@@ -965,8 +965,18 @@ HandShake(RTMP * r, int FP9HandShake) + __FUNCTION__); + RTMP_LogHex(RTMP_LOGDEBUG, reply, RTMP_SIG_SIZE); + #endif +- if (!WriteN(r, (char *)reply, RTMP_SIG_SIZE)) +- return FALSE; ++ if (r->Link.CombineConnectPacket) ++ { ++ char *HandshakeResponse = malloc(RTMP_SIG_SIZE); ++ memcpy(HandshakeResponse, (char *) reply, RTMP_SIG_SIZE); ++ r->Link.HandshakeResponse.av_val = HandshakeResponse; ++ r->Link.HandshakeResponse.av_len = RTMP_SIG_SIZE; ++ } ++ else ++ { ++ if (!WriteN(r, (char *) reply, RTMP_SIG_SIZE)) ++ return FALSE; ++ } + + /* 2nd part of handshake */ + if (ReadN(r, (char *)serversig, RTMP_SIG_SIZE) != RTMP_SIG_SIZE) +diff --git a/librtmp/hashswf.c b/librtmp/hashswf.c +index 9f4e2c0..eeed34c 100644 +--- a/librtmp/hashswf.c ++++ b/librtmp/hashswf.c +@@ -70,7 +70,7 @@ extern TLS_CTX RTMP_TLS_ctx; + + #endif /* CRYPTO */ + +-#define AGENT "Mozilla/5.0" ++#define AGENT "Mozilla/5.0 (Windows NT 5.1; rv:8.0) Gecko/20100101 Firefox/8.0" + + HTTPResult + HTTP_get(struct HTTP_ctx *http, const char *url, HTTP_read_callback *cb) +@@ -528,7 +528,7 @@ RTMP_HashSWF(const char *url, unsigned int *size, unsigned char *hash, + + if (strncmp(buf, "url: ", 5)) + continue; +- if (strncmp(buf + 5, url, hlen)) ++ if (strncmp(buf + 5, url, strlen(buf + 5) - 1)) + continue; + r1 = strrchr(buf, '/'); + i = strlen(r1); +diff --git a/librtmp/log.c b/librtmp/log.c +index 0012985..856e3e4 100644 +--- a/librtmp/log.c ++++ b/librtmp/log.c +@@ -52,8 +52,8 @@ static void rtmp_log_default(int level, const char *format, va_list vl) + vsnprintf(str, MAX_PRINT_LEN-1, format, vl); + + /* Filter out 'no-name' */ +- if ( RTMP_debuglevel + #include + #include ++#include + + #include "rtmp_sys.h" + #include "log.h" +@@ -45,6 +46,7 @@ TLS_CTX RTMP_TLS_ctx; + + #define RTMP_SIG_SIZE 1536 + #define RTMP_LARGE_HEADER_SIZE 12 ++#define HEX2BIN(a) (((a)&0x40)?((a)&0xf)+9:((a)&0xf)) + + static const int packetSize[] = { 12, 8, 4, 1 }; + +@@ -97,6 +99,9 @@ static int SendFCSubscribe(RTMP *r, AVal *subscribepath); + static int SendPlay(RTMP *r); + static int SendBytesReceived(RTMP *r); + static int SendUsherToken(RTMP *r, AVal *usherToken); ++static int SendInvoke(RTMP *r, AVal *Command, int queue); ++static int SendGetStreamLength(RTMP *r); ++static int strsplit(char *src, int srclen, char delim, char ***params); + + #if 0 /* unused */ + static int SendBGHasStream(RTMP *r, double dId, AVal *playpath); +@@ -259,6 +264,8 @@ RTMP_Init(RTMP *r) + r->m_fVideoCodecs = 252.0; + r->Link.timeout = 30; + r->Link.swfAge = 30; ++ r->Link.CombineConnectPacket = TRUE; ++ r->Link.ConnectPacket = FALSE; + } + + void +@@ -337,6 +344,7 @@ RTMP_SetupStream(RTMP *r, + AVal *flashVer, + AVal *subscribepath, + AVal *usherToken, ++ AVal *WeebToken, + int dStart, + int dStop, int bLiveStream, long int timeout) + { +@@ -359,6 +367,8 @@ RTMP_SetupStream(RTMP *r, + RTMP_Log(RTMP_LOGDEBUG, "subscribepath : %s", subscribepath->av_val); + if (usherToken && usherToken->av_val) + RTMP_Log(RTMP_LOGDEBUG, "NetStream.Authenticate.UsherToken : %s", usherToken->av_val); ++ if (WeebToken && WeebToken->av_val) ++ RTMP_Log(RTMP_LOGDEBUG, "WeebToken: %s", WeebToken->av_val); + if (flashVer && flashVer->av_val) + RTMP_Log(RTMP_LOGDEBUG, "flashVer : %s", flashVer->av_val); + if (dStart > 0) +@@ -426,6 +436,8 @@ RTMP_SetupStream(RTMP *r, + r->Link.subscribepath = *subscribepath; + if (usherToken && usherToken->av_len) + r->Link.usherToken = *usherToken; ++ if (WeebToken && WeebToken->av_len) ++ r->Link.WeebToken = *WeebToken; + r->Link.seekTime = dStart; + r->Link.stopTime = dStop; + if (bLiveStream) +@@ -483,14 +495,22 @@ static struct urlopt { + "Stream is live, no seeking possible" }, + { AVC("subscribe"), OFF(Link.subscribepath), OPT_STR, 0, + "Stream to subscribe to" }, +- { AVC("jtv"), OFF(Link.usherToken), OPT_STR, 0, +- "Justin.tv authentication token" }, +- { AVC("token"), OFF(Link.token), OPT_STR, 0, ++ { AVC("jtv"), OFF(Link.usherToken), OPT_STR, 0, ++ "Justin.tv authentication token"}, ++ { AVC("weeb"), OFF(Link.WeebToken), OPT_STR, 0, ++ "Weeb.tv authentication token"}, ++ { AVC("token"), OFF(Link.token), OPT_STR, 0, + "Key for SecureToken response" }, + { AVC("swfVfy"), OFF(Link.lFlags), OPT_BOOL, RTMP_LF_SWFV, + "Perform SWF Verification" }, + { AVC("swfAge"), OFF(Link.swfAge), OPT_INT, 0, + "Number of days to use cached SWF hash" }, ++#ifdef CRYPTO ++ { AVC("swfsize"), OFF(Link.swfSize), OPT_INT, 0, ++ "Size of the decompressed SWF file"}, ++ { AVC("swfhash"), OFF(Link.swfHash), OPT_STR, 0, ++ "SHA256 hash of the decompressed SWF file"}, ++#endif + { AVC("start"), OFF(Link.seekTime), OPT_INT, 0, + "Stream start position in milliseconds" }, + { AVC("stop"), OFF(Link.stopTime), OPT_INT, 0, +@@ -751,9 +771,16 @@ int RTMP_SetupURL(RTMP *r, char *url) + } + + #ifdef CRYPTO +- if ((r->Link.lFlags & RTMP_LF_SWFV) && r->Link.swfUrl.av_len) +- RTMP_HashSWF(r->Link.swfUrl.av_val, &r->Link.SWFSize, +- (unsigned char *)r->Link.SWFHash, r->Link.swfAge); ++ RTMP_Log(RTMP_LOGDEBUG, "Khalsa: %d %d %s\n", r->Link.swfSize, r->Link.swfHash.av_len, r->Link.swfHash.av_val); ++ if (r->Link.swfSize && r->Link.swfHash.av_len) ++ { ++ int i, j = 0; ++ for (i = 0; i < r->Link.swfHash.av_len; i += 2) ++ r->Link.SWFHash[j++] = (HEX2BIN(r->Link.swfHash.av_val[i]) << 4) | HEX2BIN(r->Link.swfHash.av_val[i + 1]); ++ r->Link.SWFSize = (uint32_t) r->Link.swfSize; ++ } ++ else if ((r->Link.lFlags & RTMP_LF_SWFV) && r->Link.swfUrl.av_len) ++ RTMP_HashSWF(r->Link.swfUrl.av_val, &r->Link.SWFSize, (unsigned char *) r->Link.SWFHash, r->Link.swfAge); + #endif + + if (r->Link.port == 0) +@@ -854,6 +881,8 @@ RTMP_Connect0(RTMP *r, struct sockaddr * service) + } + + setsockopt(r->m_sb.sb_socket, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof(on)); ++ if (r->Link.protocol & RTMP_FEATURE_HTTP) ++ setsockopt(r->m_sb.sb_socket, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, sizeof (on)); + + return TRUE; + } +@@ -1308,8 +1337,24 @@ ReadN(RTMP *r, char *buffer, int n) + return 0; + } + } +- if (r->m_resplen && !r->m_sb.sb_size) +- RTMPSockBuf_Fill(&r->m_sb); ++ ++ // Try to fill the whole buffer. previous buffer needs to be consumed ++ // completely before receiving new data. ++ if (r->m_resplen && (r->m_sb.sb_size <= 0)) ++ { ++ do ++ { ++ nBytes = RTMPSockBuf_Fill(&r->m_sb); ++ if (nBytes == -1) ++ { ++ if (!r->m_sb.sb_timedout) ++ RTMP_Close(r); ++ return 0; ++ } ++ } ++ while (r->m_resplen && (r->m_sb.sb_size < r->m_resplen) && (nBytes > 0)); ++ } ++ + avail = r->m_sb.sb_size; + if (avail > r->m_resplen) + avail = r->m_resplen; +@@ -1336,10 +1381,9 @@ ReadN(RTMP *r, char *buffer, int n) + r->m_sb.sb_size -= nRead; + nBytes = nRead; + r->m_nBytesIn += nRead; +- if (r->m_bSendCounter +- && r->m_nBytesIn > ( r->m_nBytesInSent + r->m_nClientBW / 10)) +- if (!SendBytesReceived(r)) +- return FALSE; ++ if (r->m_bSendCounter && r->m_nBytesIn > (r->m_nBytesInSent + r->m_nClientBW / 10)) ++ if (!SendBytesReceived(r)) ++ return FALSE; + } + /*RTMP_Log(RTMP_LOGDEBUG, "%s: %d bytes\n", __FUNCTION__, nBytes); */ + #ifdef _DEBUG +@@ -1390,6 +1434,16 @@ WriteN(RTMP *r, const char *buffer, int n) + } + #endif + ++ if (r->Link.ConnectPacket) ++ { ++ char *ConnectPacket = malloc(r->Link.HandshakeResponse.av_len + n); ++ memcpy(ConnectPacket, r->Link.HandshakeResponse.av_val, r->Link.HandshakeResponse.av_len); ++ memcpy(ConnectPacket + r->Link.HandshakeResponse.av_len, ptr, n); ++ ptr = ConnectPacket; ++ n += r->Link.HandshakeResponse.av_len; ++ r->Link.ConnectPacket = FALSE; ++ } ++ + while (n > 0) + { + int nBytes; +@@ -1455,6 +1509,9 @@ SendConnectPacket(RTMP *r, RTMPPacket *cp) + char pbuf[4096], *pend = pbuf + sizeof(pbuf); + char *enc; + ++ if (r->Link.CombineConnectPacket) ++ r->Link.ConnectPacket = TRUE; ++ + if (cp) + return RTMP_SendPacket(r, cp, TRUE); + +@@ -1667,7 +1724,7 @@ SendUsherToken(RTMP *r, AVal *usherToken) + packet.m_hasAbsTimestamp = 0; + packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; + +- RTMP_Log(RTMP_LOGDEBUG, "UsherToken: %s", usherToken->av_val); ++ RTMP_Log(RTMP_LOGDEBUG, "UsherToken: %.*s", usherToken->av_len, usherToken->av_val); + enc = packet.m_body; + enc = AMF_EncodeString(enc, pend, &av_NetStream_Authenticate_UsherToken); + enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes); +@@ -2096,10 +2153,8 @@ SendPlay(RTMP *r) + enc = AMF_EncodeNumber(enc, pend, -1000.0); + else + { +- if (r->Link.seekTime > 0.0) +- enc = AMF_EncodeNumber(enc, pend, r->Link.seekTime); /* resume from here */ +- else +- enc = AMF_EncodeNumber(enc, pend, 0.0); /*-2000.0);*/ /* recorded as default, -2000.0 is not reliable since that freezes the player if the stream is not found */ ++ if (r->Link.seekTime > 0.0 || r->Link.stopTime) ++ enc = AMF_EncodeNumber(enc, pend, r->Link.seekTime); /* resume from here */ + } + if (!enc) + return FALSE; +@@ -2215,7 +2270,7 @@ RTMP_SendCtrl(RTMP *r, short nType, unsigned int nObject, unsigned int nTime) + int nSize; + char *buf; + +- RTMP_Log(RTMP_LOGDEBUG, "sending ctrl. type: 0x%04x", (unsigned short)nType); ++ RTMP_Log(RTMP_LOGDEBUG, "sending ctrl, type: 0x%04x", (unsigned short)nType); + + packet.m_nChannel = 0x02; /* control channel (ping) */ + packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM; +@@ -2247,8 +2302,8 @@ RTMP_SendCtrl(RTMP *r, short nType, unsigned int nObject, unsigned int nTime) + } + else if (nType == 0x1A) + { +- *buf = nObject & 0xff; +- } ++ *buf = nObject & 0xff; ++ } + else + { + if (nSize > 2) +@@ -2305,6 +2360,7 @@ AV_clear(RTMP_METHOD *vals, int num) + free(vals); + } + ++SAVC(onBWCheck); + SAVC(onBWDone); + SAVC(onFCSubscribe); + SAVC(onFCUnsubscribe); +@@ -2314,24 +2370,26 @@ SAVC(_error); + SAVC(close); + SAVC(code); + SAVC(level); ++SAVC(description); + SAVC(onStatus); + SAVC(playlist_ready); + static const AVal av_NetStream_Failed = AVC("NetStream.Failed"); + static const AVal av_NetStream_Play_Failed = AVC("NetStream.Play.Failed"); +-static const AVal av_NetStream_Play_StreamNotFound = +-AVC("NetStream.Play.StreamNotFound"); +-static const AVal av_NetConnection_Connect_InvalidApp = +-AVC("NetConnection.Connect.InvalidApp"); ++static const AVal av_NetStream_Play_StreamNotFound = AVC("NetStream.Play.StreamNotFound"); ++static const AVal av_NetConnection_Connect_InvalidApp = AVC("NetConnection.Connect.InvalidApp"); + static const AVal av_NetStream_Play_Start = AVC("NetStream.Play.Start"); + static const AVal av_NetStream_Play_Complete = AVC("NetStream.Play.Complete"); + static const AVal av_NetStream_Play_Stop = AVC("NetStream.Play.Stop"); + static const AVal av_NetStream_Seek_Notify = AVC("NetStream.Seek.Notify"); + static const AVal av_NetStream_Pause_Notify = AVC("NetStream.Pause.Notify"); +-static const AVal av_NetStream_Play_PublishNotify = +-AVC("NetStream.Play.PublishNotify"); +-static const AVal av_NetStream_Play_UnpublishNotify = +-AVC("NetStream.Play.UnpublishNotify"); ++static const AVal av_NetStream_Play_PublishNotify = AVC("NetStream.Play.PublishNotify"); ++static const AVal av_NetStream_Play_UnpublishNotify = AVC("NetStream.Play.UnpublishNotify"); + static const AVal av_NetStream_Publish_Start = AVC("NetStream.Publish.Start"); ++static const AVal av_NetConnection_confStream = AVC("NetConnection.confStream"); ++static const AVal av_verifyClient = AVC("verifyClient"); ++static const AVal av_sendStatus = AVC("sendStatus"); ++static const AVal av_getStreamLength = AVC("getStreamLength"); ++static const AVal av_ReceiveCheckPublicStatus = AVC("ReceiveCheckPublicStatus"); + + /* Returns 0 for OK/Failed/error, 1 for 'Stop or Complete' */ + static int +@@ -2341,6 +2399,11 @@ HandleInvoke(RTMP *r, const char *body, unsigned int nBodySize) + AVal method; + double txn; + int ret = 0, nRes; ++ char pbuf[256], *pend = pbuf + sizeof (pbuf), *enc, **params = NULL; ++ char *host = r->Link.hostname.av_len ? r->Link.hostname.av_val : ""; ++ char *pageUrl = r->Link.pageUrl.av_len ? r->Link.pageUrl.av_val : ""; ++ int param_count; ++ AVal av_Command, av_Response; + if (body[0] != 0x02) /* make sure it is a string method name we start with */ + { + RTMP_Log(RTMP_LOGWARNING, "%s, Sanity failed. no string method in invoke packet", +@@ -2402,23 +2465,137 @@ HandleInvoke(RTMP *r, const char *body, unsigned int nBodySize) + RTMP_SendServerBW(r); + RTMP_SendCtrl(r, 3, 0, 300); + } +- RTMP_SendCreateStream(r); +- +- if (!(r->Link.protocol & RTMP_FEATURE_WRITE)) +- { +- /* Authenticate on Justin.tv legacy servers before sending FCSubscribe */ +- if (r->Link.usherToken.av_len) +- SendUsherToken(r, &r->Link.usherToken); +- /* Send the FCSubscribe if live stream or if subscribepath is set */ +- if (r->Link.subscribepath.av_len) +- SendFCSubscribe(r, &r->Link.subscribepath); +- else if (r->Link.lFlags & RTMP_LF_LIVE) +- SendFCSubscribe(r, &r->Link.playpath); +- } +- } ++ if (strstr(host, "tv-stream.to") || strstr(pageUrl, "tv-stream.to")) ++ { ++ static char auth[] = {'h', 0xC2, 0xA7, '4', 'j', 'h', 'H', '4', '3', 'd'}; ++ AVal av_auth; ++ SAVC(requestAccess); ++ av_auth.av_val = auth; ++ av_auth.av_len = sizeof (auth); ++ ++ enc = pbuf; ++ enc = AMF_EncodeString(enc, pend, &av_requestAccess); ++ enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes); ++ *enc++ = AMF_NULL; ++ enc = AMF_EncodeString(enc, pend, &av_auth); ++ av_Command.av_val = pbuf; ++ av_Command.av_len = enc - pbuf; ++ SendInvoke(r, &av_Command, FALSE); ++ ++ SAVC(getConnectionCount); ++ enc = pbuf; ++ enc = AMF_EncodeString(enc, pend, &av_getConnectionCount); ++ enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes); ++ *enc++ = AMF_NULL; ++ av_Command.av_val = pbuf; ++ av_Command.av_len = enc - pbuf; ++ SendInvoke(r, &av_Command, FALSE); ++ ++ SendGetStreamLength(r); ++ } ++ else if (strstr(host, "jampo.com.ua") || strstr(pageUrl, "jampo.com.ua")) ++ { ++ SendGetStreamLength(r); ++ } ++ else if (strstr(host, "streamscene.cc") || strstr(pageUrl, "streamscene.cc") ++ || strstr(host, "tsboard.tv") || strstr(pageUrl, "teamstream.in")) ++ { ++ SAVC(r); ++ enc = pbuf; ++ enc = AMF_EncodeString(enc, pend, &av_r); ++ enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes); ++ *enc++ = AMF_NULL; ++ av_Command.av_val = pbuf; ++ av_Command.av_len = enc - pbuf; ++ SendInvoke(r, &av_Command, FALSE); ++ ++ SendGetStreamLength(r); ++ } ++ else if (strstr(host, "chaturbate.com") || strstr(pageUrl, "chaturbate.com")) ++ { ++ AVal av_ModelName; ++ SAVC(CheckPublicStatus); ++ ++ if (strlen(pageUrl) > 7) ++ { ++ strsplit(pageUrl + 7, FALSE, '/', ¶ms); ++ av_ModelName.av_val = params[1]; ++ av_ModelName.av_len = strlen(params[1]); ++ ++ enc = pbuf; ++ enc = AMF_EncodeString(enc, pend, &av_CheckPublicStatus); ++ enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes); ++ *enc++ = AMF_NULL; ++ enc = AMF_EncodeString(enc, pend, &av_ModelName); ++ av_Command.av_val = pbuf; ++ av_Command.av_len = enc - pbuf; ++ ++ SendInvoke(r, &av_Command, FALSE); ++ } ++ else ++ { ++ RTMP_Log(RTMP_LOGERROR, "you must specify the pageUrl"); ++ RTMP_Close(r); ++ } ++ } ++ /* Weeb.tv specific authentication */ ++ else if (r->Link.WeebToken.av_len) ++ { ++ AVal av_Token, av_Username, av_Password; ++ SAVC(determineAccess); ++ ++ param_count = strsplit(r->Link.WeebToken.av_val, FALSE, ';', ¶ms); ++ if (param_count >= 1) ++ { ++ av_Token.av_val = params[0]; ++ av_Token.av_len = strlen(params[0]); ++ } ++ if (param_count >= 2) ++ { ++ av_Username.av_val = params[1]; ++ av_Username.av_len = strlen(params[1]); ++ } ++ if (param_count >= 3) ++ { ++ av_Password.av_val = params[2]; ++ av_Password.av_len = strlen(params[2]); ++ } ++ ++ enc = pbuf; ++ enc = AMF_EncodeString(enc, pend, &av_determineAccess); ++ enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes); ++ *enc++ = AMF_NULL; ++ enc = AMF_EncodeString(enc, pend, &av_Token); ++ enc = AMF_EncodeString(enc, pend, &av_Username); ++ enc = AMF_EncodeString(enc, pend, &av_Password); ++ av_Command.av_val = pbuf; ++ av_Command.av_len = enc - pbuf; ++ ++ RTMP_Log(RTMP_LOGDEBUG, "WeebToken: %s", r->Link.WeebToken.av_val); ++ SendInvoke(r, &av_Command, FALSE); ++ } ++ else ++ RTMP_SendCreateStream(r); ++ } ++ else if (AVMATCH(&methodInvoked, &av_getStreamLength)) ++ { ++ RTMP_SendCreateStream(r); ++ } + else if (AVMATCH(&methodInvoked, &av_createStream)) +- { +- r->m_stream_id = (int)AMFProp_GetNumber(AMF_GetProp(&obj, NULL, 3)); ++ { ++ r->m_stream_id = (int) AMFProp_GetNumber(AMF_GetProp(&obj, NULL, 3)); ++ ++ if (!(r->Link.protocol & RTMP_FEATURE_WRITE)) ++ { ++ /* Authenticate on Justin.tv legacy servers before sending FCSubscribe */ ++ if (r->Link.usherToken.av_len) ++ SendUsherToken(r, &r->Link.usherToken); ++ /* Send the FCSubscribe if live stream or if subscribepath is set */ ++ if (r->Link.subscribepath.av_len) ++ SendFCSubscribe(r, &r->Link.subscribepath); ++ else if ((r->Link.lFlags & RTMP_LF_LIVE) && (!r->Link.WeebToken.av_len)) ++ SendFCSubscribe(r, &r->Link.playpath); ++ } + + if (r->Link.protocol & RTMP_FEATURE_WRITE) + { +@@ -2441,7 +2618,7 @@ HandleInvoke(RTMP *r, const char *body, unsigned int nBodySize) + } + else if (AVMATCH(&method, &av_onBWDone)) + { +- if (!r->m_nBWCheckCounter) ++ if (!r->m_nBWCheckCounter) + SendCheckBW(r); + } + else if (AVMATCH(&method, &av_onFCSubscribe)) +@@ -2457,7 +2634,7 @@ HandleInvoke(RTMP *r, const char *body, unsigned int nBodySize) + { + SendPong(r, txn); + } +- else if (AVMATCH(&method, &av__onbwcheck)) ++ else if (AVMATCH(&method, &av__onbwcheck) || AVMATCH(&method, &av_onBWCheck)) + { + SendCheckBWResult(r, txn); + } +@@ -2473,20 +2650,63 @@ HandleInvoke(RTMP *r, const char *body, unsigned int nBodySize) + } + else if (AVMATCH(&method, &av__error)) + { +- RTMP_Log(RTMP_LOGERROR, "rtmp server sent error"); ++ double code = 0; ++ unsigned int parsedPort; ++ AMFObject obj2; ++ AMFObjectProperty p; ++ AVal redirect; ++ SAVC(ex); ++ SAVC(redirect); ++ ++ AMFProp_GetObject(AMF_GetProp(&obj, NULL, 3), &obj2); ++ if (RTMP_FindFirstMatchingProperty(&obj2, &av_ex, &p)) ++ { ++ AMFProp_GetObject(&p, &obj2); ++ if (RTMP_FindFirstMatchingProperty(&obj2, &av_code, &p)) ++ code = AMFProp_GetNumber(&p); ++ if (code == 302 && RTMP_FindFirstMatchingProperty(&obj2, &av_redirect, &p)) ++ { ++ AMFProp_GetString(&p, &redirect); ++ r->Link.redirected = TRUE; ++ ++ char *url = malloc(redirect.av_len + sizeof ("/playpath")); ++ strncpy(url, redirect.av_val, redirect.av_len); ++ url[redirect.av_len] = '\0'; ++ r->Link.tcUrl.av_val = url; ++ r->Link.tcUrl.av_len = redirect.av_len; ++ strcat(url, "/playpath"); ++ RTMP_ParseURL(url, &r->Link.protocol, &r->Link.hostname, &parsedPort, &r->Link.playpath0, &r->Link.app); ++ r->Link.port = parsedPort; ++ } ++ } ++ if (r->Link.redirected) ++ RTMP_Log(RTMP_LOGINFO, "rtmp server sent redirect"); ++ else ++ RTMP_Log(RTMP_LOGERROR, "rtmp server sent error"); + } + else if (AVMATCH(&method, &av_close)) + { +- RTMP_Log(RTMP_LOGERROR, "rtmp server requested close"); +- RTMP_Close(r); ++ if (r->Link.redirected) ++ { ++ RTMP_Log(RTMP_LOGINFO, "trying to connect with redirected url"); ++ RTMP_Close(r); ++ r->Link.redirected = FALSE; ++ RTMP_Connect(r, NULL); ++ } ++ else ++ { ++ RTMP_Log(RTMP_LOGERROR, "rtmp server requested close"); ++ RTMP_Close(r); ++ } + } + else if (AVMATCH(&method, &av_onStatus)) + { + AMFObject obj2; +- AVal code, level; ++ AVal code, level, description; + AMFProp_GetObject(AMF_GetProp(&obj, NULL, 3), &obj2); + AMFProp_GetString(AMF_GetProp(&obj2, &av_code, -1), &code); + AMFProp_GetString(AMF_GetProp(&obj2, &av_level, -1), &level); ++ AMFProp_GetString(AMF_GetProp(&obj2, &av_description, -1), &description); + + RTMP_Log(RTMP_LOGDEBUG, "%s, onStatus: %s", __FUNCTION__, code.av_val); + if (AVMATCH(&code, &av_NetStream_Failed) +@@ -2550,6 +2770,45 @@ HandleInvoke(RTMP *r, const char *body, unsigned int nBodySize) + r->m_pausing = 3; + } + } ++ ++ else if (AVMATCH(&code, &av_NetConnection_confStream)) ++ { ++#ifdef CRYPTO ++ static const char hexdig[] = "0123456789abcdef"; ++ SAVC(cf_stream); ++ int i; ++ char hash_hex[33] = {0}; ++ unsigned char hash[16]; ++ AVal auth; ++ param_count = strsplit(description.av_val, description.av_len, ':', ¶ms); ++ if (param_count >= 3) ++ { ++ char *buf = malloc(strlen(params[0]) + r->Link.playpath.av_len + 1); ++ strcpy(buf, params[0]); ++ strncat(buf, r->Link.playpath.av_val, r->Link.playpath.av_len); ++ md5_hash((unsigned char *) buf, strlen(buf), hash); ++ for (i = 0; i < 16; i++) ++ { ++ hash_hex[i * 2] = hexdig[0x0f & (hash[i] >> 4)]; ++ hash_hex[i * 2 + 1] = hexdig[0x0f & (hash[i])]; ++ } ++ auth.av_val = &hash_hex[atoi(params[1]) - 1]; ++ auth.av_len = atoi(params[2]); ++ RTMP_Log(RTMP_LOGDEBUG, "Khalsa: %.*s", auth.av_len, auth.av_val); ++ ++ enc = pbuf; ++ enc = AMF_EncodeString(enc, pend, &av_cf_stream); ++ enc = AMF_EncodeNumber(enc, pend, txn); ++ *enc++ = AMF_NULL; ++ enc = AMF_EncodeString(enc, pend, &auth); ++ av_Command.av_val = pbuf; ++ av_Command.av_len = enc - pbuf; ++ ++ SendInvoke(r, &av_Command, FALSE); ++ free(buf); ++ } ++#endif ++ } + } + else if (AVMATCH(&method, &av_playlist_ready)) + { +@@ -2563,6 +2822,74 @@ HandleInvoke(RTMP *r, const char *body, unsigned int nBodySize) + } + } + } ++ else if (AVMATCH(&method, &av_verifyClient)) ++ { ++ double VerificationNumber = AMFProp_GetNumber(AMF_GetProp(&obj, NULL, 3)); ++ RTMP_Log(RTMP_LOGDEBUG, "VerificationNumber: %.2f", VerificationNumber); ++ ++ enc = pbuf; ++ enc = AMF_EncodeString(enc, pend, &av__result); ++ enc = AMF_EncodeNumber(enc, pend, txn); ++ *enc++ = AMF_NULL; ++ enc = AMF_EncodeNumber(enc, pend, exp(atan(sqrt(VerificationNumber))) + 1); ++ av_Response.av_val = pbuf; ++ av_Response.av_len = enc - pbuf; ++ ++ AMF_Decode(&obj, av_Response.av_val, av_Response.av_len, FALSE); ++ AMF_Dump(&obj); ++ SendInvoke(r, &av_Response, FALSE); ++ } ++ else if (AVMATCH(&method, &av_sendStatus)) ++ { ++ if (r->Link.WeebToken.av_len) ++ { ++ AVal av_Authorized = AVC("User.hasAccess"); ++ AVal av_TransferLimit = AVC("User.noPremium.limited"); ++ AVal av_UserLimit = AVC("User.noPremium.tooManyUsers"); ++ AVal av_TimeLeft = AVC("timeLeft"); ++ AVal av_Status, av_ReconnectionTime; ++ ++ AMFObject Status; ++ AMFProp_GetObject(AMF_GetProp(&obj, NULL, 3), &Status); ++ AMFProp_GetString(AMF_GetProp(&Status, &av_code, -1), &av_Status); ++ RTMP_Log(RTMP_LOGINFO, "%.*s", av_Status.av_len, av_Status.av_val); ++ if (AVMATCH(&av_Status, &av_Authorized)) ++ { ++ RTMP_Log(RTMP_LOGINFO, "Weeb.tv authentication successful"); ++ RTMP_SendCreateStream(r); ++ } ++ else if (AVMATCH(&av_Status, &av_UserLimit)) ++ { ++ RTMP_Log(RTMP_LOGINFO, "No free slots available"); ++ RTMP_Close(r); ++ } ++ else if (AVMATCH(&av_Status, &av_TransferLimit)) ++ { ++ AMFProp_GetString(AMF_GetProp(&Status, &av_TimeLeft, -1), &av_ReconnectionTime); ++ RTMP_Log(RTMP_LOGINFO, "Viewing limit exceeded. try again in %.*s minutes.", av_ReconnectionTime.av_len, av_ReconnectionTime.av_val); ++ RTMP_Close(r); ++ } ++ } ++ } ++ else if (AVMATCH(&method, &av_ReceiveCheckPublicStatus)) ++ { ++ AVal Status; ++ AMFProp_GetString(AMF_GetProp(&obj, NULL, 3), &Status); ++ strsplit(Status.av_val, Status.av_len, ',', ¶ms); ++ if (strcmp(params[0], "0") == 0) ++ { ++ RTMP_Log(RTMP_LOGINFO, "Model status is %s", params[1]); ++ RTMP_Close(r); ++ } ++ else ++ { ++ AVal Playpath; ++ Playpath.av_val = params[1]; ++ Playpath.av_len = strlen(params[1]); ++ RTMP_ParsePlaypath(&Playpath, &r->Link.playpath); ++ RTMP_SendCreateStream(r); ++ } ++ } + else + { + +@@ -2748,7 +3075,7 @@ HandleCtrl(RTMP *r, const RTMPPacket *packet) + unsigned int tmp; + if (packet->m_body && packet->m_nBodySize >= 2) + nType = AMF_DecodeInt16(packet->m_body); +- RTMP_Log(RTMP_LOGDEBUG, "%s, received ctrl. type: %d, len: %d", __FUNCTION__, nType, ++ RTMP_Log(RTMP_LOGDEBUG, "%s, received ctrl, type: %d, len: %d", __FUNCTION__, nType, + packet->m_nBodySize); + /*RTMP_LogHex(packet.m_body, packet.m_nBodySize); */ + +@@ -2856,15 +3183,15 @@ HandleCtrl(RTMP *r, const RTMPPacket *packet) + RTMP_Log(RTMP_LOGDEBUG, "%s, SWFVerification ping received: ", __FUNCTION__); + if (packet->m_nBodySize > 2 && packet->m_body[2] > 0x01) + { +- RTMP_Log(RTMP_LOGERROR, +- "%s: SWFVerification Type %d request not supported! Patches welcome...", +- __FUNCTION__, packet->m_body[2]); ++ RTMP_Log(RTMP_LOGERROR, ++ "%s: SWFVerification Type %d request not supported, attempting to use SWFVerification Type 1! Patches welcome...", ++ __FUNCTION__, packet->m_body[2]); + } + #ifdef CRYPTO + /*RTMP_LogHex(packet.m_body, packet.m_nBodySize); */ + + /* respond with HMAC SHA256 of decompressed SWF, key is the 30byte player key, also the last 30 bytes of the server handshake are applied */ +- else if (r->Link.SWFSize) ++ if (r->Link.SWFSize) + { + RTMP_SendCtrl(r, 0x1B, 0, 0); + } +@@ -3142,8 +3469,18 @@ HandShake(RTMP *r, int FP9HandShake) + serversig[4], serversig[5], serversig[6], serversig[7]); + + /* 2nd part of handshake */ +- if (!WriteN(r, serversig, RTMP_SIG_SIZE)) +- return FALSE; ++ if (r->Link.CombineConnectPacket) ++ { ++ char *HandshakeResponse = malloc(RTMP_SIG_SIZE); ++ memcpy(HandshakeResponse, (char *) serversig, RTMP_SIG_SIZE); ++ r->Link.HandshakeResponse.av_val = HandshakeResponse; ++ r->Link.HandshakeResponse.av_len = RTMP_SIG_SIZE; ++ } ++ else ++ { ++ if (!WriteN(r, (char *) serversig, RTMP_SIG_SIZE)) ++ return FALSE; ++ } + + if (ReadN(r, serversig, RTMP_SIG_SIZE) != RTMP_SIG_SIZE) + return FALSE; +@@ -3709,12 +4046,11 @@ HTTP_Post(RTMP *r, RTMPTCmd cmd, const char *buf, int len) + char hbuf[512]; + int hlen = snprintf(hbuf, sizeof(hbuf), "POST /%s%s/%d HTTP/1.1\r\n" + "Host: %.*s:%d\r\n" +- "Accept: */*\r\n" +- "User-Agent: Shockwave Flash\n" +- "Connection: Keep-Alive\n" ++ "User-Agent: Shockwave Flash\r\n" ++ "Connection: Keep-Alive\r\n" + "Cache-Control: no-cache\r\n" +- "Content-type: application/x-fcs\r\n" +- "Content-length: %d\r\n\r\n", RTMPT_cmds[cmd], ++ "Content-Type: application/x-fcs\r\n" ++ "Content-Length: %d\r\n\r\n", RTMPT_cmds[cmd], + r->m_clientID.av_val ? r->m_clientID.av_val : "", + r->m_msgCounter, r->Link.hostname.av_len, r->Link.hostname.av_val, + r->Link.port, len); +@@ -3749,6 +4085,14 @@ HTTP_read(RTMP *r, int fill) + if (!ptr) + return -1; + ptr += 4; ++ int resplen = r->m_sb.sb_size - (ptr - r->m_sb.sb_start); ++ if (hlen < 4096) ++ while (resplen < hlen) ++ { ++ if (RTMPSockBuf_Fill(&r->m_sb) == -1) ++ return -1; ++ resplen = r->m_sb.sb_size - (ptr - r->m_sb.sb_start); ++ } + r->m_sb.sb_size -= ptr - r->m_sb.sb_start; + r->m_sb.sb_start = ptr; + r->m_unackd--; +@@ -4301,13 +4645,21 @@ fail: + r->m_read.status = nRead; + goto fail; + } +- /* buffer overflow, fix buffer and give up */ +- if (r->m_read.buf < mybuf || r->m_read.buf > end) { +- mybuf = realloc(mybuf, cnt + nRead); +- memcpy(mybuf+cnt, r->m_read.buf, nRead); +- r->m_read.buf = mybuf+cnt+nRead; +- break; +- } ++ /* buffer overflow, fix buffer and give up */ ++ if (r->m_read.buf < mybuf || r->m_read.buf > end) ++ { ++ if (!cnt) ++ { ++ mybuf = realloc(mybuf, sizeof (flvHeader) + cnt + nRead); ++ memcpy(mybuf, flvHeader, sizeof (flvHeader)); ++ cnt += sizeof (flvHeader); ++ } ++ else ++ mybuf = realloc(mybuf, cnt + nRead); ++ memcpy(mybuf + cnt, r->m_read.buf, nRead); ++ r->m_read.buf = mybuf + cnt + nRead; ++ break; ++ } + cnt += nRead; + r->m_read.buf += nRead; + r->m_read.buflen -= nRead; +@@ -4458,3 +4810,90 @@ RTMP_Write(RTMP *r, const char *buf, int size) + } + return size+s2; + } ++ ++static int ++SendInvoke(RTMP *r, AVal *Command, int queue) ++{ ++ RTMPPacket packet; ++ char pbuf[512], *enc; ++ ++ packet.m_nChannel = 0x03; /* control channel (invoke) */ ++ packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM; ++ packet.m_packetType = RTMP_PACKET_TYPE_INVOKE; ++ packet.m_nTimeStamp = 0; ++ packet.m_nInfoField2 = 0; ++ packet.m_hasAbsTimestamp = 0; ++ packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; ++ ++ enc = packet.m_body; ++ if (Command->av_len) ++ { ++ memcpy(enc, Command->av_val, Command->av_len); ++ enc += Command->av_len; ++ } ++ else ++ return FALSE; ++ packet.m_nBodySize = enc - packet.m_body; ++ ++ return RTMP_SendPacket(r, &packet, queue); ++} ++ ++static int ++strsplit(char *src, int srclen, char delim, char ***params) ++{ ++ char *sptr, *srcbeg, *srcend, *dstr; ++ int count = 1, i = 0, len = 0; ++ ++ if (src == NULL) ++ return 0; ++ if (!srclen) ++ srclen = strlen(src); ++ srcbeg = src; ++ srcend = srcbeg + srclen; ++ sptr = srcbeg; ++ ++ /* count the delimiters */ ++ while (sptr < srcend) ++ { ++ if (*sptr++ == delim) ++ count++; ++ } ++ sptr = srcbeg; ++ *params = calloc(count, sizeof (size_t)); ++ char **param = *params; ++ ++ for (i = 0; i < (count - 1); i++) ++ { ++ dstr = strchr(sptr, delim); ++ len = dstr - sptr; ++ param[i] = calloc(len + 1, sizeof (char)); ++ strncpy(param[i], sptr, len); ++ sptr += len + 1; ++ } ++ ++ /* copy the last string */ ++ if (sptr <= srcend) ++ { ++ len = srclen - (sptr - srcbeg); ++ param[i] = calloc(len + 1, sizeof (char)); ++ strncpy(param[i], sptr, len); ++ } ++ return count; ++} ++ ++static int ++SendGetStreamLength(RTMP *r) ++{ ++ char pbuf[256], *pend = pbuf + sizeof (pbuf), *enc; ++ AVal av_Command; ++ ++ enc = pbuf; ++ enc = AMF_EncodeString(enc, pend, &av_getStreamLength); ++ enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes); ++ *enc++ = AMF_NULL; ++ enc = AMF_EncodeString(enc, pend, &r->Link.playpath); ++ av_Command.av_val = pbuf; ++ av_Command.av_len = enc - pbuf; ++ ++ return SendInvoke(r, &av_Command, TRUE); ++} +diff --git a/librtmp/rtmp.h b/librtmp/rtmp.h +index 6b2ae5b..411b488 100644 +--- a/librtmp/rtmp.h ++++ b/librtmp/rtmp.h +@@ -150,12 +150,14 @@ extern "C" + AVal playpath; /* passed in explicitly */ + AVal tcUrl; + AVal swfUrl; ++ AVal swfHash; + AVal pageUrl; + AVal app; + AVal auth; + AVal flashVer; + AVal subscribepath; + AVal usherToken; ++ AVal WeebToken; + AVal token; + AMFObject extras; + int edepth; +@@ -172,9 +174,15 @@ extern "C" + int lFlags; + + int swfAge; ++ int swfSize; + + int protocol; ++ int ConnectPacket; ++ int CombineConnectPacket; ++ int redirected; + int timeout; /* connection timeout in seconds */ ++ AVal Extras; ++ AVal HandshakeResponse; + + unsigned short socksport; + unsigned short port; +@@ -299,6 +307,7 @@ extern "C" + AVal *flashVer, + AVal *subscribepath, + AVal *usherToken, ++ AVal *WeebToken, + int dStart, + int dStop, int bLiveStream, long int timeout); + +diff --git a/librtmp/rtmp_sys.h b/librtmp/rtmp_sys.h +index c3fd4a6..1bfb562 100644 +--- a/librtmp/rtmp_sys.h ++++ b/librtmp/rtmp_sys.h +@@ -64,6 +64,7 @@ + #include + #include + #include ++#include + typedef struct tls_ctx { + havege_state hs; + ssl_session ssn; +@@ -71,7 +72,7 @@ typedef struct tls_ctx { + #define TLS_CTX tls_ctx * + #define TLS_client(ctx,s) s = malloc(sizeof(ssl_context)); ssl_init(s);\ + ssl_set_endpoint(s, SSL_IS_CLIENT); ssl_set_authmode(s, SSL_VERIFY_NONE);\ +- ssl_set_rng(s, havege_rand, &ctx->hs);\ ++ ssl_set_rng(s, havege_random, &ctx->hs);\ + ssl_set_ciphersuites(s, ssl_default_ciphersuites);\ + ssl_set_session(s, 1, 600, &ctx->ssn) + #define TLS_setfd(s,fd) ssl_set_bio(s, net_recv, &fd, net_send, &fd) +@@ -80,6 +81,7 @@ typedef struct tls_ctx { + #define TLS_write(s,b,l) ssl_write(s,(unsigned char *)b,l) + #define TLS_shutdown(s) ssl_close_notify(s) + #define TLS_close(s) ssl_free(s); free(s) ++#define md5_hash(i, ilen, o) md5(i, ilen, o) + + #elif defined(USE_GNUTLS) + #include +@@ -95,6 +97,8 @@ typedef struct tls_ctx { + #define TLS_write(s,b,l) gnutls_record_send(s,b,l) + #define TLS_shutdown(s) gnutls_bye(s, GNUTLS_SHUT_RDWR) + #define TLS_close(s) gnutls_deinit(s) ++#define md5_hash(i, ilen, o) gnutls_digest_algorithm_t algorithm = GNUTLS_DIG_MD5;\ ++ gnutls_hash_fast(algorithm, i, ilen, o); + + #else /* USE_OPENSSL */ + #define TLS_CTX SSL_CTX * +@@ -105,6 +109,7 @@ typedef struct tls_ctx { + #define TLS_write(s,b,l) SSL_write(s,b,l) + #define TLS_shutdown(s) SSL_shutdown(s) + #define TLS_close(s) SSL_free(s) ++#define md5_hash(i, ilen, o) MD5(i, ilen, o) + + #endif + #endif +diff --git a/rtmpdump.c b/rtmpdump.c +index e52f7d4..7bb0890 100644 +--- a/rtmpdump.c ++++ b/rtmpdump.c +@@ -701,6 +701,8 @@ void usage(char *prog) + RTMP_LogPrintf + ("--jtv|-j JSON Authentication token for Justin.tv legacy servers\n"); + RTMP_LogPrintf ++ ("--weeb|-J string Authentication token for weeb.tv servers\n"); ++ RTMP_LogPrintf + ("--hashes|-# Display progress with hashes, not with the byte counter\n"); + RTMP_LogPrintf + ("--buffer|-b Buffer time in milliseconds (default: %u)\n", +@@ -747,7 +749,8 @@ main(int argc, char **argv) + AVal hostname = { 0, 0 }; + AVal playpath = { 0, 0 }; + AVal subscribepath = { 0, 0 }; +- AVal usherToken = { 0, 0 }; //Justin.tv auth token ++ AVal usherToken = { 0, 0 }; // Justin.tv auth token ++ AVal WeebToken = { 0, 0 }; // Weeb.tv auth token + int port = -1; + int protocol = RTMP_PROTOCOL_UNDEFINED; + int retries = 0; +@@ -852,12 +855,13 @@ main(int argc, char **argv) + {"quiet", 0, NULL, 'q'}, + {"verbose", 0, NULL, 'V'}, + {"jtv", 1, NULL, 'j'}, ++ {"weeb", 1, NULL, 'J'}, + {0, 0, 0, 0} + }; + + while ((opt = + getopt_long(argc, argv, +- "hVveqzRr:s:t:p:a:b:f:o:u:C:n:c:l:y:Ym:k:d:A:B:T:w:x:W:X:S:#j:", ++ "hVveqzr:s:t:p:a:b:f:o:u:C:n:c:l:y:Ym:k:d:A:B:T:w:x:W:X:S:#j:J:", + longopts, NULL)) != -1) + { + switch (opt) +@@ -1070,6 +1074,9 @@ main(int argc, char **argv) + case 'j': + STR2AVAL(usherToken, optarg); + break; ++ case 'J': ++ STR2AVAL(WeebToken, optarg); ++ break; + default: + RTMP_LogPrintf("unknown option: %c\n", opt); + usage(argv[0]); +@@ -1161,14 +1168,14 @@ main(int argc, char **argv) + + if (tcUrl.av_len == 0) + { +- tcUrl.av_len = strlen(RTMPProtocolStringsLower[protocol]) + +- hostname.av_len + app.av_len + sizeof("://:65535/"); ++ tcUrl.av_len = strlen(RTMPProtocolStringsLower[protocol]) + ++ hostname.av_len + app.av_len + sizeof ("://:65535/"); + tcUrl.av_val = (char *) malloc(tcUrl.av_len); +- if (!tcUrl.av_val) +- return RD_FAILED; ++ if (!tcUrl.av_val) ++ return RD_FAILED; + tcUrl.av_len = snprintf(tcUrl.av_val, tcUrl.av_len, "%s://%.*s:%d/%.*s", +- RTMPProtocolStringsLower[protocol], hostname.av_len, +- hostname.av_val, port, app.av_len, app.av_val); ++ RTMPProtocolStringsLower[protocol], hostname.av_len, ++ hostname.av_val, port, app.av_len, app.av_val); + } + + int first = 1; +@@ -1187,7 +1194,7 @@ main(int argc, char **argv) + + RTMP_SetupStream(&rtmp, protocol, &hostname, port, &sockshost, &playpath, + &tcUrl, &swfUrl, &pageUrl, &app, &auth, &swfHash, swfSize, +- &flashVer, &subscribepath, &usherToken, dSeek, dStopOffset, bLiveStream, timeout); ++ &flashVer, &subscribepath, &usherToken, &WeebToken, dSeek, dStopOffset, bLiveStream, timeout); + + /* Try to keep the stream moving if it pauses on us */ + if (!bLiveStream && !bRealtimeStream && !(protocol & RTMP_FEATURE_HTTP)) +diff --git a/rtmpgw.c b/rtmpgw.c +index 0cf56bb..cd4396d 100644 +--- a/rtmpgw.c ++++ b/rtmpgw.c +@@ -95,7 +95,8 @@ typedef struct + AVal flashVer; + AVal token; + AVal subscribepath; +- AVal usherToken; //Justin.tv auth token ++ AVal usherToken; // Justin.tv auth token ++ AVal WeebToken; // Weeb.tv auth token + AVal sockshost; + AMFObject extras; + int edepth; +@@ -553,7 +554,7 @@ void processTCPrequest(STREAMING_SERVER * server, // server socket and state (ou + RTMP_Init(&rtmp); + RTMP_SetBufferMS(&rtmp, req.bufferTime); + RTMP_SetupStream(&rtmp, req.protocol, &req.hostname, req.rtmpport, &req.sockshost, +- &req.playpath, &req.tcUrl, &req.swfUrl, &req.pageUrl, &req.app, &req.auth, &req.swfHash, req.swfSize, &req.flashVer, &req.subscribepath, &req.usherToken, dSeek, req.dStopOffset, ++ &req.playpath, &req.tcUrl, &req.swfUrl, &req.pageUrl, &req.app, &req.auth, &req.swfHash, req.swfSize, &req.flashVer, &req.subscribepath, &req.usherToken, &req.WeebToken, dSeek, req.dStopOffset, + req.bLiveStream, req.timeout); + /* backward compatibility, we always sent this as true before */ + if (req.auth.av_len) +@@ -957,6 +958,9 @@ ParseOption(char opt, char *arg, RTMP_REQUEST * req) + case 'j': + STR2AVAL(req->usherToken, arg); + break; ++ case 'J': ++ STR2AVAL(req->WeebToken, arg); ++ break; + default: + RTMP_LogPrintf("unknown option: %c, arg: %s\n", opt, arg); + return FALSE; +@@ -1028,6 +1032,7 @@ main(int argc, char **argv) + {"quiet", 0, NULL, 'q'}, + {"verbose", 0, NULL, 'V'}, + {"jtv", 1, NULL, 'j'}, ++ {"weeb", 1, NULL, 'J'}, + {0, 0, 0, 0} + }; + +@@ -1040,7 +1045,7 @@ main(int argc, char **argv) + + while ((opt = + getopt_long(argc, argv, +- "hvqVzr:s:t:p:a:f:u:n:c:l:y:m:d:D:A:B:T:g:w:x:W:X:S:j:", longopts, ++ "hvqVzr:s:t:p:a:f:u:n:c:l:y:m:d:D:A:B:T:g:w:x:W:X:S:j:J:", longopts, + NULL)) != -1) + { + switch (opt) +@@ -1103,6 +1108,8 @@ main(int argc, char **argv) + RTMP_LogPrintf + ("--jtv|-j JSON Authentication token for Justin.tv legacy servers\n"); + RTMP_LogPrintf ++ ("--weeb|-J string Authentication token for weeb.tv servers\n"); ++ RTMP_LogPrintf + ("--buffer|-b Buffer time in milliseconds (default: %u)\n\n", + defaultRTMPRequest.bufferTime); + +diff --git a/rtmpsrv.c b/rtmpsrv.c +index 9aa62f3..9ec8f23 100644 +--- a/rtmpsrv.c ++++ b/rtmpsrv.c +@@ -96,9 +96,20 @@ STREAMING_SERVER *rtmpServer = 0; // server structure pointer + STREAMING_SERVER *startStreaming(const char *address, int port); + void stopStreaming(STREAMING_SERVER * server); + void AVreplace(AVal *src, const AVal *orig, const AVal *repl); ++char *strreplace(char *srcstr, int srclen, char *orig, char *repl); ++int file_exists(const char *fname); ++int SendCheckBWResponse(RTMP *r, int oldMethodType, int onBWDoneInit); ++AVal AVcopy(AVal src); ++AVal StripParams(AVal *src); + + static const AVal av_dquote = AVC("\""); + static const AVal av_escdquote = AVC("\\\""); ++#ifdef WIN32 ++static const AVal av_caret = AVC("^"); ++static const AVal av_esccaret = AVC("^^"); ++static const AVal av_pipe = AVC("|"); ++static const AVal av_escpipe = AVC("^|"); ++#endif + + typedef struct + { +@@ -167,6 +178,10 @@ SAVC(level); + SAVC(code); + SAVC(description); + SAVC(secureToken); ++SAVC(_checkbw); ++SAVC(_onbwdone); ++SAVC(checkBandwidth); ++SAVC(onBWDone); + + static int + SendConnectResult(RTMP *r, double txn) +@@ -190,7 +205,7 @@ SendConnectResult(RTMP *r, double txn) + enc = AMF_EncodeNumber(enc, pend, txn); + *enc++ = AMF_OBJECT; + +- STR2AVAL(av, "FMS/3,5,1,525"); ++ STR2AVAL(av, "FMS/3,5,7,7009"); + enc = AMF_EncodeNamedString(enc, pend, &av_fmsVer, &av); + enc = AMF_EncodeNamedNumber(enc, pend, &av_capabilities, 31.0); + enc = AMF_EncodeNamedNumber(enc, pend, &av_mode, 1.0); +@@ -212,7 +227,7 @@ SendConnectResult(RTMP *r, double txn) + enc = AMF_EncodeNamedString(enc, pend, &av_secureToken, &av); + #endif + STR2AVAL(p.p_name, "version"); +- STR2AVAL(p.p_vu.p_aval, "3,5,1,525"); ++ STR2AVAL(p.p_vu.p_aval, "3,5,7,7009"); + p.p_type = AMF_STRING; + obj.o_num = 1; + obj.o_props = &p; +@@ -268,7 +283,7 @@ static int + SendPlayStart(RTMP *r) + { + RTMPPacket packet; +- char pbuf[512], *pend = pbuf+sizeof(pbuf); ++ char pbuf[1024], *pend = pbuf + sizeof (pbuf); + + packet.m_nChannel = 0x03; // control channel (invoke) + packet.m_headerType = 1; /* RTMP_PACKET_SIZE_MEDIUM; */ +@@ -300,7 +315,7 @@ static int + SendPlayStop(RTMP *r) + { + RTMPPacket packet; +- char pbuf[512], *pend = pbuf+sizeof(pbuf); ++ char pbuf[1024], *pend = pbuf + sizeof (pbuf); + + packet.m_nChannel = 0x03; // control channel (invoke) + packet.m_headerType = 1; /* RTMP_PACKET_SIZE_MEDIUM; */ +@@ -328,6 +343,49 @@ SendPlayStop(RTMP *r) + return RTMP_SendPacket(r, &packet, FALSE); + } + ++int ++SendCheckBWResponse(RTMP *r, int oldMethodType, int onBWDoneInit) ++{ ++ RTMPPacket packet; ++ char pbuf[256], *pend = pbuf + sizeof (pbuf); ++ char *enc; ++ ++ packet.m_nChannel = 0x03; /* control channel (invoke) */ ++ packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM; ++ packet.m_packetType = RTMP_PACKET_TYPE_INVOKE; ++ packet.m_nTimeStamp = 0; ++ packet.m_nInfoField2 = 0; ++ packet.m_hasAbsTimestamp = 0; ++ packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; ++ ++ enc = packet.m_body; ++ if (oldMethodType) ++ { ++ enc = AMF_EncodeString(enc, pend, &av__onbwdone); ++ enc = AMF_EncodeNumber(enc, pend, 0); ++ *enc++ = AMF_NULL; ++ enc = AMF_EncodeNumber(enc, pend, 10240); ++ enc = AMF_EncodeNumber(enc, pend, 10240); ++ } ++ else ++ { ++ enc = AMF_EncodeString(enc, pend, &av_onBWDone); ++ enc = AMF_EncodeNumber(enc, pend, 0); ++ *enc++ = AMF_NULL; ++ if (!onBWDoneInit) ++ { ++ enc = AMF_EncodeNumber(enc, pend, 10240); ++ enc = AMF_EncodeNumber(enc, pend, 10240); ++ enc = AMF_EncodeNumber(enc, pend, 0); ++ enc = AMF_EncodeNumber(enc, pend, 0); ++ } ++ } ++ ++ packet.m_nBodySize = enc - packet.m_body; ++ ++ return RTMP_SendPacket(r, &packet, FALSE); ++} ++ + static void + spawn_dumper(int argc, AVal *av, char *cmd) + { +@@ -568,6 +626,7 @@ ServeInvoke(STREAMING_SERVER *server, RTMP * r, RTMPPacket *packet, unsigned int + server->arglen += countAMF(&r->Link.extras, &server->argc); + } + SendConnectResult(r, txn); ++ SendCheckBWResponse(r, FALSE, TRUE); + } + else if (AVMATCH(&method, &av_createStream)) + { +@@ -582,10 +641,22 @@ ServeInvoke(STREAMING_SERVER *server, RTMP * r, RTMPPacket *packet, unsigned int + AVal usherToken; + AMFProp_GetString(AMF_GetProp(&obj, NULL, 3), &usherToken); + AVreplace(&usherToken, &av_dquote, &av_escdquote); ++#ifdef WIN32 ++ AVreplace(&usherToken, &av_caret, &av_esccaret); ++ AVreplace(&usherToken, &av_pipe, &av_escpipe); ++#endif + server->arglen += 6 + usherToken.av_len; + server->argc += 2; + r->Link.usherToken = usherToken; + } ++ else if (AVMATCH(&method, &av__checkbw)) ++ { ++ SendCheckBWResponse(r, TRUE, FALSE); ++ } ++ else if (AVMATCH(&method, &av_checkBandwidth)) ++ { ++ SendCheckBWResponse(r, FALSE, FALSE); ++ } + else if (AVMATCH(&method, &av_play)) + { + char *file, *p, *q, *cmd, *ptr; +@@ -599,6 +670,17 @@ ServeInvoke(STREAMING_SERVER *server, RTMP * r, RTMPPacket *packet, unsigned int + if (obj.o_num > 5) + r->Link.length = AMFProp_GetNumber(AMF_GetProp(&obj, NULL, 5)); + */ ++ double StartFlag = 0; ++ AMFObjectProperty *Start = AMF_GetProp(&obj, NULL, 4); ++ if (!(Start->p_type == AMF_INVALID)) ++ StartFlag = AMFProp_GetNumber(Start); ++ r->Link.app = AVcopy(r->Link.app); ++ if (StartFlag == -1000 || strstr(r->Link.app.av_val, "live")) ++ { ++ StartFlag = -1000; ++ server->arglen += 7; ++ server->argc += 1; ++ } + if (r->Link.tcUrl.av_len) + { + len = server->arglen + r->Link.playpath.av_len + 4 + +@@ -616,6 +698,7 @@ ServeInvoke(STREAMING_SERVER *server, RTMP * r, RTMPPacket *packet, unsigned int + argv[argc].av_val = ptr + 1; + argv[argc++].av_len = 2; + argv[argc].av_val = ptr + 5; ++ r->Link.tcUrl = StripParams(&r->Link.tcUrl); + ptr += sprintf(ptr," -r \"%s\"", r->Link.tcUrl.av_val); + argv[argc++].av_len = r->Link.tcUrl.av_len; + +@@ -640,6 +723,7 @@ ServeInvoke(STREAMING_SERVER *server, RTMP * r, RTMPPacket *packet, unsigned int + argv[argc].av_val = ptr + 1; + argv[argc++].av_len = 2; + argv[argc].av_val = ptr + 5; ++ r->Link.swfUrl = StripParams(&r->Link.swfUrl); + ptr += sprintf(ptr, " -W \"%s\"", r->Link.swfUrl.av_val); + argv[argc++].av_len = r->Link.swfUrl.av_len; + } +@@ -662,10 +746,17 @@ ServeInvoke(STREAMING_SERVER *server, RTMP * r, RTMPPacket *packet, unsigned int + r->Link.usherToken.av_val = NULL; + r->Link.usherToken.av_len = 0; + } +- if (r->Link.extras.o_num) { +- ptr = dumpAMF(&r->Link.extras, ptr, argv, &argc); +- AMF_Reset(&r->Link.extras); +- } ++ if (StartFlag == -1000) ++ { ++ argv[argc].av_val = ptr + 1; ++ argv[argc++].av_len = 6; ++ ptr += sprintf(ptr, " --live"); ++ } ++ if (r->Link.extras.o_num) ++ { ++ ptr = dumpAMF(&r->Link.extras, ptr, argv, &argc); ++ AMF_Reset(&r->Link.extras); ++ } + argv[argc].av_val = ptr + 1; + argv[argc++].av_len = 2; + argv[argc].av_val = ptr + 5; +@@ -673,7 +764,13 @@ ServeInvoke(STREAMING_SERVER *server, RTMP * r, RTMPPacket *packet, unsigned int + r->Link.playpath.av_len, r->Link.playpath.av_val); + argv[argc++].av_len = r->Link.playpath.av_len; + +- av = r->Link.playpath; ++ if (r->Link.playpath.av_len) ++ av = r->Link.playpath; ++ else ++ { ++ av.av_val = "file"; ++ av.av_len = 4; ++ } + /* strip trailing URL parameters */ + q = memchr(av.av_val, '?', av.av_len); + if (q) +@@ -725,7 +822,30 @@ ServeInvoke(STREAMING_SERVER *server, RTMP * r, RTMPPacket *packet, unsigned int + argv[argc++].av_len = 2; + argv[argc].av_val = file; + argv[argc].av_len = av.av_len; +- ptr += sprintf(ptr, " -o %s", file); ++#ifdef VLC ++ char *vlc; ++ int didAlloc = FALSE; ++ ++ if (getenv("VLC")) ++ vlc = getenv("VLC"); ++ else if (getenv("ProgramFiles")) ++ { ++ vlc = malloc(512 * sizeof (char)); ++ didAlloc = TRUE; ++ char *ProgramFiles = getenv("ProgramFiles"); ++ sprintf(vlc, "%s%s", ProgramFiles, " (x86)\\VideoLAN\\VLC\\vlc.exe"); ++ if (!file_exists(vlc)) ++ sprintf(vlc, "%s%s", ProgramFiles, "\\VideoLAN\\VLC\\vlc.exe"); ++ } ++ else ++ vlc = "C:\\Program Files\\VideoLAN\\VLC\\vlc.exe"; ++ ++ ptr += sprintf(ptr, " | %s -", vlc); ++ if (didAlloc) ++ free(vlc); ++#else ++ ptr += sprintf(ptr, " -o %s", file); ++#endif + now = RTMP_GetTime(); + if (now - server->filetime < DUPTIME && AVMATCH(&argv[argc], &server->filename)) + { +@@ -739,7 +859,23 @@ ServeInvoke(STREAMING_SERVER *server, RTMP * r, RTMPPacket *packet, unsigned int + server->filetime = now; + free(server->filename.av_val); + server->filename = argv[argc++]; +- spawn_dumper(argc, argv, cmd); ++#ifdef VLC ++ FILE *vlc_cmdfile = fopen("VLC.bat", "w"); ++ char *vlc_batchcmd = strreplace(cmd, 0, "%", "%%"); ++ fprintf(vlc_cmdfile, "%s\n", vlc_batchcmd); ++ fclose(vlc_cmdfile); ++ free(vlc_batchcmd); ++ spawn_dumper(argc, argv, "VLC.bat"); ++#else ++ spawn_dumper(argc, argv, cmd); ++#endif ++ ++#ifdef WIN32 ++ // Dump command to batch file ++ FILE *cmdfile = fopen("Command.bat", "a"); ++ fprintf(cmdfile, "%s\n", cmd); ++ fclose(cmdfile); ++#endif + } + + free(cmd); +@@ -1178,3 +1314,115 @@ AVreplace(AVal *src, const AVal *orig, const AVal *repl) + src->av_val = dest; + src->av_len = dptr - dest; + } ++ ++char * ++strreplace(char *srcstr, int srclen, char *orig, char *repl) ++{ ++ char *ptr = NULL, *sptr = srcstr; ++ int origlen = strlen(orig); ++ int repllen = strlen(repl); ++ if (!srclen) ++ srclen = strlen(srcstr); ++ char *srcend = srcstr + srclen; ++ int dstbuffer = srclen / origlen * repllen; ++ if (dstbuffer < srclen) ++ dstbuffer = srclen; ++ char *dststr = calloc(dstbuffer + 1, sizeof (char)); ++ char *dptr = dststr; ++ ++ if ((ptr = strstr(srcstr, orig))) ++ { ++ while (ptr < srcend && (ptr = strstr(sptr, orig))) ++ { ++ int len = ptr - sptr; ++ memcpy(dptr, sptr, len); ++ sptr += len + origlen; ++ dptr += len; ++ memcpy(dptr, repl, repllen); ++ dptr += repllen; ++ } ++ memcpy(dptr, sptr, srcend - sptr); ++ return dststr; ++ } ++ ++ memcpy(dststr, srcstr, srclen); ++ return dststr; ++} ++ ++AVal ++StripParams(AVal *src) ++{ ++ AVal str; ++ if (src->av_val) ++ { ++ str.av_val = calloc(src->av_len + 1, sizeof (char)); ++ strncpy(str.av_val, src->av_val, src->av_len); ++ str.av_len = src->av_len; ++ char *start = str.av_val; ++ char *end = start + str.av_len; ++ char *ptr = start; ++ ++ while (ptr < end) ++ { ++ if (*ptr == '?') ++ { ++ str.av_len = ptr - start; ++ break; ++ } ++ ptr++; ++ } ++ memset(start + str.av_len, 0, 1); ++ ++ char *dynamic = strstr(start, "[[DYNAMIC]]"); ++ if (dynamic) ++ { ++ dynamic -= 1; ++ memset(dynamic, 0, 1); ++ str.av_len = dynamic - start; ++ end = start + str.av_len; ++ } ++ ++ char *import = strstr(start, "[[IMPORT]]"); ++ if (import) ++ { ++ str.av_val = import + 11; ++ strcpy(start, "http://"); ++ str.av_val = strcat(start, str.av_val); ++ str.av_len = strlen(str.av_val); ++ } ++ return str; ++ } ++ str = *src; ++ return str; ++} ++ ++int ++file_exists(const char *fname) ++{ ++ FILE *file; ++ if ((file = fopen(fname, "r"))) ++ { ++ fclose(file); ++ return TRUE; ++ } ++ return FALSE; ++} ++ ++AVal ++AVcopy(AVal src) ++{ ++ AVal dst; ++ if (src.av_len) ++ { ++ dst.av_val = malloc(src.av_len + 1); ++ memcpy(dst.av_val, src.av_val, src.av_len); ++ dst.av_val[src.av_len] = '\0'; ++ dst.av_len = src.av_len; ++ } ++ else ++ { ++ dst.av_val = NULL; ++ dst.av_len = 0; ++ } ++ return dst; ++} +diff --git a/rtmpsuck.c b/rtmpsuck.c +index e886179..e80c686 100644 +--- a/rtmpsuck.c ++++ b/rtmpsuck.c +@@ -143,15 +143,18 @@ SAVC(onStatus); + SAVC(close); + static const AVal av_NetStream_Failed = AVC("NetStream.Failed"); + static const AVal av_NetStream_Play_Failed = AVC("NetStream.Play.Failed"); +-static const AVal av_NetStream_Play_StreamNotFound = +-AVC("NetStream.Play.StreamNotFound"); +-static const AVal av_NetConnection_Connect_InvalidApp = +-AVC("NetConnection.Connect.InvalidApp"); ++static const AVal av_NetStream_Play_StreamNotFound = AVC("NetStream.Play.StreamNotFound"); ++static const AVal av_NetConnection_Connect_InvalidApp = AVC("NetConnection.Connect.InvalidApp"); + static const AVal av_NetStream_Play_Start = AVC("NetStream.Play.Start"); + static const AVal av_NetStream_Play_Complete = AVC("NetStream.Play.Complete"); + static const AVal av_NetStream_Play_Stop = AVC("NetStream.Play.Stop"); ++static const AVal av_NetStream_Authenticate_UsherToken = AVC("NetStream.Authenticate.UsherToken"); + + static const char *cst[] = { "client", "server" }; ++char *dumpAMF(AMFObject *obj, char *ptr); ++char *strreplace(char *srcstr, int srclen, char *orig, char *repl); ++AVal AVcopy(AVal src); ++AVal StripParams(AVal *src); + + // Returns 0 for OK/Failed/error, 1 for 'Stop or Complete' + int +@@ -198,26 +201,28 @@ ServeInvoke(STREAMING_SERVER *server, int which, RTMPPacket *pack, const char *b + if (cobj.o_props[i].p_type == AMF_STRING) + { + pval = cobj.o_props[i].p_vu.p_aval; +- RTMP_LogPrintf("%.*s: %.*s\n", pname.av_len, pname.av_val, pval.av_len, pval.av_val); ++ RTMP_LogPrintf("%10.*s : %.*s\n", pname.av_len, pname.av_val, pval.av_len, pval.av_val); + } + if (AVMATCH(&pname, &av_app)) + { +- server->rc.Link.app = pval; ++ server->rc.Link.app = AVcopy(pval); + pval.av_val = NULL; + } + else if (AVMATCH(&pname, &av_flashVer)) + { +- server->rc.Link.flashVer = pval; ++ server->rc.Link.flashVer = AVcopy(pval); + pval.av_val = NULL; + } + else if (AVMATCH(&pname, &av_swfUrl)) + { + #ifdef CRYPTO + if (pval.av_val) +- RTMP_HashSWF(pval.av_val, &server->rc.Link.SWFSize, +- (unsigned char *)server->rc.Link.SWFHash, 30); ++ { ++ AVal swfUrl = StripParams(&pval); ++ RTMP_HashSWF(swfUrl.av_val, &server->rc.Link.SWFSize, (unsigned char *) server->rc.Link.SWFHash, 30); ++ } + #endif +- server->rc.Link.swfUrl = pval; ++ server->rc.Link.swfUrl = AVcopy(pval); + pval.av_val = NULL; + } + else if (AVMATCH(&pname, &av_tcUrl)) +@@ -225,7 +230,7 @@ ServeInvoke(STREAMING_SERVER *server, int which, RTMPPacket *pack, const char *b + char *r1 = NULL, *r2; + int len; + +- server->rc.Link.tcUrl = pval; ++ server->rc.Link.tcUrl = AVcopy(pval); + if ((pval.av_val[0] | 0x40) == 'r' && + (pval.av_val[1] | 0x40) == 't' && + (pval.av_val[2] | 0x40) == 'm' && +@@ -267,7 +272,7 @@ ServeInvoke(STREAMING_SERVER *server, int which, RTMPPacket *pack, const char *b + } + else if (AVMATCH(&pname, &av_pageUrl)) + { +- server->rc.Link.pageUrl = pval; ++ server->rc.Link.pageUrl = AVcopy(pval); + pval.av_val = NULL; + } + else if (AVMATCH(&pname, &av_audioCodecs)) +@@ -287,14 +292,21 @@ ServeInvoke(STREAMING_SERVER *server, int which, RTMPPacket *pack, const char *b + if (pval.av_val) + free(pval.av_val); + } ++ + if (obj.o_num > 3) + { +- if (AMFProp_GetBoolean(&obj.o_props[3])) +- server->rc.Link.lFlags |= RTMP_LF_AUTH; +- if (obj.o_num > 4) +- { +- AMFProp_GetString(&obj.o_props[4], &server->rc.Link.auth); +- } ++ int i = obj.o_num - 3; ++ server->rc.Link.extras.o_num = i; ++ server->rc.Link.extras.o_props = malloc(i * sizeof (AMFObjectProperty)); ++ memcpy(server->rc.Link.extras.o_props, obj.o_props + 3, i * sizeof (AMFObjectProperty)); ++ obj.o_num = 3; ++ } ++ ++ if (server->rc.Link.extras.o_num) ++ { ++ server->rc.Link.Extras.av_val = calloc(1024, sizeof (char)); ++ dumpAMF(&server->rc.Link.extras, server->rc.Link.Extras.av_val); ++ server->rc.Link.Extras.av_len = strlen(server->rc.Link.Extras.av_val); + } + + if (!RTMP_Connect(&server->rc, pack)) +@@ -303,6 +315,16 @@ ServeInvoke(STREAMING_SERVER *server, int which, RTMPPacket *pack, const char *b + return 1; + } + server->rc.m_bSendCounter = FALSE; ++ ++ if (server->rc.Link.extras.o_props) ++ { ++ AMF_Reset(&server->rc.Link.extras); ++ } ++ } ++ else if (AVMATCH(&method, &av_NetStream_Authenticate_UsherToken)) ++ { ++ AMFProp_GetString(AMF_GetProp(&obj, NULL, 3), &server->rc.Link.usherToken); ++ RTMP_LogPrintf("%10s : %.*s\n", "usherToken", server->rc.Link.usherToken.av_len, server->rc.Link.usherToken.av_val); + } + else if (AVMATCH(&method, &av_play)) + { +@@ -323,6 +345,14 @@ ServeInvoke(STREAMING_SERVER *server, int which, RTMPPacket *pack, const char *b + if (!av.av_val) + goto out; + ++ double StartFlag = 0; ++ AMFObjectProperty *Start = AMF_GetProp(&obj, NULL, 4); ++ if (!(Start->p_type == AMF_INVALID)) ++ StartFlag = AMFProp_GetNumber(Start); ++ if (StartFlag == -1000 || strstr(server->rc.Link.app.av_val, "live")) ++ StartFlag = -1000; ++ RTMP_LogPrintf("%10s : %s\n", "live", (StartFlag == -1000) ? "yes" : "no"); ++ + /* check for duplicates */ + for (fl = server->f_head; fl; fl=fl->f_next) + { +@@ -372,9 +402,51 @@ ServeInvoke(STREAMING_SERVER *server, int which, RTMPPacket *pack, const char *b + for (p=file; *p; p++) + if (*p == ':') + *p = '_'; +- RTMP_LogPrintf("Playpath: %.*s\nSaving as: %s\n", +- server->rc.Link.playpath.av_len, server->rc.Link.playpath.av_val, +- file); ++ RTMP_LogPrintf("%10s : %.*s\n%10s : %s\n", "Playpath", server->rc.Link.playpath.av_len, ++ server->rc.Link.playpath.av_val, "Saving as", file); ++ ++#ifdef WIN32 ++ // Dump command to batch file ++ char *cmd = NULL, *ptr = NULL; ++ AVal swfUrl, tcUrl; ++ ++ cmd = calloc(2048, sizeof (char)); ++ ptr = cmd; ++ tcUrl = StripParams(&server->rc.Link.tcUrl); ++ swfUrl = StripParams(&server->rc.Link.swfUrl); ++ ptr += sprintf(ptr, "rtmpdump -r \"%.*s\" -a \"%.*s\" -f \"%.*s\" -W \"%.*s\" -p \"%.*s\"", ++ tcUrl.av_len, tcUrl.av_val, ++ server->rc.Link.app.av_len, server->rc.Link.app.av_val, ++ server->rc.Link.flashVer.av_len, server->rc.Link.flashVer.av_val, ++ swfUrl.av_len, swfUrl.av_val, ++ server->rc.Link.pageUrl.av_len, server->rc.Link.pageUrl.av_val); ++ ++ if (server->rc.Link.usherToken.av_val) ++ { ++ char *usherToken = strreplace(server->rc.Link.usherToken.av_val, server->rc.Link.usherToken.av_len, "\"", "\\\""); ++ usherToken = strreplace(usherToken, 0, "^", "^^"); ++ usherToken = strreplace(usherToken, 0, "|", "^|"); ++ ptr += sprintf(ptr, " --jtv \"%s\"", usherToken); ++ free(usherToken); ++ } ++ ++ if (server->rc.Link.Extras.av_len) ++ { ++ ptr += sprintf(ptr, "%.*s", server->rc.Link.Extras.av_len, server->rc.Link.Extras.av_val); ++ } ++ ++ if (StartFlag == -1000) ++ ptr += sprintf(ptr, "%s", " --live"); ++ ptr += sprintf(ptr, " -y \"%.*s\"", server->rc.Link.playpath.av_len, server->rc.Link.playpath.av_val); ++ ptr += sprintf(ptr, " -o \"%s.flv\"\n", file); ++ ++ FILE *cmdfile = fopen("Command.bat", "a"); ++ fprintf(cmdfile, "%s", cmd); ++ fclose(cmdfile); ++ ++ free(cmd); ++#endif ++ + out = fopen(file, "wb"); + free(file); + if (!out) +@@ -1196,3 +1268,146 @@ main(int argc, char **argv) + #endif + return nStatus; + } ++ ++char * ++dumpAMF(AMFObject *obj, char *ptr) ++{ ++ int i; ++ const char opt[] = "NBSO Z"; ++ ++ for (i = 0; i < obj->o_num; i++) ++ { ++ AMFObjectProperty *p = &obj->o_props[i]; ++ if (p->p_type > 5) ++ continue; ++ ptr += sprintf(ptr, " -C "); ++ if (p->p_name.av_val) ++ *ptr++ = 'N'; ++ *ptr++ = opt[p->p_type]; ++ *ptr++ = ':'; ++ if (p->p_name.av_val) ++ ptr += sprintf(ptr, "%.*s:", p->p_name.av_len, p->p_name.av_val); ++ switch (p->p_type) ++ { ++ case AMF_BOOLEAN: ++ *ptr++ = p->p_vu.p_number != 0 ? '1' : '0'; ++ break; ++ case AMF_STRING: ++ memcpy(ptr, p->p_vu.p_aval.av_val, p->p_vu.p_aval.av_len); ++ ptr += p->p_vu.p_aval.av_len; ++ break; ++ case AMF_NUMBER: ++ ptr += sprintf(ptr, "%f", p->p_vu.p_number); ++ break; ++ case AMF_OBJECT: ++ *ptr++ = '1'; ++ ptr = dumpAMF(&p->p_vu.p_object, ptr); ++ ptr += sprintf(ptr, " -C O:0"); ++ break; ++ case AMF_NULL: ++ default: ++ break; ++ } ++ } ++ return ptr; ++} ++ ++char * ++strreplace(char *srcstr, int srclen, char *orig, char *repl) ++{ ++ char *ptr = NULL, *sptr = srcstr; ++ int origlen = strlen(orig); ++ int repllen = strlen(repl); ++ if (!srclen) ++ srclen = strlen(srcstr); ++ char *srcend = srcstr + srclen; ++ int dstbuffer = srclen / origlen * repllen; ++ if (dstbuffer < srclen) ++ dstbuffer = srclen; ++ char *dststr = calloc(dstbuffer + 1, sizeof (char)); ++ char *dptr = dststr; ++ ++ if ((ptr = strstr(srcstr, orig))) ++ { ++ while (ptr < srcend && (ptr = strstr(sptr, orig))) ++ { ++ int len = ptr - sptr; ++ memcpy(dptr, sptr, len); ++ sptr += len + origlen; ++ dptr += len; ++ memcpy(dptr, repl, repllen); ++ dptr += repllen; ++ } ++ memcpy(dptr, sptr, srcend - sptr); ++ return dststr; ++ } ++ ++ memcpy(dststr, srcstr, srclen); ++ return dststr; ++} ++ ++AVal ++StripParams(AVal *src) ++{ ++ AVal str; ++ if (src->av_val) ++ { ++ str.av_val = calloc(src->av_len + 1, sizeof (char)); ++ strncpy(str.av_val, src->av_val, src->av_len); ++ str.av_len = src->av_len; ++ char *start = str.av_val; ++ char *end = start + str.av_len; ++ char *ptr = start; ++ ++ while (ptr < end) ++ { ++ if (*ptr == '?') ++ { ++ str.av_len = ptr - start; ++ break; ++ } ++ ptr++; ++ } ++ memset(start + str.av_len, 0, 1); ++ ++ char *dynamic = strstr(start, "[[DYNAMIC]]"); ++ if (dynamic) ++ { ++ dynamic -= 1; ++ memset(dynamic, 0, 1); ++ str.av_len = dynamic - start; ++ end = start + str.av_len; ++ } ++ ++ char *import = strstr(start, "[[IMPORT]]"); ++ if (import) ++ { ++ str.av_val = import + 11; ++ strcpy(start, "http://"); ++ str.av_val = strcat(start, str.av_val); ++ str.av_len = strlen(str.av_val); ++ } ++ return str; ++ } ++ str = *src; ++ return str; ++} ++ ++AVal ++AVcopy(AVal src) ++{ ++ AVal dst; ++ if (src.av_len) ++ { ++ dst.av_val = malloc(src.av_len + 1); ++ memcpy(dst.av_val, src.av_val, src.av_len); ++ dst.av_val[src.av_len] = '\0'; ++ dst.av_len = src.av_len; ++ } ++ else ++ { ++ dst.av_val = NULL; ++ dst.av_len = 0; ++ } ++ return dst; ++} From ea604243f2dace73000ed79051438337ef55a9d3 Mon Sep 17 00:00:00 2001 From: davilla Date: Sun, 13 Jan 2013 13:34:04 -0500 Subject: [PATCH 113/180] [aml] fix configure logging for additional players/codecs --- configure.in | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 63d4fd95ab8ca..f037c2f496370 100644 --- a/configure.in +++ b/configure.in @@ -2314,11 +2314,17 @@ else fi if test "x$add_players" != "xno"; then - final_message="$final_message\n additional players:\tYes" + final_message="$final_message\n additional players:\tYes, $add_players" else final_message="$final_message\n additional players:\tNo" fi +if test "x$add_codecs" != "xno"; then + final_message="$final_message\n additional codecs:\tYes, $add_codecs" +else + final_message="$final_message\n additional codecs:\tNo" +fi + ### External libraries messages if test "$use_external_ffmpeg" = "yes"; then From 10a036dca4afd027103af143cdfc6f15182135d0 Mon Sep 17 00:00:00 2001 From: davilla Date: Wed, 16 Jan 2013 13:43:51 -0500 Subject: [PATCH 114/180] [aml] improve vc1 playback --- xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index 9e862ea4f9960..5b1def97137fd 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -518,6 +518,14 @@ static int write_header(am_private_t *para, am_packet_t *pkt) CLog::Log(LOGDEBUG, "[write_header]codec null!"); return PLAYER_EMPTY_P; } + //some wvc1 es data not need to add header + if (para->video_format == VFORMAT_VC1 && para->video_codec_type == VIDEO_DEC_FORMAT_WVC1) { + if ((pkt->data) && (pkt->data_size >= 4) + && (pkt->data[0] == 0) && (pkt->data[1] == 0) + && (pkt->data[2] == 1) && (pkt->data[3] == 0xd || pkt->data[3] == 0xf)) { + return PLAYER_SUCCESS; + } + } while (1) { write_bytes = para->m_dll->codec_write(pkt->codec, pkt->hdr->data + len, pkt->hdr->size - len); if (write_bytes < 0 || write_bytes > (pkt->hdr->size - len)) { From e0f472acfc3c5a61bcdee98249ce056e0927bb2a Mon Sep 17 00:00:00 2001 From: davilla Date: Wed, 16 Jan 2013 15:18:47 -0500 Subject: [PATCH 115/180] [aml] changed, never, ever trust pts in avi containers --- xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp index 159165898fce9..7847947295bfd 100644 --- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp @@ -974,8 +974,8 @@ void CDVDDemuxFFmpeg::AddStream(int iId) else st->bVFR = false; - // never trust pts in avi files with h264. - if (m_bAVI && pStream->codec->codec_id == CODEC_ID_H264) + // never trust pts in avi files + if (m_bAVI) st->bPTSInvalid = true; //average fps is more accurate for mkv files From 09cf21a04c3df1f2c96a4a31840fe0d999a3155b Mon Sep 17 00:00:00 2001 From: davilla Date: Wed, 16 Jan 2013 15:19:34 -0500 Subject: [PATCH 116/180] [aml] changed, if we get m_hints.ptsinvalid, nuke pts so we do not use it --- xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp index b2ac0c5094626..360e6f2f9bcfd 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp @@ -152,6 +152,9 @@ int CDVDVideoCodecAmlogic::Decode(BYTE *pData, int iSize, double dts, double pts m_opened = true; } + if (m_hints.ptsinvalid) + pts = DVD_NOPTS_VALUE; + return m_Codec->Decode(pData, iSize, dts, pts); } From 07f48ba72c6b1f0957bc2842a443d6c548e0d513 Mon Sep 17 00:00:00 2001 From: davilla Date: Wed, 16 Jan 2013 15:20:16 -0500 Subject: [PATCH 117/180] [aml] add debug logging to track pts adjustments --- xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index 5b1def97137fd..07882ec81a511 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -1785,7 +1785,10 @@ void CAMLCodec::Process() // correct video pts by user set delay and rendering delay app_pts += offset; if (fabs((double)pts_video/PTS_FREQ - app_pts) > 0.20) + { + CLog::Log(LOGDEBUG, "CAMLCodec::Process pts diff = %f", (double)pts_video/PTS_FREQ - app_pts); SetVideoPtsSeconds(app_pts); + } } } else From 6f6882dff9d0760b9645d3abc3d4fb559d3c7ba4 Mon Sep 17 00:00:00 2001 From: davilla Date: Fri, 18 Jan 2013 17:47:44 -0500 Subject: [PATCH 118/180] [aml] fixed, mjpeg playback using hardware video decode --- .../dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 94 ++++++++++++++++++- .../DVDCodecs/Video/DVDVideoCodecAmlogic.cpp | 6 +- 2 files changed, 95 insertions(+), 5 deletions(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index 07882ec81a511..4f1423466565d 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -153,6 +153,10 @@ class DllLibAmCodec : public DllDynamic, DllLibamCodecInterface #define CODEC_TAG_VC_1 (0x312D4356) #define CODEC_TAG_RV30 (0x30335652) #define CODEC_TAG_RV40 (0x30345652) +#define CODEC_TAG_MJPEG (0x47504a4d) +#define CODEC_TAG_mjpeg (0x47504a4c) +#define CODEC_TAG_jpeg (0x6765706a) +#define CODEC_TAG_mjpa (0x61706a6d) #define RW_WAIT_TIME (20 * 1000) // 20ms @@ -341,6 +345,12 @@ static vdec_type_t codec_tag_to_vdec_type(unsigned int codec_tag) vdec_type_t dec_type; switch (codec_tag) { + case CODEC_TAG_MJPEG: + case CODEC_TAG_mjpeg: + case CODEC_TAG_jpeg: + case CODEC_TAG_mjpa: + dec_type = VIDEO_DEC_FORMAT_MJPEG; + break; case CODEC_TAG_XVID: case CODEC_TAG_xvid: case CODEC_TAG_XVIX: @@ -719,6 +729,68 @@ static int m4s2_dx50_mp4v_write_header(am_private_t *para, am_packet_t *pkt) return ret; } +static int mjpeg_data_prefeeding(am_packet_t *pkt) +{ + const unsigned char mjpeg_addon_data[] = { + 0xff, 0xd8, 0xff, 0xc4, 0x01, 0xa2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, + 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x01, 0x00, 0x03, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x10, + 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, + 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, + 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, + 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, + 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, + 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, + 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, + 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, + 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, + 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, + 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, + 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x11, 0x00, 0x02, 0x01, + 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, + 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, + 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, + 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, + 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, + 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, + 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, + 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, + 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, + 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, + 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa + }; + + if (pkt->hdr->data) { + memcpy(pkt->hdr->data, &mjpeg_addon_data, sizeof(mjpeg_addon_data)); + pkt->hdr->size = sizeof(mjpeg_addon_data); + } else { + CLog::Log(LOGDEBUG, "[mjpeg_data_prefeeding]No enough memory!"); + return PLAYER_FAILED; + } + return PLAYER_SUCCESS; +} + +static int mjpeg_write_header(am_private_t *para, am_packet_t *pkt) +{ + mjpeg_data_prefeeding(pkt); + if (1) { + pkt->codec = ¶->vcodec; + } else { + CLog::Log(LOGDEBUG, "[mjpeg_write_header]invalid codec!"); + return PLAYER_EMPTY_P; + } + pkt->newflag = 1; + write_av_packet(para, pkt); + return PLAYER_SUCCESS; +} + static int divx3_data_prefeeding(am_packet_t *pkt, unsigned w, unsigned h) { unsigned i = (w << 12) | (h & 0xfff); @@ -1011,6 +1083,11 @@ int pre_header_feeding(am_private_t *para, am_packet_t *pkt) return ret; } */ + } else if (VFORMAT_MJPEG == para->video_format) { + ret = mjpeg_write_header(para, pkt); + if (ret != PLAYER_SUCCESS) { + return ret; + } } if (pkt->hdr) { @@ -1398,7 +1475,6 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) am_private->video_codec_id = hints.codec; am_private->video_codec_tag = hints.codec_tag; am_private->video_pid = hints.pid; - //am_private->video_pid = 0; // handle video ratio AVRational video_ratio = m_dll->av_d2q(1, SHRT_MAX); @@ -1516,8 +1592,11 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) break; case VFORMAT_H264: case VFORMAT_H264MVC: - am_private->vcodec.am_sysinfo.format = VIDEO_DEC_FORMAT_H264; - am_private->vcodec.am_sysinfo.param = (void*)(EXTERNAL_PTS | SYNC_OUTSIDE); + am_private->vcodec.am_sysinfo.format = VIDEO_DEC_FORMAT_H264; + am_private->vcodec.am_sysinfo.param = (void*)EXTERNAL_PTS; + // h264 in an avi file + if (hints.ptsinvalid) + am_private->vcodec.am_sysinfo.param = (void*)(EXTERNAL_PTS | SYNC_OUTSIDE); break; case VFORMAT_REAL: am_private->stream_type = AM_STREAM_RM; @@ -1544,6 +1623,9 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) case VFORMAT_VC1: // vc1 is extension id, from 0xfd55 to 0xfd5f according to ffmpeg am_private->vcodec.video_pid = am_private->vcodec.video_pid >> 8; + // vc1 in an avi file + if (hints.ptsinvalid) + am_private->vcodec.am_sysinfo.param = (void*)EXTERNAL_PTS; break; } am_private->vcodec.am_sysinfo.param = (void *)((unsigned int)am_private->vcodec.am_sysinfo.param | (am_private->video_rotation_degree << 16)); @@ -1668,9 +1750,13 @@ int CAMLCodec::Decode(unsigned char *pData, size_t size, double dts, double pts) if (m_1st_pts == 0) m_1st_pts = am_private->am_pkt.lastpts; } + // keep hw buffered demux above 1 second if (GetTimeSize() < 1.0) + { + CLog::Log(LOGDEBUG, "CAMLCodec::Decode: GetTimeSize() < 1.0"); return VC_BUFFER; + } // wait until we get a new frame or 100ms, m_ready_event.WaitMSec(100); @@ -1786,7 +1872,7 @@ void CAMLCodec::Process() app_pts += offset; if (fabs((double)pts_video/PTS_FREQ - app_pts) > 0.20) { - CLog::Log(LOGDEBUG, "CAMLCodec::Process pts diff = %f", (double)pts_video/PTS_FREQ - app_pts); + //CLog::Log(LOGDEBUG, "CAMLCodec::Process pts diff = %f", (double)pts_video/PTS_FREQ - app_pts); SetVideoPtsSeconds(app_pts); } } diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp index 360e6f2f9bcfd..45776aed1bfcf 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp @@ -30,7 +30,7 @@ CDVDVideoCodecAmlogic::CDVDVideoCodecAmlogic() : m_Codec(NULL), - m_pFormatName("") + m_pFormatName("amcodec") { } @@ -43,6 +43,9 @@ bool CDVDVideoCodecAmlogic::Open(CDVDStreamInfo &hints, CDVDCodecOptions &option { switch(hints.codec) { + case CODEC_ID_MJPEG: + m_pFormatName = "am-mjpeg"; + break; case CODEC_ID_MPEG1VIDEO: case CODEC_ID_MPEG2VIDEO: case CODEC_ID_MPEG2VIDEO_XVMC: @@ -77,6 +80,7 @@ bool CDVDVideoCodecAmlogic::Open(CDVDStreamInfo &hints, CDVDCodecOptions &option m_pFormatName = "am-wmv3"; break; default: + CLog::Log(LOGDEBUG, "%s: Unknown hints.codec(%d", __MODULE_NAME__, hints.codec); return false; break; } From 4bc6141ff72acdddfd68ab20161973e3b4f4aaa9 Mon Sep 17 00:00:00 2001 From: sensite Date: Sat, 19 Jan 2013 07:56:05 -0500 Subject: [PATCH 119/180] Update xbmc/epg/EpgContainer.cpp prevent pvr updates while video is playing. If pvr updates video will lag and stutter --- xbmc/epg/EpgContainer.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/xbmc/epg/EpgContainer.cpp b/xbmc/epg/EpgContainer.cpp index 23122a463b747..fb9fba0b85120 100644 --- a/xbmc/epg/EpgContainer.cpp +++ b/xbmc/epg/EpgContainer.cpp @@ -444,12 +444,13 @@ bool CEpgContainer::InterruptUpdate(void) const bool bReturn(false); CSingleLock lock(m_critSection); bReturn = g_application.m_bStop || m_bStop || m_bPreventUpdates; + const bool isVideoPlaying = g_application.m_pPlayer && g_application.m_pPlayer->IsPlaying(); + const bool isPVRPlaying = g_PVRManager.IsStarted() && g_PVRManager.IsPlaying(); lock.Leave(); return bReturn || (g_guiSettings.GetBool("epg.preventupdateswhileplayingtv") && - g_PVRManager.IsStarted() && - g_PVRManager.IsPlaying()); + ( isPVRPlaying || isVideoPlaying )); } void CEpgContainer::WaitForUpdateFinish(bool bInterrupt /* = true */) From 9470572d0d6ac56a35afb52761383ed34f59d63c Mon Sep 17 00:00:00 2001 From: davilla Date: Sat, 19 Jan 2013 15:29:35 -0500 Subject: [PATCH 120/180] add DVDVideoCodec::SetSpeed --- xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 6 ++++++ xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 2 ++ 2 files changed, 8 insertions(+) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h index 1d8bad38525cd..104cbbf58cffe 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h @@ -191,6 +191,12 @@ class CDVDVideoCodec */ virtual void SetDropState(bool bDrop) = 0; + /* + * will be called by video player indicating the playback speed. see DVD_PLAYSPEED_NORMAL, + * DVD_PLAYSPEED_PAUSE and friends. + */ + virtual void SetSpeed(int iSpeed) {}; + /* * returns the number of demuxer bytes in any internal buffers */ diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp index 29ee97ffbb37c..346223505b60b 100644 --- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp @@ -465,6 +465,8 @@ void CDVDPlayerVideo::Process() m_speed = static_cast(pMsg)->m_value; if(m_speed == DVD_PLAYSPEED_PAUSE) m_iNrOfPicturesNotToSkip = 0; + if (m_pVideoCodec) + m_pVideoCodec->SetSpeed(m_speed); } else if (pMsg->IsType(CDVDMsg::PLAYER_STARTED)) { From c6da2fc1b29fd5ecdccca4a80e0b57c5c0ed9d41 Mon Sep 17 00:00:00 2001 From: davilla Date: Sat, 19 Jan 2013 15:31:10 -0500 Subject: [PATCH 121/180] [aml] implement DVDVideoCodec::SetSpeed for AMLCodec --- .../dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 56 +++++++++++-------- .../dvdplayer/DVDCodecs/Video/AMLCodec.h | 3 +- .../DVDCodecs/Video/DVDVideoCodecAmlogic.cpp | 5 ++ .../DVDCodecs/Video/DVDVideoCodecAmlogic.h | 1 + 4 files changed, 40 insertions(+), 25 deletions(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index 4f1423466565d..1b1be047259bd 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -24,7 +24,6 @@ #include "AMLCodec.h" #include "DynamicDll.h" -#include "Application.h" #include "cores/dvdplayer/DVDClock.h" #include "cores/VideoRenderers/RenderManager.h" #include "settings/Settings.h" @@ -65,6 +64,7 @@ class DllLibamCodecInterface virtual int codec_init_cntl(codec_para_t *pcodec)=0; virtual int codec_poll_cntl(codec_para_t *pcodec)=0; + virtual int codec_set_cntl_mode(codec_para_t *pcodec, unsigned int mode)=0; virtual int codec_set_cntl_avthresh(codec_para_t *pcodec, unsigned int)=0; virtual int codec_set_cntl_syncthresh(codec_para_t *pcodec, unsigned int syncthresh)=0; @@ -96,6 +96,7 @@ class DllLibAmCodec : public DllDynamic, DllLibamCodecInterface DEFINE_METHOD1(int, codec_init_cntl, (codec_para_t *p1)) DEFINE_METHOD1(int, codec_poll_cntl, (codec_para_t *p1)) + DEFINE_METHOD2(int, codec_set_cntl_mode, (codec_para_t *p1, unsigned int p2)) DEFINE_METHOD2(int, codec_set_cntl_avthresh, (codec_para_t *p1, unsigned int p2)) DEFINE_METHOD2(int, codec_set_cntl_syncthresh,(codec_para_t *p1, unsigned int p2)) @@ -120,6 +121,7 @@ class DllLibAmCodec : public DllDynamic, DllLibamCodecInterface RESOLVE_METHOD(codec_init_cntl) RESOLVE_METHOD(codec_poll_cntl) + RESOLVE_METHOD(codec_set_cntl_mode) RESOLVE_METHOD(codec_set_cntl_avthresh) RESOLVE_METHOD(codec_set_cntl_syncthresh) @@ -1454,6 +1456,7 @@ CAMLCodec::~CAMLCodec() bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) { CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder"); + m_speed = DVD_PLAYSPEED_NORMAL; m_1st_pts = 0; m_cur_pts = 0; m_cur_pictcnt = 0; @@ -1702,6 +1705,7 @@ void CAMLCodec::Reset() } // reset some interal vars + m_speed = DVD_PLAYSPEED_NORMAL; m_1st_pts = 0; m_cur_pts = 0; m_cur_pictcnt = 0; @@ -1752,9 +1756,8 @@ int CAMLCodec::Decode(unsigned char *pData, size_t size, double dts, double pts) } // keep hw buffered demux above 1 second - if (GetTimeSize() < 1.0) + if (GetTimeSize() < 1.0 && m_speed == DVD_PLAYSPEED_NORMAL) { - CLog::Log(LOGDEBUG, "CAMLCodec::Decode: GetTimeSize() < 1.0"); return VC_BUFFER; } @@ -1797,6 +1800,32 @@ bool CAMLCodec::GetPicture(DVDVideoPicture *pDvdVideoPicture) return true; } +void CAMLCodec::SetSpeed(int speed) +{ + CLog::Log(LOGDEBUG, "CAMLCodec::SetSpeed, speed(%d)", speed); + if (m_speed != speed) + { + switch(speed) + { + case DVD_PLAYSPEED_PAUSE: + m_dll->codec_pause(&am_private->vcodec); + m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE); + break; + case DVD_PLAYSPEED_NORMAL: + m_dll->codec_resume(&am_private->vcodec); + m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE); + break; + defaut: + Reset(); + m_dll->codec_resume(&am_private->vcodec); + m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_I); + //m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_FFFB); + break; + } + } + m_speed = speed; +} + int CAMLCodec::GetDataSize() { struct buf_status vbuf ={0}; @@ -1847,14 +1876,6 @@ void CAMLCodec::Process() Sleep(10); } - if (g_application.m_pPlayer && g_application.m_pPlayer->IsPlaying()) - { - if (g_application.m_pPlayer->IsPaused()) - PauseResume(1); - else - PauseResume(2); - } - pts_video = get_pts_video(); if (m_cur_pts != pts_video) { @@ -1886,19 +1907,6 @@ void CAMLCodec::Process() CLog::Log(LOGDEBUG, "CAMLCodec::Process Stopped"); } -void CAMLCodec::PauseResume(int state) -{ - static int saved_state = -1; - if (saved_state == state) - return; - - saved_state = state; - if (saved_state == 1) - m_dll->codec_pause(&am_private->vcodec); - else - m_dll->codec_resume(&am_private->vcodec); -} - double CAMLCodec::GetPlayerPtsSeconds() { double clock_pts = 0.0; diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.h index 37f4a9b4030f2..e0e293a7efd71 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.h +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.h @@ -43,6 +43,7 @@ class CAMLCodec : public CThread int Decode(unsigned char *pData, size_t size, double dts, double pts); bool GetPicture(DVDVideoPicture* pDvdVideoPicture); + void SetSpeed(int speed); int GetDataSize(); double GetTimeSize(); @@ -50,7 +51,6 @@ class CAMLCodec : public CThread virtual void Process(); private: - void PauseResume(int state); double GetPlayerPtsSeconds(); void SetVideoPtsSeconds(double pts); void ShowMainVideo(const bool show); @@ -65,6 +65,7 @@ class CAMLCodec : public CThread DllLibAmCodec *m_dll; am_private_t *am_private; + volatile int m_speed; volatile int64_t m_1st_pts; volatile int64_t m_cur_pts; volatile int64_t m_cur_pictcnt; diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp index 45776aed1bfcf..ff9478b020525 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp @@ -179,6 +179,11 @@ void CDVDVideoCodecAmlogic::SetDropState(bool bDrop) { } +void CDVDVideoCodecAmlogic::SetSpeed(int iSpeed) +{ + m_Codec->SetSpeed(iSpeed); +} + int CDVDVideoCodecAmlogic::GetDataSize(void) { return m_Codec->GetDataSize(); diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h index d372634dfc52e..300f9f671b6cf 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h @@ -37,6 +37,7 @@ class CDVDVideoCodecAmlogic : public CDVDVideoCodec virtual int Decode(BYTE *pData, int iSize, double dts, double pts); virtual void Reset(void); virtual bool GetPicture(DVDVideoPicture *pDvdVideoPicture); + virtual void SetSpeed(int iSpeed); virtual void SetDropState(bool bDrop); virtual int GetDataSize(void); virtual double GetTimeSize(void); From 1150684673b79f241492eda5b59bac209cdc0f83 Mon Sep 17 00:00:00 2001 From: davilla Date: Sun, 20 Jan 2013 21:19:51 -0500 Subject: [PATCH 122/180] fixed amlplayer borks from merge --- xbmc/cores/amlplayer/AMLPlayer.cpp | 48 +++++++++++++----------------- xbmc/cores/amlplayer/AMLPlayer.h | 1 - 2 files changed, 20 insertions(+), 29 deletions(-) diff --git a/xbmc/cores/amlplayer/AMLPlayer.cpp b/xbmc/cores/amlplayer/AMLPlayer.cpp index 27d6310568edc..d3ec710a5ab2f 100644 --- a/xbmc/cores/amlplayer/AMLPlayer.cpp +++ b/xbmc/cores/amlplayer/AMLPlayer.cpp @@ -28,6 +28,7 @@ #include "video/VideoThumbLoader.h" #include "Util.h" #include "cores/AudioEngine/AEFactory.h" +#include "cores/AudioEngine/Utils/AEUtil.h" #include "cores/VideoRenderers/RenderFlags.h" #include "cores/VideoRenderers/RenderFormats.h" #include "cores/VideoRenderers/RenderManager.h" @@ -592,7 +593,6 @@ bool CAMLPlayer::OpenFile(const CFileItem &file, const CPlayerOptions &options) m_subtitle_delay = 0; m_subtitle_thread = NULL; - m_chapter_index = 0; m_chapter_count = 0; m_show_mainvideo = -1; @@ -813,7 +813,6 @@ float CAMLPlayer::GetPercentage() void CAMLPlayer::SetMute(bool bOnOff) { m_audio_mute = bOnOff; -#if !defined(TARGET_ANDROID) CSingleLock lock(m_aml_csection); if (m_dll->check_pid_valid(m_pid)) { @@ -822,11 +821,12 @@ void CAMLPlayer::SetMute(bool bOnOff) else m_dll->audio_set_volume(m_pid, m_audio_volume); } -#endif } void CAMLPlayer::SetVolume(float volume) { + CLog::Log(LOGDEBUG, "CAMLPlayer::SetVolume(%f)", volume); + // volume is a float percent from 0.0 to 1.0 m_audio_volume = 0.0f; if (volume > VOLUME_MINIMUM) { @@ -836,11 +836,9 @@ void CAMLPlayer::SetVolume(float volume) if (m_audio_volume >= 0.99f) m_audio_volume = 1.0f; -#if !defined(TARGET_ANDROID) CSingleLock lock(m_aml_csection); if (!m_audio_mute && m_dll->check_pid_valid(m_pid)) m_dll->audio_set_volume(m_pid, m_audio_volume); -#endif } void CAMLPlayer::GetAudioInfo(CStdString &strAudioInfo) @@ -1083,14 +1081,16 @@ int CAMLPlayer::GetChapterCount() int CAMLPlayer::GetChapter() { + // returns a one based value or zero if no chapters GetStatus(); - for (int i = 0; i < m_chapter_count - 1; i++) + int chapter_index = -1; + for (int i = 0; i < m_chapter_count; i++) { - if (m_elapsed_ms >= m_chapters[i]->seekto_ms && m_elapsed_ms < m_chapters[i + 1]->seekto_ms) - return i + 1; + if (m_elapsed_ms >= m_chapters[i]->seekto_ms) + chapter_index = i; } - return 0; + return chapter_index + 1; } void CAMLPlayer::GetChapterName(CStdString& strChapterName) @@ -1553,7 +1553,7 @@ void CAMLPlayer::Process() // restore system volume setting. SetVolume(g_settings.m_fVolumeLevel); - // the default staturation is to high, drop it + // the default staturation is too high, drop it SetVideoSaturation(110); // drop CGUIDialogBusy dialog and release the hold in OpenFile. @@ -1874,8 +1874,8 @@ bool CAMLPlayer::WaitForStopped(int timeout_ms) switch(pstatus) { default: - usleep(100 * 1000); - timeout_ms -= 100; + usleep(20 * 1000); + timeout_ms -= 20; break; case PLAYER_PLAYEND: case PLAYER_STOPED: @@ -1900,8 +1900,8 @@ bool CAMLPlayer::WaitForSearchOK(int timeout_ms) switch(pstatus) { default: - usleep(100 * 1000); - timeout_ms -= 100; + usleep(20 * 1000); + timeout_ms -= 20; break; case PLAYER_STOPED: return false; @@ -1925,19 +1925,17 @@ bool CAMLPlayer::WaitForPlaying(int timeout_ms) m_audio_mute = true; while (!m_bAbortRequest && (timeout_ms > 0)) { -#if !defined(TARGET_ANDROID) // anoying that we have to hammer audio_set_volume // but have to catch it before any audio comes out. m_dll->audio_set_volume(m_pid, 0.0); -#endif player_status pstatus = (player_status)GetPlayerSerializedState(); if (m_log_level > 5) CLog::Log(LOGDEBUG, "CAMLPlayer::WaitForPlaying: %s", m_dll->player_status2str(pstatus)); switch(pstatus) { default: - usleep(100 * 1000); - timeout_ms -= 100; + usleep(20 * 1000); + timeout_ms -= 20; break; case PLAYER_ERROR: case PLAYER_EXIT: @@ -1963,8 +1961,8 @@ bool CAMLPlayer::WaitForFormatValid(int timeout_ms) switch(pstatus) { default: - usleep(100 * 1000); - timeout_ms -= 100; + usleep(20 * 1000); + timeout_ms -= 20; break; case PLAYER_ERROR: case PLAYER_EXIT: @@ -1992,11 +1990,7 @@ bool CAMLPlayer::WaitForFormatValid(int timeout_ms) media_info.stream_info.cur_video_index, media_info.stream_info.cur_audio_index, media_info.stream_info.cur_sub_index, -#if !defined(TARGET_ANDROID) media_info.stream_info.total_chapter_num); -#else - 0); -#endif } // video info @@ -2053,10 +2047,9 @@ bool CAMLPlayer::WaitForFormatValid(int timeout_ms) info->bit_rate = media_info.audio_info[i]->bit_rate; info->duration = media_info.audio_info[i]->duration; info->format = media_info.audio_info[i]->aformat; -#if !defined(TARGET_ANDROID) if (media_info.audio_info[i]->audio_language[0] != 0) info->language = std::string(media_info.audio_info[i]->audio_language, 3); -#endif + m_audio_streams.push_back(info); } @@ -2091,7 +2084,6 @@ bool CAMLPlayer::WaitForFormatValid(int timeout_ms) if (m_subtitle_count && m_subtitle_index != 0) m_subtitle_index = 0; -#if !defined(TARGET_ANDROID) // chapter info if (media_info.stream_info.total_chapter_num > 0) { @@ -2108,7 +2100,7 @@ bool CAMLPlayer::WaitForFormatValid(int timeout_ms) } } } -#endif + return true; break; } diff --git a/xbmc/cores/amlplayer/AMLPlayer.h b/xbmc/cores/amlplayer/AMLPlayer.h index a24c858a10116..d7aaec8a7774b 100644 --- a/xbmc/cores/amlplayer/AMLPlayer.h +++ b/xbmc/cores/amlplayer/AMLPlayer.h @@ -238,7 +238,6 @@ class CAMLPlayer : public IPlayer, public CThread CDVDPlayerSubtitle *m_dvdPlayerSubtitle; CDVDOverlayContainer *m_dvdOverlayContainer; - int m_chapter_index; int m_chapter_count; int m_show_mainvideo; From da9057a7af5930e6bd34acd0e81b3629311f681f Mon Sep 17 00:00:00 2001 From: davilla Date: Mon, 21 Jan 2013 11:29:04 -0500 Subject: [PATCH 123/180] fixed more softAE borks from merge --- xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp index 6a7fce5ef5877..cedf21205d63c 100644 --- a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp +++ b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp @@ -1434,7 +1434,8 @@ void CSoftAE::ProcessSuspend() } /* idle for platform-defined time */ - m_wake.WaitMSec(SOFTAE_IDLE_WAIT_MSEC); + if (m_playingStreams.empty() && m_playing_sounds.empty()) + m_wake.WaitMSec(SOFTAE_IDLE_WAIT_MSEC); /* check if we need to resume for stream or sound */ if (!m_isSuspended && (!m_playingStreams.empty() || !m_playing_sounds.empty())) From 8303e88b1a0f5f09e9178b40f7163276c7eaecef Mon Sep 17 00:00:00 2001 From: davilla Date: Mon, 21 Jan 2013 11:30:47 -0500 Subject: [PATCH 124/180] [aml] fixed, alsa/kernel lies, so map everything to 44100 or 48000 --- xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp index adbb4c3fa9cf7..a34c5b88961d0 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp @@ -259,7 +259,25 @@ bool CAESinkALSA::InitializeHW(AEAudioFormat &format) snd_pcm_hw_params_set_access(m_pcm, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); unsigned int sampleRate = format.m_sampleRate; +#if defined(HAS_AMLPLAYER) || defined(HAS_LIBAMCODEC) + // alsa/kernel lies, so map everything to 44100 or 48000 + switch(sampleRate) + { + case 11025: + case 22050: + case 88200: + sampleRate = 44100; + break; + case 8000: + case 16000: + case 32000: + case 96000: + sampleRate = 48000; + break; + } +#endif unsigned int channelCount = format.m_channelLayout.Count(); + snd_pcm_hw_params_set_rate_near (m_pcm, hw_params, &sampleRate, NULL); snd_pcm_hw_params_set_channels_near(m_pcm, hw_params, &channelCount); From fa1a46665eb8be0b6e31e24a9e9e45fef09c0516 Mon Sep 17 00:00:00 2001 From: davilla Date: Mon, 21 Jan 2013 11:31:50 -0500 Subject: [PATCH 125/180] [aml] fixed, expand video rate exception to include more '30fps' content --- xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index 1b1be047259bd..19f276b421580 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -1523,12 +1523,15 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) am_private->video_rate = 0.5 + (float)UNIT_FREQ * 1001 / 24000; } - // check for SD h264 content incorrectly reported as 30 fsp + // check for SD h264 content incorrectly reported as some form of 30 fsp // mp4/avi containers :( - if (hints.codec == CODEC_ID_H264 && hints.width <= 720 && am_private->video_rate == 3203) + if (hints.codec == CODEC_ID_H264 && hints.width <= 720) { - CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder video_rate exception"); - am_private->video_rate = 0.5 + (float)UNIT_FREQ * 1001 / 24000; + if (am_private->video_rate >= 3200 && am_private->video_rate <= 3210) + { + CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder video_rate exception"); + am_private->video_rate = 0.5 + (float)UNIT_FREQ * 1001 / 24000; + } } // handle orientation From 59db34072cff28274c9c4726fc051d4b368c9d82 Mon Sep 17 00:00:00 2001 From: davilla Date: Wed, 23 Jan 2013 12:54:52 -0500 Subject: [PATCH 126/180] [aml] 1) fixed video buffer feed when showing still frames, 2) fixed typo (defaut != default) in ff/rw handling --- xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index 19f276b421580..22c6745421cfc 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -1758,14 +1758,21 @@ int CAMLCodec::Decode(unsigned char *pData, size_t size, double dts, double pts) m_1st_pts = am_private->am_pkt.lastpts; } + // if we have still frames, demux size will be small + // and we need to pre-buffer more. + double target_timesize = 1.0; + if (size < 100) + target_timesize = 2.0; + // keep hw buffered demux above 1 second - if (GetTimeSize() < 1.0 && m_speed == DVD_PLAYSPEED_NORMAL) + if (GetTimeSize() < target_timesize && m_speed == DVD_PLAYSPEED_NORMAL) { return VC_BUFFER; } // wait until we get a new frame or 100ms, - m_ready_event.WaitMSec(100); + if (m_old_pictcnt == m_cur_pictcnt) + m_ready_event.WaitMSec(100); // we must return VC_BUFFER or VC_PICTURE, // default to VC_BUFFER. @@ -1818,15 +1825,15 @@ void CAMLCodec::SetSpeed(int speed) m_dll->codec_resume(&am_private->vcodec); m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE); break; - defaut: + default: Reset(); m_dll->codec_resume(&am_private->vcodec); m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_I); //m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_FFFB); break; } + m_speed = speed; } - m_speed = speed; } int CAMLCodec::GetDataSize() From 8b243ab37928dd58eba5ede71c79a07892818360 Mon Sep 17 00:00:00 2001 From: davilla Date: Wed, 23 Jan 2013 13:31:51 -0500 Subject: [PATCH 127/180] [aml] add frame rate tracking --- .../DVDCodecs/Video/DVDVideoCodecAmlogic.cpp | 116 +++++++++++++++++- .../DVDCodecs/Video/DVDVideoCodecAmlogic.h | 9 ++ 2 files changed, 124 insertions(+), 1 deletion(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp index ff9478b020525..71edc952782a0 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp @@ -28,9 +28,20 @@ #define __MODULE_NAME__ "DVDVideoCodecAmlogic" +typedef struct pts_queue { + double dts; + double pts; + double sort_time; + struct pts_queue *nextpts; +} pts_queue; + CDVDVideoCodecAmlogic::CDVDVideoCodecAmlogic() : m_Codec(NULL), - m_pFormatName("amcodec") + m_pFormatName("amcodec"), + m_last_pts(0.0), + m_pts_queue(NULL), + m_queue_depth(0), + m_framerate(0.0) { } @@ -149,6 +160,7 @@ int CDVDVideoCodecAmlogic::Decode(BYTE *pData, int iSize, double dts, double pts { // Handle Input, add demuxer packet to input queue, we must accept it or // it will be discarded as DVDPlayerVideo has no concept of "try again". + if (!m_opened) { if (m_Codec && !m_Codec->OpenDecoder(m_hints)) @@ -159,11 +171,17 @@ int CDVDVideoCodecAmlogic::Decode(BYTE *pData, int iSize, double dts, double pts if (m_hints.ptsinvalid) pts = DVD_NOPTS_VALUE; + if (pData) + FrameRateTracking(dts, pts); + return m_Codec->Decode(pData, iSize, dts, pts); } void CDVDVideoCodecAmlogic::Reset(void) { + while (m_queue_depth) + PtsQueuePop(); + m_Codec->Reset(); } @@ -193,3 +211,99 @@ double CDVDVideoCodecAmlogic::GetTimeSize(void) { return m_Codec->GetTimeSize(); } + +void CDVDVideoCodecAmlogic::PtsQueuePop(void) +{ + if (!m_pts_queue || m_queue_depth == 0) + return; + + // pop the top frame off the queue + pts_queue *top_pts = m_pts_queue; + m_pts_queue = top_pts->nextpts; + m_queue_depth--; + + // and release it + free(top_pts); +} + +void CDVDVideoCodecAmlogic::PtsQueuePush(double dts, double pts) +{ + pts_queue *newpts = (pts_queue*)calloc(sizeof(pts_queue), 1); + newpts->dts = dts; + newpts->pts = pts; + // if both dts or pts are good we use those, else use decoder insert time for frame sort + if ((newpts->pts != DVD_NOPTS_VALUE) || (newpts->dts != DVD_NOPTS_VALUE)) + { + // if pts is borked (stupid avi's), use dts for frame sort + if (newpts->pts == DVD_NOPTS_VALUE) + newpts->sort_time = newpts->dts; + else + newpts->sort_time = newpts->pts; + } + pts_queue *queueWalker = m_pts_queue; + if (!queueWalker || (newpts->sort_time < queueWalker->sort_time)) + { + // we have an empty queue, or this frame earlier than the current queue head. + newpts->nextpts = queueWalker; + m_pts_queue = newpts; + } else { + // walk the queue and insert this frame where it belongs in display order. + bool ptrInserted = false; + pts_queue *nextpts = NULL; + // + while (!ptrInserted) + { + nextpts = queueWalker->nextpts; + if (!nextpts || (newpts->sort_time < nextpts->sort_time)) + { + // if the next frame is the tail of the queue, or our new frame is earlier. + newpts->nextpts = nextpts; + queueWalker->nextpts = newpts; + ptrInserted = true; + } + queueWalker = nextpts; + } + } + m_queue_depth++; +} + +void CDVDVideoCodecAmlogic::FrameRateTracking(double dts, double pts) +{ + PtsQueuePush(dts, pts); + + // in case of out-of-order pts + if (m_queue_depth > 16) + { + if (pts == DVD_NOPTS_VALUE) + pts = m_pts_queue->dts; + else + pts = m_pts_queue->pts; + + double duration = pts - m_last_pts; + m_last_pts = pts; + if (duration > 0.0) + { + switch ((int)(0.5 + ((double)DVD_TIME_BASE / duration))) + { + case 60: + // 60, 59.94 -> 60 + m_framerate = 1001.0 / 60000.0; + case 50: + // 50, 49.95 -> 50 + m_framerate = 1001.0 / 50000.0; + case 30: + // 30, 29.97 -> 30 + m_framerate = 1001.0 / 30000.0; + case 25: + // 25, 24.975 -> 25 + m_framerate = 1001.0 / 25000.0; + case 24: + // 24, 23.976 -> 24 + m_framerate = 1001.0 / 24000.0; + break; + } + } + + PtsQueuePop(); + } +} diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h index 300f9f671b6cf..8b24c6c6ed805 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h @@ -24,6 +24,7 @@ #include "DVDStreamInfo.h" class CAMLCodec; +typedef struct pts_queue pts_queue; class CDVDVideoCodecAmlogic : public CDVDVideoCodec { @@ -44,9 +45,17 @@ class CDVDVideoCodecAmlogic : public CDVDVideoCodec virtual const char* GetName(void) { return (const char*)m_pFormatName; } protected: + void PtsQueuePop(void); + void PtsQueuePush(double dts, double pts); + void FrameRateTracking(double dts, double pts); + CAMLCodec *m_Codec; const char *m_pFormatName; DVDVideoPicture m_videobuffer; bool m_opened; CDVDStreamInfo m_hints; + double m_last_pts; + pts_queue *m_pts_queue; + int32_t m_queue_depth; + double m_framerate; }; From b6857a63c232f414d3dd2e1336fac7e8a07fbc2d Mon Sep 17 00:00:00 2001 From: davilla Date: Wed, 23 Jan 2013 16:31:59 -0500 Subject: [PATCH 128/180] [aml] fixed some regressions, 100 bytes is too hi for still frames --- xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index 22c6745421cfc..d961e5090e06c 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -1761,7 +1761,7 @@ int CAMLCodec::Decode(unsigned char *pData, size_t size, double dts, double pts) // if we have still frames, demux size will be small // and we need to pre-buffer more. double target_timesize = 1.0; - if (size < 100) + if (size < 20) target_timesize = 2.0; // keep hw buffered demux above 1 second From d4d94b939c939d58fd3af3182a2cddd48537c2a2 Mon Sep 17 00:00:00 2001 From: davilla Date: Sun, 27 Jan 2013 14:43:07 -0500 Subject: [PATCH 129/180] [aml] fixed playback of video content with 24kHz audio --- xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp index a34c5b88961d0..a936ae0fa8e37 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp @@ -270,6 +270,7 @@ bool CAESinkALSA::InitializeHW(AEAudioFormat &format) break; case 8000: case 16000: + case 24000: case 32000: case 96000: sampleRate = 48000; From af5c26ad0665d12a0b9398fecaeced3204601230 Mon Sep 17 00:00:00 2001 From: Scott Davill Date: Tue, 29 Jan 2013 12:38:17 -0500 Subject: [PATCH 130/180] Revert "[aml] introduce guisettings overrides (v2)" This reverts commit c6e72e87bf1071cd2ea78b9a6375f9e3a718ce53. --- xbmc/settings/AdvancedSettings.cpp | 21 --------------------- xbmc/settings/AdvancedSettings.h | 1 - xbmc/settings/GUISettings.cpp | 21 --------------------- xbmc/settings/GUISettings.h | 3 +-- xbmc/settings/Settings.cpp | 4 +++- 5 files changed, 4 insertions(+), 46 deletions(-) diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp index 3a23a5d884de1..e7c8fb6f644f7 100644 --- a/xbmc/settings/AdvancedSettings.cpp +++ b/xbmc/settings/AdvancedSettings.cpp @@ -319,7 +319,6 @@ void CAdvancedSettings::Initialize() m_airTunesPort = 36666; m_airPlayPort = 36667; m_initialized = true; - m_settingsHidden.clear(); m_databaseMusic.Reset(); m_databaseVideo.Reset(); @@ -926,26 +925,6 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file) } } - TiXmlElement* pHideSettings = pRootElement->FirstChildElement("hidesettings"); - if (pHideSettings) - { - m_settingsHidden.clear(); - CLog::Log(LOGDEBUG,"Configuring hidden settings"); - TiXmlNode* pSetting = pHideSettings->FirstChildElement("setting"); - CStdString hiddenSetting; - while (pSetting) - { - hiddenSetting = pSetting->FirstChild()->Value(); - if (!hiddenSetting.IsEmpty()) - { - CLog::Log(LOGNOTICE,"Hiding: [%s]", hiddenSetting.c_str()); - m_settingsHidden.push_back(hiddenSetting); - } - // get next one - pSetting = pSetting->NextSiblingElement("setting"); - } - } - XMLUtils::GetInt(pRootElement, "remotedelay", m_remoteDelay, 1, 20); XMLUtils::GetFloat(pRootElement, "controllerdeadzone", m_controllerDeadzone, 0.0f, 1.0f); XMLUtils::GetUInt(pRootElement, "fanartres", m_fanartRes, 0, 1080); diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h index fd6c1a4021e0c..4d1c95081947e 100644 --- a/xbmc/settings/AdvancedSettings.h +++ b/xbmc/settings/AdvancedSettings.h @@ -210,7 +210,6 @@ class CAdvancedSettings SETTINGS_TVSHOWLIST m_tvshowEnumRegExps; CStdString m_tvshowMultiPartEnumRegExp; typedef std::vector< std::pair > StringMapping; - CStdStringArray m_settingsHidden; StringMapping m_pathSubstitutions; int m_remoteDelay; ///< \brief number of remote messages to ignore before repeating float m_controllerDeadzone; diff --git a/xbmc/settings/GUISettings.cpp b/xbmc/settings/GUISettings.cpp index c091dae20abe7..dd38263eb7819 100644 --- a/xbmc/settings/GUISettings.cpp +++ b/xbmc/settings/GUISettings.cpp @@ -1335,17 +1335,6 @@ void CGUISettings::GetSettingsGroup(CSettingsCategory* cat, vecSettings &setting } } -bool CGUISettings::CheckHiddenOverride(CSetting *setting) -{ - for (CStdStringArray::iterator i = g_advancedSettings.m_settingsHidden.begin(); - i != g_advancedSettings.m_settingsHidden.end(); i++) - { - if (strncmp(setting->GetSetting(), i->c_str(), i->size()) == 0) - return true; - } - return false; -} - void CGUISettings::LoadXML(TiXmlElement *pRootElement, bool hideSettings /* = false */) { // load our stuff... bool updated = false; @@ -1471,16 +1460,6 @@ void CGUISettings::LoadFromXML(TiXmlElement *pRootElement, mapIter &it, bool adv { CStdStringArray strSplit; StringUtils::SplitString((*it).first, ".", strSplit); - - // Look for 'hidden' entries in as.xml and treat them as Advanced - // Be sure to disable advanced if it's not in the overrides list, else - // it may remain hidden which switching to a profile where it should not be. - - if (CheckHiddenOverride((*it).second)) - (*it).second->SetAdvanced(true); - else - (*it).second->SetAdvanced(false); - if (strSplit.size() > 1) { const TiXmlNode *pChild = pRootElement->FirstChild(strSplit[0].c_str()); diff --git a/xbmc/settings/GUISettings.h b/xbmc/settings/GUISettings.h index d85106ca6a536..a2893c01802b8 100644 --- a/xbmc/settings/GUISettings.h +++ b/xbmc/settings/GUISettings.h @@ -252,7 +252,7 @@ class CSetting int GetLabel() const { return m_iLabel; }; int GetOrder() const { return m_iOrder; }; void SetOrder(int iOrder) { m_iOrder = iOrder; }; - void SetAdvanced(bool advanced = true) { m_advanced = advanced; }; + void SetAdvanced() { m_advanced = true; }; bool IsAdvanced() const { return m_advanced; }; // A setting might be invisible in the current session, yet carried over // in the config file. @@ -525,7 +525,6 @@ class CGUISettings : public Observable std::map settingsMap; std::vector settingsGroups; void LoadFromXML(TiXmlElement *pRootElement, mapIter &it, bool advanced = false); - bool CheckHiddenOverride(CSetting *setting); }; XBMC_GLOBAL_REF(CGUISettings, g_guiSettings); diff --git a/xbmc/settings/Settings.cpp b/xbmc/settings/Settings.cpp index abea97b219379..76fe784b50f29 100644 --- a/xbmc/settings/Settings.cpp +++ b/xbmc/settings/Settings.cpp @@ -169,7 +169,6 @@ bool CSettings::Reset() bool CSettings::Load() { CSpecialProtocol::SetProfilePath(GetProfileUserDataFolder()); - g_advancedSettings.Load(); CLog::Log(LOGNOTICE, "loading %s", GetSettingsFile().c_str()); if (!LoadSettings(GetSettingsFile())) { @@ -794,6 +793,9 @@ bool CSettings::LoadSettings(const CStdString& strSettingsFile) LoadPlayerCoreFactorySettings("special://xbmc/system/playercorefactory.xml", true); LoadPlayerCoreFactorySettings(GetUserDataItem("playercorefactory.xml"), false); + // Advanced settings + g_advancedSettings.Load(); + // Add the list of disc stub extensions (if any) to the list of video extensions if (!m_discStubExtensions.IsEmpty()) g_settings.m_videoExtensions += "|" + m_discStubExtensions; From 13cd0b669fab4f8752eab7ab4524fc661766b20d Mon Sep 17 00:00:00 2001 From: theuni Date: Fri, 16 Mar 2012 21:41:36 -0400 Subject: [PATCH 131/180] [aml] introduce guisettings overrides This is useful for packagers as they can override menu defaults in as.xml rather than patching xbmc code. Usage example: lookandfeel.soundskin videoplayer.rendermethod --- xbmc/Application.cpp | 3 ++- xbmc/settings/AdvancedSettings.cpp | 24 ++++++++++++++++++--- xbmc/settings/AdvancedSettings.h | 1 + xbmc/settings/GUISettings.cpp | 15 +++++++++++++ xbmc/settings/GUISettings.h | 1 + xbmc/settings/GUIWindowSettingsCategory.cpp | 1 + xbmc/settings/Settings.cpp | 3 --- 7 files changed, 41 insertions(+), 7 deletions(-) diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp index e945bf8a1e07c..851ca6b2ddedc 100644 --- a/xbmc/Application.cpp +++ b/xbmc/Application.cpp @@ -679,7 +679,8 @@ bool CApplication::Create() } CLog::Log(LOGNOTICE, "load settings..."); - + g_advancedSettings.Initialize(); + g_advancedSettings.Load(); g_guiSettings.Initialize(); // Initialize default Settings - don't move g_powerManager.SetDefaults(); if (!g_settings.Load()) diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp index e7c8fb6f644f7..c51f1e538d637 100644 --- a/xbmc/settings/AdvancedSettings.cpp +++ b/xbmc/settings/AdvancedSettings.cpp @@ -332,6 +332,7 @@ bool CAdvancedSettings::Load() // it should instead use the versions of GetString/Integer/Float that // don't take defaults in. Defaults are set in the constructor above Initialize(); // In case of profile switch. + CSpecialProtocol::SetProfilePath(g_settings.GetUserDataFolder()); ParseSettingsFile("special://xbmc/system/advancedsettings.xml"); for (unsigned int i = 0; i < m_settingsFiles.size(); i++) ParseSettingsFile(m_settingsFiles[i]); @@ -925,6 +926,26 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file) } } + TiXmlElement* pHideSettings = pRootElement->FirstChildElement("hidesettings"); + if (pHideSettings) + { + m_settingsHidden.clear(); + CLog::Log(LOGDEBUG,"Configuring hidden settings"); + TiXmlNode* pSetting = pHideSettings->FirstChildElement("setting"); + CStdString hiddenSetting; + while (pSetting) + { + hiddenSetting = pSetting->FirstChild()->Value(); + if (!hiddenSetting.IsEmpty()) + { + CLog::Log(LOGDEBUG," Hiding: [%s]", hiddenSetting.c_str()); + m_settingsHidden.push_back(hiddenSetting); + } + // get next one + pSetting = pSetting->NextSiblingElement("setting"); + } + } + XMLUtils::GetInt(pRootElement, "remotedelay", m_remoteDelay, 1, 20); XMLUtils::GetFloat(pRootElement, "controllerdeadzone", m_controllerDeadzone, 0.0f, 1.0f); XMLUtils::GetUInt(pRootElement, "fanartres", m_fanartRes, 0, 1080); @@ -1056,9 +1077,6 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file) XMLUtils::GetInt(pElement, "algorithmdirtyregions", m_guiAlgorithmDirtyRegions); XMLUtils::GetInt(pElement, "nofliptimeout", m_guiDirtyRegionNoFlipTimeout); } - - // load in the GUISettings overrides: - g_guiSettings.LoadXML(pRootElement, true); // true to hide the settings we read in } void CAdvancedSettings::Clear() diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h index 4d1c95081947e..fd6c1a4021e0c 100644 --- a/xbmc/settings/AdvancedSettings.h +++ b/xbmc/settings/AdvancedSettings.h @@ -210,6 +210,7 @@ class CAdvancedSettings SETTINGS_TVSHOWLIST m_tvshowEnumRegExps; CStdString m_tvshowMultiPartEnumRegExp; typedef std::vector< std::pair > StringMapping; + CStdStringArray m_settingsHidden; StringMapping m_pathSubstitutions; int m_remoteDelay; ///< \brief number of remote messages to ignore before repeating float m_controllerDeadzone; diff --git a/xbmc/settings/GUISettings.cpp b/xbmc/settings/GUISettings.cpp index dd38263eb7819..d1e398b7a8d86 100644 --- a/xbmc/settings/GUISettings.cpp +++ b/xbmc/settings/GUISettings.cpp @@ -1308,6 +1308,10 @@ void CGUISettings::GetSettingsGroup(CSettingsCategory* cat, vecSettings &setting vecSettings unorderedSettings; for (unsigned int index = 0; index < cat->m_settings.size(); index++) { + // filter out hidden settings + if (CheckHiddenOverride(cat->m_settings.at(index))) + continue; + if (!cat->m_settings.at(index)->IsAdvanced()) unorderedSettings.push_back(cat->m_settings.at(index)); } @@ -1335,6 +1339,17 @@ void CGUISettings::GetSettingsGroup(CSettingsCategory* cat, vecSettings &setting } } +bool CGUISettings::CheckHiddenOverride(CSetting *setting) +{ + for (CStdStringArray::iterator i = g_advancedSettings.m_settingsHidden.begin(); + i != g_advancedSettings.m_settingsHidden.end(); i++) + { + if (strncmp(setting->GetSetting(), i->c_str(), i->size()) == 0) + return true; + } + return false; +} + void CGUISettings::LoadXML(TiXmlElement *pRootElement, bool hideSettings /* = false */) { // load our stuff... bool updated = false; diff --git a/xbmc/settings/GUISettings.h b/xbmc/settings/GUISettings.h index a2893c01802b8..77f286b3ea037 100644 --- a/xbmc/settings/GUISettings.h +++ b/xbmc/settings/GUISettings.h @@ -504,6 +504,7 @@ class CGUISettings : public Observable CSetting *GetSetting(const char *strSetting); void GetSettingsGroup(CSettingsCategory* cat, vecSettings &settings); + bool CheckHiddenOverride(CSetting *setting); void LoadXML(TiXmlElement *pRootElement, bool hideSettings = false); void SaveXML(TiXmlNode *pRootNode); void LoadMasterLock(TiXmlElement *pRootElement); diff --git a/xbmc/settings/GUIWindowSettingsCategory.cpp b/xbmc/settings/GUIWindowSettingsCategory.cpp index 5d68f5f123f77..ac09b7b13b92b 100644 --- a/xbmc/settings/GUIWindowSettingsCategory.cpp +++ b/xbmc/settings/GUIWindowSettingsCategory.cpp @@ -586,6 +586,7 @@ void CGUIWindowSettingsCategory::UpdateSettings() BaseSettingControlPtr pSettingControl = m_vecSettings[i]; pSettingControl->Update(); CStdString strSetting = pSettingControl->GetSetting()->GetSetting(); + #ifdef HAVE_LIBVDPAU if (strSetting.Equals("videoplayer.vdpauUpscalingLevel")) { diff --git a/xbmc/settings/Settings.cpp b/xbmc/settings/Settings.cpp index 76fe784b50f29..a3d339b34b7f9 100644 --- a/xbmc/settings/Settings.cpp +++ b/xbmc/settings/Settings.cpp @@ -793,9 +793,6 @@ bool CSettings::LoadSettings(const CStdString& strSettingsFile) LoadPlayerCoreFactorySettings("special://xbmc/system/playercorefactory.xml", true); LoadPlayerCoreFactorySettings(GetUserDataItem("playercorefactory.xml"), false); - // Advanced settings - g_advancedSettings.Load(); - // Add the list of disc stub extensions (if any) to the list of video extensions if (!m_discStubExtensions.IsEmpty()) g_settings.m_videoExtensions += "|" + m_discStubExtensions; From 5f6a9a7b855288ba62d77e094f1765d7a15dd33c Mon Sep 17 00:00:00 2001 From: davilla Date: Wed, 30 Jan 2013 12:35:36 -0500 Subject: [PATCH 132/180] [aml] fixed wifi detect under jellybean --- xbmc/network/linux/PosixConnection.cpp | 2 +- xbmc/network/linux/PosixNetworkManager.cpp | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/xbmc/network/linux/PosixConnection.cpp b/xbmc/network/linux/PosixConnection.cpp index 42493ce37d1e7..03e618683559b 100644 --- a/xbmc/network/linux/PosixConnection.cpp +++ b/xbmc/network/linux/PosixConnection.cpp @@ -339,6 +339,7 @@ ConnectionState CPosixConnection::GetState() const if (ioctl(m_socket, SIOCGIWNAME, &wrq) < 0) return NETWORK_CONNECTION_STATE_DISCONNECTED; +#if !defined(TARGET_ANDROID) // since the wifi interface can be connected to // any wifi access point, we need to compare the assigned // essid to our connection essid. If they match, then @@ -354,7 +355,6 @@ ConnectionState CPosixConnection::GetState() const if (wrq.u.essid.length <= 0) return NETWORK_CONNECTION_STATE_DISCONNECTED; -#if !defined(TARGET_ANDROID) std::string test_essid(essid, wrq.u.essid.length); // Since Android cannot SIOCSIWSCAN (permissions error), // m_essid was defaulted to 'Wifi'. So ignore this check. diff --git a/xbmc/network/linux/PosixNetworkManager.cpp b/xbmc/network/linux/PosixNetworkManager.cpp index ef629c0da8df2..26496c5de9db2 100644 --- a/xbmc/network/linux/PosixNetworkManager.cpp +++ b/xbmc/network/linux/PosixNetworkManager.cpp @@ -231,6 +231,13 @@ void CPosixNetworkManager::FindNetworkInterfaces() n = strcspn(interfaceName, ": \t"); interfaceName[n] = 0; +#if defined(TARGET_ANDROID) + // only test ethX and wlanX interfaces, + // anything else is non-standard and we do not care about it. + if (strncmp(interfaceName, "eth", 3) != 0 && strncmp(interfaceName, "wlan", 4) != 0) + continue; +#endif + // make sure the device has ethernet encapsulation struct ifreq ifr; memset(&ifr, 0x00, sizeof(ifr)); @@ -275,6 +282,11 @@ void CPosixNetworkManager::FindNetworkInterfaces() ifr.ifr_hwaddr.sa_data[2], ifr.ifr_hwaddr.sa_data[3], ifr.ifr_hwaddr.sa_data[4], ifr.ifr_hwaddr.sa_data[5]); } + /* + CLog::Log(LOGDEBUG, "CPosixNetworkManager::FindNetworkInterfaces, " + "interfaceName(%s), macaddress(%s), essid(%s)", + interfaceName, macaddress, essid.c_str()); + */ m_connections.push_back(CConnectionPtr(new CPosixConnection(managed, m_socket, interfaceName, macaddress, essid.c_str(), connection, encryption, 100))); } From 0cce565116d6aa33de8446229b1b31480faddccb Mon Sep 17 00:00:00 2001 From: davilla Date: Fri, 1 Feb 2013 07:33:05 -0500 Subject: [PATCH 133/180] [aml] fixed network WakeOnLan --- xbmc/network/INetworkManager.h | 2 + xbmc/network/NetworkManager.cpp | 113 +-------------------- xbmc/network/NetworkUtils.cpp | 57 +++++++++++ xbmc/network/NetworkUtils.h | 2 + xbmc/network/linux/PosixNetworkManager.cpp | 63 +++++++++++- xbmc/network/linux/PosixNetworkManager.h | 1 + 6 files changed, 125 insertions(+), 113 deletions(-) diff --git a/xbmc/network/INetworkManager.h b/xbmc/network/INetworkManager.h index 6666e40f2836f..fafb459e2450d 100644 --- a/xbmc/network/INetworkManager.h +++ b/xbmc/network/INetworkManager.h @@ -63,4 +63,6 @@ class INetworkManager virtual ConnectionList GetConnections() = 0; virtual bool PumpNetworkEvents(INetworkEventsCallback *callback) = 0; + + virtual bool SendWakeOnLan(const char *mac) {return false;}; }; diff --git a/xbmc/network/NetworkManager.cpp b/xbmc/network/NetworkManager.cpp index 2abebc50fde40..02b2d55a45e56 100644 --- a/xbmc/network/NetworkManager.cpp +++ b/xbmc/network/NetworkManager.cpp @@ -34,63 +34,6 @@ #include "utils/log.h" #include "utils/RssReader.h" -/* slightly modified in_ether taken from the etherboot project (http://sourceforge.net/projects/etherboot) */ -bool in_ether(const char *bufp, unsigned char *addr) -{ - if (strlen(bufp) != 17) - return false; - - char c; - const char *orig; - unsigned char *ptr = addr; - unsigned val; - - int i = 0; - orig = bufp; - - while ((*bufp != '\0') && (i < 6)) - { - val = 0; - c = *bufp++; - - if (isdigit(c)) - val = c - '0'; - else if (c >= 'a' && c <= 'f') - val = c - 'a' + 10; - else if (c >= 'A' && c <= 'F') - val = c - 'A' + 10; - else - return false; - - val <<= 4; - c = *bufp; - if (isdigit(c)) - val |= c - '0'; - else if (c >= 'a' && c <= 'f') - val |= c - 'a' + 10; - else if (c >= 'A' && c <= 'F') - val |= c - 'A' + 10; - else if (c == ':' || c == '-' || c == 0) - val >>= 4; - else - return false; - - if (c != 0) - bufp++; - - *ptr++ = (unsigned char) (val & 0377); - i++; - - if (*bufp == ':' || *bufp == '-') - bufp++; - } - - if (bufp - orig != 17) - return false; - - return true; -} - //----------------------------------------------------------------------- //----------------------------------------------------------------------- CNetworkManager::CNetworkManager() @@ -292,61 +235,7 @@ void CNetworkManager::NetworkMessage(EMESSAGE message, int param) bool CNetworkManager::WakeOnLan(const char *mac) { -/* - int i, j, packet; - unsigned char ethaddr[8]; - unsigned char buf [128]; - unsigned char *ptr; - - // Fetch the hardware address - if (!in_ether(mac, ethaddr)) - { - CLog::Log(LOGERROR, "%s - Invalid hardware address specified (%s)", __FUNCTION__, mac); - return false; - } - - // Setup the socket - if ((packet = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) - { - CLog::Log(LOGERROR, "%s - Unable to create socket (%s)", __FUNCTION__, strerror (errno)); - return false; - } - - // Set socket options - struct sockaddr_in saddr; - saddr.sin_family = AF_INET; - saddr.sin_addr.s_addr = htonl(INADDR_BROADCAST); - saddr.sin_port = htons(9); - - unsigned int value = 1; - if (setsockopt(packet, SOL_SOCKET, SO_BROADCAST, (char*) &value, sizeof( unsigned int ) ) == SOCKET_ERROR) - { - CLog::Log(LOGERROR, "%s - Unable to set socket options (%s)", __FUNCTION__, strerror (errno)); - closesocket(packet); - return false; - } - - // Build the magic packet (6 x 0xff + 16 x MAC address) - ptr = buf; - for (i = 0; i < 6; i++) - *ptr++ = 0xff; - - for (j = 0; j < 16; j++) - for (i = 0; i < 6; i++) - *ptr++ = ethaddr[i]; - - // Send the magic packet - if (sendto(packet, (char *)buf, 102, 0, (struct sockaddr *)&saddr, sizeof (saddr)) < 0) - { - CLog::Log(LOGERROR, "%s - Unable to send magic packet (%s)", __FUNCTION__, strerror (errno)); - closesocket(packet); - return false; - } - - closesocket(packet); - CLog::Log(LOGINFO, "%s - Magic packet send to '%s'", __FUNCTION__, mac); -*/ - return true; + return m_instance->SendWakeOnLan(mac); } void CNetworkManager::StartServices() diff --git a/xbmc/network/NetworkUtils.cpp b/xbmc/network/NetworkUtils.cpp index ba3a6c236513e..f77737d6170e0 100644 --- a/xbmc/network/NetworkUtils.cpp +++ b/xbmc/network/NetworkUtils.cpp @@ -29,3 +29,60 @@ std::string CNetworkUtils::IPTotring(unsigned int ip) std::string returnString = buffer; return returnString; } + +// slightly modified in_ether taken from the etherboot project (http://sourceforge.net/projects/etherboot) +bool CNetworkUtils::in_ether(const char *bufp, unsigned char *addr) +{ + if (strlen(bufp) != 17) + return false; + + char c; + const char *orig; + unsigned char *ptr = addr; + unsigned val; + + int i = 0; + orig = bufp; + + while ((*bufp != '\0') && (i < 6)) + { + val = 0; + c = *bufp++; + + if (isdigit(c)) + val = c - '0'; + else if (c >= 'a' && c <= 'f') + val = c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + val = c - 'A' + 10; + else + return false; + + val <<= 4; + c = *bufp; + if (isdigit(c)) + val |= c - '0'; + else if (c >= 'a' && c <= 'f') + val |= c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + val |= c - 'A' + 10; + else if (c == ':' || c == '-' || c == 0) + val >>= 4; + else + return false; + + if (c != 0) + bufp++; + + *ptr++ = (unsigned char) (val & 0377); + i++; + + if (*bufp == ':' || *bufp == '-') + bufp++; + } + + if (bufp - orig != 17) + return false; + + return true; +} diff --git a/xbmc/network/NetworkUtils.h b/xbmc/network/NetworkUtils.h index e9d5fbf85ccfe..bad4f4eafdd62 100644 --- a/xbmc/network/NetworkUtils.h +++ b/xbmc/network/NetworkUtils.h @@ -26,4 +26,6 @@ class CNetworkUtils { public: static std::string IPTotring(unsigned int ip); + static bool in_ether(const char *bufp, unsigned char *addr); + }; diff --git a/xbmc/network/linux/PosixNetworkManager.cpp b/xbmc/network/linux/PosixNetworkManager.cpp index 26496c5de9db2..95bb63e4b9831 100644 --- a/xbmc/network/linux/PosixNetworkManager.cpp +++ b/xbmc/network/linux/PosixNetworkManager.cpp @@ -25,10 +25,11 @@ #include "guilib/Key.h" #include "guilib/GUIWindowManager.h" #include "guilib/LocalizeStrings.h" +#include "network/NetworkUtils.h" +#include "settings/AdvancedSettings.h" #include "settings/GUISettings.h" #include "threads/Thread.h" #include "utils/log.h" -#include "settings/AdvancedSettings.h" #include #include @@ -36,6 +37,7 @@ #include #include #include +#include #if defined(TARGET_ANDROID) #include "android/bionic_supplement/bionic_supplement.h" @@ -162,6 +164,65 @@ bool CPosixNetworkManager::PumpNetworkEvents(INetworkEventsCallback *callback) return result; } +bool CPosixNetworkManager::SendWakeOnLan(const char *mac) +{ + // Fetch the hardware address + unsigned char ethaddr[8] = {0}; + if (!CNetworkUtils::in_ether(mac, ethaddr)) + { + CLog::Log(LOGERROR, "%s - Invalid hardware address specified (%s)", __FUNCTION__, mac); + return false; + } + + // Setup the socket + int packet = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (packet < 0) + { + CLog::Log(LOGERROR, "%s - Unable to create socket (%s)", __FUNCTION__, strerror (errno)); + return false; + } + + // Set socket options + struct sockaddr_in saddr = {0}; + saddr.sin_family = AF_INET; + saddr.sin_addr.s_addr = htonl(INADDR_BROADCAST); + saddr.sin_port = htons(9); + + unsigned int value = 1; + if (setsockopt(packet, SOL_SOCKET, SO_BROADCAST, (char*)&value, sizeof(unsigned int)) == SOCKET_ERROR) + { + CLog::Log(LOGERROR, "%s - Unable to set socket options (%s)", __FUNCTION__, strerror (errno)); + closesocket(packet); + return false; + } + + // Build the magic packet (6 x 0xff + 16 x MAC address) + unsigned char buf[128] = {0}; + unsigned char *ptr = buf; + + for (int i = 0; i < 6; i++) + *ptr++ = 0xff; + + for (int j = 0; j < 16; j++) + { + for (int i = 0; i < 6; i++) + *ptr++ = ethaddr[i]; + } + + // Send the magic packet + if (sendto(packet, (char*)buf, 102, 0, (struct sockaddr*)&saddr, sizeof(saddr)) < 0) + { + CLog::Log(LOGERROR, "%s - Unable to send magic packet (%s)", __FUNCTION__, strerror (errno)); + closesocket(packet); + return false; + } + + closesocket(packet); + CLog::Log(LOGINFO, "%s - Magic packet send to '%s'", __FUNCTION__, mac); + + return true; +} + //----------------------------------------------------------------------- void CPosixNetworkManager::RestoreSavedConnection() { diff --git a/xbmc/network/linux/PosixNetworkManager.h b/xbmc/network/linux/PosixNetworkManager.h index 387adf6ea207b..a3ab34cb6f520 100644 --- a/xbmc/network/linux/PosixNetworkManager.h +++ b/xbmc/network/linux/PosixNetworkManager.h @@ -33,6 +33,7 @@ class CPosixNetworkManager : public INetworkManager virtual ConnectionList GetConnections(); virtual bool PumpNetworkEvents(INetworkEventsCallback *callback); + virtual bool SendWakeOnLan(const char *mac); private: void RestoreSavedConnection(); void RestoreSystemConnection(); From 030461be7822da7cdd48fd55ee823a7262d6d982 Mon Sep 17 00:00:00 2001 From: davilla Date: Fri, 1 Feb 2013 07:42:59 -0500 Subject: [PATCH 134/180] [aml] fixed compile under linux --- xbmc/network/NetworkUtils.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/xbmc/network/NetworkUtils.cpp b/xbmc/network/NetworkUtils.cpp index f77737d6170e0..810533d41ae28 100644 --- a/xbmc/network/NetworkUtils.cpp +++ b/xbmc/network/NetworkUtils.cpp @@ -21,6 +21,7 @@ #include "NetworkUtils.h" #include +#include std::string CNetworkUtils::IPTotring(unsigned int ip) { From 931366e14d95467f4f7557943ae739d6d0e077df Mon Sep 17 00:00:00 2001 From: davilla Date: Sat, 2 Feb 2013 06:25:23 -0500 Subject: [PATCH 135/180] [aml] fixed displayed video fps --- xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index d961e5090e06c..c78350654912c 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -1805,7 +1805,7 @@ bool CAMLCodec::GetPicture(DVDVideoPicture *pDvdVideoPicture) pDvdVideoPicture->pts = GetPlayerPtsSeconds() * (double)DVD_TIME_BASE; // video pts cannot be late or dvdplayer goes nuts, // so run it one frame ahead - pDvdVideoPicture->pts += 2 * pDvdVideoPicture->iDuration; + pDvdVideoPicture->pts += 1 * pDvdVideoPicture->iDuration; return true; } From 6af124385f0b04dbe9ae5e133ea16457fa9c0650 Mon Sep 17 00:00:00 2001 From: davilla Date: Sat, 2 Feb 2013 07:51:11 -0500 Subject: [PATCH 136/180] Revert "[aml] Changed, give android an additional 100ms audio latency" This reverts commit 70057ce66dc31e92c84883332e4dda655f47a9f1. --- xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp index 825d39a274969..1357e3ed0e4b9 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp @@ -172,7 +172,7 @@ double CAESinkAUDIOTRACK::GetDelay() // AudioMixer (if any) and audio hardware driver. double sinkbuffer_seconds_to_empty = m_sinkbuffer_sec_per_byte * (double)m_sinkbuffer->GetReadSize(); - return 0.100 + sinkbuffer_seconds_to_empty + m_audiotrack_empty_sec; + return sinkbuffer_seconds_to_empty + m_audiotrack_empty_sec; } double CAESinkAUDIOTRACK::GetCacheTime() From 106006bf9dd97f0a002a41b8c0abedb4df49bd4c Mon Sep 17 00:00:00 2001 From: davilla Date: Sat, 2 Feb 2013 10:24:17 -0500 Subject: [PATCH 137/180] [aml] fixed wmv playback --- xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index c78350654912c..c69f59d927222 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -1627,8 +1627,6 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) } break; case VFORMAT_VC1: - // vc1 is extension id, from 0xfd55 to 0xfd5f according to ffmpeg - am_private->vcodec.video_pid = am_private->vcodec.video_pid >> 8; // vc1 in an avi file if (hints.ptsinvalid) am_private->vcodec.am_sysinfo.param = (void*)EXTERNAL_PTS; @@ -1653,11 +1651,7 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) aml_set_sysfs_int("/sys/class/tsync/enable", 0); am_private->am_pkt.codec = &am_private->vcodec; - if (!(am_private->video_format == VFORMAT_VC1 && - am_private->video_codec_type == VIDEO_DEC_FORMAT_WMV3)) - { - pre_header_feeding(am_private, &am_private->am_pkt); - } + pre_header_feeding(am_private, &am_private->am_pkt); Create(); @@ -1700,12 +1694,7 @@ void CAMLCodec::Reset() am_packet_release(&am_private->am_pkt); am_packet_init(&am_private->am_pkt); am_private->am_pkt.codec = &am_private->vcodec; - - if (!(am_private->video_format == VFORMAT_VC1 && - am_private->video_codec_type == VIDEO_DEC_FORMAT_WMV3)) - { - pre_header_feeding(am_private, &am_private->am_pkt); - } + pre_header_feeding(am_private, &am_private->am_pkt); // reset some interal vars m_speed = DVD_PLAYSPEED_NORMAL; From ff8ddfd80a3343b49cd232afac2aacbf83d9d5ae Mon Sep 17 00:00:00 2001 From: davilla Date: Sun, 3 Feb 2013 08:16:02 -0500 Subject: [PATCH 138/180] [aml] fixed rmvb playback, setting volume too early on m1 can bork playback --- xbmc/cores/amlplayer/AMLPlayer.cpp | 49 ++++++++++++++++-------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/xbmc/cores/amlplayer/AMLPlayer.cpp b/xbmc/cores/amlplayer/AMLPlayer.cpp index d3ec710a5ab2f..c2bffaf0e6080 100644 --- a/xbmc/cores/amlplayer/AMLPlayer.cpp +++ b/xbmc/cores/amlplayer/AMLPlayer.cpp @@ -59,6 +59,20 @@ #include "utils/AMLUtils.h" #include "DllLibamplayer.h" +static float VolumePercentToScale(float volume) +{ + float audio_volume = 0.0; + if (volume > VOLUME_MINIMUM) + { + float dB = CAEUtil::PercentToGain(volume); + audio_volume = CAEUtil::GainToScale(dB); + } + if (audio_volume >= 0.99f) + audio_volume = 1.0f; + + return audio_volume; +} + struct AMLChapterInfo { std::string name; @@ -576,11 +590,14 @@ bool CAMLPlayer::OpenFile(const CFileItem &file, const CPlayerOptions &options) m_item = file; m_options = options; + m_pid = -1; m_elapsed_ms = 0; m_duration_ms = 0; m_audio_info = "none"; m_audio_delay = 0; + m_audio_mute = g_settings.m_bMute; + m_audio_volume = VolumePercentToScale(g_settings.m_fVolumeLevel); m_audio_passthrough_ac3 = g_guiSettings.GetBool("audiooutput.ac3passthrough"); m_audio_passthrough_dts = g_guiSettings.GetBool("audiooutput.dtspassthrough"); @@ -813,6 +830,7 @@ float CAMLPlayer::GetPercentage() void CAMLPlayer::SetMute(bool bOnOff) { m_audio_mute = bOnOff; + CSingleLock lock(m_aml_csection); if (m_dll->check_pid_valid(m_pid)) { @@ -825,16 +843,8 @@ void CAMLPlayer::SetMute(bool bOnOff) void CAMLPlayer::SetVolume(float volume) { - CLog::Log(LOGDEBUG, "CAMLPlayer::SetVolume(%f)", volume); // volume is a float percent from 0.0 to 1.0 - m_audio_volume = 0.0f; - if (volume > VOLUME_MINIMUM) - { - float dB = CAEUtil::PercentToGain(volume); - m_audio_volume = CAEUtil::GainToScale(dB); - } - if (m_audio_volume >= 0.99f) - m_audio_volume = 1.0f; + m_audio_volume = VolumePercentToScale(volume); CSingleLock lock(m_aml_csection); if (!m_audio_mute && m_dll->check_pid_valid(m_pid)) @@ -1163,8 +1173,6 @@ void CAMLPlayer::SeekTime(int64_t seek_ms) m_dll->player_timesearch(m_pid, (float)seek_ms/1000.0); WaitForSearchOK(5000); WaitForPlaying(5000); - // restore system volume setting. - SetVolume(m_audio_volume); } } @@ -1547,12 +1555,6 @@ void CAMLPlayer::Process() // get our initial status. GetStatus(); - // restore mute setting. - SetMute(g_settings.m_bMute); - - // restore system volume setting. - SetVolume(g_settings.m_fVolumeLevel); - // the default staturation is too high, drop it SetVideoSaturation(110); @@ -1921,13 +1923,14 @@ bool CAMLPlayer::WaitForSearchOK(int timeout_ms) bool CAMLPlayer::WaitForPlaying(int timeout_ms) { - // force the volume off in case we are starting muted - m_audio_mute = true; while (!m_bAbortRequest && (timeout_ms > 0)) { - // anoying that we have to hammer audio_set_volume - // but have to catch it before any audio comes out. - m_dll->audio_set_volume(m_pid, 0.0); + // anoying that we have to hammer setting audio volume via mute + // but we have to catch it before any audio comes out. + // we cannot do this for m1 (playback will bork) so trap it out. + if (aml_get_cputype() != 1) + SetMute(m_audio_mute); + player_status pstatus = (player_status)GetPlayerSerializedState(); if (m_log_level > 5) CLog::Log(LOGDEBUG, "CAMLPlayer::WaitForPlaying: %s", m_dll->player_status2str(pstatus)); @@ -1943,6 +1946,8 @@ bool CAMLPlayer::WaitForPlaying(int timeout_ms) return false; break; case PLAYER_RUNNING: + // restore mute/volume settings + SetMute(m_audio_mute); return true; break; } From e55bb988413a0f9c32b7c3f1f6505940799a77a2 Mon Sep 17 00:00:00 2001 From: toys4me Date: Wed, 6 Feb 2013 10:19:52 -0800 Subject: [PATCH 139/180] Force Interface List and Accesspoint List refresh on call to CPosixNetworkManager:GetConnection This should fix two Problems 1) Under normal conditions XBMC never refreshes its list of network interfaces once it start running. So if you plug in a USB network adapter (wireless, wired or tcp over bluetooth) xbmc doesn't see it. 2) XBMC won't refresh the list of access points, strengths, etc "if" you already have an existing connection to something. Seems that XBMC never refreshes the list of access points or its list of network interfaces after application starts unless there is a connection state change. This means if you reposition your access point, change channel on AP, or change encryption type its not reflected in interface display in XBMC. Current model for updating the m_connection is all event driven, but doesn't refresh list unless connection state changes. This patch causes FindNetworkInterfaces to be called each time GetConnections is called, which refreshes interface list (in case they changed) and refreshes AP list. This might be a slightly heavy handed way to do it, but can't see any other way to address both problem. --- xbmc/network/linux/PosixNetworkManager.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/xbmc/network/linux/PosixNetworkManager.cpp b/xbmc/network/linux/PosixNetworkManager.cpp index 95bb63e4b9831..882ea85e4562f 100644 --- a/xbmc/network/linux/PosixNetworkManager.cpp +++ b/xbmc/network/linux/PosixNetworkManager.cpp @@ -123,6 +123,11 @@ bool CPosixNetworkManager::CanManageConnections() ConnectionList CPosixNetworkManager::GetConnections() { + FindNetworkInterfaces(); + if (CanManageConnections()) + RestoreSavedConnection(); + else + RestoreSystemConnection(); return m_connections; } From 42bc2e2d973683ad04853b45ea68a849a26711e5 Mon Sep 17 00:00:00 2001 From: davilla Date: Wed, 6 Feb 2013 15:54:52 -0500 Subject: [PATCH 140/180] [aml] fixed, restore 'full stretch' so we can actually stretch --- xbmc/cores/amlplayer/AMLPlayer.cpp | 2 ++ xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/xbmc/cores/amlplayer/AMLPlayer.cpp b/xbmc/cores/amlplayer/AMLPlayer.cpp index c2bffaf0e6080..b9afa0e23a412 100644 --- a/xbmc/cores/amlplayer/AMLPlayer.cpp +++ b/xbmc/cores/amlplayer/AMLPlayer.cpp @@ -2383,6 +2383,8 @@ void CAMLPlayer::SetVideoRect(const CRect &SrcRect, const CRect &DestRect) char video_axis[256] = {0}; sprintf(video_axis, "%d %d %d %d", (int)dst_rect.x1, (int)dst_rect.y1, (int)dst_rect.x2, (int)dst_rect.y2); aml_set_sysfs_str("/sys/class/video/axis", video_axis); + // make sure we are in 'full stretch' so we can stretch + aml_set_sysfs_int("/sys/class/video/screen_mode", 1); /* CStdString rectangle; rectangle.Format("%i,%i,%i,%i", diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index c69f59d927222..37aa60b54f858 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -2048,12 +2048,16 @@ void CAMLCodec::SetVideoRect(const CRect &SrcRect, const CRect &DestRect) char video_axis[256] = {0}; sprintf(video_axis, "%d %d %d %d", (int)dst_rect.x1, (int)dst_rect.y1, (int)dst_rect.x2, (int)dst_rect.y2); aml_set_sysfs_str("/sys/class/video/axis", video_axis); + // make sure we are in 'full stretch' so we can stretch + aml_set_sysfs_int("/sys/class/video/screen_mode", 1); +/* CStdString rectangle; rectangle.Format("%i,%i,%i,%i", (int)dst_rect.x1, (int)dst_rect.y1, (int)dst_rect.Width(), (int)dst_rect.Height()); CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoRect:dst_rect(%s)", rectangle.c_str()); +*/ // we only get called once gui has changed to something // that would show video playback, so show it. From 3656dcbe8369b63b1dbcefb264882a9642544986 Mon Sep 17 00:00:00 2001 From: davilla Date: Wed, 13 Feb 2013 10:37:11 -0500 Subject: [PATCH 141/180] [aml] add CODEC_ID_AVS, CODEC_ID_CAVS --- xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 8 +++++--- .../dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp | 4 ++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index 37aa60b54f858..010f04cbeb162 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -330,9 +330,11 @@ static vformat_t codecid_to_vformat(enum CodecID id) case CODEC_ID_WMV3: format = VFORMAT_VC1; break; - case CODEC_ID_VP6F: - format = VFORMAT_SW; - break; + case CODEC_ID_AVS: + case CODEC_ID_CAVS: + format = VFORMAT_AVS; + break; + default: format = VFORMAT_UNSUPPORT; break; diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp index 71edc952782a0..da344463c839c 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp @@ -90,6 +90,10 @@ bool CDVDVideoCodecAmlogic::Open(CDVDStreamInfo &hints, CDVDCodecOptions &option case CODEC_ID_WMV3: m_pFormatName = "am-wmv3"; break; + case CODEC_ID_AVS: + case CODEC_ID_CAVS: + m_pFormatName = "am-avs"; + break; default: CLog::Log(LOGDEBUG, "%s: Unknown hints.codec(%d", __MODULE_NAME__, hints.codec); return false; From 4b9c64af07fd8177ce7842ab7fc6cfb692320f40 Mon Sep 17 00:00:00 2001 From: davilla Date: Wed, 13 Feb 2013 18:59:58 -0500 Subject: [PATCH 142/180] [aml] temp hack to disable display mode, we have to show display mode to also show refresh rate spiner --- xbmc/settings/GUIWindowSettingsCategory.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/xbmc/settings/GUIWindowSettingsCategory.cpp b/xbmc/settings/GUIWindowSettingsCategory.cpp index ac09b7b13b92b..b10fd6a7e86bb 100644 --- a/xbmc/settings/GUIWindowSettingsCategory.cpp +++ b/xbmc/settings/GUIWindowSettingsCategory.cpp @@ -604,6 +604,14 @@ void CGUIWindowSettingsCategory::UpdateSettings() if (pControl) pControl->SetEnabled(g_guiSettings.GetInt("videoscreen.screen") != DM_WINDOWED); } +#if 1 + else if (strSetting.Equals("videoscreen.screen")) + { + CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); + if (pControl) + pControl->SetEnabled(false); + } +#endif else if (strSetting.Equals("videoscreen.screenmode")) { CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); From 79085bd865bddc84592a3cf0e7fe0083a778ef32 Mon Sep 17 00:00:00 2001 From: davilla Date: Wed, 13 Feb 2013 19:16:53 -0500 Subject: [PATCH 143/180] [aml] fixes nfs debug boot of rootfs --- xbmc/network/linux/PosixNetworkManager.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/xbmc/network/linux/PosixNetworkManager.cpp b/xbmc/network/linux/PosixNetworkManager.cpp index 882ea85e4562f..098cc6ab61a99 100644 --- a/xbmc/network/linux/PosixNetworkManager.cpp +++ b/xbmc/network/linux/PosixNetworkManager.cpp @@ -103,11 +103,6 @@ CPosixNetworkManager::CPosixNetworkManager() CLog::Log(LOGDEBUG, "NetworkManager: PosixNetworkManager created"); m_socket = socket(AF_INET, SOCK_DGRAM, 0); m_post_failed = false; - FindNetworkInterfaces(); - if (CanManageConnections()) - RestoreSavedConnection(); - else - RestoreSystemConnection(); } CPosixNetworkManager::~CPosixNetworkManager() From f3d3c28db7d1385eb8aa522ddf7fab285e65c493 Mon Sep 17 00:00:00 2001 From: davilla Date: Sun, 10 Feb 2013 19:53:55 -0500 Subject: [PATCH 144/180] fixed, CSoftAEStream::GetCacheTime was calculated wrong --- xbmc/cores/AudioEngine/Engines/SoftAE/SoftAEStream.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAEStream.cpp b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAEStream.cpp index b61f46b36e476..1a7fe77de4036 100644 --- a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAEStream.cpp +++ b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAEStream.cpp @@ -496,7 +496,7 @@ double CSoftAEStream::GetCacheTime() double time; time = (double)(m_inputBuffer.Used() / m_format.m_frameSize) / (double)m_format.m_sampleRate; - time += (double)(m_waterLevel - m_framesBuffered) / (double)AE.GetSampleRate(); + time += (double)m_framesBuffered / (double)AE.GetSampleRate(); time += AE.GetCacheTime(); return time; } From c015b7cc4c663f886190dbb44a2e822f45a88458 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 14 Feb 2013 18:14:06 -0500 Subject: [PATCH 145/180] Revert "[aml] introduce guisettings overrides" This reverts commit 13cd0b669fab4f8752eab7ab4524fc661766b20d. --- xbmc/Application.cpp | 3 +-- xbmc/settings/AdvancedSettings.cpp | 24 +++------------------ xbmc/settings/AdvancedSettings.h | 1 - xbmc/settings/GUISettings.cpp | 15 ------------- xbmc/settings/GUISettings.h | 1 - xbmc/settings/GUIWindowSettingsCategory.cpp | 1 - xbmc/settings/Settings.cpp | 3 +++ 7 files changed, 7 insertions(+), 41 deletions(-) diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp index 851ca6b2ddedc..e945bf8a1e07c 100644 --- a/xbmc/Application.cpp +++ b/xbmc/Application.cpp @@ -679,8 +679,7 @@ bool CApplication::Create() } CLog::Log(LOGNOTICE, "load settings..."); - g_advancedSettings.Initialize(); - g_advancedSettings.Load(); + g_guiSettings.Initialize(); // Initialize default Settings - don't move g_powerManager.SetDefaults(); if (!g_settings.Load()) diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp index c51f1e538d637..e7c8fb6f644f7 100644 --- a/xbmc/settings/AdvancedSettings.cpp +++ b/xbmc/settings/AdvancedSettings.cpp @@ -332,7 +332,6 @@ bool CAdvancedSettings::Load() // it should instead use the versions of GetString/Integer/Float that // don't take defaults in. Defaults are set in the constructor above Initialize(); // In case of profile switch. - CSpecialProtocol::SetProfilePath(g_settings.GetUserDataFolder()); ParseSettingsFile("special://xbmc/system/advancedsettings.xml"); for (unsigned int i = 0; i < m_settingsFiles.size(); i++) ParseSettingsFile(m_settingsFiles[i]); @@ -926,26 +925,6 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file) } } - TiXmlElement* pHideSettings = pRootElement->FirstChildElement("hidesettings"); - if (pHideSettings) - { - m_settingsHidden.clear(); - CLog::Log(LOGDEBUG,"Configuring hidden settings"); - TiXmlNode* pSetting = pHideSettings->FirstChildElement("setting"); - CStdString hiddenSetting; - while (pSetting) - { - hiddenSetting = pSetting->FirstChild()->Value(); - if (!hiddenSetting.IsEmpty()) - { - CLog::Log(LOGDEBUG," Hiding: [%s]", hiddenSetting.c_str()); - m_settingsHidden.push_back(hiddenSetting); - } - // get next one - pSetting = pSetting->NextSiblingElement("setting"); - } - } - XMLUtils::GetInt(pRootElement, "remotedelay", m_remoteDelay, 1, 20); XMLUtils::GetFloat(pRootElement, "controllerdeadzone", m_controllerDeadzone, 0.0f, 1.0f); XMLUtils::GetUInt(pRootElement, "fanartres", m_fanartRes, 0, 1080); @@ -1077,6 +1056,9 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file) XMLUtils::GetInt(pElement, "algorithmdirtyregions", m_guiAlgorithmDirtyRegions); XMLUtils::GetInt(pElement, "nofliptimeout", m_guiDirtyRegionNoFlipTimeout); } + + // load in the GUISettings overrides: + g_guiSettings.LoadXML(pRootElement, true); // true to hide the settings we read in } void CAdvancedSettings::Clear() diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h index fd6c1a4021e0c..4d1c95081947e 100644 --- a/xbmc/settings/AdvancedSettings.h +++ b/xbmc/settings/AdvancedSettings.h @@ -210,7 +210,6 @@ class CAdvancedSettings SETTINGS_TVSHOWLIST m_tvshowEnumRegExps; CStdString m_tvshowMultiPartEnumRegExp; typedef std::vector< std::pair > StringMapping; - CStdStringArray m_settingsHidden; StringMapping m_pathSubstitutions; int m_remoteDelay; ///< \brief number of remote messages to ignore before repeating float m_controllerDeadzone; diff --git a/xbmc/settings/GUISettings.cpp b/xbmc/settings/GUISettings.cpp index d1e398b7a8d86..dd38263eb7819 100644 --- a/xbmc/settings/GUISettings.cpp +++ b/xbmc/settings/GUISettings.cpp @@ -1308,10 +1308,6 @@ void CGUISettings::GetSettingsGroup(CSettingsCategory* cat, vecSettings &setting vecSettings unorderedSettings; for (unsigned int index = 0; index < cat->m_settings.size(); index++) { - // filter out hidden settings - if (CheckHiddenOverride(cat->m_settings.at(index))) - continue; - if (!cat->m_settings.at(index)->IsAdvanced()) unorderedSettings.push_back(cat->m_settings.at(index)); } @@ -1339,17 +1335,6 @@ void CGUISettings::GetSettingsGroup(CSettingsCategory* cat, vecSettings &setting } } -bool CGUISettings::CheckHiddenOverride(CSetting *setting) -{ - for (CStdStringArray::iterator i = g_advancedSettings.m_settingsHidden.begin(); - i != g_advancedSettings.m_settingsHidden.end(); i++) - { - if (strncmp(setting->GetSetting(), i->c_str(), i->size()) == 0) - return true; - } - return false; -} - void CGUISettings::LoadXML(TiXmlElement *pRootElement, bool hideSettings /* = false */) { // load our stuff... bool updated = false; diff --git a/xbmc/settings/GUISettings.h b/xbmc/settings/GUISettings.h index 77f286b3ea037..a2893c01802b8 100644 --- a/xbmc/settings/GUISettings.h +++ b/xbmc/settings/GUISettings.h @@ -504,7 +504,6 @@ class CGUISettings : public Observable CSetting *GetSetting(const char *strSetting); void GetSettingsGroup(CSettingsCategory* cat, vecSettings &settings); - bool CheckHiddenOverride(CSetting *setting); void LoadXML(TiXmlElement *pRootElement, bool hideSettings = false); void SaveXML(TiXmlNode *pRootNode); void LoadMasterLock(TiXmlElement *pRootElement); diff --git a/xbmc/settings/GUIWindowSettingsCategory.cpp b/xbmc/settings/GUIWindowSettingsCategory.cpp index b10fd6a7e86bb..fea187946ef77 100644 --- a/xbmc/settings/GUIWindowSettingsCategory.cpp +++ b/xbmc/settings/GUIWindowSettingsCategory.cpp @@ -586,7 +586,6 @@ void CGUIWindowSettingsCategory::UpdateSettings() BaseSettingControlPtr pSettingControl = m_vecSettings[i]; pSettingControl->Update(); CStdString strSetting = pSettingControl->GetSetting()->GetSetting(); - #ifdef HAVE_LIBVDPAU if (strSetting.Equals("videoplayer.vdpauUpscalingLevel")) { diff --git a/xbmc/settings/Settings.cpp b/xbmc/settings/Settings.cpp index a3d339b34b7f9..76fe784b50f29 100644 --- a/xbmc/settings/Settings.cpp +++ b/xbmc/settings/Settings.cpp @@ -793,6 +793,9 @@ bool CSettings::LoadSettings(const CStdString& strSettingsFile) LoadPlayerCoreFactorySettings("special://xbmc/system/playercorefactory.xml", true); LoadPlayerCoreFactorySettings(GetUserDataItem("playercorefactory.xml"), false); + // Advanced settings + g_advancedSettings.Load(); + // Add the list of disc stub extensions (if any) to the list of video extensions if (!m_discStubExtensions.IsEmpty()) g_settings.m_videoExtensions += "|" + m_discStubExtensions; From b5d00b6f918d8013baa35981eeabee8215355efe Mon Sep 17 00:00:00 2001 From: theuni Date: Fri, 16 Mar 2012 21:41:36 -0400 Subject: [PATCH 146/180] [aml] introduce guisettings overrides v3 This is useful for packagers as they can override menu defaults in as.xml rather than patching xbmc code. Usage example: lookandfeel.soundskin videoplayer.rendermethod --- xbmc/settings/AdvancedSettings.cpp | 21 +++++++++++++++++++++ xbmc/settings/AdvancedSettings.h | 1 + xbmc/settings/GUISettings.cpp | 13 ++++++++++++- xbmc/settings/GUISettings.h | 1 + 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp index e7c8fb6f644f7..3a23a5d884de1 100644 --- a/xbmc/settings/AdvancedSettings.cpp +++ b/xbmc/settings/AdvancedSettings.cpp @@ -319,6 +319,7 @@ void CAdvancedSettings::Initialize() m_airTunesPort = 36666; m_airPlayPort = 36667; m_initialized = true; + m_settingsHidden.clear(); m_databaseMusic.Reset(); m_databaseVideo.Reset(); @@ -925,6 +926,26 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file) } } + TiXmlElement* pHideSettings = pRootElement->FirstChildElement("hidesettings"); + if (pHideSettings) + { + m_settingsHidden.clear(); + CLog::Log(LOGDEBUG,"Configuring hidden settings"); + TiXmlNode* pSetting = pHideSettings->FirstChildElement("setting"); + CStdString hiddenSetting; + while (pSetting) + { + hiddenSetting = pSetting->FirstChild()->Value(); + if (!hiddenSetting.IsEmpty()) + { + CLog::Log(LOGNOTICE,"Hiding: [%s]", hiddenSetting.c_str()); + m_settingsHidden.push_back(hiddenSetting); + } + // get next one + pSetting = pSetting->NextSiblingElement("setting"); + } + } + XMLUtils::GetInt(pRootElement, "remotedelay", m_remoteDelay, 1, 20); XMLUtils::GetFloat(pRootElement, "controllerdeadzone", m_controllerDeadzone, 0.0f, 1.0f); XMLUtils::GetUInt(pRootElement, "fanartres", m_fanartRes, 0, 1080); diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h index 4d1c95081947e..fd6c1a4021e0c 100644 --- a/xbmc/settings/AdvancedSettings.h +++ b/xbmc/settings/AdvancedSettings.h @@ -210,6 +210,7 @@ class CAdvancedSettings SETTINGS_TVSHOWLIST m_tvshowEnumRegExps; CStdString m_tvshowMultiPartEnumRegExp; typedef std::vector< std::pair > StringMapping; + CStdStringArray m_settingsHidden; StringMapping m_pathSubstitutions; int m_remoteDelay; ///< \brief number of remote messages to ignore before repeating float m_controllerDeadzone; diff --git a/xbmc/settings/GUISettings.cpp b/xbmc/settings/GUISettings.cpp index dd38263eb7819..e48bfccb3c0ff 100644 --- a/xbmc/settings/GUISettings.cpp +++ b/xbmc/settings/GUISettings.cpp @@ -1308,7 +1308,7 @@ void CGUISettings::GetSettingsGroup(CSettingsCategory* cat, vecSettings &setting vecSettings unorderedSettings; for (unsigned int index = 0; index < cat->m_settings.size(); index++) { - if (!cat->m_settings.at(index)->IsAdvanced()) + if (!cat->m_settings.at(index)->IsAdvanced() && !CheckHiddenOverride(cat->m_settings.at(index))) unorderedSettings.push_back(cat->m_settings.at(index)); } @@ -1335,6 +1335,17 @@ void CGUISettings::GetSettingsGroup(CSettingsCategory* cat, vecSettings &setting } } +bool CGUISettings::CheckHiddenOverride(CSetting *setting) +{ + for (CStdStringArray::iterator i = g_advancedSettings.m_settingsHidden.begin(); + i != g_advancedSettings.m_settingsHidden.end(); i++) + { + if (strncmp(setting->GetSetting(), i->c_str(), i->size()) == 0) + return true; + } + return false; +} + void CGUISettings::LoadXML(TiXmlElement *pRootElement, bool hideSettings /* = false */) { // load our stuff... bool updated = false; diff --git a/xbmc/settings/GUISettings.h b/xbmc/settings/GUISettings.h index a2893c01802b8..585860af4732c 100644 --- a/xbmc/settings/GUISettings.h +++ b/xbmc/settings/GUISettings.h @@ -525,6 +525,7 @@ class CGUISettings : public Observable std::map settingsMap; std::vector settingsGroups; void LoadFromXML(TiXmlElement *pRootElement, mapIter &it, bool advanced = false); + bool CheckHiddenOverride(CSetting *setting); }; XBMC_GLOBAL_REF(CGUISettings, g_guiSettings); From c677cdf39d57d9570af7123af8e02426a8700278 Mon Sep 17 00:00:00 2001 From: davilla Date: Fri, 15 Feb 2013 11:07:05 -0500 Subject: [PATCH 147/180] Revert "[aml] fixed, force system volume to max so passthrough works" This reverts commit e509e31fd3ddb43487bd5624eeb3b6992c809222. --- .../packaging/xbmc/src/org/xbmc/xbmc/Splash.java | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/tools/android/packaging/xbmc/src/org/xbmc/xbmc/Splash.java b/tools/android/packaging/xbmc/src/org/xbmc/xbmc/Splash.java index af7946e1db45d..c008c01361b9a 100644 --- a/tools/android/packaging/xbmc/src/org/xbmc/xbmc/Splash.java +++ b/tools/android/packaging/xbmc/src/org/xbmc/xbmc/Splash.java @@ -28,7 +28,6 @@ import android.view.View; import android.widget.ProgressBar; import android.widget.TextView; -import android.media.AudioManager; public class Splash extends Activity { @@ -203,17 +202,6 @@ protected void onPostExecute(Integer result) { } } - private boolean SetSystemVolumeMax() { - // Set the hardware buttons to control the music - //this.setVolumeControlStream(AudioManager.STREAM_MUSIC); - - AudioManager mAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE); - int max_volume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); - mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, max_volume, 0); - - return true; - } - private boolean ParseCpuFeature() { ProcessBuilder cmd; @@ -243,9 +231,6 @@ private boolean CheckCpuFeature(String feat) { } protected void startXBMC() { - // Set the system volume to max so passthrough works - boolean ret = SetSystemVolumeMax(); - // Run XBMC Intent intent = new Intent(); intent.setClass(this, android.app.NativeActivity.class); @@ -283,7 +268,6 @@ public void onCreate(Bundle savedInstanceState) { mState = State.InError; } } - if (mState != State.InError) { sPackagePath = getPackageResourcePath(); fPackagePath = new File(sPackagePath); From 193cac7ebb4bb1473a2ea9392fb67d17553ea424 Mon Sep 17 00:00:00 2001 From: davilla Date: Fri, 15 Feb 2013 11:42:59 -0500 Subject: [PATCH 148/180] [aml] fix audio issues with SoftAE, temp until Frodo 12.1 comes in --- xbmc/Application.cpp | 12 +- xbmc/android/activity/XBMCApp.cpp | 69 +++++- xbmc/android/activity/XBMCApp.h | 6 +- xbmc/cores/AudioEngine/AEAudioFormat.h | 2 +- xbmc/cores/AudioEngine/AEFactory.cpp | 2 +- xbmc/cores/AudioEngine/AEFactory.h | 2 +- xbmc/cores/AudioEngine/AESinkFactory.cpp | 18 +- xbmc/cores/AudioEngine/AESinkFactory.h | 4 +- .../AudioEngine/Encoders/AEEncoderFFmpeg.cpp | 2 +- .../AudioEngine/Encoders/AEEncoderFFmpeg.h | 2 +- .../AudioEngine/Engines/SoftAE/SoftAE.cpp | 212 +++++++++++++----- .../cores/AudioEngine/Engines/SoftAE/SoftAE.h | 10 +- .../Engines/SoftAE/SoftAESound.cpp | 2 +- .../AudioEngine/Engines/SoftAE/SoftAESound.h | 2 +- .../Engines/SoftAE/SoftAEStream.cpp | 13 +- .../AudioEngine/Engines/SoftAE/SoftAEStream.h | 2 +- xbmc/cores/AudioEngine/Interfaces/AE.h | 2 +- xbmc/cores/AudioEngine/Interfaces/AEEncoder.h | 2 +- xbmc/cores/AudioEngine/Interfaces/AESink.h | 2 +- xbmc/cores/AudioEngine/Interfaces/AESound.h | 2 +- xbmc/cores/AudioEngine/Interfaces/AEStream.h | 2 +- .../cores/AudioEngine/Interfaces/ThreadedAE.h | 2 +- xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 70 +++--- xbmc/cores/AudioEngine/Sinks/AESinkALSA.h | 8 +- .../AudioEngine/Sinks/AESinkAUDIOTRACK.cpp | 22 +- .../AudioEngine/Sinks/AESinkAUDIOTRACK.h | 6 +- .../AudioEngine/Sinks/AESinkDirectSound.cpp | 83 ++++++- .../AudioEngine/Sinks/AESinkDirectSound.h | 5 +- xbmc/cores/AudioEngine/Sinks/AESinkNULL.cpp | 2 +- xbmc/cores/AudioEngine/Sinks/AESinkNULL.h | 2 +- xbmc/cores/AudioEngine/Sinks/AESinkOSS.cpp | 4 +- xbmc/cores/AudioEngine/Sinks/AESinkOSS.h | 4 +- .../AudioEngine/Sinks/AESinkProfiler.cpp | 2 +- xbmc/cores/AudioEngine/Sinks/AESinkProfiler.h | 2 +- xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp | 4 +- xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.h | 6 +- .../AudioEngine/Utils/AEBitstreamPacker.cpp | 2 +- .../AudioEngine/Utils/AEBitstreamPacker.h | 2 +- xbmc/cores/AudioEngine/Utils/AEBuffer.cpp | 2 +- xbmc/cores/AudioEngine/Utils/AEBuffer.h | 2 +- .../cores/AudioEngine/Utils/AEChannelInfo.cpp | 2 +- xbmc/cores/AudioEngine/Utils/AEChannelInfo.h | 2 +- xbmc/cores/AudioEngine/Utils/AEConvert.cpp | 2 +- xbmc/cores/AudioEngine/Utils/AEConvert.h | 2 +- xbmc/cores/AudioEngine/Utils/AEDeviceInfo.cpp | 2 +- xbmc/cores/AudioEngine/Utils/AEDeviceInfo.h | 2 +- xbmc/cores/AudioEngine/Utils/AEELDParser.cpp | 2 +- xbmc/cores/AudioEngine/Utils/AEELDParser.h | 2 +- xbmc/cores/AudioEngine/Utils/AELimiter.cpp | 2 +- xbmc/cores/AudioEngine/Utils/AELimiter.h | 2 +- .../AudioEngine/Utils/AEPackIEC61937.cpp | 2 +- xbmc/cores/AudioEngine/Utils/AEPackIEC61937.h | 2 +- xbmc/cores/AudioEngine/Utils/AERemap.cpp | 2 +- xbmc/cores/AudioEngine/Utils/AERemap.h | 2 +- xbmc/cores/AudioEngine/Utils/AERingBuffer.h | 2 +- xbmc/cores/AudioEngine/Utils/AEStreamInfo.cpp | 2 +- xbmc/cores/AudioEngine/Utils/AEStreamInfo.h | 2 +- xbmc/cores/AudioEngine/Utils/AEUtil.cpp | 2 +- xbmc/cores/AudioEngine/Utils/AEUtil.h | 26 ++- xbmc/cores/AudioEngine/Utils/AEWAVLoader.cpp | 2 +- xbmc/cores/AudioEngine/Utils/AEWAVLoader.h | 2 +- 61 files changed, 471 insertions(+), 195 deletions(-) diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp index e945bf8a1e07c..219d6bdc58c60 100644 --- a/xbmc/Application.cpp +++ b/xbmc/Application.cpp @@ -332,6 +332,10 @@ #include "input/SDLJoystick.h" #endif +#if defined(TARGET_ANDROID) +#include "android/activity/XBMCApp.h" +#endif + using namespace std; using namespace ADDON; using namespace XFILE; @@ -2846,15 +2850,19 @@ bool CApplication::OnAction(const CAction &action) if (g_settings.m_bMute) UnMute(); float volume = g_settings.m_fVolumeLevel; +// Android has steps based on the max available volume level +#if defined(TARGET_ANDROID) + float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / CXBMCApp::GetMaxSystemVolume(); +#else float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / VOLUME_CONTROL_STEPS; + if (action.GetRepeat()) step *= action.GetRepeat() * 50; // 50 fps - +#endif if (action.GetID() == ACTION_VOLUME_UP) volume += (float)fabs(action.GetAmount()) * action.GetAmount() * step; else volume -= (float)fabs(action.GetAmount()) * action.GetAmount() * step; - SetVolume(volume, false); } // show visual feedback of volume change... diff --git a/xbmc/android/activity/XBMCApp.cpp b/xbmc/android/activity/XBMCApp.cpp index 94c777b5a1d5e..608781278febe 100644 --- a/xbmc/android/activity/XBMCApp.cpp +++ b/xbmc/android/activity/XBMCApp.cpp @@ -127,7 +127,6 @@ ActivityResult CXBMCApp::onActivate() default: break; } - return ActivityOK; } @@ -975,3 +974,71 @@ bool CXBMCApp::GetStorageUsage(const std::string &path, std::string &usage) usage = fmt.str(); return true; } + +// Used in Application.cpp to figure out volume steps +int CXBMCApp::GetMaxSystemVolume() +{ + static int maxVolume = -1; + if (maxVolume == -1) + { + JNIEnv *env = NULL; + AttachCurrentThread(&env); + maxVolume = GetMaxSystemVolume(env); + DetachCurrentThread(); + } + return maxVolume; +} + +int CXBMCApp::GetMaxSystemVolume(JNIEnv *env) +{ + jobject oActivity = m_activity->clazz; + jclass cActivity = env->GetObjectClass(oActivity); + + // Get Audio manager + // (AudioManager)getSystemService(Context.AUDIO_SERVICE) + jmethodID mgetSystemService = env->GetMethodID(cActivity, "getSystemService","(Ljava/lang/String;)Ljava/lang/Object;"); + jstring sAudioService = env->NewStringUTF("audio"); + jobject oAudioManager = env->CallObjectMethod(oActivity, mgetSystemService, sAudioService); + env->DeleteLocalRef(sAudioService); + env->DeleteLocalRef(cActivity); + + // Get max volume + // int max_volume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); + jclass cAudioManager = env->GetObjectClass(oAudioManager); + jmethodID mgetStreamMaxVolume = env->GetMethodID(cAudioManager, "getStreamMaxVolume", "(I)I"); + jfieldID fstreamMusic = env->GetStaticFieldID(cAudioManager, "STREAM_MUSIC", "I"); + jint stream_music = env->GetStaticIntField(cAudioManager, fstreamMusic); + int maxVolume = (int)env->CallObjectMethod(oAudioManager, mgetStreamMaxVolume, stream_music); // AudioManager.STREAM_MUSIC + + env->DeleteLocalRef(oAudioManager); + env->DeleteLocalRef(cAudioManager); + + return maxVolume; +} + +void CXBMCApp::SetSystemVolume(JNIEnv *env, float percent) +{ + CLog::Log(LOGDEBUG, "CXBMCApp::SetSystemVolume: %f", percent); + + jobject oActivity = m_activity->clazz; + jclass cActivity = env->GetObjectClass(oActivity); + + // Get Audio manager + // (AudioManager)getSystemService(Context.AUDIO_SERVICE) + jmethodID mgetSystemService = env->GetMethodID(cActivity, "getSystemService","(Ljava/lang/String;)Ljava/lang/Object;"); + jstring sAudioService = env->NewStringUTF("audio"); + jobject oAudioManager = env->CallObjectMethod(oActivity, mgetSystemService, sAudioService); + jclass cAudioManager = env->GetObjectClass(oAudioManager); + env->DeleteLocalRef(sAudioService); + env->DeleteLocalRef(cActivity); + + // Set volume + // mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, max_volume, 0); + jfieldID fstreamMusic = env->GetStaticFieldID(cAudioManager, "STREAM_MUSIC", "I"); + jint stream_music = env->GetStaticIntField(cAudioManager, fstreamMusic); + jmethodID msetStreamVolume = env->GetMethodID(cAudioManager, "setStreamVolume", "(III)V"); + env->CallObjectMethod(oAudioManager, msetStreamVolume, stream_music, int(GetMaxSystemVolume(env)*percent), 0); + env->DeleteLocalRef(oAudioManager); + env->DeleteLocalRef(cAudioManager); +} + diff --git a/xbmc/android/activity/XBMCApp.h b/xbmc/android/activity/XBMCApp.h index 4bf2d2e6a5231..c620966db3cb7 100644 --- a/xbmc/android/activity/XBMCApp.h +++ b/xbmc/android/activity/XBMCApp.h @@ -87,6 +87,7 @@ class CXBMCApp : public IActivityHandler static bool ListApplications(std::vector *applications); static bool GetIconSize(const std::string &packageName, int *width, int *height); static bool GetIcon(const std::string &packageName, void* buffer, unsigned int bufSize); + /*! * \brief If external storage is available, it returns the path for the external storage (for the specified type) * \param path will contain the path of the external storage (for the specified type) @@ -95,6 +96,7 @@ class CXBMCApp : public IActivityHandler */ static bool GetExternalStorage(std::string &path, const std::string &type = ""); static bool GetStorageUsage(const std::string &path, std::string &usage); + static int GetMaxSystemVolume(); static int GetDPI(); protected: @@ -106,6 +108,9 @@ class CXBMCApp : public IActivityHandler static int AttachCurrentThread(JNIEnv** p_env, void* thr_args = NULL); static int DetachCurrentThread(); + static int GetMaxSystemVolume(JNIEnv *env); + static void SetSystemVolume(JNIEnv *env, float percent); + private: static bool HasLaunchIntent(const std::string &package); bool getWakeLock(JNIEnv *env); @@ -116,7 +121,6 @@ class CXBMCApp : public IActivityHandler static ANativeActivity *m_activity; jobject m_wakeLock; - typedef enum { // XBMC_Initialize hasn't been executed yet Uninitialized, diff --git a/xbmc/cores/AudioEngine/AEAudioFormat.h b/xbmc/cores/AudioEngine/AEAudioFormat.h index 11d2d29dc5f2e..5a9053f9fe7a4 100644 --- a/xbmc/cores/AudioEngine/AEAudioFormat.h +++ b/xbmc/cores/AudioEngine/AEAudioFormat.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/AEFactory.cpp b/xbmc/cores/AudioEngine/AEFactory.cpp index 86392c1fff01c..f0b4177901acf 100644 --- a/xbmc/cores/AudioEngine/AEFactory.cpp +++ b/xbmc/cores/AudioEngine/AEFactory.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/AEFactory.h b/xbmc/cores/AudioEngine/AEFactory.h index 3c296efa9e7b3..99cdebd10c354 100644 --- a/xbmc/cores/AudioEngine/AEFactory.h +++ b/xbmc/cores/AudioEngine/AEFactory.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/AESinkFactory.cpp b/xbmc/cores/AudioEngine/AESinkFactory.cpp index b066ecd30e1a9..41e2298566c10 100644 --- a/xbmc/cores/AudioEngine/AESinkFactory.cpp +++ b/xbmc/cores/AudioEngine/AESinkFactory.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify @@ -129,28 +129,28 @@ IAESink *CAESinkFactory::Create(std::string &device, AEAudioFormat &desiredForma return NULL; } -#define ENUMERATE_SINK(SINK) { \ +#define ENUMERATE_SINK(SINK, force) { \ AESinkInfo info; \ info.m_sinkName = #SINK; \ - CAESink ##SINK::EnumerateDevicesEx(info.m_deviceInfoList); \ + CAESink ##SINK::EnumerateDevicesEx(info.m_deviceInfoList, force); \ if(!info.m_deviceInfoList.empty()) \ list.push_back(info); \ } -void CAESinkFactory::EnumerateEx(AESinkInfoList &list) +void CAESinkFactory::EnumerateEx(AESinkInfoList &list, bool force) { #if defined(TARGET_WINDOWS) - ENUMERATE_SINK(DirectSound); + ENUMERATE_SINK(DirectSound, force); if (g_sysinfo.IsVistaOrHigher() && !g_advancedSettings.m_audioForceDirectSound) - ENUMERATE_SINK(WASAPI); + ENUMERATE_SINK(WASAPI, force); #elif defined(TARGET_ANDROID) - ENUMERATE_SINK(AUDIOTRACK); + ENUMERATE_SINK(AUDIOTRACK, force); #elif defined(TARGET_LINUX) || defined(TARGET_FREEBSD) #if defined(HAS_ALSA) - ENUMERATE_SINK(ALSA); + ENUMERATE_SINK(ALSA, force); #endif - ENUMERATE_SINK(OSS); + ENUMERATE_SINK(OSS, force); #endif } diff --git a/xbmc/cores/AudioEngine/AESinkFactory.h b/xbmc/cores/AudioEngine/AESinkFactory.h index 99c53f9be2244..5444d2ca86e98 100644 --- a/xbmc/cores/AudioEngine/AESinkFactory.h +++ b/xbmc/cores/AudioEngine/AESinkFactory.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify @@ -40,6 +40,6 @@ class CAESinkFactory public: static void ParseDevice(std::string &device, std::string &driver); static IAESink *Create(std::string &device, AEAudioFormat &desiredFormat, bool rawPassthrough); - static void EnumerateEx(AESinkInfoList &list); + static void EnumerateEx(AESinkInfoList &list, bool force = false); /* The force flag can be used to indicate the rescan devices */ }; diff --git a/xbmc/cores/AudioEngine/Encoders/AEEncoderFFmpeg.cpp b/xbmc/cores/AudioEngine/Encoders/AEEncoderFFmpeg.cpp index 8ade469d6aa48..c611f15e8f5ac 100644 --- a/xbmc/cores/AudioEngine/Encoders/AEEncoderFFmpeg.cpp +++ b/xbmc/cores/AudioEngine/Encoders/AEEncoderFFmpeg.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Encoders/AEEncoderFFmpeg.h b/xbmc/cores/AudioEngine/Encoders/AEEncoderFFmpeg.h index b69f8c63a1ac5..0cedf3fa8c0af 100644 --- a/xbmc/cores/AudioEngine/Encoders/AEEncoderFFmpeg.h +++ b/xbmc/cores/AudioEngine/Encoders/AEEncoderFFmpeg.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp index cedf21205d63c..c28da7048be62 100644 --- a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp +++ b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify @@ -59,6 +59,7 @@ CSoftAE::CSoftAE(): m_audiophile (true ), m_running (false ), m_reOpen (false ), + m_sinkIsSuspended (false ), m_isSuspended (false ), m_softSuspend (false ), m_softSuspendTimer (0 ), @@ -74,21 +75,18 @@ CSoftAE::CSoftAE(): m_outputStageFn (NULL ), m_streamStageFn (NULL ) { + unsigned int c_retry = 5; CAESinkFactory::EnumerateEx(m_sinkInfoList); - for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt) + while(m_sinkInfoList.size() == 0 && c_retry > 0) { - CLog::Log(LOGNOTICE, "Enumerated %s devices:", itt->m_sinkName.c_str()); - int count = 0; - for (AEDeviceInfoList::iterator itt2 = itt->m_deviceInfoList.begin(); itt2 != itt->m_deviceInfoList.end(); ++itt2) - { - CLog::Log(LOGNOTICE, " Device %d", ++count); - CAEDeviceInfo& info = *itt2; - std::stringstream ss((std::string)info); - std::string line; - while(std::getline(ss, line, '\n')) - CLog::Log(LOGNOTICE, " %s", line.c_str()); - } + CLog::Log(LOGNOTICE, "No Devices found - retry: %d", c_retry); + Sleep(2000); + c_retry--; + // retry the enumeration + CAESinkFactory::EnumerateEx(m_sinkInfoList, true); } + CLog::Log(LOGNOTICE, "Found %lu Lists of Devices", m_sinkInfoList.size()); + PrintSinks(); } CSoftAE::~CSoftAE() @@ -145,7 +143,7 @@ IAESink *CSoftAE::GetSink(AEAudioFormat &newFormat, bool passthrough, std::strin } /* this method MUST be called while holding m_streamLock */ -CSoftAEStream *CSoftAE::GetMasterStream() +inline CSoftAEStream *CSoftAE::GetMasterStream() { /* remove any destroyed streams first */ for (StreamList::iterator itt = m_streams.begin(); itt != m_streams.end();) @@ -179,6 +177,18 @@ void CSoftAE::OpenSink() m_wake.Set(); } +void CSoftAE::InternalCloseSink() +{ + /* close the old sink if it was open */ + if (m_sink) + { + CExclusiveLock sinkLock(m_sinkLock); + m_sink->Drain(); + m_sink->Deinitialize(); + delete m_sink; + m_sink = NULL; + } +} /* this must NEVER be called from outside the main thread or Initialization */ void CSoftAE::InternalOpenSink() { @@ -305,15 +315,8 @@ void CSoftAE::InternalOpenSink() CExclusiveLock sinkLock(m_sinkLock); reInit = true; - - /* we are going to open, so close the old sink if it was open */ - if (m_sink) - { - m_sink->Drain(); - m_sink->Deinitialize(); - delete m_sink; - m_sink = NULL; - } + //close the sink cause it gets reinited + InternalCloseSink(); /* get the display name of the device */ GetDeviceFriendlyName(device); @@ -616,7 +619,7 @@ void CSoftAE::VerifySoundDevice(std::string& device, bool passthrough) device = firstDevice; } -void CSoftAE::GetDeviceFriendlyName(std::string &device) +inline void CSoftAE::GetDeviceFriendlyName(std::string &device) { m_deviceFriendlyName = "Device not found"; /* Match the device and find its friendly name */ @@ -726,7 +729,8 @@ void CSoftAE::PauseStream(CSoftAEStream *stream) stream->m_paused = true; streamLock.Leave(); - OpenSink(); + m_reOpen = true; + m_wake.Set(); } void CSoftAE::ResumeStream(CSoftAEStream *stream) @@ -737,7 +741,8 @@ void CSoftAE::ResumeStream(CSoftAEStream *stream) streamLock.Leave(); m_streamsPlaying = true; - OpenSink(); + m_reOpen = true; + m_wake.Set(); } void CSoftAE::Stop() @@ -774,7 +779,7 @@ IAEStream *CSoftAE::MakeStream(enum AEDataFormat dataFormat, unsigned int sample CSoftAEStream *stream = new CSoftAEStream(dataFormat, sampleRate, encodedSampleRate, channelLayout, options); m_newStreams.push_back(stream); streamLock.Leave(); - + // this is really needed here OpenSink(); return stream; } @@ -866,11 +871,9 @@ IAEStream *CSoftAE::FreeStream(IAEStream *stream) CSingleLock lock(m_streamLock); RemoveStream(m_playingStreams, (CSoftAEStream*)stream); RemoveStream(m_streams , (CSoftAEStream*)stream); - lock.Leave(); - - /* if it was the master stream we need to reopen before deletion */ - if (m_masterStream == stream) - OpenSink(); + // Reopen is old behaviour. Not opening when masterstream stops means clipping on S/PDIF. + if(!m_isSuspended && (m_masterStream == stream)) + m_reOpen = true; delete (CSoftAEStream*)stream; return NULL; @@ -976,14 +979,67 @@ bool CSoftAE::Suspend() CSoftAEStream *stream = *itt; stream->Flush(); } + streamLock.Leave(); + #if defined(TARGET_LINUX) + /*workaround sinks not playing sound after resume */ + StopAllSounds(); + bool ret = true; + if(m_sink) + { + /* Deinitialize and delete current m_sink */ + // we don't want that Run reopens our device, so we wait. + m_saveSuspend.Reset(); + // wait until we are looping in ProcessSuspend() + // this is more save to not come up unclean + // we cannot wait forever + ret = m_saveSuspend.WaitMSec(500); + if(ret) + { + CLog::Log(LOGDEBUG, "CSoftAE::Suspend - After Event"); + CExclusiveLock sinkLock(m_sinkLock); + // remove all the sinks + for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt) + { + itt->m_deviceInfoList.pop_back(); + } + InternalCloseSink(); + } + else + { + CLog::Log(LOGDEBUG, "CSoftAE::Suspend - Unload failed will continue"); + m_saveSuspend.Reset(); + } + } + // The device list is now empty and must be reenumerated afterwards. + if(ret) + m_sinkInfoList.clear(); + + // signal anybody, that we are gone now (beware of deadlocks) + // we don't unset the fields here, to care for reinit after resume + if(m_reOpen) + m_reOpenEvent.Set(); + #endif return true; } bool CSoftAE::Resume() { +#if defined(TARGET_LINUX) + // We must make sure, that we don't return empty. + if(m_sinkInfoList.empty()) + { + CLog::Log(LOGDEBUG, "CSoftAE::Resume - Re Enumerating Sinks"); + CExclusiveLock sinkLock(m_sinkLock); + // Forced enumeration - we are sure that we start completely fresh. + CAESinkFactory::EnumerateEx(m_sinkInfoList, true); + sinkLock.Leave(); // we leave here explicitly to not lock while printing new sinks + PrintSinks(); + } +#endif CLog::Log(LOGDEBUG, "CSoftAE::Resume - Resuming AE processing"); m_isSuspended = false; + // we flag reopen m_reOpen = true; return true; @@ -1000,11 +1056,12 @@ void CSoftAE::Run() { bool restart = false; - if ((this->*m_outputStageFn)(hasAudio) > 0) + /* with the new non blocking implementation - we just reOpen here, when it tells reOpen */ + if (!m_reOpen && (this->*m_outputStageFn)(hasAudio) > 0) hasAudio = false; /* taken some audio - reset our silence flag */ /* if we have enough room in the buffer */ - if (m_buffer.Free() >= m_frameSize) + if (!m_reOpen && m_buffer.Free() >= m_frameSize) { /* take some data for our use from the buffer */ uint8_t *out = (uint8_t*)m_buffer.Take(m_frameSize); @@ -1026,10 +1083,17 @@ void CSoftAE::Run() /* if we are told to restart */ if (m_reOpen || restart || !m_sink) { + if(m_sinkIsSuspended && m_sink) + { + // hint for fritsch: remember lazy evaluation + m_reOpen = !m_sink->SoftResume() || m_reOpen; + m_sinkIsSuspended = false; + CLog::Log(LOGDEBUG, "CSoftAE::Run - Sink was forgotten"); + } CLog::Log(LOGDEBUG, "CSoftAE::Run - Sink restart flagged"); InternalOpenSink(); - m_isSuspended = false; // exit Suspend state } + #if defined(TARGET_ANDROID) else if (m_playingStreams.empty() && m_playing_sounds.empty() @@ -1127,12 +1191,11 @@ bool CSoftAE::FinalizeSamples(float *buffer, unsigned int samples, bool hasAudio /* check if we need to clamp */ bool clamp = false; - float clamp_value, *fbuffer = buffer; + float *fbuffer = buffer; for (unsigned int i = 0; i < samples; i++, fbuffer++) { if (*fbuffer < -1.0f || *fbuffer > 1.0f) { - clamp_value = *fbuffer; clamp = true; break; } @@ -1142,7 +1205,7 @@ bool CSoftAE::FinalizeSamples(float *buffer, unsigned int samples, bool hasAudio if (!clamp) return true; - CLog::Log(LOGDEBUG, "CSoftAE::FinalizeSamples - Clamping buffer of %d samples, clamp value(%f)", samples, clamp_value); + CLog::Log(LOGDEBUG, "CSoftAE::FinalizeSamples - Clamping buffer of %d samples", samples); CAEUtil::ClampArray(buffer, samples); return true; } @@ -1281,12 +1344,29 @@ int CSoftAE::RunTranscodeStage(bool hasAudio) return encodedFrames; } +void CSoftAE::PrintSinks() +{ + for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt) + { + CLog::Log(LOGNOTICE, "Enumerated %s devices:", itt->m_sinkName.c_str()); + int count = 0; + for (AEDeviceInfoList::iterator itt2 = itt->m_deviceInfoList.begin(); itt2 != itt->m_deviceInfoList.end(); ++itt2) + { + CLog::Log(LOGNOTICE, " Device %d", ++count); + CAEDeviceInfo& info = *itt2; + std::stringstream ss((std::string)info); + std::string line; + while(std::getline(ss, line, '\n')) + CLog::Log(LOGNOTICE, " %s", line.c_str()); + } + } +} + unsigned int CSoftAE::RunRawStreamStage(unsigned int channelCount, void *out, bool &restart) { StreamList resumeStreams; static StreamList::iterator itt; CSingleLock streamLock(m_streamLock); - /* handle playing streams */ for (itt = m_playingStreams.begin(); itt != m_playingStreams.end(); ++itt) { @@ -1369,7 +1449,7 @@ unsigned int CSoftAE::RunStreamStage(unsigned int channelCount, void *out, bool return mixed; } -void CSoftAE::ResumeSlaveStreams(const StreamList &streams) +inline void CSoftAE::ResumeSlaveStreams(const StreamList &streams) { if (streams.empty()) return; @@ -1384,7 +1464,7 @@ void CSoftAE::ResumeSlaveStreams(const StreamList &streams) } } -void CSoftAE::RemoveStream(StreamList &streams, CSoftAEStream *stream) +inline void CSoftAE::RemoveStream(StreamList &streams, CSoftAEStream *stream) { StreamList::iterator f = std::find(streams.begin(), streams.end(), stream); if (f != streams.end()) @@ -1394,12 +1474,10 @@ void CSoftAE::RemoveStream(StreamList &streams, CSoftAEStream *stream) m_streamsPlaying = !m_playingStreams.empty(); } -void CSoftAE::ProcessSuspend() +inline void CSoftAE::ProcessSuspend() { - bool sinkIsSuspended = false; unsigned int curSystemClock = 0; - -#if defined(TARGET_WINDOWS) +#if defined(TARGET_WINDOWS) || defined(TARGET_LINUX) if (!m_softSuspend && m_playingStreams.empty() && m_playing_sounds.empty() && !g_advancedSettings.m_streamSilence) { @@ -1411,38 +1489,54 @@ void CSoftAE::ProcessSuspend() if (m_softSuspend) curSystemClock = XbmcThreads::SystemClockMillis(); #endif - /* idle while in Suspend() state until Resume() called */ /* idle if nothing to play and user hasn't enabled */ /* continuous streaming (silent stream) in as.xml */ - while ((m_isSuspended || (m_softSuspend && (curSystemClock > m_softSuspendTimer))) && - m_running && !m_reOpen) + /* In case of Suspend stay in there until Resume is called from outer thread */ + while (m_isSuspended || ((m_softSuspend && (curSystemClock > m_softSuspendTimer)) && + m_running && !m_reOpen)) { - if (m_sink && !sinkIsSuspended) + if (!m_isSuspended && m_sink && !m_sinkIsSuspended) { /* put the sink in Suspend mode */ CExclusiveLock sinkLock(m_sinkLock); - if (!m_sink->SoftSuspend()) + if (m_sink && !m_sink->SoftSuspend()) { - sinkIsSuspended = false; //sink cannot be suspended + m_sinkIsSuspended = false; //sink cannot be suspended m_softSuspend = false; //break suspend loop break; } else - sinkIsSuspended = true; //sink has suspended processing + { + CLog::Log(LOGDEBUG, "Suspended the Sink"); + m_sinkIsSuspended = true; //sink has suspended processing + } sinkLock.Leave(); } + // Signal that the Suspend can go on now. + // Idea: Outer thread calls Suspend() - but + // because of AddPackets does not care about locks, we must make + // sure, that our school bus (AE::Run) is currently driving through + // some gas station, before we move away the sink. + if(m_isSuspended) + m_saveSuspend.Set(); /* idle for platform-defined time */ - if (m_playingStreams.empty() && m_playing_sounds.empty()) - m_wake.WaitMSec(SOFTAE_IDLE_WAIT_MSEC); - - /* check if we need to resume for stream or sound */ + m_wake.WaitMSec(SOFTAE_IDLE_WAIT_MSEC); + + /* check if we need to resume for stream or sound or somebody wants to open us + * the suspend checks are only there to: + * a) not run out of softSuspend directly when we are sleeping + * b) nail(!) the thread during real Suspend into this method + * Note: It is not enough to check the streams buffer, cause it might not be filled yet + * We have to check after ProcessSuspending() if the sink is still in softsleep and resume it + */ if (!m_isSuspended && (!m_playingStreams.empty() || !m_playing_sounds.empty())) { - m_reOpen = !m_sink->SoftResume(); // sink returns false if it requires reinit - sinkIsSuspended = false; //sink processing data - m_softSuspend = false; //break suspend loop + m_reOpen = !m_sink->SoftResume() || m_reOpen; // sink returns false if it requires reinit (worthless with current implementation) + m_sinkIsSuspended = false; //sink processing data + m_softSuspend = false; //break suspend loop (under some conditions) + CLog::Log(LOGDEBUG, "Resumed the Sink"); break; } } diff --git a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h index 0b9d8390b956c..26d5e9c72127e 100644 --- a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h +++ b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify @@ -116,13 +116,14 @@ class CSoftAE : public IThreadedAE void OpenSink(); void InternalOpenSink(); + void InternalCloseSink(); void ResetEncoder(); bool SetupEncoder(AEAudioFormat &format); void Deinitialize(); - void ProcessSuspend(); /* enter suspend state if nothing to play and sink allows */ + inline void ProcessSuspend(); /* enter suspend state if nothing to play and sink allows */ - void GetDeviceFriendlyName(std::string &device); + inline void GetDeviceFriendlyName(std::string &device); IAESink *GetSink(AEAudioFormat &desiredFormat, bool passthrough, std::string &device); void StopAllSounds(); @@ -136,11 +137,13 @@ class CSoftAE : public IThreadedAE /* internal vars */ bool m_running, m_reOpen; + bool m_sinkIsSuspended; /* The sink is in unusable state, e.g. SoftSuspended */ bool m_isSuspended; /* engine suspended by external function to release audio context */ bool m_softSuspend; /* latches after last stream or sound played for timer below for idle */ unsigned int m_softSuspendTimer; /* time in milliseconds to hold sink open before soft suspend for idle */ CEvent m_reOpenEvent; CEvent m_wake; + CEvent m_saveSuspend; CCriticalSection m_runningLock; /* released when the thread exits */ CCriticalSection m_streamLock; /* m_streams lock */ @@ -242,5 +245,6 @@ class CSoftAE : public IThreadedAE void RunNormalizeStage (unsigned int channelCount, void *out, unsigned int mixed); void RemoveStream(StreamList &streams, CSoftAEStream *stream); + void PrintSinks(); }; diff --git a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAESound.cpp b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAESound.cpp index c6d50658c5d42..f9cace57f953a 100644 --- a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAESound.cpp +++ b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAESound.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAESound.h b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAESound.h index 18225880a0f57..cd50c0b47565a 100644 --- a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAESound.h +++ b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAESound.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAEStream.cpp b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAEStream.cpp index 1a7fe77de4036..258dcaca56b7a 100644 --- a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAEStream.cpp +++ b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAEStream.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify @@ -485,7 +485,6 @@ double CSoftAEStream::GetDelay() double delay = AE.GetDelay(); delay += (double)(m_inputBuffer.Used() / m_format.m_frameSize) / (double)m_format.m_sampleRate; delay += (double)m_framesBuffered / (double)AE.GetSampleRate(); - return delay; } @@ -494,10 +493,9 @@ double CSoftAEStream::GetCacheTime() if (m_delete) return 0.0; - double time; - time = (double)(m_inputBuffer.Used() / m_format.m_frameSize) / (double)m_format.m_sampleRate; + double time = AE.GetCacheTime(); + time += (double)(m_inputBuffer.Used() / m_format.m_frameSize) / (double)m_format.m_sampleRate; time += (double)m_framesBuffered / (double)AE.GetSampleRate(); - time += AE.GetCacheTime(); return time; } @@ -506,10 +504,9 @@ double CSoftAEStream::GetCacheTotal() if (m_delete) return 0.0; - double total; - total = (double)(m_inputBuffer.Size() / m_format.m_frameSize) / (double)m_format.m_sampleRate; + double total = AE.GetCacheTotal(); + total += (double)(m_inputBuffer.Size() / m_format.m_frameSize) / (double)m_format.m_sampleRate; total += (double)m_waterLevel / (double)AE.GetSampleRate(); - total += AE.GetCacheTotal(); return total; } diff --git a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAEStream.h b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAEStream.h index 7e93215f9161b..571dc8864747f 100644 --- a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAEStream.h +++ b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAEStream.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Interfaces/AE.h b/xbmc/cores/AudioEngine/Interfaces/AE.h index 0baba37c50c60..cbfa8ed3998e0 100644 --- a/xbmc/cores/AudioEngine/Interfaces/AE.h +++ b/xbmc/cores/AudioEngine/Interfaces/AE.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Interfaces/AEEncoder.h b/xbmc/cores/AudioEngine/Interfaces/AEEncoder.h index 9613d029d7f1c..055f28bef87dc 100644 --- a/xbmc/cores/AudioEngine/Interfaces/AEEncoder.h +++ b/xbmc/cores/AudioEngine/Interfaces/AEEncoder.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Interfaces/AESink.h b/xbmc/cores/AudioEngine/Interfaces/AESink.h index a67b860b41fbe..97ea571015357 100644 --- a/xbmc/cores/AudioEngine/Interfaces/AESink.h +++ b/xbmc/cores/AudioEngine/Interfaces/AESink.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Interfaces/AESound.h b/xbmc/cores/AudioEngine/Interfaces/AESound.h index 100efdbed425e..ebbcc0d7ee8ab 100644 --- a/xbmc/cores/AudioEngine/Interfaces/AESound.h +++ b/xbmc/cores/AudioEngine/Interfaces/AESound.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Interfaces/AEStream.h b/xbmc/cores/AudioEngine/Interfaces/AEStream.h index 060fcb9ebf7bb..67fa5e2a0fb41 100644 --- a/xbmc/cores/AudioEngine/Interfaces/AEStream.h +++ b/xbmc/cores/AudioEngine/Interfaces/AEStream.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Interfaces/ThreadedAE.h b/xbmc/cores/AudioEngine/Interfaces/ThreadedAE.h index 41053291babe0..82e4936b4491a 100644 --- a/xbmc/cores/AudioEngine/Interfaces/ThreadedAE.h +++ b/xbmc/cores/AudioEngine/Interfaces/ThreadedAE.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp index a936ae0fa8e37..2a57d548604de 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify @@ -79,7 +79,7 @@ CAESinkALSA::~CAESinkALSA() Deinitialize(); } -CAEChannelInfo CAESinkALSA::GetChannelLayout(AEAudioFormat format) +inline CAEChannelInfo CAESinkALSA::GetChannelLayout(AEAudioFormat format) { unsigned int count = 0; @@ -278,7 +278,6 @@ bool CAESinkALSA::InitializeHW(AEAudioFormat &format) } #endif unsigned int channelCount = format.m_channelLayout.Count(); - snd_pcm_hw_params_set_rate_near (m_pcm, hw_params, &sampleRate, NULL); snd_pcm_hw_params_set_channels_near(m_pcm, hw_params, &channelCount); @@ -352,7 +351,7 @@ bool CAESinkALSA::InitializeHW(AEAudioFormat &format) snd_pcm_uframes_t periodSize, bufferSize; snd_pcm_hw_params_get_buffer_size_max(hw_params, &bufferSize); - bufferSize = std::max(bufferSize, (snd_pcm_uframes_t)8192); + bufferSize = std::min(bufferSize, (snd_pcm_uframes_t)8192); periodSize = bufferSize / ALSA_PERIODS; periods = ALSA_PERIODS; @@ -445,7 +444,6 @@ void CAESinkALSA::Deinitialize() if (m_pcm) { - snd_pcm_drop (m_pcm); snd_pcm_close(m_pcm); m_pcm = NULL; } @@ -506,7 +504,13 @@ double CAESinkALSA::GetCacheTotal() unsigned int CAESinkALSA::AddPackets(uint8_t *data, unsigned int frames, bool hasAudio) { if (!m_pcm) - return 0; + { + SoftResume(); + if(!m_pcm) + return 0; + + CLog::Log(LOGDEBUG, "CAESinkALSA - the grAEken is hunger, feed it (I am the downmost fallback - fix your code)"); + } int ret; @@ -571,29 +575,6 @@ void CAESinkALSA::HandleError(const char* name, int err) } } -bool CAESinkALSA::SoftSuspend() -{ - /* Sink has been asked to suspend output - we release audio */ - /* device as we are in exclusive mode and thus allow external */ - /* audio sources to play. This requires us to reinitialize */ - /* on resume. */ - CLog::Log(LOGDEBUG, "CAESinkALSA::SoftSuspend"); - - Deinitialize(); - - return true; -} - -bool CAESinkALSA::SoftResume() -{ - /* Sink asked to resume output. To release audio device in */ - /* exclusive mode we release the device context and therefore */ - /* must reinitialize. Return false to force re-init by engine */ - CLog::Log(LOGDEBUG, "CAESinkALSA::SoftResume"); - - return false; -} - void CAESinkALSA::Drain() { if (!m_pcm) @@ -718,12 +699,17 @@ bool CAESinkALSA::OpenPCMDevice(const std::string &name, const std::string ¶ return false; } -void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list) +void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) { /* ensure that ALSA has been initialized */ snd_lib_error_set_handler(sndLibErrorHandler); - if(!snd_config) + if(!snd_config || force) + { + if(force) + snd_config_update_free_global(); + snd_config_update(); + } snd_config_t *config; snd_config_copy(&config, snd_config); @@ -1167,6 +1153,28 @@ bool CAESinkALSA::GetELD(snd_hctl_t *hctl, int device, CAEDeviceInfo& info, bool return true; } +bool CAESinkALSA::SoftSuspend() +{ + if(m_pcm) // it is still there + Deinitialize(); + + return true; +} +bool CAESinkALSA::SoftResume() +{ + // reinit all the clibber + bool ret = true; // all fine + if(!m_pcm) + { + if (!snd_config) + snd_config_update(); + + ret = Initialize(m_initFormat, m_initDevice); + } + //we want that AE loves us again - reinit when initialize failed + return ret; // force reinit if false +} + void CAESinkALSA::sndLibErrorHandler(const char *file, int line, const char *function, int err, const char *fmt, ...) { va_list arg; diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h index 7d4ba71fb8224..fb4efb0329324 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h +++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify @@ -48,11 +48,11 @@ class CAESinkALSA : public IAESink virtual double GetCacheTime (); virtual double GetCacheTotal (); virtual unsigned int AddPackets (uint8_t *data, unsigned int frames, bool hasAudio); - virtual bool SoftSuspend (); - virtual bool SoftResume (); virtual void Drain (); + virtual bool SoftSuspend(); + virtual bool SoftResume(); - static void EnumerateDevicesEx(AEDeviceInfoList &list); + static void EnumerateDevicesEx(AEDeviceInfoList &list, bool force = false); private: CAEChannelInfo GetChannelLayout(AEAudioFormat format); void GetAESParams(const AEAudioFormat format, std::string& params); diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp index 1357e3ed0e4b9..48473e06634c6 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify @@ -238,14 +238,16 @@ bool CAESinkAUDIOTRACK::HasVolume() return true; } -void CAESinkAUDIOTRACK::SetVolume(float volume) +void CAESinkAUDIOTRACK::SetVolume(float scale) { - m_volume = volume; + // Android uses fixed steps, reverse scale back to percent + float gain = CAEUtil::ScaleToGain(scale); + m_volume = CAEUtil::GainToPercent(gain); if (!m_passthrough) - m_volume_changed = true; + m_volume_changed = true; } -void CAESinkAUDIOTRACK::EnumerateDevicesEx(AEDeviceInfoList &list) +void CAESinkAUDIOTRACK::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) { m_info.m_channels.Reset(); m_info.m_dataFormats.clear(); @@ -284,7 +286,6 @@ void CAESinkAUDIOTRACK::Process() jmethodID jmRelease = jenv->GetMethodID(jcAudioTrack, "release", "()V"); jmethodID jmWrite = jenv->GetMethodID(jcAudioTrack, "write", "([BII)I"); jmethodID jmPlayState = jenv->GetMethodID(jcAudioTrack, "getPlayState", "()I"); - jmethodID jmSetStereoVolume = jenv->GetMethodID(jcAudioTrack, "setStereoVolume", "(FF)I"); jmethodID jmPlayHeadPosition = jenv->GetMethodID(jcAudioTrack, "getPlaybackHeadPosition", "()I"); jmethodID jmGetMinBufferSize = jenv->GetStaticMethodID(jcAudioTrack, "getMinBufferSize", "(III)I"); @@ -314,10 +315,10 @@ void CAESinkAUDIOTRACK::Process() GetStaticIntField(jenv, "AudioTrack", "MODE_STREAM")); // Set the initial volume - jfloat jvolume = 1.0; + float volume = 1.0; if (!m_passthrough) - jvolume = m_volume; - jenv->CallIntMethod(joAudioTrack, jmSetStereoVolume, jvolume, jvolume); + volume = m_volume; + CXBMCApp::SetSystemVolume(jenv, volume); // The AudioTrack object has been created and waiting to play, m_inited.Set(); @@ -339,8 +340,7 @@ void CAESinkAUDIOTRACK::Process() { // check of volume changes and make them, // do it here to keep jni calls local to this thread. - jfloat jvolume = m_volume; - jenv->CallIntMethod(joAudioTrack, jmSetStereoVolume, jvolume, jvolume); + CXBMCApp::SetSystemVolume(jenv, m_volume); m_volume_changed = false; } if (m_draining) diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h index b92c812078ddd..901139009be89 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h +++ b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify @@ -42,8 +42,8 @@ class CAESinkAUDIOTRACK : public CThread, public IAESink virtual unsigned int AddPackets (uint8_t *data, unsigned int frames, bool hasAudio); virtual void Drain (); virtual bool HasVolume (); - virtual void SetVolume (float volume); - static void EnumerateDevicesEx(AEDeviceInfoList &list); + virtual void SetVolume (float scale); + static void EnumerateDevicesEx(AEDeviceInfoList &list, bool force = false); private: virtual void Process(); diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp index 4d3d41e205a65..ac58eb685d025 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify @@ -464,7 +464,7 @@ double CAESinkDirectSound::GetCacheTotal() return (double)m_dwBufferLen / (double)m_AvgBytesPerSec; } -void CAESinkDirectSound::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList) +void CAESinkDirectSound::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList, bool force) { CAEDeviceInfo deviceInfo; @@ -603,10 +603,10 @@ void CAESinkDirectSound::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList) if (SUCCEEDED(hr) && varName.blob.cbSize > 0) { WAVEFORMATEX* smpwfxex = (WAVEFORMATEX*)varName.blob.pBlobData; - deviceInfo.m_channels = layoutsByChCount[std::min(smpwfxex->nChannels, (WORD) 2)]; + deviceInfo.m_channels = layoutsByChCount[std::max(std::min(smpwfxex->nChannels, (WORD) 8), (WORD) 2)]; deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_FLOAT)); deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_AC3)); - deviceInfo.m_sampleRates.push_back(std::min(smpwfxex->nSamplesPerSec, (DWORD) 96000)); + deviceInfo.m_sampleRates.push_back(std::min(smpwfxex->nSamplesPerSec, (DWORD) 192000)); } else { @@ -622,12 +622,25 @@ void CAESinkDirectSound::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList) deviceInfo.m_displayNameExtra = std::string("DirectSound: ").append(strFriendlyName); deviceInfo.m_deviceType = aeDeviceType; - /* Now logged by AESinkFactory on startup */ - //CLog::Log(LOGDEBUG,"Audio Device %d: %s", i, ((std::string)deviceInfo).c_str()); - deviceInfoList.push_back(deviceInfo); } + // since AE takes the first device in deviceInfoList as default audio device we need + // to sort it in order to use the real default device + if(deviceInfoList.size() > 1) + { + std::string strDD = GetDefaultDevice(); + for (AEDeviceInfoList::iterator itt = deviceInfoList.begin(); itt != deviceInfoList.end(); ++itt) + { + CAEDeviceInfo devInfo = *itt; + if(devInfo.m_deviceName == strDD) + { + deviceInfoList.erase(itt); + deviceInfoList.insert(deviceInfoList.begin(), devInfo); + } + } + } + return; failed: @@ -825,5 +838,61 @@ const char *CAESinkDirectSound::WASAPIErrToStr(HRESULT err) return NULL; } +std::string CAESinkDirectSound::GetDefaultDevice() +{ + IMMDeviceEnumerator* pEnumerator = NULL; + IMMDevice* pDevice = NULL; + IPropertyStore* pProperty = NULL; + HRESULT hr; + PROPVARIANT varName; + std::string strDevName = "default"; + + hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&pEnumerator); + if (FAILED(hr)) + { + CLog::Log(LOGERROR, __FUNCTION__": Could not allocate WASAPI device enumerator. CoCreateInstance error code: %s", WASAPIErrToStr(hr)); + goto failed; + } + + hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, &pDevice); + if (FAILED(hr)) + { + CLog::Log(LOGERROR, __FUNCTION__": Retrieval of audio endpoint enumeration failed."); + goto failed; + } + + hr = pDevice->OpenPropertyStore(STGM_READ, &pProperty); + if (FAILED(hr)) + { + CLog::Log(LOGERROR, __FUNCTION__": Retrieval of DirectSound endpoint properties failed."); + goto failed; + } + + PropVariantInit(&varName); + hr = pProperty->GetValue(PKEY_AudioEndpoint_FormFactor, &varName); + if (FAILED(hr)) + { + CLog::Log(LOGERROR, __FUNCTION__": Retrieval of DirectSound endpoint form factor failed."); + goto failed; + } + AEDeviceType aeDeviceType = winEndpoints[(EndpointFormFactor)varName.uiVal].aeDeviceType; + PropVariantClear(&varName); + + hr = pProperty->GetValue(PKEY_AudioEndpoint_GUID, &varName); + if (FAILED(hr)) + { + CLog::Log(LOGERROR, __FUNCTION__": Retrieval of DirectSound endpoint GUID failed."); + goto failed; + } + strDevName = localWideToUtf(varName.pwszVal); + PropVariantClear(&varName); +failed: + + SAFE_RELEASE(pProperty); + SAFE_RELEASE(pDevice); + SAFE_RELEASE(pEnumerator); + + return strDevName; +} diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.h b/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.h index 9f54090976588..dbf961862d781 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.h +++ b/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify @@ -43,7 +43,8 @@ class CAESinkDirectSound : public IAESink virtual double GetCacheTime (); virtual double GetCacheTotal (); virtual unsigned int AddPackets (uint8_t *data, unsigned int frames, bool hasAudio); - static void EnumerateDevicesEx (AEDeviceInfoList &deviceInfoList); + static std::string GetDefaultDevice (); + static void EnumerateDevicesEx (AEDeviceInfoList &deviceInfoList, bool force = false); private: void AEChannelsFromSpeakerMask(DWORD speakers); DWORD SpeakerMaskFromAEChannels(const CAEChannelInfo &channels); diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkNULL.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkNULL.cpp index 1468d6aa9f9ce..5f86d34e4e5f8 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkNULL.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkNULL.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkNULL.h b/xbmc/cores/AudioEngine/Sinks/AESinkNULL.h index 67e55d648d98e..e6413fcff6d8e 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkNULL.h +++ b/xbmc/cores/AudioEngine/Sinks/AESinkNULL.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkOSS.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkOSS.cpp index 06b9a7fc4ffc7..1af9912bc27e3 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkOSS.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkOSS.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify @@ -427,7 +427,7 @@ void CAESinkOSS::Drain() // ??? } -void CAESinkOSS::EnumerateDevicesEx(AEDeviceInfoList &list) +void CAESinkOSS::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) { int mixerfd; const char * mixerdev = "/dev/mixer"; diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkOSS.h b/xbmc/cores/AudioEngine/Sinks/AESinkOSS.h index aa8a9f8f9a73f..c8c1179e1e919 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkOSS.h +++ b/xbmc/cores/AudioEngine/Sinks/AESinkOSS.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify @@ -43,7 +43,7 @@ class CAESinkOSS : public IAESink virtual double GetCacheTotal () { return 0.0; } /* FIXME */ virtual unsigned int AddPackets (uint8_t *data, unsigned int frames, bool hasAudio); virtual void Drain (); - static void EnumerateDevicesEx(AEDeviceInfoList &list); + static void EnumerateDevicesEx(AEDeviceInfoList &list, bool force = false); private: int m_fd; std::string m_device; diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkProfiler.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkProfiler.cpp index 200167721e6d2..56af30e60f764 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkProfiler.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkProfiler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkProfiler.h b/xbmc/cores/AudioEngine/Sinks/AESinkProfiler.h index eb4ad0a0f8370..4718406971284 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkProfiler.h +++ b/xbmc/cores/AudioEngine/Sinks/AESinkProfiler.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp index 8475d60f7e847..de5ed0ed2a914 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify @@ -559,7 +559,7 @@ bool CAESinkWASAPI::SoftResume() return false; } -void CAESinkWASAPI::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList) +void CAESinkWASAPI::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList, bool force) { IMMDeviceEnumerator* pEnumerator = NULL; IMMDeviceCollection* pEnumDevices = NULL; diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.h b/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.h index a0c567ae7b17d..c504892b42d2e 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.h +++ b/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.h @@ -1,6 +1,6 @@ #pragma once /* -* Copyright (C) 2010-2012 Team XBMC +* Copyright (C) 2010-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify @@ -45,7 +45,7 @@ class CAESinkWASAPI : public IAESink virtual unsigned int AddPackets (uint8_t *data, unsigned int frames, bool hasAudio); virtual bool SoftSuspend (); virtual bool SoftResume (); - static void EnumerateDevicesEx (AEDeviceInfoList &deviceInfoList); + static void EnumerateDevicesEx (AEDeviceInfoList &deviceInfoList, bool force = false); private: bool InitializeExclusive(AEAudioFormat &format); void AEChannelsFromSpeakerMask(DWORD speakers); @@ -78,4 +78,4 @@ class CAESinkWASAPI : public IAESink unsigned int m_uiBufferLen; /* wasapi endpoint buffer size, in frames */ double m_avgTimeWaiting; /* time between next buffer of data from SoftAE and driver call for data */ double m_sinkLatency; /* time in seconds of total duration of the two WASAPI buffers */ -}; \ No newline at end of file +}; diff --git a/xbmc/cores/AudioEngine/Utils/AEBitstreamPacker.cpp b/xbmc/cores/AudioEngine/Utils/AEBitstreamPacker.cpp index 9eed30a099c2c..e3c790bc23dc2 100644 --- a/xbmc/cores/AudioEngine/Utils/AEBitstreamPacker.cpp +++ b/xbmc/cores/AudioEngine/Utils/AEBitstreamPacker.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Utils/AEBitstreamPacker.h b/xbmc/cores/AudioEngine/Utils/AEBitstreamPacker.h index bc40d57238dc8..69ab06775ea8b 100644 --- a/xbmc/cores/AudioEngine/Utils/AEBitstreamPacker.h +++ b/xbmc/cores/AudioEngine/Utils/AEBitstreamPacker.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Utils/AEBuffer.cpp b/xbmc/cores/AudioEngine/Utils/AEBuffer.cpp index b36f43464d225..a79a6949fc1d9 100644 --- a/xbmc/cores/AudioEngine/Utils/AEBuffer.cpp +++ b/xbmc/cores/AudioEngine/Utils/AEBuffer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Utils/AEBuffer.h b/xbmc/cores/AudioEngine/Utils/AEBuffer.h index aaaa69cfa0dc7..442a698557840 100644 --- a/xbmc/cores/AudioEngine/Utils/AEBuffer.h +++ b/xbmc/cores/AudioEngine/Utils/AEBuffer.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Utils/AEChannelInfo.cpp b/xbmc/cores/AudioEngine/Utils/AEChannelInfo.cpp index 0abfafd681e12..265a33917192c 100644 --- a/xbmc/cores/AudioEngine/Utils/AEChannelInfo.cpp +++ b/xbmc/cores/AudioEngine/Utils/AEChannelInfo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Utils/AEChannelInfo.h b/xbmc/cores/AudioEngine/Utils/AEChannelInfo.h index 1cd47dab53a79..438f085abf19a 100644 --- a/xbmc/cores/AudioEngine/Utils/AEChannelInfo.h +++ b/xbmc/cores/AudioEngine/Utils/AEChannelInfo.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Utils/AEConvert.cpp b/xbmc/cores/AudioEngine/Utils/AEConvert.cpp index 2e4da191c8c50..a4e47552e01a5 100644 --- a/xbmc/cores/AudioEngine/Utils/AEConvert.cpp +++ b/xbmc/cores/AudioEngine/Utils/AEConvert.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Utils/AEConvert.h b/xbmc/cores/AudioEngine/Utils/AEConvert.h index 03764ffa56df3..46472486aafc3 100644 --- a/xbmc/cores/AudioEngine/Utils/AEConvert.h +++ b/xbmc/cores/AudioEngine/Utils/AEConvert.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Utils/AEDeviceInfo.cpp b/xbmc/cores/AudioEngine/Utils/AEDeviceInfo.cpp index 90ab05b738077..b4a5c5ba41bc0 100644 --- a/xbmc/cores/AudioEngine/Utils/AEDeviceInfo.cpp +++ b/xbmc/cores/AudioEngine/Utils/AEDeviceInfo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Team XBMC + * Copyright (C) 2012-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Utils/AEDeviceInfo.h b/xbmc/cores/AudioEngine/Utils/AEDeviceInfo.h index 04784fac30186..2cd80a198a062 100644 --- a/xbmc/cores/AudioEngine/Utils/AEDeviceInfo.h +++ b/xbmc/cores/AudioEngine/Utils/AEDeviceInfo.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2012 Team XBMC + * Copyright (C) 2012-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Utils/AEELDParser.cpp b/xbmc/cores/AudioEngine/Utils/AEELDParser.cpp index da5c6d320b71d..ff9f2c78d53a6 100644 --- a/xbmc/cores/AudioEngine/Utils/AEELDParser.cpp +++ b/xbmc/cores/AudioEngine/Utils/AEELDParser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Team XBMC + * Copyright (C) 2012-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Utils/AEELDParser.h b/xbmc/cores/AudioEngine/Utils/AEELDParser.h index fdbbf1f1dbf40..09984627be5ac 100644 --- a/xbmc/cores/AudioEngine/Utils/AEELDParser.h +++ b/xbmc/cores/AudioEngine/Utils/AEELDParser.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2012 Team XBMC + * Copyright (C) 2012-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Utils/AELimiter.cpp b/xbmc/cores/AudioEngine/Utils/AELimiter.cpp index 1de88bc58aa9c..77af32053239b 100644 --- a/xbmc/cores/AudioEngine/Utils/AELimiter.cpp +++ b/xbmc/cores/AudioEngine/Utils/AELimiter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Utils/AELimiter.h b/xbmc/cores/AudioEngine/Utils/AELimiter.h index decc5f4028c16..ef46d0cbb46b8 100644 --- a/xbmc/cores/AudioEngine/Utils/AELimiter.h +++ b/xbmc/cores/AudioEngine/Utils/AELimiter.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Utils/AEPackIEC61937.cpp b/xbmc/cores/AudioEngine/Utils/AEPackIEC61937.cpp index 27bb343e74c50..9fc0689fed2b7 100644 --- a/xbmc/cores/AudioEngine/Utils/AEPackIEC61937.cpp +++ b/xbmc/cores/AudioEngine/Utils/AEPackIEC61937.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Utils/AEPackIEC61937.h b/xbmc/cores/AudioEngine/Utils/AEPackIEC61937.h index 30918027ca936..97016f65e4940 100644 --- a/xbmc/cores/AudioEngine/Utils/AEPackIEC61937.h +++ b/xbmc/cores/AudioEngine/Utils/AEPackIEC61937.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Utils/AERemap.cpp b/xbmc/cores/AudioEngine/Utils/AERemap.cpp index 6e44bff192826..1e9da80034ea9 100644 --- a/xbmc/cores/AudioEngine/Utils/AERemap.cpp +++ b/xbmc/cores/AudioEngine/Utils/AERemap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Utils/AERemap.h b/xbmc/cores/AudioEngine/Utils/AERemap.h index 49e984b1f242a..1b35e37916896 100644 --- a/xbmc/cores/AudioEngine/Utils/AERemap.h +++ b/xbmc/cores/AudioEngine/Utils/AERemap.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Utils/AERingBuffer.h b/xbmc/cores/AudioEngine/Utils/AERingBuffer.h index b7e18fbe32087..17c9d0ca4ce50 100644 --- a/xbmc/cores/AudioEngine/Utils/AERingBuffer.h +++ b/xbmc/cores/AudioEngine/Utils/AERingBuffer.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Utils/AEStreamInfo.cpp b/xbmc/cores/AudioEngine/Utils/AEStreamInfo.cpp index bfe5f3591ac6f..876f5b6c159f7 100644 --- a/xbmc/cores/AudioEngine/Utils/AEStreamInfo.cpp +++ b/xbmc/cores/AudioEngine/Utils/AEStreamInfo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Utils/AEStreamInfo.h b/xbmc/cores/AudioEngine/Utils/AEStreamInfo.h index c4c06c1f5378f..3c67a375804c3 100644 --- a/xbmc/cores/AudioEngine/Utils/AEStreamInfo.h +++ b/xbmc/cores/AudioEngine/Utils/AEStreamInfo.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Utils/AEUtil.cpp b/xbmc/cores/AudioEngine/Utils/AEUtil.cpp index 4f1b644607c61..6de84dc5d993c 100644 --- a/xbmc/cores/AudioEngine/Utils/AEUtil.cpp +++ b/xbmc/cores/AudioEngine/Utils/AEUtil.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Utils/AEUtil.h b/xbmc/cores/AudioEngine/Utils/AEUtil.h index be52f6321c751..458dc00e39669 100644 --- a/xbmc/cores/AudioEngine/Utils/AEUtil.h +++ b/xbmc/cores/AudioEngine/Utils/AEUtil.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify @@ -71,6 +71,19 @@ class CAEUtil return (value - 1)*db_range; } + /*! \brief convert a dB gain to volume percentage (as a proportion) + We assume a dB range of 60dB, i.e. assume that 0% volume corresponds + to a reduction of 60dB. + \param the corresponding gain in dB from -60dB .. 0dB. + \return value the volume from 0..1 + \sa ScaleToGain + */ + static inline const float GainToPercent(const float gain) + { + static const float db_range = 60.0f; + return 1+(gain/db_range); + } + /*! \brief convert a dB gain to a scale factor for audio manipulation Inverts gain = 20 log_10(scale) \param dB the gain in decibels. @@ -82,6 +95,17 @@ class CAEUtil return pow(10.0f, dB/20); } + /*! \brief convert a scale factor to dB gain for audio manipulation + Inverts GainToScale result + \param the scale factor (equivalent to a voltage multiplier). + \return dB the gain in decibels. + \sa GainToScale + */ + static inline const float ScaleToGain(const float scale) + { + return 20*log10(scale); + } + #ifdef __SSE__ static void SSEMulArray (float *data, const float mul, uint32_t count); static void SSEMulAddArray (float *data, float *add, const float mul, uint32_t count); diff --git a/xbmc/cores/AudioEngine/Utils/AEWAVLoader.cpp b/xbmc/cores/AudioEngine/Utils/AEWAVLoader.cpp index fb24d1ac7df2f..c8a521c80da44 100644 --- a/xbmc/cores/AudioEngine/Utils/AEWAVLoader.cpp +++ b/xbmc/cores/AudioEngine/Utils/AEWAVLoader.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify diff --git a/xbmc/cores/AudioEngine/Utils/AEWAVLoader.h b/xbmc/cores/AudioEngine/Utils/AEWAVLoader.h index ac4c9b5503abd..2ed33eee91c1c 100644 --- a/xbmc/cores/AudioEngine/Utils/AEWAVLoader.h +++ b/xbmc/cores/AudioEngine/Utils/AEWAVLoader.h @@ -1,6 +1,6 @@ #pragma once /* - * Copyright (C) 2010-2012 Team XBMC + * Copyright (C) 2010-2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify From fbe68b2b8714f91db8ae3ff1692de4bd3bb2b71d Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 15 Feb 2013 16:24:08 -0500 Subject: [PATCH 149/180] [aml] fix seeded guisettings with new profiles --- xbmc/settings/GUIDialogProfileSettings.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/xbmc/settings/GUIDialogProfileSettings.cpp b/xbmc/settings/GUIDialogProfileSettings.cpp index d34237b3e9cef..01903e6bd51e4 100644 --- a/xbmc/settings/GUIDialogProfileSettings.cpp +++ b/xbmc/settings/GUIDialogProfileSettings.cpp @@ -338,14 +338,7 @@ bool CGUIDialogProfileSettings::ShowForProfile(unsigned int iProfile, bool first } else { - // create some new settings - CGUISettings localSettings; - localSettings.Initialize(); - CStdString path = URIUtils::AddFileToFolder("special://masterprofile/", dialog->m_strDirectory); - path = URIUtils::AddFileToFolder(path, "guisettings.xml"); - CSettings settings; - settings.Initialize(); - settings.SaveSettings(path, &localSettings); + // Do nothing. Settings will be generated at first login. } } From cffd33abca6ba38a66349236dcd0f2f6c6e55d0b Mon Sep 17 00:00:00 2001 From: davilla Date: Mon, 18 Feb 2013 19:17:14 -0500 Subject: [PATCH 150/180] [aml] silence debug log spew --- xbmc/interfaces/python/CallbackHandler.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/xbmc/interfaces/python/CallbackHandler.cpp b/xbmc/interfaces/python/CallbackHandler.cpp index 01707b964a68d..1bb3997a4c76f 100644 --- a/xbmc/interfaces/python/CallbackHandler.cpp +++ b/xbmc/interfaces/python/CallbackHandler.cpp @@ -36,7 +36,6 @@ namespace XBMCAddon PythonCallbackHandler::PythonCallbackHandler() : RetardedAsynchCallbackHandler("PythonCallbackHandler") { objectThreadState = PyThreadState_Get(); - CLog::Log(LOGDEBUG,"NEWADDON PythonCallbackHandler construction with PyThreadState 0x%lx",(long)objectThreadState); } /** From 0ddb90baca17a9f6cbc6cf418e720635a12aa53e Mon Sep 17 00:00:00 2001 From: davilla Date: Mon, 18 Feb 2013 13:09:00 -0500 Subject: [PATCH 151/180] [aml] remove obsolete code --- .../cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index 010f04cbeb162..211c86a00c8ba 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -59,8 +59,6 @@ class DllLibamCodecInterface virtual int codec_write(codec_para_t *pcodec, void *buffer, int len)=0; virtual int codec_checkin_pts(codec_para_t *pcodec, unsigned long pts)=0; virtual int codec_get_vbuf_state(codec_para_t *pcodec, struct buf_status *)=0; - virtual int codec_set_volume(codec_para_t *pcodec, float val)=0; - virtual int codec_get_volume(codec_para_t *pcodec, float *val)=0; virtual int codec_init_cntl(codec_para_t *pcodec)=0; virtual int codec_poll_cntl(codec_para_t *pcodec)=0; @@ -68,8 +66,6 @@ class DllLibamCodecInterface virtual int codec_set_cntl_avthresh(codec_para_t *pcodec, unsigned int)=0; virtual int codec_set_cntl_syncthresh(codec_para_t *pcodec, unsigned int syncthresh)=0; - virtual int codec_audio_set_delay(codec_para_t *pcodec, int delay)=0; - // grab these from libamplayer virtual int h263vld(unsigned char *inbuf, unsigned char *outbuf, int inbuf_len, int s263)=0; virtual int decodeble_h263(unsigned char *buf)=0; @@ -91,8 +87,6 @@ class DllLibAmCodec : public DllDynamic, DllLibamCodecInterface DEFINE_METHOD3(int, codec_write, (codec_para_t *p1, void *p2, int p3)) DEFINE_METHOD2(int, codec_checkin_pts, (codec_para_t *p1, unsigned long p2)) DEFINE_METHOD2(int, codec_get_vbuf_state, (codec_para_t *p1, struct buf_status * p2)) - DEFINE_METHOD2(int, codec_set_volume, (codec_para_t *p1, float p2)) - DEFINE_METHOD2(int, codec_get_volume, (codec_para_t *p1, float *p2)) DEFINE_METHOD1(int, codec_init_cntl, (codec_para_t *p1)) DEFINE_METHOD1(int, codec_poll_cntl, (codec_para_t *p1)) @@ -100,8 +94,6 @@ class DllLibAmCodec : public DllDynamic, DllLibamCodecInterface DEFINE_METHOD2(int, codec_set_cntl_avthresh, (codec_para_t *p1, unsigned int p2)) DEFINE_METHOD2(int, codec_set_cntl_syncthresh,(codec_para_t *p1, unsigned int p2)) - DEFINE_METHOD2(int, codec_audio_set_delay, (codec_para_t *p1, int p2)) - DEFINE_METHOD4(int, h263vld, (unsigned char *p1, unsigned char *p2, int p3, int p4)) DEFINE_METHOD1(int, decodeble_h263, (unsigned char *p1)) @@ -116,8 +108,6 @@ class DllLibAmCodec : public DllDynamic, DllLibamCodecInterface RESOLVE_METHOD(codec_write) RESOLVE_METHOD(codec_checkin_pts) RESOLVE_METHOD(codec_get_vbuf_state) - RESOLVE_METHOD(codec_set_volume) - RESOLVE_METHOD(codec_get_volume) RESOLVE_METHOD(codec_init_cntl) RESOLVE_METHOD(codec_poll_cntl) @@ -125,8 +115,6 @@ class DllLibAmCodec : public DllDynamic, DllLibamCodecInterface RESOLVE_METHOD(codec_set_cntl_avthresh) RESOLVE_METHOD(codec_set_cntl_syncthresh) - RESOLVE_METHOD(codec_audio_set_delay) - RESOLVE_METHOD(h263vld) RESOLVE_METHOD(decodeble_h263) @@ -1643,10 +1631,6 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) return false; } - float volume; - if (m_dll->codec_get_volume(NULL, &volume) == 0 && volume != 1.0) - m_dll->codec_set_volume(NULL, 1.0); - m_dll->codec_set_cntl_avthresh(&am_private->vcodec, AV_SYNC_THRESH); m_dll->codec_set_cntl_syncthresh(&am_private->vcodec, 0); // disable tsync, we are playing video disconnected from audio. From 44c60146fe6d09b52a978ffdfe06233f9357c1df Mon Sep 17 00:00:00 2001 From: davilla Date: Mon, 18 Feb 2013 13:09:57 -0500 Subject: [PATCH 152/180] [aml] fixed, seeking would break a/v sync --- xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index 211c86a00c8ba..37301c74fbaef 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -1673,6 +1673,12 @@ void CAMLCodec::Reset() int blackout_policy = aml_get_sysfs_int("/sys/class/video/blackout_policy"); aml_set_sysfs_int("/sys/class/video/blackout_policy", 0); + // restore the speed (some amcodec versions require this) + if (m_speed != DVD_PLAYSPEED_NORMAL) + { + m_dll->codec_resume(&am_private->vcodec); + m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE); + } // reset the decoder m_dll->codec_reset(&am_private->vcodec); From a8b27d95bcf2bd2c345ca4b839c961265870201e Mon Sep 17 00:00:00 2001 From: davilla Date: Mon, 18 Feb 2013 13:11:03 -0500 Subject: [PATCH 153/180] [aml] fixed FrameRateTracking code, still unused at the moment --- .../DVDCodecs/Video/DVDVideoCodecAmlogic.cpp | 97 ++++++++++++++----- .../DVDCodecs/Video/DVDVideoCodecAmlogic.h | 1 + 2 files changed, 73 insertions(+), 25 deletions(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp index da344463c839c..333b709ee5db8 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp @@ -41,7 +41,8 @@ CDVDVideoCodecAmlogic::CDVDVideoCodecAmlogic() : m_last_pts(0.0), m_pts_queue(NULL), m_queue_depth(0), - m_framerate(0.0) + m_framerate(0.0), + m_video_rate(0) { } @@ -275,36 +276,82 @@ void CDVDVideoCodecAmlogic::FrameRateTracking(double dts, double pts) { PtsQueuePush(dts, pts); - // in case of out-of-order pts + // we might have out-of-order pts, + // so make sure we wait for at least 16 values in sorted queue. if (m_queue_depth > 16) { - if (pts == DVD_NOPTS_VALUE) - pts = m_pts_queue->dts; + float cur_pts; + if (m_pts_queue->pts == DVD_NOPTS_VALUE) + cur_pts = m_pts_queue->dts; else - pts = m_pts_queue->pts; + cur_pts = m_pts_queue->pts; - double duration = pts - m_last_pts; - m_last_pts = pts; - if (duration > 0.0) + float duration = cur_pts - m_last_pts; + m_last_pts = cur_pts; + + // clamp duration to sensible range, + // 66 fsp to 20 fsp + if (duration >= 15000.0 && duration <= 50000.0) { - switch ((int)(0.5 + ((double)DVD_TIME_BASE / duration))) + double framerate; + switch((int)(0.5 + duration)) { - case 60: - // 60, 59.94 -> 60 - m_framerate = 1001.0 / 60000.0; - case 50: - // 50, 49.95 -> 50 - m_framerate = 1001.0 / 50000.0; - case 30: - // 30, 29.97 -> 30 - m_framerate = 1001.0 / 30000.0; - case 25: - // 25, 24.975 -> 25 - m_framerate = 1001.0 / 25000.0; - case 24: - // 24, 23.976 -> 24 - m_framerate = 1001.0 / 24000.0; - break; + // 59.940 (16683.333333) + case 16000 ... 17000: + framerate = 60000.0 / 1001.0; + break; + + // 50.000 (20000.000000) + case 20000: + framerate = 50000.0 / 1000.0; + break; + + // 49.950 (20020.000000) + case 20020: + framerate = 50000.0 / 1001.0; + break; + + // 29.970 (33366.666656) + case 32000 ... 35000: + framerate = 30000.0 / 1001.0; + break; + + // 25.000 (40000.000000) + case 40000: + framerate = 25000.0 / 1000.0; + break; + + // 24.975 (40040.000000) + case 40040: + framerate = 25000.0 / 1001.0; + break; + + /* + // 24.000 (41666.666666) + case 41667: + framerate = 24000.0 / 1000.0; + break; + */ + + // 23.976 (41708.33333) + case 40200 ... 43200: + // 23.976 seems to have the crappiest encodings :) + framerate = 24000.0 / 1001.0; + break; + + default: + framerate = 0.0; + CLog::Log(LOGDEBUG, "%s: unknown duration(%f), cur_pts(%f)", + __MODULE_NAME__, duration, cur_pts); + break; + } + + if (framerate > 0.0 && (int)m_framerate != (int)framerate) + { + m_framerate = framerate; + m_video_rate = (int)(0.5 + (96000.0 / framerate)); + CLog::Log(LOGDEBUG, "%s: detected new framerate(%f), video_rate(%d)", + __MODULE_NAME__, m_framerate, m_video_rate); } } diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h index 8b24c6c6ed805..d3584e67767ae 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h @@ -58,4 +58,5 @@ class CDVDVideoCodecAmlogic : public CDVDVideoCodec pts_queue *m_pts_queue; int32_t m_queue_depth; double m_framerate; + int m_video_rate; }; From 128ad9e001252d48faeed1694f1286e24ab4eff6 Mon Sep 17 00:00:00 2001 From: davilla Date: Mon, 18 Feb 2013 13:13:17 -0500 Subject: [PATCH 154/180] [aml] refactor Libamplayer related code --- .../libamplayer/include/player_type.h | 39 ++++++++++++- xbmc/cores/amlplayer/AMLPlayer.cpp | 56 ++++++++++++++----- xbmc/cores/amlplayer/DllLibamplayer.h | 29 +++++++++- 3 files changed, 105 insertions(+), 19 deletions(-) diff --git a/tools/android/depends/libamplayer/libamplayer/include/player_type.h b/tools/android/depends/libamplayer/libamplayer/include/player_type.h index 37877a4a16753..37ad847573fcd 100644 --- a/tools/android/depends/libamplayer/libamplayer/include/player_type.h +++ b/tools/android/depends/libamplayer/libamplayer/include/player_type.h @@ -5,8 +5,14 @@ #include #define MSG_SIZE 64 +#if defined(HAS_AMLPLAYER_CHAPTERS) #define MAX_CHAPTERS 64 +#endif +#if defined(HAS_AMLPLAYER_VIDEO_STREAMS10) +#define MAX_VIDEO_STREAMS 10 +#else #define MAX_VIDEO_STREAMS 8 +#endif #define MAX_AUDIO_STREAMS 8 #define MAX_SUB_INTERNAL 8 #define MAX_SUB_EXTERNAL 24 @@ -65,8 +71,6 @@ typedef enum PLAYER_DIVX_AUTHORERR = 0x40001, PLAYER_DIVX_RENTAL_EXPIRED = 0x40002, PLAYER_DIVX_RENTAL_VIEW = 0x40003, - - }player_status; @@ -116,7 +120,9 @@ typedef struct aformat_t aformat; int duration; audio_tag_info *audio_tag; +#if defined(HAS_AMLPLAYER_AUDIO_LANG) char audio_language[4]; +#endif }maudio_info_t; typedef struct @@ -151,15 +157,23 @@ typedef struct int cur_sub_index; int seekable; int drm_check; +#if defined(HAS_AMLPLAYER_VIDEO_STREAMS10) + int t1; + int t2; +#endif +#if defined(HAS_AMLPLAYER_CHAPTERS) int has_chapter; int total_chapter_num; +#endif }mstream_info_t; +#if defined(HAS_AMLPLAYER_CHAPTERS) typedef struct { char *name; int64_t seekto_ms; } mchapter_info_t; +#endif typedef struct { @@ -167,7 +181,9 @@ typedef struct mvideo_info_t *video_info[MAX_VIDEO_STREAMS]; maudio_info_t *audio_info[MAX_AUDIO_STREAMS]; msub_info_t *sub_info[MAX_SUB_STREAMS]; - mchapter_info_t *chapter_info[MAX_CHAPTERS]; +#if defined(HAS_AMLPLAYER_CHAPTERS) + mchapter_info_t *chapter_info[MAX_CHAPTERS]; +#endif }media_info_t; typedef struct player_info @@ -226,8 +242,23 @@ typedef enum PLAYER_EVENTS_ERROR, ///check_pid_valid(m_pid)) { @@ -839,6 +840,7 @@ void CAMLPlayer::SetMute(bool bOnOff) else m_dll->audio_set_volume(m_pid, m_audio_volume); } +#endif } void CAMLPlayer::SetVolume(float volume) @@ -846,9 +848,11 @@ void CAMLPlayer::SetVolume(float volume) // volume is a float percent from 0.0 to 1.0 m_audio_volume = VolumePercentToScale(volume); +#if defined(HAS_AMLPLAYER_AUDIO_SETVOLUME) CSingleLock lock(m_aml_csection); if (!m_audio_mute && m_dll->check_pid_valid(m_pid)) m_dll->audio_set_volume(m_pid, m_audio_volume); +#endif } void CAMLPlayer::GetAudioInfo(CStdString &strAudioInfo) @@ -927,11 +931,13 @@ void CAMLPlayer::SetAVDelay(float fValue) CLog::Log(LOGDEBUG, "CAMLPlayer::SetAVDelay (%f)", fValue); m_audio_delay = fValue * 1000.0; +#if defined(HAS_AMLPLAYER_AUDIO_SETDELAY) if (m_audio_streams.size() && m_dll->check_pid_valid(m_pid)) { CSingleLock lock(m_aml_csection); m_dll->audio_set_delay(m_pid, m_audio_delay); } +#endif } float CAMLPlayer::GetAVDelay() @@ -1504,6 +1510,7 @@ void CAMLPlayer::Process() play_control.need_start = 1; // if 0,you can omit player_start_play API. // just play video/audio immediately. // if 1,then need call "player_start_play" API; + play_control.displast_frame = 0; // 0:black out when player exit 1:keep last frame when player exit // tweak player playback buffers for udp if (url.Left(strlen("udp://")).Equals("udp://")) @@ -1978,26 +1985,45 @@ bool CAMLPlayer::WaitForFormatValid(int timeout_ms) ClearStreamInfos(); - media_info_t media_info; + media_info_t media_info = {{0}}; +#if defined(TARGET_ANDROID) + // media_info_t might be different so check its size. + // player_get_media_info will memset to zero the passed + // structure so alloc more space and preset to a know value + // so we can compare the size we use to the size the lib uses. + int msize = sizeof(media_info_t) + 10240; + media_info_t *test_media_info = (media_info_t*)calloc(msize, 1); + memset(test_media_info, 0xEF, msize); + + int res = m_dll->player_get_media_info(m_pid, test_media_info); + + uint8_t *t1 = (uint8_t*)test_media_info; + for (size_t i = msize-1; i >= 0; i--) + { + if (t1[i] != 0xEF) + { + if (sizeof(media_info_t) != i+1) + { + CLog::Log(LOGERROR, "CAMLPlayer::media_info_t(%d) size changed to %d", + sizeof(media_info_t), i+1); + // size is different, we cannot trust it + free(test_media_info); + return false; + } + break; + } + } + media_info = *test_media_info; + free(test_media_info); +#else int res = m_dll->player_get_media_info(m_pid, &media_info); +#endif if (res != PLAYER_SUCCESS) return false; if (m_log_level > 5) - { media_info_dump(&media_info); - // m_video_index, m_audio_index, m_subtitle_index might be -1 eventhough - // total_video_xxx is > 0, not sure why, they should be set to zero or - // some other sensible value. - CLog::Log(LOGDEBUG, "CAMLPlayer::WaitForFormatValid: " - "m_video_index(%d), m_audio_index(%d), m_subtitle_index(%d), m_chapter_count(%d)", - media_info.stream_info.cur_video_index, - media_info.stream_info.cur_audio_index, - media_info.stream_info.cur_sub_index, - media_info.stream_info.total_chapter_num); - } - // video info if (media_info.stream_info.has_video && media_info.stream_info.total_video_num > 0) { @@ -2052,8 +2078,10 @@ bool CAMLPlayer::WaitForFormatValid(int timeout_ms) info->bit_rate = media_info.audio_info[i]->bit_rate; info->duration = media_info.audio_info[i]->duration; info->format = media_info.audio_info[i]->aformat; +#if defined(HAS_AMLPLAYER_AUDIO_LANG) if (media_info.audio_info[i]->audio_language[0] != 0) info->language = std::string(media_info.audio_info[i]->audio_language, 3); +#endif m_audio_streams.push_back(info); } @@ -2089,6 +2117,7 @@ bool CAMLPlayer::WaitForFormatValid(int timeout_ms) if (m_subtitle_count && m_subtitle_index != 0) m_subtitle_index = 0; +#if defined(HAS_AMLPLAYER_CHAPTERS) // chapter info if (media_info.stream_info.total_chapter_num > 0) { @@ -2105,6 +2134,7 @@ bool CAMLPlayer::WaitForFormatValid(int timeout_ms) } } } +#endif return true; break; diff --git a/xbmc/cores/amlplayer/DllLibamplayer.h b/xbmc/cores/amlplayer/DllLibamplayer.h index 200691b42582e..95f11647decca 100644 --- a/xbmc/cores/amlplayer/DllLibamplayer.h +++ b/xbmc/cores/amlplayer/DllLibamplayer.h @@ -25,6 +25,17 @@ extern "C" { +// beware, these will alter the structs +// in player_type.h. +#if 1 + #define HAS_AMLPLAYER_CHAPTERS + #define HAS_AMLPLAYER_AUDIO_LANG + #define HAS_AMLPLAYER_AUDIO_SETDELAY + #define HAS_AMLPLAYER_AUDIO_SETVOLUME +#else + #define HAS_AMLPLAYER_VIDEO_STREAMS10 +#endif + #include #include } @@ -62,8 +73,12 @@ class DllLibAmplayerInterface virtual int player_register_update_callback(callback_t *cb,update_state_fun_t up_fn,int interval_s)=0; virtual char* player_status2str(player_status status)=0; - virtual int audio_set_volume(int pid,float val)=0; +#if defined(HAS_AMLPLAYER_AUDIO_SETDELAY) virtual int audio_set_delay(int pid, int delay)=0; +#endif +#if defined(HAS_AMLPLAYER_AUDIO_SETVOLUME) + virtual int audio_set_volume(int pid,float val)=0; +#endif virtual int codec_open_sub_read(void)=0; virtual int codec_close_sub_fd(int sub_fd)=0; @@ -103,8 +118,12 @@ class DllLibAmplayer : public DllDynamic, DllLibAmplayerInterface DEFINE_METHOD3(int, player_register_update_callback, (callback_t *p1, update_state_fun_t p2, int p3)) DEFINE_METHOD1(char*, player_status2str, (player_status p1)) - DEFINE_METHOD2(int, audio_set_volume, (int p1, float p2)) +#if defined(HAS_AMLPLAYER_AUDIO_SETDELAY) DEFINE_METHOD2(int, audio_set_delay, (int p1, int p2)) +#endif +#if defined(HAS_AMLPLAYER_AUDIO_SETVOLUME) + DEFINE_METHOD2(int, audio_set_volume, (int p1, float p2)) +#endif DEFINE_METHOD0(int, codec_open_sub_read) DEFINE_METHOD1(int, codec_close_sub_fd, (int p1)) @@ -140,8 +159,12 @@ class DllLibAmplayer : public DllDynamic, DllLibAmplayerInterface RESOLVE_METHOD(player_register_update_callback) RESOLVE_METHOD(player_status2str) - RESOLVE_METHOD(audio_set_volume) +#if defined(HAS_AMLPLAYER_AUDIO_SETDELAY) RESOLVE_METHOD(audio_set_delay) +#endif +#if defined(HAS_AMLPLAYER_AUDIO_SETVOLUME) + RESOLVE_METHOD(audio_set_volume) +#endif RESOLVE_METHOD(codec_open_sub_read) RESOLVE_METHOD(codec_close_sub_fd) From 920d785f1a79135b28b244013cb86da7506435be Mon Sep 17 00:00:00 2001 From: davilla Date: Tue, 19 Feb 2013 18:30:26 -0500 Subject: [PATCH 155/180] [aml] refactor a/v sync to be less intrusive --- .../dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index 37301c74fbaef..12cc21b10e66d 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -1882,10 +1882,22 @@ void CAMLCodec::Process() double offset = g_renderManager.GetDisplayLatency() - g_settings.m_currentVideoSettings.m_AudioDelay; // correct video pts by user set delay and rendering delay app_pts += offset; - if (fabs((double)pts_video/PTS_FREQ - app_pts) > 0.20) + + double error = app_pts - (double)pts_video/PTS_FREQ; + double abs_error = fabs(error); + if (abs_error > 0.040) { - //CLog::Log(LOGDEBUG, "CAMLCodec::Process pts diff = %f", (double)pts_video/PTS_FREQ - app_pts); - SetVideoPtsSeconds(app_pts); + //CLog::Log(LOGDEBUG, "CAMLCodec::Process pts diff = %f", error); + if (abs_error > 0.125) + { + // big error so try to reset pts_pcrscr + SetVideoPtsSeconds(app_pts); + } + else + { + // small error so try to avoid a frame jump + SetVideoPtsSeconds((double)pts_video/PTS_FREQ + error/4); + } } } } From a21217a1bdc325365cee865c0cb33363f9acae08 Mon Sep 17 00:00:00 2001 From: davilla Date: Tue, 19 Feb 2013 18:30:58 -0500 Subject: [PATCH 156/180] [aml] fixed lingering stuck in pause (amcodec bug) --- xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index 12cc21b10e66d..fa810cd644a6c 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -1630,9 +1630,12 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder codec init failed, ret=0x%x", -ret); return false; } + // make sure we are not stuck in pause (amcodec bug) + m_dll->codec_resume(&am_private->vcodec); + m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE); - m_dll->codec_set_cntl_avthresh(&am_private->vcodec, AV_SYNC_THRESH); - m_dll->codec_set_cntl_syncthresh(&am_private->vcodec, 0); + m_dll->codec_set_cntl_avthresh(&am_private->vcodec, AV_SYNC_THRESH); + m_dll->codec_set_cntl_syncthresh(&am_private->vcodec, 0); // disable tsync, we are playing video disconnected from audio. aml_set_sysfs_int("/sys/class/tsync/enable", 0); From f87b0421ff97dc2d106cbcb809ce862e75a1550b Mon Sep 17 00:00:00 2001 From: davilla Date: Tue, 19 Feb 2013 19:57:16 -0500 Subject: [PATCH 157/180] [aml] add mx detect --- xbmc/utils/AMLUtils.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/xbmc/utils/AMLUtils.cpp b/xbmc/utils/AMLUtils.cpp index 18b6019680555..ce135d5912ab8 100644 --- a/xbmc/utils/AMLUtils.cpp +++ b/xbmc/utils/AMLUtils.cpp @@ -120,6 +120,11 @@ int aml_get_cputype() aml_cputype = 3; break; } + else if (stdbuffer.find("Meson6") != std::string::npos) + { + aml_cputype = 6; + break; + } } fclose(cpuinfo_fd); } From cc31a5383eec729845444666e82fecd88add8757 Mon Sep 17 00:00:00 2001 From: davilla Date: Wed, 20 Feb 2013 17:28:03 -0500 Subject: [PATCH 158/180] [aml] fixed, network might not be up when we are launched, so keep trying --- xbmc/network/NetworkManager.cpp | 17 +++++++++++++++++ xbmc/network/NetworkManager.h | 3 +++ 2 files changed, 20 insertions(+) diff --git a/xbmc/network/NetworkManager.cpp b/xbmc/network/NetworkManager.cpp index 02b2d55a45e56..bae65c8b1fb99 100644 --- a/xbmc/network/NetworkManager.cpp +++ b/xbmc/network/NetworkManager.cpp @@ -38,6 +38,7 @@ //----------------------------------------------------------------------- CNetworkManager::CNetworkManager() { + m_timer = NULL; m_instance = NULL; m_state = NETWORK_CONNECTION_STATE_UNKNOWN; } @@ -73,6 +74,22 @@ void CNetworkManager::Initialize() bool CNetworkManager::PumpNetworkEvents() { + if (!g_application.m_pPlayer) + { + if (!m_timer && !IsConnected()) + { + CLog::Log(LOGDEBUG, "NetworkManager: not connected, bgn timout"); + m_timer = new CStopWatch(); + m_timer->StartZero(); + } + } + if (m_timer && m_timer->GetElapsedSeconds() > 15) + { + CLog::Log(LOGDEBUG, "NetworkManager: not connected, end timout"); + OnConnectionListChange(m_instance->GetConnections()); + delete m_timer, m_timer = NULL; + } + return m_instance->PumpNetworkEvents(this); } diff --git a/xbmc/network/NetworkManager.h b/xbmc/network/NetworkManager.h index 0680d776349ba..010eb6034e89d 100644 --- a/xbmc/network/NetworkManager.h +++ b/xbmc/network/NetworkManager.h @@ -22,6 +22,8 @@ #include "INetworkManager.h" +class CStopWatch; + class CNetworkManager : public INetworkEventsCallback { public: @@ -77,4 +79,5 @@ class CNetworkManager : public INetworkEventsCallback CConnectionPtr m_defaultConnection; ConnectionList m_connections; ConnectionState m_state; + CStopWatch *m_timer; }; From 7aeee6d2d09f8f2bfb5ab7f44edb3b3963bee7f5 Mon Sep 17 00:00:00 2001 From: davilla Date: Thu, 21 Feb 2013 21:59:46 -0500 Subject: [PATCH 159/180] [aml] fixed, restrict network retry to android --- xbmc/network/NetworkManager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xbmc/network/NetworkManager.cpp b/xbmc/network/NetworkManager.cpp index bae65c8b1fb99..275692cb6ebe3 100644 --- a/xbmc/network/NetworkManager.cpp +++ b/xbmc/network/NetworkManager.cpp @@ -74,6 +74,7 @@ void CNetworkManager::Initialize() bool CNetworkManager::PumpNetworkEvents() { +#if defined(TARGET_ANDROID) if (!g_application.m_pPlayer) { if (!m_timer && !IsConnected()) @@ -89,6 +90,7 @@ bool CNetworkManager::PumpNetworkEvents() OnConnectionListChange(m_instance->GetConnections()); delete m_timer, m_timer = NULL; } +#endif return m_instance->PumpNetworkEvents(this); } From e0189c9343bbe9491feea8de76b6807aeee5d26a Mon Sep 17 00:00:00 2001 From: davilla Date: Mon, 25 Feb 2013 11:49:08 -0500 Subject: [PATCH 160/180] [aml] cosmetics --- xbmc/utils/AMLUtils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xbmc/utils/AMLUtils.h b/xbmc/utils/AMLUtils.h index 07e625e81368e..95e5309ce459c 100644 --- a/xbmc/utils/AMLUtils.h +++ b/xbmc/utils/AMLUtils.h @@ -25,6 +25,6 @@ int aml_set_sysfs_int(const char *path, const int val); int aml_get_sysfs_int(const char *path); bool aml_present(); -int aml_get_cputype(); +int aml_get_cputype(); void aml_cpufreq_limit(bool limit); void aml_set_audio_passthrough(bool passthrough); From 7874d6c328b8cf74dbdac5e7d89f02d8b42d048c Mon Sep 17 00:00:00 2001 From: davilla Date: Mon, 25 Feb 2013 11:50:35 -0500 Subject: [PATCH 161/180] [aml] fixed, use the right aspect ratio for display --- .../DVDCodecs/Video/DVDVideoCodecAmlogic.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp index 333b709ee5db8..35043e6bf46de 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp @@ -19,6 +19,8 @@ * */ +#include + #include "DVDVideoCodecAmlogic.h" #include "DVDClock.h" #include "DVDStreamInfo.h" @@ -122,8 +124,14 @@ bool CDVDVideoCodecAmlogic::Open(CDVDStreamInfo &hints, CDVDCodecOptions &option m_videobuffer.iFlags = DVP_FLAG_ALLOCATED; m_videobuffer.iWidth = hints.width; m_videobuffer.iHeight = hints.height; - m_videobuffer.iDisplayWidth = hints.width; - m_videobuffer.iDisplayHeight = hints.height; + + m_videobuffer.iDisplayHeight = m_videobuffer.iHeight; + m_videobuffer.iDisplayWidth = ((int)lrint(m_videobuffer.iHeight * hints.aspect)) & -3; + if (m_videobuffer.iDisplayWidth > m_videobuffer.iWidth) + { + m_videobuffer.iDisplayWidth = m_videobuffer.iWidth; + m_videobuffer.iDisplayHeight = ((int)lrint(m_videobuffer.iWidth / hints.aspect)) & -3; + } CJobManager::GetInstance().Pause(kJobTypeMediaFlags); if (CJobManager::GetInstance().IsProcessing(kJobTypeMediaFlags) > 0) From 2c8f20d61048e0b2612524c7fd47ea8e28e16fce Mon Sep 17 00:00:00 2001 From: davilla Date: Mon, 25 Feb 2013 11:51:14 -0500 Subject: [PATCH 162/180] [aml] fixed, add missing sample rates --- xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp index 2a57d548604de..11a301151d3d5 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp @@ -266,6 +266,7 @@ bool CAESinkALSA::InitializeHW(AEAudioFormat &format) case 11025: case 22050: case 88200: + case 176400: sampleRate = 44100; break; case 8000: @@ -273,6 +274,8 @@ bool CAESinkALSA::InitializeHW(AEAudioFormat &format) case 24000: case 32000: case 96000: + case 192000: + case 384000: sampleRate = 48000; break; } From 482c7bf7eeefbd8240c11126ebe53399e2b786b1 Mon Sep 17 00:00:00 2001 From: davilla Date: Tue, 26 Feb 2013 17:22:03 -0500 Subject: [PATCH 163/180] [aml] fixed, pts_pcrscr does not like negative values --- xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index fa810cd644a6c..a613311face16 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -1926,7 +1926,8 @@ double CAMLCodec::GetPlayerPtsSeconds() void CAMLCodec::SetVideoPtsSeconds(const double pts) { //CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoPtsSeconds: pts(%f)", pts); - set_pts_pcrscr((int64_t)(pts * PTS_FREQ)); + if (pts >= 0.0) + set_pts_pcrscr((int64_t)(pts * PTS_FREQ)); } void CAMLCodec::ShowMainVideo(const bool show) From 00c729ce296bbb832e64bee56dce8fc9d7eee3e6 Mon Sep 17 00:00:00 2001 From: davilla Date: Tue, 26 Feb 2013 17:22:56 -0500 Subject: [PATCH 164/180] [aml] changed, digital_raw => 1 for m1, => 2 for m3 --- xbmc/utils/AMLUtils.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/xbmc/utils/AMLUtils.cpp b/xbmc/utils/AMLUtils.cpp index ce135d5912ab8..14a421bcc50b9 100644 --- a/xbmc/utils/AMLUtils.cpp +++ b/xbmc/utils/AMLUtils.cpp @@ -145,7 +145,10 @@ void aml_cpufreq_limit(bool limit) void aml_set_audio_passthrough(bool passthrough) { if (aml_present()) - aml_set_sysfs_int("/sys/class/audiodsp/digital_raw", passthrough ? 1:0); + { + int raw = aml_get_cputype() < 3 ? 1:2; + aml_set_sysfs_int("/sys/class/audiodsp/digital_raw", passthrough ? raw:0); + } } void aml_probe_hdmi_audio() From ebb7b6ef273251727e08795f146783bde2ec4084 Mon Sep 17 00:00:00 2001 From: davilla Date: Tue, 26 Feb 2013 17:26:18 -0500 Subject: [PATCH 165/180] [aml] fixed, audio silence blips, make periodSize >= 1024 by forcing ALSA_PERIODS = 8 --- xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp index 11a301151d3d5..ea0807a7a7098 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp @@ -38,7 +38,7 @@ #endif #define ALSA_OPTIONS (SND_PCM_NONBLOCK | SND_PCM_NO_AUTO_FORMAT | SND_PCM_NO_AUTO_CHANNELS | SND_PCM_NO_AUTO_RESAMPLE) -#define ALSA_PERIODS 16 +#define ALSA_PERIODS 8 #define ALSA_MAX_CHANNELS 16 static enum AEChannel ALSAChannelMap[ALSA_MAX_CHANNELS + 1] = { @@ -350,15 +350,25 @@ bool CAESinkALSA::InitializeHW(AEAudioFormat &format) } unsigned int periods; - snd_pcm_uframes_t periodSize, bufferSize; + + snd_pcm_hw_params_get_periods_min(hw_params, &periods, NULL); + snd_pcm_hw_params_get_period_size_min(hw_params, &periodSize, NULL); + snd_pcm_hw_params_get_buffer_size_min(hw_params, &bufferSize); + CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Min: periodSize %lu, periods %u, bufferSize %lu", periodSize, periods, bufferSize); + + snd_pcm_hw_params_get_periods_max(hw_params, &periods, NULL); + snd_pcm_hw_params_get_period_size_max(hw_params, &periodSize, NULL); + snd_pcm_hw_params_get_buffer_size_max(hw_params, &bufferSize); + CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Max: periodSize %lu, periods %u, bufferSize %lu", periodSize, periods, bufferSize); + snd_pcm_hw_params_get_buffer_size_max(hw_params, &bufferSize); bufferSize = std::min(bufferSize, (snd_pcm_uframes_t)8192); periodSize = bufferSize / ALSA_PERIODS; periods = ALSA_PERIODS; - CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Request: periodSize %lu, periods %u, bufferSize %lu", periodSize, periods, bufferSize); + CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Req: periodSize %lu, periods %u, bufferSize %lu", periodSize, periods, bufferSize); /* work on a copy of the hw params */ snd_pcm_hw_params_t *hw_params_copy; From fb89276ba3d701e8f437d732f3aa3088f304eb9e Mon Sep 17 00:00:00 2001 From: davilla Date: Wed, 27 Feb 2013 07:19:38 -0500 Subject: [PATCH 166/180] [aml] refactor resolution handling --- xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp | 126 +++++++++++++------- 1 file changed, 81 insertions(+), 45 deletions(-) diff --git a/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp b/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp index 4746069bf124e..66cfef114c0d5 100644 --- a/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp +++ b/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp @@ -131,34 +131,47 @@ bool CEGLNativeTypeAmlogic::GetNativeResolution(RESOLUTION_INFO *res) const bool CEGLNativeTypeAmlogic::SetNativeResolution(const RESOLUTION_INFO &res) { - if (res.iScreenWidth == 1920 && res.iScreenHeight == 1080) + switch((int)(0.5 + res.fRefreshRate)) { - if (res.dwFlags & D3DPRESENTFLAG_INTERLACED) - { - if ((int)res.fRefreshRate == 60) - SetDisplayResolution("1080i"); - else - SetDisplayResolution("1080i50hz"); - } - else - { - if ((int)res.fRefreshRate == 60) - SetDisplayResolution("1080p"); - else - SetDisplayResolution("1080p50hz"); - } - } - else if (res.iScreenWidth == 1280 && res.iScreenHeight == 720) - { - if ((int)res.fRefreshRate == 60) - SetDisplayResolution("720p"); - else - SetDisplayResolution("720p50hz"); - } - else if (res.iScreenWidth == 720 && res.iScreenHeight == 480) - { - SetDisplayResolution("480p"); + default: + case 60: + switch(res.iScreenWidth) + { + default: + case 1280: + SetDisplayResolution("720p"); + break; + case 1920: + if (res.dwFlags & D3DPRESENTFLAG_INTERLACED) + SetDisplayResolution("1080i"); + else + SetDisplayResolution("1080p"); + break; + } + break; + case 50: + switch(res.iScreenWidth) + { + default: + case 1280: + SetDisplayResolution("720p50hz"); + break; + case 1920: + if (res.dwFlags & D3DPRESENTFLAG_INTERLACED) + SetDisplayResolution("1080i50hz"); + else + SetDisplayResolution("1080p50hz"); + break; + } + break; + case 30: + SetDisplayResolution("1080p30hz"); + break; + case 24: + SetDisplayResolution("1080p24hz"); + break; } + return true; } @@ -241,56 +254,79 @@ bool CEGLNativeTypeAmlogic::ModeToResolution(const char *mode, RESOLUTION_INFO * { res->iWidth = 1280; res->iHeight= 720; - res->iScreenWidth = res->iWidth; - res->iScreenHeight = res->iHeight; + res->iScreenWidth = 1280; + res->iScreenHeight= 720; res->fRefreshRate = 60; - res->dwFlags= D3DPRESENTFLAG_PROGRESSIVE; + res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE; } else if (fromMode.Equals("720p50hz")) { res->iWidth = 1280; res->iHeight= 720; - res->iScreenWidth = res->iWidth; - res->iScreenHeight = res->iHeight; + res->iScreenWidth = 1280; + res->iScreenHeight= 720; res->fRefreshRate = 50; - res->dwFlags= D3DPRESENTFLAG_PROGRESSIVE; + res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE; } else if (fromMode.Equals("1080p")) { res->iWidth = 1280; res->iHeight= 720; - res->iScreenWidth = 1920; - res->iScreenHeight = 1080; + res->iScreenWidth = 1920; + res->iScreenHeight= 1080; res->fRefreshRate = 60; - res->dwFlags= D3DPRESENTFLAG_PROGRESSIVE; + res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE; } - else if (fromMode.Equals("1080p50hz")) + else if (fromMode.Equals("1080p24hz")) { + res->iWidth = 1280; + res->iHeight= 720; res->iScreenWidth = 1920; res->iScreenHeight= 1080; + res->fRefreshRate = 24; + res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE; + } + else if (fromMode.Equals("1080p30hz")) + { res->iWidth = 1280; res->iHeight= 720; - res->fRefreshRate = 50; - res->dwFlags= D3DPRESENTFLAG_PROGRESSIVE; + res->iScreenWidth = 1920; + res->iScreenHeight= 1080; + res->fRefreshRate = 30; + res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE; } - else if (fromMode.Equals("1080i")) + else if (fromMode.Equals("1080p50hz")) { + res->iWidth = 1280; + res->iHeight= 720; res->iScreenWidth = 1920; res->iScreenHeight= 1080; + res->fRefreshRate = 50; + res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE; + } + else if (fromMode.Equals("1080i")) + { res->iWidth = 1280; res->iHeight= 720; + res->iScreenWidth = 1920; + res->iScreenHeight= 1080; res->fRefreshRate = 60; - res->dwFlags= D3DPRESENTFLAG_INTERLACED; + res->dwFlags = D3DPRESENTFLAG_INTERLACED; } else if (fromMode.Equals("1080i50hz")) { - res->iWidth = 1920; - res->iHeight= 1080; - res->iScreenWidth = 1280; - res->iScreenHeight= 720; + res->iWidth = 1280; + res->iHeight= 720; + res->iScreenWidth = 1920; + res->iScreenHeight= 1080; res->fRefreshRate = 50; - res->dwFlags= D3DPRESENTFLAG_INTERLACED; + res->dwFlags = D3DPRESENTFLAG_INTERLACED; } + else + { + return false; + } + res->iScreen = 0; res->bFullScreen = true; From 693a7a779b6e663e54df5bdda522077648859ca3 Mon Sep 17 00:00:00 2001 From: davilla Date: Wed, 27 Feb 2013 11:05:52 -0500 Subject: [PATCH 167/180] [aml] cosmetics --- xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp b/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp index 66cfef114c0d5..6b200fa08c82f 100644 --- a/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp +++ b/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp @@ -247,6 +247,7 @@ bool CEGLNativeTypeAmlogic::ModeToResolution(const char *mode, RESOLUTION_INFO * CStdString fromMode = mode; fromMode.Trim(); // strips, for example, 720p* to 720p + // the * indicate the 'native' mode of the display if (fromMode.Right(1) == "*") fromMode = fromMode.Left(std::max(0, (int)fromMode.size() - 1)); From aa9244a3efea8cf392ec7b59070fed7eaaba03dc Mon Sep 17 00:00:00 2001 From: davilla Date: Wed, 27 Feb 2013 11:08:45 -0500 Subject: [PATCH 168/180] [gles] fix compiler warning --- xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp index 073c0b080d3e7..dff74869954ed 100644 --- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp +++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp @@ -1366,7 +1366,7 @@ bool CLinuxRendererGLES::RenderCapture(CRenderCapture* capture) // OpenGLES returns in RGBA order but CRenderCapture needs BGRA order // XOR Swap RGBA -> BGRA unsigned char* pixels = (unsigned char*)capture->GetRenderBuffer(); - for (int i = 0; i < capture->GetWidth() * capture->GetHeight(); i++, pixels+=4) + for (unsigned int i = 0; i < capture->GetWidth() * capture->GetHeight(); i++, pixels+=4) { std::swap(pixels[0], pixels[2]); } From e8b47fc057e3219bbfe7bd0e5bd85ff823394e72 Mon Sep 17 00:00:00 2001 From: davilla Date: Wed, 27 Feb 2013 11:10:16 -0500 Subject: [PATCH 169/180] [gles] fixed, m_iVSyncMode var in two places with different type, opps. pick one, please --- xbmc/windowing/egl/WinSystemEGL.cpp | 9 ++++++--- xbmc/windowing/egl/WinSystemEGL.h | 1 - 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/xbmc/windowing/egl/WinSystemEGL.cpp b/xbmc/windowing/egl/WinSystemEGL.cpp index 4a0f2bb72ddcb..cbc895ea542cb 100644 --- a/xbmc/windowing/egl/WinSystemEGL.cpp +++ b/xbmc/windowing/egl/WinSystemEGL.cpp @@ -43,7 +43,7 @@ CWinSystemEGL::CWinSystemEGL() : CWinSystemBase() m_config = NULL; m_egl = NULL; - m_iVSyncMode = false; + m_iVSyncMode = 0; } CWinSystemEGL::~CWinSystemEGL() @@ -384,9 +384,12 @@ bool CWinSystemEGL::PresentRenderImpl(const CDirtyRegionList &dirty) void CWinSystemEGL::SetVSyncImpl(bool enable) { - m_iVSyncMode = enable; - if (!m_egl->SetVSync(m_display, m_iVSyncMode)) + m_iVSyncMode = enable ? 10:0; + if (!m_egl->SetVSync(m_display, enable)) + { + m_iVSyncMode = 0; CLog::Log(LOGERROR, "%s,Could not set egl vsync", __FUNCTION__); + } } void CWinSystemEGL::ShowOSMouse(bool show) diff --git a/xbmc/windowing/egl/WinSystemEGL.h b/xbmc/windowing/egl/WinSystemEGL.h index fae528c5faaf8..6beb8fcfc91cb 100644 --- a/xbmc/windowing/egl/WinSystemEGL.h +++ b/xbmc/windowing/egl/WinSystemEGL.h @@ -75,7 +75,6 @@ class CWinSystemEGL : public CWinSystemBase, public CRenderSystemGLES EGLConfig m_config; CEGLWrapper *m_egl; - bool m_iVSyncMode; std::string m_extensions; }; From 0c9d3c345bbfdb6a0adebb2ef0d02aa5852f187e Mon Sep 17 00:00:00 2001 From: davilla Date: Wed, 27 Feb 2013 19:55:05 -0500 Subject: [PATCH 170/180] [aml] fixed, check for hints.aspect > 0.0 && !hints.forced_aspect --- .../DVDCodecs/Video/DVDVideoCodecAmlogic.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp index 35043e6bf46de..fc67774351a57 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp @@ -125,12 +125,16 @@ bool CDVDVideoCodecAmlogic::Open(CDVDStreamInfo &hints, CDVDCodecOptions &option m_videobuffer.iWidth = hints.width; m_videobuffer.iHeight = hints.height; + m_videobuffer.iDisplayWidth = m_videobuffer.iWidth; m_videobuffer.iDisplayHeight = m_videobuffer.iHeight; - m_videobuffer.iDisplayWidth = ((int)lrint(m_videobuffer.iHeight * hints.aspect)) & -3; - if (m_videobuffer.iDisplayWidth > m_videobuffer.iWidth) + if (hints.aspect > 0.0 && !hints.forced_aspect) { - m_videobuffer.iDisplayWidth = m_videobuffer.iWidth; - m_videobuffer.iDisplayHeight = ((int)lrint(m_videobuffer.iWidth / hints.aspect)) & -3; + m_videobuffer.iDisplayWidth = ((int)lrint(m_videobuffer.iHeight * hints.aspect)) & -3; + if (m_videobuffer.iDisplayWidth > m_videobuffer.iWidth) + { + m_videobuffer.iDisplayWidth = m_videobuffer.iWidth; + m_videobuffer.iDisplayHeight = ((int)lrint(m_videobuffer.iWidth / hints.aspect)) & -3; + } } CJobManager::GetInstance().Pause(kJobTypeMediaFlags); From f31eb4ed889a0dce066b79cc3eec7ae5b31ce0e3 Mon Sep 17 00:00:00 2001 From: davilla Date: Thu, 28 Feb 2013 15:12:22 -0500 Subject: [PATCH 171/180] [aml] fix memleak, add queue mutex, cleanup --- .../DVDCodecs/Video/DVDVideoCodecAmlogic.cpp | 30 +++++++++++-------- .../DVDCodecs/Video/DVDVideoCodecAmlogic.h | 1 + 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp index fc67774351a57..f05132ce0ceea 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp @@ -46,11 +46,13 @@ CDVDVideoCodecAmlogic::CDVDVideoCodecAmlogic() : m_framerate(0.0), m_video_rate(0) { + pthread_mutex_init(&m_queue_mutex, NULL); } CDVDVideoCodecAmlogic::~CDVDVideoCodecAmlogic() { Dispose(); + pthread_mutex_destroy(&m_queue_mutex); } bool CDVDVideoCodecAmlogic::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) @@ -141,7 +143,6 @@ bool CDVDVideoCodecAmlogic::Open(CDVDStreamInfo &hints, CDVDCodecOptions &option if (CJobManager::GetInstance().IsProcessing(kJobTypeMediaFlags) > 0) { int timeout_ms = 5000; - // use m_bStop and Sleep so we can get canceled. while (timeout_ms > 0) { if (CJobManager::GetInstance().IsProcessing(kJobTypeMediaFlags) > 0) @@ -161,14 +162,12 @@ bool CDVDVideoCodecAmlogic::Open(CDVDStreamInfo &hints, CDVDCodecOptions &option void CDVDVideoCodecAmlogic::Dispose(void) { if (m_Codec) - { - m_Codec->CloseDecoder(); - m_Codec = NULL; - } - if (m_videobuffer.iFlags & DVP_FLAG_ALLOCATED) - { + m_Codec->CloseDecoder(), m_Codec = NULL; + if (m_videobuffer.iFlags) m_videobuffer.iFlags = 0; - } + while (m_queue_depth) + PtsQueuePop(); + // let thumbgen jobs resume. CJobManager::GetInstance().UnPause(kJobTypeMediaFlags); } @@ -234,10 +233,12 @@ void CDVDVideoCodecAmlogic::PtsQueuePop(void) if (!m_pts_queue || m_queue_depth == 0) return; + pthread_mutex_lock(&m_queue_mutex); // pop the top frame off the queue pts_queue *top_pts = m_pts_queue; m_pts_queue = top_pts->nextpts; m_queue_depth--; + pthread_mutex_unlock(&m_queue_mutex); // and release it free(top_pts); @@ -257,6 +258,8 @@ void CDVDVideoCodecAmlogic::PtsQueuePush(double dts, double pts) else newpts->sort_time = newpts->pts; } + + pthread_mutex_lock(&m_queue_mutex); pts_queue *queueWalker = m_pts_queue; if (!queueWalker || (newpts->sort_time < queueWalker->sort_time)) { @@ -282,6 +285,7 @@ void CDVDVideoCodecAmlogic::PtsQueuePush(double dts, double pts) } } m_queue_depth++; + pthread_mutex_unlock(&m_queue_mutex); } void CDVDVideoCodecAmlogic::FrameRateTracking(double dts, double pts) @@ -292,11 +296,13 @@ void CDVDVideoCodecAmlogic::FrameRateTracking(double dts, double pts) // so make sure we wait for at least 16 values in sorted queue. if (m_queue_depth > 16) { - float cur_pts; - if (m_pts_queue->pts == DVD_NOPTS_VALUE) + pthread_mutex_lock(&m_queue_mutex); + + float cur_pts = m_pts_queue->pts; + if (cur_pts == DVD_NOPTS_VALUE) cur_pts = m_pts_queue->dts; - else - cur_pts = m_pts_queue->pts; + + pthread_mutex_unlock(&m_queue_mutex); float duration = cur_pts - m_last_pts; m_last_pts = cur_pts; diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h index d3584e67767ae..04c4eac90adbc 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h @@ -57,6 +57,7 @@ class CDVDVideoCodecAmlogic : public CDVDVideoCodec double m_last_pts; pts_queue *m_pts_queue; int32_t m_queue_depth; + pthread_mutex_t m_queue_mutex; double m_framerate; int m_video_rate; }; From 7733a3aff70d64d38781a0a48501bbc673312fb6 Mon Sep 17 00:00:00 2001 From: davilla Date: Thu, 28 Feb 2013 17:50:23 -0500 Subject: [PATCH 172/180] [aml] more temp AE fixes, this time from https://github.com/xbmc/xbmc/pull/2320 --- xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 65 ++++----------------- 1 file changed, 10 insertions(+), 55 deletions(-) diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp index ea0807a7a7098..3997f90874dbc 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp @@ -38,7 +38,6 @@ #endif #define ALSA_OPTIONS (SND_PCM_NONBLOCK | SND_PCM_NO_AUTO_FORMAT | SND_PCM_NO_AUTO_CHANNELS | SND_PCM_NO_AUTO_RESAMPLE) -#define ALSA_PERIODS 8 #define ALSA_MAX_CHANNELS 16 static enum AEChannel ALSAChannelMap[ALSA_MAX_CHANNELS + 1] = { @@ -349,69 +348,25 @@ bool CAESinkALSA::InitializeHW(AEAudioFormat &format) } } - unsigned int periods; snd_pcm_uframes_t periodSize, bufferSize; - - snd_pcm_hw_params_get_periods_min(hw_params, &periods, NULL); - snd_pcm_hw_params_get_period_size_min(hw_params, &periodSize, NULL); - snd_pcm_hw_params_get_buffer_size_min(hw_params, &bufferSize); - CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Min: periodSize %lu, periods %u, bufferSize %lu", periodSize, periods, bufferSize); - - snd_pcm_hw_params_get_periods_max(hw_params, &periods, NULL); - snd_pcm_hw_params_get_period_size_max(hw_params, &periodSize, NULL); - snd_pcm_hw_params_get_buffer_size_max(hw_params, &bufferSize); - CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Max: periodSize %lu, periods %u, bufferSize %lu", periodSize, periods, bufferSize); - snd_pcm_hw_params_get_buffer_size_max(hw_params, &bufferSize); - bufferSize = std::min(bufferSize, (snd_pcm_uframes_t)8192); - periodSize = bufferSize / ALSA_PERIODS; - periods = ALSA_PERIODS; + bufferSize = std::min(bufferSize, (snd_pcm_uframes_t) 256 * 1024); + periodSize = 1024; - CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Req: periodSize %lu, periods %u, bufferSize %lu", periodSize, periods, bufferSize); + CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Request: periodSize %lu, bufferSize %lu", periodSize, bufferSize); - /* work on a copy of the hw params */ - snd_pcm_hw_params_t *hw_params_copy; - snd_pcm_hw_params_alloca(&hw_params_copy); + /* try to set the period size and the buffer size*/ + snd_pcm_hw_params_set_period_size_near(m_pcm, hw_params, &periodSize, NULL); + snd_pcm_hw_params_set_buffer_size_near(m_pcm, hw_params, &bufferSize); - /* try to set the buffer size then the period size */ - snd_pcm_hw_params_copy(hw_params_copy, hw_params); - snd_pcm_hw_params_set_buffer_size_near(m_pcm, hw_params_copy, &bufferSize); - snd_pcm_hw_params_set_period_size_near(m_pcm, hw_params_copy, &periodSize, NULL); - snd_pcm_hw_params_set_periods_near (m_pcm, hw_params_copy, &periods , NULL); - if (snd_pcm_hw_params(m_pcm, hw_params_copy) != 0) + if(snd_pcm_hw_params(m_pcm, hw_params) != 0) { - /* try to set the period size then the buffer size */ - snd_pcm_hw_params_copy(hw_params_copy, hw_params); - snd_pcm_hw_params_set_period_size_near(m_pcm, hw_params_copy, &periodSize, NULL); - snd_pcm_hw_params_set_buffer_size_near(m_pcm, hw_params_copy, &bufferSize); - snd_pcm_hw_params_set_periods_near (m_pcm, hw_params_copy, &periods , NULL); - if (snd_pcm_hw_params(m_pcm, hw_params_copy) != 0) - { - /* try to just set the buffer size */ - snd_pcm_hw_params_copy(hw_params_copy, hw_params); - snd_pcm_hw_params_set_buffer_size_near(m_pcm, hw_params_copy, &bufferSize); - snd_pcm_hw_params_set_periods_near (m_pcm, hw_params_copy, &periods , NULL); - if (snd_pcm_hw_params(m_pcm, hw_params_copy) != 0) - { - /* try to just set the period size */ - snd_pcm_hw_params_copy(hw_params_copy, hw_params); - snd_pcm_hw_params_set_period_size_near(m_pcm, hw_params_copy, &periodSize, NULL); - snd_pcm_hw_params_set_periods_near (m_pcm, hw_params_copy, &periods , NULL); - if (snd_pcm_hw_params(m_pcm, hw_params_copy) != 0) - { - CLog::Log(LOGERROR, "CAESinkALSA::InitializeHW - Failed to set the parameters"); - return false; - } - } - } + CLog::Log(LOGERROR, "CAESinkALSA::InitializeHW - Failed to set the parameters"); + return false; } - snd_pcm_hw_params_get_period_size(hw_params_copy, &periodSize, NULL); - snd_pcm_hw_params_get_buffer_size(hw_params_copy, &bufferSize); - - - CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Got: periodSize %lu, periods %u, bufferSize %lu", periodSize, periods, bufferSize); + CLog::Log(LOGDEBUG, "CAESinkALSA::InitializeHW - Got: periodSize %lu, bufferSize %lu", periodSize, bufferSize); /* set the format parameters */ format.m_sampleRate = sampleRate; From f8b834d2ec031a13c0297bb49fabe9aad3864462 Mon Sep 17 00:00:00 2001 From: davilla Date: Thu, 28 Feb 2013 18:35:22 -0500 Subject: [PATCH 173/180] [aml] temp fixes, from frodo 12.1 backports, replace when we merge with 12.1 --- xbmc/Application.cpp | 22 +++++++++++-------- xbmc/network/AirPlayServer.cpp | 2 +- xbmc/network/AirTunesServer.cpp | 33 ++++++++++++++-------------- xbmc/network/EventServer.cpp | 2 +- xbmc/network/Zeroconf.cpp | 4 ++-- xbmc/network/Zeroconf.h | 7 +++--- xbmc/network/linux/ZeroconfAvahi.cpp | 4 ++-- xbmc/network/linux/ZeroconfAvahi.h | 3 ++- xbmc/network/osx/ZeroconfOSX.cpp | 4 ++-- xbmc/network/osx/ZeroconfOSX.h | 3 ++- xbmc/network/windows/ZeroconfWIN.cpp | 4 ++-- xbmc/network/windows/ZeroconfWIN.h | 2 +- 12 files changed, 49 insertions(+), 41 deletions(-) diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp index 219d6bdc58c60..253cdb3b755e1 100644 --- a/xbmc/Application.cpp +++ b/xbmc/Application.cpp @@ -1525,7 +1525,7 @@ bool CApplication::StartWebServer() bool started = false; if (m_WebServer.Start(webPort, g_guiSettings.GetString("services.webserverusername"), g_guiSettings.GetString("services.webserverpassword"))) { - std::map txt; + std::vector > txt; started = true; // publish web frontend and API services #ifdef HAS_WEB_INTERFACE @@ -1575,13 +1575,17 @@ bool CApplication::StartAirplayServer() if (CAirPlayServer::StartServer(listenPort, true)) { CAirPlayServer::SetCredentials(usePassword, password); - std::map txt; - txt["deviceid"] = m_network.GetDefaultConnectionMacAddress(); - if (txt["deviceid"].empty()) - txt["deviceid"] = "FF:FF:FF:FF:FF:F2"; - txt["features"] = "0x77"; - txt["model"] = "AppleTV2,1"; - txt["srcvers"] = AIRPLAY_SERVER_VERSION_STR; + std::vector > txt; + + std::string mac_address(m_network.GetDefaultConnectionMacAddress()); + txt.push_back(std::make_pair("deviceid", m_network.GetDefaultConnectionMacAddress())); + if (mac_address.empty()) + mac_address = "FF:FF:FF:FF:FF:F2"; + txt.push_back(std::make_pair("deviceid", mac_address)); + txt.push_back(std::make_pair("features", "0x77")); + txt.push_back(std::make_pair("model", "Xbmc,1")); + txt.push_back(std::make_pair("srcvers", AIRPLAY_SERVER_VERSION_STR)); + CZeroconf::GetInstance()->PublishService("servers.airplay", "_airplay._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), listenPort, txt); ret = true; } @@ -1625,7 +1629,7 @@ bool CApplication::StartJSONRPCServer() { if (CTCPServer::StartServer(g_advancedSettings.m_jsonTcpPort, g_guiSettings.GetBool("services.esallinterfaces"))) { - std::map txt; + std::vector > txt; CZeroconf::GetInstance()->PublishService("servers.jsonrpc-tpc", "_xbmc-jsonrpc._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), g_advancedSettings.m_jsonTcpPort, txt); return true; } diff --git a/xbmc/network/AirPlayServer.cpp b/xbmc/network/AirPlayServer.cpp index 7fb58faca3407..866728c7b120a 100644 --- a/xbmc/network/AirPlayServer.cpp +++ b/xbmc/network/AirPlayServer.cpp @@ -118,7 +118,7 @@ const char *eventStrings[] = {"playing", "paused", "loading", "stopped"}; "features\r\n"\ "119\r\n"\ "model\r\n"\ -"AppleTV2,1\r\n"\ +"Xbmc,1\r\n"\ "protovers\r\n"\ "1.0\r\n"\ "srcvers\r\n"\ diff --git a/xbmc/network/AirTunesServer.cpp b/xbmc/network/AirTunesServer.cpp index 0c92ceacc5775..ee55de4777569 100644 --- a/xbmc/network/AirTunesServer.cpp +++ b/xbmc/network/AirTunesServer.cpp @@ -495,22 +495,23 @@ bool CAirTunesServer::StartServer(int port, bool nonlocal, bool usePassword, con CStdString appName; appName.Format("%s@%s", m_macAddress.c_str(), g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME).c_str()); - std::map txt; - txt["cn"] = "0,1"; - txt["ch"] = "2"; - txt["ek"] = "1"; - txt["et"] = "0,1"; - txt["sv"] = "false"; - txt["tp"] = "UDP"; - txt["sm"] = "false"; - txt["ss"] = "16"; - txt["sr"] = "44100"; - txt["pw"] = "false"; - txt["vn"] = "3"; - txt["da"] = "true"; - txt["vs"] = "130.14"; - txt["md"] = "0,1,2"; - txt["txtvers"] = "1"; + std::vector > txt; + txt.push_back(std::make_pair("txtvers", "1")); + txt.push_back(std::make_pair("cn", "0,1")); + txt.push_back(std::make_pair("ch", "2")); + txt.push_back(std::make_pair("ek", "1")); + txt.push_back(std::make_pair("et", "0,1")); + txt.push_back(std::make_pair("sv", "false")); + txt.push_back(std::make_pair("tp", "UDP")); + txt.push_back(std::make_pair("sm", "false")); + txt.push_back(std::make_pair("ss", "16")); + txt.push_back(std::make_pair("sr", "44100")); + txt.push_back(std::make_pair("pw", "false")); + txt.push_back(std::make_pair("vn", "3")); + txt.push_back(std::make_pair("da", "true")); + txt.push_back(std::make_pair("vs", "130.14")); + txt.push_back(std::make_pair("md", "0,1,2")); + txt.push_back(std::make_pair("am", "Xbmc,1")); CZeroconf::GetInstance()->PublishService("servers.airtunes", "_raop._tcp", appName, port, txt); } diff --git a/xbmc/network/EventServer.cpp b/xbmc/network/EventServer.cpp index b4fd8c437157c..beb6c79bafc01 100644 --- a/xbmc/network/EventServer.cpp +++ b/xbmc/network/EventServer.cpp @@ -155,7 +155,7 @@ void CEventServer::Run() CAddress any_addr; CSocketListener listener; int packetSize = 0; - std::map txt; + std::vector > txt; CLog::Log(LOGNOTICE, "ES: Starting UDP Event server on %s:%d", any_addr.Address(), m_iPort); diff --git a/xbmc/network/Zeroconf.cpp b/xbmc/network/Zeroconf.cpp index e83eced22ac4e..ec69f70a3a14c 100644 --- a/xbmc/network/Zeroconf.cpp +++ b/xbmc/network/Zeroconf.cpp @@ -43,7 +43,7 @@ //should be optimized away class CZeroconfDummy : public CZeroconf { - virtual bool doPublishService(const std::string&, const std::string&, const std::string&, unsigned int, std::map) + virtual bool doPublishService(const std::string&, const std::string&, const std::string&, unsigned int, const std::vector >&) { return false; } @@ -68,7 +68,7 @@ bool CZeroconf::PublishService(const std::string& fcr_identifier, const std::string& fcr_type, const std::string& fcr_name, unsigned int f_port, - std::map txt) + const std::vector >& txt) { CSingleLock lock(*mp_crit_sec); CZeroconf::PublishInfo info = {fcr_type, fcr_name, f_port, txt}; diff --git a/xbmc/network/Zeroconf.h b/xbmc/network/Zeroconf.h index 52075a5b07ee6..377f817d0f4f3 100644 --- a/xbmc/network/Zeroconf.h +++ b/xbmc/network/Zeroconf.h @@ -22,6 +22,7 @@ #include #include +#include #include "utils/Job.h" class CCriticalSection; @@ -49,7 +50,7 @@ class CZeroconf const std::string& fcr_type, const std::string& fcr_name, unsigned int f_port, - std::map txt); + const std::vector >& txt); ///removes the specified service ///returns false if fcr_identifier does not exist @@ -86,7 +87,7 @@ class CZeroconf const std::string& fcr_type, const std::string& fcr_name, unsigned int f_port, - std::map txt) = 0; + const std::vector >& txt) = 0; //removes the service if published virtual bool doRemoveService(const std::string& fcr_ident) = 0; @@ -107,7 +108,7 @@ class CZeroconf std::string type; std::string name; unsigned int port; - std::map txt; + std::vector > txt; }; //protects data diff --git a/xbmc/network/linux/ZeroconfAvahi.cpp b/xbmc/network/linux/ZeroconfAvahi.cpp index 8214bb4021349..158f7b21bf6e2 100644 --- a/xbmc/network/linux/ZeroconfAvahi.cpp +++ b/xbmc/network/linux/ZeroconfAvahi.cpp @@ -131,7 +131,7 @@ bool CZeroconfAvahi::doPublishService(const std::string& fcr_identifier, const std::string& fcr_type, const std::string& fcr_name, unsigned int f_port, - std::map txt) + const std::vector >& txt) { CLog::Log(LOGDEBUG, "CZeroconfAvahi::doPublishService identifier: %s type: %s name:%s port:%i", fcr_identifier.c_str(), fcr_type.c_str(), fcr_name.c_str(), f_port); @@ -145,7 +145,7 @@ bool CZeroconfAvahi::doPublishService(const std::string& fcr_identifier, //txt records to AvahiStringList AvahiStringList *txtList = NULL; - for(std::map::iterator it=txt.begin(); it!=txt.end(); it++) + for(std::vector >::const_iterator it=txt.begin(); it!=txt.end(); it++) { txtList = avahi_string_list_add_pair(txtList, it->first.c_str(), it->second.c_str()); } diff --git a/xbmc/network/linux/ZeroconfAvahi.h b/xbmc/network/linux/ZeroconfAvahi.h index b6881c14f62ad..704f2a2f7c22d 100644 --- a/xbmc/network/linux/ZeroconfAvahi.h +++ b/xbmc/network/linux/ZeroconfAvahi.h @@ -25,6 +25,7 @@ #include #include +#include #include #include "network/Zeroconf.h" @@ -47,7 +48,7 @@ class CZeroconfAvahi : public CZeroconf const std::string& fcr_type, const std::string& fcr_name, unsigned int f_port, - std::map txt); + const std::vector >& txt); virtual bool doRemoveService(const std::string& fcr_ident); diff --git a/xbmc/network/osx/ZeroconfOSX.cpp b/xbmc/network/osx/ZeroconfOSX.cpp index b50d310aacf98..10291e37849e3 100644 --- a/xbmc/network/osx/ZeroconfOSX.cpp +++ b/xbmc/network/osx/ZeroconfOSX.cpp @@ -44,7 +44,7 @@ bool CZeroconfOSX::doPublishService(const std::string& fcr_identifier, const std::string& fcr_type, const std::string& fcr_name, unsigned int f_port, - std::map txt) + const std::vector >& txt) { CLog::Log(LOGDEBUG, "CZeroconfOSX::doPublishService identifier: %s type: %s name:%s port:%i", fcr_identifier.c_str(), fcr_type.c_str(), fcr_name.c_str(), f_port); @@ -74,7 +74,7 @@ bool CZeroconfOSX::doPublishService(const std::string& fcr_identifier, //txt map to dictionary CFDataRef txtData = NULL; CFMutableDictionaryRef txtDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - for(std::map::const_iterator it = txt.begin(); it != txt.end(); ++it) + for(std::vector >::const_iterator it = txt.begin(); it != txt.end(); ++it) { CFStringRef key = CFStringCreateWithCString (NULL, it->first.c_str(), diff --git a/xbmc/network/osx/ZeroconfOSX.h b/xbmc/network/osx/ZeroconfOSX.h index fb4409dcf617b..34aeb6dec013d 100644 --- a/xbmc/network/osx/ZeroconfOSX.h +++ b/xbmc/network/osx/ZeroconfOSX.h @@ -20,6 +20,7 @@ */ #include +#include #include "network/Zeroconf.h" #include "threads/CriticalSection.h" @@ -42,7 +43,7 @@ class CZeroconfOSX : public CZeroconf const std::string& fcr_type, const std::string& fcr_name, unsigned int f_port, - std::map txt); + const std::vector >& txt); bool doRemoveService(const std::string& fcr_ident); diff --git a/xbmc/network/windows/ZeroconfWIN.cpp b/xbmc/network/windows/ZeroconfWIN.cpp index e879bc8bbbdba..eddc98afd047a 100644 --- a/xbmc/network/windows/ZeroconfWIN.cpp +++ b/xbmc/network/windows/ZeroconfWIN.cpp @@ -62,7 +62,7 @@ bool CZeroconfWIN::doPublishService(const std::string& fcr_identifier, const std::string& fcr_type, const std::string& fcr_name, unsigned int f_port, - std::map txt) + const std::vector >& txt) { DNSServiceRef netService = NULL; TXTRecordRef txtRecord; @@ -87,7 +87,7 @@ bool CZeroconfWIN::doPublishService(const std::string& fcr_identifier, //add txt records if(!txt.empty()) { - for(std::map::const_iterator it = txt.begin(); it != txt.end(); ++it) + for(std::vector >::const_iterator it = txt.begin(); it != txt.end(); ++it) { CLog::Log(LOGDEBUG, "ZeroconfWIN: key:%s, value:%s",it->first.c_str(),it->second.c_str()); uint8_t txtLen = (uint8_t)strlen(it->second.c_str()); diff --git a/xbmc/network/windows/ZeroconfWIN.h b/xbmc/network/windows/ZeroconfWIN.h index 3b9e3d6616d45..d8d4f2f59d40a 100644 --- a/xbmc/network/windows/ZeroconfWIN.h +++ b/xbmc/network/windows/ZeroconfWIN.h @@ -36,7 +36,7 @@ class CZeroconfWIN : public CZeroconf const std::string& fcr_type, const std::string& fcr_name, unsigned int f_port, - std::map txt); + const std::vector >& txt); bool doRemoveService(const std::string& fcr_ident); From be362430291d20fca53453a1aded83d0c157686e Mon Sep 17 00:00:00 2001 From: davilla Date: Sat, 2 Mar 2013 11:22:45 -0500 Subject: [PATCH 174/180] [aml] fixed double deviceid from f8b834d2ec031a13c0297bb49fabe9aad3864462 --- xbmc/Application.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp index 253cdb3b755e1..6367e1b77523f 100644 --- a/xbmc/Application.cpp +++ b/xbmc/Application.cpp @@ -1578,7 +1578,6 @@ bool CApplication::StartAirplayServer() std::vector > txt; std::string mac_address(m_network.GetDefaultConnectionMacAddress()); - txt.push_back(std::make_pair("deviceid", m_network.GetDefaultConnectionMacAddress())); if (mac_address.empty()) mac_address = "FF:FF:FF:FF:FF:F2"; txt.push_back(std::make_pair("deviceid", mac_address)); From acc683feb4083a20c46b88b8d9b1dd8a33b7a239 Mon Sep 17 00:00:00 2001 From: davilla Date: Sat, 2 Mar 2013 11:23:28 -0500 Subject: [PATCH 175/180] [aml] temp fixes, from frodo 12.1 backports, replace when we merge with 12.1 --- xbmc/network/AirTunesServer.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/xbmc/network/AirTunesServer.cpp b/xbmc/network/AirTunesServer.cpp index ee55de4777569..95a43c1bf0be8 100644 --- a/xbmc/network/AirTunesServer.cpp +++ b/xbmc/network/AirTunesServer.cpp @@ -147,6 +147,7 @@ LAuE4Pu13aKiJnfft7hIjbK+5kyb3TysZvoyDnb3HOKvInK7vXbKuU4ISgxB2bB3HcYzQMGsz1qJ\ void CAirTunesServer::AudioOutputFunctions::audio_set_metadata(void *cls, void *session, const void *buffer, int buflen) { + return; CAirTunesServer::SetMetadataFromBuffer((char *)buffer, buflen); } @@ -338,7 +339,11 @@ ao_device* CAirTunesServer::AudioOutputFunctions::ao_open_live(int driver_id, ao header.durationMs = 0; if (device->pipe->Write(&header, sizeof(header)) == 0) + { + delete device->pipe; + delete device; return 0; + } ThreadMessage tMsg = { TMSG_MEDIA_STOP }; CApplicationMessenger::Get().SendMessage(tMsg, true); @@ -650,7 +655,7 @@ bool CAirTunesServer::Initialize(const CStdString &password) if (m_pLibShairport->Load()) { - struct AudioOutput ao; + struct AudioOutput ao = {0}; ao.ao_initialize = AudioOutputFunctions::ao_initialize; ao.ao_play = AudioOutputFunctions::ao_play; ao.ao_default_driver_id = AudioOutputFunctions::ao_default_driver_id; From 0f782a8a86eef5b075fc85172b8a95eb61b72225 Mon Sep 17 00:00:00 2001 From: davilla Date: Sat, 2 Mar 2013 11:24:05 -0500 Subject: [PATCH 176/180] [aml] fixed, do not talk to codec if it is not open yet --- .../dvdplayer/DVDCodecs/Video/AMLCodec.cpp | 25 +++++++++++++++++++ .../dvdplayer/DVDCodecs/Video/AMLCodec.h | 1 + .../DVDCodecs/Video/DVDVideoCodecAmlogic.cpp | 16 +++++++++--- 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp index a613311face16..c813e6b28bc13 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -1427,6 +1427,7 @@ int set_header_info(am_private_t *para) /*************************************************************************/ CAMLCodec::CAMLCodec() : CThread("CAMLCodec") { + m_opened = false; am_private = new am_private_t; memset(am_private, 0, sizeof(am_private_t)); m_dll = new DllLibAmCodec; @@ -1647,6 +1648,8 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) g_renderManager.RegisterRenderUpdateCallBack((const void*)this, RenderUpdateCallBack); g_renderManager.RegisterRenderFeaturesCallBack((const void*)this, RenderFeaturesCallBack); + m_opened = true; + return true; } @@ -1659,6 +1662,8 @@ void CAMLCodec::CloseDecoder() g_renderManager.RegisterRenderFeaturesCallBack((const void*)NULL, NULL); m_dll->codec_close(&am_private->vcodec); + m_opened = false; + am_packet_release(&am_private->am_pkt); free(am_private->extradata); am_private->extradata = NULL; @@ -1666,12 +1671,16 @@ void CAMLCodec::CloseDecoder() aml_set_sysfs_int("/sys/class/tsync/enable", 1); ShowMainVideo(false); + } void CAMLCodec::Reset() { CLog::Log(LOGDEBUG, "CAMLCodec::Reset"); + if (!m_opened) + return; + // set the system blackout_policy to leave the last frame showing int blackout_policy = aml_get_sysfs_int("/sys/class/video/blackout_policy"); aml_set_sysfs_int("/sys/class/video/blackout_policy", 0); @@ -1704,6 +1713,9 @@ void CAMLCodec::Reset() int CAMLCodec::Decode(unsigned char *pData, size_t size, double dts, double pts) { + if (!m_opened) + return VC_BUFFER; + // grr, m_RenderUpdateCallBackFn in g_renderManager is NULL'ed during // g_renderManager.Configure call by player, which happens after the codec // OpenDecoder call. So we need to restore it but it does not seem to stick :) @@ -1781,6 +1793,9 @@ int CAMLCodec::Decode(unsigned char *pData, size_t size, double dts, double pts) bool CAMLCodec::GetPicture(DVDVideoPicture *pDvdVideoPicture) { + if (!m_opened) + return false; + pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED; pDvdVideoPicture->format = RENDER_FMT_BYPASS; pDvdVideoPicture->iDuration = (double)(am_private->video_rate * DVD_TIME_BASE) / UNIT_FREQ; @@ -1797,6 +1812,10 @@ bool CAMLCodec::GetPicture(DVDVideoPicture *pDvdVideoPicture) void CAMLCodec::SetSpeed(int speed) { CLog::Log(LOGDEBUG, "CAMLCodec::SetSpeed, speed(%d)", speed); + + if (!m_opened) + return; + if (m_speed != speed) { switch(speed) @@ -1822,6 +1841,9 @@ void CAMLCodec::SetSpeed(int speed) int CAMLCodec::GetDataSize() { + if (!m_opened) + return 0; + struct buf_status vbuf ={0}; if (m_dll->codec_get_vbuf_state(&am_private->vcodec, &vbuf) >= 0) m_vbufsize = vbuf.size; @@ -1831,6 +1853,9 @@ int CAMLCodec::GetDataSize() double CAMLCodec::GetTimeSize() { + if (!m_opened) + return 0; + // if m_cur_pts is zero, hw decoder was not started yet // so we use the pts of the 1st demux packet that was send // to hw decoder to calc timesize. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.h index e0e293a7efd71..9da94e9ec3ea9 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.h +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.h @@ -64,6 +64,7 @@ class CAMLCodec : public CThread static void RenderUpdateCallBack(const void *ctx, const CRect &SrcRect, const CRect &DestRect); DllLibAmCodec *m_dll; + bool m_opened; am_private_t *am_private; volatile int m_speed; volatile int64_t m_1st_pts; diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp index f05132ce0ceea..2c8fb03e0d0bc 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp @@ -203,7 +203,8 @@ void CDVDVideoCodecAmlogic::Reset(void) bool CDVDVideoCodecAmlogic::GetPicture(DVDVideoPicture* pDvdVideoPicture) { - m_Codec->GetPicture(&m_videobuffer); + if (m_Codec) + m_Codec->GetPicture(&m_videobuffer); *pDvdVideoPicture = m_videobuffer; return true; @@ -215,17 +216,24 @@ void CDVDVideoCodecAmlogic::SetDropState(bool bDrop) void CDVDVideoCodecAmlogic::SetSpeed(int iSpeed) { - m_Codec->SetSpeed(iSpeed); + if (m_Codec) + m_Codec->SetSpeed(iSpeed); } int CDVDVideoCodecAmlogic::GetDataSize(void) { - return m_Codec->GetDataSize(); + if (m_Codec) + return m_Codec->GetDataSize(); + else + return 0; } double CDVDVideoCodecAmlogic::GetTimeSize(void) { - return m_Codec->GetTimeSize(); + if (m_Codec) + return m_Codec->GetTimeSize(); + else + return 0; } void CDVDVideoCodecAmlogic::PtsQueuePop(void) From 2af1db8b12beffb556ec9093bde827950c5f1e67 Mon Sep 17 00:00:00 2001 From: davilla Date: Sun, 3 Mar 2013 09:01:44 -0500 Subject: [PATCH 177/180] [aml] fixed ffmpeg-rtp to use four byte startcodes --- lib/ffmpeg/libavformat/rtpdec_h264.c | 4 ++-- .../0036-rtp-use-four-byte-startcodes.patch | 23 +++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 lib/ffmpeg/patches/0036-rtp-use-four-byte-startcodes.patch diff --git a/lib/ffmpeg/libavformat/rtpdec_h264.c b/lib/ffmpeg/libavformat/rtpdec_h264.c index 730ed14807828..d8c87f4d6ef9c 100644 --- a/lib/ffmpeg/libavformat/rtpdec_h264.c +++ b/lib/ffmpeg/libavformat/rtpdec_h264.c @@ -113,7 +113,7 @@ static int sdp_parse_fmtp_config_h264(AVStream * stream, h264_data->level_idc = level_idc; } } else if (!strcmp(attr, "sprop-parameter-sets")) { - uint8_t start_sequence[]= { 0, 0, 1 }; + uint8_t start_sequence[]= { 0, 0, 0, 1 }; codec->extradata_size= 0; codec->extradata= NULL; @@ -176,7 +176,7 @@ static int h264_handle_packet(AVFormatContext *ctx, uint8_t nal = buf[0]; uint8_t type = (nal & 0x1f); int result= 0; - uint8_t start_sequence[]= {0, 0, 1}; + uint8_t start_sequence[]= {0, 0, 0, 1}; #ifdef DEBUG assert(data); diff --git a/lib/ffmpeg/patches/0036-rtp-use-four-byte-startcodes.patch b/lib/ffmpeg/patches/0036-rtp-use-four-byte-startcodes.patch new file mode 100644 index 0000000000000..48a1cdd32eaed --- /dev/null +++ b/lib/ffmpeg/patches/0036-rtp-use-four-byte-startcodes.patch @@ -0,0 +1,23 @@ +diff --git a/lib/ffmpeg/libavformat/rtpdec_h264.c b/lib/ffmpeg/libavformat/rtpdec_h264.c +index 730ed14..d8c87f4 100644 +--- a/lib/ffmpeg/libavformat/rtpdec_h264.c ++++ b/lib/ffmpeg/libavformat/rtpdec_h264.c +@@ -113,7 +113,7 @@ static int sdp_parse_fmtp_config_h264(AVStream * stream, + h264_data->level_idc = level_idc; + } + } else if (!strcmp(attr, "sprop-parameter-sets")) { +- uint8_t start_sequence[]= { 0, 0, 1 }; ++ uint8_t start_sequence[]= { 0, 0, 0, 1 }; + codec->extradata_size= 0; + codec->extradata= NULL; + +@@ -176,7 +176,7 @@ static int h264_handle_packet(AVFormatContext *ctx, + uint8_t nal = buf[0]; + uint8_t type = (nal & 0x1f); + int result= 0; +- uint8_t start_sequence[]= {0, 0, 1}; ++ uint8_t start_sequence[]= {0, 0, 0, 1}; + + #ifdef DEBUG + assert(data); + From bd0da6766ed5b23aa39f645ce0800dd0d31260e8 Mon Sep 17 00:00:00 2001 From: davilla Date: Sun, 3 Mar 2013 09:30:20 -0500 Subject: [PATCH 178/180] [aml] fixed ffmpeg-rtp, try tcp first --- lib/ffmpeg/libavformat/rtsp.h | 4 ++-- lib/ffmpeg/patches/0037-rtp-try-tcp-first.patch | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 lib/ffmpeg/patches/0037-rtp-try-tcp-first.patch diff --git a/lib/ffmpeg/libavformat/rtsp.h b/lib/ffmpeg/libavformat/rtsp.h index f67ceb89cad03..fa607bbc46ea2 100644 --- a/lib/ffmpeg/libavformat/rtsp.h +++ b/lib/ffmpeg/libavformat/rtsp.h @@ -35,8 +35,8 @@ * Network layer over which RTP/etc packet data will be transported. */ enum RTSPLowerTransport { - RTSP_LOWER_TRANSPORT_UDP = 0, /**< UDP/unicast */ - RTSP_LOWER_TRANSPORT_TCP = 1, /**< TCP; interleaved in RTSP */ + RTSP_LOWER_TRANSPORT_TCP = 0, /**< TCP; interleaved in RTSP */ + RTSP_LOWER_TRANSPORT_UDP = 1, /**< UDP/unicast */ RTSP_LOWER_TRANSPORT_UDP_MULTICAST = 2, /**< UDP/multicast */ RTSP_LOWER_TRANSPORT_NB, RTSP_LOWER_TRANSPORT_HTTP = 8, /**< HTTP tunneled - not a proper diff --git a/lib/ffmpeg/patches/0037-rtp-try-tcp-first.patch b/lib/ffmpeg/patches/0037-rtp-try-tcp-first.patch new file mode 100644 index 0000000000000..9405404fa19f8 --- /dev/null +++ b/lib/ffmpeg/patches/0037-rtp-try-tcp-first.patch @@ -0,0 +1,16 @@ +diff --git a/lib/ffmpeg/libavformat/rtsp.h b/lib/ffmpeg/libavformat/rtsp.h +index f67ceb8..fa607bb 100644 +--- a/lib/ffmpeg/libavformat/rtsp.h ++++ b/lib/ffmpeg/libavformat/rtsp.h +@@ -35,8 +35,8 @@ + * Network layer over which RTP/etc packet data will be transported. + */ + enum RTSPLowerTransport { +- RTSP_LOWER_TRANSPORT_UDP = 0, /**< UDP/unicast */ +- RTSP_LOWER_TRANSPORT_TCP = 1, /**< TCP; interleaved in RTSP */ ++ RTSP_LOWER_TRANSPORT_TCP = 0, /**< TCP; interleaved in RTSP */ ++ RTSP_LOWER_TRANSPORT_UDP = 1, /**< UDP/unicast */ + RTSP_LOWER_TRANSPORT_UDP_MULTICAST = 2, /**< UDP/multicast */ + RTSP_LOWER_TRANSPORT_NB, + RTSP_LOWER_TRANSPORT_HTTP = 8, /**< HTTP tunneled - not a proper + From 4b20706ed29721d3896a683289739d62013db2d1 Mon Sep 17 00:00:00 2001 From: davilla Date: Sun, 3 Mar 2013 09:29:17 -0500 Subject: [PATCH 179/180] [aml] fixed ffmpeg-rtp, nb_rtsp_streams bug on send SETUP cmd --- lib/ffmpeg/libavformat/rtsp.c | 2 +- ...fix-nb_rtsp_streams-bug-on-send-SETUP-cmd.patch | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 lib/ffmpeg/patches/0038-rtp-fix-nb_rtsp_streams-bug-on-send-SETUP-cmd.patch diff --git a/lib/ffmpeg/libavformat/rtsp.c b/lib/ffmpeg/libavformat/rtsp.c index 2fccea1bea37f..9714695eb02f9 100644 --- a/lib/ffmpeg/libavformat/rtsp.c +++ b/lib/ffmpeg/libavformat/rtsp.c @@ -403,7 +403,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, break; case 'a': if (av_strstart(p, "control:", &p)) { - if (s->nb_streams == 0) { + if (rt->nb_rtsp_streams == 0) { if (!strncmp(p, "rtsp://", 7)) av_strlcpy(rt->control_uri, p, sizeof(rt->control_uri)); diff --git a/lib/ffmpeg/patches/0038-rtp-fix-nb_rtsp_streams-bug-on-send-SETUP-cmd.patch b/lib/ffmpeg/patches/0038-rtp-fix-nb_rtsp_streams-bug-on-send-SETUP-cmd.patch new file mode 100644 index 0000000000000..b8b3cd5593aad --- /dev/null +++ b/lib/ffmpeg/patches/0038-rtp-fix-nb_rtsp_streams-bug-on-send-SETUP-cmd.patch @@ -0,0 +1,14 @@ +diff --git a/lib/ffmpeg/libavformat/rtsp.c b/lib/ffmpeg/libavformat/rtsp.c +index 2fccea1..9714695 100644 +--- a/lib/ffmpeg/libavformat/rtsp.c ++++ b/lib/ffmpeg/libavformat/rtsp.c +@@ -403,7 +403,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, + break; + case 'a': + if (av_strstart(p, "control:", &p)) { +- if (s->nb_streams == 0) { ++ if (rt->nb_rtsp_streams == 0) { + if (!strncmp(p, "rtsp://", 7)) + av_strlcpy(rt->control_uri, p, + sizeof(rt->control_uri)); + From c61227413d0cac6014c57bf472cb6ec5aa21eef5 Mon Sep 17 00:00:00 2001 From: toys4me Date: Mon, 4 Mar 2013 09:17:02 -0800 Subject: [PATCH 180/180] Add lastgood configuration to Loadsettings for guisettings If guisettings == OK, then make a copy to .lastgood If guisettings != OK, then rename to .bad and try to load .lastgood if guisettings != OK, and .lastgood not exist or bad then Reset. --- xbmc/settings/Settings.cpp | 69 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/xbmc/settings/Settings.cpp b/xbmc/settings/Settings.cpp index 76fe784b50f29..c377abeba68dd 100644 --- a/xbmc/settings/Settings.cpp +++ b/xbmc/settings/Settings.cpp @@ -172,6 +172,47 @@ bool CSettings::Load() CLog::Log(LOGNOTICE, "loading %s", GetSettingsFile().c_str()); if (!LoadSettings(GetSettingsFile())) { + CLog::Log(LOGERROR, "Unable to load %s file, appears to be bad", GetSettingsFile().c_str()); + // Move bad settings file to ".bad" + // Delete old ".bad" file if it exists + if (CFile::Exists(GetSettingsFile() + ".bad")) + CFile::Delete(GetSettingsFile() + ".bad"); + // Rename current file to .bad + CFile::Rename(GetSettingsFile(),GetSettingsFile() + ".bad"); + // Check if lastgood exists so we can restore it + if (CFile::Exists(GetSettingsFile() + ".lastgood")) + { + CLog::Log(LOGERROR, "Trying to restore .lastgood for %s file", GetSettingsFile().c_str()); + // try to restore lastgood if it exists + // we copy instead of rename, so lastgood exist even if this goes bad + CFile source_settings, dest_settings; + char * cpybuffer; + int bytes_read; + cpybuffer = (char*) malloc(sizeof(char) * 32768); + if (cpybuffer != NULL) + { + if (source_settings.Open(GetSettingsFile() + ".lastgood",0)) + { + if (dest_settings.OpenForWrite(GetSettingsFile())) + { + while ( (bytes_read = source_settings.Read(cpybuffer, 32768)) > 0 ) + { + dest_settings.Write(cpybuffer,bytes_read); + } + dest_settings.Close(); + } + source_settings.Close(); + // Try loading the lastgood backup + if ( LoadSettings(GetSettingsFile()) ) + { + CLog::Log(LOGERROR, "System has been restored to last good configuration for %s file", GetSettingsFile().c_str()); + return true; + } + } + free(cpybuffer); + } + } + CLog::Log(LOGERROR, "Unable to load %s, creating new %s with default values", GetSettingsFile().c_str(), GetSettingsFile().c_str()); if (!Reset()) return false; @@ -817,6 +858,34 @@ bool CSettings::LoadSettings(const CStdString& strSettingsFile) CLog::Log(LOGNOTICE, "Disabled debug logging due to GUI setting. Level %d.", g_advancedSettings.m_logLevel); } CLog::SetLogLevel(g_advancedSettings.m_logLevel); + + // + // Settings file looks good, lets back it up to be safe + // back up settings file to what ever its named with a .lastgood extension + + CFile source_settings, dest_settings; + char * cpybuffer; + int bytes_read; + + cpybuffer = (char*) malloc(sizeof(char) * 32768); + if (cpybuffer != NULL) + { + CFile::Delete(strSettingsFile + ".lastgood"); + if (source_settings.Open(strSettingsFile,0)) + { + if (dest_settings.OpenForWrite(strSettingsFile + ".lastgood")) + { + while ( (bytes_read = source_settings.Read(cpybuffer, 32768)) > 0 ) + { + dest_settings.Write(cpybuffer,bytes_read); + } + dest_settings.Close(); + } + source_settings.Close(); + } + free(cpybuffer); + } + return true; }