aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--addons/resource.language.en_gb/resources/strings.po16
-rw-r--r--addons/skin.estuary/media/flags/aspectratio/1.00.pngbin1076 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/aspectratio/1.19.pngbin1049 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/aspectratio/1.33.pngbin1050 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/aspectratio/1.37.pngbin1115 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/aspectratio/1.66.pngbin1036 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/aspectratio/1.78.pngbin1152 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/aspectratio/1.85.pngbin1228 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/aspectratio/2.00.pngbin1205 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/aspectratio/2.20.pngbin1144 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/aspectratio/2.35.pngbin1284 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/aspectratio/2.40.pngbin1252 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/aspectratio/2.55.pngbin1131 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/aspectratio/2.76.pngbin1193 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiochannel/0.pngbin807 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiochannel/1.pngbin839 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiochannel/10.pngbin864 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiochannel/2.pngbin958 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiochannel/3.pngbin803 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiochannel/4.pngbin928 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiochannel/5.pngbin684 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiochannel/6.pngbin809 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiochannel/7.pngbin856 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiochannel/8.pngbin657 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/aac.pngbin1042 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/aac_latm.pngbin1042 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/ac3.pngbin1383 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/aif.pngbin771 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/aifc.pngbin1076 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/aiff.pngbin771 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/alac.pngbin1056 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/ape.pngbin990 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/avc.pngbin1158 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/cdda.pngbin1223 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/dca.pngbin981 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/dolbydigital.pngbin1383 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/dts.pngbin981 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/dtshd_hra.pngbin1549 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/dtshd_ma.pngbin1524 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/dtsma.pngbin1524 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/eac3.pngbin1383 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/flac.pngbin1121 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/mp1.pngbin936 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/mp2.pngbin1105 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/mp3.pngbin1138 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/mp3float.pngbin1138 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/ogg.pngbin1077 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/opus.pngbin1351 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/pcm.pngbin1187 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/pcm_bluray.pngbin1187 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/pcm_s16le.pngbin1187 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/pcm_s24le.pngbin1187 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/truehd.pngbin1579 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/vorbis.pngbin1692 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/wav.pngbin1321 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/wavpack.pngbin1480 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/wma.pngbin1378 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/wmapro.pngbin1378 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/audiocodec/wmav2.pngbin1378 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/rds/rds.pngbin1141 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/av1.pngbin1025 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/avc1.pngbin1262 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/bluray.pngbin1313 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/div3.pngbin1213 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/divx.pngbin1213 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/dvd.pngbin1002 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/dx50.pngbin1213 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/flv.pngbin744 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/h264.pngbin1160 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/hddvd.pngbin1100 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/hdmv.pngbin1313 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/hev1.pngbin1261 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/hevc.pngbin1261 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/hvc1.pngbin1261 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/mp4v.pngbin1362 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/mpeg1.pngbin1294 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/mpeg1video.pngbin1294 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/mpeg2.pngbin1429 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/mpeg2video.pngbin1429 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/mpeg4.pngbin1362 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/theora.pngbin1515 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/tv.pngbin708 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/vc-1.pngbin1045 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/vc1.pngbin1045 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/vhs.pngbin1097 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/vp8.pngbin1193 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/vp9.pngbin1143 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/wmv.pngbin1394 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/wmv3.pngbin1394 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/wvc1.pngbin1045 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videocodec/xvid.pngbin1195 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videohdr/dolbyvision.pngbin2759 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videohdr/hdr10.pngbin2910 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videohdr/hlg.pngbin2078 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videoresolution/1080.pngbin1441 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videoresolution/3D.pngbin938 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videoresolution/480.pngbin1594 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videoresolution/4K.pngbin814 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videoresolution/540.pngbin1541 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videoresolution/576.pngbin1451 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videoresolution/720.pngbin1317 -> 0 bytes
-rw-r--r--addons/skin.estuary/media/flags/videoresolution/8K.pngbin1277 -> 0 bytes
-rw-r--r--addons/skin.estuary/xml/DialogPVRGuideSearch.xml36
-rw-r--r--addons/skin.estuary/xml/DialogSeekBar.xml113
-rw-r--r--addons/skin.estuary/xml/Home.xml5
-rw-r--r--addons/skin.estuary/xml/Includes.xml284
-rw-r--r--addons/skin.estuary/xml/Variables.xml173
-rw-r--r--cmake/modules/FindCurl.cmake4
-rw-r--r--tools/depends/target/curl/01-win-nghttp2-add-name.patch11
-rw-r--r--tools/depends/target/curl/CURL-VERSION4
-rw-r--r--xbmc/FileItem.cpp75
-rw-r--r--xbmc/FileItem.h26
-rw-r--r--xbmc/pvr/PVRContextMenus.cpp15
-rw-r--r--xbmc/pvr/PVRDatabase.cpp5
-rw-r--r--xbmc/pvr/dialogs/GUIDialogPVRGuideSearch.cpp15
-rw-r--r--xbmc/pvr/epg/EpgDatabase.cpp66
-rw-r--r--xbmc/pvr/epg/EpgDatabase.h2
-rw-r--r--xbmc/pvr/epg/EpgSearchData.h8
-rw-r--r--xbmc/pvr/epg/EpgSearchFilter.cpp30
-rw-r--r--xbmc/pvr/epg/EpgSearchFilter.h238
-rw-r--r--xbmc/pvr/guilib/PVRGUIActionsEPG.cpp19
-rw-r--r--xbmc/pvr/guilib/PVRGUIActionsEPG.h7
-rw-r--r--xbmc/pvr/windows/GUIWindowPVRSearch.cpp2
-rw-r--r--xbmc/test/TestFileItem.cpp57
-rw-r--r--xbmc/utils/ArtUtils.cpp65
-rw-r--r--xbmc/utils/ArtUtils.h18
-rw-r--r--xbmc/utils/test/TestArtUtils.cpp122
-rw-r--r--xbmc/video/VideoDatabase.cpp10
-rw-r--r--xbmc/video/VideoInfoScanner.cpp12
129 files changed, 852 insertions, 586 deletions
diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po
index 96fa299ac1..46d1d6174f 100644
--- a/addons/resource.language.en_gb/resources/strings.po
+++ b/addons/resource.language.en_gb/resources/strings.po
@@ -3704,6 +3704,7 @@ msgid "Any channel"
msgstr ""
#. Label of "Start any time" radio button in PVR timer settings dialog
+#: addons/skin.estuary/xml/DialogPVRGuideSearch.xml
#: xbmc/pvr/dialogs/GUIDialogPVRTimerSettings.cpp
msgctxt "#810"
msgid "Start any time"
@@ -3750,6 +3751,7 @@ msgid "Record only new episodes"
msgstr ""
#. Label of "End any time" radio button in PVR timer settings dialog
+#: addons/skin.estuary/xml/DialogPVRGuideSearch.xml
#: xbmc/pvr/dialogs/GUIDialogPVRTimerSettings.cpp
msgctxt "#817"
msgid "End any time"
@@ -11853,7 +11855,19 @@ msgctxt "#19354"
msgid "Play only this programme"
msgstr ""
-#empty strings from id 19355 to 19498
+#. Label of a context menu entry to create a copy of an EPG saved saerch
+#: xbmc/pvr/PVRContextMenus.cpp
+msgctxt "#19355"
+msgid "Duplicate"
+msgstr ""
+
+#. Initial title of a duplicated EPG saved search.
+#: xbmc/pvr/PVRContextMenus.cpp
+msgctxt "#19356"
+msgid "Copy of '{0:s}'"
+msgstr ""
+
+#empty strings from id 19357 to 19498
#. label for epg genre value
#: xbmc/pvr/epg/Epg.cpp
diff --git a/addons/skin.estuary/media/flags/aspectratio/1.00.png b/addons/skin.estuary/media/flags/aspectratio/1.00.png
deleted file mode 100644
index eb41c15f7f..0000000000
--- a/addons/skin.estuary/media/flags/aspectratio/1.00.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/aspectratio/1.19.png b/addons/skin.estuary/media/flags/aspectratio/1.19.png
deleted file mode 100644
index 80289ae466..0000000000
--- a/addons/skin.estuary/media/flags/aspectratio/1.19.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/aspectratio/1.33.png b/addons/skin.estuary/media/flags/aspectratio/1.33.png
deleted file mode 100644
index 43e079495a..0000000000
--- a/addons/skin.estuary/media/flags/aspectratio/1.33.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/aspectratio/1.37.png b/addons/skin.estuary/media/flags/aspectratio/1.37.png
deleted file mode 100644
index e86c6f7a1d..0000000000
--- a/addons/skin.estuary/media/flags/aspectratio/1.37.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/aspectratio/1.66.png b/addons/skin.estuary/media/flags/aspectratio/1.66.png
deleted file mode 100644
index 80ca726bcc..0000000000
--- a/addons/skin.estuary/media/flags/aspectratio/1.66.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/aspectratio/1.78.png b/addons/skin.estuary/media/flags/aspectratio/1.78.png
deleted file mode 100644
index 01d70b832d..0000000000
--- a/addons/skin.estuary/media/flags/aspectratio/1.78.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/aspectratio/1.85.png b/addons/skin.estuary/media/flags/aspectratio/1.85.png
deleted file mode 100644
index 479804fde6..0000000000
--- a/addons/skin.estuary/media/flags/aspectratio/1.85.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/aspectratio/2.00.png b/addons/skin.estuary/media/flags/aspectratio/2.00.png
deleted file mode 100644
index cd8ff2569f..0000000000
--- a/addons/skin.estuary/media/flags/aspectratio/2.00.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/aspectratio/2.20.png b/addons/skin.estuary/media/flags/aspectratio/2.20.png
deleted file mode 100644
index d0cebe276e..0000000000
--- a/addons/skin.estuary/media/flags/aspectratio/2.20.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/aspectratio/2.35.png b/addons/skin.estuary/media/flags/aspectratio/2.35.png
deleted file mode 100644
index cacb088692..0000000000
--- a/addons/skin.estuary/media/flags/aspectratio/2.35.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/aspectratio/2.40.png b/addons/skin.estuary/media/flags/aspectratio/2.40.png
deleted file mode 100644
index 35aff17350..0000000000
--- a/addons/skin.estuary/media/flags/aspectratio/2.40.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/aspectratio/2.55.png b/addons/skin.estuary/media/flags/aspectratio/2.55.png
deleted file mode 100644
index a592e04fbe..0000000000
--- a/addons/skin.estuary/media/flags/aspectratio/2.55.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/aspectratio/2.76.png b/addons/skin.estuary/media/flags/aspectratio/2.76.png
deleted file mode 100644
index 051e671b6a..0000000000
--- a/addons/skin.estuary/media/flags/aspectratio/2.76.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiochannel/0.png b/addons/skin.estuary/media/flags/audiochannel/0.png
deleted file mode 100644
index a5be90821a..0000000000
--- a/addons/skin.estuary/media/flags/audiochannel/0.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiochannel/1.png b/addons/skin.estuary/media/flags/audiochannel/1.png
deleted file mode 100644
index 87f541c99c..0000000000
--- a/addons/skin.estuary/media/flags/audiochannel/1.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiochannel/10.png b/addons/skin.estuary/media/flags/audiochannel/10.png
deleted file mode 100644
index 49ed3ec3ab..0000000000
--- a/addons/skin.estuary/media/flags/audiochannel/10.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiochannel/2.png b/addons/skin.estuary/media/flags/audiochannel/2.png
deleted file mode 100644
index c7102b6c22..0000000000
--- a/addons/skin.estuary/media/flags/audiochannel/2.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiochannel/3.png b/addons/skin.estuary/media/flags/audiochannel/3.png
deleted file mode 100644
index 5f9b0cca6d..0000000000
--- a/addons/skin.estuary/media/flags/audiochannel/3.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiochannel/4.png b/addons/skin.estuary/media/flags/audiochannel/4.png
deleted file mode 100644
index 67c04c0e03..0000000000
--- a/addons/skin.estuary/media/flags/audiochannel/4.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiochannel/5.png b/addons/skin.estuary/media/flags/audiochannel/5.png
deleted file mode 100644
index a7f5f895ac..0000000000
--- a/addons/skin.estuary/media/flags/audiochannel/5.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiochannel/6.png b/addons/skin.estuary/media/flags/audiochannel/6.png
deleted file mode 100644
index d35e28d8e4..0000000000
--- a/addons/skin.estuary/media/flags/audiochannel/6.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiochannel/7.png b/addons/skin.estuary/media/flags/audiochannel/7.png
deleted file mode 100644
index e026a26753..0000000000
--- a/addons/skin.estuary/media/flags/audiochannel/7.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiochannel/8.png b/addons/skin.estuary/media/flags/audiochannel/8.png
deleted file mode 100644
index b32fc36ab4..0000000000
--- a/addons/skin.estuary/media/flags/audiochannel/8.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/aac.png b/addons/skin.estuary/media/flags/audiocodec/aac.png
deleted file mode 100644
index 55e81409b7..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/aac.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/aac_latm.png b/addons/skin.estuary/media/flags/audiocodec/aac_latm.png
deleted file mode 100644
index 55e81409b7..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/aac_latm.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/ac3.png b/addons/skin.estuary/media/flags/audiocodec/ac3.png
deleted file mode 100644
index d01a87739e..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/ac3.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/aif.png b/addons/skin.estuary/media/flags/audiocodec/aif.png
deleted file mode 100644
index ce4677858b..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/aif.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/aifc.png b/addons/skin.estuary/media/flags/audiocodec/aifc.png
deleted file mode 100644
index ed9a26c6bb..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/aifc.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/aiff.png b/addons/skin.estuary/media/flags/audiocodec/aiff.png
deleted file mode 100644
index ce4677858b..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/aiff.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/alac.png b/addons/skin.estuary/media/flags/audiocodec/alac.png
deleted file mode 100644
index a49527cf6a..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/alac.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/ape.png b/addons/skin.estuary/media/flags/audiocodec/ape.png
deleted file mode 100644
index 94e01abf20..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/ape.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/avc.png b/addons/skin.estuary/media/flags/audiocodec/avc.png
deleted file mode 100644
index 91aa179870..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/avc.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/cdda.png b/addons/skin.estuary/media/flags/audiocodec/cdda.png
deleted file mode 100644
index 3f257dd567..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/cdda.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/dca.png b/addons/skin.estuary/media/flags/audiocodec/dca.png
deleted file mode 100644
index 1dc52ec67f..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/dca.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/dolbydigital.png b/addons/skin.estuary/media/flags/audiocodec/dolbydigital.png
deleted file mode 100644
index d01a87739e..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/dolbydigital.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/dts.png b/addons/skin.estuary/media/flags/audiocodec/dts.png
deleted file mode 100644
index 1dc52ec67f..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/dts.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/dtshd_hra.png b/addons/skin.estuary/media/flags/audiocodec/dtshd_hra.png
deleted file mode 100644
index 53ffb9002b..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/dtshd_hra.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/dtshd_ma.png b/addons/skin.estuary/media/flags/audiocodec/dtshd_ma.png
deleted file mode 100644
index f20256e591..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/dtshd_ma.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/dtsma.png b/addons/skin.estuary/media/flags/audiocodec/dtsma.png
deleted file mode 100644
index f20256e591..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/dtsma.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/eac3.png b/addons/skin.estuary/media/flags/audiocodec/eac3.png
deleted file mode 100644
index d01a87739e..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/eac3.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/flac.png b/addons/skin.estuary/media/flags/audiocodec/flac.png
deleted file mode 100644
index f173541ebd..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/flac.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/mp1.png b/addons/skin.estuary/media/flags/audiocodec/mp1.png
deleted file mode 100644
index d3065f1b95..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/mp1.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/mp2.png b/addons/skin.estuary/media/flags/audiocodec/mp2.png
deleted file mode 100644
index ed4e21eefe..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/mp2.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/mp3.png b/addons/skin.estuary/media/flags/audiocodec/mp3.png
deleted file mode 100644
index 258d161f5a..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/mp3.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/mp3float.png b/addons/skin.estuary/media/flags/audiocodec/mp3float.png
deleted file mode 100644
index 258d161f5a..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/mp3float.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/ogg.png b/addons/skin.estuary/media/flags/audiocodec/ogg.png
deleted file mode 100644
index 208200a63e..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/ogg.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/opus.png b/addons/skin.estuary/media/flags/audiocodec/opus.png
deleted file mode 100644
index df856a6d57..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/opus.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/pcm.png b/addons/skin.estuary/media/flags/audiocodec/pcm.png
deleted file mode 100644
index 0c7a5bdeee..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/pcm.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/pcm_bluray.png b/addons/skin.estuary/media/flags/audiocodec/pcm_bluray.png
deleted file mode 100644
index 30b4f8b138..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/pcm_bluray.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/pcm_s16le.png b/addons/skin.estuary/media/flags/audiocodec/pcm_s16le.png
deleted file mode 100644
index dc514806e3..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/pcm_s16le.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/pcm_s24le.png b/addons/skin.estuary/media/flags/audiocodec/pcm_s24le.png
deleted file mode 100644
index 81ceacc06d..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/pcm_s24le.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/truehd.png b/addons/skin.estuary/media/flags/audiocodec/truehd.png
deleted file mode 100644
index 4bcf8c1fda..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/truehd.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/vorbis.png b/addons/skin.estuary/media/flags/audiocodec/vorbis.png
deleted file mode 100644
index e7ec2c5361..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/vorbis.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/wav.png b/addons/skin.estuary/media/flags/audiocodec/wav.png
deleted file mode 100644
index 76cd02d3fc..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/wav.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/wavpack.png b/addons/skin.estuary/media/flags/audiocodec/wavpack.png
deleted file mode 100644
index 6501af9942..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/wavpack.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/wma.png b/addons/skin.estuary/media/flags/audiocodec/wma.png
deleted file mode 100644
index 20093c15d5..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/wma.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/wmapro.png b/addons/skin.estuary/media/flags/audiocodec/wmapro.png
deleted file mode 100644
index 20093c15d5..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/wmapro.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/audiocodec/wmav2.png b/addons/skin.estuary/media/flags/audiocodec/wmav2.png
deleted file mode 100644
index 20093c15d5..0000000000
--- a/addons/skin.estuary/media/flags/audiocodec/wmav2.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/rds/rds.png b/addons/skin.estuary/media/flags/rds/rds.png
deleted file mode 100644
index e5de4ccfcf..0000000000
--- a/addons/skin.estuary/media/flags/rds/rds.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/av1.png b/addons/skin.estuary/media/flags/videocodec/av1.png
deleted file mode 100644
index f594b9ea9c..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/av1.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/avc1.png b/addons/skin.estuary/media/flags/videocodec/avc1.png
deleted file mode 100644
index 78da5d8936..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/avc1.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/bluray.png b/addons/skin.estuary/media/flags/videocodec/bluray.png
deleted file mode 100644
index b8fe922c6d..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/bluray.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/div3.png b/addons/skin.estuary/media/flags/videocodec/div3.png
deleted file mode 100644
index 65a9a6517c..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/div3.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/divx.png b/addons/skin.estuary/media/flags/videocodec/divx.png
deleted file mode 100644
index 65a9a6517c..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/divx.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/dvd.png b/addons/skin.estuary/media/flags/videocodec/dvd.png
deleted file mode 100644
index 9e9bd97ab0..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/dvd.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/dx50.png b/addons/skin.estuary/media/flags/videocodec/dx50.png
deleted file mode 100644
index 65a9a6517c..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/dx50.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/flv.png b/addons/skin.estuary/media/flags/videocodec/flv.png
deleted file mode 100644
index 8b1b5775d5..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/flv.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/h264.png b/addons/skin.estuary/media/flags/videocodec/h264.png
deleted file mode 100644
index 64cfa04ec9..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/h264.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/hddvd.png b/addons/skin.estuary/media/flags/videocodec/hddvd.png
deleted file mode 100644
index 4a170a91b6..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/hddvd.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/hdmv.png b/addons/skin.estuary/media/flags/videocodec/hdmv.png
deleted file mode 100644
index b8fe922c6d..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/hdmv.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/hev1.png b/addons/skin.estuary/media/flags/videocodec/hev1.png
deleted file mode 100644
index 1e1d3c186b..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/hev1.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/hevc.png b/addons/skin.estuary/media/flags/videocodec/hevc.png
deleted file mode 100644
index 1e1d3c186b..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/hevc.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/hvc1.png b/addons/skin.estuary/media/flags/videocodec/hvc1.png
deleted file mode 100644
index 1e1d3c186b..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/hvc1.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/mp4v.png b/addons/skin.estuary/media/flags/videocodec/mp4v.png
deleted file mode 100644
index da9d967bb8..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/mp4v.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/mpeg1.png b/addons/skin.estuary/media/flags/videocodec/mpeg1.png
deleted file mode 100644
index 8b210cf2d1..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/mpeg1.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/mpeg1video.png b/addons/skin.estuary/media/flags/videocodec/mpeg1video.png
deleted file mode 100644
index 8b210cf2d1..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/mpeg1video.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/mpeg2.png b/addons/skin.estuary/media/flags/videocodec/mpeg2.png
deleted file mode 100644
index f46483b765..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/mpeg2.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/mpeg2video.png b/addons/skin.estuary/media/flags/videocodec/mpeg2video.png
deleted file mode 100644
index f46483b765..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/mpeg2video.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/mpeg4.png b/addons/skin.estuary/media/flags/videocodec/mpeg4.png
deleted file mode 100644
index da9d967bb8..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/mpeg4.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/theora.png b/addons/skin.estuary/media/flags/videocodec/theora.png
deleted file mode 100644
index 8f1af4bb94..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/theora.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/tv.png b/addons/skin.estuary/media/flags/videocodec/tv.png
deleted file mode 100644
index b7cb357442..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/tv.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/vc-1.png b/addons/skin.estuary/media/flags/videocodec/vc-1.png
deleted file mode 100644
index 843497f6a9..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/vc-1.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/vc1.png b/addons/skin.estuary/media/flags/videocodec/vc1.png
deleted file mode 100644
index 843497f6a9..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/vc1.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/vhs.png b/addons/skin.estuary/media/flags/videocodec/vhs.png
deleted file mode 100644
index a1a4ff3198..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/vhs.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/vp8.png b/addons/skin.estuary/media/flags/videocodec/vp8.png
deleted file mode 100644
index d9ad357901..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/vp8.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/vp9.png b/addons/skin.estuary/media/flags/videocodec/vp9.png
deleted file mode 100644
index c09a28cb10..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/vp9.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/wmv.png b/addons/skin.estuary/media/flags/videocodec/wmv.png
deleted file mode 100644
index 34a7cedf3b..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/wmv.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/wmv3.png b/addons/skin.estuary/media/flags/videocodec/wmv3.png
deleted file mode 100644
index 34a7cedf3b..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/wmv3.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/wvc1.png b/addons/skin.estuary/media/flags/videocodec/wvc1.png
deleted file mode 100644
index 843497f6a9..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/wvc1.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videocodec/xvid.png b/addons/skin.estuary/media/flags/videocodec/xvid.png
deleted file mode 100644
index b835bf6873..0000000000
--- a/addons/skin.estuary/media/flags/videocodec/xvid.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videohdr/dolbyvision.png b/addons/skin.estuary/media/flags/videohdr/dolbyvision.png
deleted file mode 100644
index 5875eb80e7..0000000000
--- a/addons/skin.estuary/media/flags/videohdr/dolbyvision.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videohdr/hdr10.png b/addons/skin.estuary/media/flags/videohdr/hdr10.png
deleted file mode 100644
index e4b671fe12..0000000000
--- a/addons/skin.estuary/media/flags/videohdr/hdr10.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videohdr/hlg.png b/addons/skin.estuary/media/flags/videohdr/hlg.png
deleted file mode 100644
index a8bc078d70..0000000000
--- a/addons/skin.estuary/media/flags/videohdr/hlg.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videoresolution/1080.png b/addons/skin.estuary/media/flags/videoresolution/1080.png
deleted file mode 100644
index fa076b8d2d..0000000000
--- a/addons/skin.estuary/media/flags/videoresolution/1080.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videoresolution/3D.png b/addons/skin.estuary/media/flags/videoresolution/3D.png
deleted file mode 100644
index 9b6c26254f..0000000000
--- a/addons/skin.estuary/media/flags/videoresolution/3D.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videoresolution/480.png b/addons/skin.estuary/media/flags/videoresolution/480.png
deleted file mode 100644
index 66deb31b80..0000000000
--- a/addons/skin.estuary/media/flags/videoresolution/480.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videoresolution/4K.png b/addons/skin.estuary/media/flags/videoresolution/4K.png
deleted file mode 100644
index f3d13bdccf..0000000000
--- a/addons/skin.estuary/media/flags/videoresolution/4K.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videoresolution/540.png b/addons/skin.estuary/media/flags/videoresolution/540.png
deleted file mode 100644
index dd6c3823d1..0000000000
--- a/addons/skin.estuary/media/flags/videoresolution/540.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videoresolution/576.png b/addons/skin.estuary/media/flags/videoresolution/576.png
deleted file mode 100644
index 8a96be926c..0000000000
--- a/addons/skin.estuary/media/flags/videoresolution/576.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videoresolution/720.png b/addons/skin.estuary/media/flags/videoresolution/720.png
deleted file mode 100644
index 0b6406004a..0000000000
--- a/addons/skin.estuary/media/flags/videoresolution/720.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/media/flags/videoresolution/8K.png b/addons/skin.estuary/media/flags/videoresolution/8K.png
deleted file mode 100644
index de46f91e9b..0000000000
--- a/addons/skin.estuary/media/flags/videoresolution/8K.png
+++ /dev/null
Binary files differ
diff --git a/addons/skin.estuary/xml/DialogPVRGuideSearch.xml b/addons/skin.estuary/xml/DialogPVRGuideSearch.xml
index e1e766025e..8ac09e05d0 100644
--- a/addons/skin.estuary/xml/DialogPVRGuideSearch.xml
+++ b/addons/skin.estuary/xml/DialogPVRGuideSearch.xml
@@ -5,12 +5,12 @@
<controls>
<control type="group">
<centertop>50%</centertop>
- <height>890</height>
+ <height>960</height>
<centerleft>50%</centerleft>
<width>1780</width>
<include content="DialogBackgroundCommons">
<param name="width" value="1780" />
- <param name="height" value="890" />
+ <param name="height" value="960" />
<param name="header_label" value="$LOCALIZE[19142]" />
<param name="header_id" value="2" />
</include>
@@ -41,7 +41,7 @@
<left>10</left>
<top>210</top>
<width>1460</width>
- <height>675</height>
+ <height>740</height>
<texture border="40">buttons/dialogbutton-nofo.png</texture>
</control>
<control type="grouplist" id="5000">
@@ -69,16 +69,23 @@
<control type="edit" id="14">
<description>Start Date</description>
<width>710</width>
- <onright>16</onright>
+ <onright>15</onright>
<include>DefaultSettingButton</include>
<label>$LOCALIZE[19128]</label>
</control>
- <control type="edit" id="15">
- <description>Stop Date</description>
+ <control type="radiobutton" id="32">
+ <description>Start any time</description>
+ <width>710</width>
+ <onright>33</onright>
+ <include>DefaultSettingButton</include>
+ <label>$LOCALIZE[810]</label>
+ </control>
+ <control type="edit" id="16">
+ <description>Start time</description>
<width>710</width>
<onright>17</onright>
<include>DefaultSettingButton</include>
- <label>$LOCALIZE[19129]</label>
+ <label>$LOCALIZE[19126]</label>
</control>
<control type="radiobutton" id="30">
<description>Ignore finished broadcasts</description>
@@ -138,17 +145,24 @@
<include>DefaultSettingButton</include>
<label>$LOCALIZE[19131]</label>
</control>
- <control type="edit" id="16">
- <description>Start time</description>
+ <control type="edit" id="15">
+ <description>Stop Date</description>
<width>710</width>
<onleft>14</onleft>
<include>DefaultSettingButton</include>
- <label>$LOCALIZE[19126]</label>
+ <label>$LOCALIZE[19129]</label>
+ </control>
+ <control type="radiobutton" id="33">
+ <description>End any time</description>
+ <width>710</width>
+ <onleft>32</onleft>
+ <include>DefaultSettingButton</include>
+ <label>$LOCALIZE[817]</label>
</control>
<control type="edit" id="17">
<description>Stop time</description>
<width>710</width>
- <onleft>15</onleft>
+ <onleft>16</onleft>
<include>DefaultSettingButton</include>
<label>$LOCALIZE[19127]</label>
</control>
diff --git a/addons/skin.estuary/xml/DialogSeekBar.xml b/addons/skin.estuary/xml/DialogSeekBar.xml
index 5e870977a5..958757d98b 100644
--- a/addons/skin.estuary/xml/DialogSeekBar.xml
+++ b/addons/skin.estuary/xml/DialogSeekBar.xml
@@ -49,115 +49,14 @@
<label>[COLOR red][B]$LOCALIZE[19158][/B][/COLOR]</label>
</control>
</control>
- <control type="grouplist">
- <right>20</right>
- <centertop>125</centertop>
- <width>800</width>
- <height>50</height>
- <align>right</align>
- <include>Animation_BottomSlide</include>
- <orientation>horizontal</orientation>
- <itemgap>5</itemgap>
- <visible>[Player.ShowInfo | Window.IsActive(fullscreeninfo)] + !Player.ChannelPreviewActive + Window.IsActive(fullscreenvideo)</visible>
- <animation effect="fade" start="0" end="100" time="200" delay="1000">Visible</animation>
- <include content="MediaFlag">
- <param name="texture" value="$INFO[VideoPlayer.VideoCodec,flags/videocodec/,.png]" />
- <param name="visible" value="!String.IsEmpty(VideoPlayer.VideoCodec)" />
- </include>
- <include content="MediaFlag">
- <param name="texture" value="$INFO[VideoPlayer.VideoResolution,flags/videoresolution/,.png]" />
- <param name="visible" value="!String.IsEmpty(VideoPlayer.VideoResolution)" />
- </include>
- <include content="MediaFlag">
- <param name="texture" value="$INFO[VideoPlayer.HdrType,flags/videohdr/,.png]" />
- <param name="visible" value="!String.IsEmpty(VideoPlayer.HdrType)" />
- </include>
- <include content="MediaFlag">
- <param name="texture" value="$INFO[VideoPlayer.VideoAspect,flags/aspectratio/,.png]" />
- <param name="visible" value="!String.IsEmpty(VideoPlayer.VideoAspect)" />
- </include>
- <include content="MediaFlag">
- <param name="texture" value="$INFO[VideoPlayer.AudioCodec,flags/audiocodec/,.png]" />
- <param name="visible" value="!String.IsEmpty(VideoPlayer.AudioCodec)" />
- </include>
- <include content="MediaFlag">
- <param name="texture" value="$INFO[VideoPlayer.AudioChannels,flags/audiochannel/,.png]" />
- <param name="visible" value="!String.IsEmpty(VideoPlayer.AudioChannels)" />
- </include>
- </control>
- <control type="grouplist">
- <right>20</right>
- <centertop>125</centertop>
- <width>800</width>
- <height>50</height>
- <align>right</align>
- <include>Animation_BottomSlide</include>
- <orientation>horizontal</orientation>
- <itemgap>10</itemgap>
- <visible>Player.ShowInfo + !Player.ChannelPreviewActive + Window.IsActive(visualisation)</visible>
- <animation effect="fade" start="0" end="100" time="200" delay="1000">Visible</animation>
- <include content="MediaFlag">
- <param name="texture" value="flags/rds/rds.png" />
- <param name="visible" value="RDS.HasRDS" />
- </include>
- <include content="MediaFlag">
- <param name="texture" value="$INFO[MusicPlayer.Codec,flags/audiocodec/,.png]" />
- <param name="visible" value="!String.IsEmpty(MusicPlayer.Codec)" />
- </include>
- <include content="MediaFlag">
- <param name="texture" value="$INFO[MusicPlayer.Channels,flags/audiochannel/,.png]" />
- <param name="visible" value="!String.IsEmpty(MusicPlayer.Channels)" />
- </include>
- <control type="group">
- <visible>!String.IsEmpty(MusicPlayer.SampleRate)</visible>
- <width>115</width>
- <control type="label">
- <width>115</width>
- <height>60</height>
- <align>center</align>
- <aligny>center</aligny>
- <label>$INFO[MusicPlayer.SampleRate, ,kHz]</label>
- <font>font_flag</font>
- </control>
- <include content="MediaFlag">
- <param name="texture" value="flags/flag.png" />
- </include>
- </control>
- <control type="group">
- <visible>!String.IsEmpty(MusicPlayer.BitRate)</visible>
- <width>115</width>
- <control type="label">
- <width>115</width>
- <height>60</height>
- <align>center</align>
- <aligny>center</aligny>
- <label>$INFO[MusicPlayer.BitRate, ,kbps ]</label>
- <font>font_flag</font>
- </control>
- <include content="MediaFlag">
- <param name="texture" value="flags/flag.png" />
- </include>
- </control>
- <control type="group">
- <visible>!String.IsEmpty(MusicPlayer.BitsPerSample)</visible>
- <width>115</width>
- <control type="label">
- <width>115</width>
- <height>60</height>
- <align>center</align>
- <aligny>center</aligny>
- <label>$INFO[MusicPlayer.BitsPerSample, ,bit]</label>
- <font>font_flag</font>
- </control>
- <include content="MediaFlag">
- <param name="texture" value="flags/flag.png" />
- </include>
- </control>
+ <control type="group">
+ <top>195</top>
+ <include condition="!Skin.HasSetting(hide_mediaflags)">MediaFlags</include>
</control>
</control>
<control type="label">
<centerleft>50%</centerleft>
- <centertop>125</centertop>
+ <centertop>120</centertop>
<width>50%</width>
<height>60</height>
<align>center</align>
@@ -170,8 +69,8 @@
<control type="label" id="40000">
<centerleft>50%</centerleft>
<centertop>175</centertop>
- <width>50%</width>
- <height>50</height>
+ <width>380</width>
+ <height>60</height>
<align>center</align>
<aligny>top</aligny>
<label>$VAR[SeekLabel]</label>
diff --git a/addons/skin.estuary/xml/Home.xml b/addons/skin.estuary/xml/Home.xml
index 24d032df23..5ac611a33f 100644
--- a/addons/skin.estuary/xml/Home.xml
+++ b/addons/skin.estuary/xml/Home.xml
@@ -1120,10 +1120,7 @@
<height>70</height>
<animation effect="fade" start="0" end="100" time="300" delay="300">WindowOpen</animation>
<animation effect="fade" start="100" end="0" time="200">WindowClose</animation>
- <include condition="!Skin.HasSetting(hide_mediaflags)" content="MediaFlags">
- <param name="infolabel_prefix" value="Container." />
- <param name="resolution_var" value="$VAR[ContainerResolutionFlagVar]" />
- </include>
+ <include condition="!Skin.HasSetting(hide_mediaflags)">MediaFlags</include>
<control type="rss">
<animation effect="slide" end="0,90" time="300" tween="sine" easing="inout" condition="$EXP[infodialog_active]">conditional</animation>
<left>0</left>
diff --git a/addons/skin.estuary/xml/Includes.xml b/addons/skin.estuary/xml/Includes.xml
index 294f13e800..b649528a36 100644
--- a/addons/skin.estuary/xml/Includes.xml
+++ b/addons/skin.estuary/xml/Includes.xml
@@ -339,37 +339,47 @@
<include name="MediaFlag">
<param name="width">115</param>
<param name="height">60</param>
- <param name="visible">true</param>
+ <param name="flag_visible">true</param>
+ <param name="texture">flags/flag.png</param>
<definition>
- <control type="image">
+ <control type="group">
<width>$PARAM[width]</width>
<height>$PARAM[height]</height>
- <fadetime>0</fadetime>
- <aspectratio align="center" aligny="center">keep</aspectratio>
- <texture>$PARAM[texture]</texture>
- <visible>$PARAM[visible]</visible>
+ <visible>$PARAM[flag_visible]</visible>
+ <control type="image">
+ <fadetime>0</fadetime>
+ <align>center</align>
+ <aligny>center</aligny>
+ <aspectratio>keep</aspectratio>
+ <texture>$PARAM[texture]</texture>
+ </control>
+ <control type="label">
+ <align>center</align>
+ <aligny>center</aligny>
+ <label>$PARAM[flag_label]</label>
+ <font>font_flag</font>
+ </control>
</control>
</definition>
</include>
<include name="MediaFlags">
- <param name="infolabel_prefix"></param>
- <param name="resolution_var">$VAR[ResolutionFlagVar]</param>
+ <param name="visible">true</param>
<definition>
<control type="grouplist">
<visible>Window.IsActive(Home) | Window.IsActive(10025)</visible>
<orientation>horizontal</orientation>
<right>20</right>
- <top>0</top>
- <height>70</height>
+ <bottom>0</bottom>
+ <height>60</height>
<align>right</align>
<itemgap>10</itemgap>
<width>1900</width>
<usecontrolcoords>true</usecontrolcoords>
<control type="group">
<width>150</width>
- <visible>System.AddonIsEnabled(resource.images.studios.white) + !String.IsEmpty($PARAM[infolabel_prefix]ListItem.Studio)</visible>
+ <visible>System.AddonIsEnabled(resource.images.studios.white) + !String.IsEmpty(ListItem.Studio)</visible>
<include content="MediaFlag">
- <param name="texture" value="$INFO[$PARAM[infolabel_prefix]ListItem.Studio,resource://resource.images.studios.white/,.png]" />
+ <param name="texture" value="$INFO[ListItem.Studio,resource://resource.images.studios.white/,.png]" />
</include>
</control>
<control type="group">
@@ -378,154 +388,158 @@
<visible>!String.IsEmpty($PARAM[infolabel_prefix]ListItem.Premiered)</visible>
<include content="InfoFlag">
<param name="icon" value="lists/year.png" />
- <param name="label" value="$INFO[$PARAM[infolabel_prefix]ListItem.Premiered]" />
- </include>
- </control>
- <control type="group">
- <width>115</width>
- <visible>!String.IsEmpty($PARAM[infolabel_prefix]ListItem.Duration)</visible>
- <control type="label">
- <width>115</width>
- <height>60</height>
- <align>center</align>
- <aligny>center</aligny>
- <label>$INFO[$PARAM[infolabel_prefix]ListItem.Duration]</label>
- <font>font_flag</font>
- </control>
- <include content="MediaFlag">
- <param name="texture" value="flags/flag.png" />
+ <param name="label" value="$INFO[ListItem.Premiered]" />
</include>
</control>
<include content="MediaFlag">
- <param name="texture" value="$INFO[ListItem.VideoCodec,flags/videocodec/,.png]" />
- <param name="visible" value="!String.IsEmpty($PARAM[infolabel_prefix]ListItem.VideoCodec)" />
+ <param name="flag_visible" value="!String.IsEmpty(ListItem.Duration)" />
+ <param name="flag_label" value="$INFO[ListItem.Duration]" />
</include>
<include content="MediaFlag">
- <param name="texture" value="$PARAM[resolution_var]" />
- <param name="visible" value="!String.IsEmpty($PARAM[infolabel_prefix]ListItem.VideoResolution)" />
+ <param name="flag_visible" value="ListItem.IsStereoscopic" />
+ <param name="flag_label" value="3D" />
</include>
<include content="MediaFlag">
- <param name="texture" value="$INFO[ListItem.HdrType,flags/videohdr/,.png]" />
- <param name="visible" value="!String.IsEmpty($PARAM[infolabel_prefix]ListItem.HdrType)" />
+ <param name="flag_visible" value="!String.IsEmpty(ListItem.VideoCodec)" />
+ <param name="flag_label" value="$VAR[VideoListCodecVar]" />
</include>
<include content="MediaFlag">
- <param name="texture" value="$INFO[ListItem.VideoAspect,flags/aspectratio/,.png]" />
- <param name="visible" value="!String.IsEmpty($PARAM[infolabel_prefix]ListItem.VideoAspect)" />
+ <param name="flag_visible" value="!String.IsEmpty(ListItem.VideoResolution)" />
+ <param name="flag_label" value="$INFO[ListItem.VideoResolution]$VAR[VideoListResolutionTypeVar, ]" />
</include>
<include content="MediaFlag">
- <param name="texture" value="$INFO[$PARAM[infolabel_prefix]ListItem.AudioCodec,flags/audiocodec/,.png]" />
- <param name="visible" value="!String.IsEmpty($PARAM[infolabel_prefix]ListItem.AudioCodec)" />
+ <param name="flag_visible" value="!String.IsEmpty(ListItem.HdrType)" />
+ <param name="flag_label" value="$VAR[VideoListHDRVar]" />
</include>
<include content="MediaFlag">
- <param name="texture" value="$INFO[$PARAM[infolabel_prefix]ListItem.AudioChannels,flags/audiochannel/,.png]" />
- <param name="visible" value="!String.IsEmpty($PARAM[infolabel_prefix]ListItem.AudioChannels)" />
+ <param name="flag_visible" value="!String.IsEmpty(ListItem.VideoAspect)" />
+ <param name="flag_label" value="$INFO[ListItem.VideoAspect,,:1]" />
+ </include>
+ <include content="MediaFlag">
+ <param name="flag_visible" value="!String.IsEmpty(ListItem.AudioCodec)" />
+ <param name="flag_label" value="$VAR[AudioListCodecVar]" />
+ </include>
+ <include content="MediaFlag">
+ <param name="flag_visible" value="!String.IsEmpty(ListItem.AudioChannels)" />
+ <param name="flag_label" value="$VAR[AudioListChannelsVar]" />
+ </include>
+ </control>
+ <control type="grouplist">
+ <visible>[Player.ShowInfo | Window.IsActive(fullscreeninfo)] + !Player.ChannelPreviewActive + Window.IsActive(fullscreenvideo)</visible>
+ <orientation>horizontal</orientation>
+ <right>20</right>
+ <bottom>0</bottom>
+ <height>60</height>
+ <align>right</align>
+ <itemgap>10</itemgap>
+ <width>1900</width>
+ <usecontrolcoords>true</usecontrolcoords>
+ <include content="MediaFlag">
+ <param name="flag_visible" value="VideoPlayer.IsStereoscopic" />
+ <param name="flag_label" value="3D" />
+ </include>
+ <include content="MediaFlag">
+ <param name="flag_visible" value="!String.IsEmpty(VideoPlayer.VideoCodec)" />
+ <param name="flag_label" value="$VAR[VideoPlayerCodecVar]" />
+ </include>
+ <include content="MediaFlag">
+ <param name="flag_visible" value="!String.IsEmpty(VideoPlayer.VideoResolution)" />
+ <param name="flag_label" value="$INFO[VideoPlayer.VideoResolution]$VAR[VideoPlayerResolutionTypeVar, ]" />
+ </include>
+ <include content="MediaFlag">
+ <param name="flag_visible" value="!String.IsEmpty(VideoPlayer.HdrType)" />
+ <param name="flag_label" value="$VAR[VideoPlayerHDRVar]" />
+ </include>
+ <include content="MediaFlag">
+ <param name="flag_visible" value="!String.IsEmpty(VideoPlayer.VideoAspect)" />
+ <param name="flag_label" value="$INFO[VideoPlayer.VideoAspect,,:1]" />
+ </include>
+ <include content="MediaFlag">
+ <param name="flag_visible" value="!String.IsEmpty(VideoPlayer.AudioCodec)" />
+ <param name="flag_label" value="$VAR[VideoPlayerAudioCodecVar]" />
+ </include>
+ <include content="MediaFlag">
+ <param name="flag_visible" value="!String.IsEmpty(VideoPlayer.AudioChannels)" />
+ <param name="flag_label" value="$VAR[VideoPlayerAudioChannelsVar]" />
</include>
</control>
<control type="grouplist">
<visible>Container.Content(albums) | Window.IsActive(10502)</visible>
<orientation>horizontal</orientation>
<right>20</right>
- <top>0</top>
- <height>70</height>
+ <bottom>10</bottom>
+ <height>60</height>
<align>right</align>
<itemgap>10</itemgap>
<width>1900</width>
<usecontrolcoords>true</usecontrolcoords>
- <control type="group">
- <width>115</width>
- <visible>!String.IsEmpty($PARAM[infolabel_prefix]ListItem.Duration)</visible>
- <visible>Container.Content(albums) + ![Window.IsVisible(songinformation) | Window.IsVisible(musicinformation)]</visible>
- <control type="label">
- <width>110</width>
- <height>60</height>
- <align>center</align>
- <aligny>center</aligny>
- <label>$INFO[$PARAM[infolabel_prefix]ListItem.Duration]</label>
- <font>font_flag</font>
- </control>
- <include content="MediaFlag">
- <param name="texture" value="flags/flag.png" />
- </include>
- </control>
- <control type="group">
- <width>115</width>
- <visible>!String.IsEmpty($PARAM[infolabel_prefix]ListItem.FileExtension)</visible>
- <control type="label">
- <width>110</width>
- <height>60</height>
- <align>center</align>
- <aligny>center</aligny>
- <label>$INFO[$PARAM[infolabel_prefix]ListItem.FileExtension]</label>
- <font>font_flag</font>
- </control>
- <include content="MediaFlag">
- <param name="texture" value="flags/flag.png" />
- </include>
- </control>
<include content="MediaFlag">
- <param name="texture" value="$INFO[$PARAM[infolabel_prefix]ListItem.MusicChannels,flags/audiochannel/,.png]" />
- <param name="visible" value="!String.IsEmpty($PARAM[infolabel_prefix]ListItem.MusicChannels)" />
+ <param name="flag_visible" value="!String.IsEmpty(ListItem.Duration) + Container.Content(albums) + ![Window.IsVisible(songinformation) | Window.IsVisible(musicinformation)]" />
+ <param name="flag_label" value="$INFO[ListItem.Duration]" />
+ </include>
+ <include content="MediaFlag">
+ <param name="flag_visible" value="!String.IsEmpty(ListItem.FileExtension)" />
+ <param name="flag_label" value="$INFO[ListItem.FileExtension]" />
+ </include>
+ <include content="MediaFlag">
+ <param name="flag_visible" value="!String.IsEmpty(ListItem.MusicChannels)" />
+ <param name="flag_label" value="$VAR[MusicListChannelsVar]" />
+ </include>
+ <include content="MediaFlag">
+ <param name="flag_visible" value="!String.IsEmpty(ListItem.Samplerate)" />
+ <param name="flag_label" value="$INFO[ListItem.Samplerate, ,kHz]" />
+ </include>
+ <include content="MediaFlag">
+ <param name="flag_visible" value="!String.IsEmpty(ListItem.BitRate)" />
+ <param name="flag_label" value="$INFO[ListItem.BitRate, ,kbps]" />
+ </include>
+ <include content="MediaFlag">
+ <param name="flag_visible" value="!String.IsEmpty(ListItem.MusicBitsPerSample)" />
+ <param name="flag_label" value="$INFO[ListItem.MusicBitsPerSample, ,bit]" />
+ </include>
+ <include content="MediaFlag">
+ <param name="flag_visible" value="!String.IsEmpty(ListItem.BMP)" />
+ <param name="flag_label" value="$INFO[ListItem.BMP, ,bpm]" />
+ </include>
+ </control>
+ <control type="grouplist">
+ <visible>Player.ShowInfo + !Player.ChannelPreviewActive + Window.IsActive(visualisation)</visible>)
+ <orientation>horizontal</orientation>
+ <right>20</right>
+ <bottom>10</bottom>
+ <height>60</height>
+ <align>right</align>
+ <itemgap>10</itemgap>
+ <width>1900</width>
+ <usecontrolcoords>true</usecontrolcoords>
+ <include content="MediaFlag">
+ <param name="flag_visible" value="RDS.HasRDS" />
+ <param name="flag_label" value="RDS" />
+ </include>
+ <include content="MediaFlag">
+ <param name="flag_visible" value="!String.IsEmpty(MusicPlayer.Codec)" />
+ <param name="flag_label" value="$VAR[MusicPlayerCodecVar]" />
+ </include>
+ <include content="MediaFlag">
+ <param name="flag_visible" value="!String.IsEmpty(MusicPlayer.Channels)" />
+ <param name="flag_label" value="$VAR[MusicPlayerAudioChannelsVar]" />
+ </include>
+ <include content="MediaFlag">
+ <param name="flag_visible" value="!String.IsEmpty(MusicPlayer.SampleRate)" />
+ <param name="flag_label" value="$INFO[MusicPlayer.SampleRate, ,kHz]" />
+ </include>
+ <include content="MediaFlag">
+ <param name="flag_visible" value="!String.IsEmpty(MusicPlayer.BitRate)" />
+ <param name="flag_label" value="$INFO[MusicPlayer.BitRate, ,kbps]" />
+ </include>
+ <include content="MediaFlag">
+ <param name="flag_visible" value="!String.IsEmpty(MusicPlayer.BitsPerSample)" />
+ <param name="flag_label" value="$INFO[MusicPlayer.BitsPerSample, ,bit]" />
+ </include>
+ <include content="MediaFlag">
+ <param name="flag_visible" value="!String.IsEmpty(MusicPlayer.BMP)" />
+ <param name="flag_label" value="$INFO[MusicPlayer.BMP, ,bpm]" />
</include>
- <control type="group">
- <visible>!String.IsEmpty(ListItem.Samplerate)</visible>
- <width>115</width>
- <control type="label">
- <width>110</width>
- <height>60</height>
- <align>center</align>
- <aligny>center</aligny>
- <label>$INFO[ListItem.Samplerate, ,kHz]</label>
- <font>font_flag</font>
- </control>
- <include content="MediaFlag">
- <param name="texture" value="flags/flag.png" />
- </include>
- </control>
- <control type="group">
- <visible>!String.IsEmpty(ListItem.BitRate)</visible>
- <width>115</width>
- <control type="label">
- <width>110</width>
- <height>60</height>
- <align>center</align>
- <aligny>center</aligny>
- <label>$INFO[ListItem.BitRate, ,kbps]</label>
- <font>font_flag</font>
- </control>
- <include content="MediaFlag">
- <param name="texture" value="flags/flag.png" />
- </include>
- </control>
- <control type="group">
- <visible>!String.IsEmpty(ListItem.MusicBitsPerSample)</visible>
- <width>115</width>
- <control type="label">
- <width>110</width>
- <height>60</height>
- <align>center</align>
- <aligny>center</aligny>
- <label>$INFO[ListItem.MusicBitsPerSample, ,bit]</label>
- <font>font_flag</font>
- </control>
- <include content="MediaFlag">
- <param name="texture" value="flags/flag.png" />
- </include>
- </control>
- <control type="group">
- <visible>!String.IsEmpty(ListItem.BMP)</visible>
- <width>115</width>
- <control type="label">
- <width>110</width>
- <height>60</height>
- <align>center</align>
- <aligny>center</aligny>
- <label>$INFO[ListItem.BMP, ,bpm]</label>
- <font>font_flag</font>
- </control>
- <include content="MediaFlag">
- <param name="texture" value="flags/flag.png" />
- </include>
- </control>
</control>
</definition>
</include>
diff --git a/addons/skin.estuary/xml/Variables.xml b/addons/skin.estuary/xml/Variables.xml
index e5fd8b989b..48d31556df 100644
--- a/addons/skin.estuary/xml/Variables.xml
+++ b/addons/skin.estuary/xml/Variables.xml
@@ -708,7 +708,7 @@
<value condition="!String.IsEmpty(Container(50).ListItem.Art(thumb))">$INFO[Container(50).ListItem.Art(thumb)]</value>
<value>$INFO[ListItem.Art(thumb)]</value>
</variable>
- <variable name="VideoResolutionTypeVar">
+ <variable name="VideoListResolutionTypeVar">
<value condition="String.IsEqual(ListItem.VideoResolution,480)">SD</value>
<value condition="String.IsEqual(ListItem.VideoResolution,540)">SD</value>
<value condition="String.IsEqual(ListItem.VideoResolution,576)">SD</value>
@@ -716,8 +716,19 @@
<value condition="String.IsEqual(ListItem.VideoResolution,1080)">HD</value>
<value condition="String.IsEqual(ListItem.VideoResolution,4K)">UHD</value>
<value condition="String.IsEqual(ListItem.VideoResolution,8K)">UHD</value>
- </variable>
- <variable name="VideoCodecVar">
+ <value>$INFO[ListItem.VideoResolution]</value>
+ </variable>
+ <variable name="VideoPlayerResolutionTypeVar">
+ <value condition="String.IsEqual(VideoPlayer.VideoResolution,480)">SD</value>
+ <value condition="String.IsEqual(VideoPlayer.VideoResolution,540)">SD</value>
+ <value condition="String.IsEqual(VideoPlayer.VideoResolution,576)">SD</value>
+ <value condition="String.IsEqual(VideoPlayer.VideoResolution,720)">HD</value>
+ <value condition="String.IsEqual(VideoPlayer.VideoResolution,1080)">HD</value>
+ <value condition="String.IsEqual(VideoPlayer.VideoResolution,4K)">UHD</value>
+ <value condition="String.IsEqual(VideoPlayer.VideoResolution,8K)">UHD</value>
+ <value>$INFO[VideoPlayer.VideoResolution]</value>
+ </variable>
+ <variable name="VideoListCodecVar">
<value condition="String.IsEqual(ListItem.VideoCodec,av1)">AV1</value>
<value condition="String.IsEqual(ListItem.VideoCodec,avc1)">AVC-1</value>
<value condition="String.IsEqual(ListItem.VideoCodec,div3)">DivX</value>
@@ -744,13 +755,46 @@
<value condition="String.IsEqual(ListItem.VideoCodec,xvid)">XviD</value>
<value>$INFO[ListItem.VideoCodec]</value>
</variable>
- <variable name="VideoHDRVar">
- <value condition="String.IsEqual(ListItem.HdrType,dolbyvision)">Dolby Vision</value>
+ <variable name="VideoPlayerCodecVar">
+ <value condition="String.IsEqual(VideoPlayer.VideoCodec,av1)">AV1</value>
+ <value condition="String.IsEqual(VideoPlayer.VideoCodec,avc1)">AVC-1</value>
+ <value condition="String.IsEqual(VideoPlayer.VideoCodec,div3)">DivX</value>
+ <value condition="String.IsEqual(VideoPlayer.VideoCodec,divx)">DivX</value>
+ <value condition="String.IsEqual(VideoPlayer.VideoCodec,dx50)">DivX</value>
+ <value condition="String.IsEqual(VideoPlayer.VideoCodec,flv)">FLV</value>
+ <value condition="String.IsEqual(VideoPlayer.VideoCodec,h264)">H.264</value>
+ <value condition="String.IsEqual(VideoPlayer.VideoCodec,hev1)">H.265</value>
+ <value condition="String.IsEqual(VideoPlayer.VideoCodec,hevc)">H.265</value>
+ <value condition="String.IsEqual(VideoPlayer.VideoCodec,hvc1)">H.265</value>
+ <value condition="String.IsEqual(VideoPlayer.VideoCodec,mpeg1)">MPEG-1</value>
+ <value condition="String.IsEqual(VideoPlayer.VideoCodec,mpeg2)">MPEG-2</value>
+ <value condition="String.IsEqual(VideoPlayer.VideoCodec,mpeg2video)">MPEG-2</value>
+ <value condition="String.IsEqual(VideoPlayer.VideoCodec,mp4v)">MPEG-4</value>
+ <value condition="String.IsEqual(VideoPlayer.VideoCodec,mpeg4)">MPEG-4</value>
+ <value condition="String.IsEqual(VideoPlayer.VideoCodec,theora)">Theora</value>
+ <value condition="String.IsEqual(VideoPlayer.VideoCodec,vc1)">VC-1</value>
+ <value condition="String.IsEqual(VideoPlayer.VideoCodec,vc-1)">VC-1</value>
+ <value condition="String.IsEqual(VideoPlayer.VideoCodec,vp8)">VP8</value>
+ <value condition="String.IsEqual(VideoPlayer.VideoCodec,vp9)">VP9</value>
+ <value condition="String.IsEqual(VideoPlayer.VideoCodec,wmv)">WMV</value>
+ <value condition="String.IsEqual(VideoPlayer.VideoCodec,wmv3)">WMV</value>
+ <value condition="String.IsEqual(VideoPlayer.VideoCodec,wvc1)">VC-1</value>
+ <value condition="String.IsEqual(VideoPlayer.VideoCodec,xvid)">XviD</value>
+ <value>$INFO[VideoPlayer.VideoCodec]</value>
+ </variable>
+ <variable name="VideoListHDRVar">
+ <value condition="String.IsEqual(ListItem.HdrType,dolbyvision)">DoVi</value>
<value condition="String.IsEqual(ListItem.HdrType,hdr10)">HDR10</value>
<value condition="String.IsEqual(ListItem.HdrType,hlg)">HLG</value>
<value>$INFO[ListItem.HdrType]</value>
</variable>
- <variable name="AudioCodecVar">
+ <variable name="VideoPlayerHDRVar">
+ <value condition="String.IsEqual(VideoPlayer.HdrType,dolbyvision)">DoVi</value>
+ <value condition="String.IsEqual(VideoPlayer.HdrType,hdr10)">HDR10</value>
+ <value condition="String.IsEqual(VideoPlayer.HdrType,hlg)">HLG</value>
+ <value>$INFO[VideoPlayer.HdrType]</value>
+ </variable>
+ <variable name="AudioListCodecVar">
<value condition="String.IsEqual(ListItem.AudioCodec,aac)">AAC</value>
<value condition="String.IsEqual(ListItem.AudioCodec,aac_latm)">AAC</value>
<value condition="String.IsEqual(ListItem.AudioCodec,ac3)">Dolby D</value>
@@ -786,7 +830,43 @@
<value condition="String.IsEqual(ListItem.AudioCodec,wmav2)">WMA</value>
<value>$INFO[ListItem.AudioCodec]</value>
</variable>
- <variable name="AudioChannelsVar">
+ <variable name="VideoPlayerAudioCodecVar">
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,aac)">AAC</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,aac_latm)">AAC</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,ac3)">Dolby D</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,aif)">AIFF</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,aifc)">AIFF</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,aiff)">AIFF</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,alac)">ALAC</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,ape)">APE</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,avc)">AVC</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,cdda)">CDDA</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,dca)">DTS</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,dolbydigital)">Dolby D</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,dts)">DTS</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,dtshd_hra)">DTSHD-HRA</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,dtshd_ma)">DTSHD-MA</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,dtsma)">DTSHD-MA</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,eac3)">Dolby D+</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,flac)">FLAC</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,mp1)">MP1</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,mp3)">MP3</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,mp3float)">MP3</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,ogg)">OGG</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,opus)">OPUS</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,pcm)">PCM</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,pcm_bluray)">PCM</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,pcm_s16le)">PCM</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,pcm_s24le)">PCM</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,truehd)">TrueHD</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,vorbis)">Vorbis</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,wav)">WAV</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,wavpack)">WAVP</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,wmapro)">WMA-PRO</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioCodec,wmav2)">WMA</value>
+ <value>$INFO[VideoPlayer.AudioCodec]</value>
+ </variable>
+ <variable name="AudioListChannelsVar">
<value condition="String.IsEqual(ListItem.AudioChannels,0)">0.0</value>
<value condition="String.IsEqual(ListItem.AudioChannels,1)">1.0</value>
<value condition="String.IsEqual(ListItem.AudioChannels,2)">2.0</value>
@@ -799,13 +879,88 @@
<value condition="String.IsEqual(ListItem.AudioChannels,10)">9.1</value>
<value>$INFO[ListItem.AudioChannels]</value>
</variable>
+ <variable name="VideoPlayerAudioChannelsVar">
+ <value condition="String.IsEqual(VideoPlayer.AudioChannels,0)">0.0</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioChannels,1)">1.0</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioChannels,2)">2.0</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioChannels,3)">2.1</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioChannels,4)">4.0</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioChannels,5)">4.1</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioChannels,6)">5.1</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioChannels,7)">6.1</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioChannels,8)">7.1</value>
+ <value condition="String.IsEqual(VideoPlayer.AudioChannels,10)">9.1</value>
+ <value>$INFO[VideoPlayer.AudioChannels]</value>
+ </variable>
+ <variable name="MusicPlayerCodecVar">
+ <value condition="String.IsEqual(MusicPlayer.Codec,aac)">AAC</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,aac_latm)">AAC</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,ac3)">Dolby D</value>
+ <value condition="String.IsEqual(LMusicPlayer.Codec,aif)">AIFF</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,aifc)">AIFF</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,aiff)">AIFF</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,alac)">ALAC</value>
+ <value condition="String.IsEqual(LMusicPlayer.Codec,ape)">APE</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,avc)">AVC</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,cdda)">CDDA</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,dca)">DTS</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,dolbydigital)">Dolby D</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,dts)">DTS</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,dtshd_hra)">DTSHD-HRA</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,dtshd_ma)">DTSHD-MA</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,dtsma)">DTSHD-MA</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,eac3)">Dolby D+</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,flac)">FLAC</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,mp1)">MP1</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,mp3)">MP3</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,mp3float)">MP3</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,ogg)">OGG</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,opus)">OPUS</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,pcm)">PCM</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,pcm_bluray)">PCM</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,pcm_s16le)">PCM</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,pcm_s24le)">PCM</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,truehd)">TrueHD</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,vorbis)">Vorbis</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,wav)">WAV</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,wavpack)">WAVP</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,wmapro)">WMA-PRO</value>
+ <value condition="String.IsEqual(MusicPlayer.Codec,wmav2)">WMA</value>
+ <value>$INFO[MusicPlayer.Codec]</value>
+ </variable>
+ <variable name="MusicListChannelsVar">
+ <value condition="String.IsEqual(ListItem.MusicChannels,0)">0.0</value>
+ <value condition="String.IsEqual(ListItem.MusicChannels,1)">1.0</value>
+ <value condition="String.IsEqual(ListItem.MusicChannels,2)">2.0</value>
+ <value condition="String.IsEqual(ListItem.MusicChannels,3)">2.1</value>
+ <value condition="String.IsEqual(ListItem.MusicChannels,4)">4.0</value>
+ <value condition="String.IsEqual(ListItem.MusicChannels,5)">4.1</value>
+ <value condition="String.IsEqual(ListItem.MusicChannels,6)">5.1</value>
+ <value condition="String.IsEqual(ListItem.MusicChannels,7)">6.1</value>
+ <value condition="String.IsEqual(ListItem.MusicChannels,8)">7.1</value>
+ <value condition="String.IsEqual(ListItem.MusicChannels,10)">9.1</value>
+ <value>$INFO[ListItem.MusicChannels]</value>
+ </variable>
+ <variable name="MusicPlayerAudioChannelsVar">
+ <value condition="String.IsEqual(MusicPlayer.Channels,0)">0.0</value>
+ <value condition="String.IsEqual(MusicPlayer.Channels,1)">1.0</value>
+ <value condition="String.IsEqual(MusicPlayer.Channels,2)">2.0</value>
+ <value condition="String.IsEqual(MusicPlayer.Channels,3)">2.1</value>
+ <value condition="String.IsEqual(MusicPlayer.Channels,4)">4.0</value>
+ <value condition="String.IsEqual(MusicPlayer.Channels,5)">4.1</value>
+ <value condition="String.IsEqual(MusicPlayer.Channels,6)">5.1</value>
+ <value condition="String.IsEqual(MusicPlayer.Channels,7)">6.1</value>
+ <value condition="String.IsEqual(MusicPlayer.Channels,8)">7.1</value>
+ <value condition="String.IsEqual(MusicPlayer.Channels,10)">9.1</value>
+ <value>$INFO[MusicPlayer.Channels]</value>
+ </variable>
<variable name="MediaInfoListLabelVar">
<value condition="Window.IsVisible(selectvideoversion)">$INFO[ListItem.VideoVersionName]</value>
<value>$INFO[ListItem.Label]</value>
</variable>
<variable name="MediaInfoListLabel2Var">
- <value condition="ListItem.IsStereoscopic">$INFO[ListItem.Duration,$LOCALIZE[180]: ][CR]$VAR[VideoCodecVar,, ]$INFO[ListItem.VideoResolution,| , ]$VAR[VideoResolutionTypeVar,, ]$VAR[VideoHDRVar,| , ]| 3D $INFO[ListItem.VideoAspect,| ,:1 ]$VAR[AudioCodecVar,| , ]$VAR[AudioChannelsVar]</value>
- <value>$INFO[ListItem.Duration,$LOCALIZE[180]: ][CR]$VAR[VideoCodecVar,, ]$INFO[ListItem.VideoResolution,| , ]$VAR[VideoResolutionTypeVar,, ]$VAR[VideoHDRVar,| , ]$INFO[ListItem.VideoAspect,| ,:1 ]$VAR[AudioCodecVar,| , ]$VAR[AudioChannelsVar]</value>
+ <value condition="ListItem.IsStereoscopic">$INFO[ListItem.Duration,$LOCALIZE[180]: ][CR]3D | $VAR[VideoListCodecVar]$INFO[ListItem.VideoResolution, | ]$VAR[VideoListResolutionTypeVar, ]$VAR[VideoListHDRVar, | ]$VAR[VideoListAspectVar, | ]$VAR[AudioListCodecVar, | ]$VAR[AudioListChannelsVar, ]</value>
+ <value>$INFO[ListItem.Duration,$LOCALIZE[180]: ][CR]$VAR[VideoListCodecVar]$INFO[ListItem.VideoResolution, | ]$VAR[VideoListResolutionTypeVar, ]$VAR[VideoListHDRVar, | ]$VAR[VideoListAspectVar, | ]$VAR[AudioListCodecVar, | ]$VAR[AudioListChannelsVar, ]</value>
</variable>
<variable name="PVRInstanceName">
<value condition="Integer.IsGreater(PVR.ClientCount,1)">$INFO[ListItem.PVRClientName,[COLOR grey]$LOCALIZE[31137]:[/COLOR] ,]$INFO[ListItem.PVRInstanceName, (,)]</value>
diff --git a/cmake/modules/FindCurl.cmake b/cmake/modules/FindCurl.cmake
index a26682395c..3ce4ed5829 100644
--- a/cmake/modules/FindCurl.cmake
+++ b/cmake/modules/FindCurl.cmake
@@ -34,10 +34,6 @@ if(NOT TARGET ${APP_NAME_LC}::${CMAKE_FIND_PACKAGE_NAME})
set(PLATFORM_LINK_LIBS crypt32.lib)
endif()
- set(patches "${CORE_SOURCE_DIR}/tools/depends/target/${MODULE_LC}/01-win-nghttp2-add-name.patch")
-
- generate_patchcommand("${patches}")
-
set(CMAKE_ARGS -DBUILD_CURL_EXE=OFF
-DBUILD_SHARED_LIBS=OFF
-DBUILD_STATIC_LIBS=ON
diff --git a/tools/depends/target/curl/01-win-nghttp2-add-name.patch b/tools/depends/target/curl/01-win-nghttp2-add-name.patch
deleted file mode 100644
index e07843010a..0000000000
--- a/tools/depends/target/curl/01-win-nghttp2-add-name.patch
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/CMake/FindNGHTTP2.cmake
-+++ b/CMake/FindNGHTTP2.cmake
-@@ -25,7 +25,7 @@
-
- find_path(NGHTTP2_INCLUDE_DIR "nghttp2/nghttp2.h")
-
--find_library(NGHTTP2_LIBRARY NAMES nghttp2)
-+find_library(NGHTTP2_LIBRARY NAMES nghttp2 nghttp2_static)
-
- find_package_handle_standard_args(NGHTTP2
- FOUND_VAR
diff --git a/tools/depends/target/curl/CURL-VERSION b/tools/depends/target/curl/CURL-VERSION
index f9a42c2939..50facb2358 100644
--- a/tools/depends/target/curl/CURL-VERSION
+++ b/tools/depends/target/curl/CURL-VERSION
@@ -1,6 +1,6 @@
LIBNAME=curl
-VERSION=8.7.1
+VERSION=8.10.0
ARCHIVE=$(LIBNAME)-$(VERSION).tar.xz
-SHA512=5bbde9d5648e9226f5490fa951690aaf159149345f3a315df2ba58b2468f3e59ca32e8a49734338afc861803a4f81caac6d642a4699b72c6310ebfb1f618aad2
+SHA512=055277695ea242fcb0bf26ca6c4867a385cd578cd73ed4c5c4a020233248044c1ecaebcbaeaac47d3ffe07a41300ea5fc86396d7e812137cf75ed3e1b54ca5b2
BYPRODUCT=libcurl.a
BYPRODUCT_WIN=libcurl.lib
diff --git a/xbmc/FileItem.cpp b/xbmc/FileItem.cpp
index 9efa598f82..dcc28288e4 100644
--- a/xbmc/FileItem.cpp
+++ b/xbmc/FileItem.cpp
@@ -1944,90 +1944,19 @@ std::string CFileItem::FindLocalArt(const std::string &artFile, bool useFolder)
std::string thumb;
if (!m_bIsFolder)
{
- thumb = GetLocalArt(artFile, false);
+ thumb = ART::GetLocalArt(*this, artFile, false);
if (!thumb.empty() && CFile::Exists(thumb))
return thumb;
}
if ((useFolder || (m_bIsFolder && !IsFileFolder())) && !artFile.empty())
{
- std::string thumb2 = GetLocalArt(artFile, true);
+ std::string thumb2 = ART::GetLocalArt(*this, artFile, true);
if (!thumb2.empty() && thumb2 != thumb && CFile::Exists(thumb2))
return thumb2;
}
return "";
}
-std::string CFileItem::GetLocalArtBaseFilename() const
-{
- bool useFolder = false;
- return GetLocalArtBaseFilename(useFolder);
-}
-
-std::string CFileItem::GetLocalArtBaseFilename(bool& useFolder) const
-{
- std::string strFile;
- if (IsStack())
- {
- std::string strPath;
- URIUtils::GetParentPath(m_strPath,strPath);
- strFile = URIUtils::AddFileToFolder(
- strPath, URIUtils::GetFileName(CStackDirectory::GetStackedTitlePath(m_strPath)));
- }
-
- std::string file = strFile.empty() ? m_strPath : strFile;
- if (URIUtils::IsInRAR(file) || URIUtils::IsInZIP(file))
- {
- std::string strPath = URIUtils::GetDirectory(file);
- std::string strParent;
- URIUtils::GetParentPath(strPath,strParent);
- strFile = URIUtils::AddFileToFolder(strParent, URIUtils::GetFileName(file));
- }
-
- if (IsMultiPath())
- strFile = CMultiPathDirectory::GetFirstPath(m_strPath);
-
- if (IsOpticalMediaFile())
- { // optical media files should be treated like folders
- useFolder = true;
- strFile = GetLocalMetadataPath();
- }
- else if (useFolder && !(m_bIsFolder && !IsFileFolder()))
- {
- file = strFile.empty() ? m_strPath : strFile;
- strFile = URIUtils::GetDirectory(file);
- }
-
- if (strFile.empty())
- strFile = GetDynPath();
-
- return strFile;
-}
-
-std::string CFileItem::GetLocalArt(const std::string& artFile, bool useFolder) const
-{
- // no retrieving of empty art files from folders
- if (useFolder && artFile.empty())
- return "";
-
- std::string strFile = GetLocalArtBaseFilename(useFolder);
- if (strFile.empty()) // empty filepath -> nothing to find
- return "";
-
- if (useFolder)
- {
- if (!artFile.empty())
- return URIUtils::AddFileToFolder(strFile, artFile);
- }
- else
- {
- if (artFile.empty()) // old thumbnail matching
- return URIUtils::ReplaceExtension(strFile, ".tbn");
- else
- return URIUtils::ReplaceExtension(strFile, "-" + artFile);
- }
- return "";
-}
-
std::string CFileItem::GetMovieName(bool bUseFolderNames /* = false */) const
{
if (IsPlugin() && HasVideoInfoTag() && !GetVideoInfoTag()->m_strTitle.empty())
diff --git a/xbmc/FileItem.h b/xbmc/FileItem.h
index afaaf47c6a..635c964d8d 100644
--- a/xbmc/FileItem.h
+++ b/xbmc/FileItem.h
@@ -397,32 +397,6 @@ public:
CPictureInfoTag* GetPictureInfoTag();
- /*!
- \brief Assemble the base filename of local artwork for an item,
- accounting for archives, stacks and multi-paths, and BDMV/VIDEO_TS folders.
- `useFolder` is set to false
- \return the path to the base filename for artwork lookup.
- \sa GetLocalArt
- */
- std::string GetLocalArtBaseFilename() const;
- /*!
- \brief Assemble the base filename of local artwork for an item,
- accounting for archives, stacks and multi-paths, and BDMV/VIDEO_TS folders.
- \param useFolder whether to look in the folder for the art file. Defaults to false.
- \return the path to the base filename for artwork lookup.
- \sa GetLocalArt
- */
- std::string GetLocalArtBaseFilename(bool& useFolder) const;
-
- /*! \brief Assemble the filename of a particular piece of local artwork for an item.
- No file existence check is typically performed.
- \param artFile the art file to search for.
- \param useFolder whether to look in the folder for the art file. Defaults to false.
- \return the path to the local artwork.
- \sa FindLocalArt
- */
- std::string GetLocalArt(const std::string& artFile, bool useFolder = false) const;
-
/*! \brief Assemble the filename of a particular piece of local artwork for an item,
and check for file existence.
\param artFile the art file to search for.
diff --git a/xbmc/pvr/PVRContextMenus.cpp b/xbmc/pvr/PVRContextMenus.cpp
index 9ab47757f7..f882c9e624 100644
--- a/xbmc/pvr/PVRContextMenus.cpp
+++ b/xbmc/pvr/PVRContextMenus.cpp
@@ -81,6 +81,7 @@ DECL_STATICCONTEXTMENUITEM(ExecuteSearch);
DECL_STATICCONTEXTMENUITEM(EditSearch);
DECL_STATICCONTEXTMENUITEM(RenameSearch);
DECL_STATICCONTEXTMENUITEM(ChooseIconForSearch);
+DECL_STATICCONTEXTMENUITEM(DuplicateSearch);
DECL_STATICCONTEXTMENUITEM(DeleteSearch);
class PVRClientMenuHook : public IContextMenuItem
@@ -749,6 +750,19 @@ bool ChooseIconForSearch::Execute(const std::shared_ptr<CFileItem>& item) const
}
///////////////////////////////////////////////////////////////////////////////
+// Duplicate a saved search
+
+bool DuplicateSearch::IsVisible(const CFileItem& item) const
+{
+ return item.HasEPGSearchFilter();
+}
+
+bool DuplicateSearch::Execute(const std::shared_ptr<CFileItem>& item) const
+{
+ return CServiceBroker::GetPVRManager().Get<PVR::GUI::EPG>().DuplicateSavedSearch(*item);
+}
+
+///////////////////////////////////////////////////////////////////////////////
// Delete saved search
bool DeleteSearch::IsVisible(const CFileItem& item) const
@@ -794,6 +808,7 @@ CPVRContextMenuManager::CPVRContextMenuManager()
std::make_shared<CONTEXTMENUITEM::EditSearch>(21450), /* Edit */
std::make_shared<CONTEXTMENUITEM::RenameSearch>(118), /* Rename */
std::make_shared<CONTEXTMENUITEM::ChooseIconForSearch>(19284), /* Choose icon */
+ std::make_shared<CONTEXTMENUITEM::DuplicateSearch>(19355), /* Duplicate */
std::make_shared<CONTEXTMENUITEM::DeleteSearch>(117), /* Delete */
})
{
diff --git a/xbmc/pvr/PVRDatabase.cpp b/xbmc/pvr/PVRDatabase.cpp
index ec4428384c..84e7eb99c9 100644
--- a/xbmc/pvr/PVRDatabase.cpp
+++ b/xbmc/pvr/PVRDatabase.cpp
@@ -590,7 +590,7 @@ int CPVRDatabase::GetClientID(const std::string& addonID, unsigned int instanceI
if (ExecuteQuery(sql))
return static_cast<int>(m_pDS->lastinsertid());
- return -1;
+ return PVR_CLIENT_INVALID_UID;
}
/********** Channel provider methods **********/
@@ -1306,7 +1306,8 @@ std::vector<std::shared_ptr<CPVRTimerInfoTag>> CPVRDatabase::GetTimers(
newTag->m_iClientIndex = -m_pDS->fv("iClientIndex").get_asInt();
newTag->m_iParentClientIndex = m_pDS->fv("iParentClientIndex").get_asInt();
newTag->m_iClientId = m_pDS->fv("iClientId").get_asInt();
- newTag->SetTimerType(CPVRTimerType::CreateFromIds(m_pDS->fv("iTimerType").get_asInt(), -1));
+ newTag->SetTimerType(CPVRTimerType::CreateFromIds(m_pDS->fv("iTimerType").get_asInt(),
+ PVR_CLIENT_INVALID_UID));
newTag->m_state = static_cast<PVR_TIMER_STATE>(m_pDS->fv("iState").get_asInt());
newTag->m_strTitle = m_pDS->fv("sTitle").get_asString().c_str();
newTag->m_iClientChannelUid = m_pDS->fv("iClientChannelUid").get_asInt();
diff --git a/xbmc/pvr/dialogs/GUIDialogPVRGuideSearch.cpp b/xbmc/pvr/dialogs/GUIDialogPVRGuideSearch.cpp
index 90faa68af2..b5cb4cf64a 100644
--- a/xbmc/pvr/dialogs/GUIDialogPVRGuideSearch.cpp
+++ b/xbmc/pvr/dialogs/GUIDialogPVRGuideSearch.cpp
@@ -51,6 +51,8 @@ using namespace PVR;
static constexpr int CONTROL_BTN_SAVE = 29;
static constexpr int CONTROL_BTN_IGNORE_FINISHED = 30;
static constexpr int CONTROL_BTN_IGNORE_FUTURE = 31;
+static constexpr int CONTROL_BTN_START_ANY_TIME = 32;
+static constexpr int CONTROL_BTN_END_ANY_TIME = 33;
CGUIDialogPVRGuideSearch::CGUIDialogPVRGuideSearch()
: CGUIDialog(WINDOW_DIALOG_PVR_GUIDE_SEARCH, "DialogPVRGuideSearch.xml")
@@ -225,6 +227,12 @@ bool CGUIDialogPVRGuideSearch::OnMessage(CGUIMessage& message)
UpdateChannelSpin();
return true;
}
+ else if (iControl == CONTROL_BTN_START_ANY_TIME || iControl == CONTROL_BTN_END_ANY_TIME)
+ {
+ UpdateSearchFilter();
+ Update();
+ return true;
+ }
}
break;
}
@@ -316,6 +324,9 @@ void CGUIDialogPVRGuideSearch::UpdateSearchFilter()
m_searchFilter->SetEndDateTime(end);
m_endDateTime = end;
}
+
+ m_searchFilter->SetStartAnyTime(IsRadioSelected(CONTROL_BTN_START_ANY_TIME));
+ m_searchFilter->SetEndAnyTime(IsRadioSelected(CONTROL_BTN_END_ANY_TIME));
}
void CGUIDialogPVRGuideSearch::Update()
@@ -340,6 +351,10 @@ void CGUIDialogPVRGuideSearch::Update()
m_searchFilter->ShouldIgnoreFinishedBroadcasts());
SET_CONTROL_SELECTED(GetID(), CONTROL_BTN_IGNORE_FUTURE,
m_searchFilter->ShouldIgnoreFutureBroadcasts());
+ SET_CONTROL_SELECTED(GetID(), CONTROL_BTN_START_ANY_TIME, m_searchFilter->IsStartAnyTime());
+ SET_CONTROL_SELECTED(GetID(), CONTROL_BTN_END_ANY_TIME, m_searchFilter->IsEndAnyTime());
+ CONTROL_ENABLE_ON_CONDITION(CONTROL_EDIT_START_TIME, !m_searchFilter->IsStartAnyTime());
+ CONTROL_ENABLE_ON_CONDITION(CONTROL_EDIT_STOP_TIME, !m_searchFilter->IsEndAnyTime());
// Set start/end datetime fields
m_startDateTime = m_searchFilter->GetStartDateTime();
diff --git a/xbmc/pvr/epg/EpgDatabase.cpp b/xbmc/pvr/epg/EpgDatabase.cpp
index 7c17c03909..17c4d4354d 100644
--- a/xbmc/pvr/epg/EpgDatabase.cpp
+++ b/xbmc/pvr/epg/EpgDatabase.cpp
@@ -130,7 +130,9 @@ void CPVREpgDatabase::CreateTables()
"bIgnorePresentTimers bool, "
"bIgnorePresentRecordings bool, "
"iChannelGroup integer, "
- "sIconPath varchar(255)"
+ "sIconPath varchar(255), "
+ "bStartAnyTime bool, "
+ "bEndAnyTime bool"
")");
}
@@ -337,6 +339,14 @@ void CPVREpgDatabase::UpdateTables(int iVersion)
m_pDS->exec("ALTER TABLE epgtags ADD sParentalRatingIcon varchar(512);");
m_pDS->exec("ALTER TABLE epgtags ADD sParentalRatingSource varchar(128);");
}
+
+ if (iVersion < 19)
+ {
+ m_pDS->exec("ALTER TABLE savedsearches ADD bStartAnyTime bool;");
+ m_pDS->exec("ALTER TABLE savedsearches ADD bEndAnyTime bool;");
+ m_pDS->exec("UPDATE savedsearches SET bStartAnyTime = 1;");
+ m_pDS->exec("UPDATE savedsearches SET bEndAnyTime = 1;");
+ }
}
bool CPVREpgDatabase::DeleteEpg()
@@ -694,11 +704,25 @@ std::vector<std::shared_ptr<CPVREpgInfoTag>> CPVREpgDatabase::GetEpgTags(
// min start datetime
/////////////////////////////////////////////////////////////////////////////////////////////
+ static constexpr unsigned int ONE_DAY{60 * 60 * 24};
+
if (searchData.m_startDateTime.IsValid())
{
time_t minStart;
searchData.m_startDateTime.GetAsTime(minStart);
- filter.AppendWhere(PrepareSQL("iStartTime >= %u", static_cast<unsigned int>(minStart)));
+
+ if (searchData.m_startAnyTime)
+ {
+ filter.AppendWhere(PrepareSQL("iStartTime >= %u", static_cast<unsigned int>(minStart)));
+ }
+ else
+ {
+ const unsigned int startDate{static_cast<unsigned int>(minStart) / ONE_DAY};
+ filter.AppendWhere(PrepareSQL("(iStartTime / %u) >= %u", ONE_DAY, startDate));
+
+ const unsigned int startTime{static_cast<unsigned int>(minStart) % ONE_DAY};
+ filter.AppendWhere(PrepareSQL("(iStartTime %% %u) >= %u", ONE_DAY, startTime));
+ }
}
/////////////////////////////////////////////////////////////////////////////////////////////
@@ -709,7 +733,19 @@ std::vector<std::shared_ptr<CPVREpgInfoTag>> CPVREpgDatabase::GetEpgTags(
{
time_t maxEnd;
searchData.m_endDateTime.GetAsTime(maxEnd);
- filter.AppendWhere(PrepareSQL("iEndTime <= %u", static_cast<unsigned int>(maxEnd)));
+
+ if (searchData.m_endAnyTime)
+ {
+ filter.AppendWhere(PrepareSQL("iEndTime <= %u", static_cast<unsigned int>(maxEnd)));
+ }
+ else
+ {
+ const unsigned int endDate{static_cast<unsigned int>(maxEnd) / ONE_DAY};
+ filter.AppendWhere(PrepareSQL("(iEndTime / %u) <= %u", ONE_DAY, endDate));
+
+ const unsigned int endTime{static_cast<unsigned int>(maxEnd) % ONE_DAY};
+ filter.AppendWhere(PrepareSQL("(iEndTime %% %u) <= %u", ONE_DAY, endTime));
+ }
}
/////////////////////////////////////////////////////////////////////////////////////////////
@@ -1340,6 +1376,8 @@ std::shared_ptr<CPVREpgSearchFilter> CPVREpgDatabase::CreateEpgSearchFilter(
newSearch->SetIgnorePresentRecordings(m_pDS->fv("bIgnorePresentRecordings").get_asBool());
newSearch->SetChannelGroupID(m_pDS->fv("iChannelGroup").get_asInt());
newSearch->SetIconPath(m_pDS->fv("sIconPath").get_asString());
+ newSearch->SetStartAnyTime(m_pDS->fv("bStartAnyTime").get_asBool());
+ newSearch->SetEndAnyTime(m_pDS->fv("bEndAnyTime").get_asBool());
newSearch->SetChanged(false);
@@ -1404,16 +1442,16 @@ bool CPVREpgDatabase::Persist(CPVREpgSearchFilter& epgSearch)
// Insert a new entry if this is a new search, replace the existing otherwise
std::string strQuery;
- if (epgSearch.GetDatabaseId() == -1)
+ if (epgSearch.GetDatabaseId() == PVR_EPG_SEARCH_INVALID_DATABASE_ID)
strQuery = PrepareSQL(
"INSERT INTO savedsearches "
"(sTitle, sLastExecutedDateTime, sSearchTerm, bSearchInDescription, bIsCaseSensitive, "
"iGenreType, bIncludeUnknownGenres, sStartDateTime, sEndDateTime, iMinimumDuration, "
"iMaximumDuration, bIsRadio, iClientId, iChannelUid, bRemoveDuplicates, "
"bIgnoreFinishedBroadcasts, bIgnoreFutureBroadcasts, bFreeToAirOnly, bIgnorePresentTimers, "
- "bIgnorePresentRecordings, iChannelGroup, sIconPath) "
+ "bIgnorePresentRecordings, iChannelGroup, sIconPath, bStartAnyTime, bEndAnyTime) "
"VALUES ('%s', '%s', '%s', %i, %i, %i, %i, '%s', '%s', %i, %i, %i, %i, %i, %i, %i, %i, "
- "%i, %i, %i, %i, '%s');",
+ "%i, %i, %i, %i, '%s', %i, %i);",
epgSearch.GetTitle().c_str(),
epgSearch.GetLastExecutedDateTime().IsValid()
? epgSearch.GetLastExecutedDateTime().GetAsDBDateTime().c_str()
@@ -1433,7 +1471,8 @@ bool CPVREpgDatabase::Persist(CPVREpgSearchFilter& epgSearch)
epgSearch.ShouldIgnoreFutureBroadcasts() ? 1 : 0, epgSearch.IsFreeToAirOnly() ? 1 : 0,
epgSearch.ShouldIgnorePresentTimers() ? 1 : 0,
epgSearch.ShouldIgnorePresentRecordings() ? 1 : 0, epgSearch.GetChannelGroupID(),
- epgSearch.GetIconPath().c_str());
+ epgSearch.GetIconPath().c_str(), epgSearch.IsStartAnyTime() ? 1 : 0,
+ epgSearch.IsEndAnyTime() ? 1 : 0);
else
strQuery = PrepareSQL(
"REPLACE INTO savedsearches "
@@ -1441,9 +1480,9 @@ bool CPVREpgDatabase::Persist(CPVREpgSearchFilter& epgSearch)
"bIsCaseSensitive, iGenreType, bIncludeUnknownGenres, sStartDateTime, sEndDateTime, "
"iMinimumDuration, iMaximumDuration, bIsRadio, iClientId, iChannelUid, bRemoveDuplicates, "
"bIgnoreFinishedBroadcasts, bIgnoreFutureBroadcasts, bFreeToAirOnly, bIgnorePresentTimers, "
- "bIgnorePresentRecordings, iChannelGroup, sIconPath) "
+ "bIgnorePresentRecordings, iChannelGroup, sIconPath, bStartAnyTime, bEndAnyTime) "
"VALUES (%i, '%s', '%s', '%s', %i, %i, %i, %i, '%s', '%s', %i, %i, %i, %i, %i, %i, %i, %i, "
- "%i, %i, %i, %i, '%s');",
+ "%i, %i, %i, %i, '%s', %i, %i);",
epgSearch.GetDatabaseId(), epgSearch.GetTitle().c_str(),
epgSearch.GetLastExecutedDateTime().IsValid()
? epgSearch.GetLastExecutedDateTime().GetAsDBDateTime().c_str()
@@ -1463,14 +1502,15 @@ bool CPVREpgDatabase::Persist(CPVREpgSearchFilter& epgSearch)
epgSearch.ShouldIgnoreFutureBroadcasts() ? 1 : 0, epgSearch.IsFreeToAirOnly() ? 1 : 0,
epgSearch.ShouldIgnorePresentTimers() ? 1 : 0,
epgSearch.ShouldIgnorePresentRecordings() ? 1 : 0, epgSearch.GetChannelGroupID(),
- epgSearch.GetIconPath().c_str());
+ epgSearch.GetIconPath().c_str(), epgSearch.IsStartAnyTime() ? 1 : 0,
+ epgSearch.IsEndAnyTime() ? 1 : 0);
bool bReturn = ExecuteQuery(strQuery);
if (bReturn)
{
// Set the database id for searches persisted for the first time
- if (epgSearch.GetDatabaseId() == -1)
+ if (epgSearch.GetDatabaseId() == PVR_EPG_SEARCH_INVALID_DATABASE_ID)
epgSearch.SetDatabaseId(static_cast<int>(m_pDS->lastinsertid()));
epgSearch.SetChanged(false);
@@ -1481,7 +1521,7 @@ bool CPVREpgDatabase::Persist(CPVREpgSearchFilter& epgSearch)
bool CPVREpgDatabase::UpdateSavedSearchLastExecuted(const CPVREpgSearchFilter& epgSearch)
{
- if (epgSearch.GetDatabaseId() == -1)
+ if (epgSearch.GetDatabaseId() == PVR_EPG_SEARCH_INVALID_DATABASE_ID)
return false;
std::unique_lock<CCriticalSection> lock(m_critSection);
@@ -1494,7 +1534,7 @@ bool CPVREpgDatabase::UpdateSavedSearchLastExecuted(const CPVREpgSearchFilter& e
bool CPVREpgDatabase::Delete(const CPVREpgSearchFilter& epgSearch)
{
- if (epgSearch.GetDatabaseId() == -1)
+ if (epgSearch.GetDatabaseId() == PVR_EPG_SEARCH_INVALID_DATABASE_ID)
return false;
CLog::LogFC(LOGDEBUG, LOGEPG, "Deleting saved search '{}' from the database",
diff --git a/xbmc/pvr/epg/EpgDatabase.h b/xbmc/pvr/epg/EpgDatabase.h
index cf114a1050..8ea846bf42 100644
--- a/xbmc/pvr/epg/EpgDatabase.h
+++ b/xbmc/pvr/epg/EpgDatabase.h
@@ -66,7 +66,7 @@ namespace PVR
* @brief Get the minimal database version that is required to operate correctly.
* @return The minimal database version.
*/
- int GetSchemaVersion() const override { return 18; }
+ int GetSchemaVersion() const override { return 19; }
/*!
* @brief Get the default sqlite database filename.
diff --git a/xbmc/pvr/epg/EpgSearchData.h b/xbmc/pvr/epg/EpgSearchData.h
index e5e6ef7057..c0ab72069a 100644
--- a/xbmc/pvr/epg/EpgSearchData.h
+++ b/xbmc/pvr/epg/EpgSearchData.h
@@ -25,8 +25,10 @@ struct PVREpgSearchData
int m_iGenreType = EPG_SEARCH_UNSET; /*!< The genre type for an entry */
bool m_bIgnoreFinishedBroadcasts; /*!< True to ignore finished broadcasts, false if not */
bool m_bIgnoreFutureBroadcasts; /*!< True to ignore future broadcasts, false if not */
- CDateTime m_startDateTime; /*!< The minimum start time for an entry */
- CDateTime m_endDateTime; /*!< The maximum end time for an entry */
+ CDateTime m_startDateTime; /*!< The minimum start date and time for an entry */
+ CDateTime m_endDateTime; /*!< The maximum end date and time for an entry */
+ bool m_startAnyTime{true}; /*!< Match any start time */
+ bool m_endAnyTime{true}; /*!< Match any end time */
void Reset()
{
@@ -38,6 +40,8 @@ struct PVREpgSearchData
m_bIgnoreFutureBroadcasts = false;
m_startDateTime.SetValid(false);
m_endDateTime.SetValid(false);
+ m_startAnyTime = true;
+ m_endAnyTime = true;
}
};
diff --git a/xbmc/pvr/epg/EpgSearchFilter.cpp b/xbmc/pvr/epg/EpgSearchFilter.cpp
index 2425c0a1c5..b7533ce4c5 100644
--- a/xbmc/pvr/epg/EpgSearchFilter.cpp
+++ b/xbmc/pvr/epg/EpgSearchFilter.cpp
@@ -28,8 +28,7 @@
using namespace PVR;
-CPVREpgSearchFilter::CPVREpgSearchFilter(bool bRadio)
-: m_bIsRadio(bRadio)
+CPVREpgSearchFilter::CPVREpgSearchFilter(bool bRadio) : m_bIsRadio(bRadio)
{
Reset();
}
@@ -149,6 +148,15 @@ void CPVREpgSearchFilter::SetStartDateTime(const CDateTime& startDateTime)
}
}
+void CPVREpgSearchFilter::SetStartAnyTime(bool startAnyTime)
+{
+ if (m_searchData.m_startAnyTime != startAnyTime)
+ {
+ m_searchData.m_startAnyTime = startAnyTime;
+ m_bChanged = true;
+ }
+}
+
void CPVREpgSearchFilter::SetEndDateTime(const CDateTime& endDateTime)
{
if (m_searchData.m_endDateTime != endDateTime)
@@ -158,6 +166,15 @@ void CPVREpgSearchFilter::SetEndDateTime(const CDateTime& endDateTime)
}
}
+void CPVREpgSearchFilter::SetEndAnyTime(bool endAnyTime)
+{
+ if (m_searchData.m_endAnyTime != endAnyTime)
+ {
+ m_searchData.m_endAnyTime = endAnyTime;
+ m_bChanged = true;
+ }
+}
+
void CPVREpgSearchFilter::SetIncludeUnknownGenres(bool bIncludeUnknownGenres)
{
if (m_searchData.m_bIncludeUnknownGenres != bIncludeUnknownGenres)
@@ -348,7 +365,8 @@ void CPVREpgSearchFilter::RemoveDuplicates(std::vector<std::shared_ptr<CPVREpgIn
for (auto it = results.begin(); it != results.end();)
{
it = results.erase(std::remove_if(results.begin(), results.end(),
- [&it](const std::shared_ptr<const CPVREpgInfoTag>& entry) {
+ [&it](const std::shared_ptr<const CPVREpgInfoTag>& entry)
+ {
return *it != entry && (*it)->Title() == entry->Title() &&
(*it)->Plot() == entry->Plot() &&
(*it)->PlotOutline() == entry->PlotOutline();
@@ -396,10 +414,12 @@ bool CPVREpgSearchFilter::MatchFreeToAir(const std::shared_ptr<const CPVREpgInfo
bool CPVREpgSearchFilter::MatchTimers(const std::shared_ptr<const CPVREpgInfoTag>& tag) const
{
- return (!m_bIgnorePresentTimers || !CServiceBroker::GetPVRManager().Timers()->GetTimerForEpgTag(tag));
+ return (!m_bIgnorePresentTimers ||
+ !CServiceBroker::GetPVRManager().Timers()->GetTimerForEpgTag(tag));
}
bool CPVREpgSearchFilter::MatchRecordings(const std::shared_ptr<const CPVREpgInfoTag>& tag) const
{
- return (!m_bIgnorePresentRecordings || !CServiceBroker::GetPVRManager().Recordings()->GetRecordingForEpgTag(tag));
+ return (!m_bIgnorePresentRecordings ||
+ !CServiceBroker::GetPVRManager().Recordings()->GetRecordingForEpgTag(tag));
}
diff --git a/xbmc/pvr/epg/EpgSearchFilter.h b/xbmc/pvr/epg/EpgSearchFilter.h
index f6cca5cf0c..960d89f472 100644
--- a/xbmc/pvr/epg/EpgSearchFilter.h
+++ b/xbmc/pvr/epg/EpgSearchFilter.h
@@ -18,156 +18,164 @@
namespace PVR
{
- class CPVREpgInfoTag;
+static constexpr int PVR_EPG_SEARCH_INVALID_DATABASE_ID{-1};
- class CPVREpgSearchFilter
- {
- public:
- CPVREpgSearchFilter() = delete;
+class CPVREpgInfoTag;
- /*!
- * @brief ctor.
- * @param bRadio the type of channels to search - if true, 'radio'. 'tv', otherwise.
- */
- explicit CPVREpgSearchFilter(bool bRadio);
+class CPVREpgSearchFilter
+{
+public:
+ CPVREpgSearchFilter() = delete;
+
+ /*!
+ * @brief ctor.
+ * @param bRadio the type of channels to search - if true, 'radio'. 'tv', otherwise.
+ */
+ explicit CPVREpgSearchFilter(bool bRadio);
+
+ /*!
+ * @brief Clear this filter.
+ */
+ void Reset();
+
+ /*!
+ * @brief Return the path for this filter.
+ * @return the path.
+ */
+ std::string GetPath() const;
- /*!
- * @brief Clear this filter.
- */
- void Reset();
+ /*!
+ * @brief Check if a tag will be filtered or not.
+ * @param tag The tag to check.
+ * @return True if this tag matches the filter, false if not.
+ */
+ bool FilterEntry(const std::shared_ptr<const CPVREpgInfoTag>& tag) const;
- /*!
- * @brief Return the path for this filter.
- * @return the path.
- */
- std::string GetPath() const;
+ /*!
+ * @brief remove duplicates from a list of epg tags.
+ * @param results The list of epg tags.
+ */
+ static void RemoveDuplicates(std::vector<std::shared_ptr<CPVREpgInfoTag>>& results);
- /*!
- * @brief Check if a tag will be filtered or not.
- * @param tag The tag to check.
- * @return True if this tag matches the filter, false if not.
- */
- bool FilterEntry(const std::shared_ptr<const CPVREpgInfoTag>& tag) const;
+ /*!
+ * @brief Get the type of channels to search.
+ * @return true, if 'radio'. false, otherwise.
+ */
+ bool IsRadio() const { return m_bIsRadio; }
- /*!
- * @brief remove duplicates from a list of epg tags.
- * @param results The list of epg tags.
- */
- static void RemoveDuplicates(std::vector<std::shared_ptr<CPVREpgInfoTag>>& results);
+ const std::string& GetSearchTerm() const { return m_searchData.m_strSearchTerm; }
+ void SetSearchTerm(const std::string& strSearchTerm);
- /*!
- * @brief Get the type of channels to search.
- * @return true, if 'radio'. false, otherwise.
- */
- bool IsRadio() const { return m_bIsRadio; }
+ void SetSearchPhrase(const std::string& strSearchPhrase);
- const std::string& GetSearchTerm() const { return m_searchData.m_strSearchTerm; }
- void SetSearchTerm(const std::string& strSearchTerm);
+ bool IsCaseSensitive() const { return m_bIsCaseSensitive; }
+ void SetCaseSensitive(bool bIsCaseSensitive);
- void SetSearchPhrase(const std::string& strSearchPhrase);
+ bool ShouldSearchInDescription() const { return m_searchData.m_bSearchInDescription; }
+ void SetSearchInDescription(bool bSearchInDescription);
- bool IsCaseSensitive() const { return m_bIsCaseSensitive; }
- void SetCaseSensitive(bool bIsCaseSensitive);
+ int GetGenreType() const { return m_searchData.m_iGenreType; }
+ void SetGenreType(int iGenreType);
- bool ShouldSearchInDescription() const { return m_searchData.m_bSearchInDescription; }
- void SetSearchInDescription(bool bSearchInDescription);
+ int GetMinimumDuration() const { return m_iMinimumDuration; }
+ void SetMinimumDuration(int iMinimumDuration);
- int GetGenreType() const { return m_searchData.m_iGenreType; }
- void SetGenreType(int iGenreType);
+ int GetMaximumDuration() const { return m_iMaximumDuration; }
+ void SetMaximumDuration(int iMaximumDuration);
- int GetMinimumDuration() const { return m_iMinimumDuration; }
- void SetMinimumDuration(int iMinimumDuration);
+ bool ShouldIgnoreFinishedBroadcasts() const { return m_searchData.m_bIgnoreFinishedBroadcasts; }
+ void SetIgnoreFinishedBroadcasts(bool bIgnoreFinishedBroadcasts);
- int GetMaximumDuration() const { return m_iMaximumDuration; }
- void SetMaximumDuration(int iMaximumDuration);
+ bool ShouldIgnoreFutureBroadcasts() const { return m_searchData.m_bIgnoreFutureBroadcasts; }
+ void SetIgnoreFutureBroadcasts(bool bIgnoreFutureBroadcasts);
- bool ShouldIgnoreFinishedBroadcasts() const { return m_searchData.m_bIgnoreFinishedBroadcasts; }
- void SetIgnoreFinishedBroadcasts(bool bIgnoreFinishedBroadcasts);
+ const CDateTime& GetStartDateTime() const { return m_searchData.m_startDateTime; }
+ void SetStartDateTime(const CDateTime& startDateTime);
- bool ShouldIgnoreFutureBroadcasts() const { return m_searchData.m_bIgnoreFutureBroadcasts; }
- void SetIgnoreFutureBroadcasts(bool bIgnoreFutureBroadcasts);
+ bool IsStartAnyTime() const { return m_searchData.m_startAnyTime; }
+ void SetStartAnyTime(bool startAnyTime);
- const CDateTime& GetStartDateTime() const { return m_searchData.m_startDateTime; }
- void SetStartDateTime(const CDateTime& startDateTime);
+ const CDateTime& GetEndDateTime() const { return m_searchData.m_endDateTime; }
+ void SetEndDateTime(const CDateTime& endDateTime);
- const CDateTime& GetEndDateTime() const { return m_searchData.m_endDateTime; }
- void SetEndDateTime(const CDateTime& endDateTime);
+ bool IsEndAnyTime() const { return m_searchData.m_endAnyTime; }
+ void SetEndAnyTime(bool endAnyTime);
- bool ShouldIncludeUnknownGenres() const { return m_searchData.m_bIncludeUnknownGenres; }
- void SetIncludeUnknownGenres(bool bIncludeUnknownGenres);
+ bool ShouldIncludeUnknownGenres() const { return m_searchData.m_bIncludeUnknownGenres; }
+ void SetIncludeUnknownGenres(bool bIncludeUnknownGenres);
- bool ShouldRemoveDuplicates() const { return m_bRemoveDuplicates; }
- void SetRemoveDuplicates(bool bRemoveDuplicates);
+ bool ShouldRemoveDuplicates() const { return m_bRemoveDuplicates; }
+ void SetRemoveDuplicates(bool bRemoveDuplicates);
- int GetClientID() const { return m_iClientID; }
- void SetClientID(int iClientID);
+ int GetClientID() const { return m_iClientID; }
+ void SetClientID(int iClientID);
- int GetChannelGroupID() const { return m_iChannelGroupID; }
- void SetChannelGroupID(int iChannelGroupID);
+ int GetChannelGroupID() const { return m_iChannelGroupID; }
+ void SetChannelGroupID(int iChannelGroupID);
- int GetChannelUID() const { return m_iChannelUID; }
- void SetChannelUID(int iChannelUID);
+ int GetChannelUID() const { return m_iChannelUID; }
+ void SetChannelUID(int iChannelUID);
- bool IsFreeToAirOnly() const { return m_bFreeToAirOnly; }
- void SetFreeToAirOnly(bool bFreeToAirOnly);
+ bool IsFreeToAirOnly() const { return m_bFreeToAirOnly; }
+ void SetFreeToAirOnly(bool bFreeToAirOnly);
- bool ShouldIgnorePresentTimers() const { return m_bIgnorePresentTimers; }
- void SetIgnorePresentTimers(bool bIgnorePresentTimers);
+ bool ShouldIgnorePresentTimers() const { return m_bIgnorePresentTimers; }
+ void SetIgnorePresentTimers(bool bIgnorePresentTimers);
- bool ShouldIgnorePresentRecordings() const { return m_bIgnorePresentRecordings; }
- void SetIgnorePresentRecordings(bool bIgnorePresentRecordings);
+ bool ShouldIgnorePresentRecordings() const { return m_bIgnorePresentRecordings; }
+ void SetIgnorePresentRecordings(bool bIgnorePresentRecordings);
- int GetDatabaseId() const { return m_iDatabaseId; }
- void SetDatabaseId(int iDatabaseId);
+ int GetDatabaseId() const { return m_iDatabaseId; }
+ void SetDatabaseId(int iDatabaseId);
- const std::string& GetTitle() const { return m_title; }
- void SetTitle(const std::string& title);
+ const std::string& GetTitle() const { return m_title; }
+ void SetTitle(const std::string& title);
- const std::string& GetIconPath() const { return m_iconPath; }
- void SetIconPath(const std::string& iconPath);
+ const std::string& GetIconPath() const { return m_iconPath; }
+ void SetIconPath(const std::string& iconPath);
- const CDateTime& GetLastExecutedDateTime() const { return m_lastExecutedDateTime; }
- void SetLastExecutedDateTime(const CDateTime& lastExecutedDateTime);
+ const CDateTime& GetLastExecutedDateTime() const { return m_lastExecutedDateTime; }
+ void SetLastExecutedDateTime(const CDateTime& lastExecutedDateTime);
- const PVREpgSearchData& GetEpgSearchData() const { return m_searchData; }
- void SetEpgSearchDataFiltered() { m_bEpgSearchDataFiltered = true; }
+ const PVREpgSearchData& GetEpgSearchData() const { return m_searchData; }
+ void SetEpgSearchDataFiltered() { m_bEpgSearchDataFiltered = true; }
- bool IsChanged() const { return m_bChanged; }
- void SetChanged(bool bChanged) { m_bChanged = bChanged; }
+ bool IsChanged() const { return m_bChanged; }
+ void SetChanged(bool bChanged) { m_bChanged = bChanged; }
- private:
- bool MatchGenre(const std::shared_ptr<const CPVREpgInfoTag>& tag) const;
- bool MatchDuration(const std::shared_ptr<const CPVREpgInfoTag>& tag) const;
- bool MatchStartAndEndTimes(const std::shared_ptr<const CPVREpgInfoTag>& tag) const;
- bool MatchSearchTerm(const std::shared_ptr<const CPVREpgInfoTag>& tag) const;
- bool MatchChannel(const std::shared_ptr<const CPVREpgInfoTag>& tag) const;
- bool MatchChannelGroup(const std::shared_ptr<const CPVREpgInfoTag>& tag) const;
- bool MatchFreeToAir(const std::shared_ptr<const CPVREpgInfoTag>& tag) const;
- bool MatchTimers(const std::shared_ptr<const CPVREpgInfoTag>& tag) const;
- bool MatchRecordings(const std::shared_ptr<const CPVREpgInfoTag>& tag) const;
+private:
+ bool MatchGenre(const std::shared_ptr<const CPVREpgInfoTag>& tag) const;
+ bool MatchDuration(const std::shared_ptr<const CPVREpgInfoTag>& tag) const;
+ bool MatchStartAndEndTimes(const std::shared_ptr<const CPVREpgInfoTag>& tag) const;
+ bool MatchSearchTerm(const std::shared_ptr<const CPVREpgInfoTag>& tag) const;
+ bool MatchChannel(const std::shared_ptr<const CPVREpgInfoTag>& tag) const;
+ bool MatchChannelGroup(const std::shared_ptr<const CPVREpgInfoTag>& tag) const;
+ bool MatchFreeToAir(const std::shared_ptr<const CPVREpgInfoTag>& tag) const;
+ bool MatchTimers(const std::shared_ptr<const CPVREpgInfoTag>& tag) const;
+ bool MatchRecordings(const std::shared_ptr<const CPVREpgInfoTag>& tag) const;
- bool m_bChanged = false;
+ bool m_bChanged = false;
- PVREpgSearchData m_searchData;
- bool m_bEpgSearchDataFiltered = false;
+ PVREpgSearchData m_searchData;
+ bool m_bEpgSearchDataFiltered = false;
- bool m_bIsCaseSensitive; /*!< Do a case sensitive search */
- int m_iMinimumDuration; /*!< The minimum duration for an entry */
- int m_iMaximumDuration; /*!< The maximum duration for an entry */
- bool m_bRemoveDuplicates; /*!< True to remove duplicate events, false if not */
+ bool m_bIsCaseSensitive; /*!< Do a case sensitive search */
+ int m_iMinimumDuration; /*!< The minimum duration for an entry */
+ int m_iMaximumDuration; /*!< The maximum duration for an entry */
+ bool m_bRemoveDuplicates; /*!< True to remove duplicate events, false if not */
- // PVR specific filters
- bool m_bIsRadio; /*!< True to filter radio channels only, false to tv only */
- int m_iClientID = PVR_CLIENT_INVALID_UID; /*!< The client id */
- int m_iChannelGroupID{-1}; /*! The channel group id */
- int m_iChannelUID = -1; /*!< The channel uid */
- bool m_bFreeToAirOnly; /*!< Include free to air channels only */
- bool m_bIgnorePresentTimers; /*!< True to ignore currently present timers (future recordings), false if not */
- bool m_bIgnorePresentRecordings; /*!< True to ignore currently active recordings, false if not */
+ // PVR specific filters
+ bool m_bIsRadio; /*!< True to filter radio channels only, false to tv only */
+ int m_iClientID = PVR_CLIENT_INVALID_UID; /*!< The client id */
+ int m_iChannelGroupID{-1}; /*!< The channel group id */
+ int m_iChannelUID = -1; /*!< The channel uid */
+ bool m_bFreeToAirOnly; /*!< Include free to air channels only */
+ bool m_bIgnorePresentTimers; /*!< True to ignore currently present timers, false if not */
+ bool m_bIgnorePresentRecordings; /*!< True to ignore currently active recordings, false if not */
- int m_iDatabaseId = -1;
- std::string m_title;
- std::string m_iconPath;
- CDateTime m_lastExecutedDateTime;
- };
-}
+ int m_iDatabaseId{PVR_EPG_SEARCH_INVALID_DATABASE_ID};
+ std::string m_title;
+ std::string m_iconPath;
+ CDateTime m_lastExecutedDateTime;
+};
+} // namespace PVR
diff --git a/xbmc/pvr/guilib/PVRGUIActionsEPG.cpp b/xbmc/pvr/guilib/PVRGUIActionsEPG.cpp
index 9b76bb7672..866c3987e8 100644
--- a/xbmc/pvr/guilib/PVRGUIActionsEPG.cpp
+++ b/xbmc/pvr/guilib/PVRGUIActionsEPG.cpp
@@ -30,6 +30,7 @@
#include "settings/Settings.h"
#include "settings/SettingsComponent.h"
#include "storage/MediaManager.h"
+#include "utils/StringUtils.h"
#include "utils/Variant.h"
#include "utils/log.h"
@@ -248,6 +249,24 @@ bool CPVRGUIActionsEPG::ChooseIconForSavedSearch(const CFileItem& item)
return true;
}
+bool CPVRGUIActionsEPG::DuplicateSavedSearch(const CFileItem& item)
+{
+ const auto searchFilter{item.GetEPGSearchFilter()};
+
+ if (!searchFilter)
+ {
+ CLog::LogF(LOGERROR, "Wrong item type. No EPG search filter present.");
+ return false;
+ }
+
+ const auto dupedSearchFilter{std::make_shared<CPVREpgSearchFilter>(*searchFilter)};
+ dupedSearchFilter->SetDatabaseId(PVR_EPG_SEARCH_INVALID_DATABASE_ID); // force new db entry
+ dupedSearchFilter->SetTitle(StringUtils::Format(g_localizeStrings.Get(19356), // Copy of '<title>'
+ searchFilter->GetTitle()));
+ CServiceBroker::GetPVRManager().EpgContainer().PersistSavedSearch(*dupedSearchFilter);
+ return true;
+}
+
bool CPVRGUIActionsEPG::DeleteSavedSearch(const CFileItem& item)
{
const auto searchFilter = item.GetEPGSearchFilter();
diff --git a/xbmc/pvr/guilib/PVRGUIActionsEPG.h b/xbmc/pvr/guilib/PVRGUIActionsEPG.h
index 5041b1adc3..3f2ce6a1b5 100644
--- a/xbmc/pvr/guilib/PVRGUIActionsEPG.h
+++ b/xbmc/pvr/guilib/PVRGUIActionsEPG.h
@@ -76,6 +76,13 @@ public:
bool ChooseIconForSavedSearch(const CFileItem& item);
/*!
+ * @brief Duplicate a saved search.
+ * @param item The item containing a search filter.
+ * @return True on success, false otherwise.
+ */
+ bool DuplicateSavedSearch(const CFileItem& item);
+
+ /*!
* @brief Delete a saved search. Opens confirmation dialog before deleting.
* @param item The item containing a search filter.
* @return True on success, false otherwise.
diff --git a/xbmc/pvr/windows/GUIWindowPVRSearch.cpp b/xbmc/pvr/windows/GUIWindowPVRSearch.cpp
index 356e65dcc0..50504e4628 100644
--- a/xbmc/pvr/windows/GUIWindowPVRSearch.cpp
+++ b/xbmc/pvr/windows/GUIWindowPVRSearch.cpp
@@ -455,7 +455,7 @@ void CGUIWindowPVRSearchBase::ExecuteSearch()
}
// Save if not a transient search
- if (m_searchfilter->GetDatabaseId() != -1)
+ if (m_searchfilter->GetDatabaseId() != PVR_EPG_SEARCH_INVALID_DATABASE_ID)
CServiceBroker::GetPVRManager().EpgContainer().UpdateSavedSearchLastExecuted(*m_searchfilter);
}
diff --git a/xbmc/test/TestFileItem.cpp b/xbmc/test/TestFileItem.cpp
index e78ba27676..e5ca906ab8 100644
--- a/xbmc/test/TestFileItem.cpp
+++ b/xbmc/test/TestFileItem.cpp
@@ -42,63 +42,6 @@ AdvancedSettingsResetBase::AdvancedSettingsResetBase()
settings->GetAdvancedSettings()->Initialize(*settingsMgr);
}
-class TestFileItemSpecifiedArtJpg : public AdvancedSettingsResetBase,
- public WithParamInterface<TestFileData>
-{
-};
-
-
-TEST_P(TestFileItemSpecifiedArtJpg, GetLocalArt)
-{
- CFileItem item;
- item.SetPath(GetParam().file);
- std::string path = CURL(item.GetLocalArt("art.jpg", GetParam().use_folder)).Get();
- std::string compare = CURL(GetParam().base).Get();
- EXPECT_EQ(compare, path);
-}
-
-const TestFileData MovieFiles[] = {{ "c:\\dir\\filename.avi", false, "c:\\dir\\filename-art.jpg" },
- { "c:\\dir\\filename.avi", true, "c:\\dir\\art.jpg" },
- { "/dir/filename.avi", false, "/dir/filename-art.jpg" },
- { "/dir/filename.avi", true, "/dir/art.jpg" },
- { "smb://somepath/file.avi", false, "smb://somepath/file-art.jpg" },
- { "smb://somepath/file.avi", true, "smb://somepath/art.jpg" },
- { "stack:///path/to/movie-cd1.avi , /path/to/movie-cd2.avi", false, "/path/to/movie-art.jpg" },
- { "stack:///path/to/movie-cd1.avi , /path/to/movie-cd2.avi", true, "/path/to/art.jpg" },
- { "stack:///path/to/movie_name/cd1/some_file1.avi , /path/to/movie_name/cd2/some_file2.avi", true, "/path/to/movie_name/art.jpg" },
- { "/home/user/TV Shows/Dexter/S1/1x01.avi", false, "/home/user/TV Shows/Dexter/S1/1x01-art.jpg" },
- { "/home/user/TV Shows/Dexter/S1/1x01.avi", true, "/home/user/TV Shows/Dexter/S1/art.jpg" },
- { "zip://g%3a%5cmultimedia%5cmovies%5cSphere%2ezip/Sphere.avi", false, "g:\\multimedia\\movies\\Sphere-art.jpg" },
- { "zip://g%3a%5cmultimedia%5cmovies%5cSphere%2ezip/Sphere.avi", true, "g:\\multimedia\\movies\\art.jpg" },
- { "/home/user/movies/movie_name/video_ts/VIDEO_TS.IFO", false, "/home/user/movies/movie_name/art.jpg" },
- { "/home/user/movies/movie_name/video_ts/VIDEO_TS.IFO", true, "/home/user/movies/movie_name/art.jpg" },
- { "/home/user/movies/movie_name/BDMV/index.bdmv", false, "/home/user/movies/movie_name/art.jpg" },
- { "/home/user/movies/movie_name/BDMV/index.bdmv", true, "/home/user/movies/movie_name/art.jpg" }};
-
-INSTANTIATE_TEST_SUITE_P(MovieFiles, TestFileItemSpecifiedArtJpg, ValuesIn(MovieFiles));
-
-class TestFileItemFallbackArt : public AdvancedSettingsResetBase,
- public WithParamInterface<TestFileData>
-{
-};
-
-TEST_P(TestFileItemFallbackArt, GetLocalArt)
-{
- CFileItem item;
- item.SetPath(GetParam().file);
- std::string path = CURL(item.GetLocalArt("", GetParam().use_folder)).Get();
- std::string compare = CURL(GetParam().base).Get();
- EXPECT_EQ(compare, path);
-}
-
-const TestFileData NoArtFiles[] = {{ "c:\\dir\\filename.avi", false, "c:\\dir\\filename.tbn" },
- { "/dir/filename.avi", false, "/dir/filename.tbn" },
- { "smb://somepath/file.avi", false, "smb://somepath/file.tbn" },
- { "/home/user/TV Shows/Dexter/S1/1x01.avi", false, "/home/user/TV Shows/Dexter/S1/1x01.tbn" },
- { "zip://g%3a%5cmultimedia%5cmovies%5cSphere%2ezip/Sphere.avi", false, "g:\\multimedia\\movies\\Sphere.tbn" }};
-
-INSTANTIATE_TEST_SUITE_P(NoArt, TestFileItemFallbackArt, ValuesIn(NoArtFiles));
-
class TestFileItemBasePath : public AdvancedSettingsResetBase,
public WithParamInterface<TestFileData>
{
diff --git a/xbmc/utils/ArtUtils.cpp b/xbmc/utils/ArtUtils.cpp
index b1e90855fd..6394f6c7c8 100644
--- a/xbmc/utils/ArtUtils.cpp
+++ b/xbmc/utils/ArtUtils.cpp
@@ -178,6 +178,71 @@ std::string GetFolderThumb(const CFileItem& item, const std::string& folderJPG /
return URIUtils::AddFileToFolder(strFolder, folderJPG);
}
+std::string GetLocalArt(const CFileItem& item, const std::string& artFile, bool useFolder)
+{
+ // no retrieving of empty art files from folders
+ if (useFolder && artFile.empty())
+ return "";
+
+ std::string strFile = GetLocalArtBaseFilename(item, useFolder);
+ if (strFile.empty()) // empty filepath -> nothing to find
+ return "";
+
+ if (useFolder)
+ {
+ if (!artFile.empty())
+ return URIUtils::AddFileToFolder(strFile, artFile);
+ }
+ else
+ {
+ if (artFile.empty()) // old thumbnail matching
+ return URIUtils::ReplaceExtension(strFile, ".tbn");
+ else
+ return URIUtils::ReplaceExtension(strFile, "-" + artFile);
+ }
+ return "";
+}
+
+std::string GetLocalArtBaseFilename(const CFileItem& item, bool& useFolder)
+{
+ std::string strFile;
+ if (item.IsStack())
+ {
+ std::string strPath;
+ URIUtils::GetParentPath(item.GetPath(), strPath);
+ strFile = URIUtils::AddFileToFolder(
+ strPath, URIUtils::GetFileName(CStackDirectory::GetStackedTitlePath(item.GetPath())));
+ }
+
+ std::string file = strFile.empty() ? item.GetPath() : strFile;
+ if (URIUtils::IsInRAR(file) || URIUtils::IsInZIP(file))
+ {
+ std::string strPath = URIUtils::GetDirectory(file);
+ std::string strParent;
+ URIUtils::GetParentPath(strPath, strParent);
+ strFile = URIUtils::AddFileToFolder(strParent, URIUtils::GetFileName(file));
+ }
+
+ if (item.IsMultiPath())
+ strFile = CMultiPathDirectory::GetFirstPath(item.GetPath());
+
+ if (item.IsOpticalMediaFile())
+ { // optical media files should be treated like folders
+ useFolder = true;
+ strFile = item.GetLocalMetadataPath();
+ }
+ else if (useFolder && !(item.m_bIsFolder && !item.IsFileFolder()))
+ {
+ file = strFile.empty() ? item.GetPath() : strFile;
+ strFile = URIUtils::GetDirectory(file);
+ }
+
+ if (strFile.empty())
+ strFile = item.GetDynPath();
+
+ return strFile;
+}
+
std::string GetLocalFanart(const CFileItem& item)
{
if (VIDEO::IsVideoDb(item))
diff --git a/xbmc/utils/ArtUtils.h b/xbmc/utils/ArtUtils.h
index 07671d28dd..99848308b2 100644
--- a/xbmc/utils/ArtUtils.h
+++ b/xbmc/utils/ArtUtils.h
@@ -26,6 +26,24 @@ void FillInDefaultIcon(CFileItem& item);
*/
std::string GetFolderThumb(const CFileItem& item, const std::string& folderJPG = "folder.jpg");
+/*! \brief Assemble the filename of a particular piece of local artwork for an item.
+ No file existence check is typically performed.
+ \param artFile the art file to search for.
+ \param useFolder whether to look in the folder for the art file. Defaults to false.
+ \return the path to the local artwork.
+ \sa FindLocalArt
+ */
+std::string GetLocalArt(const CFileItem& item, const std::string& artFile, bool useFolder = false);
+
+/*!
+ \brief Assemble the base filename of local artwork for an item,
+ accounting for archives, stacks and multi-paths, and BDMV/VIDEO_TS folders.
+ \param useFolder whether to look in the folder for the art file. Defaults to false.
+ \return the path to the base filename for artwork lookup.
+ \sa GetLocalArt
+ */
+std::string GetLocalArtBaseFilename(const CFileItem& item, bool& useFolder);
+
/*!
\brief Get the local fanart for item if it exists
\return path to the local fanart for this item, or empty if none exists
diff --git a/xbmc/utils/test/TestArtUtils.cpp b/xbmc/utils/test/TestArtUtils.cpp
index f373634e55..6f9f1967db 100644
--- a/xbmc/utils/test/TestArtUtils.cpp
+++ b/xbmc/utils/test/TestArtUtils.cpp
@@ -7,9 +7,14 @@
*/
#include "FileItem.h"
+#include "ServiceBroker.h"
#include "URL.h"
#include "filesystem/Directory.h"
#include "platform/Filesystem.h"
+#include "settings/AdvancedSettings.h"
+#include "settings/Settings.h"
+#include "settings/SettingsComponent.h"
+#include "settings/lib/SettingsManager.h"
#include "utils/ArtUtils.h"
#include "utils/FileUtils.h"
#include "utils/StringUtils.h"
@@ -47,6 +52,47 @@ std::string unique_path(const std::string& input)
return ret;
}
+class AdvancedSettingsResetBase : public testing::Test
+{
+public:
+ AdvancedSettingsResetBase();
+};
+
+AdvancedSettingsResetBase::AdvancedSettingsResetBase()
+{
+ // Force all advanced settings to be reset to defaults
+ const auto settings = CServiceBroker::GetSettingsComponent();
+ CSettingsManager* settingsMgr = settings->GetSettings()->GetSettingsManager();
+ settings->GetAdvancedSettings()->Uninitialize(*settingsMgr);
+ settings->GetAdvancedSettings()->Initialize(*settingsMgr);
+}
+
+struct ArtFilenameTest
+{
+ std::string path;
+ std::string result;
+ bool isFolder = false;
+ bool result_folder = false;
+ bool force_use_folder = false;
+};
+
+class GetLocalArtBaseFilenameTest : public testing::WithParamInterface<ArtFilenameTest>,
+ public testing::Test
+{
+};
+
+const auto local_art_filename_tests = std::array{
+ ArtFilenameTest{"/home/user/foo.avi", "/home/user/foo.avi"},
+ ArtFilenameTest{"stack:///home/user/foo-cd1.avi , /home/user/foo-cd2.avi",
+ "/home/user/foo.avi"},
+ ArtFilenameTest{"zip://%2fhome%2fuser%2fbar.zip/foo.avi", "/home/user/foo.avi"},
+ ArtFilenameTest{"multipath://%2fhome%2fuser%2fbar%2f/%2fhome%2fuser%2ffoo%2f",
+ "/home/user/bar/", true, true},
+ ArtFilenameTest{"/home/user/VIDEO_TS/VIDEO_TS.IFO", "/home/user/", false, true},
+ ArtFilenameTest{"/home/user/BDMV/index.bdmv", "/home/user/", false, true},
+ ArtFilenameTest{"/home/user/foo.avi", "/home/user/", false, true, true},
+};
+
struct FanartTest
{
std::string path;
@@ -147,6 +193,58 @@ class FolderThumbTest : public testing::WithParamInterface<FolderTest>, public t
{
};
+struct LocalArtTest
+{
+ std::string file;
+ std::string art;
+ bool use_folder;
+ std::string base;
+};
+
+const auto local_art_tests = std::array{
+ LocalArtTest{"c:\\dir\\filename.avi", "art.jpg", false, "c:\\dir\\filename-art.jpg"},
+ LocalArtTest{"c:\\dir\\filename.avi", "art.jpg", true, "c:\\dir\\art.jpg"},
+ LocalArtTest{"/dir/filename.avi", "art.jpg", false, "/dir/filename-art.jpg"},
+ LocalArtTest{"/dir/filename.avi", "art.jpg", true, "/dir/art.jpg"},
+ LocalArtTest{"smb://somepath/file.avi", "art.jpg", false, "smb://somepath/file-art.jpg"},
+ LocalArtTest{"smb://somepath/file.avi", "art.jpg", true, "smb://somepath/art.jpg"},
+ LocalArtTest{"stack:///path/to/movie-cd1.avi , /path/to/movie-cd2.avi", "art.jpg", false,
+ "/path/to/movie-art.jpg"},
+ LocalArtTest{"stack:///path/to/movie-cd1.avi , /path/to/movie-cd2.avi", "art.jpg", true,
+ "/path/to/art.jpg"},
+ LocalArtTest{
+ "stack:///path/to/movie_name/cd1/some_file1.avi , /path/to/movie_name/cd2/some_file2.avi",
+ "art.jpg", true, "/path/to/movie_name/art.jpg"},
+ LocalArtTest{"/home/user/TV Shows/Dexter/S1/1x01.avi", "art.jpg", false,
+ "/home/user/TV Shows/Dexter/S1/1x01-art.jpg"},
+ LocalArtTest{"/home/user/TV Shows/Dexter/S1/1x01.avi", "art.jpg", true,
+ "/home/user/TV Shows/Dexter/S1/art.jpg"},
+ LocalArtTest{"zip://g%3a%5cmultimedia%5cmovies%5cSphere%2ezip/Sphere.avi", "art.jpg", false,
+ "g:\\multimedia\\movies\\Sphere-art.jpg"},
+ LocalArtTest{"zip://g%3a%5cmultimedia%5cmovies%5cSphere%2ezip/Sphere.avi", "art.jpg", true,
+ "g:\\multimedia\\movies\\art.jpg"},
+ LocalArtTest{"/home/user/movies/movie_name/video_ts/VIDEO_TS.IFO", "art.jpg", false,
+ "/home/user/movies/movie_name/art.jpg"},
+ LocalArtTest{"/home/user/movies/movie_name/video_ts/VIDEO_TS.IFO", "art.jpg", true,
+ "/home/user/movies/movie_name/art.jpg"},
+ LocalArtTest{"/home/user/movies/movie_name/BDMV/index.bdmv", "art.jpg", false,
+ "/home/user/movies/movie_name/art.jpg"},
+ LocalArtTest{"/home/user/movies/movie_name/BDMV/index.bdmv", "art.jpg", true,
+ "/home/user/movies/movie_name/art.jpg"},
+ LocalArtTest{"c:\\dir\\filename.avi", "", false, "c:\\dir\\filename.tbn"},
+ LocalArtTest{"/dir/filename.avi", "", false, "/dir/filename.tbn"},
+ LocalArtTest{"smb://somepath/file.avi", "", false, "smb://somepath/file.tbn"},
+ LocalArtTest{"/home/user/TV Shows/Dexter/S1/1x01.avi", "", false,
+ "/home/user/TV Shows/Dexter/S1/1x01.tbn"},
+ LocalArtTest{"zip://g%3a%5cmultimedia%5cmovies%5cSphere%2ezip/Sphere.avi", "", false,
+ "g:\\multimedia\\movies\\Sphere.tbn"},
+};
+
+class TestLocalArt : public AdvancedSettingsResetBase,
+ public testing::WithParamInterface<LocalArtTest>
+{
+};
+
} // namespace
TEST_P(FillInDefaultIconTest, FillInDefaultIcon)
@@ -173,6 +271,30 @@ TEST_P(FolderThumbTest, GetFolderThumb)
INSTANTIATE_TEST_SUITE_P(TestArtUtils, FolderThumbTest, testing::ValuesIn(folder_thumb_tests));
+TEST_P(TestLocalArt, GetLocalArt)
+{
+ CFileItem item;
+ item.SetPath(GetParam().file);
+ std::string path = CURL(ART::GetLocalArt(item, GetParam().art, GetParam().use_folder)).Get();
+ std::string compare = CURL(GetParam().base).Get();
+ EXPECT_EQ(compare, path);
+}
+
+INSTANTIATE_TEST_SUITE_P(TestArtUtils, TestLocalArt, testing::ValuesIn(local_art_tests));
+
+TEST_P(GetLocalArtBaseFilenameTest, GetLocalArtBaseFilename)
+{
+ CFileItem item(GetParam().path, GetParam().isFolder);
+ bool useFolder = GetParam().force_use_folder ? true : GetParam().isFolder;
+ const std::string res = ART::GetLocalArtBaseFilename(item, useFolder);
+ EXPECT_EQ(res, GetParam().result);
+ EXPECT_EQ(useFolder, GetParam().result_folder);
+}
+
+INSTANTIATE_TEST_SUITE_P(TestArtUtils,
+ GetLocalArtBaseFilenameTest,
+ testing::ValuesIn(local_art_filename_tests));
+
TEST_P(GetLocalFanartTest, GetLocalFanart)
{
std::string path, file_path, uniq;
diff --git a/xbmc/video/VideoDatabase.cpp b/xbmc/video/VideoDatabase.cpp
index e4e51a7f86..f333bb334b 100644
--- a/xbmc/video/VideoDatabase.cpp
+++ b/xbmc/video/VideoDatabase.cpp
@@ -10748,7 +10748,7 @@ void CVideoDatabase::ExportToXML(const std::string &path, bool singleFile /* = t
}
for (const auto &i : artwork)
{
- std::string savedThumb = item.GetLocalArt(i.first, false);
+ std::string savedThumb = ART::GetLocalArt(item, i.first, false);
CServiceBroker::GetTextureCache()->Export(i.second, savedThumb, overwrite);
}
if (actorThumbs)
@@ -10894,7 +10894,7 @@ void CVideoDatabase::ExportToXML(const std::string &path, bool singleFile /* = t
}
for (const auto &i : artwork)
{
- std::string savedThumb = item.GetLocalArt(i.first, false);
+ std::string savedThumb = ART::GetLocalArt(item, i.first, false);
CServiceBroker::GetTextureCache()->Export(i.second, savedThumb, overwrite);
}
}
@@ -10992,7 +10992,7 @@ void CVideoDatabase::ExportToXML(const std::string &path, bool singleFile /* = t
for (const auto &i : artwork)
{
- std::string savedThumb = item.GetLocalArt(i.first, true);
+ std::string savedThumb = ART::GetLocalArt(item, i.first, true);
CServiceBroker::GetTextureCache()->Export(i.second, savedThumb, overwrite);
}
@@ -11011,7 +11011,7 @@ void CVideoDatabase::ExportToXML(const std::string &path, bool singleFile /* = t
seasonThumb = StringUtils::Format("season{:02}", i.first);
for (const auto &j : i.second)
{
- std::string savedThumb(item.GetLocalArt(seasonThumb + "-" + j.first, true));
+ std::string savedThumb(ART::GetLocalArt(item, seasonThumb + "-" + j.first, true));
if (!i.second.empty())
CServiceBroker::GetTextureCache()->Export(j.second, savedThumb, overwrite);
}
@@ -11094,7 +11094,7 @@ void CVideoDatabase::ExportToXML(const std::string &path, bool singleFile /* = t
}
for (const auto &i : artwork)
{
- std::string savedThumb = item.GetLocalArt(i.first, false);
+ std::string savedThumb = ART::GetLocalArt(item, i.first, false);
CServiceBroker::GetTextureCache()->Export(i.second, savedThumb, overwrite);
}
if (actorThumbs)
diff --git a/xbmc/video/VideoInfoScanner.cpp b/xbmc/video/VideoInfoScanner.cpp
index 9dc3588a5c..c02ee60282 100644
--- a/xbmc/video/VideoInfoScanner.cpp
+++ b/xbmc/video/VideoInfoScanner.cpp
@@ -38,6 +38,7 @@
#include "settings/Settings.h"
#include "settings/SettingsComponent.h"
#include "tags/VideoInfoTagLoaderFactory.h"
+#include "utils/ArtUtils.h"
#include "utils/Digest.h"
#include "utils/FileExtensionProvider.h"
#include "utils/RegExp.h"
@@ -1792,14 +1793,21 @@ namespace KODI::VIDEO
{
if (!pItem->SkipLocalArt())
{
+ bool useFolder = false;
if (bApplyToDir && (content == CONTENT_MOVIES || content == CONTENT_MUSICVIDEOS))
{
- std::string filename = pItem->GetLocalArtBaseFilename();
+ std::string filename = ART::GetLocalArtBaseFilename(*pItem, useFolder);
std::string directory = URIUtils::GetDirectory(filename);
if (filename != directory)
AddLocalItemArtwork(art, artTypes, directory, addAll, exactName);
}
- AddLocalItemArtwork(art, artTypes, pItem->GetLocalArtBaseFilename(), addAll, exactName);
+
+ // Reset useFolder to false as GetLocalArtBaseFilename may modify it in
+ // the previous call.
+ useFolder = false;
+
+ AddLocalItemArtwork(art, artTypes, ART::GetLocalArtBaseFilename(*pItem, useFolder), addAll,
+ exactName);
}
if (moviePartOfSet)