aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--addons/skin.estuary/xml/DialogPlayerProcessInfo.xml2
-rw-r--r--addons/skin.estuary/xml/DialogSeekBar.xml151
-rw-r--r--addons/skin.estuary/xml/Includes_PVR.xml87
-rw-r--r--addons/skin.estuary/xml/MusicOSD.xml30
-rw-r--r--addons/skin.estuary/xml/VideoOSD.xml30
-rw-r--r--lib/libUPnP/Neptune/Source/System/Bsd/NptBsdSockets.cpp29
-rw-r--r--lib/libUPnP/patches/0045-platinum-win10-uwp-fixes.patch25
-rw-r--r--lib/libUPnP/patches/0047-neptune-fix-device-discovery-on-windows.patch49
-rw-r--r--xbmc/GUIInfoManager.cpp82
-rw-r--r--xbmc/addons/PVRClient.cpp9
-rw-r--r--xbmc/addons/PVRClient.h7
-rw-r--r--xbmc/dialogs/GUIDialogSeekBar.cpp92
-rw-r--r--xbmc/dialogs/GUIDialogSeekBar.h9
-rw-r--r--xbmc/guilib/GUIControlFactory.cpp5
-rw-r--r--xbmc/guilib/GUIProgressControl.cpp52
-rw-r--r--xbmc/guilib/GUIProgressControl.h4
-rw-r--r--xbmc/guilib/guiinfo/GUIInfoLabels.h10
-rw-r--r--xbmc/guilib/guiinfo/PlayerGUIInfo.cpp7
-rw-r--r--xbmc/pvr/CMakeLists.txt6
-rw-r--r--xbmc/pvr/PVRGUIInfo.cpp320
-rw-r--r--xbmc/pvr/PVRGUIInfo.h48
-rw-r--r--xbmc/pvr/PVRGUITimesInfo.cpp395
-rw-r--r--xbmc/pvr/PVRGUITimesInfo.h83
-rw-r--r--xbmc/pvr/PVRManager.cpp19
-rw-r--r--xbmc/pvr/PVRManager.h11
-rw-r--r--xbmc/pvr/epg/Epg.cpp6
-rw-r--r--xbmc/pvr/epg/EpgInfoTag.cpp6
-rw-r--r--xbmc/pvr/epg/EpgInfoTag.h2
-rw-r--r--xbmc/settings/AdvancedSettings.cpp2
-rw-r--r--xbmc/settings/AdvancedSettings.h4
30 files changed, 971 insertions, 611 deletions
diff --git a/addons/skin.estuary/xml/DialogPlayerProcessInfo.xml b/addons/skin.estuary/xml/DialogPlayerProcessInfo.xml
index 53c4567c60..5dbbaf8361 100644
--- a/addons/skin.estuary/xml/DialogPlayerProcessInfo.xml
+++ b/addons/skin.estuary/xml/DialogPlayerProcessInfo.xml
@@ -8,7 +8,7 @@
<control type="group">
<bottom>0</bottom>
<height>250</height>
- <animation effect="slide" end="0,-80" time="150" condition="PVR.IsTimeShift">conditional</animation>
+ <animation effect="slide" end="0,-20" time="150" condition="VideoPlayer.Content(LiveTV)">conditional</animation>
<control type="image">
<left>10</left>
<top>-240</top>
diff --git a/addons/skin.estuary/xml/DialogSeekBar.xml b/addons/skin.estuary/xml/DialogSeekBar.xml
index a307f28ce0..b4b4d6de91 100644
--- a/addons/skin.estuary/xml/DialogSeekBar.xml
+++ b/addons/skin.estuary/xml/DialogSeekBar.xml
@@ -143,107 +143,83 @@
<label>$VAR[SeekLabel]</label>
<shadowcolor>black</shadowcolor>
</control>
- <control type="group" id="6000">
- <top>-5</top>
- <visible>PVR.IsTimeShift + !Player.ChannelPreviewActive</visible>
- <animation effect="fade" time="300">VisibleChange</animation>
- <control type="label">
- <top>0</top>
- <right>20</right>
- <width>400</width>
- <height>50</height>
- <align>right</align>
- <aligny>center</aligny>
- <font>font30</font>
- <label>$INFO[PVR.TimeShiftEnd]</label>
+ <control type="group">
+ <visible>VideoPlayer.Content(LiveTV)</visible>
+ <control type="group">
+ <visible>Player.SeekEnabled + VideoPlayer.HasEPG</visible>
+ <include content="PVRProgress">
+ <param name="ts_bar_top" value="70"/>
+ <param name="epg_bar_top" value="78"/>
+ <param name="ts_bar_height" value="8"/>
+ <param name="epg_bar_height" value="8"/>
+ </include>
</control>
- <control type="label">
- <top>0</top>
- <left>20</left>
- <width>400</width>
- <height>50</height>
- <align>left</align>
- <aligny>center</aligny>
- <font>font30</font>
- <label>$INFO[PVR.TimeShiftStart]</label>
+ <control type="group">
+ <visible>Player.SeekEnabled + !VideoPlayer.HasEPG</visible>
+ <include content="PVRProgress">
+ <param name="ts_bar_top" value="70"/>
+ <param name="ts_bar_height" value="16"/>
+ </include>
</control>
- <control type="label">
- <top>0</top>
- <left>20</left>
- <right>20</right>
- <height>50</height>
- <align>center</align>
- <aligny>center</aligny>
- <font>font30</font>
- <label>[B]$LOCALIZE[31026][/B] $INFO[PVR.TimeshiftCur] (-$INFO[PVR.TimeshiftOffset])</label>
+ <control type="group">
+ <visible>!Player.SeekEnabled + VideoPlayer.HasEPG</visible>
+ <include content="PVRProgress">
+ <param name="epg_bar_top" value="70"/>
+ <param name="epg_bar_height" value="16"/>
+ </include>
+ </control>
+ <control type="group">
+ <visible>!Player.SeekEnabled + !VideoPlayer.HasEPG</visible>
+ <include content="PVRProgress"/>
+ </control>
+ <control type="slider" id="403">
+ <left>0</left>
+ <top>65</top>
+ <width>100%</width>
+ <height>26</height>
+ <texturesliderbar colordiffuse="00FFFFFF">osd/progress/nub_bar.png</texturesliderbar>
+ <textureslidernib colordiffuse="button_focus">osd/progress/nub_bar.png</textureslidernib>
+ <textureslidernibfocus colordiffuse="button_focus">colors/white.png</textureslidernibfocus>
+ <visible>Player.SeekEnabled + !Player.ChannelPreviewActive</visible>
</control>
+ </control>
+ <control type="group">
+ <visible>!VideoPlayer.Content(LiveTV)</visible>
<control type="progress">
<left>0</left>
- <top>50</top>
+ <top>70</top>
<width>100%</width>
- <height>15</height>
- <info>PVR.timeshiftprogress</info>
- <texturebg border="3" colordiffuse="60FFFFFF">colors/white50.png</texturebg>
+ <height>16</height>
+ <info>Player.ProgressCache</info>
+ <texturebg border="3" colordiffuse="00FFFFFF">colors/white50.png</texturebg>
<midtexture>colors/white50.png</midtexture>
- <visible>VideoPlayer.Content(livetv)</visible>
</control>
- </control>
- <control type="progress">
- <left>0</left>
- <top>70</top>
- <width>100%</width>
- <height>15</height>
- <info>PVR.EpgEventProgress</info>
- <texturebg border="3" colordiffuse="60FFFFFF">colors/white50.png</texturebg>
- <midtexture colordiffuse="button_focus">colors/white.png</midtexture>
- <visible>VideoPlayer.HasEpg</visible>
- </control>
- <control type="progress">
- <left>0</left>
- <top>70</top>
- <width>100%</width>
- <height>15</height>
- <info>Player.ProgressCache</info>
- <texturebg border="3" colordiffuse="60FFFFFF">colors/white50.png</texturebg>
- <midtexture>colors/white50.png</midtexture>
- <visible>!VideoPlayer.Content(livetv)</visible>
- </control>
- <control type="progress">
- <left>0</left>
- <top>70</top>
- <width>100%</width>
- <height>15</height>
- <info>Player.Progress</info>
- <texturebg border="3" colordiffuse="60FFFFFF">colors/white50.png</texturebg>
- <midtexture colordiffuse="button_focus">colors/white.png</midtexture>
- <visible>!VideoPlayer.HasEpg + !Player.ChannelPreviewActive</visible>
- </control>
- <control type="slider" id="401">
- <left>5</left>
- <top>65</top>
- <width>100%</width>
- <height>25</height>
- <texturesliderbar colordiffuse="00FFFFFF">osd/progress/nub_bar.png</texturesliderbar>
- <textureslidernib colordiffuse="button_focus">osd/progress/nub_bar.png</textureslidernib>
- <textureslidernibfocus colordiffuse="button_focus">colors/white.png</textureslidernibfocus>
- <visible>Player.SeekEnabled + !VideoPlayer.HasEpg + !Player.ChannelPreviewActive</visible>
- </control>
- <control type="slider" id="402">
- <left>5</left>
- <top>65</top>
- <width>100%</width>
- <height>25</height>
- <texturesliderbar colordiffuse="00FFFFFF">osd/progress/nub_bar.png</texturesliderbar>
- <textureslidernib colordiffuse="button_focus">osd/progress/nub_bar.png</textureslidernib>
- <textureslidernibfocus colordiffuse="button_focus">colors/white.png</textureslidernibfocus>
- <visible>Player.SeekEnabled + VideoPlayer.HasEpg + !Player.ChannelPreviewActive</visible>
+ <control type="progress">
+ <left>0</left>
+ <top>70</top>
+ <width>100%</width>
+ <height>16</height>
+ <info>Player.Progress</info>
+ <texturebg border="3" colordiffuse="60FFFFFF">colors/white50.png</texturebg>
+ <midtexture colordiffuse="button_focus">colors/white.png</midtexture>
+ </control>
+ <control type="slider" id="401">
+ <left>0</left>
+ <top>65</top>
+ <width>100%</width>
+ <height>26</height>
+ <texturesliderbar colordiffuse="00FFFFFF">osd/progress/nub_bar.png</texturesliderbar>
+ <textureslidernib colordiffuse="button_focus">osd/progress/nub_bar.png</textureslidernib>
+ <textureslidernibfocus colordiffuse="button_focus">colors/white.png</textureslidernibfocus>
+ <visible>Player.SeekEnabled</visible>
+ </control>
</control>
</control>
<control type="group">
<visible>!Window.IsVisible(playerprocessinfo)</visible>
<visible>Player.ShowInfo + VideoPlayer.Content(LiveTV)</visible>
<animation effect="fade" time="400">VisibleChange</animation>
- <animation effect="slide" end="0,-80" time="150" condition="Control.IsVisible(6000)">conditional</animation>
+ <animation effect="slide" end="0,-20" time="150" condition="VideoPlayer.Content(LiveTV)">conditional</animation>
<bottom>0</bottom>
<height>380</height>
<control type="label">
@@ -295,7 +271,6 @@
<visible>Player.ShowInfo + !VideoPlayer.Content(LiveTV) + Window.IsActive(fullscreenvideo)</visible>
<animation effect="fade" time="200">VisibleChange</animation>
<control type="group">
- <animation effect="slide" end="0,-80" time="150" condition="PVR.IsTimeShift">conditional</animation>
<control type="image">
<depth>DepthOSD+</depth>
<left>10</left>
diff --git a/addons/skin.estuary/xml/Includes_PVR.xml b/addons/skin.estuary/xml/Includes_PVR.xml
index 938eb63dad..8ec061bee3 100644
--- a/addons/skin.estuary/xml/Includes_PVR.xml
+++ b/addons/skin.estuary/xml/Includes_PVR.xml
@@ -101,6 +101,93 @@
<orientation>vertical</orientation>
</control>
</include>
+ <include name="PVRProgress">
+ <control type="group">
+ <animation effect="fade" time="400">VisibleChange</animation>
+ <visible>!Player.ChannelPreviewActive</visible>
+ <control type="group">
+ <visible>Player.SeekEnabled | VideoPlayer.HasEPG</visible>
+ <control type="label">
+ <top>22</top>
+ <right>20</right>
+ <width>400</width>
+ <height>50</height>
+ <align>right</align>
+ <aligny>center</aligny>
+ <font>font30</font>
+ <label>$INFO[PVR.TimeshiftProgressEndTime]</label>
+ </control>
+ <control type="label">
+ <top>22</top>
+ <left>20</left>
+ <width>400</width>
+ <height>50</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font30</font>
+ <label>$INFO[PVR.TimeshiftProgressStartTime]</label>
+ </control>
+ <control type="label">
+ <top>22</top>
+ <left>20</left>
+ <right>20</right>
+ <height>50</height>
+ <align>center</align>
+ <aligny>center</aligny>
+ <font>font30</font>
+ <label>[B]$LOCALIZE[31026][/B] $INFO[PVR.TimeshiftCur] (-$INFO[PVR.TimeshiftOffset])</label>
+ <visible>PVR.IsTimeShift</visible>
+ </control>
+ </control>
+ <control type="group">
+ <visible>VideoPlayer.HasEPG</visible>
+ <control type="progress">
+ <left>0</left>
+ <top>$PARAM[epg_bar_top]</top>
+ <width>100%</width>
+ <height>$PARAM[epg_bar_height]</height>
+ <info2>PVR.TimeshiftProgressEpgStart</info2>
+ <info>PVR.TimeshiftProgressPlayPos</info>
+ <texturebg border="3" colordiffuse="60FFFFFF">colors/white50.png</texturebg>
+ <midtexture colordiffuse="button_focus">colors/white.png</midtexture>
+ </control>
+ <control type="progress">
+ <left>0</left>
+ <top>$PARAM[epg_bar_top]</top>
+ <width>100%</width>
+ <height>$PARAM[epg_bar_height]</height>
+ <info2>PVR.TimeshiftProgressPlayPos</info2>
+ <info>PVR.TimeshiftProgressEpgEnd</info>
+ <texturebg border="3" colordiffuse="00FFFFFF">colors/white50.png</texturebg>
+ <midtexture>colors/white50.png</midtexture>
+ </control>
+ </control>
+ <control type="progress">
+ <left>0</left>
+ <top>$PARAM[ts_bar_top]</top>
+ <width>100%</width>
+ <height>$PARAM[ts_bar_height]</height>
+ <info2>PVR.TimeshiftProgressBufferStart</info2>
+ <info>PVR.TimeshiftProgressBufferEnd</info>
+ <texturebg border="3" colordiffuse="60FFFFFF">colors/white50.png</texturebg>
+ <midtexture>colors/white70.png</midtexture>
+ <visible>Player.SeekEnabled</visible>
+ </control>
+ </control>
+ <control type="group">
+ <animation effect="fade" time="400">VisibleChange</animation>
+ <visible>Player.ChannelPreviewActive</visible>
+ <control type="progress">
+ <left>0</left>
+ <top>70</top>
+ <width>100%</width>
+ <height>16</height>
+ <info>PVR.EpgEventProgress</info>
+ <texturebg border="3" colordiffuse="60FFFFFF">colors/white50.png</texturebg>
+ <midtexture colordiffuse="button_focus">colors/white.png</midtexture>
+ </control>
+ </control>
+ </include>
<include name="PVRInfoPanel">
<control type="group">
<visible>!ListItem.IsFolder</visible>
diff --git a/addons/skin.estuary/xml/MusicOSD.xml b/addons/skin.estuary/xml/MusicOSD.xml
index 0ce7dc5025..6097c0729b 100644
--- a/addons/skin.estuary/xml/MusicOSD.xml
+++ b/addons/skin.estuary/xml/MusicOSD.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<window>
+ <onload condition="!Player.PauseEnabled">SetFocus(603)</onload>
<defaultcontrol always="true">602</defaultcontrol>
<depth>DepthOSD</depth>
<controls>
@@ -62,6 +63,7 @@
<radioposy>0</radioposy>
<selected>Player.Paused</selected>
<onclick>PlayerControl(Play)</onclick>
+ <visible>Player.PauseEnabled</visible>
</control>
<control type="radiobutton" id="603">
<include content="OSDButton">
@@ -183,13 +185,13 @@
</control>
</control>
<control type="label">
- <right>30</right>
+ <animation effect="slide" end="0,-20" time="150" condition="MusicPlayer.Content(LiveTV)">conditional</animation>
+ <right>20</right>
<top>-60</top>
- <textoffsetx>20</textoffsetx>
<aligny>center</aligny>
<align>right</align>
- <width>1858</width>
- <height>60</height>
+ <width>1000</width>
+ <height>50</height>
<label>$VAR[MusicOSDHelpTextVar]</label>
</control>
</control>
@@ -213,55 +215,55 @@
<left>0</left>
<top>-5</top>
<width>100%</width>
- <height>25</height>
+ <height>26</height>
<onup>8010</onup>
<ondown>650</ondown>
<texturesliderbar colordiffuse="00FFFFFF">osd/progress/nub_leftright.png</texturesliderbar>
<textureslidernib>osd/progress/nub_leftright.png</textureslidernib>
<textureslidernibfocus colordiffuse="button_focus">osd/progress/nub_leftright.png</textureslidernibfocus>
<info>Player.Progress</info>
- <visible>Player.SeekEnabled + !Control.HasFocus(87) + !VideoPlayer.HasEpg</visible>
+ <visible>Player.SeekEnabled + !Control.HasFocus(87) + !MusicPlayer.Content(LiveTV)</visible>
<action>seek</action>
</control>
<control type="slider">
<left>0</left>
<top>-5</top>
<width>100%</width>
- <height>25</height>
+ <height>26</height>
<onup>8010</onup>
<ondown>650</ondown>
<texturesliderbar colordiffuse="00FFFFFF">osd/progress/nub_leftright.png</texturesliderbar>
<textureslidernib colordiffuse="button_focus">osd/progress/nub_leftright.png</textureslidernib>
<textureslidernibfocus colordiffuse="button_focus">osd/progress/nub_leftright.png</textureslidernibfocus>
<info>Player.Progress</info>
- <visible>Player.SeekEnabled + Control.HasFocus(87) + !VideoPlayer.HasEpg</visible>
+ <visible>Player.SeekEnabled + Control.HasFocus(87) + !MusicPlayer.Content(LiveTV)</visible>
<action>seek</action>
</control>
<control type="slider">
<left>0</left>
<top>-5</top>
<width>100%</width>
- <height>25</height>
+ <height>26</height>
<onup>8010</onup>
<ondown>650</ondown>
<texturesliderbar colordiffuse="00FFFFFF">osd/progress/nub_leftright.png</texturesliderbar>
<textureslidernib>osd/progress/nub_leftright.png</textureslidernib>
<textureslidernibfocus colordiffuse="button_focus">osd/progress/nub_leftright.png</textureslidernibfocus>
- <info>PVR.EpgEventProgress</info>
- <visible>Player.SeekEnabled + !Control.HasFocus(87) + VideoPlayer.HasEpg</visible>
+ <info>PVR.TimeshiftProgressPlayPos</info>
+ <visible>Player.SeekEnabled + !Control.HasFocus(87) + MusicPlayer.Content(LiveTV)</visible>
</control>
<control type="slider">
<left>0</left>
<top>-5</top>
<width>100%</width>
- <height>25</height>
+ <height>26</height>
<onup>8010</onup>
<ondown>650</ondown>
<texturesliderbar colordiffuse="00FFFFFF">osd/progress/nub_leftright.png</texturesliderbar>
<textureslidernib colordiffuse="button_focus">osd/progress/nub_leftright.png</textureslidernib>
<textureslidernibfocus colordiffuse="button_focus">osd/progress/nub_leftright.png</textureslidernibfocus>
- <info>PVR.EpgEventProgress</info>
- <visible>Player.SeekEnabled + Control.HasFocus(87) + VideoPlayer.HasEpg</visible>
+ <info>PVR.TimeshiftProgressPlayPos</info>
+ <visible>Player.SeekEnabled + Control.HasFocus(87) + MusicPlayer.Content(LiveTV)</visible>
</control>
</control>
</controls>
diff --git a/addons/skin.estuary/xml/VideoOSD.xml b/addons/skin.estuary/xml/VideoOSD.xml
index 3b4a83e04b..5aeaff5bb9 100644
--- a/addons/skin.estuary/xml/VideoOSD.xml
+++ b/addons/skin.estuary/xml/VideoOSD.xml
@@ -21,15 +21,15 @@
<visible>![Window.IsVisible(SliderDialog) | Window.IsVisible(osdaudiosettings) | Window.IsVisible(osdvideosettings) | Window.IsVisible(VideoBookmarks) | Window.IsVisible(playerprocessinfo) | Window.IsVisible(osdcmssettings) | Window.IsVisible(PVROSDChannels) | Window.IsVisible(pvrchannelguide)]</visible>
<animation effect="fade" time="200">VisibleChange</animation>
<control type="label">
- <right>30</right>
+ <animation effect="slide" end="0,-20" time="150" condition="VideoPlayer.Content(LiveTV)">conditional</animation>
+ <right>20</right>
<top>0</top>
<align>right</align>
- <textoffsetx>20</textoffsetx>
<aligny>center</aligny>
<width>1000</width>
- <height>60</height>
+ <height>50</height>
<label>$VAR[VideoOSDHelpTextVar]</label>
- <visible>!Player.ShowInfo + !PVR.IsTimeShift</visible>
+ <visible>!Player.ShowInfo</visible>
</control>
<control type="group" id="200">
<control type="grouplist" id="201">
@@ -140,7 +140,7 @@
</include>
<onclick>Dialog.Close(VideoOSD)</onclick>
<onclick>ActivateWindow(pvrchannelguide)</onclick>
- <visible>VideoPlayer.Content(livetv)</visible>
+ <visible>VideoPlayer.Content(livetv) + VideoPlayer.HasEPG</visible>
</control>
<control type="radiobutton" id="700">
<include content="OSDButton">
@@ -199,47 +199,47 @@
<top>-5</top>
<left>0</left>
<width>100%</width>
- <height>25</height>
+ <height>26</height>
<texturesliderbar colordiffuse="00FFFFFF">osd/progress/nub_leftright.png</texturesliderbar>
<textureslidernib>osd/progress/nub_leftright.png</textureslidernib>
<textureslidernibfocus colordiffuse="button_focus">osd/progress/nub_leftright.png</textureslidernibfocus>
<info>Player.Progress</info>
<action>seek</action>
- <visible>!Control.HasFocus(87) + !VideoPlayer.HasEpg</visible>
+ <visible>!Control.HasFocus(87) + !VideoPlayer.Content(LiveTV)</visible>
</control>
<control type="slider">
<top>-5</top>
<left>0</left>
<width>100%</width>
- <height>25</height>
+ <height>26</height>
<texturesliderbar colordiffuse="00FFFFFF">osd/progress/nub_leftright.png</texturesliderbar>
<textureslidernib colordiffuse="button_focus">osd/progress/nub_leftright.png</textureslidernib>
<textureslidernibfocus colordiffuse="button_focus">osd/progress/nub_leftright.png</textureslidernibfocus>
<info>Player.Progress</info>
<action>seek</action>
- <visible>Control.HasFocus(87) + !VideoPlayer.HasEpg</visible>
+ <visible>Control.HasFocus(87) + !VideoPlayer.Content(LiveTV)</visible>
</control>
<control type="slider">
<top>-5</top>
<left>0</left>
<width>100%</width>
- <height>25</height>
+ <height>26</height>
<texturesliderbar colordiffuse="00FFFFFF">osd/progress/nub_leftright.png</texturesliderbar>
<textureslidernib>osd/progress/nub_leftright.png</textureslidernib>
<textureslidernibfocus colordiffuse="button_focus">osd/progress/nub_leftright.png</textureslidernibfocus>
- <info>PVR.EpgEventProgress</info>
- <visible>!Control.HasFocus(87) + VideoPlayer.HasEpg</visible>
+ <info>PVR.TimeshiftProgressPlayPos</info>
+ <visible>!Control.HasFocus(87) + VideoPlayer.Content(LiveTV)</visible>
</control>
<control type="slider">
<top>-5</top>
<left>0</left>
<width>100%</width>
- <height>25</height>
+ <height>26</height>
<texturesliderbar colordiffuse="00FFFFFF">osd/progress/nub_leftright.png</texturesliderbar>
<textureslidernib colordiffuse="button_focus">osd/progress/nub_leftright.png</textureslidernib>
<textureslidernibfocus colordiffuse="button_focus">osd/progress/nub_leftright.png</textureslidernibfocus>
- <info>PVR.EpgEventProgress</info>
- <visible>Control.HasFocus(87) + VideoPlayer.HasEpg</visible>
+ <info>PVR.TimeshiftProgressPlayPos</info>
+ <visible>Control.HasFocus(87) + VideoPlayer.Content(LiveTV)</visible>
</control>
</control>
</control>
diff --git a/lib/libUPnP/Neptune/Source/System/Bsd/NptBsdSockets.cpp b/lib/libUPnP/Neptune/Source/System/Bsd/NptBsdSockets.cpp
index b1dc45a52a..638446d776 100644
--- a/lib/libUPnP/Neptune/Source/System/Bsd/NptBsdSockets.cpp
+++ b/lib/libUPnP/Neptune/Source/System/Bsd/NptBsdSockets.cpp
@@ -131,48 +131,19 @@ static NPT_WinsockSystem& WinsockInitializer = NPT_WinsockSystem::Initializer;
#undef SetPort
#endif
-#ifndef TARGET_WINDOWS_STORE
-#if !defined(EWOULDBLOCK)
#define EWOULDBLOCK WSAEWOULDBLOCK
-#endif
-#if !defined(EINPROGRESS)
#define EINPROGRESS WSAEINPROGRESS
-#endif
-#if !defined(ECONNREFUSED)
#define ECONNREFUSED WSAECONNREFUSED
-#endif
-#if !defined(ECONNABORTED)
#define ECONNABORTED WSAECONNABORTED
-#endif
-#if !defined(ECONNRESET)
#define ECONNRESET WSAECONNRESET
-#endif
-#if !defined(ETIMEDOUT)
#define ETIMEDOUT WSAETIMEDOUT
-#endif
-#if !defined(ENETRESET)
#define ENETRESET WSAENETRESET
-#endif
-#if !defined(EADDRINUSE)
#define EADDRINUSE WSAEADDRINUSE
-#endif
-#if !defined(ENETDOWN)
#define ENETDOWN WSAENETDOWN
-#endif
-#if !defined(ENETUNREACH)
#define ENETUNREACH WSAENETUNREACH
-#endif
-#if !defined(EHOSTUNREACH)
-#define EHOSTUNREACH WSAEHOSTUNREACH
-#endif
-#if !defined(ENOTCONN)
#define ENOTCONN WSAENOTCONN
-#endif
-#endif
#if !defined(EAGAIN)
#define EAGAIN WSAEWOULDBLOCK
-#endif
-#if !defined(EINTR)
#define EINTR WSAEINTR
#endif
#if !defined(SHUT_RDWR)
diff --git a/lib/libUPnP/patches/0045-platinum-win10-uwp-fixes.patch b/lib/libUPnP/patches/0045-platinum-win10-uwp-fixes.patch
index 752c1d4301..22034321a2 100644
--- a/lib/libUPnP/patches/0045-platinum-win10-uwp-fixes.patch
+++ b/lib/libUPnP/patches/0045-platinum-win10-uwp-fixes.patch
@@ -4,17 +4,16 @@ Date: Fri, 2 Jun 2017 16:34:58 +0300
Subject: [PATCH] [win10] uwp fixes libUPnP
---
- lib/libUPnP/CMakeLists.txt | 8 ++++--
lib/libUPnP/Neptune/Source/Core/NptConfig.h | 13 ++++++++++
lib/libUPnP/Neptune/Source/Core/NptUtils.cpp | 30 ++++++++++++++++++++++
lib/libUPnP/Neptune/Source/Core/NptUtils.h | 7 +++++
- .../Neptune/Source/System/Bsd/NptBsdSockets.cpp | 2 ++
.../Source/System/StdC/NptStdcEnvironment.cpp | 2 +-
.../System/Win32/NptWin32DynamicLibraries.cpp | 4 +++
.../Source/System/Win32/NptWin32MessageQueue.cpp | 3 ++-
.../Source/System/Win32/NptWin32MessageQueue.h | 3 +++
+ .../Neptune/Source/System/Win32/NptWin32Queue.cpp | 6 ++---
.../Source/System/Win32/NptWin32SerialPort.cpp | 2 ++
- 10 files changed, 70 insertions(+), 4 deletions(-)
+ 9 files changed, 65 insertions(+), 5 deletions(-)
diff --git a/lib/libUPnP/Neptune/Source/Core/NptConfig.h b/lib/libUPnP/Neptune/Source/Core/NptConfig.h
index d51f67f94e..130d5cc33b 100644
@@ -121,26 +120,6 @@ index 3a06d497f4..89b2e29812 100644
+#endif
+
#endif // _NPT_UTILS_H_
-diff --git a/lib/libUPnP/Neptune/Source/System/Bsd/NptBsdSockets.cpp b/lib/libUPnP/Neptune/Source/System/Bsd/NptBsdSockets.cpp
-index ee86dbf4b0..a42dfbfb85 100644
---- a/lib/libUPnP/Neptune/Source/System/Bsd/NptBsdSockets.cpp
-+++ b/lib/libUPnP/Neptune/Source/System/Bsd/NptBsdSockets.cpp
-@@ -131,6 +131,7 @@ static NPT_WinsockSystem& WinsockInitializer = NPT_WinsockSystem::Initializer;
- #undef SetPort
- #endif
-
-+#ifndef TARGET_WINDOWS_STORE
- #if !defined(EWOULDBLOCK)
- #define EWOULDBLOCK WSAEWOULDBLOCK
- #endif
-@@ -167,6 +168,7 @@ static NPT_WinsockSystem& WinsockInitializer = NPT_WinsockSystem::Initializer;
- #if !defined(ENOTCONN)
- #define ENOTCONN WSAENOTCONN
- #endif
-+#endif
- #if !defined(EAGAIN)
- #define EAGAIN WSAEWOULDBLOCK
- #endif
diff --git a/lib/libUPnP/Neptune/Source/System/StdC/NptStdcEnvironment.cpp b/lib/libUPnP/Neptune/Source/System/StdC/NptStdcEnvironment.cpp
index c9f9939d2b..f700b2212b 100644
--- a/lib/libUPnP/Neptune/Source/System/StdC/NptStdcEnvironment.cpp
diff --git a/lib/libUPnP/patches/0047-neptune-fix-device-discovery-on-windows.patch b/lib/libUPnP/patches/0047-neptune-fix-device-discovery-on-windows.patch
new file mode 100644
index 0000000000..391ee3b302
--- /dev/null
+++ b/lib/libUPnP/patches/0047-neptune-fix-device-discovery-on-windows.patch
@@ -0,0 +1,49 @@
+--- a/lib/libUPnP/Neptune/Source/System/Bsd/NptBsdSockets.cpp
++++ b/lib/libUPnP/Neptune/Source/System/Bsd/NptBsdSockets.cpp
+@@ -131,46 +131,19 @@
+ #undef SetPort
+ #endif
+
+-#if !defined(EWOULDBLOCK)
+ #define EWOULDBLOCK WSAEWOULDBLOCK
+-#endif
+-#if !defined(EINPROGRESS)
+ #define EINPROGRESS WSAEINPROGRESS
+-#endif
+-#if !defined(ECONNREFUSED)
+ #define ECONNREFUSED WSAECONNREFUSED
+-#endif
+-#if !defined(ECONNABORTED)
+ #define ECONNABORTED WSAECONNABORTED
+-#endif
+-#if !defined(ECONNRESET)
+ #define ECONNRESET WSAECONNRESET
+-#endif
+-#if !defined(ETIMEDOUT)
+ #define ETIMEDOUT WSAETIMEDOUT
+-#endif
+-#if !defined(ENETRESET)
+ #define ENETRESET WSAENETRESET
+-#endif
+-#if !defined(EADDRINUSE)
+ #define EADDRINUSE WSAEADDRINUSE
+-#endif
+-#if !defined(ENETDOWN)
+ #define ENETDOWN WSAENETDOWN
+-#endif
+-#if !defined(ENETUNREACH)
+ #define ENETUNREACH WSAENETUNREACH
+-#endif
+-#if !defined(EHOSTUNREACH)
+-#define EHOSTUNREACH WSAEHOSTUNREACH
+-#endif
+-#if !defined(ENOTCONN)
+ #define ENOTCONN WSAENOTCONN
+-#endif
+ #if !defined(EAGAIN)
+ #define EAGAIN WSAEWOULDBLOCK
+-#endif
+-#if !defined(EINTR)
+ #define EINTR WSAEINTR
+ #endif
+ #if !defined(SHUT_RDWR)
diff --git a/xbmc/GUIInfoManager.cpp b/xbmc/GUIInfoManager.cpp
index 381082a4d3..95677356a7 100644
--- a/xbmc/GUIInfoManager.cpp
+++ b/xbmc/GUIInfoManager.cpp
@@ -4558,6 +4558,31 @@ const infomap playlist[] = {{ "length", PLAYLIST_LENGTH },
/// _boolean_,
/// Returns true if PVR is currently playing a channel and if this channel is currently recorded.
/// }
+/// \table_row3{ <b>`PVR.TimeshiftProgressPlayPos`</b>,
+/// \anchor PVR_TimeshiftProgressPlayPos
+/// _integer_,
+/// Returns the percentage of the current play position within the PVR timeshift progress.
+/// }
+/// \table_row3{ <b>`PVR.TimeshiftProgressEpgStart`</b>,
+/// \anchor PVR_TimeshiftProgressEpgStart
+/// _integer_,
+/// Returns the percentage of the start of the currently playing epg event within the PVR timeshift progress.
+/// }
+/// \table_row3{ <b>`PVR.TimeshiftProgressEpgEnd`</b>,
+/// \anchor PVR_TimeshiftProgressEpgEnd
+/// _integer_,
+/// Returns the percentage of the end of the currently playing epg event within the PVR timeshift progress.
+/// }
+/// \table_row3{ <b>`PVR.TimeshiftProgressBufferStart`</b>,
+/// \anchor PVR_TimeshiftProgressBufferStart
+/// _integer_,
+/// Returns the percentage of the start of the timeshift buffer within the PVR timeshift progress.
+/// }
+/// \table_row3{ <b>`PVR.TimeshiftProgressBufferEnd`</b>,
+/// \anchor PVR_TimeshiftProgressBufferEnd
+/// _integer_,
+/// Returns the percentage of the end of the timeshift buffer within the PVR timeshift progress.
+/// }
/// \table_end
///
/// -----------------------------------------------------------------------------
@@ -4632,7 +4657,12 @@ const infomap pvr[] = {{ "isrecording", PVR_IS_RECORDING
{ "hasnonrecordingradiotimer", PVR_HAS_NONRECORDING_RADIO_TIMER },
{ "channelnumberinput", PVR_CHANNEL_NUMBER_INPUT },
{ "canrecordplayingchannel", PVR_CAN_RECORD_PLAYING_CHANNEL },
- { "isrecordingplayingchannel", PVR_IS_RECORDING_PLAYING_CHANNEL }};
+ { "isrecordingplayingchannel", PVR_IS_RECORDING_PLAYING_CHANNEL },
+ { "timeshiftprogressplaypos", PVR_TIMESHIFT_PROGRESS_PLAY_POS },
+ { "timeshiftprogressepgstart", PVR_TIMESHIFT_PROGRESS_EPG_START },
+ { "timeshiftprogressepgend", PVR_TIMESHIFT_PROGRESS_EPG_END },
+ { "timeshiftprogressbufferstart", PVR_TIMESHIFT_PROGRESS_BUFFER_START },
+ { "timeshiftprogressbufferend", PVR_TIMESHIFT_PROGRESS_BUFFER_END }};
/// \page modules__General__List_of_gui_access
/// \section modules__General__List_of_gui_access_PvrTimes PvrTimes
@@ -4774,6 +4804,51 @@ const infomap pvr[] = {{ "isrecording", PVR_IS_RECORDING
/// Added with Leia: (secs)\, (mins)\, (hours) for total time values and (m).
/// Example: 3661 seconds => h=1\, hh=01\, m=1\, mm=01\, ss=01\, hours=1\, mins=61\, secs=3661
/// }
+/// \table_row3{ <b>`PVR.TimeshiftProgressDuration`</b>,
+/// \anchor PVR_TimeshiftProgressDuration
+/// _string_,
+/// Returns the duration of the PVR timeshift progress in the
+/// format hh:mm:ss. hh: will be omitted if hours value is zero.
+/// }
+/// \table_row3{ <b>`PVR.TimeshiftProgressDuration(format)`</b>,
+/// \anchor PVR_TimeshiftProgressDuration_format
+/// _string_,
+/// Returns the duration of the PVR timeshift progress in different formats:
+/// Hours (hh)\, minutes (mm) or seconds (ss).
+/// Also supported: (hh:mm)\, (mm:ss)\, (hh:mm:ss)\, (h:mm:ss).
+/// Added with Leia: (secs)\, (mins)\, (hours) for total time values and (m).
+/// Example: 3661 seconds => h=1\, hh=01\, m=1\, mm=01\, ss=01\, hours=1\, mins=61\, secs=3661
+/// }
+/// \table_row3{ <b>`PVR.TimeshiftProgressStartTime`</b>,
+/// \anchor PVR_TimeshiftProgressStartTime
+/// _string_,
+/// Returns the start time of the PVR timeshift progress in the
+/// format hh:mm:ss. hh: will be omitted if hours value is zero.
+/// }
+/// \table_row3{ <b>`PVR.TimeshiftProgressStartTime(format)`</b>,
+/// \anchor PVR_TimeshiftProgressStartTime_format
+/// _string_,
+/// Returns the start time of the PVR timeshift progress in different formats:
+/// Hours (hh)\, minutes (mm) or seconds (ss).
+/// Also supported: (hh:mm)\, (mm:ss)\, (hh:mm:ss)\, (h:mm:ss).
+/// Added with Leia: (secs)\, (mins)\, (hours) for total time values and (m).
+/// Example: 3661 seconds => h=1\, hh=01\, m=1\, mm=01\, ss=01\, hours=1\, mins=61\, secs=3661
+/// }
+/// \table_row3{ <b>`PVR.TimeshiftProgressEndTime`</b>,
+/// \anchor PVR_TimeshiftProgressEndTime
+/// _string_,
+/// Returns the end time of the PVR timeshift progress in the
+/// format hh:mm:ss. hh: will be omitted if hours value is zero.
+/// }
+/// \table_row3{ <b>`PVR.TimeshiftProgressEndTime(format)`</b>,
+/// \anchor PVR_TimeshiftProgressEndTime_format
+/// _string_,
+/// Returns the end time of the PVR timeshift progress in different formats:
+/// Hours (hh)\, minutes (mm) or seconds (ss).
+/// Also supported: (hh:mm)\, (mm:ss)\, (hh:mm:ss)\, (h:mm:ss).
+/// Added with Leia: (secs)\, (mins)\, (hours) for total time values and (m).
+/// Example: 3661 seconds => h=1\, hh=01\, m=1\, mm=01\, ss=01\, hours=1\, mins=61\, secs=3661
+/// }
/// \table_end
///
/// -----------------------------------------------------------------------------
@@ -4786,7 +4861,10 @@ const infomap pvr_times[] = {{ "epgeventduration", PVR_EPG_EVENT_DURA
{ "timeshiftstart", PVR_TIMESHIFT_START_TIME },
{ "timeshiftend", PVR_TIMESHIFT_END_TIME },
{ "timeshiftcur", PVR_TIMESHIFT_PLAY_TIME },
- { "timeshiftoffset", PVR_TIMESHIFT_OFFSET }};
+ { "timeshiftoffset", PVR_TIMESHIFT_OFFSET },
+ { "timeshiftprogressduration", PVR_TIMESHIFT_PROGRESS_DURATION },
+ { "timeshiftprogressstarttime", PVR_TIMESHIFT_PROGRESS_START_TIME },
+ { "timeshiftprogressendtime", PVR_TIMESHIFT_PROGRESS_END_TIME }};
/// \page modules__General__List_of_gui_access
/// \section modules__General__List_of_gui_access_RDS Radio RDS
diff --git a/xbmc/addons/PVRClient.cpp b/xbmc/addons/PVRClient.cpp
index 4805ccc9d6..b7a64e07d1 100644
--- a/xbmc/addons/PVRClient.cpp
+++ b/xbmc/addons/PVRClient.cpp
@@ -1339,15 +1339,6 @@ PVR_ERROR CPVRClient::CanSeekStream(bool &bCanSeek) const
});
}
-PVR_ERROR CPVRClient::IsTimeshifting(bool &bTimeshifting) const
-{
- bTimeshifting = false;
- return DoAddonCall(__FUNCTION__, [&bTimeshifting](const AddonInstance* addon) {
- bTimeshifting = addon->IsTimeshifting();
- return PVR_ERROR_NO_ERROR;
- });
-}
-
PVR_ERROR CPVRClient::GetStreamTimes(PVR_STREAM_TIMES *times)
{
return DoAddonCall(__FUNCTION__, [&times](const AddonInstance* addon) {
diff --git a/xbmc/addons/PVRClient.h b/xbmc/addons/PVRClient.h
index a25304bcca..ced1d95858 100644
--- a/xbmc/addons/PVRClient.h
+++ b/xbmc/addons/PVRClient.h
@@ -799,13 +799,6 @@ namespace PVR
static const char *ToString(const PVR_ERROR error);
/*!
- * @brief Check whether timeshifting is active for the currently playing stream, if any.
- * @param bTimeshifting True, if timeshifting is active, false otherwise.
- * @return PVR_ERROR_NO_ERROR on success, respective error code otherwise.
- */
- PVR_ERROR IsTimeshifting(bool &bTimeshifting) const;
-
- /*!
* @brief Check whether the currently playing stream, if any, is a real-time stream.
* @param bRealTime True if real-time, false otherwise.
* @return PVR_ERROR_NO_ERROR on success, respective error code otherwise.
diff --git a/xbmc/dialogs/GUIDialogSeekBar.cpp b/xbmc/dialogs/GUIDialogSeekBar.cpp
index e646097e02..138fa83621 100644
--- a/xbmc/dialogs/GUIDialogSeekBar.cpp
+++ b/xbmc/dialogs/GUIDialogSeekBar.cpp
@@ -17,6 +17,7 @@
#define POPUP_SEEK_PROGRESS 401
#define POPUP_SEEK_EPG_EVENT_PROGRESS 402
+#define POPUP_SEEK_TIMESHIFT_PROGRESS 403
CGUIDialogSeekBar::CGUIDialogSeekBar(void)
: CGUIDialog(WINDOW_DIALOG_SEEK_BAR, "DialogSeekBar.xml", DialogModalityType::MODELESS)
@@ -35,7 +36,9 @@ bool CGUIDialogSeekBar::OnMessage(CGUIMessage& message)
return CGUIDialog::OnMessage(message);
case GUI_MSG_ITEM_SELECT:
if (message.GetSenderId() == GetID() &&
- (message.GetControlId() == POPUP_SEEK_PROGRESS || message.GetControlId() == POPUP_SEEK_EPG_EVENT_PROGRESS))
+ (message.GetControlId() == POPUP_SEEK_PROGRESS ||
+ message.GetControlId() == POPUP_SEEK_EPG_EVENT_PROGRESS ||
+ message.GetControlId() == POPUP_SEEK_TIMESHIFT_PROGRESS))
return CGUIDialog::OnMessage(message);
break;
case GUI_MSG_REFRESH_TIMER:
@@ -52,68 +55,83 @@ void CGUIDialogSeekBar::FrameMove()
return;
}
- unsigned int percent = g_application.GetAppPlayer().GetSeekHandler().InProgress()
- ? std::lrintf(GetSeekPercent())
- : std::lrintf(g_application.GetPercentage());
+ int progress = GetProgress();
+ if (progress != m_lastProgress)
+ CONTROL_SELECT_ITEM(POPUP_SEEK_PROGRESS, m_lastProgress = progress);
- if (percent != m_lastPercent)
- CONTROL_SELECT_ITEM(POPUP_SEEK_PROGRESS, m_lastPercent = percent);
+ int epgEventProgress = GetEpgEventProgress();
+ if (epgEventProgress != m_lastEpgEventProgress)
+ CONTROL_SELECT_ITEM(POPUP_SEEK_EPG_EVENT_PROGRESS, m_lastEpgEventProgress = epgEventProgress);
- unsigned int epgEventPercent = g_application.GetAppPlayer().GetSeekHandler().InProgress()
- ? GetEpgEventSeekPercent()
- : GetEpgEventProgress();
-
- if (epgEventPercent != m_lastEpgEventPercent)
- CONTROL_SELECT_ITEM(POPUP_SEEK_EPG_EVENT_PROGRESS, m_lastEpgEventPercent = epgEventPercent);
+ int timeshiftProgress = GetTimeshiftProgress();
+ if (timeshiftProgress != m_lastTimeshiftProgress)
+ CONTROL_SELECT_ITEM(POPUP_SEEK_TIMESHIFT_PROGRESS, m_lastTimeshiftProgress = timeshiftProgress);
CGUIDialog::FrameMove();
}
-float CGUIDialogSeekBar::GetSeekPercent() const
+int CGUIDialogSeekBar::GetProgress() const
{
- int totaltime = std::lrint(g_application.GetTotalTime());
- if (totaltime == 0)
- return 0.0f;
+ CGUIInfoManager& infoMgr = CServiceBroker::GetGUI()->GetInfoManager();
- float percentPlayTime = static_cast<float>(std::lrint(g_application.GetTime() * 1000)) / totaltime * 0.1f;
- float percentPerSecond = 100.0f / static_cast<float>(totaltime);
- float percent = percentPlayTime + percentPerSecond * g_application.GetAppPlayer().GetSeekHandler().GetSeekSize();
+ int progress = 0;
- if (percent > 100.0f)
- percent = 100.0f;
- if (percent < 0.0f)
- percent = 0.0f;
+ if (g_application.GetAppPlayer().GetSeekHandler().GetSeekSize() != 0)
+ infoMgr.GetInt(progress, PLAYER_SEEKBAR);
+ else
+ infoMgr.GetInt(progress, PLAYER_PROGRESS);
- return percent;
+ return progress;
}
int CGUIDialogSeekBar::GetEpgEventProgress() const
{
- int value = 0;
- CServiceBroker::GetGUI()->GetInfoManager().GetInt(value, PVR_EPG_EVENT_PROGRESS);
- return value;
-}
+ CGUIInfoManager& infoMgr = CServiceBroker::GetGUI()->GetInfoManager();
+
+ int progress = 0;
+ infoMgr.GetInt(progress, PVR_EPG_EVENT_PROGRESS);
-int CGUIDialogSeekBar::GetEpgEventSeekPercent() const
-{
int seekSize = g_application.GetAppPlayer().GetSeekHandler().GetSeekSize();
if (seekSize != 0)
{
- CGUIInfoManager& infoMgr = CServiceBroker::GetGUI()->GetInfoManager();
-
- int progress = 0;
- infoMgr.GetInt(progress, PVR_EPG_EVENT_PROGRESS);
-
int total = 0;
infoMgr.GetInt(total, PVR_EPG_EVENT_DURATION);
float totalTime = static_cast<float>(total);
+ if (totalTime == 0.0f)
+ return 0;
+
float percentPerSecond = 100.0f / totalTime;
float percent = progress + percentPerSecond * seekSize;
+ percent = std::max(0.0f, std::min(percent, 100.0f));
return std::lrintf(percent);
}
- else
+
+ return progress;
+}
+
+int CGUIDialogSeekBar::GetTimeshiftProgress() const
+{
+ CGUIInfoManager& infoMgr = CServiceBroker::GetGUI()->GetInfoManager();
+
+ int progress = 0;
+ infoMgr.GetInt(progress, PVR_TIMESHIFT_PROGRESS_PLAY_POS);
+
+ int seekSize = g_application.GetAppPlayer().GetSeekHandler().GetSeekSize();
+ if (seekSize != 0)
{
- return GetEpgEventProgress();
+ int total = 0;
+ infoMgr.GetInt(total, PVR_TIMESHIFT_PROGRESS_DURATION);
+
+ float totalTime = static_cast<float>(total);
+ if (totalTime == 0.0f)
+ return 0;
+
+ float percentPerSecond = 100.0f / totalTime;
+ float percent = progress + percentPerSecond * seekSize;
+ percent = std::max(0.0f, std::min(percent, 100.0f));
+ return std::lrintf(percent);
}
+
+ return progress;
}
diff --git a/xbmc/dialogs/GUIDialogSeekBar.h b/xbmc/dialogs/GUIDialogSeekBar.h
index f50563a522..314bf2724e 100644
--- a/xbmc/dialogs/GUIDialogSeekBar.h
+++ b/xbmc/dialogs/GUIDialogSeekBar.h
@@ -18,10 +18,11 @@ public:
bool OnMessage(CGUIMessage& message) override;
void FrameMove() override;
private:
- float GetSeekPercent() const;
+ int GetProgress() const;
int GetEpgEventProgress() const;
- int GetEpgEventSeekPercent() const;
+ int GetTimeshiftProgress() const;
- unsigned int m_lastPercent = ~0U;
- unsigned int m_lastEpgEventPercent = ~0U;
+ int m_lastProgress = 0;
+ int m_lastEpgEventProgress = 0;
+ int m_lastTimeshiftProgress = 0;
};
diff --git a/xbmc/guilib/GUIControlFactory.cpp b/xbmc/guilib/GUIControlFactory.cpp
index 4cefeddb5a..253e63d790 100644
--- a/xbmc/guilib/GUIControlFactory.cpp
+++ b/xbmc/guilib/GUIControlFactory.cpp
@@ -667,6 +667,7 @@ CGUIControl* CGUIControlFactory::Create(int parentID, const CRect &rect, TiXmlEl
bool defaultAlways = false;
std::string strTmp;
int singleInfo = 0;
+ int singleInfo2 = 0;
std::string strLabel;
int iUrlSet=0;
std::string toggleSelect;
@@ -855,6 +856,8 @@ CGUIControl* CGUIControlFactory::Create(int parentID, const CRect &rect, TiXmlEl
std::string infoString;
if (XMLUtils::GetString(pControlNode, "info", infoString))
singleInfo = CServiceBroker::GetGUI()->GetInfoManager().TranslateString(infoString);
+ if (XMLUtils::GetString(pControlNode, "info2", infoString))
+ singleInfo2 = CServiceBroker::GetGUI()->GetInfoManager().TranslateString(infoString);
GetTexture(pControlNode, "texturefocus", textureFocus);
GetTexture(pControlNode, "texturenofocus", textureNoFocus);
@@ -1288,7 +1291,7 @@ CGUIControl* CGUIControlFactory::Create(int parentID, const CRect &rect, TiXmlEl
textureBackground, textureLeft, textureMid, textureRight,
textureOverlay, bReveal);
- static_cast<CGUIProgressControl*>(control)->SetInfo(singleInfo);
+ static_cast<CGUIProgressControl*>(control)->SetInfo(singleInfo, singleInfo2);
}
break;
case CGUIControl::GUICONTROL_IMAGE:
diff --git a/xbmc/guilib/GUIProgressControl.cpp b/xbmc/guilib/GUIProgressControl.cpp
index 548ae7a033..4b60061d7a 100644
--- a/xbmc/guilib/GUIProgressControl.cpp
+++ b/xbmc/guilib/GUIProgressControl.cpp
@@ -177,9 +177,10 @@ void CGUIProgressControl::SetInvalid()
m_guiOverlay.SetInvalid();
}
-void CGUIProgressControl::SetInfo(int iInfo)
+void CGUIProgressControl::SetInfo(int iInfo, int iInfo2)
{
m_iInfoCode = iInfo;
+ m_iInfoCode2 = iInfo2;
}
bool CGUIProgressControl::UpdateColors()
@@ -220,17 +221,15 @@ bool CGUIProgressControl::UpdateLayout(void)
if (m_guiLeft.GetFileName().empty() && m_guiRight.GetFileName().empty())
{ // rendering without left and right image - fill the mid image completely
- float width = m_fPercent * m_width * 0.01f;
- float offset = fabs(fScaleY * 0.5f * (m_guiMid.GetTextureHeight() - m_guiBackground.GetTextureHeight()));
- if (offset > 0) // Center texture to the background if necessary
- bChanged |= m_guiMid.SetPosition(posX, posY + offset);
- else
- bChanged |= m_guiMid.SetPosition(posX, posY);
+ float width = (m_fPercent - m_fPercent2) * m_width * 0.01f;
+ float offsetX = m_fPercent2 * m_width * 0.01f;;
+ float offsetY = fabs(fScaleY * 0.5f * (m_guiMid.GetTextureHeight() - m_guiBackground.GetTextureHeight()));
+ bChanged |= m_guiMid.SetPosition(posX + (offsetX > 0 ? offsetX : 0), posY + (offsetY > 0 ? offsetY : 0));
bChanged |= m_guiMid.SetHeight(fScaleY * m_guiMid.GetTextureHeight());
if (m_bReveal)
{
bChanged |= m_guiMid.SetWidth(m_width);
- float x = posX, y = posY + offset, w = width, h = fScaleY * m_guiMid.GetTextureHeight();
+ float x = posX + offsetX, y = posY + offsetY, w = width, h = fScaleY * m_guiMid.GetTextureHeight();
CRect rect(x, y, x + w, y + h);
if (rect != m_guiMidClipRect)
{
@@ -246,30 +245,25 @@ bool CGUIProgressControl::UpdateLayout(void)
}
else
{
- float fWidth = m_fPercent;
+ float fWidth = m_fPercent - m_fPercent2;
float fFullWidth = m_guiBackground.GetTextureWidth() - m_guiLeft.GetTextureWidth() - m_guiRight.GetTextureWidth();
fWidth /= 100.0f;
fWidth *= fFullWidth;
- float offset = fabs(fScaleY * 0.5f * (m_guiLeft.GetTextureHeight() - m_guiBackground.GetTextureHeight()));
- if (offset > 0) // Center texture to the background if necessary
- bChanged |= m_guiLeft.SetPosition(posX, posY + offset);
- else
- bChanged |= m_guiLeft.SetPosition(posX, posY);
+ float offsetY = fabs(fScaleY * 0.5f * (m_guiLeft.GetTextureHeight() - m_guiBackground.GetTextureHeight()));
+ bChanged |= m_guiLeft.SetPosition(posX, posY + (offsetY > 0 ? offsetY : 0));
bChanged |= m_guiLeft.SetHeight(fScaleY * m_guiLeft.GetTextureHeight());
bChanged |= m_guiLeft.SetWidth(fScaleX * m_guiLeft.GetTextureWidth());
posX += fScaleX * m_guiLeft.GetTextureWidth();
- offset = fabs(fScaleY * 0.5f * (m_guiMid.GetTextureHeight() - m_guiBackground.GetTextureHeight()));
- if (offset > 0) // Center texture to the background if necessary
- bChanged |= m_guiMid.SetPosition(posX, posY + offset);
- else
- bChanged |= m_guiMid.SetPosition(posX, posY);
+ float offsetX = m_fPercent2 * fWidth * 0.01f;;
+ offsetY = fabs(fScaleY * 0.5f * (m_guiMid.GetTextureHeight() - m_guiBackground.GetTextureHeight()));
+ bChanged |= m_guiMid.SetPosition(posX + offsetX, posY + (offsetY > 0 ? offsetY : 0));
bChanged |= m_guiMid.SetHeight(fScaleY * m_guiMid.GetTextureHeight());
if (m_bReveal)
{
bChanged |= m_guiMid.SetWidth(fScaleX * fFullWidth);
- float x = posX, y = posY + offset, w = fScaleX * fWidth, h = fScaleY * m_guiMid.GetTextureHeight();
+ float x = posX + offsetX, y = posY + offsetY, w = fScaleX * fWidth, h = fScaleY * m_guiMid.GetTextureHeight();
CRect rect(x, y, x + w, y + h);
if (rect != m_guiMidClipRect)
{
@@ -285,11 +279,8 @@ bool CGUIProgressControl::UpdateLayout(void)
posX += fWidth * fScaleX;
- offset = fabs(fScaleY * 0.5f * (m_guiRight.GetTextureHeight() - m_guiBackground.GetTextureHeight()));
- if (offset > 0) // Center texture to the background if necessary
- bChanged |= m_guiRight.SetPosition(posX, posY + offset);
- else
- bChanged |= m_guiRight.SetPosition(posX, posY);
+ offsetY = fabs(fScaleY * 0.5f * (m_guiRight.GetTextureHeight() - m_guiBackground.GetTextureHeight()));
+ bChanged |= m_guiRight.SetPosition(posX, posY + (offsetY > 0 ? offsetY : 0));
bChanged |= m_guiRight.SetHeight(fScaleY * m_guiRight.GetTextureHeight());
bChanged |= m_guiRight.SetWidth(fScaleX * m_guiRight.GetTextureWidth());
}
@@ -312,10 +303,13 @@ void CGUIProgressControl::UpdateInfo(const CGUIListItem *item)
{
int value;
if (CServiceBroker::GetGUI()->GetInfoManager().GetInt(value, m_iInfoCode, m_parentID, item))
- m_fPercent = (float)value;
-
- if (m_fPercent < 0.0f) m_fPercent = 0.0f;
- if (m_fPercent > 100.0f) m_fPercent = 100.0f;
+ m_fPercent = std::max(0.0f, std::min(static_cast<float>(value), 100.0f));
+ }
+ if (m_iInfoCode2)
+ {
+ int value;
+ if (CServiceBroker::GetGUI()->GetInfoManager().GetInt(value, m_iInfoCode2, m_parentID, item))
+ m_fPercent2 = std::max(0.0f, std::min(static_cast<float>(value), 100.0f));
}
}
}
diff --git a/xbmc/guilib/GUIProgressControl.h b/xbmc/guilib/GUIProgressControl.h
index 66cf65afca..2b4ccfb38a 100644
--- a/xbmc/guilib/GUIProgressControl.h
+++ b/xbmc/guilib/GUIProgressControl.h
@@ -42,7 +42,7 @@ public:
bool OnMessage(CGUIMessage& message) override;
void SetPosition(float posX, float posY) override;
void SetPercentage(float fPercent);
- void SetInfo(int iInfo);
+ void SetInfo(int iInfo, int iInfo2 = 0);
int GetInfo() const {return m_iInfoCode;};
float GetPercentage() const;
@@ -59,7 +59,9 @@ protected:
CRect m_guiMidClipRect;
int m_iInfoCode;
+ int m_iInfoCode2 = 0;
float m_fPercent;
+ float m_fPercent2 = 0.0f;
bool m_bReveal;
bool m_bChanged;
};
diff --git a/xbmc/guilib/guiinfo/GUIInfoLabels.h b/xbmc/guilib/guiinfo/GUIInfoLabels.h
index 7e5c7b7aec..413beacaa1 100644
--- a/xbmc/guilib/guiinfo/GUIInfoLabels.h
+++ b/xbmc/guilib/guiinfo/GUIInfoLabels.h
@@ -584,7 +584,15 @@
#define PVR_EPG_EVENT_FINISH_TIME (PVR_STRINGS_START + 61)
#define PVR_TIMESHIFT_OFFSET (PVR_STRINGS_START + 62)
#define PVR_EPG_EVENT_SEEK_TIME (PVR_STRINGS_START + 63)
-#define PVR_STRINGS_END PVR_EPG_EVENT_SEEK_TIME
+#define PVR_TIMESHIFT_PROGRESS_PLAY_POS (PVR_STRINGS_START + 64)
+#define PVR_TIMESHIFT_PROGRESS_DURATION (PVR_STRINGS_START + 65)
+#define PVR_TIMESHIFT_PROGRESS_EPG_START (PVR_STRINGS_START + 66)
+#define PVR_TIMESHIFT_PROGRESS_EPG_END (PVR_STRINGS_START + 67)
+#define PVR_TIMESHIFT_PROGRESS_BUFFER_START (PVR_STRINGS_START + 68)
+#define PVR_TIMESHIFT_PROGRESS_BUFFER_END (PVR_STRINGS_START + 69)
+#define PVR_TIMESHIFT_PROGRESS_START_TIME (PVR_STRINGS_START + 70)
+#define PVR_TIMESHIFT_PROGRESS_END_TIME (PVR_STRINGS_START + 71)
+#define PVR_STRINGS_END PVR_TIMESHIFT_PROGRESS_END_TIME
#define RDS_DATA_START 1400
#define RDS_HAS_RDS (RDS_DATA_START)
diff --git a/xbmc/guilib/guiinfo/PlayerGUIInfo.cpp b/xbmc/guilib/guiinfo/PlayerGUIInfo.cpp
index c721ad60d1..572edc22c3 100644
--- a/xbmc/guilib/guiinfo/PlayerGUIInfo.cpp
+++ b/xbmc/guilib/guiinfo/PlayerGUIInfo.cpp
@@ -66,12 +66,7 @@ float CPlayerGUIInfo::GetSeekPercent() const
float fPercentPlayTime = static_cast<float>(GetPlayTime() * 1000) / iTotal * 0.1f;
float fPercentPerSecond = 100.0f / static_cast<float>(iTotal);
float fPercent = fPercentPlayTime + fPercentPerSecond * g_application.GetAppPlayer().GetSeekHandler().GetSeekSize();
-
- if (fPercent > 100.0f)
- fPercent = 100.0f;
- if (fPercent < 0.0f)
- fPercent = 0.0f;
-
+ fPercent = std::max(0.0f, std::min(fPercent, 100.0f));
return fPercent;
}
diff --git a/xbmc/pvr/CMakeLists.txt b/xbmc/pvr/CMakeLists.txt
index a1098e7a1e..37e22a1fca 100644
--- a/xbmc/pvr/CMakeLists.txt
+++ b/xbmc/pvr/CMakeLists.txt
@@ -10,7 +10,8 @@ set(SOURCES PVRActionListener.cpp
PVRJobs.cpp
PVRGUIChannelNavigator.cpp
PVRGUIProgressHandler.cpp
- PVRGUITimerInfo.cpp)
+ PVRGUITimerInfo.cpp
+ PVRGUITimesInfo.cpp)
set(HEADERS PVRActionListener.h
PVRDatabase.h
@@ -26,6 +27,7 @@ set(HEADERS PVRActionListener.h
PVRJobs.h
PVRGUIChannelNavigator.h
PVRGUIProgressHandler.h
- PVRGUITimerInfo.h)
+ PVRGUITimerInfo.h
+ PVRGUITimesInfo.h)
core_add_library(pvr)
diff --git a/xbmc/pvr/PVRGUIInfo.cpp b/xbmc/pvr/PVRGUIInfo.cpp
index 370bd7b0c3..1907a27671 100644
--- a/xbmc/pvr/PVRGUIInfo.cpp
+++ b/xbmc/pvr/PVRGUIInfo.cpp
@@ -14,7 +14,6 @@
#include "Application.h"
#include "GUIInfoManager.h"
#include "ServiceBroker.h"
-#include "cores/DataCacheCore.h"
#include "guilib/GUIComponent.h"
#include "guilib/LocalizeStrings.h"
#include "guilib/guiinfo/GUIInfo.h"
@@ -52,9 +51,11 @@ CPVRGUIInfo::~CPVRGUIInfo(void)
void CPVRGUIInfo::ResetProperties(void)
{
CSingleLock lock(m_critSection);
+
m_anyTimersInfo.ResetProperties();
m_tvTimersInfo.ResetProperties();
m_radioTimersInfo.ResetProperties();
+ m_timesInfo.Reset();
m_bHasTVRecordings = false;
m_bHasRadioRecordings = false;
m_iCurrentActiveClient = 0;
@@ -68,7 +69,6 @@ void CPVRGUIInfo::ResetProperties(void)
m_strBackendChannels .clear();
m_iBackendDiskTotal = 0;
m_iBackendDiskUsed = 0;
- m_iDuration = 0;
m_bIsPlayingTV = false;
m_bIsPlayingRadio = false;
m_bIsPlayingRecording = false;
@@ -78,15 +78,7 @@ void CPVRGUIInfo::ResetProperties(void)
m_bCanRecordPlayingChannel = false;
m_bHasTVChannels = false;
m_bHasRadioChannels = false;
- m_bHasTimeshiftData = false;
- m_bIsTimeshifting = false;
- m_iStartTime = time_t(0);
- m_iTimeshiftStartTime = time_t(0);
- m_iTimeshiftEndTime = time_t(0);
- m_iTimeshiftPlayTime = time_t(0);
- m_iTimeshiftOffset = 0;
-
- ResetPlayingTag();
+
ClearQualityInfo(m_qualityInfo);
ClearDescrambleInfo(m_descrambleInfo);
@@ -134,7 +126,7 @@ void CPVRGUIInfo::Notify(const Observable &obs, const ObservableMessage msg)
void CPVRGUIInfo::Process(void)
{
- unsigned int mLoop(0);
+ unsigned int iLoop = 0;
int toggleInterval = g_advancedSettings.m_iPVRInfoToggleInterval / 1000;
/* updated on request */
@@ -169,11 +161,7 @@ void CPVRGUIInfo::Process(void)
Sleep(0);
if (!m_bStop)
- UpdateTimeshift();
- Sleep(0);
-
- if (!m_bStop)
- UpdatePlayingTag();
+ UpdateTimeshiftData();
Sleep(0);
if (!m_bStop)
@@ -185,18 +173,15 @@ void CPVRGUIInfo::Process(void)
Sleep(0);
// Update the backend cache every toggleInterval seconds
- if (!m_bStop && mLoop % toggleInterval == 0)
+ if (!m_bStop && iLoop % toggleInterval == 0)
UpdateBackendCache();
- if (++mLoop == 1000)
- mLoop = 0;
+ if (++iLoop == 1000)
+ iLoop = 0;
if (!m_bStop)
Sleep(1000);
}
-
- if (!m_bStop)
- ResetPlayingTag();
}
void CPVRGUIInfo::UpdateQualityData(void)
@@ -272,65 +257,9 @@ void CPVRGUIInfo::UpdateMisc(void)
m_bIsRecordingPlayingChannel = bIsRecordingPlayingChannel;
}
-void CPVRGUIInfo::UpdateTimeshift(void)
+void CPVRGUIInfo::UpdateTimeshiftData(void)
{
- if (!CServiceBroker::GetPVRManager().IsPlayingTV() && !CServiceBroker::GetPVRManager().IsPlayingRadio())
- {
- // If nothing is playing (anymore), there is no need to poll the timeshift values from the clients.
- CSingleLock lock(m_critSection);
- if (m_bHasTimeshiftData)
- {
- m_bHasTimeshiftData = false;
- m_bIsTimeshifting = false;
- m_iStartTime = 0;
- m_iTimeshiftStartTime = 0;
- m_iTimeshiftEndTime = 0;
- m_iTimeshiftPlayTime = 0;
- m_iLastTimeshiftUpdate = 0;
- m_iTimeshiftOffset = 0;
- }
- return;
- }
-
- bool bIsTimeshifting = CServiceBroker::GetPVRManager().IsTimeshifting();
- time_t now = std::time(nullptr);
- time_t iStartTime = CServiceBroker::GetDataCacheCore().GetStartTime();
- time_t iPlayTime = CServiceBroker::GetDataCacheCore().GetPlayTime() / 1000;
- time_t iMinTime = bIsTimeshifting ? CServiceBroker::GetDataCacheCore().GetMinTime() / 1000 : 0;
- time_t iMaxTime = bIsTimeshifting ? CServiceBroker::GetDataCacheCore().GetMaxTime() / 1000 : 0;
- bool bPlaying = CServiceBroker::GetDataCacheCore().GetSpeed() == 1.0;
-
- CSingleLock lock(m_critSection);
-
- m_iLastTimeshiftUpdate = now;
-
- if (!iStartTime)
- {
- if (m_iStartTime == 0)
- iStartTime = now;
- else
- iStartTime = m_iStartTime;
- }
-
- m_bIsTimeshifting = bIsTimeshifting;
- m_iStartTime = iStartTime;
- m_iTimeshiftStartTime = iStartTime + iMinTime;
- m_iTimeshiftEndTime = iStartTime + iMaxTime;
-
- if (m_iTimeshiftEndTime > m_iTimeshiftStartTime)
- {
- // timeshifting supported
- m_iTimeshiftPlayTime = iStartTime + iPlayTime;
- }
- else if (bPlaying)
- {
- // timeshifting not supported
- m_iTimeshiftPlayTime = now - m_iTimeshiftOffset;
- }
-
- m_iTimeshiftOffset = now - m_iTimeshiftPlayTime;
-
- m_bHasTimeshiftData = true;
+ m_timesInfo.Update();
}
bool CPVRGUIInfo::InitCurrentItem(CFileItem *item)
@@ -701,32 +630,53 @@ bool CPVRGUIInfo::GetPVRLabel(const CFileItem *item, const CGUIInfo &info, std::
switch (info.m_info)
{
case PVR_EPG_EVENT_DURATION:
- CharInfoEpgEventDuration(item, static_cast<TIME_FORMAT>(info.GetData1()), strValue);
+ {
+ const CPVREpgInfoTagPtr epgTag = (item->IsPVRChannel() || item->IsEPG()) ? CPVRItem(item).GetEpgInfoTag() : nullptr;
+ strValue = m_timesInfo.GetEpgEventDuration(epgTag, static_cast<TIME_FORMAT>(info.GetData1()));
return true;
+ }
case PVR_EPG_EVENT_ELAPSED_TIME:
- CharInfoEpgEventElapsedTime(item, static_cast<TIME_FORMAT>(info.GetData1()), strValue);
+ {
+ const CPVREpgInfoTagPtr epgTag = (item->IsPVRChannel() || item->IsEPG()) ? CPVRItem(item).GetEpgInfoTag() : nullptr;
+ strValue = m_timesInfo.GetEpgEventElapsedTime(epgTag, static_cast<TIME_FORMAT>(info.GetData1()));
return true;
+ }
case PVR_EPG_EVENT_REMAINING_TIME:
- CharInfoEpgEventRemainingTime(item, static_cast<TIME_FORMAT>(info.GetData1()), strValue);
+ {
+ const CPVREpgInfoTagPtr epgTag = (item->IsPVRChannel() || item->IsEPG()) ? CPVRItem(item).GetEpgInfoTag() : nullptr;
+ strValue = m_timesInfo.GetEpgEventRemainingTime(epgTag, static_cast<TIME_FORMAT>(info.GetData1()));
return true;
+ }
case PVR_EPG_EVENT_FINISH_TIME:
- CharInfoEpgEventFinishTime(item, static_cast<TIME_FORMAT>(info.GetData1()), strValue);
+ {
+ const CPVREpgInfoTagPtr epgTag = (item->IsPVRChannel() || item->IsEPG()) ? CPVRItem(item).GetEpgInfoTag() : nullptr;
+ strValue = m_timesInfo.GetEpgEventFinishTime(epgTag, static_cast<TIME_FORMAT>(info.GetData1()));
return true;
+ }
case PVR_TIMESHIFT_START_TIME:
- CharInfoTimeshiftStartTime(static_cast<TIME_FORMAT>(info.GetData1()), strValue);
+ strValue = m_timesInfo.GetTimeshiftStartTime(static_cast<TIME_FORMAT>(info.GetData1()));
return true;
case PVR_TIMESHIFT_END_TIME:
- CharInfoTimeshiftEndTime(static_cast<TIME_FORMAT>(info.GetData1()), strValue);
+ strValue = m_timesInfo.GetTimeshiftEndTime(static_cast<TIME_FORMAT>(info.GetData1()));
return true;
case PVR_TIMESHIFT_PLAY_TIME:
- CharInfoTimeshiftPlayTime(static_cast<TIME_FORMAT>(info.GetData1()), strValue);
+ strValue = m_timesInfo.GetTimeshiftPlayTime(static_cast<TIME_FORMAT>(info.GetData1()));
return true;
case PVR_TIMESHIFT_OFFSET:
- CharInfoTimeshiftOffset(static_cast<TIME_FORMAT>(info.GetData1()), strValue);
+ strValue = m_timesInfo.GetTimeshiftOffset(static_cast<TIME_FORMAT>(info.GetData1()));
+ return true;
+ case PVR_TIMESHIFT_PROGRESS_DURATION:
+ strValue = m_timesInfo.GetTimeshiftProgressDuration(static_cast<TIME_FORMAT>(info.GetData1()));
+ return true;
+ case PVR_TIMESHIFT_PROGRESS_START_TIME:
+ strValue = m_timesInfo.GetTimeshiftProgressStartTime(static_cast<TIME_FORMAT>(info.GetData1()));
+ return true;
+ case PVR_TIMESHIFT_PROGRESS_END_TIME:
+ strValue = m_timesInfo.GetTimeshiftProgressEndTime(static_cast<TIME_FORMAT>(info.GetData1()));
return true;
case PVR_EPG_EVENT_SEEK_TIME:
- strValue = StringUtils::SecondsToTimeString(GetElapsedTime() + g_application.GetAppPlayer().GetSeekHandler().GetSeekSize(),
- static_cast<TIME_FORMAT>(info.GetData1())).c_str();
+ strValue = m_timesInfo.GetEpgEventSeekTime(g_application.GetAppPlayer().GetSeekHandler().GetSeekSize(),
+ static_cast<TIME_FORMAT>(info.GetData1()));
return true;
case PVR_NOW_RECORDING_TITLE:
strValue = m_anyTimersInfo.GetActiveTimerTitle();
@@ -1090,24 +1040,35 @@ bool CPVRGUIInfo::GetPVRInt(const CFileItem *item, const CGUIInfo &info, int& iV
case PVR_EPG_EVENT_DURATION:
{
const CPVREpgInfoTagPtr epgTag = (item->IsPVRChannel() || item->IsEPG()) ? CPVRItem(item).GetEpgInfoTag() : nullptr;
- if (epgTag && epgTag != m_playingEpgTag)
- iValue = epgTag->GetDuration();
- else
- iValue = m_iDuration;
+ iValue = m_timesInfo.GetEpgEventDuration(epgTag);
return true;
}
case PVR_EPG_EVENT_PROGRESS:
{
const CPVREpgInfoTagPtr epgTag = (item->IsPVRChannel() || item->IsEPG()) ? CPVRItem(item).GetEpgInfoTag() : nullptr;
- if (epgTag && epgTag != m_playingEpgTag)
- iValue = std::lrintf(epgTag->ProgressPercentage());
- else
- iValue = std::lrintf(static_cast<float>(GetElapsedTime()) / m_iDuration * 100);
+ iValue = m_timesInfo.GetEpgEventProgress(epgTag);
return true;
}
case PVR_TIMESHIFT_PROGRESS:
- iValue = std::lrintf(static_cast<float>(m_iTimeshiftPlayTime - m_iTimeshiftStartTime) /
- (m_iTimeshiftEndTime - m_iTimeshiftStartTime) * 100);
+ iValue = m_timesInfo.GetTimeshiftProgress();
+ return true;
+ case PVR_TIMESHIFT_PROGRESS_DURATION:
+ iValue = m_timesInfo.GetTimeshiftProgressDuration();
+ return true;
+ case PVR_TIMESHIFT_PROGRESS_PLAY_POS:
+ iValue = m_timesInfo.GetTimeshiftProgressPlayPosition();
+ return true;
+ case PVR_TIMESHIFT_PROGRESS_EPG_START:
+ iValue = m_timesInfo.GetTimeshiftProgressEpgStart();
+ return true;
+ case PVR_TIMESHIFT_PROGRESS_EPG_END:
+ iValue = m_timesInfo.GetTimeshiftProgressEpgEnd();
+ return true;
+ case PVR_TIMESHIFT_PROGRESS_BUFFER_START:
+ iValue = m_timesInfo.GetTimeshiftProgressBufferStart();
+ return true;
+ case PVR_TIMESHIFT_PROGRESS_BUFFER_END:
+ iValue = m_timesInfo.GetTimeshiftProgressBufferEnd();
return true;
case PVR_ACTUAL_STREAM_SIG_PROGR:
iValue = std::lrintf(static_cast<float>(m_qualityInfo.iSignal) / 0xFFFF * 100);
@@ -1345,7 +1306,7 @@ bool CPVRGUIInfo::GetPVRBool(const CFileItem *item, const CGUIInfo &info, bool&
bValue = m_bIsPlayingEncryptedStream;
return true;
case PVR_IS_TIMESHIFTING:
- bValue = m_bIsTimeshifting;
+ bValue = m_timesInfo.IsTimeshifting();
return true;
case PVR_CAN_RECORD_PLAYING_CHANNEL:
bValue = m_bCanRecordPlayingChannel;
@@ -1389,84 +1350,6 @@ bool CPVRGUIInfo::GetRadioRDSBool(const CFileItem *item, const CGUIInfo &info, b
return false;
}
-namespace
-{
- std::string TimeToTimeString(time_t datetime, TIME_FORMAT format, bool withSeconds)
- {
- CDateTime time;
- time.SetFromUTCDateTime(datetime);
- return time.GetAsLocalizedTime(format, withSeconds);
- }
-} // unnamed namespace
-
-void CPVRGUIInfo::CharInfoTimeshiftStartTime(TIME_FORMAT format, std::string &strValue) const
-{
- strValue = TimeToTimeString(m_iTimeshiftStartTime, format, false);
-}
-
-void CPVRGUIInfo::CharInfoTimeshiftEndTime(TIME_FORMAT format, std::string &strValue) const
-{
- strValue = TimeToTimeString(m_iTimeshiftEndTime, format, false);
-}
-
-void CPVRGUIInfo::CharInfoTimeshiftPlayTime(TIME_FORMAT format, std::string &strValue) const
-{
- strValue = TimeToTimeString(m_iTimeshiftPlayTime, format, true);
-}
-
-void CPVRGUIInfo::CharInfoTimeshiftOffset(TIME_FORMAT format, std::string &strValue) const
-{
- strValue = StringUtils::SecondsToTimeString(m_iTimeshiftOffset, format).c_str();
-}
-
-void CPVRGUIInfo::CharInfoEpgEventDuration(const CFileItem *item, TIME_FORMAT format, std::string &strValue) const
-{
- int iDuration = 0;
- const CPVREpgInfoTagPtr epgTag = (item->IsPVRChannel() || item->IsEPG()) ? CPVRItem(item).GetEpgInfoTag() : nullptr;
- if (epgTag && epgTag != m_playingEpgTag)
- iDuration = epgTag->GetDuration();
- else
- iDuration = m_iDuration;
-
- strValue = StringUtils::SecondsToTimeString(iDuration, format).c_str();
-}
-
-void CPVRGUIInfo::CharInfoEpgEventElapsedTime(const CFileItem *item, TIME_FORMAT format, std::string &strValue) const
-{
- int iElapsed = 0;
- const CPVREpgInfoTagPtr epgTag = (item->IsPVRChannel() || item->IsEPG()) ? CPVRItem(item).GetEpgInfoTag() : nullptr;
- if (epgTag && epgTag != m_playingEpgTag)
- iElapsed = epgTag->Progress();
- else
- iElapsed = GetElapsedTime();
-
- strValue = StringUtils::SecondsToTimeString(iElapsed, format).c_str();
-}
-
-int CPVRGUIInfo::GetRemainingTime(const CFileItem *item) const
-{
- int iRemaining = 0;
- const CPVREpgInfoTagPtr epgTag = (item->IsPVRChannel() || item->IsEPG()) ? CPVRItem(item).GetEpgInfoTag() : nullptr;
- if (epgTag && epgTag != m_playingEpgTag)
- iRemaining = epgTag->GetDuration() - epgTag->Progress();
- else
- iRemaining = m_iDuration - GetElapsedTime();
-
- return iRemaining;
-}
-
-void CPVRGUIInfo::CharInfoEpgEventRemainingTime(const CFileItem *item, TIME_FORMAT format, std::string &strValue) const
-{
- strValue = StringUtils::SecondsToTimeString(GetRemainingTime(item), format).c_str();
-}
-
-void CPVRGUIInfo::CharInfoEpgEventFinishTime(const CFileItem *item, TIME_FORMAT format, std::string &strValue) const
-{
- CDateTime finish = CDateTime::GetCurrentDateTime();
- finish += CDateTimeSpan(0, 0, 0, GetRemainingTime(item));
- strValue = finish.GetAsLocalizedTime(format);
-}
-
void CPVRGUIInfo::CharInfoBackendNumber(std::string &strValue) const
{
size_t numBackends = m_backendProperties.size();
@@ -1709,80 +1592,3 @@ void CPVRGUIInfo::UpdateNextTimer(void)
m_tvTimersInfo.UpdateNextTimer();
m_radioTimersInfo.UpdateNextTimer();
}
-
-int CPVRGUIInfo::GetElapsedTime(void) const
-{
- CSingleLock lock(m_critSection);
-
- if (m_playingEpgTag || m_iTimeshiftStartTime)
- {
- CDateTime current(m_iTimeshiftPlayTime);
- CDateTime start = m_playingEpgTag ? m_playingEpgTag->StartAsUTC()
- : CDateTime(m_iTimeshiftStartTime);
- CDateTimeSpan time = current > start ? current - start : CDateTimeSpan(0, 0, 0, 0);
- return time.GetSecondsTotal();
- }
- else
- {
- return 0;
- }
-}
-
-void CPVRGUIInfo::ResetPlayingTag(void)
-{
- CSingleLock lock(m_critSection);
- m_playingEpgTag.reset();
- m_iDuration = 0;
-}
-
-CPVREpgInfoTagPtr CPVRGUIInfo::GetPlayingTag() const
-{
- CSingleLock lock(m_critSection);
- return m_playingEpgTag;
-}
-
-void CPVRGUIInfo::UpdatePlayingTag(void)
-{
- const CPVRChannelPtr currentChannel(CServiceBroker::GetPVRManager().GetPlayingChannel());
- const CPVREpgInfoTagPtr currentTag(CServiceBroker::GetPVRManager().GetPlayingEpgTag());
- if (currentChannel || currentTag)
- {
- CPVREpgInfoTagPtr epgTag(GetPlayingTag());
- CPVRChannelPtr channel;
- if (epgTag)
- channel = epgTag->Channel();
-
- if (!epgTag || !epgTag->IsActive() ||
- !channel || !currentChannel || *channel != *currentChannel)
- {
- const CPVREpgInfoTagPtr newTag(currentTag ? currentTag : currentChannel->GetEPGNow());
-
- CSingleLock lock(m_critSection);
- if (newTag)
- {
- m_playingEpgTag = newTag;
- m_iDuration = m_playingEpgTag->GetDuration();
- }
- else if (m_iTimeshiftEndTime > m_iTimeshiftStartTime)
- {
- m_playingEpgTag.reset();
- m_iDuration = m_iTimeshiftEndTime - m_iTimeshiftStartTime;
- }
- else
- {
- m_playingEpgTag.reset();
- m_iDuration = 0;
- }
- }
- }
- else
- {
- const CPVRRecordingPtr recording(CServiceBroker::GetPVRManager().GetPlayingRecording());
- if (recording)
- {
- CSingleLock lock(m_critSection);
- m_playingEpgTag.reset();
- m_iDuration = recording->GetDuration();
- }
- }
-}
diff --git a/xbmc/pvr/PVRGUIInfo.h b/xbmc/pvr/PVRGUIInfo.h
index 78b74634a8..9d3e05ab59 100644
--- a/xbmc/pvr/PVRGUIInfo.h
+++ b/xbmc/pvr/PVRGUIInfo.h
@@ -19,6 +19,7 @@
#include "utils/Observer.h"
#include "pvr/PVRGUITimerInfo.h"
+#include "pvr/PVRGUITimesInfo.h"
#include "pvr/PVRTypes.h"
#include "pvr/addons/PVRClients.h"
@@ -52,17 +53,6 @@ namespace PVR
bool GetInt(int& value, const CGUIListItem *item, int contextWindow, const KODI::GUILIB::GUIINFO::CGUIInfo &info) const override;
bool GetBool(bool& value, const CGUIListItem *item, int contextWindow, const KODI::GUILIB::GUIINFO::CGUIInfo &info) const override;
- /*!
- * @brief Clear the playing EPG tag.
- */
- void ResetPlayingTag(void);
-
- /*!
- * @brief Get the currently playing EPG tag.
- * @return The currently playing EPG tag or NULL if no EPG tag is playing.
- */
- CPVREpgInfoTagPtr GetPlayingTag() const;
-
private:
void ResetProperties(void);
void ClearQualityInfo(PVR_SIGNAL_STATUS &qualityInfo);
@@ -70,14 +60,14 @@ namespace PVR
void Process(void) override;
- void UpdatePlayingTag(void);
void UpdateTimersCache(void);
void UpdateBackendCache(void);
void UpdateQualityData(void);
void UpdateDescrambleData(void);
void UpdateMisc(void);
void UpdateNextTimer(void);
- void UpdateTimeshift(void);
+ void UpdateTimeshiftData(void);
+ void UpdateTimeshiftProgressData();
void UpdateTimersToggle(void);
@@ -92,10 +82,6 @@ namespace PVR
bool GetPVRBool(const CFileItem *item, const KODI::GUILIB::GUIINFO::CGUIInfo &info, bool& bValue) const;
bool GetRadioRDSBool(const CFileItem *item, const KODI::GUILIB::GUIINFO::CGUIInfo &info, bool &bValue) const;
- void CharInfoEpgEventDuration(const CFileItem *item, TIME_FORMAT format, std::string &strValue) const;
- void CharInfoEpgEventElapsedTime(const CFileItem *item, TIME_FORMAT format, std::string &strValue) const;
- void CharInfoEpgEventRemainingTime(const CFileItem *item, TIME_FORMAT format, std::string &strValue) const;
- void CharInfoEpgEventFinishTime(const CFileItem *item, TIME_FORMAT format, std::string &strValue) const;
void CharInfoBackendNumber(std::string &strValue) const;
void CharInfoTotalDiskSpace(std::string &strValue) const;
void CharInfoSignal(std::string &strValue) const;
@@ -117,19 +103,6 @@ namespace PVR
void CharInfoService(std::string &strValue) const;
void CharInfoMux(std::string &strValue) const;
void CharInfoProvider(std::string &strValue) const;
- void CharInfoTimeshiftStartTime(TIME_FORMAT format, std::string &strValue) const;
- void CharInfoTimeshiftEndTime(TIME_FORMAT format, std::string &strValue) const;
- void CharInfoTimeshiftPlayTime(TIME_FORMAT format, std::string &strValue) const;
- void CharInfoTimeshiftOffset(TIME_FORMAT format, std::string &strValue) const;
-
- /*!
- * @brief Get the elapsed time since the start of the currently playing epg event or if
- * no epg is available since the start of the playback of the current Live TV stream.
- * @return The time in seconds or 0 if no channel is playing.
- */
- int GetElapsedTime(void) const;
-
- int GetRemainingTime(const CFileItem *item) const;
/** @name PVRGUIInfo data */
//@{
@@ -137,6 +110,8 @@ namespace PVR
CPVRGUITVTimerInfo m_tvTimersInfo;
CPVRGUIRadioTimerInfo m_radioTimersInfo;
+ CPVRGUITimesInfo m_timesInfo;
+
bool m_bHasTVRecordings;
bool m_bHasRadioRecordings;
unsigned int m_iCurrentActiveClient;
@@ -150,7 +125,6 @@ namespace PVR
std::string m_strBackendChannels;
long long m_iBackendDiskTotal;
long long m_iBackendDiskUsed;
- unsigned int m_iDuration;
bool m_bIsPlayingTV;
bool m_bIsPlayingRadio;
bool m_bIsPlayingRecording;
@@ -167,18 +141,8 @@ namespace PVR
PVR_SIGNAL_STATUS m_qualityInfo; /*!< stream quality information */
PVR_DESCRAMBLE_INFO m_descrambleInfo; /*!< stream descramble information */
- CPVREpgInfoTagPtr m_playingEpgTag;
std::vector<SBackend> m_backendProperties;
- bool m_bHasTimeshiftData;
- bool m_bIsTimeshifting;
- time_t m_iLastTimeshiftUpdate;
- time_t m_iStartTime;
- time_t m_iTimeshiftStartTime;
- time_t m_iTimeshiftEndTime;
- time_t m_iTimeshiftPlayTime;
- unsigned int m_iTimeshiftOffset;
-
mutable CCriticalSection m_critSection;
/**
@@ -187,7 +151,7 @@ namespace PVR
* backend querying when we're not displaying any of the queried
* information.
*/
- mutable std::atomic<bool> m_updateBackendCacheRequested;
+ mutable std::atomic<bool> m_updateBackendCacheRequested;
bool m_bRegistered;
};
diff --git a/xbmc/pvr/PVRGUITimesInfo.cpp b/xbmc/pvr/PVRGUITimesInfo.cpp
new file mode 100644
index 0000000000..2dbcda3567
--- /dev/null
+++ b/xbmc/pvr/PVRGUITimesInfo.cpp
@@ -0,0 +1,395 @@
+/*
+ * Copyright (C) 2012-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "PVRGUITimesInfo.h"
+
+#include <cmath>
+
+#include "ServiceBroker.h"
+#include "cores/DataCacheCore.h"
+#include "settings/AdvancedSettings.h"
+#include "threads/SingleLock.h"
+#include "utils/StringUtils.h"
+
+#include "pvr/PVRManager.h"
+
+using namespace PVR;
+
+CPVRGUITimesInfo::CPVRGUITimesInfo()
+{
+ Reset();
+}
+
+void CPVRGUITimesInfo::Reset()
+{
+ CSingleLock lock(m_critSection);
+
+ m_iStartTime = 0;
+ m_iDuration = 0;
+ m_iTimeshiftStartTime = 0;
+ m_iTimeshiftEndTime = 0;
+ m_iTimeshiftPlayTime = 0;
+ m_iTimeshiftOffset = 0;
+
+ m_iTimeshiftProgressStartTime = 0;
+ m_iTimeshiftProgressEndTime = 0;
+ m_iTimeshiftProgressDuration = 0;
+
+ m_playingEpgTag.reset();
+}
+
+void CPVRGUITimesInfo::UpdatePlayingTag()
+{
+ const CPVRChannelPtr currentChannel = CServiceBroker::GetPVRManager().GetPlayingChannel();
+ CPVREpgInfoTagPtr currentTag = CServiceBroker::GetPVRManager().GetPlayingEpgTag();
+
+ if (currentChannel || currentTag)
+ {
+ if (!currentTag)
+ currentTag = currentChannel->GetEPGNow();
+
+ CSingleLock lock(m_critSection);
+
+ const CPVRChannelPtr playingChannel = m_playingEpgTag ? m_playingEpgTag->Channel() : nullptr;
+ if (!m_playingEpgTag || !m_playingEpgTag->IsActive() ||
+ !playingChannel || !currentChannel || *playingChannel != *currentChannel)
+ {
+ if (currentTag)
+ {
+ m_playingEpgTag = currentTag;
+ m_iDuration = m_playingEpgTag->GetDuration();
+ }
+ else if (m_iTimeshiftEndTime > m_iTimeshiftStartTime)
+ {
+ m_playingEpgTag.reset();
+ m_iDuration = m_iTimeshiftEndTime - m_iTimeshiftStartTime;
+ }
+ else
+ {
+ m_playingEpgTag.reset();
+ m_iDuration = 0;
+ }
+ }
+ }
+ else
+ {
+ const CPVRRecordingPtr recording = CServiceBroker::GetPVRManager().GetPlayingRecording();
+ if (recording)
+ {
+ CSingleLock lock(m_critSection);
+ m_playingEpgTag.reset();
+ m_iDuration = recording->GetDuration();
+ }
+ }
+}
+
+void CPVRGUITimesInfo::UpdateTimeshiftData()
+{
+ if (!CServiceBroker::GetPVRManager().IsPlayingTV() && !CServiceBroker::GetPVRManager().IsPlayingRadio())
+ {
+ // If nothing is playing (anymore), there is no need to update data.
+ Reset();
+ return;
+ }
+
+ time_t now = std::time(nullptr);
+ time_t iStartTime;
+ int64_t iPlayTime, iMinTime, iMaxTime;
+ CServiceBroker::GetDataCacheCore().GetPlayTimes(iStartTime, iPlayTime, iMinTime, iMaxTime);
+ bool bPlaying = CServiceBroker::GetDataCacheCore().GetSpeed() == 1.0;
+
+ CSingleLock lock(m_critSection);
+
+ if (!iStartTime)
+ {
+ if (m_iStartTime == 0)
+ iStartTime = now;
+ else
+ iStartTime = m_iStartTime;
+
+ iMinTime = iPlayTime;
+ iMaxTime = iPlayTime;
+ }
+
+ m_iStartTime = iStartTime;
+ m_iTimeshiftStartTime = iStartTime + iMinTime / 1000;
+ m_iTimeshiftEndTime = iStartTime + iMaxTime / 1000;
+
+ if (m_iTimeshiftEndTime > m_iTimeshiftStartTime)
+ {
+ // timeshifting supported
+ m_iTimeshiftPlayTime = iStartTime + iPlayTime / 1000;
+ m_iTimeshiftOffset = (iMaxTime - iPlayTime) / 1000;
+ }
+ else
+ {
+ // timeshifting not supported
+ if (bPlaying)
+ m_iTimeshiftPlayTime = now - m_iTimeshiftOffset;
+
+ m_iTimeshiftOffset = now - m_iTimeshiftPlayTime;
+ }
+
+ UpdateTimeshiftProgressData();
+}
+
+void CPVRGUITimesInfo::UpdateTimeshiftProgressData()
+{
+ // Note: General idea of the ts progress is always to be able to visualise both the complete
+ // ts buffer and the complete playing epg event (if any) side by side with the same time
+ // scale. Ts progress start and end times will be calculated accordingly.
+ // + Start is usually ts buffer start, except if start time of playing epg event is
+ // before ts buffer start, then progress start is epg event start.
+ // + End is usually ts buffer end, except if end time of playing epg event is
+ // after ts buffer end, then progress end is epg event end.
+
+ CSingleLock lock(m_critSection);
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // start time
+ //////////////////////////////////////////////////////////////////////////////////////
+ bool bUpdatedStartTime = false;
+ if (m_playingEpgTag)
+ {
+ time_t start = 0;
+ m_playingEpgTag->StartAsUTC().GetAsTime(start);
+ if (start < m_iTimeshiftStartTime)
+ {
+ // playing event started before start of ts buffer
+ m_iTimeshiftProgressStartTime = start;
+ bUpdatedStartTime = true;
+ }
+ }
+
+ if (!bUpdatedStartTime)
+ {
+ // default to ts buffer start
+ m_iTimeshiftProgressStartTime = m_iTimeshiftStartTime;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // end time
+ //////////////////////////////////////////////////////////////////////////////////////
+ bool bUpdatedEndTime = false;
+ if (m_playingEpgTag)
+ {
+ time_t end = 0;
+ m_playingEpgTag->EndAsUTC().GetAsTime(end);
+ if (end > m_iTimeshiftEndTime)
+ {
+ // playing event will end after end of ts buffer
+ m_iTimeshiftProgressEndTime = end;
+ bUpdatedEndTime = true;
+ }
+ }
+
+ if (!bUpdatedEndTime)
+ {
+ // default to ts buffer end
+ m_iTimeshiftProgressEndTime = m_iTimeshiftEndTime;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // duration
+ //////////////////////////////////////////////////////////////////////////////////////
+ m_iTimeshiftProgressDuration = m_iTimeshiftProgressEndTime - m_iTimeshiftProgressStartTime;
+}
+
+void CPVRGUITimesInfo::Update()
+{
+ UpdatePlayingTag();
+ UpdateTimeshiftData();
+}
+
+std::string CPVRGUITimesInfo::TimeToTimeString(time_t datetime, TIME_FORMAT format, bool withSeconds)
+{
+ CDateTime time;
+ time.SetFromUTCDateTime(datetime);
+ return time.GetAsLocalizedTime(format, withSeconds);
+}
+
+std::string CPVRGUITimesInfo::GetTimeshiftStartTime(TIME_FORMAT format) const
+{
+ CSingleLock lock(m_critSection);
+ return TimeToTimeString(m_iTimeshiftStartTime, format, false);
+}
+
+std::string CPVRGUITimesInfo::GetTimeshiftEndTime(TIME_FORMAT format) const
+{
+ CSingleLock lock(m_critSection);
+ return TimeToTimeString(m_iTimeshiftEndTime, format, false);
+}
+
+std::string CPVRGUITimesInfo::GetTimeshiftPlayTime(TIME_FORMAT format) const
+{
+ CSingleLock lock(m_critSection);
+ return TimeToTimeString(m_iTimeshiftPlayTime, format, true);
+}
+
+std::string CPVRGUITimesInfo::GetTimeshiftOffset(TIME_FORMAT format) const
+{
+ CSingleLock lock(m_critSection);
+ return StringUtils::SecondsToTimeString(m_iTimeshiftOffset, format);
+}
+
+std::string CPVRGUITimesInfo::GetTimeshiftProgressDuration(TIME_FORMAT format) const
+{
+ CSingleLock lock(m_critSection);
+ return StringUtils::SecondsToTimeString(m_iTimeshiftProgressDuration, format);
+}
+
+std::string CPVRGUITimesInfo::GetTimeshiftProgressStartTime(TIME_FORMAT format) const
+{
+ CSingleLock lock(m_critSection);
+ return TimeToTimeString(m_iTimeshiftProgressStartTime, format, false);
+}
+
+std::string CPVRGUITimesInfo::GetTimeshiftProgressEndTime(TIME_FORMAT format) const
+{
+ CSingleLock lock(m_critSection);
+ return TimeToTimeString(m_iTimeshiftProgressEndTime, format, false);
+}
+
+std::string CPVRGUITimesInfo::GetEpgEventDuration(const CPVREpgInfoTagPtr& epgTag, TIME_FORMAT format) const
+{
+ CSingleLock lock(m_critSection);
+ return StringUtils::SecondsToTimeString(GetEpgEventDuration(epgTag), format);
+}
+
+std::string CPVRGUITimesInfo::GetEpgEventElapsedTime(const CPVREpgInfoTagPtr& epgTag, TIME_FORMAT format) const
+{
+ int iElapsed = 0;
+ CSingleLock lock(m_critSection);
+ if (epgTag && epgTag != m_playingEpgTag)
+ iElapsed = epgTag->Progress();
+ else
+ iElapsed = GetElapsedTime();
+
+ return StringUtils::SecondsToTimeString(iElapsed, format);
+}
+
+std::string CPVRGUITimesInfo::GetEpgEventRemainingTime(const CPVREpgInfoTagPtr& epgTag, TIME_FORMAT format) const
+{
+ CSingleLock lock(m_critSection);
+ return StringUtils::SecondsToTimeString(GetRemainingTime(epgTag), format);
+}
+
+std::string CPVRGUITimesInfo::GetEpgEventFinishTime(const CPVREpgInfoTagPtr& epgTag, TIME_FORMAT format) const
+{
+ CDateTime finish = CDateTime::GetCurrentDateTime();
+ finish += CDateTimeSpan(0, 0, 0, GetRemainingTime(epgTag));
+ return finish.GetAsLocalizedTime(format);
+}
+
+std::string CPVRGUITimesInfo::GetEpgEventSeekTime(int iSeekSize, TIME_FORMAT format) const
+{
+ return StringUtils::SecondsToTimeString(GetElapsedTime() + iSeekSize, format);
+}
+
+int CPVRGUITimesInfo::GetElapsedTime() const
+{
+ CSingleLock lock(m_critSection);
+ if (m_playingEpgTag || m_iTimeshiftStartTime)
+ {
+ CDateTime current(m_iTimeshiftPlayTime);
+ CDateTime start = m_playingEpgTag ? m_playingEpgTag->StartAsUTC() : CDateTime(m_iTimeshiftStartTime);
+ CDateTimeSpan time = current > start ? current - start : CDateTimeSpan(0, 0, 0, 0);
+ return time.GetSecondsTotal();
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+int CPVRGUITimesInfo::GetRemainingTime(const CPVREpgInfoTagPtr& epgTag) const
+{
+ CSingleLock lock(m_critSection);
+ if (epgTag && epgTag != m_playingEpgTag)
+ return epgTag->GetDuration() - epgTag->Progress();
+ else
+ return m_iDuration - GetElapsedTime();
+}
+
+int CPVRGUITimesInfo::GetTimeshiftProgress() const
+{
+ CSingleLock lock(m_critSection);
+ return std::lrintf(static_cast<float>(m_iTimeshiftPlayTime - m_iTimeshiftStartTime) / (m_iTimeshiftEndTime - m_iTimeshiftStartTime) * 100);
+}
+
+int CPVRGUITimesInfo::GetTimeshiftProgressDuration() const
+{
+ CSingleLock lock(m_critSection);
+ return m_iTimeshiftProgressDuration;
+}
+
+int CPVRGUITimesInfo::GetTimeshiftProgressPlayPosition() const
+{
+ CSingleLock lock(m_critSection);
+ return std::lrintf(static_cast<float>(m_iTimeshiftPlayTime - m_iTimeshiftProgressStartTime) / m_iTimeshiftProgressDuration * 100);
+}
+
+int CPVRGUITimesInfo::GetTimeshiftProgressEpgStart() const
+{
+ CSingleLock lock(m_critSection);
+ if (m_playingEpgTag)
+ {
+ time_t epgStart = 0;
+ m_playingEpgTag->StartAsUTC().GetAsTime(epgStart);
+ return std::lrintf(static_cast<float>(epgStart - m_iTimeshiftProgressStartTime) / m_iTimeshiftProgressDuration * 100);
+ }
+ return 0;
+}
+
+int CPVRGUITimesInfo::GetTimeshiftProgressEpgEnd() const
+{
+ CSingleLock lock(m_critSection);
+ if (m_playingEpgTag)
+ {
+ time_t epgEnd = 0;
+ m_playingEpgTag->EndAsUTC().GetAsTime(epgEnd);
+ return std::lrintf(static_cast<float>(epgEnd - m_iTimeshiftProgressStartTime) / m_iTimeshiftProgressDuration * 100);
+ }
+ return 0;
+}
+
+int CPVRGUITimesInfo::GetTimeshiftProgressBufferStart() const
+{
+ CSingleLock lock(m_critSection);
+ return std::lrintf(static_cast<float>(m_iTimeshiftStartTime - m_iTimeshiftProgressStartTime) / m_iTimeshiftProgressDuration * 100);
+}
+
+int CPVRGUITimesInfo::GetTimeshiftProgressBufferEnd() const
+{
+ CSingleLock lock(m_critSection);
+ return std::lrintf(static_cast<float>(m_iTimeshiftEndTime - m_iTimeshiftProgressStartTime) / m_iTimeshiftProgressDuration * 100);
+}
+
+int CPVRGUITimesInfo::GetEpgEventDuration(const CPVREpgInfoTagPtr& epgTag) const
+{
+ CSingleLock lock(m_critSection);
+ if (epgTag && epgTag != m_playingEpgTag)
+ return epgTag->GetDuration();
+ else
+ return m_iDuration;
+}
+
+int CPVRGUITimesInfo::GetEpgEventProgress(const CPVREpgInfoTagPtr& epgTag) const
+{
+ CSingleLock lock(m_critSection);
+ if (epgTag && epgTag != m_playingEpgTag)
+ return std::lrintf(epgTag->ProgressPercentage());
+ else
+ return std::lrintf(static_cast<float>(GetElapsedTime()) / m_iDuration * 100);
+}
+
+bool CPVRGUITimesInfo::IsTimeshifting() const
+{
+ CSingleLock lock(m_critSection);
+ return (m_iTimeshiftOffset > static_cast<unsigned int>(g_advancedSettings.m_iPVRTimeshiftThreshold));
+}
diff --git a/xbmc/pvr/PVRGUITimesInfo.h b/xbmc/pvr/PVRGUITimesInfo.h
new file mode 100644
index 0000000000..479bdce5f9
--- /dev/null
+++ b/xbmc/pvr/PVRGUITimesInfo.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2012-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "XBDateTime.h"
+#include "threads/CriticalSection.h"
+
+#include "pvr/PVRTypes.h"
+
+namespace PVR
+{
+ class CPVRGUITimesInfo
+ {
+ public:
+ CPVRGUITimesInfo();
+ virtual ~CPVRGUITimesInfo() = default;
+
+ void Reset();
+ void Update();
+
+ // GUI info labels
+ std::string GetTimeshiftStartTime(TIME_FORMAT format) const;
+ std::string GetTimeshiftEndTime(TIME_FORMAT format) const;
+ std::string GetTimeshiftPlayTime(TIME_FORMAT format) const;
+ std::string GetTimeshiftOffset(TIME_FORMAT format) const;
+ std::string GetTimeshiftProgressDuration(TIME_FORMAT format) const;
+ std::string GetTimeshiftProgressStartTime(TIME_FORMAT format) const;
+ std::string GetTimeshiftProgressEndTime(TIME_FORMAT format) const;
+
+ std::string GetEpgEventDuration(const CPVREpgInfoTagPtr& epgTag, TIME_FORMAT format) const;
+ std::string GetEpgEventElapsedTime(const CPVREpgInfoTagPtr& epgTag, TIME_FORMAT format) const;
+ std::string GetEpgEventRemainingTime(const CPVREpgInfoTagPtr& epgTag, TIME_FORMAT format) const;
+ std::string GetEpgEventFinishTime(const CPVREpgInfoTagPtr& epgTag, TIME_FORMAT format) const;
+ std::string GetEpgEventSeekTime(int iSeekSize, TIME_FORMAT format) const;
+
+ // GUI info ints
+ int GetTimeshiftProgress() const;
+ int GetTimeshiftProgressDuration() const;
+ int GetTimeshiftProgressPlayPosition() const;
+ int GetTimeshiftProgressEpgStart() const;
+ int GetTimeshiftProgressEpgEnd() const;
+ int GetTimeshiftProgressBufferStart() const;
+ int GetTimeshiftProgressBufferEnd() const;
+
+ int GetEpgEventDuration(const CPVREpgInfoTagPtr& epgTag) const;
+ int GetEpgEventProgress(const CPVREpgInfoTagPtr& epgTag) const;
+
+ // GUI info bools
+ bool IsTimeshifting() const;
+
+ private:
+ void UpdatePlayingTag();
+ void UpdateTimeshiftData();
+ void UpdateTimeshiftProgressData();
+
+ static std::string TimeToTimeString(time_t datetime, TIME_FORMAT format, bool withSeconds);
+
+ int GetElapsedTime() const;
+ int GetRemainingTime(const CPVREpgInfoTagPtr& epgTag) const;
+
+ mutable CCriticalSection m_critSection;
+
+ CPVREpgInfoTagPtr m_playingEpgTag;
+
+ time_t m_iStartTime;
+ unsigned int m_iDuration;
+ time_t m_iTimeshiftStartTime;
+ time_t m_iTimeshiftEndTime;
+ time_t m_iTimeshiftPlayTime;
+ unsigned int m_iTimeshiftOffset;
+
+ time_t m_iTimeshiftProgressStartTime;
+ time_t m_iTimeshiftProgressEndTime;
+ unsigned int m_iTimeshiftProgressDuration;
+ };
+
+} // namespace PVR
diff --git a/xbmc/pvr/PVRManager.cpp b/xbmc/pvr/PVRManager.cpp
index 947ce39f2c..a26c0e0e1f 100644
--- a/xbmc/pvr/PVRManager.cpp
+++ b/xbmc/pvr/PVRManager.cpp
@@ -667,31 +667,12 @@ bool CPVRManager::IsRecordingOnPlayingChannel(void) const
return currentChannel && currentChannel->IsRecording();
}
-bool CPVRManager::IsTimeshifting(void) const
-{
- bool bTimeshifting = false;
- if (m_playingChannel)
- {
- const CPVRClientPtr client = GetClient(m_playingChannel->ClientID());
- if (client)
- client->IsTimeshifting(bTimeshifting);
- }
- return bTimeshifting;
-}
-
bool CPVRManager::CanRecordOnPlayingChannel(void) const
{
const CPVRChannelPtr currentChannel = GetPlayingChannel();
return currentChannel && currentChannel->CanRecord();
}
-void CPVRManager::ResetPlayingTag(void)
-{
- CSingleLock lock(m_critSection);
- if (IsStarted() && m_guiInfo)
- m_guiInfo->ResetPlayingTag();
-}
-
void CPVRManager::RestartParentalTimer()
{
if (m_parentalTimer)
diff --git a/xbmc/pvr/PVRManager.h b/xbmc/pvr/PVRManager.h
index e5e02e30a8..a1c7094db2 100644
--- a/xbmc/pvr/PVRManager.h
+++ b/xbmc/pvr/PVRManager.h
@@ -192,12 +192,6 @@ namespace PVR
bool IsPlayingEpgTag(const CPVREpgInfoTagPtr &epgTag) const;
/*!
- * @brief Check whether the currently playing livetv stream is timeshifted.
- * @return True if there is a playing stream and if it is timeshifted, false otherwise.
- */
- bool IsTimeshifting() const;
-
- /*!
* @return True while the PVRManager is initialising.
*/
inline bool IsInitialising(void) const
@@ -281,11 +275,6 @@ namespace PVR
bool EpgsCreated(void) const;
/*!
- * @brief Reset the playing EPG tag.
- */
- void ResetPlayingTag(void);
-
- /*!
* @brief Inform PVR manager that playback of an item just started.
* @param item The item that started to play.
*/
diff --git a/xbmc/pvr/epg/Epg.cpp b/xbmc/pvr/epg/Epg.cpp
index 4e7ae97fe2..a6724421bd 100644
--- a/xbmc/pvr/epg/Epg.cpp
+++ b/xbmc/pvr/epg/Epg.cpp
@@ -501,13 +501,7 @@ bool CPVREpg::Update(const time_t start, const time_t end, int iUpdateTime, bool
bGrabSuccess = LoadFromClients(start, end);
if (bGrabSuccess)
- {
- CPVRChannelPtr channel(CServiceBroker::GetPVRManager().GetPlayingChannel());
- if (channel &&
- channel->EpgID() == m_iEpgID)
- CServiceBroker::GetPVRManager().ResetPlayingTag();
m_bLoaded = true;
- }
else
CLog::LogF(LOGERROR, "Failed to update table '%s'", Name().c_str());
diff --git a/xbmc/pvr/epg/EpgInfoTag.cpp b/xbmc/pvr/epg/EpgInfoTag.cpp
index 27bf83813e..890ef7e38b 100644
--- a/xbmc/pvr/epg/EpgInfoTag.cpp
+++ b/xbmc/pvr/epg/EpgInfoTag.cpp
@@ -208,10 +208,9 @@ void CPVREpgInfoTag::ToSortable(SortItem& sortable, Field field) const
CDateTime CPVREpgInfoTag::GetCurrentPlayingTime() const
{
- if (CServiceBroker::GetPVRManager().GetPlayingChannel() == Channel() &&
- CServiceBroker::GetPVRManager().IsTimeshifting())
+ if (CServiceBroker::GetPVRManager().GetPlayingChannel() == Channel())
{
- // timeshifting; start time valid?
+ // start time valid?
time_t startTime = CServiceBroker::GetDataCacheCore().GetStartTime();
if (startTime > 0)
{
@@ -219,7 +218,6 @@ CDateTime CPVREpgInfoTag::GetCurrentPlayingTime() const
}
}
- // not timeshifting
return CDateTime::GetUTCDateTime();
}
diff --git a/xbmc/pvr/epg/EpgInfoTag.h b/xbmc/pvr/epg/EpgInfoTag.h
index 4b9560171c..56242597f5 100644
--- a/xbmc/pvr/epg/EpgInfoTag.h
+++ b/xbmc/pvr/epg/EpgInfoTag.h
@@ -101,7 +101,7 @@ namespace PVR
int Progress(void) const;
/*!
- * @brief Get a pointer to the next event. Set by CPVREpg in a call to Sort()
+ * @brief Get a pointer to the next event.
* @return A pointer to the next event or NULL if it's not set.
*/
CPVREpgInfoTagPtr GetNextEvent(void) const;
diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp
index e7f6cd3748..5c39cd1ffb 100644
--- a/xbmc/settings/AdvancedSettings.cpp
+++ b/xbmc/settings/AdvancedSettings.cpp
@@ -349,6 +349,7 @@ void CAdvancedSettings::Initialize()
m_bPVRChannelIconsAutoScan = true;
m_bPVRAutoScanIconsUserSet = false;
m_iPVRNumericChannelSwitchTimeout = 2000;
+ m_iPVRTimeshiftThreshold = 10;
m_cacheMemSize = 1024 * 1024 * 20;
m_cacheBufferMode = CACHE_BUFFER_MODE_INTERNET; // Default (buffer all internet streams/filesystems)
@@ -1096,6 +1097,7 @@ void CAdvancedSettings::ParseSettingsFile(const std::string &file)
XMLUtils::GetBoolean(pPVR, "channeliconsautoscan", m_bPVRChannelIconsAutoScan);
XMLUtils::GetBoolean(pPVR, "autoscaniconsuserset", m_bPVRAutoScanIconsUserSet);
XMLUtils::GetInt(pPVR, "numericchannelswitchtimeout", m_iPVRNumericChannelSwitchTimeout, 50, 60000);
+ XMLUtils::GetInt(pPVR, "timeshiftthreshold", m_iPVRTimeshiftThreshold, 0, 60);
}
TiXmlElement* pDatabase = pRootElement->FirstChildElement("videodatabase");
diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h
index be771cb3bb..266b7d433b 100644
--- a/xbmc/settings/AdvancedSettings.h
+++ b/xbmc/settings/AdvancedSettings.h
@@ -324,8 +324,8 @@ class CAdvancedSettings : public ISettingCallback, public ISettingsHandler
int m_iPVRInfoToggleInterval; /*!< @brief if there are more than 1 pvr gui info item available (e.g. multiple recordings active at the same time), use this toggle delay in milliseconds. defaults to 3000. */
bool m_bPVRChannelIconsAutoScan; /*!< @brief automatically scan user defined folder for channel icons when loading internal channel groups */
bool m_bPVRAutoScanIconsUserSet; /*!< @brief mark channel icons populated by auto scan as "user set" */
- int m_iPVRNumericChannelSwitchTimeout; /*!< @brief time in ms before the numeric dialog auto closes when confirmchannelswitch is disabled */
-
+ int m_iPVRNumericChannelSwitchTimeout; /*!< @brief time in msecs after that a channel switch occurs after entering a channel number, if confirmchannelswitch is disabled */
+ int m_iPVRTimeshiftThreshold; /*!< @brief time diff between current playing time and timeshift buffer end, in seconds, before a playing stream is displayed as timeshifting. */
DatabaseSettings m_databaseMusic; // advanced music database setup
DatabaseSettings m_databaseVideo; // advanced video database setup
DatabaseSettings m_databaseTV; // advanced tv database setup