aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--addons/skin.confluence/720p/ViewsFileMode.xml56
-rw-r--r--addons/skin.confluence/720p/ViewsVideoLibrary.xml16
-rw-r--r--addons/skin.confluence/720p/includes.xml62
-rw-r--r--addons/skin.confluence/media/flagging/video/Set.pngbin0 -> 3109 bytes
-rw-r--r--project/BuildDependencies/scripts/0_package.list2
-rw-r--r--project/cmake/addons/addons/pvr.iptvsimple/pvr.iptvsimple.txt2
-rw-r--r--system/settings/settings.xml2
-rw-r--r--tools/depends/target/libass/Makefile8
-rw-r--r--xbmc/GUIInfoManager.cpp6
-rw-r--r--xbmc/GUIInfoManager.h1
-rw-r--r--xbmc/GUILargeTextureManager.cpp35
-rw-r--r--xbmc/TextureCache.cpp20
-rw-r--r--xbmc/TextureCache.h2
-rw-r--r--xbmc/cores/VideoRenderers/BaseRenderer.cpp7
-rw-r--r--xbmc/cores/VideoRenderers/BaseRenderer.h9
-rw-r--r--xbmc/cores/VideoRenderers/OverlayRenderer.cpp58
-rw-r--r--xbmc/cores/VideoRenderers/RenderManager.cpp4
-rw-r--r--xbmc/cores/VideoRenderers/RenderManager.h2
-rw-r--r--xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayCodecFFmpeg.cpp1
-rw-r--r--xbmc/cores/dvdplayer/DVDOverlayRenderer.cpp2
-rw-r--r--xbmc/cores/dvdplayer/DVDPlayer.cpp7
-rw-r--r--xbmc/cores/dvdplayer/DVDPlayerVideo.h2
-rw-r--r--xbmc/cores/dvdplayer/DVDSubtitles/DVDSubtitlesLibass.cpp11
-rw-r--r--xbmc/cores/dvdplayer/DVDSubtitles/DVDSubtitlesLibass.h2
-rw-r--r--xbmc/cores/dvdplayer/DVDSubtitles/DllLibass.h3
-rw-r--r--xbmc/cores/dvdplayer/IDVDPlayer.h2
-rw-r--r--xbmc/cores/omxplayer/OMXPlayerVideo.h2
-rw-r--r--xbmc/input/linux/LIRC.cpp56
-rw-r--r--xbmc/input/linux/LIRC.h12
-rw-r--r--xbmc/interfaces/json-rpc/PlayerOperations.cpp31
-rw-r--r--xbmc/network/NetworkServices.cpp57
-rw-r--r--xbmc/network/NetworkServices.h3
-rw-r--r--xbmc/network/upnp/UPnP.cpp82
-rw-r--r--xbmc/network/upnp/UPnP.h8
-rw-r--r--xbmc/pvr/dialogs/GUIDialogPVRChannelManager.cpp6
35 files changed, 348 insertions, 231 deletions
diff --git a/addons/skin.confluence/720p/ViewsFileMode.xml b/addons/skin.confluence/720p/ViewsFileMode.xml
index 53bda87853..bc93810d14 100644
--- a/addons/skin.confluence/720p/ViewsFileMode.xml
+++ b/addons/skin.confluence/720p/ViewsFileMode.xml
@@ -68,19 +68,9 @@
<top>8</top>
<width>40</width>
<height>26</height>
- <texture>$INFO[ListItem.VideoResolution,flagging/lists/,.png]</texture>
+ <texture>$VAR[MediaInfoOverlayVar]</texture>
<aspectratio>keep</aspectratio>
- <visible>Window.IsVisible(Videos) + [Container.Content(Movies) | Container.Content(Episodes) | Container.Content(MusicVideos)]</visible>
- <visible>!ListItem.IsStereoscopic</visible>
- </control>
- <control type="image">
- <left>625</left>
- <top>8</top>
- <width>40</width>
- <height>26</height>
- <texture>flagging/lists/3D.png</texture>
- <visible>Window.IsVisible(Videos) + [Container.Content(Movies) | Container.Content(Episodes) | Container.Content(MusicVideos)]</visible>
- <visible>ListItem.IsStereoscopic</visible>
+ <visible>Window.IsVisible(Videos) + [Container.Content(Movies) | Container.Content(Sets) | Container.Content(Episodes) | Container.Content(MusicVideos)]</visible>
</control>
<control type="image">
<left>665</left>
@@ -171,19 +161,9 @@
<top>8</top>
<width>40</width>
<height>26</height>
- <texture>$INFO[ListItem.VideoResolution,flagging/lists/,.png]</texture>
+ <texture>$VAR[MediaInfoOverlayVar]</texture>
<aspectratio>keep</aspectratio>
- <visible>Window.IsVisible(Videos) + [Container.Content(Movies) | Container.Content(Episodes) | Container.Content(MusicVideos)]</visible>
- <visible>!ListItem.IsStereoscopic</visible>
- </control>
- <control type="image">
- <left>625</left>
- <top>8</top>
- <width>40</width>
- <height>26</height>
- <texture>flagging/lists/3D.png</texture>
- <visible>Window.IsVisible(Videos) + [Container.Content(Movies) | Container.Content(Episodes) | Container.Content(MusicVideos)]</visible>
- <visible>ListItem.IsStereoscopic</visible>
+ <visible>Window.IsVisible(Videos) + [Container.Content(Movies) | Container.Content(Sets) | Container.Content(Episodes) | Container.Content(MusicVideos)]</visible>
</control>
<control type="image">
<left>665</left>
@@ -588,19 +568,9 @@
<top>8</top>
<width>40</width>
<height>26</height>
- <texture>$INFO[ListItem.VideoResolution,flagging/lists/,.png]</texture>
+ <texture>$VAR[MediaInfoOverlayVar]</texture>
<aspectratio>keep</aspectratio>
- <visible>Window.IsVisible(Videos) + [Container.Content(Movies) | Container.Content(Episodes) | Container.Content(MusicVideos)]</visible>
- <visible>!ListItem.IsStereoscopic</visible>
- </control>
- <control type="image">
- <left>1010</left>
- <top>8</top>
- <width>40</width>
- <height>26</height>
- <texture>flagging/lists/3D.png</texture>
- <visible>Window.IsVisible(Videos) + [Container.Content(Movies) | Container.Content(Episodes) | Container.Content(MusicVideos)]</visible>
- <visible>ListItem.IsStereoscopic</visible>
+ <visible>Window.IsVisible(Videos) + [Container.Content(Movies) | Container.Content(Sets) | Container.Content(Episodes) | Container.Content(MusicVideos)]</visible>
</control>
<control type="image">
<left>1050</left>
@@ -699,19 +669,9 @@
<top>8</top>
<width>40</width>
<height>26</height>
- <texture>$INFO[ListItem.VideoResolution,flagging/lists/,.png]</texture>
+ <texture>$VAR[MediaInfoOverlayVar]</texture>
<aspectratio>keep</aspectratio>
- <visible>Window.IsVisible(Videos) + [Container.Content(Movies) | Container.Content(Episodes) | Container.Content(MusicVideos)]</visible>
- <visible>!ListItem.IsStereoscopic</visible>
- </control>
- <control type="image">
- <left>1010</left>
- <top>8</top>
- <width>40</width>
- <height>26</height>
- <texture>flagging/lists/3D.png</texture>
- <visible>Window.IsVisible(Videos) + [Container.Content(Movies) | Container.Content(Episodes) | Container.Content(MusicVideos)]</visible>
- <visible>ListItem.IsStereoscopic</visible>
+ <visible>Window.IsVisible(Videos) + [Container.Content(Movies) | Container.Content(Sets) | Container.Content(Episodes) | Container.Content(MusicVideos)]</visible>
</control>
<control type="image">
<left>1050</left>
diff --git a/addons/skin.confluence/720p/ViewsVideoLibrary.xml b/addons/skin.confluence/720p/ViewsVideoLibrary.xml
index 3b173be113..eba09863b2 100644
--- a/addons/skin.confluence/720p/ViewsVideoLibrary.xml
+++ b/addons/skin.confluence/720p/ViewsVideoLibrary.xml
@@ -811,9 +811,9 @@
<top>8</top>
<width>40</width>
<height>26</height>
- <texture>$VAR[ResolutionOverlayVar]</texture>
+ <texture>$VAR[MediaInfoOverlayVar]</texture>
<aspectratio>keep</aspectratio>
- <visible>Container.Content(Movies) | Container.Content(Episodes) | Container.Content(MusicVideos)</visible>
+ <visible>Container.Content(Movies) | Container.Content(Sets) | Container.Content(Episodes) | Container.Content(MusicVideos)</visible>
</control>
<control type="image">
<left>555</left>
@@ -882,9 +882,9 @@
<top>8</top>
<width>40</width>
<height>26</height>
- <texture>$VAR[ResolutionOverlayVar]</texture>
+ <texture>$VAR[MediaInfoOverlayVar]</texture>
<aspectratio>keep</aspectratio>
- <visible>Container.Content(Movies) | Container.Content(Episodes) | Container.Content(MusicVideos)</visible>
+ <visible>Container.Content(Movies) | Container.Content(Sets) | Container.Content(Episodes) | Container.Content(MusicVideos)</visible>
</control>
<control type="image">
<left>555</left>
@@ -1227,9 +1227,9 @@
<top>8</top>
<width>40</width>
<height>26</height>
- <texture>$VAR[ResolutionOverlayVar]</texture>
+ <texture>$VAR[MediaInfoOverlayVar]</texture>
<aspectratio>keep</aspectratio>
- <visible>Container.Content(Movies) | Container.Content(Episodes) | Container.Content(MusicVideos)</visible>
+ <visible>Container.Content(Movies) | Container.Content(Sets) | Container.Content(Episodes) | Container.Content(MusicVideos)</visible>
</control>
<control type="image">
<left>555</left>
@@ -1298,9 +1298,9 @@
<top>8</top>
<width>40</width>
<height>26</height>
- <texture>$VAR[ResolutionOverlayVar]</texture>
+ <texture>$VAR[MediaInfoOverlayVar]</texture>
<aspectratio>keep</aspectratio>
- <visible>Container.Content(Movies) | Container.Content(Episodes) | Container.Content(MusicVideos)</visible>
+ <visible>Container.Content(Movies) | Container.Content(Sets) | Container.Content(Episodes) | Container.Content(MusicVideos)</visible>
</control>
<control type="image">
<left>555</left>
diff --git a/addons/skin.confluence/720p/includes.xml b/addons/skin.confluence/720p/includes.xml
index 902fa4da24..c9e8a045dd 100644
--- a/addons/skin.confluence/720p/includes.xml
+++ b/addons/skin.confluence/720p/includes.xml
@@ -16,7 +16,8 @@
<include file="IncludesBackgroundBuilding.xml" />
<constant name="FanartCrossfadeTime">500</constant>
<constant name="IconCrossfadeTime">400</constant>
- <variable name="ResolutionOverlayVar">
+ <variable name="MediaInfoOverlayVar">
+ <value condition="ListItem.IsCollection">flagging/video/Set.png</value>
<value condition="!ListItem.IsStereoscopic">$INFO[ListItem.VideoResolution,flagging/lists/,.png]</value>
<value>flagging/lists/3D.png</value>
</variable>
@@ -68,11 +69,19 @@
<value condition="Player.Forwarding">$LOCALIZE[31044]</value>
<value condition="Player.Rewinding">$LOCALIZE[31045]</value>
</variable>
+ <variable name="PlayerControlsRepeatImageVar">
+ <value condition="Playlist.IsRepeatOne + Control.HasFocus(604)">OSDRepeatOneFO.png</value>
+ <value condition="Playlist.IsRepeat + Control.HasFocus(604)">OSDRepeatAllFO.png</value>
+ <value condition="Control.HasFocus(604)">OSDRepeatFO.png</value>
+ <value condition="Playlist.IsRepeatOne">OSDRepeatOneNF.png</value>
+ <value condition="Playlist.IsRepeat">OSDRepeatAllNF.png</value>
+ <value>OSDRepeatNF.png</value>
+ </variable>
<variable name="PVRChannelMgrHeader">
<value condition="!IsEmpty(Window.Property(IsRadio))">$LOCALIZE[19199] - $LOCALIZE[19024]</value>
<value>$LOCALIZE[19199] - $LOCALIZE[19023]</value>
</variable>
- <include name="DialogBackgroundCommons">
+ <include name="DialogBackgroundCommons">
<control type="image">
<description>background image</description>
<left>0</left>
@@ -897,54 +906,7 @@
<top>2</top>
<width>39</width>
<height>39</height>
- <texture>OSDRepeatNF.png</texture>
- <visible>!Playlist.IsRepeat + !Playlist.IsRepeatOne</visible>
- <visible>!Control.HasFocus(604)</visible>
- </control>
- <control type="image">
- <left>165</left>
- <top>2</top>
- <width>39</width>
- <height>39</height>
- <texture>OSDRepeatFO.png</texture>
- <visible>!Playlist.IsRepeat + !Playlist.IsRepeatOne</visible>
- <visible>Control.HasFocus(604)</visible>
- </control>
- <control type="image">
- <left>165</left>
- <top>2</top>
- <width>39</width>
- <height>39</height>
- <texture>OSDRepeatOneNF.png</texture>
- <visible>Playlist.IsRepeatOne</visible>
- <visible>!Control.HasFocus(604)</visible>
- </control>
- <control type="image">
- <left>165</left>
- <top>2</top>
- <width>39</width>
- <height>39</height>
- <texture>OSDRepeatOneFO.png</texture>
- <visible>Playlist.IsRepeatOne</visible>
- <visible>Control.HasFocus(604)</visible>
- </control>
- <control type="image">
- <left>165</left>
- <top>2</top>
- <width>39</width>
- <height>39</height>
- <texture>OSDRepeatAllNF.png</texture>
- <visible>Playlist.IsRepeat</visible>
- <visible>!Control.HasFocus(604)</visible>
- </control>
- <control type="image">
- <left>165</left>
- <top>2</top>
- <width>39</width>
- <height>39</height>
- <texture>OSDRepeatAllFO.png</texture>
- <visible>Playlist.IsRepeat</visible>
- <visible>Control.HasFocus(604)</visible>
+ <texture>$VAR[PlayerControlsRepeatImageVar]</texture>
</control>
<control type="togglebutton" id="605">
<left>205</left>
diff --git a/addons/skin.confluence/media/flagging/video/Set.png b/addons/skin.confluence/media/flagging/video/Set.png
new file mode 100644
index 0000000000..fd8834fab2
--- /dev/null
+++ b/addons/skin.confluence/media/flagging/video/Set.png
Binary files differ
diff --git a/project/BuildDependencies/scripts/0_package.list b/project/BuildDependencies/scripts/0_package.list
index a1de1e25a8..ab64b4c94a 100644
--- a/project/BuildDependencies/scripts/0_package.list
+++ b/project/BuildDependencies/scripts/0_package.list
@@ -16,7 +16,7 @@ freetype-2.4.6-win32-3.7z
giflib-5.0.5p-win32.7z
gnutls-3.2.3-win32.zip
jsonschemabuilder-1.0.0-win32-3.7z
-libass-0.10.2-win32.7z
+libass-0.12.1-win32.7z
libbluray-0.4.0-win32.zip
libcdio-0.83-win32-2.7z
libcec-2.2.0-win32-1.7z
diff --git a/project/cmake/addons/addons/pvr.iptvsimple/pvr.iptvsimple.txt b/project/cmake/addons/addons/pvr.iptvsimple/pvr.iptvsimple.txt
index dd0ba6bdca..d1d4d3c2ce 100644
--- a/project/cmake/addons/addons/pvr.iptvsimple/pvr.iptvsimple.txt
+++ b/project/cmake/addons/addons/pvr.iptvsimple/pvr.iptvsimple.txt
@@ -1 +1 @@
-pvr.iptvsimple https://github.com/kodi-pvr/pvr.iptvsimple 38a72e5
+pvr.iptvsimple https://github.com/kodi-pvr/pvr.iptvsimple a2e6c6f
diff --git a/system/settings/settings.xml b/system/settings/settings.xml
index 921247ff58..323a2f14ac 100644
--- a/system/settings/settings.xml
+++ b/system/settings/settings.xml
@@ -2168,7 +2168,7 @@
</dependencies>
<control type="toggle" />
</setting>
- <setting id="services.upnpcontroller" type="boolean" label="21361" help="36326">
+ <setting id="services.upnpcontroller" type="boolean" parent="services.upnpserver" label="21361" help="36326">
<level>1</level>
<default>false</default>
<dependencies>
diff --git a/tools/depends/target/libass/Makefile b/tools/depends/target/libass/Makefile
index 8df2cecc1f..5fba256894 100644
--- a/tools/depends/target/libass/Makefile
+++ b/tools/depends/target/libass/Makefile
@@ -3,7 +3,7 @@ DEPS= ../../Makefile.include Makefile
# lib name, version
LIBNAME=libass
-VERSION=0.10.1
+VERSION=0.12.1
SOURCE=$(LIBNAME)-$(VERSION)
ARCHIVE=$(SOURCE).tar.gz
@@ -31,9 +31,9 @@ $(LIBDYLIB): $(PLATFORM)
.installed-$(PLATFORM): $(LIBDYLIB)
$(MAKE) -C $(PLATFORM) install
ifeq ($(OS),android)
- rm -f $(PREFIX)/lib/libass.la $(PREFIX)/lib/libass.so $(PREFIX)/lib/libass.so.4
- mv -f $(PREFIX)/lib/libass.so.4.1.0 $(PREFIX)/lib/libass.so
- $(RPL) -e "libass.so.4" "libass.so\x00\x00" $(PREFIX)/lib/libass.so
+ rm -f $(PREFIX)/lib/libass.la $(PREFIX)/lib/libass.so $(PREFIX)/lib/libass.so.5
+ mv -f $(PREFIX)/lib/libass.so.5.1.0 $(PREFIX)/lib/libass.so
+ $(RPL) -e "libass.so.5" "libass.so\x00\x00" $(PREFIX)/lib/libass.so
-$(READELF) --dynamic $(PREFIX)/lib/libass.so | grep ibrary
endif
touch $@
diff --git a/xbmc/GUIInfoManager.cpp b/xbmc/GUIInfoManager.cpp
index 208ca41a09..3f2e1cb426 100644
--- a/xbmc/GUIInfoManager.cpp
+++ b/xbmc/GUIInfoManager.cpp
@@ -567,6 +567,7 @@ const infomap listitem_labels[]= {{ "thumb", LISTITEM_THUMB },
{ "isresumable", LISTITEM_IS_RESUMABLE},
{ "percentplayed", LISTITEM_PERCENT_PLAYED},
{ "isfolder", LISTITEM_IS_FOLDER },
+ { "iscollection", LISTITEM_IS_COLLECTION },
{ "originaltitle", LISTITEM_ORIGINALTITLE },
{ "lastplayed", LISTITEM_LASTPLAYED },
{ "playcount", LISTITEM_PLAYCOUNT },
@@ -5440,6 +5441,11 @@ bool CGUIInfoManager::GetItemBool(const CGUIListItem *item, int condition) const
if (!stereoMode.empty() && stereoMode != "mono")
return true;
}
+ else if (condition == LISTITEM_IS_COLLECTION)
+ {
+ if (pItem->HasVideoInfoTag())
+ return (pItem->GetVideoInfoTag()->m_type == MediaTypeVideoCollection);
+ }
}
return false;
diff --git a/xbmc/GUIInfoManager.h b/xbmc/GUIInfoManager.h
index fec4431661..f82fdf2386 100644
--- a/xbmc/GUIInfoManager.h
+++ b/xbmc/GUIInfoManager.h
@@ -663,6 +663,7 @@ namespace INFO
#define LISTITEM_CHANNEL_NUMBER_LBL (LISTITEM_START + 145)
#define LISTITEM_IMDBNUMBER (LISTITEM_START + 146)
#define LISTITEM_EPISODENAME (LISTITEM_START + 147)
+#define LISTITEM_IS_COLLECTION (LISTITEM_START + 148)
#define LISTITEM_PROPERTY_START (LISTITEM_START + 200)
#define LISTITEM_PROPERTY_END (LISTITEM_PROPERTY_START + 1000)
diff --git a/xbmc/GUILargeTextureManager.cpp b/xbmc/GUILargeTextureManager.cpp
index d7255a66de..cb94356ff7 100644
--- a/xbmc/GUILargeTextureManager.cpp
+++ b/xbmc/GUILargeTextureManager.cpp
@@ -57,27 +57,33 @@ bool CImageLoader::DoWork()
else
loadPath = texturePath;
- if (m_use_cache && loadPath.empty())
- {
- // not in our texture cache, so try and load directly and then cache the result
- loadPath = CTextureCache::Get().CacheImage(texturePath, &m_texture);
- if (m_texture)
- return true; // we're done
- }
- if (!m_use_cache || !loadPath.empty())
+ if (!loadPath.empty())
{
// direct route - load the image
unsigned int start = XbmcThreads::SystemClockMillis();
m_texture = CBaseTexture::LoadFromFile(loadPath, g_graphicsContext.GetWidth(), g_graphicsContext.GetHeight(), CSettings::Get().GetBool("pictures.useexifrotation"));
- if (!m_texture)
- return false;
+
if (XbmcThreads::SystemClockMillis() - start > 100)
CLog::Log(LOGDEBUG, "%s - took %u ms to load %s", __FUNCTION__, XbmcThreads::SystemClockMillis() - start, loadPath.c_str());
- if (needsChecking)
- CTextureCache::Get().BackgroundCacheImage(texturePath);
+ if (m_texture)
+ {
+ if (needsChecking)
+ CTextureCache::Get().BackgroundCacheImage(texturePath);
+
+ return true;
+ }
+
+ // Fallthrough on failure:
+ CLog::Log(LOGERROR, "%s - Direct texture file loading failed for %s", __FUNCTION__, loadPath.c_str());
}
- return true;
+
+ if (!m_use_cache)
+ return false; // We're done
+
+ // not in our texture cache or it failed to load from it, so try and load directly and then cache the result
+ CTextureCache::Get().CacheImage(texturePath, &m_texture);
+ return (m_texture != NULL);
}
CGUILargeTextureManager::CLargeTexture::CLargeTexture(const std::string &path):
@@ -241,6 +247,3 @@ void CGUILargeTextureManager::OnJobComplete(unsigned int jobID, bool success, CJ
}
}
}
-
-
-
diff --git a/xbmc/TextureCache.cpp b/xbmc/TextureCache.cpp
index 542183b9e1..44c20b74f7 100644
--- a/xbmc/TextureCache.cpp
+++ b/xbmc/TextureCache.cpp
@@ -133,16 +133,7 @@ void CTextureCache::BackgroundCacheImage(const std::string &url)
AddJob(new CTextureCacheJob(CTextureUtils::UnwrapImageURL(url), details.hash));
}
-bool CTextureCache::CacheImage(const std::string &image, CTextureDetails &details)
-{
- std::string path = GetCachedImage(image, details);
- if (path.empty()) // not cached
- path = CacheImage(image, NULL, &details);
-
- return !path.empty();
-}
-
-std::string CTextureCache::CacheImage(const std::string &image, CBaseTexture **texture, CTextureDetails *details)
+std::string CTextureCache::CacheImage(const std::string &image, CBaseTexture **texture /* = NULL */, CTextureDetails *details /* = NULL */)
{
std::string url = CTextureUtils::UnwrapImageURL(image);
CSingleLock lock(m_processingSection);
@@ -176,6 +167,15 @@ std::string CTextureCache::CacheImage(const std::string &image, CBaseTexture **t
return GetCachedImage(url, *details, true);
}
+bool CTextureCache::CacheImage(const std::string &image, CTextureDetails &details)
+{
+ std::string path = GetCachedImage(image, details);
+ if (path.empty()) // not cached
+ path = CacheImage(image, NULL, &details);
+
+ return !path.empty();
+}
+
void CTextureCache::ClearCachedImage(const std::string &url, bool deleteSource /*= false */)
{
// TODO: This can be removed when the texture cache covers everything.
diff --git a/xbmc/TextureCache.h b/xbmc/TextureCache.h
index f35c56c7c9..549d565f7c 100644
--- a/xbmc/TextureCache.h
+++ b/xbmc/TextureCache.h
@@ -92,7 +92,7 @@ public:
\return cached url of this image
\sa CTextureCacheJob::CacheTexture
*/
- std::string CacheImage(const std::string &url, CBaseTexture **texture = NULL, CTextureDetails *details = NULL);
+ std::string CacheImage(const std::string &image, CBaseTexture **texture = NULL, CTextureDetails *details = NULL);
/*! \brief Cache an image to image cache if not already cached, returning the image details.
\param image url of the image to cache.
diff --git a/xbmc/cores/VideoRenderers/BaseRenderer.cpp b/xbmc/cores/VideoRenderers/BaseRenderer.cpp
index 751a61bd02..4345c0fb13 100644
--- a/xbmc/cores/VideoRenderers/BaseRenderer.cpp
+++ b/xbmc/cores/VideoRenderers/BaseRenderer.cpp
@@ -306,10 +306,11 @@ float CBaseRenderer::GetAspectRatio() const
return m_sourceFrameRatio * width / height * m_sourceHeight / m_sourceWidth;
}
-void CBaseRenderer::GetVideoRect(CRect &source, CRect &dest)
+void CBaseRenderer::GetVideoRect(CRect &source, CRect &dest, CRect &view)
{
source = m_sourceRect;
dest = m_destRect;
+ view = m_viewRect;
}
inline void CBaseRenderer::ReorderDrawPoints()
@@ -567,7 +568,7 @@ void CBaseRenderer::CalculateFrameAspectRatio(unsigned int desired_width, unsign
void CBaseRenderer::ManageDisplay()
{
- const CRect view = g_graphicsContext.GetViewWindow();
+ m_viewRect = g_graphicsContext.GetViewWindow();
m_sourceRect.x1 = 0.0f;
m_sourceRect.y1 = 0.0f;
@@ -614,7 +615,7 @@ void CBaseRenderer::ManageDisplay()
break;
}
- CalcNormalDisplayRect(view.x1, view.y1, view.Width(), view.Height(), GetAspectRatio() * CDisplaySettings::Get().GetPixelRatio(), CDisplaySettings::Get().GetZoomAmount(), CDisplaySettings::Get().GetVerticalShift());
+ CalcNormalDisplayRect(m_viewRect.x1, m_viewRect.y1, m_viewRect.Width(), m_viewRect.Height(), GetAspectRatio() * CDisplaySettings::Get().GetPixelRatio(), CDisplaySettings::Get().GetZoomAmount(), CDisplaySettings::Get().GetVerticalShift());
}
void CBaseRenderer::SetViewMode(int viewMode)
diff --git a/xbmc/cores/VideoRenderers/BaseRenderer.h b/xbmc/cores/VideoRenderers/BaseRenderer.h
index 8988e352d2..389695ac30 100644
--- a/xbmc/cores/VideoRenderers/BaseRenderer.h
+++ b/xbmc/cores/VideoRenderers/BaseRenderer.h
@@ -80,7 +80,13 @@ public:
void SetViewMode(int viewMode);
RESOLUTION GetResolution() const;
- void GetVideoRect(CRect &source, CRect &dest);
+
+ /*! \brief Get video rectangle and view window
+ \param source is original size of the video
+ \param dest is the target rendering area honoring aspect ratio of source
+ \param view is the entire target rendering area for the video (including black bars)
+ */
+ void GetVideoRect(CRect &source, CRect &dest, CRect &view);
float GetAspectRatio() const;
virtual bool AddVideoPicture(DVDVideoPicture* picture, int index) { return false; }
@@ -139,6 +145,7 @@ protected:
CRect m_destRect;
CRect m_oldDestRect; // destrect of the previous frame
CRect m_sourceRect;
+ CRect m_viewRect;
// rendering flags
unsigned m_iFlags;
diff --git a/xbmc/cores/VideoRenderers/OverlayRenderer.cpp b/xbmc/cores/VideoRenderers/OverlayRenderer.cpp
index e8c4bec535..866992ffa8 100644
--- a/xbmc/cores/VideoRenderers/OverlayRenderer.cpp
+++ b/xbmc/cores/VideoRenderers/OverlayRenderer.cpp
@@ -220,8 +220,7 @@ void CRenderer::Render(COverlay* o, float adjust_height)
{
CRect rs, rd, rv;
RESOLUTION_INFO res;
- g_renderManager.GetVideoRect(rs, rd);
- rv = g_graphicsContext.GetViewWindow();
+ g_renderManager.GetVideoRect(rs, rd, rv);
res = g_graphicsContext.GetResInfo(g_renderManager.GetResolution());
SRenderState state;
@@ -326,14 +325,40 @@ bool CRenderer::HasOverlay(int idx)
COverlay* CRenderer::Convert(CDVDOverlaySSA* o, double pts)
{
- CRect src, dst;
- g_renderManager.GetVideoRect(src, dst);
-
- int width = MathUtils::round_int(dst.Width());
- int height = MathUtils::round_int(dst.Height());
-
+ // libass render in a target area which named as frame. the frame size may bigger than video size,
+ // and including margins between video to frame edge. libass allow to render subtitles into the margins.
+ // this has been used to show subtitles in the top or bottom "black bar" between video to frame border.
+ CRect src, dst, target;
+ g_renderManager.GetVideoRect(src, dst, target);
+ int videoWidth = MathUtils::round_int(dst.Width());
+ int videoHeight = MathUtils::round_int(dst.Height());
+ int targetWidth = MathUtils::round_int(target.Width());
+ int targetHeight = MathUtils::round_int(target.Height());
+ int useMargin;
+
+ int subalign = CSettings::Get().GetInt("subtitles.align");
+ if(subalign == SUBTITLE_ALIGN_BOTTOM_OUTSIDE
+ || subalign == SUBTITLE_ALIGN_TOP_OUTSIDE
+ || subalign == SUBTITLE_ALIGN_MANUAL)
+ useMargin = 1;
+ else
+ useMargin = 0;
+ double position;
+ // position used to call ass_set_line_position, it's vertical line position of subtitles in percent.
+ // value is 0-100: 0 = on the bottom (default), 100 = on top.
+ if(subalign == SUBTITLE_ALIGN_TOP_INSIDE
+ || subalign == SUBTITLE_ALIGN_TOP_OUTSIDE)
+ position = 100.0;
+ else if (subalign == SUBTITLE_ALIGN_MANUAL)
+ {
+ RESOLUTION_INFO res;
+ res = g_graphicsContext.GetResInfo(g_renderManager.GetResolution());
+ position = 100.0 - (res.iSubtitles - res.Overscan.top) * 100 / res.iHeight;
+ }
+ else
+ position = 0.0;
int changes = 0;
- ASS_Image* images = o->m_libass->RenderImage(width, height, pts, &changes);
+ ASS_Image* images = o->m_libass->RenderImage(targetWidth, targetHeight, videoWidth, videoHeight, pts, useMargin, position, &changes);
if(o->m_overlay)
{
@@ -341,12 +366,21 @@ COverlay* CRenderer::Convert(CDVDOverlaySSA* o, double pts)
return o->m_overlay->Acquire();
}
+ COverlay *overlay = NULL;
#if defined(HAS_GL) || defined(HAS_GLES)
- return new COverlayGlyphGL(images, width, height);
+ overlay = new COverlayGlyphGL(images, targetWidth, targetHeight);
#elif defined(HAS_DX)
- return new COverlayQuadsDX(images, width, height);
+ overlay = new COverlayQuadsDX(images, targetWidth, targetHeight);
#endif
- return NULL;
+ // scale to video dimensions
+ if (overlay)
+ {
+ overlay->m_width = (float)targetWidth / videoWidth;
+ overlay->m_height = (float)targetHeight / videoHeight;
+ overlay->m_x = ((float)videoWidth - targetWidth) / 2 / videoWidth;
+ overlay->m_y = ((float)videoHeight - targetHeight) / 2 / videoHeight;
+ }
+ return overlay;
}
diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp
index cfef46ccf9..25323ef43c 100644
--- a/xbmc/cores/VideoRenderers/RenderManager.cpp
+++ b/xbmc/cores/VideoRenderers/RenderManager.cpp
@@ -129,11 +129,11 @@ CXBMCRenderManager::~CXBMCRenderManager()
m_pRenderer = NULL;
}
-void CXBMCRenderManager::GetVideoRect(CRect &source, CRect &dest)
+void CXBMCRenderManager::GetVideoRect(CRect &source, CRect &dest, CRect &view)
{
CSharedLock lock(m_sharedSection);
if (m_pRenderer)
- m_pRenderer->GetVideoRect(source, dest);
+ m_pRenderer->GetVideoRect(source, dest, view);
}
float CXBMCRenderManager::GetAspectRatio()
diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h
index b5ceb799ba..f32f4a9fd4 100644
--- a/xbmc/cores/VideoRenderers/RenderManager.h
+++ b/xbmc/cores/VideoRenderers/RenderManager.h
@@ -54,7 +54,7 @@ public:
~CXBMCRenderManager();
// Functions called from the GUI
- void GetVideoRect(CRect &source, CRect &dest);
+ void GetVideoRect(CRect &source, CRect &dest, CRect &view);
float GetAspectRatio();
void Update();
void FrameMove();
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayCodecFFmpeg.cpp
index 354a0f1dbd..113c9fd68c 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayCodecFFmpeg.cpp
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayCodecFFmpeg.cpp
@@ -27,7 +27,6 @@
#include "utils/log.h"
#include "utils/EndianSwap.h"
#include "guilib/GraphicContext.h"
-#include "xbmc/rendering/RenderSystem.h"
CDVDOverlayCodecFFmpeg::CDVDOverlayCodecFFmpeg() : CDVDOverlayCodec("FFmpeg Subtitle Decoder")
{
diff --git a/xbmc/cores/dvdplayer/DVDOverlayRenderer.cpp b/xbmc/cores/dvdplayer/DVDOverlayRenderer.cpp
index 34506c9f6e..0a20cc273f 100644
--- a/xbmc/cores/dvdplayer/DVDOverlayRenderer.cpp
+++ b/xbmc/cores/dvdplayer/DVDOverlayRenderer.cpp
@@ -71,7 +71,7 @@ void CDVDOverlayRenderer::Render(DVDPictureRenderer* pPicture, CDVDOverlaySSA* p
height = pPicture->height;
width = pPicture->width;
- ASS_Image* img = pOverlay->m_libass->RenderImage(width, height, pts);
+ ASS_Image* img = pOverlay->m_libass->RenderImage(width, height, width, height, pts);
int depth = OVERLAY::GetStereoscopicDepth();
diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp
index 82b59d2080..ab7816c26b 100644
--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp
+++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp
@@ -3924,8 +3924,8 @@ bool CDVDPlayer::OnAction(const CAction &action)
case ACTION_MOUSE_MOVE:
case ACTION_MOUSE_LEFT_CLICK:
{
- CRect rs, rd;
- m_dvdPlayerVideo->GetVideoRect(rs, rd);
+ CRect rs, rd, rv;
+ m_dvdPlayerVideo->GetVideoRect(rs, rd, rv);
CPoint pt(action.GetAmount(), action.GetAmount(1));
if (!rd.PtInRect(pt))
return false; // out of bounds
@@ -4162,7 +4162,8 @@ void CDVDPlayer::GetVideoStreamInfo(SPlayerVideoStreamInfo &info)
}
info.videoCodecName = retVal;
info.videoAspectRatio = m_dvdPlayerVideo->GetAspectRatio();
- m_dvdPlayerVideo->GetVideoRect(info.SrcRect, info.DestRect);
+ CRect viewRect;
+ m_dvdPlayerVideo->GetVideoRect(info.SrcRect, info.DestRect, viewRect);
info.stereoMode = m_dvdPlayerVideo->GetStereoMode();
if (info.stereoMode == "mono")
info.stereoMode = "";
diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.h b/xbmc/cores/dvdplayer/DVDPlayerVideo.h
index ead6f70798..3dfba89a46 100644
--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.h
+++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.h
@@ -84,7 +84,7 @@ public:
void EnableFullscreen(bool bEnable) { m_bAllowFullscreen = bEnable; }
#ifdef HAS_VIDEO_PLAYBACK
- void GetVideoRect(CRect& SrcRect, CRect& DestRect) const { g_renderManager.GetVideoRect(SrcRect, DestRect); }
+ void GetVideoRect(CRect& SrcRect, CRect& DestRect, CRect& ViewRect) const { g_renderManager.GetVideoRect(SrcRect, DestRect, ViewRect); }
float GetAspectRatio() { return g_renderManager.GetAspectRatio(); }
#endif
diff --git a/xbmc/cores/dvdplayer/DVDSubtitles/DVDSubtitlesLibass.cpp b/xbmc/cores/dvdplayer/DVDSubtitles/DVDSubtitlesLibass.cpp
index 6890c264df..0b5b050bbd 100644
--- a/xbmc/cores/dvdplayer/DVDSubtitles/DVDSubtitlesLibass.cpp
+++ b/xbmc/cores/dvdplayer/DVDSubtitles/DVDSubtitlesLibass.cpp
@@ -154,7 +154,7 @@ bool CDVDSubtitlesLibass::CreateTrack(char* buf, size_t size)
return true;
}
-ASS_Image* CDVDSubtitlesLibass::RenderImage(int imageWidth, int imageHeight, double pts, int *changes)
+ASS_Image* CDVDSubtitlesLibass::RenderImage(int frameWidth, int frameHeight, int videoWidth, int videoHeight, double pts, int useMargin, double position, int *changes)
{
CSingleLock lock(m_section);
if(!m_renderer || !m_track)
@@ -163,8 +163,13 @@ ASS_Image* CDVDSubtitlesLibass::RenderImage(int imageWidth, int imageHeight, dou
return NULL;
}
- double storage_aspact = (double)imageWidth / imageHeight;
- m_dll.ass_set_frame_size(m_renderer, imageWidth, imageHeight);
+ double storage_aspact = (double)frameWidth / frameHeight;
+ m_dll.ass_set_frame_size(m_renderer, frameWidth, frameHeight);
+ int topmargin = (frameHeight - videoHeight) / 2;
+ int leftmargin = (frameWidth - videoWidth) / 2;
+ m_dll.ass_set_margins(m_renderer, topmargin, topmargin, leftmargin, leftmargin);
+ m_dll.ass_set_use_margins(m_renderer, useMargin);
+ m_dll.ass_set_line_position(m_renderer, position);
m_dll.ass_set_aspect_ratio(m_renderer, storage_aspact / g_graphicsContext.GetResInfo().fPixelRatio, storage_aspact);
return m_dll.ass_render_frame(m_renderer, m_track, DVD_TIME_TO_MSEC(pts), changes);
}
diff --git a/xbmc/cores/dvdplayer/DVDSubtitles/DVDSubtitlesLibass.h b/xbmc/cores/dvdplayer/DVDSubtitles/DVDSubtitlesLibass.h
index ee30436184..b9129928ad 100644
--- a/xbmc/cores/dvdplayer/DVDSubtitles/DVDSubtitlesLibass.h
+++ b/xbmc/cores/dvdplayer/DVDSubtitles/DVDSubtitlesLibass.h
@@ -32,7 +32,7 @@ public:
CDVDSubtitlesLibass();
virtual ~CDVDSubtitlesLibass();
- ASS_Image* RenderImage(int imageWidth, int imageHeight, double pts, int* changes = NULL);
+ ASS_Image* RenderImage(int frameWidth, int frameHeight, int videoWidth, int videoHeight, double pts, int useMargin = 0, double position = 0.0, int* changes = NULL);
ASS_Event* GetEvents();
int GetNrOfEvents();
diff --git a/xbmc/cores/dvdplayer/DVDSubtitles/DllLibass.h b/xbmc/cores/dvdplayer/DVDSubtitles/DllLibass.h
index 6e30ea4cbe..78716e61b5 100644
--- a/xbmc/cores/dvdplayer/DVDSubtitles/DllLibass.h
+++ b/xbmc/cores/dvdplayer/DVDSubtitles/DllLibass.h
@@ -49,6 +49,7 @@ public:
virtual void ass_set_aspect_ratio(ASS_Renderer* priv, double dar, double sar)=0;
virtual void ass_set_margins(ASS_Renderer* priv, int t, int b, int l, int r)=0;
virtual void ass_set_use_margins(ASS_Renderer* priv, int use)=0;
+ virtual void ass_set_line_position(ASS_Renderer* priv, double line_position)=0;
virtual void ass_set_font_scale(ASS_Renderer* priv, double font_scale)=0;
virtual ASS_Image* ass_render_frame(ASS_Renderer *priv, ASS_Track* track, long long now, int* detect_change)=0;
virtual ASS_Track* ass_new_track(ASS_Library*)=0;
@@ -77,6 +78,7 @@ class DllLibass : public DllDynamic, DllLibassInterface
DEFINE_METHOD3(void, ass_set_aspect_ratio, (ASS_Renderer * p1, double p2, double p3))
DEFINE_METHOD5(void, ass_set_margins, (ASS_Renderer * p1, int p2, int p3, int p4, int p5))
DEFINE_METHOD2(void, ass_set_use_margins, (ASS_Renderer * p1, int p2))
+ DEFINE_METHOD2(void, ass_set_line_position, (ASS_Renderer * p1, double p2))
DEFINE_METHOD2(void, ass_set_font_scale, (ASS_Renderer * p1, double p2))
DEFINE_METHOD4(ASS_Image *, ass_render_frame, (ASS_Renderer * p1, ASS_Track * p2, long long p3, int * p4))
DEFINE_METHOD1(ASS_Track *, ass_new_track, (ASS_Library * p1))
@@ -99,6 +101,7 @@ class DllLibass : public DllDynamic, DllLibassInterface
RESOLVE_METHOD(ass_set_aspect_ratio)
RESOLVE_METHOD(ass_set_margins)
RESOLVE_METHOD(ass_set_use_margins)
+ RESOLVE_METHOD(ass_set_line_position)
RESOLVE_METHOD(ass_set_font_scale)
RESOLVE_METHOD(ass_render_frame)
RESOLVE_METHOD(ass_new_track)
diff --git a/xbmc/cores/dvdplayer/IDVDPlayer.h b/xbmc/cores/dvdplayer/IDVDPlayer.h
index cd8abfdc78..bbf76e06f9 100644
--- a/xbmc/cores/dvdplayer/IDVDPlayer.h
+++ b/xbmc/cores/dvdplayer/IDVDPlayer.h
@@ -69,7 +69,7 @@ public:
virtual bool IsSubtitleEnabled() = 0;
virtual void EnableFullscreen(bool bEnable) = 0;
#ifdef HAS_VIDEO_PLAYBACK
- virtual void GetVideoRect(CRect& SrcRect, CRect& DestRect) const = 0;
+ virtual void GetVideoRect(CRect& SrcRect, CRect& DestRect, CRect& ViewRect) const = 0;
virtual float GetAspectRatio() = 0;
#endif
virtual double GetDelay() = 0;
diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.h b/xbmc/cores/omxplayer/OMXPlayerVideo.h
index 7908ee57a2..3d0c13e162 100644
--- a/xbmc/cores/omxplayer/OMXPlayerVideo.h
+++ b/xbmc/cores/omxplayer/OMXPlayerVideo.h
@@ -124,7 +124,7 @@ public:
void SetFlags(unsigned flags) { m_flags = flags; };
int GetFreeSpace();
void SetVideoRect(const CRect &SrcRect, const CRect &DestRect);
- void GetVideoRect(CRect& SrcRect, CRect& DestRect) const { g_renderManager.GetVideoRect(SrcRect, DestRect); }
+ void GetVideoRect(CRect& SrcRect, CRect& DestRect, CRect& ViewRect) const { g_renderManager.GetVideoRect(SrcRect, DestRect, ViewRect); }
static void RenderUpdateCallBack(const void *ctx, const CRect &SrcRect, const CRect &DestRect);
void ResolutionUpdateCallBack(uint32_t width, uint32_t height, float framerate, float pixel_aspect);
static void ResolutionUpdateCallBack(void *ctx, uint32_t width, uint32_t height, float framerate, float pixel_aspect);
diff --git a/xbmc/input/linux/LIRC.cpp b/xbmc/input/linux/LIRC.cpp
index f0693f0f3b..e19a00fc42 100644
--- a/xbmc/input/linux/LIRC.cpp
+++ b/xbmc/input/linux/LIRC.cpp
@@ -36,6 +36,7 @@
#include "utils/log.h"
#include "settings/AdvancedSettings.h"
#include "utils/TimeUtils.h"
+#include "threads/SingleLock.h"
CRemoteControl::CRemoteControl()
: CThread("RemoteControl")
@@ -46,10 +47,10 @@ CRemoteControl::CRemoteControl()
, m_holdTime(0)
, m_button(0)
, m_bInitialized(false)
- , m_used(true)
- , m_deviceName(LIRC_DEVICE)
, m_inReply(false)
, m_nrSending(0)
+ , m_used(true)
+ , m_deviceName(LIRC_DEVICE)
{
}
@@ -74,6 +75,9 @@ void CRemoteControl::Reset()
void CRemoteControl::Disconnect()
{
+ CSingleLock lock(m_CS);
+ //make sure that any new function calls abort directly
+ m_bInitialized = false;
m_event.Set();
if (IsRunning())
@@ -81,7 +85,6 @@ void CRemoteControl::Disconnect()
if (m_fd != -1)
{
- m_bInitialized = false;
if (m_file != NULL)
fclose(m_file);
if (m_fd != -1)
@@ -113,6 +116,11 @@ void CRemoteControl::SetDeviceName(const std::string& value)
void CRemoteControl::Initialize()
{
+ //Create must not be called twice, make sure to lock before
+ //check IsRunning() so that any other thread will block until
+ //we know IsRunning is true and will not call Create again
+ CSingleLock lock(m_CS);
+
if (m_bInitialized || !m_used || IsRunning())
return;
@@ -121,6 +129,13 @@ void CRemoteControl::Initialize()
void CRemoteControl::Process()
{
struct sockaddr_un addr;
+ if (m_deviceName.length() >= sizeof(addr.sun_path))
+ {
+ CLog::Log(LOGERROR, "LIRC %s: device name is too long(%ud), maximum is %d",
+ __FUNCTION__, m_deviceName.length(), sizeof(addr.sun_path));
+ return;
+ }
+
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, m_deviceName.c_str());
@@ -134,7 +149,10 @@ void CRemoteControl::Process()
while (!m_bStop && iAttempt <= 60)
{
if (Connect(addr, iAttempt == 0))
+ {
+ m_bInitialized = true;
break;
+ }
if (iAttempt == 0)
CLog::Log(LOGINFO, "CRemoteControl::Process - failed to connect to LIRC, will keep retrying every %d seconds", iMsRetryDelay / 1000);
@@ -152,6 +170,9 @@ void CRemoteControl::Process()
}
bool CRemoteControl::CheckDevice() {
+ if (!m_bInitialized || !m_used)
+ return false;
+
#ifdef HAVE_INOTIFY
if (m_inotify_fd < 0 || m_inotify_wd < 0)
return true; // inotify wasn't setup for some reason, assume all is well
@@ -181,11 +202,18 @@ void CRemoteControl::Update()
uint32_t now = XbmcThreads::SystemClockMillis();
+ char buf[128];
// Read a line from the socket
- while (fgets(m_buf, sizeof(m_buf), m_file) != NULL)
+ while (true)
{
+ {
+ CSingleLock lock(m_CS);
+ if (fgets(buf, sizeof(buf), m_file) == NULL)
+ break;
+ }
+
// Remove the \n
- m_buf[strlen(m_buf)-1] = '\0';
+ buf[strlen(buf)-1] = '\0';
// Parse the result. Sample line:
// 000000037ff07bdd 00 OK mceusb
@@ -193,7 +221,7 @@ void CRemoteControl::Update()
char buttonName[128];
char repeatStr[4];
char deviceName[128];
- sscanf(m_buf, "%s %s %s %s", &scanCode[0], &repeatStr[0], &buttonName[0], &deviceName[0]);
+ sscanf(buf, "%s %s %s %s", &scanCode[0], &repeatStr[0], &buttonName[0], &deviceName[0]);
//beginning of lirc reply packet
//we get one when lirc is done sending something
@@ -232,7 +260,7 @@ void CRemoteControl::Update()
CLog::Log(LOGERROR, "LIRC: invalid non-numeric character in expression %s", repeatStr);
if (repeat == 0)
{
- CLog::Log(LOGDEBUG, "LIRC: %s - NEW at %d:%s (%s)", __FUNCTION__, now, m_buf, buttonName);
+ CLog::Log(LOGDEBUG, "LIRC: %s - NEW at %d:%s (%s)", __FUNCTION__, now, buf, buttonName);
m_firstClickTime = now;
m_holdTime = 0;
return;
@@ -250,6 +278,8 @@ void CRemoteControl::Update()
//drop commands when already sending
//because keypresses come in faster than lirc can send we risk hammering the daemon with commands
+ CSingleLock lock(m_CS);
+
if (m_nrSending > 0)
{
m_sendData.clear();
@@ -268,7 +298,10 @@ void CRemoteControl::Update()
}
if (feof(m_file) != 0)
+ {
+ CSingleExit ex(m_CS); //Disconnect takes the lock
Disconnect();
+ }
}
WORD CRemoteControl::GetButton()
@@ -286,12 +319,15 @@ void CRemoteControl::AddSendCommand(const std::string& command)
if (!m_bInitialized || !m_used)
return;
+ CSingleLock lock(m_CS);
+
m_sendData += command;
m_sendData += '\n';
}
bool CRemoteControl::Connect(struct sockaddr_un addr, bool logMessages)
{
+ bool bResult = false;
// Open the socket from which we will receive the remote commands
if ((m_fd = socket(AF_UNIX, SOCK_STREAM, 0)) != -1)
{
@@ -320,7 +356,7 @@ bool CRemoteControl::Connect(struct sockaddr_un addr, bool logMessages)
// Set an inotify watch on the lirc device
if ((m_inotify_wd = inotify_add_watch(m_inotify_fd, m_deviceName.c_str(), IN_DELETE_SELF)) != -1)
{
- m_bInitialized = true;
+ bResult = true;
CLog::Log(LOGINFO, "LIRC %s: successfully started", __FUNCTION__);
}
else
@@ -329,7 +365,7 @@ bool CRemoteControl::Connect(struct sockaddr_un addr, bool logMessages)
}
}
#else
- m_bInitialized = true;
+ bResult = true;
CLog::Log(LOGINFO, "LIRC %s: successfully started", __FUNCTION__);
#endif
}
@@ -348,7 +384,7 @@ bool CRemoteControl::Connect(struct sockaddr_un addr, bool logMessages)
else if (logMessages)
CLog::Log(LOGINFO, "LIRC %s: socket failed: %s", __FUNCTION__, strerror(errno));
- return m_bInitialized;
+ return bResult;
}
#endif
diff --git a/xbmc/input/linux/LIRC.h b/xbmc/input/linux/LIRC.h
index 2e8bdc5512..5fd872381f 100644
--- a/xbmc/input/linux/LIRC.h
+++ b/xbmc/input/linux/LIRC.h
@@ -22,6 +22,7 @@
#define LIRC_H
#include <string>
+#include <atomic>
#include "system.h"
#include "threads/Thread.h"
@@ -59,16 +60,19 @@ private:
FILE* m_file;
unsigned int m_holdTime;
int32_t m_button;
- char m_buf[128];
- bool m_bInitialized;
+
+ std::atomic<bool> m_bInitialized;
+ std::atomic<bool> m_inReply;
+ std::atomic<int> m_nrSending;
+
bool m_used;
uint32_t m_firstClickTime;
std::string m_deviceName;
bool CheckDevice();
std::string m_sendData;
- bool m_inReply;
- int m_nrSending;
CEvent m_event;
+ CCriticalSection m_CS;
+
};
#endif
diff --git a/xbmc/interfaces/json-rpc/PlayerOperations.cpp b/xbmc/interfaces/json-rpc/PlayerOperations.cpp
index 181fd80145..80d885ea4d 100644
--- a/xbmc/interfaces/json-rpc/PlayerOperations.cpp
+++ b/xbmc/interfaces/json-rpc/PlayerOperations.cpp
@@ -1033,10 +1033,10 @@ int CPlayerOperations::GetActivePlayers()
PlayerType CPlayerOperations::GetPlayer(const CVariant &player)
{
- int activePlayers = GetActivePlayers();
- int playerID;
+ int iPlayer = (int)player.asInteger();
+ PlayerType playerID;
- switch ((int)player.asInteger())
+ switch (iPlayer)
{
case PLAYLIST_VIDEO:
playerID = Video;
@@ -1051,38 +1051,35 @@ PlayerType CPlayerOperations::GetPlayer(const CVariant &player)
break;
default:
- playerID = PlayerImplicit;
+ playerID = None;
break;
}
- int choosenPlayer = playerID & activePlayers;
-
- // Implicit order
- if (choosenPlayer & Video)
- return Video;
- else if (choosenPlayer & Audio)
- return Audio;
- else if (choosenPlayer & Picture)
- return Picture;
+ if (GetPlaylist(playerID) == iPlayer)
+ return playerID;
else
return None;
}
int CPlayerOperations::GetPlaylist(PlayerType player)
{
+ int playlist = g_playlistPlayer.GetCurrentPlaylist();
+ if (playlist == PLAYLIST_NONE) // No active playlist, try guessing
+ playlist = g_application.m_pPlayer->GetPreferredPlaylist();
+
switch (player)
{
case Video:
- return PLAYLIST_VIDEO;
+ return playlist == PLAYLIST_NONE ? PLAYLIST_VIDEO : playlist;
case Audio:
- return PLAYLIST_MUSIC;
+ return playlist == PLAYLIST_NONE ? PLAYLIST_MUSIC : playlist;
case Picture:
return PLAYLIST_PICTURE;
default:
- return PLAYLIST_NONE;
+ return playlist;
}
}
@@ -1292,7 +1289,7 @@ JSONRPC_STATUS CPlayerOperations::GetPropertyValue(PlayerType player, const std:
switch (player)
{
case Video:
- case Audio:
+ case Audio: /* Return the position of current item if there is an active playlist */
if (!IsPVRChannel() && g_playlistPlayer.GetCurrentPlaylist() == playlist)
result = g_playlistPlayer.GetCurrentSong();
else
diff --git a/xbmc/network/NetworkServices.cpp b/xbmc/network/NetworkServices.cpp
index 5dab3d1d37..a09078b535 100644
--- a/xbmc/network/NetworkServices.cpp
+++ b/xbmc/network/NetworkServices.cpp
@@ -279,9 +279,11 @@ bool CNetworkServices::OnSettingChanging(const CSetting *setting)
if (!StartUPnPServer())
return false;
- // always stop and restart the client if necessary
+ // always stop and restart the client and controller if necessary
StopUPnPClient();
+ StopUPnPController();
StartUPnPClient();
+ StartUPnPController();
}
else
return StopUPnPServer();
@@ -296,9 +298,9 @@ bool CNetworkServices::OnSettingChanging(const CSetting *setting)
else if (settingId == "services.upnpcontroller")
{
// always stop and restart
- StopUPnPClient();
+ StopUPnPController();
if (((CSettingBool*)setting)->GetValue())
- return StartUPnPClient();
+ return StartUPnPController();
}
else
#endif // HAS_UPNP
@@ -799,6 +801,7 @@ bool CNetworkServices::StartUPnP()
#ifdef HAS_UPNP
ret |= StartUPnPClient();
ret |= StartUPnPServer();
+ ret |= StartUPnPController();
ret |= StartUPnPRenderer();
#endif // HAS_UPNP
return ret;
@@ -821,11 +824,7 @@ bool CNetworkServices::StopUPnP(bool bWait)
bool CNetworkServices::StartUPnPClient()
{
#ifdef HAS_UPNP
- if (!CSettings::Get().GetBool("services.upnpcontroller") ||
- !CSettings::Get().GetBool("services.upnpserver"))
- return false;
-
- CLog::Log(LOGNOTICE, "starting upnp controller");
+ CLog::Log(LOGNOTICE, "starting upnp client");
CUPnP::GetInstance()->StartClient();
return IsUPnPClientRunning();
#endif // HAS_UPNP
@@ -843,7 +842,7 @@ bool CNetworkServices::IsUPnPClientRunning()
bool CNetworkServices::StopUPnPClient()
{
#ifdef HAS_UPNP
- if (!IsUPnPRendererRunning())
+ if (!IsUPnPClientRunning())
return true;
CLog::Log(LOGNOTICE, "stopping upnp client");
@@ -854,6 +853,42 @@ bool CNetworkServices::StopUPnPClient()
return false;
}
+bool CNetworkServices::StartUPnPController()
+{
+#ifdef HAS_UPNP
+ if (!CSettings::Get().GetBool("services.upnpcontroller") ||
+ !CSettings::Get().GetBool("services.upnpserver"))
+ return false;
+
+ CLog::Log(LOGNOTICE, "starting upnp controller");
+ CUPnP::GetInstance()->StartController();
+ return IsUPnPControllerRunning();
+#endif // HAS_UPNP
+ return false;
+}
+
+bool CNetworkServices::IsUPnPControllerRunning()
+{
+#ifdef HAS_UPNP
+ return CUPnP::GetInstance()->IsControllerStarted();
+#endif // HAS_UPNP
+ return false;
+}
+
+bool CNetworkServices::StopUPnPController()
+{
+#ifdef HAS_UPNP
+ if (!IsUPnPControllerRunning())
+ return true;
+
+ CLog::Log(LOGNOTICE, "stopping upnp controller");
+ CUPnP::GetInstance()->StopController();
+
+ return true;
+#endif // HAS_UPNP
+ return false;
+}
+
bool CNetworkServices::StartUPnPRenderer()
{
#ifdef HAS_UPNP
@@ -911,10 +946,10 @@ bool CNetworkServices::IsUPnPServerRunning()
bool CNetworkServices::StopUPnPServer()
{
#ifdef HAS_UPNP
- if (!IsUPnPRendererRunning())
+ if (!IsUPnPServerRunning())
return true;
- StopUPnPClient();
+ StopUPnPController();
CLog::Log(LOGNOTICE, "stopping upnp server");
CUPnP::GetInstance()->StopServer();
diff --git a/xbmc/network/NetworkServices.h b/xbmc/network/NetworkServices.h
index 5e1e628099..8612ecd53b 100644
--- a/xbmc/network/NetworkServices.h
+++ b/xbmc/network/NetworkServices.h
@@ -76,6 +76,9 @@ public:
bool StartUPnPClient();
bool IsUPnPClientRunning();
bool StopUPnPClient();
+ bool StartUPnPController();
+ bool IsUPnPControllerRunning();
+ bool StopUPnPController();
bool StartUPnPRenderer();
bool IsUPnPRendererRunning();
bool StopUPnPRenderer();
diff --git a/xbmc/network/upnp/UPnP.cpp b/xbmc/network/upnp/UPnP.cpp
index 05ba0111d5..23b1ebdf31 100644
--- a/xbmc/network/upnp/UPnP.cpp
+++ b/xbmc/network/upnp/UPnP.cpp
@@ -448,6 +448,7 @@ CUPnP::~CUPnP()
{
m_UPnP->Stop();
StopClient();
+ StopController();
StopServer();
delete m_UPnP;
@@ -492,7 +493,7 @@ CUPnP::ReleaseInstance(bool bWait)
}
/*----------------------------------------------------------------------
-| CUPnP::StartServer
+| CUPnP::GetServer
+---------------------------------------------------------------------*/
CUPnPServer* CUPnP::GetServer()
{
@@ -530,27 +531,47 @@ CUPnP::SaveFileState(const CFileItem& item, const CBookmark& bookmark, const boo
}
/*----------------------------------------------------------------------
-| CUPnP::StartClient
+| CUPnP::CreateControlPoint
+---------------------------------------------------------------------*/
void
-CUPnP::StartClient()
+CUPnP::CreateControlPoint()
{
- if (!m_CtrlPointHolder->m_CtrlPoint.IsNull()) return;
+ if (!m_CtrlPointHolder->m_CtrlPoint.IsNull())
+ return;
// create controlpoint
m_CtrlPointHolder->m_CtrlPoint = new PLT_CtrlPoint();
// start it
m_UPnP->AddCtrlPoint(m_CtrlPointHolder->m_CtrlPoint);
+}
+
+/*----------------------------------------------------------------------
+| CUPnP::DestroyControlPoint
++---------------------------------------------------------------------*/
+void
+CUPnP::DestroyControlPoint()
+{
+ if (m_CtrlPointHolder->m_CtrlPoint.IsNull())
+ return;
+
+ m_UPnP->RemoveCtrlPoint(m_CtrlPointHolder->m_CtrlPoint);
+ m_CtrlPointHolder->m_CtrlPoint = NULL;
+}
+
+/*----------------------------------------------------------------------
+| CUPnP::StartClient
++---------------------------------------------------------------------*/
+void
+CUPnP::StartClient()
+{
+ if (m_MediaBrowser != NULL)
+ return;
+
+ CreateControlPoint();
// start browser
m_MediaBrowser = new CMediaBrowser(m_CtrlPointHolder->m_CtrlPoint);
-
- // start controller
- if (CSettings::Get().GetBool("services.upnpcontroller") &&
- CSettings::Get().GetBool("services.upnpserver")) {
- m_MediaController = new CMediaController(m_CtrlPointHolder->m_CtrlPoint);
- }
}
/*----------------------------------------------------------------------
@@ -559,15 +580,44 @@ CUPnP::StartClient()
void
CUPnP::StopClient()
{
- if (m_CtrlPointHolder->m_CtrlPoint.IsNull()) return;
-
- m_UPnP->RemoveCtrlPoint(m_CtrlPointHolder->m_CtrlPoint);
- m_CtrlPointHolder->m_CtrlPoint = NULL;
+ if (m_MediaBrowser == NULL)
+ return;
delete m_MediaBrowser;
m_MediaBrowser = NULL;
- delete m_MediaController;
- m_MediaController = NULL;
+
+ if (!IsControllerStarted())
+ DestroyControlPoint();
+}
+
+/*----------------------------------------------------------------------
+| CUPnP::StartController
++---------------------------------------------------------------------*/
+void
+CUPnP::StartController()
+{
+ if (m_MediaController != NULL)
+ return;
+
+ CreateControlPoint();
+
+ m_MediaController = new CMediaController(m_CtrlPointHolder->m_CtrlPoint);
+}
+
+/*----------------------------------------------------------------------
+| CUPnP::StopController
++---------------------------------------------------------------------*/
+void
+CUPnP::StopController()
+{
+ if (m_MediaController == NULL)
+ return;
+
+ delete m_MediaController;
+ m_MediaController = NULL;
+
+ if (!IsClientStarted())
+ DestroyControlPoint();
}
/*----------------------------------------------------------------------
diff --git a/xbmc/network/upnp/UPnP.h b/xbmc/network/upnp/UPnP.h
index 56c91b0a7b..69c4e94afe 100644
--- a/xbmc/network/upnp/UPnP.h
+++ b/xbmc/network/upnp/UPnP.h
@@ -58,6 +58,11 @@ public:
void StopClient();
bool IsClientStarted() { return (m_MediaBrowser != NULL); }
+ // controller
+ void StartController();
+ void StopController();
+ bool IsControllerStarted() { return (m_MediaController != NULL); }
+
// renderer
bool StartRenderer();
void StopRenderer();
@@ -79,6 +84,9 @@ public:
static void RegisterUserdata(void* ptr);
static void UnregisterUserdata(void* ptr);
private:
+ void CreateControlPoint();
+ void DestroyControlPoint();
+
// methods
CUPnPRenderer* CreateRenderer(int port = 0);
CUPnPServer* CreateServer(int port = 0);
diff --git a/xbmc/pvr/dialogs/GUIDialogPVRChannelManager.cpp b/xbmc/pvr/dialogs/GUIDialogPVRChannelManager.cpp
index 25292e7292..ab2be2b91b 100644
--- a/xbmc/pvr/dialogs/GUIDialogPVRChannelManager.cpp
+++ b/xbmc/pvr/dialogs/GUIDialogPVRChannelManager.cpp
@@ -769,12 +769,14 @@ void CGUIDialogPVRChannelManager::SaveList(void)
CPVRChannelGroupPtr group = g_PVRChannelGroups->GetGroupAll(m_bIsRadio);
if (!group)
return;
+
for (int iListPtr = 0; iListPtr < m_channelItems->Size(); iListPtr++)
{
- if (!m_channelItems->HasPVRChannelInfoTag())
+ CFileItemPtr pItem = m_channelItems->Get(iListPtr);
+
+ if (!pItem->HasPVRChannelInfoTag())
continue;
- CFileItemPtr pItem = m_channelItems->Get(iListPtr);
if (pItem->GetProperty("SupportsSettings").asBoolean())
RenameChannel(pItem);