Index: skin/Project Mayhem III/PAL/Home.xml =================================================================== --- skin/Project Mayhem III/PAL/Home.xml (revision 30593) +++ skin/Project Mayhem III/PAL/Home.xml (working copy) @@ -680,6 +680,7 @@ 96 9 5 + XBMC.System.PWMControl(#FF0000) home-focus.gif - 30 @@ -705,6 +706,7 @@ 96 2 3 + XBMC.System.PWMControl(#00FF00) home-focus.gif - 30 @@ -730,6 +732,7 @@ 96 5 4 + XBMC.System.PWMControl(#FFFFFF,#000000,#000000,#000000,firework,500) home-focus.gif - 30 @@ -755,6 +758,7 @@ 96 3 7 + XBMC.System.PWMControl(#FF00FF) home-focus.gif - 30 @@ -780,6 +784,7 @@ 96 4 9 + XBMC.System.PWMControl(#FFFF00) home-focus.gif - 30 @@ -820,6 +825,7 @@ 6 10 5 + XBMC.System.PWMControl(#00FFFF) home-focus.gif - 20 @@ -838,6 +844,7 @@ 96 10 5 + XBMC.System.PWMControl(#FFFFFF) home-focus.gif - 20 Index: userdata/AdvancedSettings.xml =================================================================== --- userdata/AdvancedSettings.xml (revision 0) +++ userdata/AdvancedSettings.xml (revision 0) @@ -0,0 +1,13 @@ + + + true + 30 + 1 + 1.2 + 1.0 + 0.8 + 2 + 50 + 20 + + Index: xbmc/AdvancedSettings.cpp =================================================================== --- xbmc/AdvancedSettings.cpp (revision 30593) +++ xbmc/AdvancedSettings.cpp (working copy) @@ -217,6 +217,22 @@ m_bAutoFatxLimit = true; m_bgInfoLoaderMaxThreads = 1; + + m_ambiLight = false; + m_ambiLightSpaceBetweenPixels = 30; + m_ambiLightFloatingAverageFrames = 1; + m_ambiLightMinRGB = 2; + m_ambiLightMaxRGB = 255; + m_ambiLightMode = "linear"; + m_ambiLightPosition = "all"; + m_ambiLightGammaR = 1.2f; + m_ambiLightGammaG = 1.0f; + m_ambiLightGammaB = 0.8f; + m_ambiLightIntensityR = 1.0f; + m_ambiLightIntensityG = 1.0f; + m_ambiLightIntensityB = 1.0f; + m_ambiLightFilterThreshold = 50; + m_ambiLightDarknessLimit = 20; } bool CAdvancedSettings::Load() @@ -432,6 +448,26 @@ XMLUtils::GetBoolean(pElement, "verbose", m_bPythonVerbose); } + pElement = pRootElement->FirstChildElement("ambilight"); + if (pElement) + { + XMLUtils::GetBoolean(pElement, "enabled", m_ambiLight); + XMLUtils::GetInt(pElement, "spaceBetweenPixels", m_ambiLightSpaceBetweenPixels); + XMLUtils::GetInt(pElement, "floatingAverageFrames", m_ambiLightFloatingAverageFrames); + XMLUtils::GetInt(pElement, "minRGB", m_ambiLightMinRGB); + XMLUtils::GetInt(pElement, "maxRGB", m_ambiLightMaxRGB); + XMLUtils::GetString(pElement, "mode", m_ambiLightMode); + XMLUtils::GetString(pElement, "position", m_ambiLightPosition); + XMLUtils::GetFloat(pElement, "gammaR", m_ambiLightGammaR); + XMLUtils::GetFloat(pElement, "gammaG", m_ambiLightGammaG); + XMLUtils::GetFloat(pElement, "gammaB", m_ambiLightGammaB); + XMLUtils::GetFloat(pElement, "intensityR", m_ambiLightIntensityR); + XMLUtils::GetFloat(pElement, "intensityG", m_ambiLightIntensityG); + XMLUtils::GetFloat(pElement, "intensityB", m_ambiLightIntensityB); + XMLUtils::GetInt(pElement, "filterThreshold", m_ambiLightFilterThreshold); + XMLUtils::GetInt(pElement, "darknessLimit", m_ambiLightDarknessLimit); + } + XMLUtils::GetBoolean(pRootElement, "autofatxlimit", m_bAutoFatxLimit); XMLUtils::GetString(pRootElement, "cddbaddress", m_cddbAddress); Index: xbmc/AdvancedSettings.h =================================================================== --- xbmc/AdvancedSettings.h (revision 30593) +++ xbmc/AdvancedSettings.h (working copy) @@ -41,183 +41,199 @@ class CAdvancedSettings { - public: - CAdvancedSettings(); +public: + CAdvancedSettings(); - bool Load(); - void Clear(); + bool Load(); + void Clear(); - static void GetCustomTVRegexps(TiXmlElement *pRootElement, SETTINGS_TVSHOWLIST& settings); - static void GetCustomRegexps(TiXmlElement *pRootElement, CStdStringArray& settings); - static void GetCustomRegexpReplacers(TiXmlElement *pRootElement, CStdStringArray& settings); - static void GetCustomExtensions(TiXmlElement *pRootElement, CStdString& extensions); + static void GetCustomTVRegexps(TiXmlElement *pRootElement, SETTINGS_TVSHOWLIST& settings); + static void GetCustomRegexps(TiXmlElement *pRootElement, CStdStringArray& settings); + static void GetCustomRegexpReplacers(TiXmlElement *pRootElement, CStdStringArray& settings); + static void GetCustomExtensions(TiXmlElement *pRootElement, CStdString& extensions); - // multipath testing - // multipath testing - bool m_useMultipaths; - bool m_DisableModChipDetection; + // multipath testing + // multipath testing + bool m_useMultipaths; + bool m_DisableModChipDetection; - int m_audioHeadRoom; - float m_karaokeSyncDelay; - float m_ac3Gain; - float m_audioPlayCountMinimumPercent; + int m_audioHeadRoom; + float m_karaokeSyncDelay; + float m_ac3Gain; + float m_audioPlayCountMinimumPercent; - float m_videoSubsDelayRange; - float m_videoAudioDelayRange; - int m_videoSmallStepBackSeconds; - int m_videoSmallStepBackTries; - int m_videoSmallStepBackDelay; - bool m_videoUseTimeSeeking; - int m_videoTimeSeekForward; - int m_videoTimeSeekBackward; - int m_videoTimeSeekForwardBig; - int m_videoTimeSeekBackwardBig; - int m_videoPercentSeekForward; - int m_videoPercentSeekBackward; - int m_videoPercentSeekForwardBig; - int m_videoPercentSeekBackwardBig; - CStdString m_videoPPFFmpegDeint; - CStdString m_videoPPFFmpegPostProc; + float m_videoSubsDelayRange; + float m_videoAudioDelayRange; + int m_videoSmallStepBackSeconds; + int m_videoSmallStepBackTries; + int m_videoSmallStepBackDelay; + bool m_videoUseTimeSeeking; + int m_videoTimeSeekForward; + int m_videoTimeSeekBackward; + int m_videoTimeSeekForwardBig; + int m_videoTimeSeekBackwardBig; + int m_videoPercentSeekForward; + int m_videoPercentSeekBackward; + int m_videoPercentSeekForwardBig; + int m_videoPercentSeekBackwardBig; + CStdString m_videoPPFFmpegDeint; + CStdString m_videoPPFFmpegPostProc; - bool m_musicUseTimeSeeking; - int m_musicTimeSeekForward; - int m_musicTimeSeekBackward; - int m_musicTimeSeekForwardBig; - int m_musicTimeSeekBackwardBig; - int m_musicPercentSeekForward; - int m_musicPercentSeekBackward; - int m_musicPercentSeekForwardBig; - int m_musicPercentSeekBackwardBig; - int m_musicResample; - int m_videoBlackBarColour; - int m_videoIgnoreAtStart; - int m_videoIgnoreAtEnd; - bool m_audioApplyDrc; + bool m_musicUseTimeSeeking; + int m_musicTimeSeekForward; + int m_musicTimeSeekBackward; + int m_musicTimeSeekForwardBig; + int m_musicTimeSeekBackwardBig; + int m_musicPercentSeekForward; + int m_musicPercentSeekBackward; + int m_musicPercentSeekForwardBig; + int m_musicPercentSeekBackwardBig; + int m_musicResample; + int m_videoBlackBarColour; + int m_videoIgnoreAtStart; + int m_videoIgnoreAtEnd; + bool m_audioApplyDrc; - float m_videoPlayCountMinimumPercent; + float m_videoPlayCountMinimumPercent; - int m_cacheMemBufferSize; + int m_cacheMemBufferSize; - float m_slideshowBlackBarCompensation; - float m_slideshowZoomAmount; - float m_slideshowPanAmount; + float m_slideshowBlackBarCompensation; + float m_slideshowZoomAmount; + float m_slideshowPanAmount; - int m_lcdRows; - int m_lcdColumns; - int m_lcdAddress1; - int m_lcdAddress2; - int m_lcdAddress3; - int m_lcdAddress4; + int m_lcdRows; + int m_lcdColumns; + int m_lcdAddress1; + int m_lcdAddress2; + int m_lcdAddress3; + int m_lcdAddress4; - int m_autoDetectPingTime; + int m_autoDetectPingTime; - int m_songInfoDuration; - int m_busyDialogDelay; - int m_logLevel; - CStdString m_cddbAddress; - bool m_usePCDVDROM; - bool m_fullScreenOnMovieStart; - bool m_noDVDROM; - CStdString m_cachePath; - bool m_displayRemoteCodes; - CStdString m_videoCleanDateTimeRegExp; - CStdStringArray m_videoCleanStringRegExps; - CStdStringArray m_videoExcludeFromListingRegExps; - CStdStringArray m_moviesExcludeFromScanRegExps; - CStdStringArray m_tvshowExcludeFromScanRegExps; - CStdStringArray m_audioExcludeFromListingRegExps; - CStdStringArray m_audioExcludeFromScanRegExps; - CStdStringArray m_pictureExcludeFromListingRegExps; - CStdStringArray m_videoStackRegExps; - CStdStringArray m_trailerMatchRegExps; - SETTINGS_TVSHOWLIST m_tvshowStackRegExps; - CStdString m_tvshowMultiPartStackRegExp; - CStdStringArray m_pathSubstitutions; - int m_remoteRepeat; - float m_controllerDeadzone; - bool m_FTPShowCache; + int m_songInfoDuration; + int m_busyDialogDelay; + int m_logLevel; + CStdString m_cddbAddress; + bool m_usePCDVDROM; + bool m_fullScreenOnMovieStart; + bool m_noDVDROM; + CStdString m_cachePath; + bool m_displayRemoteCodes; + CStdString m_videoCleanDateTimeRegExp; + CStdStringArray m_videoCleanStringRegExps; + CStdStringArray m_videoExcludeFromListingRegExps; + CStdStringArray m_moviesExcludeFromScanRegExps; + CStdStringArray m_tvshowExcludeFromScanRegExps; + CStdStringArray m_audioExcludeFromListingRegExps; + CStdStringArray m_audioExcludeFromScanRegExps; + CStdStringArray m_pictureExcludeFromListingRegExps; + CStdStringArray m_videoStackRegExps; + CStdStringArray m_trailerMatchRegExps; + SETTINGS_TVSHOWLIST m_tvshowStackRegExps; + CStdString m_tvshowMultiPartStackRegExp; + CStdStringArray m_pathSubstitutions; + int m_remoteRepeat; + float m_controllerDeadzone; + bool m_FTPShowCache; - bool m_playlistAsFolders; - bool m_detectAsUdf; + bool m_playlistAsFolders; + bool m_detectAsUdf; - int m_thumbSize; - int m_fanartHeight; + int m_thumbSize; + int m_fanartHeight; - int m_sambaclienttimeout; - CStdString m_sambadoscodepage; - bool m_sambastatfiles; - - bool m_bHTTPDirectoryStatFilesize; + int m_sambaclienttimeout; + CStdString m_sambadoscodepage; + bool m_sambastatfiles; - bool m_bFTPThumbs; + bool m_bHTTPDirectoryStatFilesize; - CStdString m_musicThumbs; - CStdString m_dvdThumbs; - CStdString m_fanartImages; + bool m_bFTPThumbs; - bool m_bMusicLibraryHideAllItems; - int m_iMusicLibraryRecentlyAddedItems; - bool m_bMusicLibraryAllItemsOnBottom; - bool m_bMusicLibraryAlbumsSortByArtistThenYear; - CStdString m_strMusicLibraryAlbumFormat; - CStdString m_strMusicLibraryAlbumFormatRight; - bool m_prioritiseAPEv2tags; - CStdString m_musicItemSeparator; - CStdString m_videoItemSeparator; - std::vector m_musicTagsFromFileFilters; + CStdString m_musicThumbs; + CStdString m_dvdThumbs; + CStdString m_fanartImages; - bool m_bVideoLibraryHideAllItems; - bool m_bVideoLibraryAllItemsOnBottom; - int m_iVideoLibraryRecentlyAddedItems; - bool m_bVideoLibraryHideRecentlyAddedItems; - bool m_bVideoLibraryHideEmptySeries; - bool m_bVideoLibraryCleanOnUpdate; - bool m_bVideoLibraryExportAutoThumbs; - bool m_bVideoLibraryMyMoviesCategoriesToGenres; - bool m_bVideoLibraryImportWatchedState; + bool m_bMusicLibraryHideAllItems; + int m_iMusicLibraryRecentlyAddedItems; + bool m_bMusicLibraryAllItemsOnBottom; + bool m_bMusicLibraryAlbumsSortByArtistThenYear; + CStdString m_strMusicLibraryAlbumFormat; + CStdString m_strMusicLibraryAlbumFormatRight; + bool m_prioritiseAPEv2tags; + CStdString m_musicItemSeparator; + CStdString m_videoItemSeparator; + std::vector m_musicTagsFromFileFilters; - bool m_bVideoScannerIgnoreErrors; + bool m_bVideoLibraryHideAllItems; + bool m_bVideoLibraryAllItemsOnBottom; + int m_iVideoLibraryRecentlyAddedItems; + bool m_bVideoLibraryHideRecentlyAddedItems; + bool m_bVideoLibraryHideEmptySeries; + bool m_bVideoLibraryCleanOnUpdate; + bool m_bVideoLibraryExportAutoThumbs; + bool m_bVideoLibraryMyMoviesCategoriesToGenres; + bool m_bVideoLibraryImportWatchedState; - bool m_bUseEvilB; - std::vector m_vecTokens; // cleaning strings tied to language - //TuxBox - int m_iTuxBoxStreamtsPort; - bool m_bTuxBoxSubMenuSelection; - int m_iTuxBoxDefaultSubMenu; - int m_iTuxBoxDefaultRootMenu; - bool m_bTuxBoxAudioChannelSelection; - bool m_bTuxBoxPictureIcon; - int m_iTuxBoxEpgRequestTime; - int m_iTuxBoxZapWaitTime; - bool m_bTuxBoxSendAllAPids; - bool m_bTuxBoxZapstream; - int m_iTuxBoxZapstreamPort; + bool m_bVideoScannerIgnoreErrors; - int m_iMythMovieLength; // minutes + bool m_bUseEvilB; + std::vector m_vecTokens; // cleaning strings tied to language + //TuxBox + int m_iTuxBoxStreamtsPort; + bool m_bTuxBoxSubMenuSelection; + int m_iTuxBoxDefaultSubMenu; + int m_iTuxBoxDefaultRootMenu; + bool m_bTuxBoxAudioChannelSelection; + bool m_bTuxBoxPictureIcon; + int m_iTuxBoxEpgRequestTime; + int m_iTuxBoxZapWaitTime; + bool m_bTuxBoxSendAllAPids; + bool m_bTuxBoxZapstream; + int m_iTuxBoxZapstreamPort; - // EDL Commercial Break - bool m_bEdlMergeShortCommBreaks; - int m_iEdlMaxCommBreakLength; // seconds - int m_iEdlMinCommBreakLength; // seconds - int m_iEdlMaxCommBreakGap; // seconds - int m_iEdlMaxStartGap; // seconds - int m_iEdlCommBreakAutowait; // seconds - int m_iEdlCommBreakAutowind; // seconds + int m_iMythMovieLength; // minutes - bool m_bFirstLoop; - int m_curlconnecttimeout; - int m_curllowspeedtime; - int m_curlretries; + // EDL Commercial Break + bool m_bEdlMergeShortCommBreaks; + int m_iEdlMaxCommBreakLength; // seconds + int m_iEdlMinCommBreakLength; // seconds + int m_iEdlMaxCommBreakGap; // seconds + int m_iEdlMaxStartGap; // seconds + int m_iEdlCommBreakAutowait; // seconds + int m_iEdlCommBreakAutowind; // seconds - int m_playlistRetries; - int m_playlistTimeout; - int m_iSkipLoopFilter; - bool m_bVirtualShares; - bool m_bNavVKeyboard; // if true we navigate the virtual keyboard using cursor keys - - bool m_bPythonVerbose; - bool m_bAutoFatxLimit; - int m_bgInfoLoaderMaxThreads; + bool m_bFirstLoop; + int m_curlconnecttimeout; + int m_curllowspeedtime; + int m_curlretries; + + int m_playlistRetries; + int m_playlistTimeout; + int m_iSkipLoopFilter; + bool m_bVirtualShares; + bool m_bNavVKeyboard; // if true we navigate the virtual keyboard using cursor keys + + bool m_bPythonVerbose; + bool m_bAutoFatxLimit; + int m_bgInfoLoaderMaxThreads; + + bool m_ambiLight; + int m_ambiLightSpaceBetweenPixels; + int m_ambiLightFloatingAverageFrames; + int m_ambiLightMinRGB; + int m_ambiLightMaxRGB; + CStdString m_ambiLightMode; + CStdString m_ambiLightPosition; + float m_ambiLightGammaR; + float m_ambiLightGammaG; + float m_ambiLightGammaB; + float m_ambiLightIntensityR; + float m_ambiLightIntensityG; + float m_ambiLightIntensityB; + int m_ambiLightFilterThreshold; + int m_ambiLightDarknessLimit; }; extern CAdvancedSettings g_advancedSettings; Index: xbmc/Application.cpp =================================================================== --- xbmc/Application.cpp (revision 30593) +++ xbmc/Application.cpp (working copy) @@ -2790,6 +2790,7 @@ } UpdateLCD(); + g_iledSmartxxrgb.AmbiLightUpdateFrameNumber(); // read raw input from controller, remote control, mouse and keyboard ReadInput(); Index: xbmc/cores/dvdplayer/DVDPlayerVideo.cpp =================================================================== --- xbmc/cores/dvdplayer/DVDPlayerVideo.cpp (revision 30593) +++ xbmc/cores/dvdplayer/DVDPlayerVideo.cpp (working copy) @@ -18,7 +18,7 @@ * http://www.gnu.org/copyleft/gpl.html * */ - + #include "stdafx.h" #include "AdvancedSettings.h" #include "GUISettings.h" @@ -38,15 +38,16 @@ #include "DVDCodecs/Overlay/DVDOverlaySSA.h" #include #include +#include "utils/LED.h" using namespace std; CDVDPlayerVideo::CDVDPlayerVideo( CDVDClock* pClock - , CDVDOverlayContainer* pOverlayContainer - , CDVDMessageQueue& parent) -: CThread() -, m_messageQueue("video") -, m_messageParent(parent) + , CDVDOverlayContainer* pOverlayContainer + , CDVDMessageQueue& parent) + : CThread() + , m_messageQueue("video") + , m_messageParent(parent) { m_pClock = pClock; m_pOverlayContainer = pOverlayContainer; @@ -81,7 +82,7 @@ { StopThread(); g_dvdPerformanceCounter.DisableVideoQueue(); - + #ifdef HAS_VIDEO_PLAYBACK if(m_output.inited) { @@ -93,16 +94,16 @@ double CDVDPlayerVideo::GetOutputDelay() { - double time = m_messageQueue.GetPacketCount(CDVDMsg::DEMUXER_PACKET); - if( m_fFrameRate ) - time = (time * DVD_TIME_BASE) / m_fFrameRate; - else - time = 0.0; + double time = m_messageQueue.GetPacketCount(CDVDMsg::DEMUXER_PACKET); + if( m_fFrameRate ) + time = (time * DVD_TIME_BASE) / m_fFrameRate; + else + time = 0.0; - if( m_speed != 0 ) - time = time * DVD_PLAYSPEED_NORMAL / abs(m_speed); + if( m_speed != 0 ) + time = time * DVD_PLAYSPEED_NORMAL / abs(m_speed); - return time; + return time; } bool CDVDPlayerVideo::OpenStream( CDVDStreamInfo &hint ) @@ -197,7 +198,7 @@ { CThread::SetName("CDVDPlayerVideo"); m_iDroppedFrames = 0; - + m_iCurrentPts = DVD_NOPTS_VALUE; m_FlipTimeStamp = m_pClock->GetAbsoluteClock(); @@ -381,8 +382,8 @@ bRequestDrop = false; #else if (m_messageQueue.GetDataSize() == 0 - || m_iNrOfPicturesNotToSkip > 0 - || m_speed < 0) + || m_iNrOfPicturesNotToSkip > 0 + || m_speed < 0) { bRequestDrop = false; m_iDroppedRequest = 0; @@ -440,6 +441,23 @@ memset(&picture, 0, sizeof(DVDVideoPicture)); if (m_pVideoCodec->GetPicture(&picture)) { + + // AMBI-LIGHT STUFF + if(g_advancedSettings.m_ambiLight) + { + g_iledSmartxxrgb.AmbiLightUpdate(); + g_iledSmartxxrgb.AmbiLightParamsUpdate(0,picture.iWidth,2); + + for(unsigned int i=0;iiGroupId; @@ -594,6 +612,8 @@ m_pOverlayCodecCC = NULL; } + //g_iledSmartxxrgb.AmbiLightStop(); + CLog::Log(LOGNOTICE, "thread end: video_thread"); } @@ -690,7 +710,7 @@ bool bHasSpecialOverlay = m_pOverlayContainer->ContainsOverlayType(DVDOVERLAY_TYPE_SPU) || m_pOverlayContainer->ContainsOverlayType(DVDOVERLAY_TYPE_IMAGE) || m_pOverlayContainer->ContainsOverlayType(DVDOVERLAY_TYPE_SSA); - + if (bHasSpecialOverlay) { if (m_pTempOverlayPicture && (m_pTempOverlayPicture->iWidth != pSource->iWidth || m_pTempOverlayPicture->iHeight != pSource->iHeight)) @@ -698,7 +718,7 @@ CDVDCodecUtils::FreePicture(m_pTempOverlayPicture); m_pTempOverlayPicture = NULL; } - + if (!m_pTempOverlayPicture) m_pTempOverlayPicture = CDVDCodecUtils::AllocatePicture(pSource->iWidth, pSource->iHeight); } @@ -706,7 +726,7 @@ CDVDCodecUtils::CopyPicture(m_pTempOverlayPicture, pSource); else CDVDCodecUtils::CopyPicture(pDest, pSource); - + m_pOverlayContainer->Lock(); VecOverlays* pVecOverlays = m_pOverlayContainer->GetOverlays(); @@ -735,7 +755,7 @@ } m_pOverlayContainer->Unlock(); - + if (bHasSpecialOverlay && m_pTempOverlayPicture) CDVDCodecUtils::CopyPicture(pDest, m_pTempOverlayPicture); } @@ -746,13 +766,13 @@ #ifdef HAS_VIDEO_PLAYBACK /* check so that our format or aspect has changed. if it has, reconfigure renderer */ if (!g_renderManager.IsConfigured() - || m_output.width != pPicture->iWidth - || m_output.height != pPicture->iHeight - || m_output.dwidth != pPicture->iDisplayWidth - || m_output.dheight != pPicture->iDisplayHeight - || m_output.framerate != m_fFrameRate - || ( m_output.color_matrix != pPicture->color_matrix && pPicture->color_matrix != 0 ) // don't reconfigure on unspecified - || m_output.color_range != pPicture->color_range) + || m_output.width != pPicture->iWidth + || m_output.height != pPicture->iHeight + || m_output.dwidth != pPicture->iDisplayWidth + || m_output.dheight != pPicture->iDisplayHeight + || m_output.framerate != m_fFrameRate + || ( m_output.color_matrix != pPicture->color_matrix && pPicture->color_matrix != 0 ) // don't reconfigure on unspecified + || m_output.color_range != pPicture->color_range) { CLog::Log(LOGNOTICE, " fps: %f, pwidth: %i, pheight: %i, dwidth: %i, dheight: %i", m_fFrameRate, pPicture->iWidth, pPicture->iHeight, pPicture->iDisplayWidth, pPicture->iDisplayHeight); @@ -762,19 +782,19 @@ switch(pPicture->color_matrix) { - case 7: // SMPTE 240M (1987) - flags |= CONF_FLAGS_YUVCOEF_240M; - break; - case 6: // SMPTE 170M - case 5: // ITU-R BT.470-2 - case 4: // FCC - flags |= CONF_FLAGS_YUVCOEF_BT601; - break; - case 3: // RESERVED - case 2: // UNSPECIFIED - case 1: // ITU-R Rec.709 (1990) -- BT.709 - default: - flags |= CONF_FLAGS_YUVCOEF_BT709; + case 7: // SMPTE 240M (1987) + flags |= CONF_FLAGS_YUVCOEF_240M; + break; + case 6: // SMPTE 170M + case 5: // ITU-R BT.470-2 + case 4: // FCC + flags |= CONF_FLAGS_YUVCOEF_BT601; + break; + case 3: // RESERVED + case 2: // UNSPECIFIED + case 1: // ITU-R Rec.709 (1990) -- BT.709 + default: + flags |= CONF_FLAGS_YUVCOEF_BT709; } if(m_bAllowFullscreen) @@ -818,7 +838,7 @@ // calculate the time we need to delay this picture before displaying double iSleepTime, iClockSleep, iFrameSleep, iCurrentClock, iFrameDuration; - + iCurrentClock = m_pClock->GetAbsoluteClock(); // snapshot current clock iClockSleep = pts - m_pClock->GetClock(); //sleep calculated by pts to clock comparison iFrameSleep = m_FlipTimeStamp - iCurrentClock; // sleep calculated by duration of frame @@ -902,7 +922,7 @@ if( m_speed < 0 ) { if( iClockSleep < -DVD_MSEC_TO_TIME(200) - && !(pPicture->iFlags & DVP_FLAG_NOSKIP) ) + && !(pPicture->iFlags & DVP_FLAG_NOSKIP) ) return result | EOS_DROPPED; } @@ -950,7 +970,7 @@ // video device might not be done yet while (index < 0 && !CThread::m_bStop && - CDVDClock::GetAbsoluteClock() < iCurrentClock + iSleepTime ) + CDVDClock::GetAbsoluteClock() < iCurrentClock + iSleepTime ) { Sleep(1); index = g_renderManager.GetImage(&image); Index: xbmc/cores/VideoRenderers/XBoxRenderer.cpp =================================================================== --- xbmc/cores/VideoRenderers/XBoxRenderer.cpp (revision 30593) +++ xbmc/cores/VideoRenderers/XBoxRenderer.cpp (working copy) @@ -24,6 +24,7 @@ #include "Application.h" #include "XBVideoConfig.h" #include "Settings.h" +#include "utils/LED.h" // http://www.martinreddy.net/gfx/faqs/colorconv.faq @@ -283,7 +284,7 @@ xscale = 1.0f; yscale = 1.0f; } - + // horizontal centering, and align to bottom of subtitles line osdRect.left = (float)rv.left + (float)(rv.right - rv.left - (float)w * xscale) / 2.0f; osdRect.right = osdRect.left + (float)w * xscale; @@ -306,7 +307,7 @@ if ( D3D_OK != m_pD3DDevice->CreateTexture(m_iOSDTextureWidth, m_iOSDTextureHeight[iOSDBuffer], 1, 0, D3DFMT_LIN_L8, 0, &m_pOSDYTexture[iOSDBuffer]) || D3D_OK != m_pD3DDevice->CreateTexture(m_iOSDTextureWidth, m_iOSDTextureHeight[iOSDBuffer], 1, 0, D3DFMT_LIN_A8, 0, &m_pOSDATexture[iOSDBuffer]) - ) + ) { CLog::Log(LOGERROR, "Could not create OSD/Sub textures"); DeleteOSDTextures(iOSDBuffer); @@ -337,7 +338,7 @@ if ( (D3D_OK == m_pOSDYTexture[iOSDBuffer]->LockRect(0, &lr, &rc, 0)) && (D3D_OK == m_pOSDATexture[iOSDBuffer]->LockRect(0, &lra, &rc, 0)) - ) + ) { //clear the textures memset(lr.pBits, 0, lr.Pitch*m_iOSDTextureHeight[iOSDBuffer]); @@ -392,7 +393,7 @@ //m_pD3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_INVSRCALPHA ); //m_pD3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_SRCALPHA ); - // Note the mplayer code actually does this + // Note the mplayer code actually does this //m_pD3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE ); //m_pD3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_SRCALPHA ); } @@ -559,7 +560,7 @@ DeleteYV12Texture(i); } if(m_iYV12RenderBuffer > i) - m_iYV12RenderBuffer = i; + m_iYV12RenderBuffer = i; m_NumYV12Buffers = i+1; } } @@ -671,16 +672,16 @@ // If the TV has no HD support widescreen mode is chossen according to video AR if (g_videoConfig.Has1080i()) // Widescreen TV with 1080i res - m_iResolution = HDTV_1080i; + m_iResolution = HDTV_1080i; else if (g_videoConfig.Has720p()) // Widescreen TV with 720p res - m_iResolution = HDTV_720p; + m_iResolution = HDTV_720p; else if (g_videoConfig.Has480p()) // Widescreen TV with 480p { if (bWideScreenMode) // Choose widescreen mode according to video AR m_iResolution = HDTV_480p_16x9; else m_iResolution = HDTV_480p_4x3; - } + } else if (bWideScreenMode) // Standard 16:9 TV set with no HD m_iResolution = NTSC_16x9; else @@ -692,7 +693,7 @@ // We choose 16:9 resolution only for 16:9 video sources if (m_fSourceFrameRatio >= 16.0f / 9.0f) - { + { // The video fits best into widescreen modes so they are // the first choices if (g_videoConfig.Has1080i()) @@ -738,7 +739,7 @@ m_fps = fps; m_iFlags = flags; m_bConfigured = true; - + // setup what colorspace we live in if(flags & CONF_FLAGS_YUV_FULLRANGE) m_yuvrange = yuv_range_full; @@ -747,18 +748,21 @@ switch(CONF_FLAGS_YUVCOEF_MASK(flags)) { - case CONF_FLAGS_YUVCOEF_240M: - m_yuvcoef = yuv_coef_smtp240m; break; - case CONF_FLAGS_YUVCOEF_BT709: - m_yuvcoef = yuv_coef_bt709; break; - case CONF_FLAGS_YUVCOEF_BT601: - m_yuvcoef = yuv_coef_bt601; break; - case CONF_FLAGS_YUVCOEF_EBU: - m_yuvcoef = yuv_coef_ebu; break; - default: - m_yuvcoef = yuv_coef_bt601; break; + case CONF_FLAGS_YUVCOEF_240M: + m_yuvcoef = yuv_coef_smtp240m; break; + case CONF_FLAGS_YUVCOEF_BT709: + m_yuvcoef = yuv_coef_bt709; break; + case CONF_FLAGS_YUVCOEF_BT601: + m_yuvcoef = yuv_coef_bt601; break; + case CONF_FLAGS_YUVCOEF_EBU: + m_yuvcoef = yuv_coef_ebu; break; + default: + m_yuvcoef = yuv_coef_bt601; break; } + // init Params for AmbiLight + g_iledSmartxxrgb.AmbiLightParamsInit(width,height,m_yuvcoef,m_yuvrange); + // calculate the input frame aspect ratio CalculateFrameAspectRatio(d_width, d_height); ChooseBestResolution(m_fps); @@ -798,16 +802,16 @@ source = NextYV12Texture(); #ifdef MP_DIRECTRENDERING - if( source < 0 ) - { /* no free source existed, so create one */ - CSingleLock lock(g_graphicsContext); - if( CreateYV12Texture(m_NumYV12Buffers) ) - { - source = m_NumYV12Buffers; - m_NumYV12Buffers++; - m_image[source].flags |= IMAGE_FLAG_DYNAMIC; - } + if( source < 0 ) + { /* no free source existed, so create one */ + CSingleLock lock(g_graphicsContext); + if( CreateYV12Texture(m_NumYV12Buffers) ) + { + source = m_NumYV12Buffers; + m_NumYV12Buffers++; + m_image[source].flags |= IMAGE_FLAG_DYNAMIC; } + } #endif if( source >= 0 && m_image[source].plane[0] ) @@ -833,7 +837,7 @@ { if( m_image[source].flags & IMAGE_FLAG_WRITING ) SetEvent(m_eventTexturesDone[source]); - + m_image[source].flags &= ~IMAGE_FLAG_INUSE; /* if image should be preserved reserve it so it's not auto seleceted */ @@ -918,10 +922,15 @@ unsigned int CXBoxRenderer::DrawSlice(unsigned char *src[], int stride[], int w, int h, int x, int y) { - BYTE *s; - BYTE *d; - int i, p; + BYTE *s0,*s1,*s2; + BYTE *d0,*d1,*d2; + int w2,h2,x2,y2; + + // check if we've finished the recent Frame and push it to the SmartXX... + if(g_advancedSettings.m_ambiLight) + g_iledSmartxxrgb.AmbiLightUpdate(); + int index = NextYV12Texture(); if( index < 0 ) return -1; @@ -930,40 +939,47 @@ CLog::Log(LOGWARNING, CStdString(__FUNCTION__) + " - Timeout waiting for texture %d", index); YV12Image &im = m_image[index]; - // copy Y - p = 0; - d = (BYTE*)im.plane[p] + im.stride[p] * y + x; - s = src[p]; - for (i = 0;i < h;i++) - { - memcpy(d, s, w); - s += stride[p]; - d += im.stride[p]; - } + // Y + d0 = (BYTE*)im.plane[0] + im.stride[0] * y + x; + s0 = src[0]; - w >>= im.cshift_x; h >>= im.cshift_y; - x >>= im.cshift_x; y >>= im.cshift_y; + w2 = w >> im.cshift_x; h2 = h >> im.cshift_y; + x2 = x >> im.cshift_x; y2 = y >> im.cshift_y; - // copy U - p = 1; - d = (BYTE*)im.plane[p] + im.stride[p] * y + x; - s = src[p]; - for (i = 0;i < h;i++) + // U + d1 = (BYTE*)im.plane[1] + im.stride[1] * y2 + x2; + s1 = src[1]; + + // V + d2 = (BYTE*)im.plane[2] + im.stride[2] * y2 + x2; + s2 = src[2]; + + int widthRatio = (int)(w/w2); + int heightRatio = (int)(h/h2); + + //Update AmbiLights params... + if(g_advancedSettings.m_ambiLight) + g_iledSmartxxrgb.AmbiLightParamsUpdate(x,w,widthRatio); + + for (int i = 0;i < h;i++) { - memcpy(d, s, w); - s += stride[p]; - d += im.stride[p]; - } + memcpy(d0, s0, w); + s0 += stride[0]; + d0 += im.stride[0]; - // copy V - p = 2; - d = (BYTE*)im.plane[p] + im.stride[p] * y + x; - s = src[p]; - for (i = 0;i < h;i++) - { - memcpy(d, s, w); - s += stride[p]; - d += im.stride[p]; + if(i % heightRatio == 0) + { + memcpy(d1, s1, w2); + s1 += stride[1]; + d1 += im.stride[1]; + + memcpy(d2, s2, w2); + s2 += stride[2]; + d2 += im.stride[2]; + } + // calculate RGB-values for the recent row of the frame... + if(g_advancedSettings.m_ambiLight) + g_iledSmartxxrgb.AmbiLightRGBCalculate(s0,s1,s2); } SetEvent(m_eventTexturesDone[index]); @@ -1038,13 +1054,14 @@ DeleteYV12Texture(i); DeleteOSDTextures(i); } - + if (m_hLowMemShader) { m_pD3DDevice->DeletePixelShader(m_hLowMemShader); m_hLowMemShader = 0; } + g_iledSmartxxrgb.AmbiLightStop(); m_bConfigured = false; } @@ -1357,7 +1374,7 @@ void CXBoxRenderer::DeleteYV12Texture(int index) { CSingleLock lock(g_graphicsContext); - + YV12Image &im = m_image[index]; YUVFIELDS &fields = m_YUVTexture[index]; @@ -1382,7 +1399,7 @@ im.plane[p] = NULL; m_NumYV12Buffers = 0; - + CLog::Log(LOGDEBUG, "Deleted YV12 texture %i", index); } @@ -1439,24 +1456,24 @@ p = 0; stride = im.stride[p]; im.plane[p] = (BYTE*)dwTextureSize; - XGSetTextureHeader(im.width , im.height>>1 , 1, 0, D3DFMT_LIN_L8, 0, fields[2][p], dwTextureSize + stride, stride<<1); - XGSetTextureHeader(im.width , im.height>>1 , 1, 0, D3DFMT_LIN_L8, 0, fields[1][p], dwTextureSize, stride<<1); + XGSetTextureHeader(im.width , im.height>>1 , 1, 0, D3DFMT_LIN_L8, 0, fields[2][p], dwTextureSize + stride, stride<<1); + XGSetTextureHeader(im.width , im.height>>1 , 1, 0, D3DFMT_LIN_L8, 0, fields[1][p], dwTextureSize, stride<<1); dwTextureSize += XGSetTextureHeader(im.width , im.height , 1, 0, D3DFMT_LIN_L8, 0, fields[0][p], dwTextureSize, stride); /* U */ p = 1; stride = im.stride[p]; im.plane[p] = (BYTE*)dwTextureSize; - XGSetTextureHeader(im.width>>im.cshift_x, im.height>>im.cshift_y>>1, 1, 0, D3DFMT_LIN_L8, 0, fields[2][p], dwTextureSize + stride, stride<<1); - XGSetTextureHeader(im.width>>im.cshift_x, im.height>>im.cshift_y>>1, 1, 0, D3DFMT_LIN_L8, 0, fields[1][p], dwTextureSize, stride<<1); + XGSetTextureHeader(im.width>>im.cshift_x, im.height>>im.cshift_y>>1, 1, 0, D3DFMT_LIN_L8, 0, fields[2][p], dwTextureSize + stride, stride<<1); + XGSetTextureHeader(im.width>>im.cshift_x, im.height>>im.cshift_y>>1, 1, 0, D3DFMT_LIN_L8, 0, fields[1][p], dwTextureSize, stride<<1); dwTextureSize += XGSetTextureHeader(im.width>>im.cshift_x, im.height>>im.cshift_y, 1, 0, D3DFMT_LIN_L8, 0, fields[0][p], dwTextureSize, stride); /* V */ p = 2; stride = im.stride[p]; im.plane[p] = (BYTE*)dwTextureSize; - XGSetTextureHeader(im.width>>im.cshift_x, im.height>>im.cshift_y>>1, 1, 0, D3DFMT_LIN_L8, 0, fields[2][p], dwTextureSize + stride, stride<<1); - XGSetTextureHeader(im.width>>im.cshift_x, im.height>>im.cshift_y>>1, 1, 0, D3DFMT_LIN_L8, 0, fields[1][p], dwTextureSize, stride<<1); + XGSetTextureHeader(im.width>>im.cshift_x, im.height>>im.cshift_y>>1, 1, 0, D3DFMT_LIN_L8, 0, fields[2][p], dwTextureSize + stride, stride<<1); + XGSetTextureHeader(im.width>>im.cshift_x, im.height>>im.cshift_y>>1, 1, 0, D3DFMT_LIN_L8, 0, fields[1][p], dwTextureSize, stride<<1); dwTextureSize += XGSetTextureHeader(im.width>>im.cshift_x, im.height>>im.cshift_y, 1, 0, D3DFMT_LIN_L8, 0, fields[0][p], dwTextureSize, stride); BYTE* data = (BYTE*)XPhysicalAlloc(dwTextureSize, MAXULONG_PTR, D3DTEXTURE_ALIGNMENT, memflags); Index: xbmc/Util.cpp =================================================================== --- xbmc/Util.cpp (revision 30593) +++ xbmc/Util.cpp (working copy) @@ -4397,14 +4397,21 @@ strWhiteB= arSplit[3].c_str(); strTran = arSplit[4].c_str(); iTrTime = atoi(arSplit[5].c_str()); + CUtil::PWMControl(strRgbA,strRgbB,strWhiteA,strWhiteB,strTran, iTrTime); } - else if(parameter.size() > 6) + else if(parameter.size() == 7) { strRgbA = strRgbB = parameter; strWhiteA = strWhiteB = "#000000"; - strTran = "none"; + strTran = "fade2"; + tRGBColor rgb; + sscanf(parameter,"#%2X%2X%2X",&rgb.r,&rgb.g,&rgb.b); + + //CUtil::PWMControl(strRgbA,strRgbB,strWhiteA,strWhiteB,strTran, iTrTime); + g_iledSmartxxrgb.SetRGBState(rgb); } - CUtil::PWMControl(strRgbA,strRgbB,strWhiteA,strWhiteB,strTran, iTrTime); + else + CLog::Log(LOGDEBUG,"System.PWMControl(): Invalid parameters - use: System.PWMControl(#rgb1,#rgb2,#white1,#white2,mode,time)"); } else if (execute.Equals("backupsysteminfo")) { Index: xbmc/utils/LED.cpp =================================================================== --- xbmc/utils/LED.cpp (revision 30593) +++ xbmc/utils/LED.cpp (working copy) @@ -50,9 +50,23 @@ #include "xbox/XKUtils.h" #include "LCD.h" #include "GUISettings.h" +#include "Settings.h" #include +// set accuracy of color calculation +#define h_MAX 255 +#define s_MAX 255 +#define v_MAX 255 +#define POS_DIV(a, b) ( (a)/(b) + ( ((a)%(b) >= (b)/2 ) ? 1 : 0) ) + +#define WINDOW_SIZE 5 +#define HUE_WINDOW 5 +#define MIN_PERCENTAGE 0.01 +#define FADE2_MAX_TIME 1000 +#define SLOWLIMIT 12 +#define SLOWTIMES 4 + ILEDSmartxxRGB g_iledSmartxxrgb; void ILED::CLEDControl(int ixLED) @@ -88,17 +102,20 @@ ILEDSmartxxRGB::ILEDSmartxxRGB() { - strCurrentStatus = "NULL"; - strLastStatus = "NULL"; - + strCurrentStatus = "NULL"; + strLastStatus = "NULL"; + s_RGBs.strTransition = "NULL"; - s_CurRGB.red = 0; - s_CurRGB.green = 0; - s_CurRGB.blue = 0; + s_CurRGB.red = 0; + s_CurRGB.green = 0; + s_CurRGB.blue = 0; s_CurRGB.white = 0; - + dwLastTime = 0; bRepeat = false; + isPaused = false; + + AmbiLightParams.AmbiLightIsPlaying=false; } ILEDSmartxxRGB::~ILEDSmartxxRGB() @@ -108,119 +125,317 @@ { if (g_sysinfo.SmartXXModCHIP().Equals("SmartXX V3") || g_sysinfo.SmartXXModCHIP().Equals("SmartXX OPX")) { - SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_LOWEST); - CLog::Log(LOGDEBUG,"Starting SmartXX RGB LED thread"); + //SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_LOWEST); + //SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_HIGHEST); + SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_HIGHEST); + CLog::Log(LOGDEBUG,"Starting SmartXX RGB LED thread"); SetRGBStatus("general"); } } void ILEDSmartxxRGB::Process() { - while(!m_bStop) - { - dwFrameTime = timeGetTime() - dwLastTime; + while(!m_bStop) + { + if(!isPaused) + { + dwFrameTime = timeGetTime() - dwLastTime; - if( (s_RGBs.strTransition.IsEmpty() || s_RGBs.strTransition.Equals("none")) && !strLastTransition.Equals("none") ) - { - strLastTransition = "none"; - s_CurRGB.red = s_RGBs.red1; - s_CurRGB.green = s_RGBs.green1; - s_CurRGB.blue = s_RGBs.blue1; - s_CurRGB.white = s_RGBs.white1; - - SetRGBLed(s_CurRGB.red,s_CurRGB.green,s_CurRGB.blue, s_CurRGB.white); - } - else if(s_RGBs.strTransition.Equals("switch") && !strLastTransition.Equals("switch")) - { - if(dwFrameTime >= s_RGBs.iTime ) - { - s_CurRGB.red = s_RGBs.red2; - s_CurRGB.green = s_RGBs.green2; - s_CurRGB.blue = s_RGBs.blue2; - s_CurRGB.white = s_RGBs.white2; - strLastTransition = "switch"; - SetRGBLed(s_CurRGB.red,s_CurRGB.green,s_CurRGB.blue,s_CurRGB.white); - } - else + if( (s_RGBs.strTransition.IsEmpty() || s_RGBs.strTransition.Equals("none")) && !strLastTransition.Equals("none") ) { s_CurRGB.red = s_RGBs.red1; - s_CurRGB.green = s_RGBs.green1; + s_CurRGB.green = s_RGBs.green1; s_CurRGB.blue = s_RGBs.blue1; s_CurRGB.white = s_RGBs.white1; - SetRGBLed(s_CurRGB.red,s_CurRGB.green,s_CurRGB.blue,s_CurRGB.white); + + SetRGBLed(s_CurRGB.red,s_CurRGB.green,s_CurRGB.blue, s_CurRGB.white); } - - } - else if(s_RGBs.strTransition.Equals("blink")) - { - strLastTransition = "blink"; - if(dwFrameTime >= s_RGBs.iTime ) - { - s_CurRGB.red = (s_CurRGB.red != s_RGBs.red1) ? s_RGBs.red1 : s_RGBs.red2; - s_CurRGB.green = (s_CurRGB.green != s_RGBs.green1) ? s_RGBs.green1 : s_RGBs.green2; - s_CurRGB.blue = (s_CurRGB.blue != s_RGBs.blue1) ? s_RGBs.blue1 : s_RGBs.blue2; - s_CurRGB.white= (s_CurRGB.white != s_RGBs.white1) ? s_RGBs.white1 : s_RGBs.white2; - dwLastTime = timeGetTime(); - SetRGBLed(s_CurRGB.red,s_CurRGB.green,s_CurRGB.blue,s_CurRGB.white); - } - } - else if(s_RGBs.strTransition.Equals("fade") || s_RGBs.strTransition.Equals("fadeloop") || s_RGBs.strTransition.Equals("faderepeat")) - { + else if(s_RGBs.strTransition.Equals("switch") && !strLastTransition.Equals("switch")) + { + if(dwFrameTime >= s_RGBs.iTime ) + { + s_CurRGB.red = s_RGBs.red2; + s_CurRGB.green = s_RGBs.green2; + s_CurRGB.blue = s_RGBs.blue2; + s_CurRGB.white = s_RGBs.white2; + SetRGBLed(s_CurRGB.red,s_CurRGB.green,s_CurRGB.blue,s_CurRGB.white); + } + else + { + s_CurRGB.red = s_RGBs.red1; + s_CurRGB.green = s_RGBs.green1; + s_CurRGB.blue = s_RGBs.blue1; + s_CurRGB.white = s_RGBs.white1; + SetRGBLed(s_CurRGB.red,s_CurRGB.green,s_CurRGB.blue,s_CurRGB.white); + } + } + else if(s_RGBs.strTransition.Equals("blink")) + { + strLastTransition = "blink"; + if(dwFrameTime >= s_RGBs.iTime ) + { + s_CurRGB.red = (s_CurRGB.red != s_RGBs.red1) ? s_RGBs.red1 : s_RGBs.red2; + s_CurRGB.green = (s_CurRGB.green != s_RGBs.green1) ? s_RGBs.green1 : s_RGBs.green2; + s_CurRGB.blue = (s_CurRGB.blue != s_RGBs.blue1) ? s_RGBs.blue1 : s_RGBs.blue2; + s_CurRGB.white= (s_CurRGB.white != s_RGBs.white1) ? s_RGBs.white1 : s_RGBs.white2; + dwLastTime = timeGetTime(); + SetRGBLed(s_CurRGB.red,s_CurRGB.green,s_CurRGB.blue,s_CurRGB.white); + } + } + else if(s_RGBs.strTransition.Equals("fade") || s_RGBs.strTransition.Equals("fadeloop") || s_RGBs.strTransition.Equals("faderepeat")) + { + static double distanceR,distanceG,distanceB,distanceW; + + if(!strLastTransition.Equals("fade")) + { + distanceR = bRepeat ? s_RGBs.red1-s_RGBs.red2 : s_RGBs.red2-s_RGBs.red1; + distanceG = bRepeat ? s_RGBs.green1-s_RGBs.green2 : s_RGBs.green2-s_RGBs.green1; + distanceB = bRepeat ? s_RGBs.blue1-s_RGBs.blue2 : s_RGBs.blue2-s_RGBs.blue1; + distanceW = bRepeat ? s_RGBs.white1-s_RGBs.white2 : s_RGBs.white2-s_RGBs.white1; + + strLastTransition = "fade"; + + if(s_RGBs.strTransition.Equals("faderepeat"))bRepeat=!bRepeat; + } + + if(dwFrameTime <= s_RGBs.iTime ) + { + double stepR=distanceR/s_RGBs.iTime*dwFrameTime; + double stepG=distanceG/s_RGBs.iTime*dwFrameTime; + double stepB=distanceB/s_RGBs.iTime*dwFrameTime; + double stepW=distanceW/s_RGBs.iTime*dwFrameTime; + + s_CurRGB.red=(bRepeat ? s_RGBs.red1 : s_RGBs.red2) +(int)stepR; + s_CurRGB.green=(bRepeat ? s_RGBs.green1 : s_RGBs.green2)+(int)stepG; + s_CurRGB.blue=(bRepeat ? s_RGBs.blue1 : s_RGBs.blue2)+(int)stepB; + s_CurRGB.white=(bRepeat ? s_RGBs.white1 : s_RGBs.white2)+(int)stepW; + + SetRGBLed(s_CurRGB.red,s_CurRGB.green,s_CurRGB.blue,s_CurRGB.white); + } + else if(s_RGBs.strTransition.Equals("fadeloop") || s_RGBs.strTransition.Equals("faderepeat")) + { + strLastTransition="none"; + dwLastTime = timeGetTime(); + } + } + else if(s_RGBs.strTransition.Equals("fade2")) + { + static int distanceR,distanceG,distanceB,distanceW; + static int maxDiffR,maxDiffG,maxDiffB; + + if(!strLastTransition.Equals("fade2")) + { + strLastTransition = "fade2"; + dwFrameTime = 0; + dwLastTime = timeGetTime(); + + s_RGBs.red1 =s_CurRGB.red; + s_RGBs.green1 =s_CurRGB.green; + s_RGBs.blue1 =s_CurRGB.blue ; + + distanceR = s_RGBs.red2-s_RGBs.red1; + distanceG = s_RGBs.green2-s_RGBs.green1; + distanceB = s_RGBs.blue2-s_RGBs.blue1; + distanceW = s_RGBs.white2-s_RGBs.white1; + + /*maxDiffR=(int)((float)distanceR/FADE2_MAX_TIME*2); + maxDiffG=(int)((float)distanceG/FADE2_MAX_TIME*2); + maxDiffB=(int)((float)distanceB/FADE2_MAX_TIME*2); + if(maxDiffR==0)maxDiffR=1; + if(maxDiffG==0)maxDiffG=1; + if(maxDiffB==0)maxDiffB=1;*/ + + + int max=abs(MAX(distanceR,distanceG,distanceB)); + + //max eine sekunde transition time + s_RGBs.iTime = int((max/255.0f)*FADE2_MAX_TIME); + } + + if(dwFrameTime <= s_RGBs.iTime && (s_CurRGB.red!=s_RGBs.red2 || s_CurRGB.blue!=s_RGBs.blue2 || s_CurRGB.green!=s_RGBs.green2)) + { + // how far do we need to be according to current time... + int stepR=(int)((double)distanceR/s_RGBs.iTime*dwFrameTime); + int stepG=(int)((double)distanceG/s_RGBs.iTime*dwFrameTime); + int stepB=(int)((double)distanceB/s_RGBs.iTime*dwFrameTime); + int stepW=(int)((double)distanceW/s_RGBs.iTime*dwFrameTime); + + + /*int diffR=abs(s_CurRGB.red-s_RGBs.red1+stepR); + int diffG=abs(s_CurRGB.green-s_RGBs.green1+stepG); + int diffB=abs(s_CurRGB.blue-s_RGBs.blue1+stepB); + + if(diffR>maxDiffR) + stepR=s_CurRGB.red+maxDiffR-s_RGBs.red1; + if(diffG>maxDiffG) + stepG=s_CurRGB.green+maxDiffG-s_RGBs.green1; + if(diffB>maxDiffB) + stepB=s_CurRGB.blue+maxDiffB-s_RGBs.blue1;*/ + + s_CurRGB.red=s_RGBs.red1+stepR; + s_CurRGB.green=s_RGBs.green1+stepG; + s_CurRGB.blue=s_RGBs.blue1+stepB; + s_CurRGB.white=s_RGBs.white1+stepW; + + /*if(s_CurRGB.red<=SLOWLIMIT) + { + static int counter=0; + if(counter==SLOWTIMES) + { + if(s_CurRGB.reds_RGBs.red2) s_CurRGB.red--; + counter=0; + } + counter++; + } + else + { + if(s_CurRGB.reds_RGBs.red2) s_CurRGB.red--; + } + + if(s_CurRGB.blue<=SLOWLIMIT) + { + static int counter=0; + if(counter==SLOWTIMES) + { + if(s_CurRGB.blues_RGBs.blue2) s_CurRGB.blue--; + counter=0; + } + counter++; + } + else + { + if(s_CurRGB.blues_RGBs.blue2) s_CurRGB.blue--; + } + + + if(s_CurRGB.green<=SLOWLIMIT) + { + static int counter=0; + if(counter==SLOWTIMES) + { + if(s_CurRGB.greens_RGBs.green2) s_CurRGB.green--; + counter=0; + } + counter++; + } + else + { + if(s_CurRGB.greens_RGBs.green2) s_CurRGB.green--; + }*/ + + + SetRGBLed(s_CurRGB.red,s_CurRGB.green,s_CurRGB.blue,s_CurRGB.white); + + /*static int i=0,minR=255,minG=255,minB=255,maxR=0,maxG=0,maxB=0; + minR=s_CurRGB.redmaxR?s_CurRGB.red:maxR; + maxG=s_CurRGB.green>maxG?s_CurRGB.green:maxG; + maxB=s_CurRGB.blue>maxB?s_CurRGB.blue:maxB; + + static int dwLastTime=0; + i=(i+1) % 100; + if(i==0) + { + CLog::DebugLog("AmbiTime: %i minR%i G%i B%i maxR%i G%i B%i",timeGetTime()-dwLastTime,minR,minG,minB,maxR,maxG,maxB); + dwLastTime=timeGetTime(); + minR=minG=minB=255; + maxR=maxG=maxB=0; + }*/ + } + else + { + strLastTransition = "reset"; + } + } + /*else if(s_RGBs.strTransition.Equals("firework")) + { static double distanceR,distanceG,distanceB,distanceW; + static double logScaleR,logScaleG,logScaleB,logScaleW; + static int counter; - if(!strLastTransition.Equals("fade")) - { - distanceR = bRepeat ? s_RGBs.red1-s_RGBs.red2 : s_RGBs.red2-s_RGBs.red1; - distanceG = bRepeat ? s_RGBs.green1-s_RGBs.green2 : s_RGBs.green2-s_RGBs.green1; - distanceB = bRepeat ? s_RGBs.blue1-s_RGBs.blue2 : s_RGBs.blue2-s_RGBs.blue1; - distanceW = bRepeat ? s_RGBs.white1-s_RGBs.white2 : s_RGBs.white2-s_RGBs.white1; + if(!strLastTransition.Equals("firework")) + { + counter=0; + strLastTransition="reset"; + } - strLastTransition = "fade"; + if(strLastTransition.Equals("reset")) + { + distanceR = s_RGBs.red1-s_RGBs.red2; + distanceG = s_RGBs.green1-s_RGBs.green2; + distanceB = s_RGBs.blue1-s_RGBs.blue2; + distanceW = s_RGBs.white1-s_RGBs.white2; - if(s_RGBs.strTransition.Equals("faderepeat"))bRepeat=!bRepeat; - } + logScaleR = 127/log(distanceR); + logScaleG = 127/log(distanceG); + logScaleB = 127/log(distanceB); + logScaleW = 127/log(distanceW); - if(dwFrameTime <= s_RGBs.iTime ) - { - double stepR=distanceR/s_RGBs.iTime*dwFrameTime; - double stepG=distanceG/s_RGBs.iTime*dwFrameTime; - double stepB=distanceB/s_RGBs.iTime*dwFrameTime; - double stepW=distanceW/s_RGBs.iTime*dwFrameTime; + counter++; + } - s_CurRGB.red=(bRepeat ? s_RGBs.red1 : s_RGBs.red2) +(int)stepR; - s_CurRGB.green=(bRepeat ? s_RGBs.green1 : s_RGBs.green2)+(int)stepG; - s_CurRGB.blue=(bRepeat ? s_RGBs.blue1 : s_RGBs.blue2)+(int)stepB; - s_CurRGB.white=(bRepeat ? s_RGBs.white1 : s_RGBs.white2)+(int)stepW; - - SetRGBLed(s_CurRGB.red,s_CurRGB.green,s_CurRGB.blue,s_CurRGB.white); - } - else if(s_RGBs.strTransition.Equals("fadeloop") || s_RGBs.strTransition.Equals("faderepeat")) + if(counter<=3) { - strLastTransition="none"; - dwFrameTime = 0; - dwLastTime = timeGetTime(); + if(dwFrameTime <= s_RGBs.iTime ) + { + double stepR=log(distanceR/s_RGBs.iTime*dwFrameTime)*logScaleR*-1; + double stepG=log(distanceG/s_RGBs.iTime*dwFrameTime)*logScaleG*-1; + double stepB=log(distanceB/s_RGBs.iTime*dwFrameTime)*logScaleB*-1; + double stepW=log(distanceW/s_RGBs.iTime*dwFrameTime)*logScaleW*-1; + + s_CurRGB.red=s_RGBs.red1+(int)stepR; + s_CurRGB.green=s_RGBs.green1+(int)stepG; + s_CurRGB.blue=s_RGBs.blue1+(int)stepB; + s_CurRGB.white=s_RGBs.white1+(int)stepW; + + SetRGBLed(s_CurRGB.red,s_CurRGB.green,s_CurRGB.blue,s_CurRGB.white); } - } - - Sleep(10); - } + else + { + SetRGBLed(0,0,0,s_CurRGB.white); + Sleep(200); + strLastTransition="reset"; + dwLastTime = timeGetTime(); + } + } + }*/ + } + for(int i=0;i<10;i++) + Sleep(1); + } } void ILEDSmartxxRGB::OnExit() { - SetRGBLed(0,0,0,0xb); //r=0,g=0,b=0 w=0xb (Status LED ON) + // this can also be called when navigationg in the XBMC while a movie runs in background. + // when in menu it can happen that parallel to AmbiLight PWMControl will be started. In that + // case we want AmbiLight to stay on and so the ambilight will stop the rgb-thread. To avoid + // flashing of LEDs in this case we don't turn them off. + if(!AmbiLightParams.AmbiLightIsPlaying) + { + SetRGBLed(0,0,0,0xb); //r=0,g=0,b=0 w=0xb (Status LED ON) - // SmartXX OPX port for RGB-Red is the same port for display brightness control - // Restoring brightness value from the settings - if ( g_sysinfo.SmartXXModCHIP().Equals("SmartXX OPX") ) - g_lcd->SetBackLight(g_guiSettings.GetInt("lcd.backlight")); + // SmartXX OPX port for RGB-Red is the same port for display brightness control + // Restoring brightness value from the settings + if ( g_sysinfo.SmartXXModCHIP().Equals("SmartXX OPX") ) + g_lcd->SetBackLight(g_guiSettings.GetInt("lcd.backlight")); - CLog::Log(LOGDEBUG,"Stopping SmartXX RGB LED thread"); + CLog::Log(LOGDEBUG,"Stopping SmartXX RGB LED thread"); + } } bool ILEDSmartxxRGB::Start() { - if (g_sysinfo.SmartXXModCHIP().Equals("SmartXX V3") || g_sysinfo.SmartXXModCHIP().Equals("SmartXX OPX")) - { + if ((g_sysinfo.SmartXXModCHIP().Equals("SmartXX V3") || g_sysinfo.SmartXXModCHIP().Equals("SmartXX OPX"))) // && !AmbiLightParams.AmbiLightIsPlaying && !isPaused) + { Create(); return true; } @@ -232,61 +447,76 @@ StopThread(); } bool ILEDSmartxxRGB::IsRunning() -{ +{ return (m_ThreadHandle != NULL); } +void ILEDSmartxxRGB::Pause() +{ + //isPaused=true; +} +void ILEDSmartxxRGB::Continue() +{ + if(isPaused) + dwLastTime=timeGetTime(); + isPaused=false; +} +bool ILEDSmartxxRGB::IsPaused() +{ + return isPaused; +} + void ILEDSmartxxRGB::getRGBValues(const CStdString &strRGBa, const CStdString &strRGBb, const CStdString &strWhiteA, const CStdString &strWhiteB, RGBVALUES* s_rgb) { - DWORD red=0,green=0,blue=0,white=0; - + DWORD red=0,green=0,blue=0,white=0; + int ret = sscanf(strRGBa,"#%2X%2X%2X",&red,&green,&blue); - if(ret == 3) - { - s_rgb->red1 = int(red/2); - s_rgb->green1 = int(green/2); - s_rgb->blue1 = int(blue/2); - } - else - { - s_rgb->red1 = 0; - s_rgb->green1 = 0; - s_rgb->blue1 = 0; - } + if(ret == 3) + { + s_rgb->red1 = int(red/2); + s_rgb->green1 = int(green/2); + s_rgb->blue1 = int(blue/2); + } + else + { + s_rgb->red1 = 0; + s_rgb->green1 = 0; + s_rgb->blue1 = 0; + } - ret = sscanf(strRGBb,"#%2X%2X%2X",&red,&green,&blue); - if(ret == 3) - { - s_rgb->red2 = int(red/2); - s_rgb->green2 = int(green/2); - s_rgb->blue2 = int(blue/2); - } - else - { - s_rgb->red2 = 0; - s_rgb->green2 = 0; - s_rgb->blue2 = 0; - } - + ret = sscanf(strRGBb,"#%2X%2X%2X",&red,&green,&blue); + if(ret == 3) + { + s_rgb->red2 = int(red/2); + s_rgb->green2 = int(green/2); + s_rgb->blue2 = int(blue/2); + } + else + { + s_rgb->red2 = 0; + s_rgb->green2 = 0; + s_rgb->blue2 = 0; + } + ret = sscanf(strWhiteA,"#%2X",&white); - if(ret == 1) - { + if(ret == 1) + { s_rgb->white1 = int(white/2); - } - else - { + } + else + { s_rgb->white1 = 0; - } + } ret = sscanf(strWhiteB,"#%2X",&white); - if(ret == 1) - { + if(ret == 1) + { s_rgb->white2 = int(white/2); - } - else - { + } + else + { s_rgb->white2 = 0; - } + } } bool ILEDSmartxxRGB::SetRGBStatus(const CStdString &strStatus) @@ -298,12 +528,28 @@ bool ILEDSmartxxRGB::SetRGBLed(int red, int green, int blue, int white) { + static oldR=0,oldG=0,oldB=0; + /*if(abs(oldR-red)>1) + CLog::DebugLog("RSkipAmbilight"); + if(abs(oldG-green)>1) + CLog::DebugLog("GSkipAmbilight"); + if(abs(oldB-blue)>1) + CLog::DebugLog("BSkipAmbilight");*/ + oldR=red; + oldG=green; + oldB=blue; + + + red=CLAMP(red/2,0,127); + green=CLAMP(green/2,0,127); + blue=CLAMP(blue/2,0,127); + _outp( g_sysinfo.SmartXXModCHIP().Equals("SmartXX V3") ? SMARTXX_PWD_RED:SMARTXX_OPX_PWD_RED, red); _outp( g_sysinfo.SmartXXModCHIP().Equals("SmartXX V3") ? SMARTXX_PWD_GREEN:SMARTXX_OPX_PWD_GREEN, green); _outp( g_sysinfo.SmartXXModCHIP().Equals("SmartXX V3") ? SMARTXX_PWD_BLUE:SMARTXX_OPX_PWD_BLUE, blue); - + _outp( SMARTXX_PWM_STATUS, white); - + return true; } @@ -344,3 +590,575 @@ return SetRGBStatus(strTransition); } + +bool ILEDSmartxxRGB::SetRGBState(tRGBColor rgb) +{ + // we have a new request: start reset + strCurrentStatus = "NULL"; + strLastStatus = "NULL"; + strLastTransition = "NULL"; + s_RGBs.strTransition = "NULL"; + // is used to identify first frame in blink-mode, 0 is not usable to do this check as zero is + // a valid value for a color + s_RGBs.strTransition = "fade2"; + s_RGBs.red2 =rgb.r; + s_RGBs.green2 =rgb.g; + s_RGBs.blue2 =rgb.b; + + /*s_RGBs.red1 =s_CurRGB.red; + s_RGBs.green1 =s_CurRGB.green; + s_RGBs.blue1 =s_CurRGB.blue ;*/ + + //dwFrameTime = 0; + //dwLastTime = timeGetTime(); + bRepeat = false; + // end reset + + + + SetRGBStatus(s_RGBs.strTransition); + + if(!IsRunning()) + Start(); + return true; +} + + +void ILEDSmartxxRGB::AmbiLightUpdateFrameNumber() +{ + // only do this, if ambilight is enabled... + if(g_advancedSettings.m_ambiLight && AmbiLightParams.AmbiLightIsPlaying) + { + AmbiLightParams.recentFrame=(AmbiLightParams.recentFrame+1) % g_advancedSettings.m_ambiLightFloatingAverageFrames; + AmbiLightParams.frameHasChanged=true; + } +} + +void ILEDSmartxxRGB::AmbiLightSetAverageColor(unsigned int H,unsigned int S,unsigned int V) +{ + // this function is called after we've gotten the average color of the recent frame. It then shifts + // the array containing the values of our FloatingAverageArray (if enabled) to push out the oldest value and + // insert these new values at the beginning (FIFO). + + // first copy AmbiLightParams to local var for better handling... + AMBILIGHT ¶ms=AmbiLightParams; + // also copy our FloatingAverageFrames-var to local var... + unsigned int FloatingAverageFrames=g_advancedSettings.m_ambiLightFloatingAverageFrames; + + // when mode is linear, then the oldest frame in our floating average counts once, the frame after that counts twice, + // the frame after that thrice and so on... + /*if(g_advancedSettings.m_ambiLightMode=="linear") + { + // in this case the sums have to be recalculated from zero... + params.sumR=0; + params.sumG=0; + params.sumB=0; + // recalculate RGB arrays, starting with the now oldest frame... + // if we have a framenumber of 5 at the moment and FloatingAverageFrames of 10 + // then the first index is 5 which is the 6th field in the array, which takes now + // the oldest value... + for(unsigned int i=1;ioldSumH) + { + oldSumH=sumH; + hsv.h=i+1; + } + } + //now find the max inside our window... + int maxH=hsv.h; + for(int i=hsv.h+1;ihsvHisto.h[maxH]?i:maxH; + hsv.h=maxH; + + //window limits for saturation histogram... + int iMin=CLAMP(hsv.h-WINDOW_SIZE,0,360); + int iMax=CLAMP(hsv.h+WINDOW_SIZE,0,360); + + //now we count all pixels around the + int relevantPixelCount=0; + for(int i=iMin;i<=iMax;i++) + relevantPixelCount+=hsvHisto.h[i]; + + // nur wenn die Anzahl der für das Maximum relevanten Pixel eine Fläche einnimmt die größer als die Vorgegebene + // Minimalgröße ist wird die Saturation und der Value berechnet (ohne die bleibt die Farbe schwarz)... + if(relevantPixelCount*(g_advancedSettings.m_ambiLightSpaceBetweenPixels+1)>=params.SourceWidth*params.SourceHeight*MIN_PERCENTAGE) + { + //Saturation Histogramm + for(int i=0;i<(int)params.PixelCount;i++) + { + if(params.hsvMatrix[i].h>=iMin && params.hsvMatrix[i].h<=iMax) + hsvHisto.s[params.hsvMatrix[i].s]++; + } + + //Max Saturation + for(int i=0;i<=100;i++) + hsv.s=hsvHisto.s[i]>hsvHisto.s[hsv.s] ? i : hsv.s; + + //Value Average + int sumV=0; + for(int i=0;i<(int)params.PixelCount;i++) + sumV+=params.hsvMatrix[i].v; + + if(params.PixelCount>0) + hsv.v=sumV/params.PixelCount; + } + + rgb=HSV2RGB(hsv); + + // now we take the power of gamma for each RGB-value and use our scale-factor to form an valid RGB-value... + // this gamma factor is an simple way to control how fast a LED turns bright especially in lower values. if in dark + // passages you always have blue light try an gamme value below 1 so blue will have a lower gamma curve. On the other + // hand you could pass Red and green a gamma above 1, common value would be e.g. gammaR=2.2, gammeG=2.0, gammaB=0.8 + // (as blue often seems to be the brightest LED). + rgb.r=(int)(pow((float)rgb.r,params.gammaR)*params.gammaScaleR); + rgb.g=(int)(pow((float)rgb.g,params.gammaG)*params.gammaScaleG); + rgb.b=(int)(pow((float)rgb.b,params.gammaB)*params.gammaScaleB); + + rgb.r=CLAMP(rgb.r,g_advancedSettings.m_ambiLightMinRGB,g_advancedSettings.m_ambiLightMaxRGB); + rgb.g=CLAMP(rgb.g,g_advancedSettings.m_ambiLightMinRGB,g_advancedSettings.m_ambiLightMaxRGB); + rgb.b=CLAMP(rgb.b,g_advancedSettings.m_ambiLightMinRGB,g_advancedSettings.m_ambiLightMaxRGB); + + + // our values get passed to the SmartXX... + SetRGBState(rgb); + //SetRGBLed(rgb.r,rgb.g,rgb.b,0); +} + +void ILEDSmartxxRGB::AmbiLightParamsInit(unsigned int SourceWidth,unsigned int SourceHeight,YUVCOEF yuvcoef,YUVRANGE yuvrange) +{ + AMBILIGHT ¶ms=AmbiLightParams; + + if(g_advancedSettings.m_ambiLight==true) + { + CLog::DebugLog ("Params x %i w %i",params.x,params.w); + + CLog::Log(LOGDEBUG,"AmbiLight is initializing..."); + + s_CurRGB.red=2; + s_CurRGB.green=2; + s_CurRGB.blue=2; + params.AmbiLightIsPlaying=true; + // here we initialize our Params, it's always called, when a new movie starts... + params.frameHasChanged = false; + params.recentFrame = 0; + + params.SourceWidth=SourceWidth; + params.SourceHeight=SourceHeight; + + params.yuvcoef=yuvcoef; + params.yuvrange=yuvrange; + + params.PixelCount=0; + params.RowCount=0; + params.PixelOverflow=0; + + params.R=0; + params.G=0; + params.B=0; + + params.hsvMatrix=new tHSVColor[92161]; + //memset(¶ms.hsvMatrix,0,sizeof(params.hsvMatrix)*92161); + + if(params.arrH==NULL) + { + params.hsvh=new tHSVHistogramm[g_advancedSettings.m_ambiLightFloatingAverageFrames]; + params.arrH=new unsigned int[g_advancedSettings.m_ambiLightFloatingAverageFrames]; + params.arrS=new unsigned int[g_advancedSettings.m_ambiLightFloatingAverageFrames]; + params.arrV=new unsigned int[g_advancedSettings.m_ambiLightFloatingAverageFrames]; + } + + //initialize Array... + for(int i=0;i0) + { + //static unsigned int oldR=0,oldG=0,oldB=0; + + // then we calculate the average of the last frame... + + //unsigned int R=(unsigned int)(params.R/params.PixelCount); + //unsigned int G=(unsigned int)(params.G/params.PixelCount); + //unsigned int B=(unsigned int)(params.B/params.PixelCount); + + // check, whether we have a skip (e.g. a new scene or st.) + + //AmbiLightCheckSkip(oldR,oldG,oldB,R,G,B); + //oldR=R;oldG=G;oldB=B; + + // pass it to SetAverageColor... + + //AmbiLightSetAverageColor(R,G,B); + + // and push it onto the SmartXX... + AmbiLightRGBSet(); + } + + // then the RGB-values get zeroed for a fresh start in this new frame... + + params.R=0; + params.G=0; + params.B=0; + + //memset(¶ms.hsvMatrix,0,sizeof(params.hsvMatrix)*92161); + // the counter is reset... + + params.PixelCount=0; + + // a new startposition for Pixeloverflow is calculated... + + //params.PixelOverflow=g_advancedSettings.m_ambiLightSpaceBetweenPixels*params.recentFrame; + + // and FrameChange Property... + params.frameHasChanged = false; + // and RowCount is reset... + params.RowCount=0; + } +} +void ILEDSmartxxRGB::AmbiLightCheckSkip(unsigned int oldR,unsigned int oldG,unsigned int oldB,unsigned int newR,unsigned int newG,unsigned int newB) +{ + /*AMBILIGHT ¶ms=AmbiLightParams; + int skipR=oldR-newR; + int skipG=oldG-newG; + int skipB=oldB-newB; + + if(skipR<0) skipR*=-1; + if(skipG<0) skipG*=-1; + if(skipB<0) skipB*=-1; + + if((skipR+skipG+skipB)>g_advancedSettings.m_ambiLightFilterThreshold*3) + { + for(int i=0;i=params.SourceHeight/2) || position=="left" || position=="right" || position=="all") + { + // these vars take the x-value from where to start getting pixels and the width. e.g. if you only want to interpret + // the left area of the screen, then StartX equals zero and EndX equals StartX+resolutionwidth/2 + // these are always recalulated as x and w might change during different YUV-chunks... + unsigned int StartX; + unsigned int EndX; + // here we set StartX and EndW for different modes... + if(position=="left") + { + StartX=params.x; + EndX=StartX+params.w/2; + } + else if(position=="right") + { + StartX=params.x+params.SourceWidth/2; + EndX=StartX+params.w/2; + } + else + { + StartX=params.x; + EndX=StartX+params.w; + } + // now we go on the first pixel in a line is always Startx+PixelOverflow. PixelOverflow is calculated like this: + // when you have a resolution width of 1280px and SpaceBetweenPixels is 499 (means each 500th pixel in a row is + // interpreted) then the first Pixel taken is StartX+PixelCount which euals normally 0, then we add SpaceBetweenPixels+1 + // so our next Pixel in this row is number 500 (between 0 and 500 there's 499px). the next one is, as you guessed + // 1000 and the next one should be 1500 but, as our resolution width is only 1280, here's the overflow + // (also you have to take notice of FloatingAverageFrames which decreases SpaceBetweenPixels, so if we have + // FloatingAverageFrames of 10 then in each Frame we would interpret only each 500*10=5000th pixel) + for(unsigned int i=10;i=g_advancedSettings.m_ambiLightDarknessLimit) + { + params.hsvMatrix[params.PixelCount]=hsv; + // this counter is necessary, so we know, how many pixels we've counted in this frame... + params.PixelCount++; + } + } + // now our OverFlow-Parameter gets set as described above... + params.PixelOverflow=params.PixelOverflow % g_advancedSettings.m_ambiLightSpaceBetweenPixels*g_advancedSettings.m_ambiLightFloatingAverageFrames; + } + // and the RowCounter gets increased, it's necessary for us to know where we are when mode is top or bottom... + params.RowCount++; +} + +tRGBColor ILEDSmartxxRGB::AmbiLightYUV2RGB(BYTE y, BYTE u, BYTE v) +{ + YUVCOEF &coef = AmbiLightParams.yuvcoef; + YUVRANGE &range = AmbiLightParams.yuvrange; + + // normalize + float Yp = (y - range.y_min) * 255.0f / (range.y_max - range.y_min); + float Up = (u - range.u_min) * 255.0f / (range.u_max - range.u_min) - 127.5f; + float Vp = (v - range.v_min) * 255.0f / (range.v_max - range.v_min) - 127.5f; + + // recalculate + tRGBColor rgb; + rgb.r = (int)(Yp + coef.r_up * Up + coef.r_vp * Vp); + rgb.g = (int)(Yp + coef.g_up * Up + coef.g_vp * Vp); + rgb.b = (int)(Yp + coef.b_up * Up + coef.b_vp * Vp); + + // clamp + rgb.r = CLAMP(rgb.r, 0, 255); + rgb.g = CLAMP(rgb.g, 0, 255); + rgb.b = CLAMP(rgb.b, 0, 255); + + return rgb; +} + +tHSVColor ILEDSmartxxRGB::RGB2HSV(tRGBColor rgb) +{ + float min,max,delta; + float h,s,v; + float r,g,b; + + //skalieren der RGB-Werte auf das Intervall [0;1] + r=(float)rgb.r/255.0f; + g=(float)rgb.g/255.0f; + b=(float)rgb.b/255.0f; + + min=MIN(r,g,b); + max=MAX(r,g,b); + + v=max; // v + + delta=max-min; + + if(max!=0) + { + s=delta/max; // s + + if(r==g && g==b) + h=0; + else if(r==max) // h + h=(g-b)/delta; + else if(g==max) + h=2+(b-r)/delta; + else + h=4+(r-g)/delta; + + h*=60.0f; + if(h<0.0f) + h+=360.0f; + } + else + { + // r = g = b = 0 // s = 0, v is undefined + s=0.0f; + h=0.0f; + } + + //skalieren: h=[0;360]; s,v=[0;100] + tHSVColor hsv; + hsv.h=(int)h; + hsv.s=(int)(s*100); + hsv.v=(int)(v*100); + + return hsv; +} + +tRGBColor ILEDSmartxxRGB::HSV2RGB(tHSVColor hsv) +{ + int i; + float f,p,q,t; + float h,s,v; + float r,g,b; + + h=(float)hsv.h; + s=(float)hsv.s/100.0f; + v=(float)hsv.v/100.0f; + + if(s==0) + { + r=g=b=v; + } + else + { + h/=60; + i=(int)h; + f=h-i; + p=v*(1-s); + q=v*(1-s*f); + t=v*(1-s*(1-f)); + + switch(i) + { + case 0: + case 6: + r=v; + g=t; + b=p; + break; + case 1: + r=q; + g=v; + b=p; + break; + case 2: + r=p; + g=v; + b=t; + break; + case 3: + r=p; + g=q; + b=v; + break; + case 4: + r=t; + g=p; + b=v; + break; + default: + r=v; + g=p; + b=q; + break; + } + } + + tRGBColor rgb; + rgb.r=(int)(r*255); + rgb.g=(int)(g*255); + rgb.b=(int)(b*255); + return rgb; +} Index: xbmc/utils/LED.h =================================================================== --- xbmc/utils/LED.h (revision 30593) +++ xbmc/utils/LED.h (working copy) @@ -22,6 +22,7 @@ */ #include "Thread.h" +#include "cores/VideoRenderers/XBoxRenderer.h" #define SMARTXX_PWD_RED 0xf70c //PWM1: SmartXX V3 port for RGB red output #define SMARTXX_PWD_GREEN 0xf70d //PWM2: SmartXX V3 port for RGB green output @@ -35,27 +36,32 @@ //#define SMARTXX_PWM_LIGHT 0xF701 //PWM5: Display Port brightness control //#define SMARTXX_PWM_CONTRAST 0xF703 //PWM6: Display Port contrast control +#define MAX(a, b, c) (((a) > (b) && (a) > (c)) ? (a) : ((b) > (c) ? (b) : (c))) +#define MIN(a, b, c) (((a) < (b) && (a) < (c)) ? (a) : ((b) < (c) ? (b) : (c))) + +#define FRAMES 10 + struct RGBVALUE { - unsigned short red; - unsigned short green; - unsigned short blue; + unsigned short red; + unsigned short green; + unsigned short blue; unsigned short white; }; struct RGBVALUES { - CStdString strTransition; - DWORD iTime; + CStdString strTransition; + DWORD iTime; - unsigned short red1; - unsigned short green1; - unsigned short blue1; + unsigned short red1; + unsigned short green1; + unsigned short blue1; unsigned short white1; - unsigned short red2; - unsigned short green2; - unsigned short blue2; + unsigned short red2; + unsigned short green2; + unsigned short blue2; unsigned short white2; }; @@ -64,38 +70,129 @@ public: static void CLEDControl(int ixLED); }; -class ILEDSmartxxRGB : public CThread -{ -protected: - RGBVALUE s_CurRGB; - RGBVALUES s_RGBs; - CStdString strCurrentStatus; - CStdString strLastStatus; - CStdString strLastTransition; - - DWORD dwLastTime; - DWORD dwFrameTime; - bool bRepeat; +// --- tRGBColor -------------------------------------------------------------- +typedef struct { + int r, g, b; +} tRGBColor; - void getRGBValues(const CStdString &strRGBa, const CStdString &strRGBb, const CStdString &strWhiteA, const CStdString &strWhiteB, RGBVALUES* s_rgb); - bool SetRGBStatus(const CStdString &strStatus); - -public: - ILEDSmartxxRGB(); - ~ILEDSmartxxRGB(); +// --- tHSVColor -------------------------------------------------------------- +typedef struct { + int h, s, v; +} tHSVColor; - virtual void OnStartup(); - virtual void OnExit(); - virtual void Process(); - virtual bool IsRunning(); - virtual bool Start(); - virtual void Stop(); - bool SetRGBState(const CStdString &strRGB1, const CStdString &strRGB2, const CStdString &strWhiteA, const CStdString &strWhiteB, const CStdString &strTransition, int iTranTime); - - //can used outsite to pass the values directly to the RGB port! - //Don't forget to check if there is a SmartXX V3/OPX! -> CSysInfo::SmartXXModCHIP() - bool SetRGBLed(int red, int green, int blue, int white); +// --- tHSVHistogram ---------------------------------------------------------- +typedef struct { + int h[361]; + int s[101]; + int v[101]; +} tHSVHistogramm; -}; -extern ILEDSmartxxRGB g_iledSmartxxrgb; +struct AMBILIGHT { + bool frameHasChanged; + bool AmbiLightIsPlaying; + + unsigned int SourceWidth; + unsigned int SourceHeight; + unsigned int RowCount; + unsigned int PixelCount; + unsigned int PixelOverflow; + int WidthRatio; + + int x; + int w; + + unsigned int R; + unsigned int G; + unsigned int B; + + unsigned int *arrH; + unsigned int *arrS; + unsigned int *arrV; + + // new calculation + tHSVHistogramm *hsvh; + tHSVColor *hsvMatrix; + // end new calculation + + YUVCOEF yuvcoef; + YUVRANGE yuvrange; + + unsigned int recentFrame; + + float gammaR; + float gammaG; + float gammaB; + float gammaScaleR; + float gammaScaleG; + float gammaScaleB; }; + + class ILEDSmartxxRGB : public CThread + { + protected: + RGBVALUE s_CurRGB; + RGBVALUES s_RGBs; + + CStdString strCurrentStatus; + CStdString strLastStatus; + CStdString strLastTransition; + + DWORD dwLastTime; + DWORD dwFrameTime; + bool bRepeat; + bool isPaused; + + void getRGBValues(const CStdString &strRGBa, const CStdString &strRGBb, const CStdString &strWhiteA, const CStdString &strWhiteB, RGBVALUES* s_rgb); + bool SetRGBStatus(const CStdString &strStatus); + + public: + ILEDSmartxxRGB(); + ~ILEDSmartxxRGB(); + + //virtual void OnStartup(); + //virtual void OnExit(); + //virtual void Process(); + //virtual bool IsRunning(); + //virtual bool Start(); + //virtual void Stop(); + //bool SetRGBState(const CStdString &strRGB1, const CStdString &strRGB2, const CStdString &strWhiteA, const CStdString &strWhiteB, const CStdString &strTransition, int iTranTime); + + //can used outsite to pass the values directly to the RGB port! + //Don't forget to check if there is a SmartXX V3/OPX! -> CSysInfo::SmartXXModCHIP() + //bool SetRGBLed(int red, int green, int blue, int white); + + AMBILIGHT AmbiLightParams; + void AmbiLightSetAverageColor(unsigned int R,unsigned int B,unsigned int G); + void AmbiLightRGBSet(); + tRGBColor AmbiLightYUV2RGB(BYTE y, BYTE u, BYTE v); + void AmbiLightCheckSkip(unsigned int oldR,unsigned int oldG,unsigned int oldB,unsigned int newR,unsigned int newG,unsigned int newB); + tHSVColor RGB2HSV(tRGBColor rgb); + tRGBColor HSV2RGB(tHSVColor color); public: + //ILEDSmartxxRGB(); + //~ILEDSmartxxRGB(); + + virtual void OnStartup(); + virtual void OnExit(); + virtual void Process(); + virtual bool IsRunning(); + virtual bool Start(); + virtual void Stop(); + virtual void Pause(); + virtual void Continue(); + virtual bool IsPaused(); + + bool SetRGBState(const CStdString &strRGB1, const CStdString &strRGB2, const CStdString &strWhiteA, const CStdString &strWhiteB, const CStdString &strTransition, int iTranTime); + bool SetRGBState(tRGBColor rgb); + + //can used outsite to pass the values directly to the RGB port! + //Don't forget to check if there is a SmartXX V3/OPX! -> CSysInfo::SmartXXModCHIP() + bool SetRGBLed(int red, int green, int blue, int white); + + void AmbiLightUpdateFrameNumber(); + void AmbiLightRGBCalculate(BYTE *s0,BYTE *s1,BYTE *s2); + void AmbiLightParamsInit(unsigned int SourceWidth,unsigned int SourceHeight,YUVCOEF yuvcoef,YUVRANGE yuvrange); + void AmbiLightParamsUpdate(int x,int w,int widthRatio); + void AmbiLightUpdate(); + void AmbiLightStop(); + }; + extern ILEDSmartxxRGB g_iledSmartxxrgb;