Merge pull request #4361 from afedchin/dxva_h264_intel_g
authorjmarshallnz <jcmarsha@gmail.com>
Mon, 10 Mar 2014 02:10:17 +0000 (15:10 +1300)
committerjmarshallnz <jcmarsha@gmail.com>
Mon, 10 Mar 2014 02:10:17 +0000 (15:10 +1300)
[DXVA] Fix h264 deconding with refs > 11 on recent Intel GPUs (SNB/IVB)

62 files changed:
addons/skin.confluence/720p/DialogOK.xml
addons/skin.confluence/720p/DialogProgress.xml
addons/skin.confluence/720p/DialogYesNo.xml
addons/skin.confluence/720p/ViewsPVR.xml
addons/xbmc.json/addon.xml
lib/ffmpeg/libavformat/asfdec.c
lib/ffmpeg/patches/0071-ffmpeg-backport-avformat-asfdec-call-read-frame-flush.patch [new file with mode: 0644]
system/settings/settings.xml
xbmc/Application.cpp
xbmc/FileItem.cpp
xbmc/FileItem.h
xbmc/NfoFile.cpp
xbmc/NfoFile.h
xbmc/XbmcContext.cpp
xbmc/cores/AudioEngine/AEFactory.cpp
xbmc/cores/AudioEngine/AEFactory.h
xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp
xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.h
xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp
xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.h
xbmc/cores/AudioEngine/Interfaces/AE.h
xbmc/cores/AudioEngine/Sinks/AESinkDARWINIOS.cpp
xbmc/cores/AudioEngine/Sinks/AESinkDARWINOSX.cpp
xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp
xbmc/cores/AudioEngine/Sinks/osx/CoreAudioDevice.cpp
xbmc/cores/AudioEngine/Sinks/osx/CoreAudioDevice.h
xbmc/cores/AudioEngine/Sinks/osx/CoreAudioStream.cpp
xbmc/cores/AudioEngine/Sinks/osx/CoreAudioStream.h
xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthrough.cpp
xbmc/cores/omxplayer/OMXPlayerAudio.cpp
xbmc/cores/paplayer/MP3codec.cpp
xbmc/cores/paplayer/PAPlayer.cpp
xbmc/cores/playercorefactory/PlayerCoreFactory.cpp
xbmc/dbwrappers/mysqldataset.cpp
xbmc/epg/GUIEPGGridContainer.cpp
xbmc/epg/GUIEPGGridContainer.h
xbmc/guilib/DispResource.h
xbmc/guilib/GUIListGroup.cpp
xbmc/guilib/GUIListLabel.cpp
xbmc/interfaces/json-rpc/AudioLibrary.cpp
xbmc/interfaces/json-rpc/ServiceDescription.h
xbmc/interfaces/json-rpc/SettingsOperations.cpp
xbmc/interfaces/json-rpc/types.json
xbmc/interfaces/legacy/Dialog.cpp
xbmc/interfaces/legacy/Dialog.h
xbmc/interfaces/legacy/WindowXML.cpp
xbmc/interfaces/python/LanguageHook.cpp
xbmc/music/infoscanner/MusicInfoScanner.cpp
xbmc/music/tags/MusicInfoTag.cpp
xbmc/music/tags/MusicInfoTag.h
xbmc/music/windows/GUIWindowMusicBase.cpp
xbmc/pictures/PictureInfoTag.cpp
xbmc/pvr/recordings/PVRRecordings.cpp
xbmc/pvr/windows/GUIViewStatePVR.cpp
xbmc/pvr/windows/GUIViewStatePVR.h
xbmc/pvr/windows/GUIWindowPVRRecordings.cpp
xbmc/settings/lib/Setting.cpp
xbmc/settings/lib/Setting.h
xbmc/settings/lib/SettingDefinitions.h
xbmc/utils/URIUtils.cpp
xbmc/video/VideoThumbLoader.cpp
xbmc/windowing/windows/WinSystemWin32.cpp

index 505dc12..c5605cb 100644 (file)
                        <left>30</left>
                        <top>60</top>
                        <width>550</width>
-                       <height>80</height>
+                       <height>100</height>
                        <align>left</align>
                        <label>-</label>
                        <font>font13</font>
-                       <autoscroll time="3000" delay="4000" repeat="5000">Skin.HasSetting(AutoScroll)</autoscroll>
+                       <autoscroll time="3000" delay="4000" repeat="5000">true</autoscroll>
                </control>
                <control type="button" id="10">
                        <description>OK button</description>
index 196b9bf..4ebd405 100644 (file)
@@ -71,7 +71,7 @@
                        <align>left</align>
                        <label>-</label>
                        <font>font13</font>
-                       <autoscroll time="3000" delay="4000" repeat="5000">Skin.HasSetting(AutoScroll)</autoscroll>
+                       <autoscroll time="3000" delay="4000" repeat="5000">true</autoscroll>
                </control>
                <control type="progress">
                        <description>Progressbar</description>
index c583977..f648ba4 100644 (file)
                        <left>30</left>
                        <top>60</top>
                        <width>550</width>
-                       <height>80</height>
+                       <height>100</height>
                        <align>left</align>
                        <label>-</label>
                        <font>font13</font>
-                       <autoscroll time="3000" delay="4000" repeat="5000">Skin.HasSetting(AutoScroll)</autoscroll>
+                       <autoscroll time="3000" delay="4000" repeat="5000">true</autoscroll>
                </control>
                <control type="button" id="11">
                        <description>Yes button</description>
index fb5d377..ac84014 100644 (file)
                                                <texture border="3">epg-genres/$INFO[ListItem.Property(GenreType)].png</texture>
                                        </control>
                                        <control type="label" id="1">
-                                               <left>6</left>
+                                               <left>10</left>
                                                <top>3</top>
-                                               <width>30</width>
+                                               <width>20</width>
                                                <height>25</height>
                                                <font>font12</font>
                                                <aligny>center</aligny>
                                                <texture border="3">epg-genres/$INFO[ListItem.Property(GenreType)].png</texture>
                                        </control>
                                        <control type="label" id="1">
-                                               <left>6</left>
+                                               <left>10</left>
                                                <top>3</top>
-                                               <width>30</width>
+                                               <width>20</width>
                                                <height>25</height>
                                                <font>font12</font>
                                                <aligny>center</aligny>
index 1a26cd2..10178d9 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<addon id="xbmc.json" version="6.14.0" provider-name="Team XBMC">
+<addon id="xbmc.json" version="6.14.1" provider-name="Team XBMC">
   <backwards-compatibility abi="6.0.0"/>
   <requires>
     <import addon="xbmc.core" version="0.1.0"/>
index c7e16f5..7f14177 100644 (file)
@@ -1401,6 +1401,7 @@ static int64_t asf_read_pts(AVFormatContext *s, int stream_index,
     if (avio_seek(s->pb, pos, SEEK_SET) < 0)
         return AV_NOPTS_VALUE;
 
+    ff_read_frame_flush(s);
     asf_reset_header(s);
     for (;;) {
         if (av_read_frame(s, pkt) < 0) {
diff --git a/lib/ffmpeg/patches/0071-ffmpeg-backport-avformat-asfdec-call-read-frame-flush.patch b/lib/ffmpeg/patches/0071-ffmpeg-backport-avformat-asfdec-call-read-frame-flush.patch
new file mode 100644 (file)
index 0000000..5198548
--- /dev/null
@@ -0,0 +1,30 @@
+From 4b101ab02ea762f70903e894a4b002b229526a4a Mon Sep 17 00:00:00 2001
+From: Michael Niedermayer <michaelni@gmx.at>
+Date: Mon, 12 Aug 2013 22:52:23 +0200
+Subject: [PATCH] avformat/asfdec: call ff_read_frame_flush() in asf_read_pts()
+
+flushing just the asf demuxer but not the cores buffers leads to inconsistencies
+and a "random" packet position which later causes an assertion failure
+
+Fixes Ticket2853
+
+Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
+---
+ libavformat/asfdec.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/libavformat/asfdec.c b/libavformat/asfdec.c
+index cffbcc4..0d6370d 100644
+--- a/libavformat/asfdec.c
++++ b/libavformat/asfdec.c
+@@ -1414,6 +1414,7 @@ static int64_t asf_read_pts(AVFormatContext *s, int stream_index,
+     if (avio_seek(s->pb, pos, SEEK_SET) < 0)
+         return AV_NOPTS_VALUE;
++    ff_read_frame_flush(s);
+     asf_reset_header(s);
+     for (;;) {
+         if (av_read_frame(s, pkt) < 0) {
+-- 
+1.8.5.5
+
index 4cd94d0..c6b03b9 100644 (file)
           <constraints>
             <options>languages</options>
             <delimiter>,</delimiter>
-            <minimum>1</minimum>
-            <maximum>3</maximum>
+            <minimumItems>1</minimumItems>
+            <maximumItems>3</maximumItems>
           </constraints>
           <control type="list" format="string">
             <multiselect>true</multiselect>
index 265881f..5acd7c5 100644 (file)
@@ -4993,7 +4993,6 @@ bool CApplication::ExecuteXBMCAction(std::string actionStr)
   //We don't know if there is unsecure information in this yet, so we
   //postpone any logging
   const std::string in_actionStr(actionStr);
-  CLog::Log(LOGDEBUG,"%s : Translating action string", __FUNCTION__);
   CGUIInfoLabel info(actionStr, "");
   actionStr = info.GetLabel(0);
 
index d38119a..093862b 100644 (file)
@@ -2775,21 +2775,25 @@ CStdString CFileItem::GetTBNFile() const
   return thumbFile;
 }
 
+bool CFileItem::SkipLocalArt() const
+{
+  return (m_strPath.empty()
+       || StringUtils::StartsWithNoCase(m_strPath, "newsmartplaylist://")
+       || StringUtils::StartsWithNoCase(m_strPath, "newplaylist://")
+       || m_bIsShareOrDrive
+       || IsInternetStream()
+       || URIUtils::IsUPnP(m_strPath)
+       || (URIUtils::IsFTP(m_strPath) && !g_advancedSettings.m_bFTPThumbs)
+       || IsPlugin()
+       || IsAddonsPath()
+       || IsParentFolder()
+       || IsLiveTV()
+       || IsDVD());
+}
+
 CStdString CFileItem::FindLocalArt(const std::string &artFile, bool useFolder) const
 {
-  // ignore a bunch that are meaningless
-  if (m_strPath.empty()
-   || StringUtils::StartsWithNoCase(m_strPath, "newsmartplaylist://")
-   || StringUtils::StartsWithNoCase(m_strPath, "newplaylist://")
-   || m_bIsShareOrDrive
-   || IsInternetStream()
-   || URIUtils::IsUPnP(m_strPath)
-   || (URIUtils::IsFTP(m_strPath) && !g_advancedSettings.m_bFTPThumbs)
-   || IsPlugin()
-   || IsAddonsPath()
-   || IsParentFolder()
-   || IsLiveTV()
-   || IsDVD())
+  if (SkipLocalArt())
     return "";
 
   CStdString thumb;
index 43b2022..286bd34 100644 (file)
@@ -332,6 +332,12 @@ public:
    */
   CStdString FindLocalArt(const std::string &artFile, bool useFolder) const;
 
+  /*! \brief Whether or not to skip searching for local art.
+   \return true if local art should be skipped for this item, false otherwise.
+   \sa GetLocalArt, FindLocalArt
+   */
+  bool SkipLocalArt() const;
+
   // Gets the .tbn file associated with this item
   CStdString GetTBNFile() const;
   // Gets the folder image associated with this item (defaults to folder.jpg)
index 804a2b0..fb1db08 100644 (file)
@@ -37,7 +37,7 @@ using namespace std;
 using namespace XFILE;
 using namespace ADDON;
 
-CNfoFile::NFOResult CNfoFile::Create(const CStdString& strPath, const ScraperPtr& info, int episode, const CStdString& strPath2)
+CNfoFile::NFOResult CNfoFile::Create(const CStdString& strPath, const ScraperPtr& info, int episode)
 {
   m_info = info; // assume we can use these settings
   m_type = ScraperTypeFromContent(info->Content());
index 01f742a..b2648f4 100644 (file)
@@ -46,8 +46,7 @@ public:
     ERROR_NFO    = 4
   };
 
-  NFOResult Create(const CStdString&, const ADDON::ScraperPtr&, int episode=-1,
-                   const CStdString& strPath2="");
+  NFOResult Create(const CStdString&, const ADDON::ScraperPtr&, int episode=-1);
   template<class T>
     bool GetDetails(T& details,const char* document=NULL, bool prioritise=false)
   {
index fcb81eb..c928c82 100644 (file)
@@ -50,6 +50,8 @@ namespace XBMC
   Context::~Context()
   {
     // cleanup
+    XbmcCommons::Exception::SetLogger(NULL);
+    CThread::SetLogger(NULL);
     delete impl->loggerImpl;
 
     delete impl;
index 17ebcc9..67f61c1 100644 (file)
@@ -180,7 +180,7 @@ std::string CAEFactory::GetDefaultDevice(bool passthrough)
   return "default";
 }
 
-bool CAEFactory::SupportsRaw(AEDataFormat format)
+bool CAEFactory::SupportsRaw(AEDataFormat format, int samplerate)
 {
   // check if passthrough is enabled
   if (!CSettings::Get().GetBool("audiooutput.passthrough"))
@@ -203,7 +203,7 @@ bool CAEFactory::SupportsRaw(AEDataFormat format)
     return false;
 
   if(AE)
-    return AE->SupportsRaw(format);
+    return AE->SupportsRaw(format, samplerate);
 
   return false;
 }
index 1d55513..59f9316 100644 (file)
@@ -52,7 +52,7 @@ public:
   static void EnumerateOutputDevices(AEDeviceList &devices, bool passthrough);
   static void VerifyOutputDevice(std::string &device, bool passthrough);
   static std::string GetDefaultDevice(bool passthrough);
-  static bool SupportsRaw(AEDataFormat format);
+  static bool SupportsRaw(AEDataFormat format, int samplerate);
   static bool SupportsSilenceTimeout();
 
   /**
index 02c0a34..8ac14d3 100644 (file)
@@ -236,6 +236,9 @@ void CActiveAE::StateMachine(int signal, Protocol *port, Message *msg)
           return;
         case CActiveAEControlProtocol::DISPLAYRESET:
           return;
+        case CActiveAEControlProtocol::APPFOCUSED:
+          m_sink.m_controlPort.SendOutMessage(CSinkControlProtocol::APPFOCUSED, msg->data, sizeof(bool));
+          return;
         default:
           break;
         }
@@ -393,13 +396,14 @@ void CActiveAE::StateMachine(int signal, Protocol *port, Message *msg)
     case AE_TOP_CONFIGURED:
       if (port == &m_controlPort)
       {
+        bool streaming;
         switch (signal)
         {
         case CActiveAEControlProtocol::RECONFIGURE:
           if (m_streams.empty())
           {
-            bool silence = false;
-            m_sink.m_controlPort.SendOutMessage(CSinkControlProtocol::SILENCEMODE, &silence, sizeof(bool));
+            streaming = false;
+            m_sink.m_controlPort.SendOutMessage(CSinkControlProtocol::STREAMING, &streaming, sizeof(bool));
           }
           LoadSettings();
           ChangeResamplers();
@@ -460,12 +464,18 @@ void CActiveAE::StateMachine(int signal, Protocol *port, Message *msg)
           CActiveAEStream *stream;
           stream = *(CActiveAEStream**)msg->data;
           if (stream->m_paused != true && m_streams.size() == 1)
+          {
             FlushEngine();
+            streaming = false;
+            m_sink.m_controlPort.SendOutMessage(CSinkControlProtocol::STREAMING, &streaming, sizeof(bool));
+          }
           stream->m_paused = true;
           return;
         case CActiveAEControlProtocol::RESUMESTREAM:
           stream = *(CActiveAEStream**)msg->data;
           stream->m_paused = false;
+          streaming = true;
+          m_sink.m_controlPort.SendOutMessage(CSinkControlProtocol::STREAMING, &streaming, sizeof(bool));
           m_extTimeout = 0;
           return;
         case CActiveAEControlProtocol::FLUSHSTREAM:
@@ -946,7 +956,7 @@ void CActiveAE::Configure(AEAudioFormat *desiredFmt)
     unsigned int buffertime = m_sinkFormat.m_frames / m_sinkFormat.m_sampleRate;
     if (buffertime > MAX_BUFFER_TIME)
     {
-      CLog::Log(LOGWARNING, "ActiveAE::%s - sink returned large buffer of %d ms, reducing to %d ms", __FUNCTION__, buffertime, MAX_BUFFER_TIME*1000);
+      CLog::Log(LOGWARNING, "ActiveAE::%s - sink returned large buffer of %d ms, reducing to %d ms", __FUNCTION__, buffertime, (int)(MAX_BUFFER_TIME*1000));
       m_sinkFormat.m_frames = MAX_BUFFER_TIME * m_sinkFormat.m_sampleRate;
     }
   }
@@ -974,8 +984,8 @@ void CActiveAE::Configure(AEAudioFormat *desiredFmt)
     sinkInputFormat = inputFormat;
     m_internalFormat = inputFormat;
 
-    bool silence = false;
-    m_sink.m_controlPort.SendOutMessage(CSinkControlProtocol::SILENCEMODE, &silence, sizeof(bool));
+    bool streaming = false;
+    m_sink.m_controlPort.SendOutMessage(CSinkControlProtocol::STREAMING, &streaming, sizeof(bool));
 
     delete m_encoder;
     m_encoder = NULL;
@@ -999,8 +1009,8 @@ void CActiveAE::Configure(AEAudioFormat *desiredFmt)
   // resample buffers for streams
   else
   {
-    bool silence = true;
-    m_sink.m_controlPort.SendOutMessage(CSinkControlProtocol::SILENCEMODE, &silence, sizeof(bool));
+    bool streaming = true;
+    m_sink.m_controlPort.SendOutMessage(CSinkControlProtocol::STREAMING, &streaming, sizeof(bool));
 
     AEAudioFormat outputFormat;
     if (m_mode == MODE_RAW)
@@ -2176,9 +2186,9 @@ void CActiveAE::OnSettingsChange(const std::string& setting)
   }
 }
 
-bool CActiveAE::SupportsRaw(AEDataFormat format)
+bool CActiveAE::SupportsRaw(AEDataFormat format, int samplerate)
 {
-  if (!m_sink.SupportsFormat(CSettings::Get().GetString("audiooutput.passthroughdevice"), format))
+  if (!m_sink.SupportsFormat(CSettings::Get().GetString("audiooutput.passthroughdevice"), format, samplerate))
     return false;
 
   return true;
@@ -2218,19 +2228,19 @@ bool CActiveAE::IsSettingVisible(const std::string &settingId)
   }
   else if (settingId == "audiooutput.truehdpassthrough")
   {
-    if (m_sink.SupportsFormat(CSettings::Get().GetString("audiooutput.passthroughdevice"), AE_FMT_TRUEHD) &&
+    if (m_sink.SupportsFormat(CSettings::Get().GetString("audiooutput.passthroughdevice"), AE_FMT_TRUEHD, 192000) &&
         CSettings::Get().GetInt("audiooutput.config") != AE_CONFIG_FIXED)
       return true;
   }
   else if (settingId == "audiooutput.dtshdpassthrough")
   {
-    if (m_sink.SupportsFormat(CSettings::Get().GetString("audiooutput.passthroughdevice"), AE_FMT_DTSHD) &&
+    if (m_sink.SupportsFormat(CSettings::Get().GetString("audiooutput.passthroughdevice"), AE_FMT_DTSHD, 192000) &&
         CSettings::Get().GetInt("audiooutput.config") != AE_CONFIG_FIXED)
       return true;
   }
   else if (settingId == "audiooutput.eac3passthrough")
   {
-    if (m_sink.SupportsFormat(CSettings::Get().GetString("audiooutput.passthroughdevice"), AE_FMT_EAC3) &&
+    if (m_sink.SupportsFormat(CSettings::Get().GetString("audiooutput.passthroughdevice"), AE_FMT_EAC3, 192000) &&
         CSettings::Get().GetInt("audiooutput.config") != AE_CONFIG_FIXED)
       return true;
   }
@@ -2354,6 +2364,11 @@ void CActiveAE::OnResetDevice()
   m_controlPort.SendOutMessage(CActiveAEControlProtocol::DISPLAYRESET);
 }
 
+void CActiveAE::OnAppFocusChange(bool focus)
+{
+  m_controlPort.SendOutMessage(CActiveAEControlProtocol::APPFOCUSED, &focus, sizeof(focus));
+}
+
 //-----------------------------------------------------------------------------
 // Utils
 //-----------------------------------------------------------------------------
index 225c694..25f8274 100644 (file)
@@ -89,6 +89,7 @@ public:
     GETSTATE,
     DISPLAYLOST,
     DISPLAYRESET,
+    APPFOCUSED,
     KEEPCONFIG,
     TIMEOUT,
   };
@@ -221,7 +222,7 @@ public:
 
   virtual void EnumerateOutputDevices(AEDeviceList &devices, bool passthrough);
   virtual std::string GetDefaultDevice(bool passthrough);
-  virtual bool SupportsRaw(AEDataFormat format);
+  virtual bool SupportsRaw(AEDataFormat format, int samplerate);
   virtual bool SupportsSilenceTimeout();
   virtual bool SupportsQualityLevel(enum AEQuality level);
   virtual bool IsSettingVisible(const std::string &settingId);
@@ -233,6 +234,7 @@ public:
 
   virtual void OnLostDevice();
   virtual void OnResetDevice();
+  virtual void OnAppFocusChange(bool focus);
 
 protected:
   void PlaySound(CActiveAESound *sound);
index 679f7d6..10971f5 100644 (file)
@@ -107,7 +107,7 @@ bool CActiveAESink::HasPassthroughDevice()
   return false;
 }
 
-bool CActiveAESink::SupportsFormat(const std::string &device, AEDataFormat format)
+bool CActiveAESink::SupportsFormat(const std::string &device, AEDataFormat format, int samplerate)
 {
   std::string dev = device;
   std::string dri;
@@ -124,7 +124,14 @@ bool CActiveAESink::SupportsFormat(const std::string &device, AEDataFormat forma
           AEDataFormatList::iterator itt3;
           itt3 = find(info.m_dataFormats.begin(), info.m_dataFormats.end(), format);
           if (itt3 != info.m_dataFormats.end())
-            return true;
+          {
+            AESampleRateList::iterator itt4;
+            itt4 = find(info.m_sampleRates.begin(), info.m_sampleRates.end(), samplerate);
+            if (itt4 != info.m_sampleRates.end())
+              return true;
+            else
+              return false;
+          }
           else
             return false;
         }
@@ -177,6 +184,7 @@ void CActiveAESink::StateMachine(int signal, Protocol *port, Message *msg)
           }
           m_extError = false;
           m_extSilenceTimer = 0;
+          m_extStreaming = false;
           ReturnBuffers();
           OpenSink();
 
@@ -216,6 +224,12 @@ void CActiveAESink::StateMachine(int signal, Protocol *port, Message *msg)
           msg->Reply(CSinkControlProtocol::ACC);
           return;
 
+        case CSinkControlProtocol::APPFOCUSED:
+          m_extAppFocused = *(bool*)msg->data;
+          SetSilenceTimer();
+          m_extTimeout = 0;
+          return;
+
         default:
           break;
         }
@@ -275,19 +289,14 @@ void CActiveAESink::StateMachine(int signal, Protocol *port, Message *msg)
       {
         switch (signal)
         {
-        case CSinkControlProtocol::SILENCEMODE:
-          bool silencemode;
-          silencemode = *(bool*)msg->data;
-          if (silencemode)
-            m_extSilenceTimeout = XbmcThreads::EndTime::InfiniteValue;
-          else
-            m_extSilenceTimeout = CSettings::Get().GetInt("audiooutput.streamsilence") * 60000;
-          m_extSilenceTimer.Set(m_extSilenceTimeout);
+        case CSinkControlProtocol::STREAMING:
+          m_extStreaming = *(bool*)msg->data;
+          SetSilenceTimer();
           if (!m_extSilenceTimer.IsTimePast())
           {
             m_state = S_TOP_CONFIGURED_SILENCE;
-            m_extTimeout = 0;
           }
+          m_extTimeout = 0;
           return;
         case CSinkControlProtocol::VOLUME:
           m_volume = *(float*)msg->data;
@@ -339,7 +348,10 @@ void CActiveAESink::StateMachine(int signal, Protocol *port, Message *msg)
       {
         switch (signal)
         {
-        case CSinkControlProtocol::SILENCEMODE:
+        case CSinkControlProtocol::STREAMING:
+          m_extStreaming = *(bool*)msg->data;
+          SetSilenceTimer();
+          m_extTimeout = 0;
           return;
         case CSinkControlProtocol::VOLUME:
           m_volume = *(float*)msg->data;
@@ -427,7 +439,10 @@ void CActiveAESink::StateMachine(int signal, Protocol *port, Message *msg)
           {
             m_sink->Drain();
             m_state = S_TOP_CONFIGURED_IDLE;
-            m_extTimeout = 10000;
+            if (m_extAppFocused)
+              m_extTimeout = 10000;
+            else
+              m_extTimeout = 0;
           }
           return;
         default:
@@ -477,6 +492,7 @@ void CActiveAESink::Process()
   m_state = S_TOP_UNCONFIGURED;
   m_extTimeout = 1000;
   m_bStateMachineSelfTrigger = false;
+  m_extAppFocused = true;
 
   while (!m_bStop)
   {
@@ -905,3 +921,14 @@ void CActiveAESink::GenerateNoise()
   convertFn(noise, nb_floats, m_sampleOfSilence.pkt->data[0]);
   _aligned_free(noise);
 }
+
+void CActiveAESink::SetSilenceTimer()
+{
+  if (m_extStreaming)
+    m_extSilenceTimeout = XbmcThreads::EndTime::InfiniteValue;
+  else if (m_extAppFocused)
+    m_extSilenceTimeout = CSettings::Get().GetInt("audiooutput.streamsilence") * 60000;
+  else
+    m_extSilenceTimeout = 0;
+  m_extSilenceTimer.Set(m_extSilenceTimeout);
+}
index 420b966..81b1117 100644 (file)
@@ -57,7 +57,8 @@ public:
   {
     CONFIGURE,
     UNCONFIGURE,
-    SILENCEMODE,
+    STREAMING,
+    APPFOCUSED,
     VOLUME,
     FLUSH,
     TIMEOUT,
@@ -97,7 +98,7 @@ public:
   void Dispose();
   AEDeviceType GetDeviceType(const std::string &device);
   bool HasPassthroughDevice();
-  bool SupportsFormat(const std::string &device, AEDataFormat format);
+  bool SupportsFormat(const std::string &device, AEDataFormat format, int samplerate);
   CSinkControlProtocol m_controlPort;
   CSinkDataProtocol m_dataPort;
 
@@ -108,6 +109,7 @@ protected:
   void GetDeviceFriendlyName(std::string &device);
   void OpenSink();
   void ReturnBuffers();
+  void SetSilenceTimer();
 
   unsigned int OutputSamples(CSampleBuffer* samples);
   void ConvertInit(CSampleBuffer* samples);
@@ -123,6 +125,8 @@ protected:
   int m_extTimeout;
   bool m_extError;
   unsigned int m_extSilenceTimeout;
+  bool m_extAppFocused;
+  bool m_extStreaming;
   XbmcThreads::EndTime m_extSilenceTimer;
 
   CSampleBuffer m_sampleOfSilence;
index dd32897..3379bf6 100644 (file)
@@ -203,7 +203,7 @@ public:
    * @see CAEPackIEC61937::CAEPackIEC61937()
    * @returns true if the AudioEngine is capable of RAW output
    */
-  virtual bool SupportsRaw(AEDataFormat format) { return false; }
+  virtual bool SupportsRaw(AEDataFormat format, int samplerate) { return false; }
 
    /**
    * Returns true if the AudioEngine supports drain mode which is not streaming silence when idle
index eed93fa..130b8a9 100644 (file)
@@ -237,10 +237,16 @@ unsigned int CAAudioUnitSink::write(uint8_t *data, unsigned int frames)
   if (m_buffer->GetWriteSize() < frames * m_frameSize)
   { // no space to write - wait for a bit
     CSingleLock lock(mutex);
+    unsigned int timeout = 900 * frames / m_sampleRate;
     if (!m_started)
-      condVar.wait(lock);
-    else
-      condVar.wait(lock, 900 * frames / m_sampleRate);
+      timeout = 500;
+
+    // we are using a timer here for beeing sure for timeouts
+    // condvar can be woken spuriously as signaled
+    XbmcThreads::EndTime timer(timeout);
+    condVar.wait(mutex, timeout);
+    if (!m_started && timer.IsTimePast())
+      return INT_MAX;
   }
 
   unsigned int write_frames = std::min(frames, m_buffer->GetWriteSize() / m_frameSize);
@@ -253,11 +259,21 @@ unsigned int CAAudioUnitSink::write(uint8_t *data, unsigned int frames)
 void CAAudioUnitSink::drain()
 {
   unsigned int bytes = m_buffer->GetReadSize();
-  while (bytes)
+  unsigned int totalBytes = bytes;
+  int maxNumTimeouts = 3;
+  unsigned int timeout = 900 * bytes / (m_sampleRate * m_frameSize);
+  while (bytes && maxNumTimeouts > 0)
   {
     CSingleLock lock(mutex);
-    condVar.wait(mutex, 900 * bytes / (m_sampleRate * m_frameSize));
+    XbmcThreads::EndTime timer(timeout);
+    condVar.wait(mutex, timeout);
+
     bytes = m_buffer->GetReadSize();
+    // if we timeout and don't
+    // consum bytes - decrease maxNumTimeouts
+    if (timer.IsTimePast() && bytes == totalBytes)
+      maxNumTimeouts--;
+    totalBytes = bytes;
   }
 }
 
index a9e123d..60eb532 100644 (file)
@@ -83,8 +83,15 @@ static void EnumerateDevices(CADeviceList &list)
     device.m_displayName = device.m_deviceName;
     device.m_displayNameExtra = "";
 
-    if (device.m_deviceName.find("HDMI") != std::string::npos)
-      device.m_deviceType = AE_DEVTYPE_HDMI;
+    // flag indicating that passthroughformats where added throughout the stream enumeration
+    bool hasPassthroughFormats = false;
+    // the maximum number of channels found in the streams
+    UInt32 numMaxChannels = 0;
+    // the terminal type as reported by ca
+    UInt32 caTerminalType = 0;
+      
+    bool isDigital = caDevice.IsDigital(caTerminalType);
+
 
     CLog::Log(LOGDEBUG, "EnumerateDevices:Device(%s)" , device.m_deviceName.c_str());
     AudioStreamIdList streams;
@@ -101,6 +108,7 @@ static void EnumerateDevices(CADeviceList &list)
             std::string formatString;
             CLog::Log(LOGDEBUG, "EnumerateDevices:Format(%s)" ,
                                 StreamDescriptionToString(desc, formatString));
+
             // add stream format info
             switch (desc.mFormatID)
             {
@@ -110,9 +118,8 @@ static void EnumerateDevices(CADeviceList &list)
                   device.m_dataFormats.push_back(AE_FMT_AC3);
                 if (!HasDataFormat(device.m_dataFormats, AE_FMT_DTS))
                   device.m_dataFormats.push_back(AE_FMT_DTS);
-                // if we are not hdmi, this is an S/PDIF device
-                if (device.m_deviceType != AE_DEVTYPE_HDMI)
-                  device.m_deviceType = AE_DEVTYPE_IEC958;
+                hasPassthroughFormats = true;
+                isDigital = true;// sanity - those are always digital devices!
                 break;
               default:
                 AEDataFormat format = AE_FMT_INVALID;
@@ -123,8 +130,19 @@ static void EnumerateDevices(CADeviceList &list)
                       format = AE_FMT_S16BE;
                     else
                     {
+                      // if it is no digital stream per definition
+                      // check if the device name suggests that it is digital
+                      // (some hackintonshs are not so smart in announcing correct
+                      // ca devices ...
+                      if (!isDigital)
+                      {
+                        std::string devNameLower = device.m_deviceName;
+                        StringUtils::ToLower(devNameLower);                       
+                        isDigital = devNameLower.find("digital") != std::string::npos;
+                      }
+
                       /* Passthrough is possible with a 2ch digital output */
-                      if (desc.mChannelsPerFrame == 2 && CCoreAudioStream::IsDigitalOuptut(*j))
+                      if (desc.mChannelsPerFrame == 2 && isDigital)
                       {
                         if (desc.mSampleRate == 48000)
                         {
@@ -132,11 +150,13 @@ static void EnumerateDevices(CADeviceList &list)
                             device.m_dataFormats.push_back(AE_FMT_AC3);
                           if (!HasDataFormat(device.m_dataFormats, AE_FMT_DTS))
                             device.m_dataFormats.push_back(AE_FMT_DTS);
+                          hasPassthroughFormats = true;
                         }
                         else if (desc.mSampleRate == 192000)
                         {
                           if (!HasDataFormat(device.m_dataFormats, AE_FMT_EAC3))
                             device.m_dataFormats.push_back(AE_FMT_EAC3);
+                          hasPassthroughFormats = true;
                         }
                       }
                       format = AE_FMT_S16LE;
@@ -160,6 +180,10 @@ static void EnumerateDevices(CADeviceList &list)
                     }
                     break;
                 }
+                
+                if (numMaxChannels < desc.mChannelsPerFrame)
+                  numMaxChannels = desc.mChannelsPerFrame;
+                
                 if (format != AE_FMT_INVALID && !HasDataFormat(device.m_dataFormats, format))
                   device.m_dataFormats.push_back(format);
                 break;
@@ -182,6 +206,46 @@ static void EnumerateDevices(CADeviceList &list)
       }
     }
 
+    
+    // flag indicating that the device name "sounds" like HDMI
+    bool hasHdmiName = device.m_deviceName.find("HDMI") != std::string::npos;
+    // flag indicating that the device name "sounds" like DisplayPort
+    bool hasDisplayPortName = device.m_deviceName.find("DisplayPort") != std::string::npos;
+    
+    // decide the type of the device based on the discovered information
+    // in the streams
+    // device defaults to PCM (see start of the while loop)
+    // it can be HDMI, DisplayPort or Optical
+    // for all of those types it needs to support
+    // passthroughformats and needs to be a digital port
+    if (hasPassthroughFormats && isDigital)
+    {
+      // if the max number of channels was more then 2
+      // this can be HDMI or DisplayPort or Thunderbolt
+      if (numMaxChannels > 2)
+      {
+        // either the devicename suggests its HDMI
+        // or CA reported the terminalType as HDMI
+        if (hasHdmiName || caTerminalType == kIOAudioDeviceTransportTypeHdmi)
+          device.m_deviceType = AE_DEVTYPE_HDMI;
+
+        // either the devicename suggests its DisplayPort
+        // or CA reported the terminalType as DisplayPort or Thunderbolt
+        if (hasDisplayPortName || caTerminalType == kIOAudioDeviceTransportTypeDisplayPort || caTerminalType == kIOAudioDeviceTransportTypeThunderbolt)
+          device.m_deviceType = AE_DEVTYPE_DP;
+      }
+      else// treat all other digital passthrough devices as optical
+        device.m_deviceType = AE_DEVTYPE_IEC958;
+    }
+
+    // devicename based overwrites from former code - maybe FIXME at some point when we
+    // are sure that the upper detection does its job in all[tm] use cases
+    if (hasHdmiName)
+      device.m_deviceType = AE_DEVTYPE_HDMI;
+    if (hasDisplayPortName)
+      device.m_deviceType = AE_DEVTYPE_DP;
+    
+    
     list.push_back(std::make_pair(deviceID, device));
     //in the first place of the list add the default device
     //with name "default" - if this is selected
@@ -561,10 +625,16 @@ unsigned int CAESinkDARWINOSX::AddPackets(uint8_t *data, unsigned int frames, bo
   if (m_buffer->GetWriteSize() < frames * m_format.m_frameSize)
   { // no space to write - wait for a bit
     CSingleLock lock(mutex);
+    unsigned int timeout = 900 * frames / m_format.m_sampleRate;
     if (!m_started)
-      condVar.wait(lock);
-    else
-      condVar.wait(lock, 900 * frames / m_format.m_sampleRate);
+      timeout = 500;
+
+    // we are using a timer here for beeing sure for timeouts
+    // condvar can be woken spuriously as signaled
+    XbmcThreads::EndTime timer(timeout);
+    condVar.wait(mutex, timeout);
+    if (!m_started && timer.IsTimePast())
+      return INT_MAX;    
   }
 
   unsigned int write_frames = std::min(frames, m_buffer->GetWriteSize() / m_format.m_frameSize);
@@ -577,11 +647,21 @@ unsigned int CAESinkDARWINOSX::AddPackets(uint8_t *data, unsigned int frames, bo
 void CAESinkDARWINOSX::Drain()
 {
   int bytes = m_buffer->GetReadSize();
-  while (bytes)
+  int totalBytes = bytes;
+  int maxNumTimeouts = 3;
+  unsigned int timeout = 900 * bytes / (m_format.m_sampleRate * m_format.m_frameSize);
+  while (bytes && maxNumTimeouts > 0)
   {
     CSingleLock lock(mutex);
-    condVar.wait(mutex, 900 * bytes / (m_format.m_sampleRate * m_format.m_frameSize));
+    XbmcThreads::EndTime timer(timeout);
+    condVar.wait(mutex, timeout);
+
     bytes = m_buffer->GetReadSize();
+    // if we timeout and don't
+    // consum bytes - decrease maxNumTimeouts
+    if (timer.IsTimePast() && bytes == totalBytes)
+      maxNumTimeouts--;
+    totalBytes = bytes;
   }
 }
 
index d52c6f1..c77fe47 100644 (file)
@@ -36,6 +36,8 @@
 #define NUM_OMX_BUFFERS 2
 #define AUDIO_PLAYBUFFER (1.0/20.0)
 
+static const unsigned int PassthroughSampleRates[] = { 8000, 11025, 16000, 22050, 24000, 32000, 41400, 48000, 88200, 96000, 176400, 192000 };
+
 CAEDeviceInfo CAESinkPi::m_info;
 
 CAESinkPi::CAESinkPi() :
@@ -282,7 +284,8 @@ void CAESinkPi::EnumerateDevicesEx(AEDeviceInfoList &list, bool force)
   m_info.m_displayNameExtra = "";
   m_info.m_channels += AE_CH_FL;
   m_info.m_channels += AE_CH_FR;
-  m_info.m_sampleRates.push_back(48000);
+  for (unsigned int i=0; i<sizeof PassthroughSampleRates/sizeof *PassthroughSampleRates; i++)
+    m_info.m_sampleRates.push_back(PassthroughSampleRates[i]);
   m_info.m_dataFormats.push_back(AE_FMT_S16LE);
   m_info.m_dataFormats.push_back(AE_FMT_AC3);
   m_info.m_dataFormats.push_back(AE_FMT_DTS);
index 937e561..20b8728 100644 (file)
@@ -239,6 +239,38 @@ std::string CCoreAudioDevice::GetName()
   return name;
 }
 
+bool CCoreAudioDevice::IsDigital(UInt32 &transportType)
+{
+  bool isDigital = false;
+  if (!m_DeviceId)
+    return false;
+
+  AudioObjectPropertyAddress  propertyAddress;
+  propertyAddress.mScope    = kAudioDevicePropertyScopeOutput;
+  propertyAddress.mElement  = 0;
+  propertyAddress.mSelector = kAudioDevicePropertyTransportType;
+
+  UInt32 propertySize = sizeof(transportType);
+  OSStatus ret = AudioObjectGetPropertyData(m_DeviceId, &propertyAddress, 0, NULL, &propertySize, &transportType);
+  if (ret != noErr)
+      return false;
+    
+  if (transportType == kIOAudioDeviceTransportTypeFireWire)
+    isDigital = true;
+  if (transportType == kIOAudioDeviceTransportTypeUSB)
+    isDigital = true;
+  if (transportType == kIOAudioDeviceTransportTypeHdmi)
+    isDigital = true;
+  if (transportType == kIOAudioDeviceTransportTypeDisplayPort)
+    isDigital = true;
+  if (transportType == kIOAudioDeviceTransportTypeThunderbolt)
+    isDigital = true;
+  if (transportType == kAudioStreamTerminalTypeDigitalAudioInterface)
+    isDigital = true;
+    
+  return isDigital;
+}
+
 UInt32 CCoreAudioDevice::GetTotalOutputChannels()
 {
   UInt32 channels = 0;
index dcd5bf6..e95f8c1 100644 (file)
@@ -51,6 +51,7 @@ public:
   
   AudioDeviceID GetId() {return m_DeviceId;}
   std::string   GetName();
+  bool          IsDigital(UInt32 &transportType);
   UInt32        GetTotalOutputChannels();
   bool          GetStreams(AudioStreamIdList *pList);
   bool          IsRunning();
index 05fd5bf..94b1426 100644 (file)
 #include "utils/log.h"
 #include "utils/StdString.h"
 
-// defines taken from CoreAudio/AudioHardware.h from SDK 10.8
-#if !defined kAudioStreamTerminalTypeHDMI
-#define kAudioStreamTerminalTypeHDMI 'hdmi'
-#endif
-
-#if !defined kAudioStreamTerminalTypeDisplayPort
-#define kAudioStreamTerminalTypeDisplayPort 'dprt'
-#endif
-
 CCoreAudioStream::CCoreAudioStream() :
   m_StreamId  (0    )
 {
@@ -136,12 +127,19 @@ UInt32 CCoreAudioStream::GetDirection()
   return val;
 }
 
+// WARNING - don't rely on this method - the return value of
+// GetTerminalType is driver specific - the checked return
+// values are only recommendations from apple
 bool CCoreAudioStream::IsDigitalOuptut(AudioStreamID id)
 {
   UInt32 type = GetTerminalType(id);
+  // yes apple is mixing types here...
   return (type == kAudioStreamTerminalTypeDigitalAudioInterface ||
-          type == kAudioStreamTerminalTypeDisplayPort ||
-          type == kAudioStreamTerminalTypeHDMI);
+          type == kIOAudioDeviceTransportTypeDisplayPort ||
+          type == kIOAudioDeviceTransportTypeHdmi ||
+          type == kIOAudioDeviceTransportTypeFireWire ||
+          type == kIOAudioDeviceTransportTypeThunderbolt ||
+          type == kIOAudioDeviceTransportTypeUSB);
 }
 
 UInt32 CCoreAudioStream::GetTerminalType(AudioStreamID id)
index 3f3d1d0..6edc7e2 100644 (file)
 
 #include "threads/Event.h"
 #include <CoreAudio/CoreAudio.h>
+#include <IOKit/audio/IOAudioTypes.h>
 
 #include <list>
 
+// not defined in 10.6 sdk
+#ifndef kIOAudioDeviceTransportTypeThunderbolt
+#define kIOAudioDeviceTransportTypeThunderbolt 'thun'
+#endif
+
+
 typedef std::list<AudioStreamID> AudioStreamIdList;
 typedef std::list<AudioStreamRangedDescription> StreamFormatList;
 
index 5338c71..79b4e6e 100644 (file)
@@ -40,11 +40,11 @@ CDVDAudioCodecPassthrough::~CDVDAudioCodecPassthrough(void)
 
 bool CDVDAudioCodecPassthrough::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
 {
-  bool bSupportsAC3Out    = CAEFactory::SupportsRaw(AE_FMT_AC3);
-  bool bSupportsEAC3Out   = CAEFactory::SupportsRaw(AE_FMT_EAC3);
-  bool bSupportsDTSOut    = CAEFactory::SupportsRaw(AE_FMT_DTS);
-  bool bSupportsTrueHDOut = CAEFactory::SupportsRaw(AE_FMT_TRUEHD);
-  bool bSupportsDTSHDOut  = CAEFactory::SupportsRaw(AE_FMT_DTSHD);
+  bool bSupportsAC3Out    = CAEFactory::SupportsRaw(AE_FMT_AC3, hints.samplerate);
+  bool bSupportsEAC3Out   = CAEFactory::SupportsRaw(AE_FMT_EAC3, 192000);
+  bool bSupportsDTSOut    = CAEFactory::SupportsRaw(AE_FMT_DTS, hints.samplerate);
+  bool bSupportsTrueHDOut = CAEFactory::SupportsRaw(AE_FMT_TRUEHD, 192000);
+  bool bSupportsDTSHDOut  = CAEFactory::SupportsRaw(AE_FMT_DTSHD, 192000);
 
   /* only get the dts core from the parser if we don't support dtsHD */
   m_info.SetCoreOnly(!bSupportsDTSHDOut);
index 27dbb5d..8219015 100644 (file)
@@ -511,12 +511,12 @@ AEDataFormat OMXPlayerAudio::GetDataFormat(CDVDStreamInfo hints)
   /* check our audio capabilties */
 
   /* pathrought is overriding hw decode*/
-  if(hints.codec == AV_CODEC_ID_AC3 && CAEFactory::SupportsRaw(AE_FMT_AC3) && !CSettings::Get().GetBool("audiooutput.dualaudio"))
+  if(hints.codec == AV_CODEC_ID_AC3 && CAEFactory::SupportsRaw(AE_FMT_AC3, hints.samplerate) && !CSettings::Get().GetBool("audiooutput.dualaudio"))
   {
     dataFormat = AE_FMT_AC3;
     m_passthrough = true;
   }
-  if(hints.codec == AV_CODEC_ID_DTS && CAEFactory::SupportsRaw(AE_FMT_DTS) && !CSettings::Get().GetBool("audiooutput.dualaudio"))
+  if(hints.codec == AV_CODEC_ID_DTS && CAEFactory::SupportsRaw(AE_FMT_DTS, hints.samplerate) && !CSettings::Get().GetBool("audiooutput.dualaudio"))
   {
     dataFormat = AE_FMT_DTS;
     m_passthrough = true;
index 7db7a15..a6f663a 100644 (file)
@@ -886,13 +886,14 @@ int MP3Codec::ReadDuration()
 
       double tpfbs[] = { 0, 384.0f, 1152.0f, 1152.0f };
       frequency = freqtab[version][freqindex];
-      tpf = tpfbs[layer] / (double) frequency;
-      if (version == MPEG_VERSION2_5 || version == MPEG_VERSION2)
-        tpf /= 2;
 
       if (frequency == 0)
         return 0;
 
+      tpf = tpfbs[layer] / (double) frequency;
+      if (version == MPEG_VERSION2_5 || version == MPEG_VERSION2)
+        tpf /= 2;
+
       /* Channel mode (stereo/mono) */
       int chmode = (mpegheader & 0xc0) >> 6;
       /* calculate position of Xing VBR header */
index c08f823..1c33880 100644 (file)
@@ -250,8 +250,19 @@ bool PAPlayer::OpenFile(const CFileItem& file, const CPlayerOptions &options)
     m_isPaused = false; // Make sure to reset the pause state
   }
 
-  if (!QueueNextFileEx(file, false))
-    return false;
+  // if audio engine is suspended i.e. by a DisplayLost event (HDMI), MakeStream
+  // waits until the engine is resumed. if we block the main thread here, it can't
+  // resume the engine after a DisplayReset event
+  if (CAEFactory::IsSuspended())
+  {
+    if (!QueueNextFile(file))
+      return false;
+  }
+  else
+  {
+    if (!QueueNextFileEx(file, false))
+      return false;
+  }
 
   CSharedLock lock(m_streamsLock);
   if (m_streams.size() == 2)
index 9eff89d..570c5eb 100644 (file)
@@ -191,8 +191,8 @@ void CPlayerCoreFactory::GetPlayers( const CFileItem& item, VECPLAYERCORES &vecC
 
     if (bAdd)
     {
-      if ((url.GetFileType().Equals("ac3") && !CAEFactory::SupportsRaw(AE_FMT_AC3))
-            || (url.GetFileType().Equals("dts") && !CAEFactory::SupportsRaw(AE_FMT_DTS)))
+      if ((url.GetFileType().Equals("ac3"))
+            || (url.GetFileType().Equals("dts")))
       {
         CLog::Log(LOGDEBUG, "CPlayerCoreFactory::GetPlayers: adding DVDPlayer (%d)", EPC_DVDPLAYER);
         vecCores.push_back(EPC_DVDPLAYER);
index c186fdf..b85cbf3 100644 (file)
@@ -1484,7 +1484,7 @@ bool MysqlDataset::query(const char *query) {
   size_t loc;
 
   // mysql doesn't understand CAST(foo as integer) => change to CAST(foo as signed integer)
-  if ((loc = ci_find(qry, "as integer)")) != string::npos)
+  while ((loc = ci_find(qry, "as integer)")) != string::npos)
     qry = qry.insert(loc + 3, "signed ");
 
   MYSQL_RES *stmt = NULL;
index c9b1eb8..ed48c90 100644 (file)
@@ -411,21 +411,35 @@ void CGUIEPGGridContainer::ProcessProgrammeGrid(unsigned int currentTime, CDirty
 
       bool focused = (channel == m_channelOffset + m_channelCursor) && (item == m_gridIndex[m_channelOffset + m_channelCursor][m_blockOffset + m_blockCursor].item);
 
-      if (m_orientation == VERTICAL)
-        ProcessItem(posA2, posB, item.get(), m_lastChannel, focused, m_programmeLayout, m_focusedProgrammeLayout, currentTime, dirtyregions, m_gridIndex[channel][block].width);
-      else
-        ProcessItem(posB, posA2, item.get(), m_lastChannel, focused, m_programmeLayout, m_focusedProgrammeLayout, currentTime, dirtyregions, m_gridIndex[channel][block].height);
+      // calculate the size to truncate if item is out of grid view
+      float truncateSize = 0;
+      if (posA2 < posA)
+      {
+        truncateSize = posA - posA2;
+        posA2 = posA; // reset to grid start position
+      }
 
-      // increment our X position
       if (m_orientation == VERTICAL)
       {
+        // truncate item's width
+        m_gridIndex[channel][block].width = m_gridIndex[channel][block].originWidth - truncateSize;
+
+        ProcessItem(posA2, posB, item.get(), m_lastChannel, focused, m_programmeLayout, m_focusedProgrammeLayout, currentTime, dirtyregions, m_gridIndex[channel][block].width);
+
+        // increment our X position
         posA2 += m_gridIndex[channel][block].width; // assumes focused & unfocused layouts have equal length
-        block += (int)(m_gridIndex[channel][block].width / m_blockSize);
+        block += (int)(m_gridIndex[channel][block].originWidth / m_blockSize);
       }
       else
       {
+        // truncate item's height
+        m_gridIndex[channel][block].height = m_gridIndex[channel][block].originHeight - truncateSize;
+
+        ProcessItem(posB, posA2, item.get(), m_lastChannel, focused, m_programmeLayout, m_focusedProgrammeLayout, currentTime, dirtyregions, m_gridIndex[channel][block].height);
+
+        // increment our X position
         posA2 += m_gridIndex[channel][block].height; // assumes focused & unfocused layouts have equal length
-        block += (int)(m_gridIndex[channel][block].height / m_blockSize);
+        block += (int)(m_gridIndex[channel][block].originHeight / m_blockSize);
       }
     }
 
@@ -494,6 +508,10 @@ void CGUIEPGGridContainer::RenderProgrammeGrid()
 
       bool focused = (channel == m_channelOffset + m_channelCursor) && (item == m_gridIndex[m_channelOffset + m_channelCursor][m_blockOffset + m_blockCursor].item);
 
+      // reset to grid start position if first item is out of grid view
+      if (posA2 < posA)
+        posA2 = posA;
+
       // render our item
       if (focused)
       {
@@ -521,12 +539,12 @@ void CGUIEPGGridContainer::RenderProgrammeGrid()
       if (m_orientation == VERTICAL)
       {
         posA2 += m_gridIndex[channel][block].width; // assumes focused & unfocused layouts have equal length
-        block += (int)(m_gridIndex[channel][block].width / m_blockSize);
+        block += (int)(m_gridIndex[channel][block].originWidth / m_blockSize);
       }
       else
       {
         posA2 += m_gridIndex[channel][block].height; // assumes focused & unfocused layouts have equal length
-        block += (int)(m_gridIndex[channel][block].height / m_blockSize);
+        block += (int)(m_gridIndex[channel][block].originHeight / m_blockSize);
       }
     }
 
@@ -596,53 +614,55 @@ void CGUIEPGGridContainer::ProcessItem(float posX, float posY, CGUIListItem* ite
     if (!item->GetFocusedLayout())
     {
       CGUIListItemLayout *layout = new CGUIListItemLayout(*focusedlayout);
-      if (resize != -1.0f)
-      {
-        if (m_orientation == VERTICAL)
-          layout->SetWidth(resize);
-        else
-          layout->SetHeight(resize);
-      }
       item->SetFocusedLayout(layout);
     }
-    if (item->GetFocusedLayout())
+
+    if (resize != -1.0f)
     {
-      if (item != lastitem || !HasFocus())
-      {
-        item->GetFocusedLayout()->SetFocusedItem(0);
-      }
-      if (item != lastitem && HasFocus())
-      {
-        item->GetFocusedLayout()->ResetAnimation(ANIM_TYPE_UNFOCUS);
-        unsigned int subItem = 1;
-        if (lastitem && lastitem->GetFocusedLayout())
-          subItem = lastitem->GetFocusedLayout()->GetFocusedItem();
-        item->GetFocusedLayout()->SetFocusedItem(subItem ? subItem : 1);
-      }
-      item->GetFocusedLayout()->Process(item,m_parentID,currentTime,dirtyregions);
+      if (m_orientation == VERTICAL)
+        item->GetFocusedLayout()->SetWidth(resize);
+      else
+        item->GetFocusedLayout()->SetHeight(resize);
+    }
+
+    if (item != lastitem || !HasFocus())
+      item->GetFocusedLayout()->SetFocusedItem(0);
+
+    if (item != lastitem && HasFocus())
+    {
+      item->GetFocusedLayout()->ResetAnimation(ANIM_TYPE_UNFOCUS);
+      unsigned int subItem = 1;
+      if (lastitem && lastitem->GetFocusedLayout())
+        subItem = lastitem->GetFocusedLayout()->GetFocusedItem();
+      item->GetFocusedLayout()->SetFocusedItem(subItem ? subItem : 1);
     }
+
+    item->GetFocusedLayout()->Process(item, m_parentID, currentTime, dirtyregions);
     lastitem = item;
   }
   else
   {
-    if (item->GetFocusedLayout())
-      item->GetFocusedLayout()->SetFocusedItem(0);  // focus is not set
     if (!item->GetLayout())
     {
       CGUIListItemLayout *layout = new CGUIListItemLayout(*normallayout);
-      if (resize != -1.0f)
-      {
-        if (m_orientation == VERTICAL)
-          layout->SetWidth(resize);
-        else
-          layout->SetHeight(resize);
-      }
       item->SetLayout(layout);
     }
+
+    if (resize != -1.0f)
+    {
+      if (m_orientation == VERTICAL)
+        item->GetLayout()->SetWidth(resize);
+      else
+        item->GetLayout()->SetHeight(resize);
+    }
+
+    if (item->GetFocusedLayout())
+      item->GetFocusedLayout()->SetFocusedItem(0);
+
     if (item->GetFocusedLayout() && item->GetFocusedLayout()->IsAnimating(ANIM_TYPE_UNFOCUS))
-      item->GetFocusedLayout()->Process(item,m_parentID,currentTime,dirtyregions);
-    else if (item->GetLayout())
-      item->GetLayout()->Process(item,m_parentID,currentTime,dirtyregions);
+      item->GetFocusedLayout()->Process(item, m_parentID, currentTime, dirtyregions);
+    else
+      item->GetLayout()->Process(item, m_parentID, currentTime, dirtyregions);
   }
   g_graphicsContext.RestoreOrigin();
 }
@@ -983,15 +1003,18 @@ void CGUIEPGGridContainer::UpdateItems()
 
         if (m_orientation == VERTICAL)
         {
-          m_gridIndex[row][savedBlock].width   = itemSize*m_blockSize;
-          m_gridIndex[row][savedBlock].height  = m_channelHeight;
+          m_gridIndex[row][savedBlock].originWidth = itemSize*m_blockSize;
+          m_gridIndex[row][savedBlock].originHeight = m_channelHeight;
         }
         else
         {
-          m_gridIndex[row][savedBlock].width   = m_channelWidth;
-          m_gridIndex[row][savedBlock].height  = itemSize*m_blockSize;
+          m_gridIndex[row][savedBlock].originWidth = m_channelWidth;
+          m_gridIndex[row][savedBlock].originHeight = itemSize*m_blockSize;
         }
 
+        m_gridIndex[row][savedBlock].width = m_gridIndex[row][savedBlock].originWidth;
+        m_gridIndex[row][savedBlock].height = m_gridIndex[row][savedBlock].originHeight;
+
         itemSize = 1;
         savedBlock = block+1;
       }
index 0322790..205dc52 100644 (file)
@@ -39,6 +39,8 @@ namespace EPG
   struct GridItemsPtr
   {
     CGUIListItemPtr item;
+    float originWidth;
+    float originHeight;
     float width;
     float height;
   };
index 58a0d55..fc5ab16 100644 (file)
@@ -27,6 +27,7 @@ public:
   virtual ~IDispResource() {};
   virtual void OnLostDevice() {};
   virtual void OnResetDevice() {};
+  virtual void OnAppFocusChange(bool focus) {};
 };
 
 #endif
index 0599cce..c574360 100644 (file)
@@ -118,16 +118,16 @@ void CGUIListGroup::UpdateInfo(const CGUIListItem *item)
 
 void CGUIListGroup::EnlargeWidth(float difference)
 {
-  // Alters the width of the controls that have an ID of 1
+  // Alters the width of the controls that have an ID of 1 to 14
   for (iControls it = m_children.begin(); it != m_children.end(); it++)
   {
     CGUIControl *child = *it;
     if (child->GetID() >= 1 && child->GetID() <= 14)
     {
-      if (child->GetID() == 1) // label
+      if (child->GetID() == 1)
       {
-        child->SetWidth(child->GetWidth() + difference - 10);
-        child->SetVisible(child->GetWidth() > 10); ///
+        child->SetWidth(child->GetWidth() + difference);
+        child->SetVisible(child->GetWidth() > 10);
       }
       else
       {
@@ -140,16 +140,16 @@ void CGUIListGroup::EnlargeWidth(float difference)
 
 void CGUIListGroup::EnlargeHeight(float difference)
 {
-  // Alters the width of the controls that have an ID of 1
+  // Alters the height of the controls that have an ID of 1 to 14
   for (iControls it = m_children.begin(); it != m_children.end(); it++)
   {
     CGUIControl *child = *it;
     if (child->GetID() >= 1 && child->GetID() <= 14)
     {
-      if (child->GetID() == 1) // label
+      if (child->GetID() == 1)
       {
         child->SetHeight(child->GetHeight() + difference);
-        child->SetVisible(child->GetHeight() > 10); ///
+        child->SetVisible(child->GetHeight() > 10);
       }
       else
       {
index e63a99d..f9f594f 100644 (file)
@@ -111,7 +111,7 @@ void CGUIListLabel::SetWidth(float width)
   else if (m_label.GetLabelInfo().align & XBFONT_CENTER_X)
     m_label.SetMaxRect(m_posX - m_width*0.5f, m_posY, m_width, m_height);
   else
-    m_label.SetMaxRect(m_posX, m_posY, m_posX + m_width, m_posY + m_height);
+    m_label.SetMaxRect(m_posX, m_posY, m_width, m_height);
   CGUIControl::SetWidth(m_width);
 }
 
index 4d8d74c..6214d1d 100644 (file)
@@ -465,7 +465,7 @@ JSONRPC_STATUS CAudioLibrary::SetAlbumDetails(const CStdString &method, ITranspo
   if (ParameterNotNull(parameterObject, "year"))
     album.iYear = (int)parameterObject["year"].asInteger();
 
-  if (musicdatabase.UpdateAlbum(album) <= 0)
+  if (!musicdatabase.UpdateAlbum(album))
     return InternalError;
 
   CJSONRPCUtils::NotifyItemUpdated();
index 836da56..cd2c6f3 100644 (file)
@@ -22,7 +22,7 @@
 namespace JSONRPC
 {
   const char* const JSONRPC_SERVICE_ID          = "http://xbmc.org/jsonrpc/ServiceDescription.json";
-  const char* const JSONRPC_SERVICE_VERSION     = "6.14.0";
+  const char* const JSONRPC_SERVICE_VERSION     = "6.14.1";
   const char* const JSONRPC_SERVICE_DESCRIPTION = "JSON-RPC API of XBMC";
 
   const char* const JSONRPC_SERVICE_TYPES[] = {  
@@ -1644,8 +1644,8 @@ namespace JSONRPC
         "\"elementtype\": { \"$ref\": \"Setting.Type\", \"required\": true },"
         "\"definition\": { \"$ref\": \"Setting.Details.Setting\", \"required\": true },"
         "\"delimiter\": { \"type\": \"string\", \"required\": true },"
-        "\"minimum\": { \"type\": \"integer\" },"
-        "\"maximum\": { \"type\": \"integer\" }"
+        "\"minimumItems\": { \"type\": \"integer\" },"
+        "\"maximumItems\": { \"type\": \"integer\" }"
       "},"
       "\"additionalProperties\": false"
     "}",
index 86a21e6..c564ba6 100644 (file)
@@ -593,8 +593,8 @@ bool CSettingsOperations::SerializeSettingList(const CSettingList* setting, CVar
 
   obj["elementtype"] = obj["definition"]["type"];
   obj["delimiter"] = setting->GetDelimiter();
-  obj["minimum"] = setting->GetMinimum();
-  obj["maximum"] = setting->GetMaximum();
+  obj["minimumItems"] = setting->GetMinimumItems();
+  obj["maximumItems"] = setting->GetMaximumItems();
 
   return true;
 }
index a6b3f9b..c65b258 100644 (file)
       "elementtype": { "$ref": "Setting.Type", "required": true },
       "definition": { "$ref": "Setting.Details.Setting", "required": true },
       "delimiter": { "type": "string", "required": true },
-      "minimum": { "type": "integer" },
-      "maximum": { "type": "integer" }
+      "minimumItems": { "type": "integer" },
+      "maximumItems": { "type": "integer" }
     },
     "additionalProperties": false
   },
index fd8eaa2..8456c89 100644 (file)
@@ -437,7 +437,7 @@ namespace XBMCAddon
     {
       XBMC_TRACE;
 
-      if (dlg)
+      if (dlg && open)
       {
         DelayedCallGuard dg;
         dlg->Close();
@@ -457,6 +457,7 @@ namespace XBMCAddon
 
       dlg = pDialog;
       handle = pHandle;
+      open = true;
 
       pHandle->SetTitle(heading);
       if (!message.empty())
@@ -484,6 +485,7 @@ namespace XBMCAddon
     {
       DelayedCallGuard dcguard(languageHook);
       handle->MarkFinished();
+      open = false;
     }
 
     bool DialogProgressBG::isFinished()
index af63323..4b41e68 100644 (file)
@@ -361,13 +361,14 @@ namespace XBMCAddon
     {
       CGUIDialogExtendedProgressBar* dlg;
       CGUIDialogProgressBarHandle* handle;
+      bool open;
 
     protected:
       virtual void deallocating();
 
     public:
 
-      DialogProgressBG() : dlg(NULL), handle(NULL) {}
+      DialogProgressBG() : dlg(NULL), handle(NULL), open(false) {}
       virtual ~DialogProgressBG();
 
 
index da8dceb..1fb644b 100644 (file)
@@ -249,6 +249,7 @@ namespace XBMCAddon
     void WindowXML::clearList()
     {
       XBMC_TRACE;
+      LOCKGUI;
       A(ClearFileItems());
 
       A(m_viewControl).SetItems(*(A(m_vecItems)));
index 832611c..12bb50c 100644 (file)
@@ -129,7 +129,6 @@ namespace XBMCAddon
     String PythonLanguageHook::GetAddonId()
     {
       XBMC_TRACE;
-      const char* id = NULL;
 
       // Get a reference to the main module
       // and global dictionary
@@ -138,8 +137,9 @@ namespace XBMCAddon
       // Extract a reference to the function "func_name"
       // from the global dictionary
       PyObject* pyid = PyDict_GetItemString(global_dict, "__xbmcaddonid__");
-      id = PyString_AsString(pyid);
-      return id;
+      if (pyid)
+        return PyString_AsString(pyid);
+      return "";
     }
 
     String PythonLanguageHook::GetAddonVersion()
@@ -152,8 +152,9 @@ namespace XBMCAddon
       // Extract a reference to the function "func_name"
       // from the global dictionary
       PyObject* pyversion = PyDict_GetItemString(global_dict, "__xbmcapiversion__");
-      String version(PyString_AsString(pyversion));
-      return version;
+      if (pyversion)
+        return PyString_AsString(pyversion);
+      return "";
     }
 
     void PythonLanguageHook::RegisterPlayerCallback(IPlayerCallback* player) { XBMC_TRACE; g_pythonParser.RegisterPythonPlayerCallBack(player); }
index 0368bb6..98032f2 100644 (file)
@@ -990,13 +990,17 @@ INFO_RET CMusicInfoScanner::DownloadAlbumInfo(const CAlbum& album, const ADDON::
   }
 
   // handle nfo files
-  CStdString strNfo = URIUtils::AddFileToFolder(album.strPath, "album.nfo");
+  CStdString path = album.strPath;
+  if (path.empty())
+    m_musicDatabase.GetAlbumPath(album.idAlbum, path);
+
+  CStdString strNfo = URIUtils::AddFileToFolder(path, "album.nfo");
   CNfoFile::NFOResult result = CNfoFile::NO_NFO;
   CNfoFile nfoReader;
   if (XFILE::CFile::Exists(strNfo))
   {
     CLog::Log(LOGDEBUG,"Found matching nfo file: %s", strNfo.c_str());
-    result = nfoReader.Create(strNfo, info, -1, album.strPath);
+    result = nfoReader.Create(strNfo, info);
     if (result == CNfoFile::FULL_NFO)
     {
       CLog::Log(LOGDEBUG, "%s Got details from nfo", __FUNCTION__);
@@ -1202,7 +1206,11 @@ INFO_RET CMusicInfoScanner::DownloadArtistInfo(const CArtist& artist, const ADDO
   }
 
   // handle nfo files
-  CStdString strNfo = URIUtils::AddFileToFolder(artist.strPath, "artist.nfo");
+  CStdString path = artist.strPath;
+  if (path.empty())
+    m_musicDatabase.GetArtistPath(artist.idArtist, path);
+
+  CStdString strNfo = URIUtils::AddFileToFolder(path, "artist.nfo");
   CNfoFile::NFOResult result=CNfoFile::NO_NFO;
   CNfoFile nfoReader;
   if (XFILE::CFile::Exists(strNfo))
index bd03676..c2d0793 100644 (file)
@@ -55,6 +55,20 @@ bool EmbeddedArtInfo::matches(const EmbeddedArtInfo &right) const
           mime == right.mime);
 }
 
+void EmbeddedArtInfo::Archive(CArchive &ar)
+{
+  if (ar.IsStoring())
+  {
+    ar << size;
+    ar << mime;
+  }
+  else
+  {
+    ar >> size;
+    ar >> mime;
+  }
+}
+
 EmbeddedArt::EmbeddedArt(const uint8_t *dat, size_t siz, const std::string &mim)
 {
   set(dat, siz, mim);
@@ -543,6 +557,7 @@ void CMusicInfoTag::SetSong(const CSong& song)
   SetComment(song.strComment);
   SetPlayCount(song.iTimesPlayed);
   SetLastPlayed(song.lastPlayed);
+  SetCoverArtInfo(song.embeddedArt.size, song.embeddedArt.mime);
   m_rating = song.rating;
   m_strURL = song.strFileName;
   SYSTEMTIME stTime;
@@ -646,6 +661,7 @@ void CMusicInfoTag::Archive(CArchive& ar)
     ar << m_strLyrics;
     ar << m_bCompilation;
     ar << m_listeners;
+    ar << m_coverArt;
   }
   else
   {
@@ -674,6 +690,7 @@ void CMusicInfoTag::Archive(CArchive& ar)
     ar >> m_strLyrics;
     ar >> m_bCompilation;
     ar >> m_listeners;
+    ar >> m_coverArt;
   }
 }
 
index 0b76d22..48fdb8e 100644 (file)
@@ -46,7 +46,7 @@ enum ReplayGain
 
 namespace MUSIC_INFO
 {
-  class EmbeddedArtInfo
+  class EmbeddedArtInfo : public IArchivable
   {
   public:
     EmbeddedArtInfo() {};
@@ -55,6 +55,7 @@ namespace MUSIC_INFO
     void clear();
     bool empty() const;
     bool matches(const EmbeddedArtInfo &right) const;
+    virtual void Archive(CArchive& ar);
     size_t      size;
     std::string mime;
   };
index f5261b7..8b1b767 100644 (file)
@@ -373,6 +373,7 @@ void CGUIWindowMusicBase::ShowArtistInfo(const CFileItem *pItem, bool bShowInfo
   if (!m_musicdatabase.GetArtist(params.GetArtistId(), artist))
       return;
 
+  m_musicdatabase.GetArtistPath(params.GetArtistId(), artist.strPath);
   while (1)
   {
     // Check if we have the information in the database first
@@ -411,9 +412,7 @@ void CGUIWindowMusicBase::ShowArtistInfo(const CFileItem *pItem, bool bShowInfo
     CGUIDialogMusicInfo *pDlgArtistInfo = (CGUIDialogMusicInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_INFO);
     if (pDlgArtistInfo)
     {
-      CStdString strPath;
-      m_musicdatabase.GetArtistPath(params.GetArtistId(), strPath);
-      pDlgArtistInfo->SetArtist(artist, strPath);
+      pDlgArtistInfo->SetArtist(artist, artist.strPath);
       pDlgArtistInfo->DoModal();
 
       if (pDlgArtistInfo->NeedRefresh())
@@ -445,6 +444,7 @@ bool CGUIWindowMusicBase::ShowAlbumInfo(const CFileItem *pItem, bool bShowInfo /
   if (!m_musicdatabase.GetAlbum(params.GetAlbumId(), album))
     return false;
 
+  m_musicdatabase.GetAlbumPath(params.GetAlbumId(), album.strPath);
   while (1)
   {
     if (!m_musicdatabase.HasAlbumBeenScraped(params.GetAlbumId()))
@@ -491,9 +491,7 @@ bool CGUIWindowMusicBase::ShowAlbumInfo(const CFileItem *pItem, bool bShowInfo /
     CGUIDialogMusicInfo *pDlgAlbumInfo = (CGUIDialogMusicInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_INFO);
     if (pDlgAlbumInfo)
     {
-      CStdString strPath;
-      m_musicdatabase.GetAlbumPath(params.GetAlbumId(), strPath);
-      pDlgAlbumInfo->SetAlbum(album, strPath);
+      pDlgAlbumInfo->SetAlbum(album, album.strPath);
       pDlgAlbumInfo->DoModal();
 
       if (pDlgAlbumInfo->NeedRefresh())
@@ -503,7 +501,7 @@ bool CGUIWindowMusicBase::ShowAlbumInfo(const CFileItem *pItem, bool bShowInfo /
       }
       else if (pDlgAlbumInfo->HasUpdatedThumb())
       {
-        UpdateThumb(album, strPath);
+        UpdateThumb(album, album.strPath);
       }
     }
     break;
index 35cb660..cffb691 100644 (file)
@@ -337,7 +337,7 @@ const CStdString CPictureInfoTag::GetInfo(int info) const
       // Archived data is already converted (EXIF_COMMENT_CHARSET_CONVERTED)
       // Unknown data can't be converted as it could be any codec (EXIF_COMMENT_CHARSET_UNKNOWN)
       // JIS data can't be converted as CharsetConverter and iconv lacks support (EXIF_COMMENT_CHARSET_JIS)
-      value = m_exifInfo.Comments;
+      g_charsetConverter.unknownToUTF8(m_exifInfo.Comments, value);
     }
     break;
   case SLIDE_EXIF_LONG_DATE_TIME:
index 9495064..7859d16 100644 (file)
@@ -224,16 +224,6 @@ void CPVRRecordings::GetSubDirectories(const CStdString &strBase, CFileItemList
     }
     results->AddFront(pItem, 0);
   }
-
-  // Add parent directory item
-  if (!strUseBase.empty() && (subDirectories > 0 || files.Size() > 0) && CSettings::Get().GetBool("filelists.showparentdiritems"))
-  {
-    CStdString strLabel("..");
-    CFileItemPtr pItem(new CFileItem(strLabel));
-    pItem->SetPath("pvr://recordings");
-    pItem->m_bIsShareOrDrive = false;
-    results->AddFront(pItem, 0);
-  }
 }
 
 bool CPVRRecordings::HasAllRecordingsPathExtension(const CStdString &strDirectory)
index 4ffca74..8fed994 100644 (file)
@@ -65,3 +65,8 @@ void CGUIViewStatePVR::SaveViewState(void)
   PVRWindow ActiveView = GetActiveView();
   SaveViewToDb(m_items.GetPath(), ActiveView == PVR_WINDOW_UNKNOWN ? WINDOW_PVR : WINDOW_PVR + 100 - ActiveView, NULL);
 }
+
+bool CGUIViewStatePVR::HideParentDirItems(void)
+{
+  return (CGUIViewState::HideParentDirItems() || PVR_WINDOW_RECORDINGS != GetActiveView() || m_items.GetPath() == "pvr://recordings/");
+}
index 8b09b7b..04060ef 100644 (file)
@@ -33,7 +33,7 @@ namespace PVR
     PVRWindow GetActiveView(void);
   protected:
     bool AutoPlayNextItem(void) { return false; };
-    bool HideParentDirItems(void) { return true; }
+    bool HideParentDirItems(void);
     void SaveViewState(void);
   };
 }
index 1c7a697..feb3900 100644 (file)
@@ -402,6 +402,9 @@ bool CGUIWindowPVRRecordings::OnContextButtonMarkWatched(const CFileItemPtr &ite
 
 void CGUIWindowPVRRecordings::BeforeUpdate(const CStdString &strDirectory)
 {
+  // set items path to current directory
+  m_parent->m_vecItems->SetPath(strDirectory);
+
   if (m_thumbLoader.IsLoading())
     m_thumbLoader.StopThread();
 }
index 2963a6f..b27dcdd 100644 (file)
@@ -251,14 +251,14 @@ CSettingList::CSettingList(const std::string &id, CSetting *settingDefinition, C
   : CSetting(id, settingsManager),
     m_definition(settingDefinition),
     m_delimiter("|"),
-    m_minimum(0), m_maximum(-1)
+    m_minimumItems(0), m_maximumItems(-1)
 { }
 
 CSettingList::CSettingList(const std::string &id, const CSettingList &setting)
   : CSetting(id, setting),
     m_definition(NULL),
     m_delimiter("|"),
-    m_minimum(0), m_maximum(-1)
+    m_minimumItems(0), m_maximumItems(-1)
 {
   copy(setting);
 }
@@ -306,15 +306,15 @@ bool CSettingList::Deserialize(const TiXmlNode *node, bool update /* = false */)
     if (XMLUtils::GetString(constraints, SETTING_XML_ELM_DELIMITER, delimiter) && !delimiter.empty())
       m_delimiter = delimiter;
 
-    XMLUtils::GetInt(constraints, SETTING_XML_ELM_MINIMUM, m_minimum);
-    if (m_minimum < 0)
-      m_minimum = 0;
-    XMLUtils::GetInt(constraints, SETTING_XML_ELM_MAXIMUM, m_maximum);
-    if (m_maximum <= 0)
-      m_maximum = -1;
-    else if (m_maximum < m_minimum)
+    XMLUtils::GetInt(constraints, SETTING_XML_ELM_MINIMUM_ITEMS, m_minimumItems);
+    if (m_minimumItems < 0)
+      m_minimumItems = 0;
+    XMLUtils::GetInt(constraints, SETTING_XML_ELM_MAXIMUM_ITEMS, m_maximumItems);
+    if (m_maximumItems <= 0)
+      m_maximumItems = -1;
+    else if (m_maximumItems < m_minimumItems)
     {
-      CLog::Log(LOGWARNING, "CSettingList: invalid <minimum> (%d) and/or <maximum> (%d) of %s", m_minimum, m_maximum, m_id.c_str());
+      CLog::Log(LOGWARNING, "CSettingList: invalid <minimum> (%d) and/or <maximum> (%d) of %s", m_minimumItems, m_maximumItems, m_id.c_str());
       return false;
     }
   }
@@ -407,8 +407,8 @@ bool CSettingList::SetValue(const SettingPtrList &values)
 {
   CExclusiveLock lock(m_critical);
 
-  if ((int)values.size() < m_minimum ||
-     (m_maximum > 0 && (int)values.size() > m_maximum))
+  if ((int)values.size() < m_minimumItems ||
+     (m_maximumItems > 0 && (int)values.size() > m_maximumItems))
     return false;
 
   bool equal = values.size() == m_values.size();
@@ -476,8 +476,8 @@ void CSettingList::copy(const CSettingList &setting)
   }
 
   m_delimiter = setting.m_delimiter;
-  m_minimum = setting.m_minimum;
-  m_maximum = setting.m_maximum;
+  m_minimumItems = setting.m_minimumItems;
+  m_maximumItems = setting.m_maximumItems;
 }
 
 void CSettingList::copy(const SettingPtrList &srcValues, SettingPtrList &dstValues)
@@ -505,8 +505,8 @@ bool CSettingList::fromString(const std::string &strValue, SettingPtrList &value
 
 bool CSettingList::fromValues(const std::vector<std::string> &strValues, SettingPtrList &values) const
 {
-  if ((int)strValues.size() < m_minimum ||
-     (m_maximum > 0 && (int)strValues.size() > m_maximum))
+  if ((int)strValues.size() < m_minimumItems ||
+     (m_maximumItems > 0 && (int)strValues.size() > m_maximumItems))
     return false;
 
   bool ret = true;
index a3adcc1..b39bb62 100644 (file)
@@ -166,8 +166,8 @@ public:
   const CSetting* GetDefinition() const { return m_definition; }
 
   const std::string& GetDelimiter() const { return m_delimiter; }
-  int GetMinimum() const { return m_minimum; }
-  int GetMaximum() const { return m_maximum; }
+  int GetMinimumItems() const { return m_minimumItems; }
+  int GetMaximumItems() const { return m_maximumItems; }
   
   bool FromString(const std::vector<std::string> &value);
 
@@ -187,8 +187,8 @@ protected:
   SettingPtrList m_defaults;
   CSetting *m_definition;
   std::string m_delimiter;
-  int m_minimum;
-  int m_maximum;
+  int m_minimumItems;
+  int m_maximumItems;
 };
 
 /*!
index 381d0fa..1722451 100644 (file)
@@ -45,6 +45,8 @@
 #define SETTING_XML_ELM_UPDATE        "update"
 #define SETTING_XML_ELM_ACCESS        "access"
 #define SETTING_XML_ELM_DELIMITER     "delimiter"
+#define SETTING_XML_ELM_MINIMUM_ITEMS "minimumitems"
+#define SETTING_XML_ELM_MAXIMUM_ITEMS "maximumitems"
 
 #define SETTING_XML_ATTR_ID           "id"
 #define SETTING_XML_ATTR_LABEL        "label"
index ea4ff97..fd2eb5a 100644 (file)
@@ -1224,12 +1224,13 @@ std::string URIUtils::resolvePath(const std::string &path)
   }
 
   CStdString realPath;
-  int i = 0;
   // re-add any / or \ at the beginning
-  while (path.at(i) == delim.at(0))
+  for (std::string::const_iterator itPath = path.begin(); itPath != path.end(); ++itPath)
   {
+    if (*itPath != delim.at(0))
+      break;
+
     realPath += delim;
-    i++;
   }
   // put together the path
   realPath += StringUtils::Join(realParts, delim);
index 04da6f0..7291eca 100644 (file)
@@ -473,6 +473,9 @@ bool CVideoThumbLoader::FillThumb(CFileItem &item)
 
 std::string CVideoThumbLoader::GetLocalArt(const CFileItem &item, const std::string &type, bool checkFolder)
 {
+  if (item.SkipLocalArt())
+    return "";
+
   /* Cache directory for (sub) folders on streamed filesystems. We need to do this
      else entering (new) directories from the app thread becomes much slower. This
      is caused by the fact that Curl Stat/Exist() is really slow and that the 
index 4391de3..55358ad 100644 (file)
@@ -358,8 +358,8 @@ RECT CWinSystemWin32::ScreenRect(int screen)
   const MONITOR_DETAILS &details = GetMonitor(screen);
 
   DEVMODEW sDevMode;
-  ZeroMemory(&sDevMode, sizeof(DEVMODE));
-  sDevMode.dmSize = sizeof(DEVMODE);
+  ZeroMemory(&sDevMode, sizeof(sDevMode));
+  sDevMode.dmSize = sizeof(sDevMode);
   if(!EnumDisplaySettingsW(details.DeviceNameW.c_str(), ENUM_CURRENT_SETTINGS, &sDevMode))
     CLog::Log(LOGERROR, "%s : EnumDisplaySettings failed with %d", __FUNCTION__, GetLastError());
 
@@ -445,8 +445,8 @@ bool CWinSystemWin32::ChangeResolution(RESOLUTION_INFO res)
   const MONITOR_DETAILS &details = GetMonitor(res.iScreen);
 
   DEVMODEW sDevMode;
-  ZeroMemory(&sDevMode, sizeof(DEVMODE));
-  sDevMode.dmSize = sizeof(DEVMODE);
+  ZeroMemory(&sDevMode, sizeof(sDevMode));
+  sDevMode.dmSize = sizeof(sDevMode);
 
   // If we can't read the current resolution or any detail of the resolution is different than res
   if (!EnumDisplaySettingsW(details.DeviceNameW.c_str(), ENUM_CURRENT_SETTINGS, &sDevMode) ||
@@ -455,8 +455,8 @@ bool CWinSystemWin32::ChangeResolution(RESOLUTION_INFO res)
       ((sDevMode.dmDisplayFlags & DM_INTERLACED) && !(res.dwFlags & D3DPRESENTFLAG_INTERLACED)) ||
       (!(sDevMode.dmDisplayFlags & DM_INTERLACED) && (res.dwFlags & D3DPRESENTFLAG_INTERLACED)) )
   {
-    ZeroMemory(&sDevMode, sizeof(DEVMODE));
-    sDevMode.dmSize = sizeof(DEVMODE);
+    ZeroMemory(&sDevMode, sizeof(sDevMode));
+    sDevMode.dmSize = sizeof(sDevMode);
     sDevMode.dmDriverExtra = 0;
     sDevMode.dmPelsWidth = res.iWidth;
     sDevMode.dmPelsHeight = res.iHeight;