aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore7
-rw-r--r--Kodi.xcodeproj/project.pbxproj90
-rw-r--r--Makefile.in1
-rw-r--r--addons/resource.language.en_gb/resources/strings.po486
-rw-r--r--addons/skin.confluence/720p/DialogPVRRadioRDSInfo.xml949
-rw-r--r--addons/skin.confluence/720p/Home.xml21
-rw-r--r--addons/skin.confluence/720p/MusicOSD.xml19
-rw-r--r--addons/skin.confluence/720p/MusicVisualisation.xml4
-rw-r--r--addons/skin.confluence/720p/MyPVRChannels.xml893
-rw-r--r--addons/skin.confluence/720p/PlayerControls.xml17
-rw-r--r--addons/skin.confluence/720p/SkinSettings.xml12
-rw-r--r--addons/skin.confluence/720p/includes.xml44
-rw-r--r--addons/skin.confluence/language/resource.language.en_gb/strings.po10
-rw-r--r--addons/skin.confluence/media/OSDRadioRDSFO.pngbin0 -> 5776 bytes
-rw-r--r--addons/skin.confluence/media/OSDRadioRDSNF.pngbin0 -> 1419 bytes
-rw-r--r--addons/skin.confluence/media/flagging/rds/rds-logo.pngbin0 -> 22082 bytes
-rw-r--r--addons/skin.confluence/media/flagging/rds/rds-radiotext-logo.pngbin0 -> 29924 bytes
-rw-r--r--addons/skin.confluence/media/flagging/rds/rds-radiotext-plus-logo.pngbin0 -> 32031 bytes
-rw-r--r--configure.ac55
-rw-r--r--project/BuildDependencies/scripts/0_package.list2
-rw-r--r--project/VS2010Express/XBMC.vcxproj15
-rw-r--r--project/VS2010Express/XBMC.vcxproj.filters48
-rw-r--r--project/VS2010Express/XbmcThreads.vcxproj2
-rw-r--r--project/VS2010Express/XbmcThreads.vcxproj.filters2
-rw-r--r--system/settings/settings.xml36
-rw-r--r--tools/depends/native/Makefile5
-rw-r--r--tools/depends/native/giflib-native/Makefile2
-rw-r--r--tools/depends/native/libsdl-native/01-SDL_SetWidthHeight.patch33
-rw-r--r--tools/depends/native/libsdl-native/02-OSX_interpretKeyEvents.patch15
-rw-r--r--tools/depends/native/libsdl-native/03-mavericks-compile.patch12
-rw-r--r--tools/depends/native/libsdl-native/Makefile43
-rw-r--r--tools/depends/native/libsdl_image-native/Makefile41
-rw-r--r--tools/depends/target/Makefile2
-rw-r--r--tools/depends/target/giflib/01-android.patch18
-rw-r--r--tools/depends/target/giflib/Makefile48
-rw-r--r--tools/depends/target/gmp/Makefile3
-rw-r--r--xbmc/Application.cpp16
-rw-r--r--xbmc/ApplicationPlayer.cpp20
-rw-r--r--xbmc/ApplicationPlayer.h3
-rw-r--r--xbmc/Autorun.cpp10
-rw-r--r--xbmc/DllPaths_generated.h.in3
-rw-r--r--xbmc/DllPaths_generated_android.h.in2
-rw-r--r--xbmc/DllPaths_win32.h1
-rw-r--r--xbmc/FileItem.cpp27
-rw-r--r--xbmc/FileItem.h19
-rw-r--r--xbmc/GUIInfoManager.cpp324
-rw-r--r--xbmc/GUIInfoManager.h7
-rw-r--r--xbmc/GUIUserMessages.h3
-rw-r--r--xbmc/LangInfo.cpp2
-rw-r--r--xbmc/addons/Addon.h2
-rw-r--r--xbmc/addons/AddonCallbacksGUI.cpp14
-rw-r--r--xbmc/addons/AddonInstaller.cpp71
-rw-r--r--xbmc/addons/AddonInstaller.h16
-rw-r--r--xbmc/addons/GUIDialogAddonInfo.cpp8
-rw-r--r--xbmc/addons/IAddon.h2
-rw-r--r--xbmc/addons/ImageResource.cpp4
-rw-r--r--xbmc/addons/LanguageResource.cpp9
-rw-r--r--xbmc/addons/Repository.cpp35
-rw-r--r--xbmc/addons/Skin.cpp9
-rw-r--r--xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSP.cpp15
-rw-r--r--xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSP.h7
-rw-r--r--xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPAddon.cpp6
-rw-r--r--xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPAddon.h2
-rw-r--r--xbmc/cores/DllLoader/SoLoader.cpp1
-rw-r--r--xbmc/cores/IPlayer.h3
-rw-r--r--xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayCodecSSA.cpp6
-rw-r--r--xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.cpp32
-rw-r--r--xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.h23
-rw-r--r--xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp2
-rw-r--r--xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp14
-rw-r--r--xbmc/cores/dvdplayer/DVDMessageQueue.cpp2
-rw-r--r--xbmc/cores/dvdplayer/DVDPlayer.cpp80
-rw-r--r--xbmc/cores/dvdplayer/DVDPlayer.h9
-rw-r--r--xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp1748
-rw-r--r--xbmc/cores/dvdplayer/DVDPlayerRadioRDS.h161
-rw-r--r--xbmc/cores/dvdplayer/Makefile.in1
-rw-r--r--xbmc/dialogs/GUIDialogKeyboardGeneric.cpp8
-rw-r--r--xbmc/dialogs/GUIDialogYesNo.cpp35
-rw-r--r--xbmc/dialogs/GUIDialogYesNo.h23
-rw-r--r--xbmc/filesystem/FileCache.cpp4
-rw-r--r--xbmc/filesystem/XbtFile.cpp2
-rw-r--r--xbmc/guiinfo/GUIInfoLabels.h48
-rw-r--r--xbmc/guilib/AnimatedGif.cpp663
-rw-r--r--xbmc/guilib/AnimatedGif.h162
-rw-r--r--xbmc/guilib/DllLibGif.h187
-rw-r--r--xbmc/guilib/GUIFontTTF.cpp2
-rw-r--r--xbmc/guilib/GUITexture.cpp70
-rw-r--r--xbmc/guilib/GUITexture.h5
-rw-r--r--xbmc/guilib/GUIWindowManager.cpp28
-rw-r--r--xbmc/guilib/Gif.cpp627
-rw-r--r--xbmc/guilib/Gif.h121
-rw-r--r--xbmc/guilib/Makefile.in7
-rw-r--r--xbmc/guilib/TextureBundleXBT.cpp2
-rw-r--r--xbmc/guilib/TextureManager.cpp46
-rw-r--r--xbmc/guilib/WindowIDs.h1
-rw-r--r--xbmc/guilib/imagefactory.cpp8
-rw-r--r--xbmc/input/ButtonTranslator.cpp1
-rw-r--r--xbmc/input/InputManager.cpp4
-rw-r--r--xbmc/interfaces/Builtins.cpp28
-rw-r--r--xbmc/interfaces/legacy/InfoTagRadioRDS.cpp248
-rw-r--r--xbmc/interfaces/legacy/InfoTagRadioRDS.h165
-rw-r--r--xbmc/interfaces/legacy/Makefile1
-rw-r--r--xbmc/interfaces/legacy/Player.cpp19
-rw-r--r--xbmc/interfaces/legacy/Player.h15
-rw-r--r--xbmc/interfaces/python/swig.cpp33
-rw-r--r--xbmc/interfaces/swig/AddonModuleXbmc.i1
-rw-r--r--xbmc/main/osx/SDLMain.h2
-rw-r--r--xbmc/main/osx/SDLMain.mm2
-rw-r--r--xbmc/messaging/ApplicationMessenger.cpp37
-rw-r--r--xbmc/messaging/ApplicationMessenger.h32
-rw-r--r--xbmc/messaging/ThreadMessage.h17
-rw-r--r--xbmc/messaging/helpers/DialogHelper.cpp89
-rw-r--r--xbmc/messaging/helpers/DialogHelper.h98
-rw-r--r--xbmc/messaging/helpers/Makefile.in6
-rw-r--r--xbmc/music/GUIViewStateMusic.cpp19
-rw-r--r--xbmc/music/MusicDatabase.cpp14
-rw-r--r--xbmc/music/dialogs/GUIDialogMusicOSD.cpp3
-rw-r--r--xbmc/music/tags/MusicInfoTag.cpp43
-rw-r--r--xbmc/network/NetworkServices.cpp11
-rw-r--r--xbmc/network/WakeOnAccess.cpp8
-rw-r--r--xbmc/network/cddb.cpp4
-rw-r--r--xbmc/network/upnp/UPnPPlayer.cpp11
-rw-r--r--xbmc/osx/CocoaInterface.h7
-rw-r--r--xbmc/osx/CocoaInterface.mm49
-rw-r--r--xbmc/osx/DarwinUtils.mm8
-rw-r--r--xbmc/osx/OSXTextInputResponder.mm2
-rw-r--r--xbmc/pvr/PVRManager.cpp37
-rw-r--r--xbmc/pvr/PVRManager.h5
-rw-r--r--xbmc/pvr/addons/PVRClient.cpp21
-rw-r--r--xbmc/pvr/addons/PVRClient.h2
-rw-r--r--xbmc/pvr/channels/Makefile3
-rw-r--r--xbmc/pvr/channels/PVRRadioRDSInfoTag.cpp908
-rw-r--r--xbmc/pvr/channels/PVRRadioRDSInfoTag.h231
-rw-r--r--xbmc/pvr/dialogs/GUIDialogPVRRadioRDSInfo.cpp416
-rw-r--r--xbmc/pvr/dialogs/GUIDialogPVRRadioRDSInfo.h72
-rw-r--r--xbmc/pvr/dialogs/Makefile1
-rw-r--r--xbmc/pvr/timers/PVRTimerInfoTag.cpp8
-rw-r--r--xbmc/pvr/timers/PVRTimers.cpp2
-rw-r--r--xbmc/settings/DisplaySettings.cpp15
-rw-r--r--xbmc/settings/MediaSettings.cpp11
-rw-r--r--xbmc/settings/SettingAddon.cpp4
-rw-r--r--xbmc/settings/SettingAddon.h2
-rw-r--r--xbmc/system.h5
-rw-r--r--xbmc/threads/LockFree.cpp279
-rw-r--r--xbmc/threads/LockFree.h124
-rw-r--r--xbmc/threads/Makefile1
-rw-r--r--xbmc/utils/AutoPtrHandle.h42
-rw-r--r--xbmc/utils/CryptThreading.cpp5
-rw-r--r--xbmc/utils/RssManager.cpp12
-rw-r--r--xbmc/utils/SystemInfo.cpp4
-rw-r--r--xbmc/video/Teletext.cpp4
-rw-r--r--xbmc/video/VideoInfoScanner.cpp8
-rw-r--r--xbmc/windowing/WinEventsSDL.h4
153 files changed, 8783 insertions, 2123 deletions
diff --git a/.gitignore b/.gitignore
index 90bfcbbacf..c4eb27f570 100644
--- a/.gitignore
+++ b/.gitignore
@@ -337,6 +337,7 @@ lib/cpluff/stamp-h1
/project/VS2010Express/*.vsp
/project/VS2010Express/*.metaproj
/project/VS2010Express/*.metaproj.tmp
+/project/VS2010Express/.vs
# /skin/
/skin/Confluence/media/Textures.xbt
@@ -827,3 +828,9 @@ xbmc/main/posix/Makefile
/pvr-addons
/adsp-addons
+
+# files removed in Jarvis
+/addons/visualization.dxspectrum/*
+/addons/visualization.milkdrop/*
+/addons/visualization.vortex/*
+/addons/visualization.waveform/*
diff --git a/Kodi.xcodeproj/project.pbxproj b/Kodi.xcodeproj/project.pbxproj
index 21170206de..7c35fc1425 100644
--- a/Kodi.xcodeproj/project.pbxproj
+++ b/Kodi.xcodeproj/project.pbxproj
@@ -29,7 +29,6 @@
18B7C38B12942090009E7A26 /* GUIViewStateAddonBrowser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B7C38812942090009E7A26 /* GUIViewStateAddonBrowser.cpp */; };
18B7C392129420E5009E7A26 /* Settings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B7C38E129420E5009E7A26 /* Settings.cpp */; };
18B7C3A812942132009E7A26 /* AdvancedSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B7C3A612942132009E7A26 /* AdvancedSettings.cpp */; };
- 18B7C7A91294222E009E7A26 /* AnimatedGif.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B7C7541294222E009E7A26 /* AnimatedGif.cpp */; };
18B7C7AB1294222E009E7A26 /* D3DResource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B7C7561294222E009E7A26 /* D3DResource.cpp */; };
18B7C7AC1294222E009E7A26 /* DDSImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B7C7571294222E009E7A26 /* DDSImage.cpp */; };
18B7C7AD1294222E009E7A26 /* DirectXGraphics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B7C7581294222E009E7A26 /* DirectXGraphics.cpp */; };
@@ -256,6 +255,9 @@
39B4F3701B96F845009B2D88 /* RepositoryUpdater.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39B4F36E1B96F845009B2D88 /* RepositoryUpdater.cpp */; };
39B4F3711B96F845009B2D88 /* RepositoryUpdater.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39B4F36E1B96F845009B2D88 /* RepositoryUpdater.cpp */; };
39B4F3721B96F845009B2D88 /* RepositoryUpdater.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39B4F36E1B96F845009B2D88 /* RepositoryUpdater.cpp */; };
+ 39BD2AD81B845D40004A5A15 /* DialogHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39BD2AD71B845D40004A5A15 /* DialogHelper.cpp */; };
+ 39BD2AD91B845D40004A5A15 /* DialogHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39BD2AD71B845D40004A5A15 /* DialogHelper.cpp */; };
+ 39BD2ADA1B845D40004A5A15 /* DialogHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39BD2AD71B845D40004A5A15 /* DialogHelper.cpp */; };
4260D5C71B67BB8F003F6F2D /* GUIWindowSplash.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4260D5C51B67BB8F003F6F2D /* GUIWindowSplash.cpp */; };
4260D5C81B67BB8F003F6F2D /* GUIWindowSplash.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4260D5C51B67BB8F003F6F2D /* GUIWindowSplash.cpp */; };
4260D5C91B67BB8F003F6F2D /* GUIWindowSplash.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4260D5C51B67BB8F003F6F2D /* GUIWindowSplash.cpp */; };
@@ -732,7 +734,6 @@
7CF80DCB19710DC2003B2B34 /* KeyboardLayout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CF80DC719710DC2003B2B34 /* KeyboardLayout.cpp */; };
815EE6350E17F1DC009FBE3C /* DVDInputStreamRTMP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 815EE6330E17F1DC009FBE3C /* DVDInputStreamRTMP.cpp */; };
820023DB171A28A300667D1C /* OSXTextInputResponder.mm in Sources */ = {isa = PBXBuildFile; fileRef = 820023DA171A28A300667D1C /* OSXTextInputResponder.mm */; };
- 83A72B970FBC8E3B00171871 /* LockFree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83A72B950FBC8E3B00171871 /* LockFree.cpp */; settings = {COMPILER_FLAGS = "-O0"; }; };
83E0B2490F7C95FF0091643F /* Atomics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83E0B2480F7C95FF0091643F /* Atomics.cpp */; };
880DBE4E0DC223FF00E26B71 /* MediaSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 880DBE4B0DC223FF00E26B71 /* MediaSource.cpp */; };
880DBE550DC224A100E26B71 /* MusicFileDirectory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 880DBE530DC224A100E26B71 /* MusicFileDirectory.cpp */; };
@@ -829,6 +830,18 @@
DF0ABB74183A94A30018445D /* Utf8Utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF0ABB71183A94A30018445D /* Utf8Utils.cpp */; };
DF0ABB75183A94A30018445D /* Utf8Utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF0ABB71183A94A30018445D /* Utf8Utils.cpp */; };
DF0DF15C13A3ADA7008ED511 /* NFSDirectory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF0DF15913A3ADA7008ED511 /* NFSDirectory.cpp */; };
+ DF0E4AC51AD597ED00A75430 /* DVDPlayerRadioRDS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF0E4AC31AD597ED00A75430 /* DVDPlayerRadioRDS.cpp */; };
+ DF0E4AC61AD597ED00A75430 /* DVDPlayerRadioRDS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF0E4AC31AD597ED00A75430 /* DVDPlayerRadioRDS.cpp */; };
+ DF0E4AC71AD597ED00A75430 /* DVDPlayerRadioRDS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF0E4AC31AD597ED00A75430 /* DVDPlayerRadioRDS.cpp */; };
+ DF0E4ACA1AD5982500A75430 /* InfoTagRadioRDS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF0E4AC81AD5982500A75430 /* InfoTagRadioRDS.cpp */; };
+ DF0E4ACB1AD5982500A75430 /* InfoTagRadioRDS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF0E4AC81AD5982500A75430 /* InfoTagRadioRDS.cpp */; };
+ DF0E4ACC1AD5982500A75430 /* InfoTagRadioRDS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF0E4AC81AD5982500A75430 /* InfoTagRadioRDS.cpp */; };
+ DF0E4ACF1AD5984600A75430 /* PVRRadioRDSInfoTag.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF0E4ACD1AD5984600A75430 /* PVRRadioRDSInfoTag.cpp */; };
+ DF0E4AD01AD5984600A75430 /* PVRRadioRDSInfoTag.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF0E4ACD1AD5984600A75430 /* PVRRadioRDSInfoTag.cpp */; };
+ DF0E4AD11AD5984600A75430 /* PVRRadioRDSInfoTag.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF0E4ACD1AD5984600A75430 /* PVRRadioRDSInfoTag.cpp */; };
+ DF0E4AD41AD5986F00A75430 /* GUIDialogPVRRadioRDSInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF0E4AD21AD5986F00A75430 /* GUIDialogPVRRadioRDSInfo.cpp */; };
+ DF0E4AD51AD5986F00A75430 /* GUIDialogPVRRadioRDSInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF0E4AD21AD5986F00A75430 /* GUIDialogPVRRadioRDSInfo.cpp */; };
+ DF0E4AD61AD5986F00A75430 /* GUIDialogPVRRadioRDSInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF0E4AD21AD5986F00A75430 /* GUIDialogPVRRadioRDSInfo.cpp */; };
DF14CF7E1A77782E00396CC9 /* InputManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF14CF7C1A77782E00396CC9 /* InputManager.cpp */; };
DF14CF7F1A77782E00396CC9 /* InputManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF14CF7C1A77782E00396CC9 /* InputManager.cpp */; };
DF14CF801A77782E00396CC9 /* InputManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF14CF7C1A77782E00396CC9 /* InputManager.cpp */; };
@@ -848,6 +861,9 @@
DF2401261B41A26F001E02DA /* ImageResource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2401241B41A26E001E02DA /* ImageResource.cpp */; };
DF2401271B41A26F001E02DA /* ImageResource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2401241B41A26E001E02DA /* ImageResource.cpp */; };
DF2401281B41A26F001E02DA /* ImageResource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2401241B41A26E001E02DA /* ImageResource.cpp */; };
+ DF2863B719918B07008994AB /* Gif.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2863B519918B07008994AB /* Gif.cpp */; };
+ DF2863B819918B07008994AB /* Gif.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2863B519918B07008994AB /* Gif.cpp */; };
+ DF2863B919918B07008994AB /* Gif.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2863B519918B07008994AB /* Gif.cpp */; };
DF28DF4D17B8379E0077F41A /* ProfilesOperations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF28DF4B17B8379E0077F41A /* ProfilesOperations.cpp */; };
DF28DF4E17B8379E0077F41A /* ProfilesOperations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF28DF4B17B8379E0077F41A /* ProfilesOperations.cpp */; };
DF28DF4F17B8379E0077F41A /* ProfilesOperations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF28DF4B17B8379E0077F41A /* ProfilesOperations.cpp */; };
@@ -1442,7 +1458,6 @@
DFF0F26E17528350002DA3A4 /* ZipDirectory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38E17930D25F9FA00618676 /* ZipDirectory.cpp */; };
DFF0F26F17528350002DA3A4 /* ZipFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF93D6971444A8B0007C6459 /* ZipFile.cpp */; };
DFF0F27017528350002DA3A4 /* ZipManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38E17950D25F9FA00618676 /* ZipManager.cpp */; };
- DFF0F27117528350002DA3A4 /* AnimatedGif.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B7C7541294222E009E7A26 /* AnimatedGif.cpp */; };
DFF0F27217528350002DA3A4 /* cximage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF404A3416B9896C00D8023E /* cximage.cpp */; };
DFF0F27317528350002DA3A4 /* D3DResource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B7C7561294222E009E7A26 /* D3DResource.cpp */; };
DFF0F27417528350002DA3A4 /* DDSImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B7C7571294222E009E7A26 /* DDSImage.cpp */; };
@@ -1743,7 +1758,6 @@
DFF0F3B317528350002DA3A4 /* Implementation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 38F4E56C13CCCB3B00664821 /* Implementation.cpp */; };
DFF0F3B417528350002DA3A4 /* Atomics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83E0B2480F7C95FF0091643F /* Atomics.cpp */; };
DFF0F3B517528350002DA3A4 /* Event.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38E1E350D25F9FD00618676 /* Event.cpp */; };
- DFF0F3B617528350002DA3A4 /* LockFree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83A72B950FBC8E3B00171871 /* LockFree.cpp */; };
DFF0F3B717528350002DA3A4 /* SystemClock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3802709813D5A653009493DD /* SystemClock.cpp */; };
DFF0F3B817528350002DA3A4 /* Thread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38E1E850D25F9FD00618676 /* Thread.cpp */; };
DFF0F3B917528350002DA3A4 /* Timer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFD928F116384B6800709DAE /* Timer.cpp */; };
@@ -2609,7 +2623,6 @@
E49912D7174E5DA000741B6D /* ZipDirectory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38E17930D25F9FA00618676 /* ZipDirectory.cpp */; };
E49912D8174E5DA000741B6D /* ZipFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF93D6971444A8B0007C6459 /* ZipFile.cpp */; };
E49912D9174E5DA000741B6D /* ZipManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38E17950D25F9FA00618676 /* ZipManager.cpp */; };
- E49912DA174E5DAD00741B6D /* AnimatedGif.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B7C7541294222E009E7A26 /* AnimatedGif.cpp */; };
E49912DB174E5DAD00741B6D /* cximage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF404A3416B9896C00D8023E /* cximage.cpp */; };
E49912DC174E5DAD00741B6D /* D3DResource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B7C7561294222E009E7A26 /* D3DResource.cpp */; };
E49912DD174E5DAD00741B6D /* DDSImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B7C7571294222E009E7A26 /* DDSImage.cpp */; };
@@ -2910,7 +2923,6 @@
E4991437174E604700741B6D /* Implementation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 38F4E56C13CCCB3B00664821 /* Implementation.cpp */; };
E4991438174E604700741B6D /* Atomics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83E0B2480F7C95FF0091643F /* Atomics.cpp */; };
E4991439174E604700741B6D /* Event.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38E1E350D25F9FD00618676 /* Event.cpp */; };
- E499143A174E604700741B6D /* LockFree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83A72B950FBC8E3B00171871 /* LockFree.cpp */; };
E499143B174E604700741B6D /* SystemClock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3802709813D5A653009493DD /* SystemClock.cpp */; };
E499143C174E604700741B6D /* Thread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38E1E850D25F9FD00618676 /* Thread.cpp */; };
E499143D174E604700741B6D /* Timer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFD928F116384B6800709DAE /* Timer.cpp */; };
@@ -3319,7 +3331,6 @@
18B7C38F129420E5009E7A26 /* Settings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Settings.h; sourceTree = "<group>"; };
18B7C3A612942132009E7A26 /* AdvancedSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AdvancedSettings.cpp; sourceTree = "<group>"; };
18B7C3A712942132009E7A26 /* AdvancedSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AdvancedSettings.h; sourceTree = "<group>"; };
- 18B7C6F61294222D009E7A26 /* AnimatedGif.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimatedGif.h; sourceTree = "<group>"; };
18B7C6F81294222D009E7A26 /* D3DResource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = D3DResource.h; sourceTree = "<group>"; };
18B7C6F91294222D009E7A26 /* DDSImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDSImage.h; sourceTree = "<group>"; };
18B7C6FA1294222D009E7A26 /* DirectXGraphics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirectXGraphics.h; sourceTree = "<group>"; };
@@ -3407,7 +3418,6 @@
18B7C7511294222E009E7A26 /* VisibleEffect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VisibleEffect.h; sourceTree = "<group>"; };
18B7C7521294222E009E7A26 /* XBTF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XBTF.h; sourceTree = "<group>"; };
18B7C7531294222E009E7A26 /* XBTFReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XBTFReader.h; sourceTree = "<group>"; };
- 18B7C7541294222E009E7A26 /* AnimatedGif.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AnimatedGif.cpp; sourceTree = "<group>"; };
18B7C7561294222E009E7A26 /* D3DResource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = D3DResource.cpp; sourceTree = "<group>"; };
18B7C7571294222E009E7A26 /* DDSImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DDSImage.cpp; sourceTree = "<group>"; };
18B7C7581294222E009E7A26 /* DirectXGraphics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DirectXGraphics.cpp; sourceTree = "<group>"; };
@@ -3657,6 +3667,8 @@
3994427E1A8DD96F006C39E9 /* VideoLibraryQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VideoLibraryQueue.h; sourceTree = "<group>"; };
39B4F36E1B96F845009B2D88 /* RepositoryUpdater.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RepositoryUpdater.cpp; sourceTree = "<group>"; };
39B4F36F1B96F845009B2D88 /* RepositoryUpdater.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RepositoryUpdater.h; sourceTree = "<group>"; };
+ 39BD2AD61B845D40004A5A15 /* DialogHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DialogHelper.h; path = helpers/DialogHelper.h; sourceTree = "<group>"; };
+ 39BD2AD71B845D40004A5A15 /* DialogHelper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DialogHelper.cpp; path = helpers/DialogHelper.cpp; sourceTree = "<group>"; };
4260D5C51B67BB8F003F6F2D /* GUIWindowSplash.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIWindowSplash.cpp; sourceTree = "<group>"; };
4260D5C61B67BB8F003F6F2D /* GUIWindowSplash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIWindowSplash.h; sourceTree = "<group>"; };
42DAC16B1A6E780C0066B4C8 /* IActionListener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IActionListener.h; sourceTree = "<group>"; };
@@ -4242,8 +4254,6 @@
820023D9171A28A300667D1C /* OSXTextInputResponder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSXTextInputResponder.h; sourceTree = "<group>"; };
820023DA171A28A300667D1C /* OSXTextInputResponder.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = OSXTextInputResponder.mm; sourceTree = "<group>"; };
82F6F0EA16F269BB0081CC3C /* Buffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Buffer.h; path = commons/Buffer.h; sourceTree = "<group>"; };
- 83A72B950FBC8E3B00171871 /* LockFree.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LockFree.cpp; sourceTree = "<group>"; };
- 83A72B960FBC8E3B00171871 /* LockFree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LockFree.h; sourceTree = "<group>"; };
83E0B2470F7C95FF0091643F /* Atomics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Atomics.h; sourceTree = "<group>"; };
83E0B2480F7C95FF0091643F /* Atomics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Atomics.cpp; sourceTree = "<group>"; };
880DBE490DC223FF00E26B71 /* Album.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Album.h; sourceTree = "<group>"; };
@@ -4410,6 +4420,14 @@
DF0ABB72183A94A30018445D /* Utf8Utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Utf8Utils.h; sourceTree = "<group>"; };
DF0DF15913A3ADA7008ED511 /* NFSDirectory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NFSDirectory.cpp; sourceTree = "<group>"; };
DF0DF15A13A3ADA7008ED511 /* NFSDirectory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NFSDirectory.h; sourceTree = "<group>"; };
+ DF0E4AC31AD597ED00A75430 /* DVDPlayerRadioRDS.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DVDPlayerRadioRDS.cpp; sourceTree = "<group>"; };
+ DF0E4AC41AD597ED00A75430 /* DVDPlayerRadioRDS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DVDPlayerRadioRDS.h; sourceTree = "<group>"; };
+ DF0E4AC81AD5982500A75430 /* InfoTagRadioRDS.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InfoTagRadioRDS.cpp; sourceTree = "<group>"; };
+ DF0E4AC91AD5982500A75430 /* InfoTagRadioRDS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InfoTagRadioRDS.h; sourceTree = "<group>"; };
+ DF0E4ACD1AD5984600A75430 /* PVRRadioRDSInfoTag.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PVRRadioRDSInfoTag.cpp; sourceTree = "<group>"; };
+ DF0E4ACE1AD5984600A75430 /* PVRRadioRDSInfoTag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PVRRadioRDSInfoTag.h; sourceTree = "<group>"; };
+ DF0E4AD21AD5986F00A75430 /* GUIDialogPVRRadioRDSInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIDialogPVRRadioRDSInfo.cpp; sourceTree = "<group>"; };
+ DF0E4AD31AD5986F00A75430 /* GUIDialogPVRRadioRDSInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIDialogPVRRadioRDSInfo.h; sourceTree = "<group>"; };
DF14CF7C1A77782E00396CC9 /* InputManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InputManager.cpp; sourceTree = "<group>"; };
DF14CF7D1A77782E00396CC9 /* InputManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InputManager.h; sourceTree = "<group>"; };
DF1ACFD115FCE50700E10810 /* AddonModuleXbmc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AddonModuleXbmc.cpp; sourceTree = "<group>"; };
@@ -4496,6 +4514,9 @@
DF2345E015FA639500A934F6 /* UPnPServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UPnPServer.h; sourceTree = "<group>"; };
DF2401241B41A26E001E02DA /* ImageResource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageResource.cpp; sourceTree = "<group>"; };
DF2401251B41A26E001E02DA /* ImageResource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageResource.h; sourceTree = "<group>"; };
+ DF2863B419918B07008994AB /* DllLibGif.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DllLibGif.h; sourceTree = "<group>"; };
+ DF2863B519918B07008994AB /* Gif.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Gif.cpp; sourceTree = "<group>"; };
+ DF2863B619918B07008994AB /* Gif.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Gif.h; sourceTree = "<group>"; };
DF28DF4B17B8379E0077F41A /* ProfilesOperations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProfilesOperations.cpp; sourceTree = "<group>"; };
DF28DF4C17B8379E0077F41A /* ProfilesOperations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProfilesOperations.h; sourceTree = "<group>"; };
DF28ED94170E1A11005FA9D2 /* GUIDialogLockSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIDialogLockSettings.cpp; sourceTree = "<group>"; };
@@ -6042,8 +6063,6 @@
isa = PBXGroup;
children = (
391416BE1B4A3EFA00BBF0AA /* guiinfo */,
- 18B7C7541294222E009E7A26 /* AnimatedGif.cpp */,
- 18B7C6F61294222D009E7A26 /* AnimatedGif.h */,
DF404A3416B9896C00D8023E /* cximage.cpp */,
DF404A3516B9896C00D8023E /* cximage.h */,
18B7C7561294222E009E7A26 /* D3DResource.cpp */,
@@ -6057,9 +6076,12 @@
F558F27A13ABD56600631E12 /* DirtyRegionSolvers.h */,
F558F27D13ABD57400631E12 /* DirtyRegionTracker.cpp */,
F558F27E13ABD57400631E12 /* DirtyRegionTracker.h */,
+ DF2863B419918B07008994AB /* DllLibGif.h */,
18B7C7591294222E009E7A26 /* FrameBufferObject.cpp */,
18B7C6FB1294222D009E7A26 /* FrameBufferObject.h */,
18B7C6FC1294222D009E7A26 /* Geometry.h */,
+ DF2863B519918B07008994AB /* Gif.cpp */,
+ DF2863B619918B07008994AB /* Gif.h */,
18B7C75A1294222E009E7A26 /* GraphicContext.cpp */,
18B7C6FD1294222D009E7A26 /* GraphicContext.h */,
18B7C6FE1294222D009E7A26 /* gui3d.h */,
@@ -6456,6 +6478,15 @@
path = jobs;
sourceTree = "<group>";
};
+ 39BD2AD51B845D1E004A5A15 /* helpers */ = {
+ isa = PBXGroup;
+ children = (
+ 39BD2AD71B845D40004A5A15 /* DialogHelper.cpp */,
+ 39BD2AD61B845D40004A5A15 /* DialogHelper.h */,
+ );
+ name = helpers;
+ sourceTree = "<group>";
+ };
430C880812D649B10098821A /* powermanagement */ = {
isa = PBXGroup;
children = (
@@ -6811,8 +6842,6 @@
E38E1E360D25F9FD00618676 /* Event.h */,
38F4E55E13CCCB3B00664821 /* Helpers.h */,
38F4E55F13CCCB3B00664821 /* Lockables.h */,
- 83A72B950FBC8E3B00171871 /* LockFree.cpp */,
- 83A72B960FBC8E3B00171871 /* LockFree.h */,
E38E1E7A0D25F9FD00618676 /* SharedSection.h */,
E38E1E7C0D25F9FD00618676 /* SingleLock.h */,
3802709813D5A653009493DD /* SystemClock.cpp */,
@@ -7671,6 +7700,8 @@
C8482881156CFCD8005A996F /* PVRChannelGroups.h */,
C8482882156CFCD8005A996F /* PVRChannelGroupsContainer.cpp */,
C8482883156CFCD8005A996F /* PVRChannelGroupsContainer.h */,
+ DF0E4ACD1AD5984600A75430 /* PVRRadioRDSInfoTag.cpp */,
+ DF0E4ACE1AD5984600A75430 /* PVRRadioRDSInfoTag.h */,
);
path = channels;
sourceTree = "<group>";
@@ -7690,6 +7721,8 @@
C8482892156CFCD8005A996F /* GUIDialogPVRGuideOSD.h */,
C8482893156CFCD8005A996F /* GUIDialogPVRGuideSearch.cpp */,
C8482894156CFCD8005A996F /* GUIDialogPVRGuideSearch.h */,
+ DF0E4AD21AD5986F00A75430 /* GUIDialogPVRRadioRDSInfo.cpp */,
+ DF0E4AD31AD5986F00A75430 /* GUIDialogPVRRadioRDSInfo.h */,
C8482895156CFCD8005A996F /* GUIDialogPVRRecordingInfo.cpp */,
C8482896156CFCD8005A996F /* GUIDialogPVRRecordingInfo.h */,
C8482897156CFCD8005A996F /* GUIDialogPVRTimerSettings.cpp */,
@@ -7829,6 +7862,8 @@
DF1AD1A215FCE77900E10810 /* File.h */,
DF1AD1A515FCE77900E10810 /* InfoTagMusic.cpp */,
DF1AD1A615FCE77900E10810 /* InfoTagMusic.h */,
+ DF0E4AC81AD5982500A75430 /* InfoTagRadioRDS.cpp */,
+ DF0E4AC91AD5982500A75430 /* InfoTagRadioRDS.h */,
DF1AD1A915FCE77900E10810 /* InfoTagVideo.cpp */,
DF1AD1AA15FCE77900E10810 /* InfoTagVideo.h */,
DF1AD1AD15FCE77900E10810 /* Keyboard.cpp */,
@@ -7971,6 +8006,7 @@
DF4A3BAC1B4B0FC100F9CDC0 /* messaging */ = {
isa = PBXGroup;
children = (
+ 39BD2AD51B845D1E004A5A15 /* helpers */,
DF4A3BAD1B4B0FC100F9CDC0 /* ApplicationMessenger.cpp */,
DF4A3BAE1B4B0FC100F9CDC0 /* ApplicationMessenger.h */,
DF4A3BAF1B4B0FC100F9CDC0 /* IMessageTarget.h */,
@@ -8569,6 +8605,8 @@
E38E15850D25F9FA00618676 /* DVDPlayer.h */,
E38E15860D25F9FA00618676 /* DVDPlayerAudio.cpp */,
E38E15870D25F9FA00618676 /* DVDPlayerAudio.h */,
+ DF0E4AC31AD597ED00A75430 /* DVDPlayerRadioRDS.cpp */,
+ DF0E4AC41AD597ED00A75430 /* DVDPlayerRadioRDS.h */,
E38E15880D25F9FA00618676 /* DVDPlayerSubtitle.cpp */,
E38E15890D25F9FA00618676 /* DVDPlayerSubtitle.h */,
F5E55B5B10741272006E788A /* DVDPlayerTeletext.cpp */,
@@ -10512,6 +10550,7 @@
E38E22430D25F9FE00618676 /* filestr.cpp in Sources */,
E38E22440D25F9FE00618676 /* find.cpp in Sources */,
E38E22450D25F9FE00618676 /* getbits.cpp in Sources */,
+ DF0E4ACA1AD5982500A75430 /* InfoTagRadioRDS.cpp in Sources */,
E38E22460D25F9FE00618676 /* global.cpp in Sources */,
E38E22470D25F9FE00618676 /* int64.cpp in Sources */,
E38E22480D25F9FE00618676 /* isnt.cpp in Sources */,
@@ -10670,7 +10709,6 @@
F5AACA680FB3DE2D00DBB77C /* GUIDialogSelect.cpp in Sources */,
F5AACA970FB3E2B800DBB77C /* GUIDialogSlider.cpp in Sources */,
F59876C00FBA351D008EF4FB /* VideoReferenceClock.cpp in Sources */,
- 83A72B970FBC8E3B00171871 /* LockFree.cpp in Sources */,
F5987F050FBDF274008EF4FB /* DPMSSupport.cpp in Sources */,
F5987FDB0FBE2DFD008EF4FB /* PAPlayer.cpp in Sources */,
F548786D0FE060FF00E506FD /* DVDSubtitleParserMPL2.cpp in Sources */,
@@ -10720,6 +10758,7 @@
F592568810FBF2E100D2C91D /* ConvolutionKernels.cpp in Sources */,
F5DC87E2110A287400EE1B15 /* RingBuffer.cpp in Sources */,
F5F244651110DC6B009126C6 /* FileOperationJob.cpp in Sources */,
+ DF0E4AC51AD597ED00A75430 /* DVDPlayerRadioRDS.cpp in Sources */,
F5F245EE1112C9AB009126C6 /* FileUtils.cpp in Sources */,
F5A7A702112893E50059D6AA /* AnnouncementManager.cpp in Sources */,
F5A7A85B112908F00059D6AA /* WebServer.cpp in Sources */,
@@ -10750,10 +10789,10 @@
18B7C3841294203F009E7A26 /* AddonDatabase.cpp in Sources */,
18B7C38A12942090009E7A26 /* GUIDialogAddonInfo.cpp in Sources */,
18B7C38B12942090009E7A26 /* GUIViewStateAddonBrowser.cpp in Sources */,
+ 39BD2AD81B845D40004A5A15 /* DialogHelper.cpp in Sources */,
18B7C392129420E5009E7A26 /* Settings.cpp in Sources */,
18B7C3A812942132009E7A26 /* AdvancedSettings.cpp in Sources */,
395C29DB1A98A11C00EBC7AD /* WsgiResponse.cpp in Sources */,
- 18B7C7A91294222E009E7A26 /* AnimatedGif.cpp in Sources */,
18B7C7AB1294222E009E7A26 /* D3DResource.cpp in Sources */,
18B7C7AC1294222E009E7A26 /* DDSImage.cpp in Sources */,
18B7C7AD1294222E009E7A26 /* DirectXGraphics.cpp in Sources */,
@@ -10912,6 +10951,7 @@
DF34892A13FD9C780026A711 /* AirPlayServer.cpp in Sources */,
DF34898213FDAAF60026A711 /* HttpParser.cpp in Sources */,
18968DC814155D7C005BA742 /* ApplicationOperations.cpp in Sources */,
+ DF0E4AD41AD5986F00A75430 /* GUIDialogPVRRadioRDSInfo.cpp in Sources */,
32C631281423A90F00F18420 /* JpegIO.cpp in Sources */,
DF448457140048A60069344B /* AirTunesServer.cpp in Sources */,
DF44845E140048C80069344B /* PipesManager.cpp in Sources */,
@@ -11273,6 +11313,7 @@
7CCDA238192753E30074CF51 /* PltMediaItem.cpp in Sources */,
7CCDA241192753E30074CF51 /* PltMediaServer.cpp in Sources */,
7CCDA24A192753E30074CF51 /* PltSyncMediaBrowser.cpp in Sources */,
+ DF0E4ACF1AD5984600A75430 /* PVRRadioRDSInfoTag.cpp in Sources */,
7CCDA779192756250074CF51 /* Neptune.cpp in Sources */,
7CCDA782192756250074CF51 /* NptAutomaticCleaner.cpp in Sources */,
7CCDA785192756250074CF51 /* NptBase64.cpp in Sources */,
@@ -11338,6 +11379,7 @@
7CF34D9F1930264A00D543C5 /* AudioEncoder.cpp in Sources */,
7C973CFA1B5038580002A874 /* GUIDialogAudioDSPManager.cpp in Sources */,
7CF80DC919710DC2003B2B34 /* KeyboardLayout.cpp in Sources */,
+ DF2863B719918B07008994AB /* Gif.cpp in Sources */,
B179BD6B1AD8EA7B00EA8D49 /* InputCodingTableBaiduPY.cpp in Sources */,
B179BD6E1AD8EA7B00EA8D49 /* InputCodingTableBasePY.cpp in Sources */,
B179BD711AD8EA7B00EA8D49 /* InputCodingTableFactory.cpp in Sources */,
@@ -11520,6 +11562,7 @@
B5011E4319AF3B56005ADF89 /* PosixFile.cpp in Sources */,
DFF0F19E17528350002DA3A4 /* Edl.cpp in Sources */,
DFF0F19F17528350002DA3A4 /* ExternalPlayer.cpp in Sources */,
+ 39BD2ADA1B845D40004A5A15 /* DialogHelper.cpp in Sources */,
DFF0F1A217528350002DA3A4 /* AudioDecoder.cpp in Sources */,
DFF0F1A317528350002DA3A4 /* CodecFactory.cpp in Sources */,
DFF0F1A417528350002DA3A4 /* DVDPlayerCodec.cpp in Sources */,
@@ -11695,11 +11738,11 @@
DFEA4B511B5271EB00562321 /* ActiveAEDSP.cpp in Sources */,
DFF0F26917528350002DA3A4 /* VirtualDirectory.cpp in Sources */,
395C29C31A98A0A000EBC7AD /* Webinterface.cpp in Sources */,
+ DF0E4AD11AD5984600A75430 /* PVRRadioRDSInfoTag.cpp in Sources */,
DFF0F26D17528350002DA3A4 /* ZeroconfDirectory.cpp in Sources */,
DFF0F26E17528350002DA3A4 /* ZipDirectory.cpp in Sources */,
DFF0F26F17528350002DA3A4 /* ZipFile.cpp in Sources */,
DFF0F27017528350002DA3A4 /* ZipManager.cpp in Sources */,
- DFF0F27117528350002DA3A4 /* AnimatedGif.cpp in Sources */,
DFF0F27217528350002DA3A4 /* cximage.cpp in Sources */,
DFF0F27317528350002DA3A4 /* D3DResource.cpp in Sources */,
DFEA4B591B5271FA00562321 /* ActiveAEDSPProcess.cpp in Sources */,
@@ -11784,6 +11827,7 @@
DFF0F2BA17528350002DA3A4 /* JpegIO.cpp in Sources */,
4260D5C91B67BB8F003F6F2D /* GUIWindowSplash.cpp in Sources */,
DFF0F2BC17528350002DA3A4 /* LocalizeStrings.cpp in Sources */,
+ DF0E4AC71AD597ED00A75430 /* DVDPlayerRadioRDS.cpp in Sources */,
DFF0F2BD17528350002DA3A4 /* MatrixGLES.cpp in Sources */,
DFF0F2BE17528350002DA3A4 /* Shader.cpp in Sources */,
DFF0F2BF17528350002DA3A4 /* Texture.cpp in Sources */,
@@ -12031,10 +12075,10 @@
DFF0F3B417528350002DA3A4 /* Atomics.cpp in Sources */,
DFF0F3B517528350002DA3A4 /* Event.cpp in Sources */,
DF29BCFC1B5D911800904347 /* GUIViewStateEventLog.cpp in Sources */,
- DFF0F3B617528350002DA3A4 /* LockFree.cpp in Sources */,
DFF0F3B717528350002DA3A4 /* SystemClock.cpp in Sources */,
DFF0F3B817528350002DA3A4 /* Thread.cpp in Sources */,
DFF0F3B917528350002DA3A4 /* Timer.cpp in Sources */,
+ DF0E4AD61AD5986F00A75430 /* GUIDialogPVRRadioRDSInfo.cpp in Sources */,
DFF0F3BA17528350002DA3A4 /* AlarmClock.cpp in Sources */,
DFF0F3BB17528350002DA3A4 /* AliasShortcutUtils.cpp in Sources */,
DFF0F3BC17528350002DA3A4 /* Archive.cpp in Sources */,
@@ -12154,6 +12198,7 @@
DFF0F43617528350002DA3A4 /* BackgroundInfoLoader.cpp in Sources */,
DFF0F43717528350002DA3A4 /* CueDocument.cpp in Sources */,
DFF0F43817528350002DA3A4 /* DatabaseManager.cpp in Sources */,
+ DF0E4ACC1AD5982500A75430 /* InfoTagRadioRDS.cpp in Sources */,
DFF0F43917528350002DA3A4 /* DbUrl.cpp in Sources */,
DFF0F43A17528350002DA3A4 /* DynamicDll.cpp in Sources */,
DFF0F43C17528350002DA3A4 /* FileItem.cpp in Sources */,
@@ -12394,6 +12439,7 @@
7CF34DA11930264A00D543C5 /* AudioEncoder.cpp in Sources */,
DF6F52B01AF6D03F001BC57D /* dacp.cpp in Sources */,
7CF80DCB19710DC2003B2B34 /* KeyboardLayout.cpp in Sources */,
+ DF2863B919918B07008994AB /* Gif.cpp in Sources */,
B179BD6D1AD8EA7B00EA8D49 /* InputCodingTableBaiduPY.cpp in Sources */,
B179BD701AD8EA7B00EA8D49 /* InputCodingTableBasePY.cpp in Sources */,
B179BD731AD8EA7B00EA8D49 /* InputCodingTableFactory.cpp in Sources */,
@@ -12726,6 +12772,7 @@
E49912AC174E5D9900741B6D /* SFTPDirectory.cpp in Sources */,
E49912AD174E5D9900741B6D /* SFTPFile.cpp in Sources */,
E49912AE174E5D9900741B6D /* ShoutcastFile.cpp in Sources */,
+ DF0E4AD51AD5986F00A75430 /* GUIDialogPVRRadioRDSInfo.cpp in Sources */,
395C29C21A98A0A000EBC7AD /* Webinterface.cpp in Sources */,
E49912B2174E5D9900741B6D /* SmartPlaylistDirectory.cpp in Sources */,
E49912B3174E5D9900741B6D /* SMBDirectory.cpp in Sources */,
@@ -12768,7 +12815,6 @@
E49912D7174E5DA000741B6D /* ZipDirectory.cpp in Sources */,
E49912D8174E5DA000741B6D /* ZipFile.cpp in Sources */,
E49912D9174E5DA000741B6D /* ZipManager.cpp in Sources */,
- E49912DA174E5DAD00741B6D /* AnimatedGif.cpp in Sources */,
E49912DB174E5DAD00741B6D /* cximage.cpp in Sources */,
E49912DC174E5DAD00741B6D /* D3DResource.cpp in Sources */,
E49912DD174E5DAD00741B6D /* DDSImage.cpp in Sources */,
@@ -12975,6 +13021,7 @@
E49913B6174E5F3C00741B6D /* AirPlayServer.cpp in Sources */,
E49913B7174E5F3C00741B6D /* AirTunesServer.cpp in Sources */,
E49913B8174E5F3C00741B6D /* cddb.cpp in Sources */,
+ 39BD2AD91B845D40004A5A15 /* DialogHelper.cpp in Sources */,
E49913B9174E5F3C00741B6D /* DNSNameCache.cpp in Sources */,
E49913BA174E5F3C00741B6D /* EventClient.cpp in Sources */,
E49913BB174E5F3C00741B6D /* EventPacket.cpp in Sources */,
@@ -13054,6 +13101,7 @@
E4991405174E5FB900741B6D /* PVRTimerInfoTag.cpp in Sources */,
E4991406174E5FB900741B6D /* PVRTimers.cpp in Sources */,
E4991407174E5FB900741B6D /* GUIViewStatePVR.cpp in Sources */,
+ DF0E4AD01AD5984600A75430 /* PVRRadioRDSInfoTag.cpp in Sources */,
E4991408174E5FB900741B6D /* GUIWindowPVRBase.cpp in Sources */,
E4991409174E5FB900741B6D /* GUIWindowPVRChannels.cpp in Sources */,
E499140B174E5FB900741B6D /* GUIWindowPVRGuide.cpp in Sources */,
@@ -13092,7 +13140,6 @@
E4991437174E604700741B6D /* Implementation.cpp in Sources */,
E4991438174E604700741B6D /* Atomics.cpp in Sources */,
E4991439174E604700741B6D /* Event.cpp in Sources */,
- E499143A174E604700741B6D /* LockFree.cpp in Sources */,
E499143B174E604700741B6D /* SystemClock.cpp in Sources */,
E499143C174E604700741B6D /* Thread.cpp in Sources */,
E499143D174E604700741B6D /* Timer.cpp in Sources */,
@@ -13187,6 +13234,7 @@
E4991496174E606600741B6D /* VideoDbUrl.cpp in Sources */,
E4991497174E606600741B6D /* VideoInfoDownloader.cpp in Sources */,
E4991498174E606600741B6D /* VideoInfoScanner.cpp in Sources */,
+ DF0E4AC61AD597ED00A75430 /* DVDPlayerRadioRDS.cpp in Sources */,
E4991499174E606600741B6D /* VideoInfoTag.cpp in Sources */,
E499149A174E606600741B6D /* VideoReferenceClock.cpp in Sources */,
E499149B174E606600741B6D /* VideoThumbLoader.cpp in Sources */,
@@ -13345,6 +13393,7 @@
7CC7B6B41918699000DDB120 /* GUIDialogSettingsBase.cpp in Sources */,
7CC7B6B71918699000DDB120 /* GUIDialogSettingsManagerBase.cpp in Sources */,
7CC7B6BA1918699000DDB120 /* GUIDialogSettingsManualBase.cpp in Sources */,
+ DF0E4ACB1AD5982500A75430 /* InfoTagRadioRDS.cpp in Sources */,
7CC7B6C1191869EA00DDB120 /* SettingCreator.cpp in Sources */,
7CC7B6C4191869EA00DDB120 /* SettingUtils.cpp in Sources */,
7CC7B6C919186A8800DDB120 /* SettingConditions.cpp in Sources */,
@@ -13452,6 +13501,7 @@
7CF34DA01930264A00D543C5 /* AudioEncoder.cpp in Sources */,
395C29F71A98B44B00EBC7AD /* AddonModuleXbmcwsgi.cpp in Sources */,
7CF80DCA19710DC2003B2B34 /* KeyboardLayout.cpp in Sources */,
+ DF2863B819918B07008994AB /* Gif.cpp in Sources */,
B179BD6C1AD8EA7B00EA8D49 /* InputCodingTableBaiduPY.cpp in Sources */,
B179BD6F1AD8EA7B00EA8D49 /* InputCodingTableBasePY.cpp in Sources */,
B179BD721AD8EA7B00EA8D49 /* InputCodingTableFactory.cpp in Sources */,
diff --git a/Makefile.in b/Makefile.in
index f855dd27d8..e0d355cbb7 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -60,6 +60,7 @@ DIRECTORY_ARCHIVES=$(DVDPLAYER_ARCHIVES) \
xbmc/main/posix/MessagePrinter.a \
xbmc/media/media.a \
xbmc/messaging/messaging.a \
+ xbmc/messaging/helpers/messagingHelpers.a \
xbmc/music/dialogs/musicdialogs.a \
xbmc/music/infoscanner/musicscanner.a \
xbmc/music/karaoke/karaoke.a \
diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po
index 88d3637464..9e237ea883 100644
--- a/addons/resource.language.en_gb/resources/strings.po
+++ b/addons/resource.language.en_gb/resources/strings.po
@@ -14018,7 +14018,491 @@ msgctxt "#29802"
msgid "Passthrough audio in use"
msgstr ""
-#empty strings from id 29803 to 33000
+#empty strings from id 29803 to 29899
+
+#. Header string on RDS Radiotext+ Info dialog
+#: addons/skin.confluence/720p/DialogPVRRadioRDSInfo.xml
+msgctxt "#29900"
+msgid "RadiotextPlus info"
+msgstr ""
+
+#. Music band name which make the song (if present)
+#: addons/skin.confluence/720p/DialogPVRRadioRDSInfo.xml
+msgctxt "#29901"
+msgid "Band"
+msgstr ""
+
+#. Style of the current playing radio
+#: addons/skin.confluence/720p/DialogPVRRadioRDSInfo.xml
+msgctxt "#29902"
+msgid "Style"
+msgstr ""
+
+#. Concert composer of the music (if present)
+#: addons/skin.confluence/720p/DialogPVRRadioRDSInfo.xml
+msgctxt "#29903"
+msgid "Composer"
+msgstr ""
+
+#. Artits which sing the music (if present)
+#: addons/skin.confluence/720p/DialogPVRRadioRDSInfo.xml
+msgctxt "#29904"
+msgid "Artist"
+msgstr ""
+
+#. Conductor of the classic music (if present)
+#: addons/skin.confluence/720p/DialogPVRRadioRDSInfo.xml
+msgctxt "#29905"
+msgid "Conductor"
+msgstr ""
+
+#. Moderator currently on radio (if present)
+#: addons/skin.confluence/720p/DialogPVRRadioRDSInfo.xml
+msgctxt "#29906"
+msgid "Moderator"
+msgstr ""
+
+#. List of editoral staff (if present)
+#: addons/skin.confluence/720p/DialogPVRRadioRDSInfo.xml
+msgctxt "#29907"
+msgid "Editorial Staff"
+msgstr ""
+
+#. Current playing program name
+#: addons/skin.confluence/720p/DialogPVRRadioRDSInfo.xml
+msgctxt "#29908"
+msgid "Program"
+msgstr ""
+
+#. Studio name (if present)
+#: addons/skin.confluence/720p/DialogPVRRadioRDSInfo.xml
+msgctxt "#29909"
+msgid "Studio"
+msgstr ""
+
+#. Phone number (if present)
+#: addons/skin.confluence/720p/DialogPVRRadioRDSInfo.xml
+msgctxt "#29910"
+msgid "Phone"
+msgstr ""
+
+#. EMail address (if present)
+#: addons/skin.confluence/720p/DialogPVRRadioRDSInfo.xml
+msgctxt "#29911"
+msgid "EMail"
+msgstr ""
+
+#. SMS message number (if present)
+#: addons/skin.confluence/720p/DialogPVRRadioRDSInfo.xml
+msgctxt "#29912"
+msgid "SMS"
+msgstr ""
+
+#. Hotline phone (if present)
+#: addons/skin.confluence/720p/DialogPVRRadioRDSInfo.xml
+msgctxt "#29913"
+msgid "Hotline"
+msgstr ""
+
+#. Website address (if present)
+#: addons/skin.confluence/720p/DialogPVRRadioRDSInfo.xml
+msgctxt "#29914"
+msgid "Website"
+msgstr ""
+
+#. General information news, in list selector (if present)
+#: addons/skin.confluence/720p/DialogPVRRadioRDSInfo.xml
+msgctxt "#29915"
+msgid "Info"
+msgstr ""
+
+#. News, in list selector (if present)
+#: xbmc/pvr/dialogs/GUIDialogPVRRadioRDSInfo.cpp
+msgctxt "#29916"
+msgid "News"
+msgstr ""
+
+#. Local news, in list selector (if present)
+#: xbmc/pvr/dialogs/GUIDialogPVRRadioRDSInfo.cpp
+msgctxt "#29917"
+msgid "News local"
+msgstr ""
+
+#. Sport news, in list selector (if present)
+#: xbmc/pvr/dialogs/GUIDialogPVRRadioRDSInfo.cpp
+msgctxt "#29918"
+msgid "Sport"
+msgstr ""
+
+#. Lottery information, in list selector (if present)
+#: xbmc/pvr/dialogs/GUIDialogPVRRadioRDSInfo.cpp
+msgctxt "#29919"
+msgid "Lottery"
+msgstr ""
+
+# Stock information, in list selector (if present)
+#: xbmc/pvr/dialogs/GUIDialogPVRRadioRDSInfo.cpp
+msgctxt "#29920"
+msgid "Stock"
+msgstr ""
+
+#. Other informations, in list selector (if present)
+#: xbmc/pvr/dialogs/GUIDialogPVRRadioRDSInfo.cpp
+msgctxt "#29921"
+msgid "Other"
+msgstr ""
+
+#. Horoscope messages, in list selector (if present)
+#: xbmc/pvr/dialogs/GUIDialogPVRRadioRDSInfo.cpp
+msgctxt "#29922"
+msgid "Horoscope"
+msgstr ""
+
+#empty strings from id 29923 to 29925
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29926"
+msgid "Adult hits"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29927"
+msgid "Spanish talk"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29928"
+msgid "Spanish music"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29929"
+msgid "Hip hop"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29930"
+msgid "Radio Traffic advisory message!"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29931"
+msgid "Radio message"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29932"
+msgid "Language"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29933"
+msgid "College"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29934"
+msgid "Personality"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29935"
+msgid "Public"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29936"
+msgid "Soft music"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29937"
+msgid "Adult hits"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29938"
+msgid "Soft rock"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29939"
+msgid "Talk"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29940"
+msgid "No programme type"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29941"
+msgid "News"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29942"
+msgid "Current affairs"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29943"
+msgid "Information"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29944"
+msgid "Sport"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29945"
+msgid "Education"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29946"
+msgid "Drama"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29947"
+msgid "Culture"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29948"
+msgid "Science"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29949"
+msgid "Varied"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29950"
+msgid "Pop music"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29951"
+msgid "Rock music"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29952"
+msgid "Easy listening music"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29953"
+msgid "Light classical"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29954"
+msgid "Serious classical"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29955"
+msgid "Other music"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29956"
+msgid "Weather"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29957"
+msgid "Finance"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29958"
+msgid "Children's Programmes"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29959"
+msgid "Social Affairs"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29960"
+msgid "Religion"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29961"
+msgid "Phone-in"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29962"
+msgid "Travel"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29963"
+msgid "Leisure"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29964"
+msgid "Jazz Music"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29965"
+msgid "Country Music"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29966"
+msgid "National Music"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29967"
+msgid "Oldies Music"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29968"
+msgid "Folk Music"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29969"
+msgid "Documentary"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29960"
+msgid "Alarm Test"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29971"
+msgid "Alarm"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29977"
+msgid "Classic rock music"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29978"
+msgid "Classical"
+msgstr ""
+
+#. Program style name
+#: xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
+msgctxt "#29979"
+msgid "Nostalgia"
+msgstr ""
+
+#. Settings boolean value to enable/disable RDS
+#: system/settings/settings.xml
+msgctxt "#29980"
+msgid "Enable RDS for radio channels"
+msgstr ""
+
+#. Help text for RDS enable/disable
+#: system/settings/settings.xml
+msgctxt "#29981"
+msgid "RDS data can be used if present"
+msgstr ""
+
+#. Boolean value to enable traffic advisory from RDS
+#: system/settings/settings.xml
+msgctxt "#29982"
+msgid "Message traffic advisory"
+msgstr ""
+
+#. Help text of boolean on/off value
+#: system/settings/settings.xml
+msgctxt "#29983"
+msgid "RDS inform you about traffic advisory messages"
+msgstr ""
+
+#. Boolean value on settings
+#: system/settings/settings.xml
+msgctxt "#29984"
+msgid "Increase volume on traffic advisory"
+msgstr ""
+
+#. Help text of boolean on/off value
+#: system/settings/settings.xml
+msgctxt "#29985"
+msgid "If traffic advisory is send from RDS, volume is increased"
+msgstr ""
+
+#. Boolean value on settings
+#: system/settings/settings.xml
+msgctxt "#29986"
+msgid "Publicate traffic messages"
+msgstr ""
+
+#. Help text of boolean on/off value
+#: system/settings/settings.xml
+msgctxt "#29987"
+msgid "Send present traffic messages around and can be handled from addons (nothing inisde KODI)"
+msgstr ""
+
+#empty strings from id 29888 to 33000
#strings 30000 thru 30999 reserved for plug-ins and plug-in settings
#strings 31000 thru 31999 reserved for skins
#strings 32000 thru 32999 reserved for scripts
diff --git a/addons/skin.confluence/720p/DialogPVRRadioRDSInfo.xml b/addons/skin.confluence/720p/DialogPVRRadioRDSInfo.xml
new file mode 100644
index 0000000000..a7b936aa55
--- /dev/null
+++ b/addons/skin.confluence/720p/DialogPVRRadioRDSInfo.xml
@@ -0,0 +1,949 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<window>
+ <defaultcontrol always="true">10</defaultcontrol>
+ <coordinates>
+ <left>200</left>
+ <top>20</top>
+ </coordinates>
+ <include>dialogeffect</include>
+ <controls>
+ <control type="image">
+ <description>background image</description>
+ <left>0</left>
+ <top>0</top>
+ <width>880</width>
+ <height>680</height>
+ <texture border="40">DialogBack2.png</texture>
+ <visible>Window.IsVisible(FullscreenVideo) | Window.IsVisible(Visualisation)</visible>
+ </control>
+ <control type="image">
+ <description>background image</description>
+ <left>0</left>
+ <top>0</top>
+ <width>880</width>
+ <height>680</height>
+ <texture border="40">DialogBack.png</texture>
+ <visible>![Window.IsVisible(FullscreenVideo) | Window.IsVisible(Visualisation)]</visible>
+ </control>
+ <control type="image">
+ <description>Dialog Header image</description>
+ <left>40</left>
+ <top>16</top>
+ <width>880</width>
+ <height>40</height>
+ <texture>dialogheader.png</texture>
+ </control>
+ <control type="label">
+ <description>header label</description>
+ <left>40</left>
+ <top>20</top>
+ <width>800</width>
+ <height>30</height>
+ <font>font13_title</font>
+ <label>$LOCALIZE[29900]</label>
+ <align>center</align>
+ <aligny>center</aligny>
+ <textcolor>selected</textcolor>
+ <shadowcolor>black</shadowcolor>
+ </control>
+ <control type="button">
+ <description>Close Window button</description>
+ <left>800</left>
+ <top>15</top>
+ <width>64</width>
+ <height>32</height>
+ <label>-</label>
+ <font>-</font>
+ <onclick>PreviousMenu</onclick>
+ <texturefocus>DialogCloseButton-focus.png</texturefocus>
+ <texturenofocus>DialogCloseButton.png</texturenofocus>
+ <onleft>10</onleft>
+ <onright>10</onright>
+ <onup>10</onup>
+ <ondown>10</ondown>
+ <visible>system.getbool(input.enablemouse)</visible>
+ </control>
+ <control type="group">
+ <description>Normal song info group</description>
+ <left>0</left>
+ <top>70</top>
+ <visible>IsEmpty(RDS.IsClassical)</visible>
+ <control type="label">
+ <description>Artist Title</description>
+ <left>10</left>
+ <top>0</top>
+ <width>140</width>
+ <height>25</height>
+ <align>right</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>blue</textcolor>
+ <label>$LOCALIZE[557]:</label>
+ <visible>IsEmpty(RDS.Band)</visible>
+ </control>
+ <control type="fadelabel">
+ <description>Artist Value</description>
+ <left>160</left>
+ <top>0</top>
+ <width>704</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <label fallback="161">$INFO[RDS.Artist]</label>
+ <scrollout>false</scrollout>
+ <pauseatend>2000</pauseatend>
+ <visible>IsEmpty(RDS.Band)</visible>
+ </control>
+ <control type="label">
+ <description>Band Title</description>
+ <left>10</left>
+ <top>0</top>
+ <width>140</width>
+ <height>25</height>
+ <align>right</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>blue</textcolor>
+ <label>$LOCALIZE[29901]:</label>
+ <visible>!IsEmpty(RDS.Band)</visible>
+ </control>
+ <control type="fadelabel">
+ <description>Band Value</description>
+ <left>160</left>
+ <top>0</top>
+ <width>292</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <label>$INFO[RDS.Band]</label>
+ <scrollout>false</scrollout>
+ <pauseatend>2000</pauseatend>
+ <visible>!IsEmpty(RDS.Band)</visible>
+ </control>
+ <control type="label">
+ <description>Artist Name (alt pos)</description>
+ <left>385</left>
+ <top>0</top>
+ <width>140</width>
+ <height>25</height>
+ <align>right</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>blue</textcolor>
+ <label>$LOCALIZE[557]:</label>
+ <visible>!IsEmpty(RDS.Artist)+!IsEmpty(RDS.Band)</visible>
+ </control>
+ <control type="fadelabel">
+ <description>Artist Value (alt pos)</description>
+ <left>535</left>
+ <top>0</top>
+ <width>328</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <label>$INFO[RDS.Artist]</label>
+ <visible>!IsEmpty(RDS.Artist)+!IsEmpty(RDS.Band)</visible>
+ </control>
+ <control type="label">
+ <description>Song Title</description>
+ <left>10</left>
+ <top>35</top>
+ <width>140</width>
+ <height>25</height>
+ <align>right</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>blue</textcolor>
+ <label>$LOCALIZE[556]:</label>
+ </control>
+ <control type="fadelabel">
+ <description>Song Value</description>
+ <left>160</left>
+ <top>35</top>
+ <width>704</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <label fallback="161">$INFO[RDS.Title]</label>
+ <scrollout>false</scrollout>
+ <pauseatend>2000</pauseatend>
+ </control>
+ <control type="label">
+ <description>Programme style Name</description>
+ <left>10</left>
+ <top>70</top>
+ <width>140</width>
+ <height>25</height>
+ <align>right</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>blue</textcolor>
+ <label>$LOCALIZE[29902]:</label>
+ <visible>!IsEmpty(RDS.ProgStyle)</visible>
+ </control>
+ <control type="fadelabel">
+ <description>Programme style Value</description>
+ <left>160</left>
+ <top>70</top>
+ <width>704</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <label>$INFO[RDS.ProgStyle]</label>
+ <visible>!IsEmpty(RDS.ProgStyle)</visible>
+ </control>
+ </control>
+ <control type="group">
+ <description>Classic concert music group</description>
+ <left>0</left>
+ <top>70</top>
+ <visible>!IsEmpty(RDS.IsClassical)</visible>
+ <control type="label">
+ <description>Composer Title</description>
+ <left>10</left>
+ <top>0</top>
+ <width>140</width>
+ <height>25</height>
+ <align>right</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>blue</textcolor>
+ <label>$LOCALIZE[29903]:</label>
+ </control>
+ <control type="fadelabel">
+ <description>Composer Value</description>
+ <left>160</left>
+ <top>0</top>
+ <width>704</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <label fallback="161">$INFO[RDS.Composer]</label>
+ <scrollout>false</scrollout>
+ <pauseatend>2000</pauseatend>
+ </control>
+ <control type="label">
+ <description>Song Title</description>
+ <left>10</left>
+ <top>35</top>
+ <width>140</width>
+ <height>25</height>
+ <align>right</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>blue</textcolor>
+ <label>$LOCALIZE[556]:</label>
+ </control>
+ <control type="fadelabel">
+ <description>Song Value</description>
+ <left>160</left>
+ <top>35</top>
+ <width>704</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <label fallback="161">$INFO[RDS.Title]</label>
+ <scrollout>false</scrollout>
+ <pauseatend>2000</pauseatend>
+ </control>
+ <control type="label">
+ <description>Artist Title</description>
+ <left>10</left>
+ <top>70</top>
+ <width>140</width>
+ <height>25</height>
+ <align>right</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>blue</textcolor>
+ <label>$LOCALIZE[29904]:</label>
+ <visible>IsEmpty(RDS.Band)+!IsEmpty(RDS.Artist)</visible>
+ </control>
+ <control type="textbox">
+ <description>Artist Value</description>
+ <left>160</left>
+ <top>66</top>
+ <width>704</width>
+ <height>29</height>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <align>left</align>
+ <pagecontrol>-</pagecontrol>
+ <label fallback="161">$INFO[RDS.Artist]</label>
+ <autoscroll time="2000" delay="3000" repeat="5000">true</autoscroll>
+ <visible>IsEmpty(RDS.Band)+!IsEmpty(RDS.Artist)</visible>
+ </control>
+ <control type="label">
+ <description>Band Title</description>
+ <left>10</left>
+ <top>70</top>
+ <width>140</width>
+ <height>25</height>
+ <align>right</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>blue</textcolor>
+ <label>$LOCALIZE[29901]:</label>
+ <visible>!IsEmpty(RDS.Band)</visible>
+ </control>
+ <control type="fadelabel">
+ <description>Band Value</description>
+ <left>160</left>
+ <top>70</top>
+ <width>292</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <label>$INFO[RDS.Band]</label>
+ <scrollout>false</scrollout>
+ <pauseatend>2000</pauseatend>
+ <visible>!IsEmpty(RDS.Band)</visible>
+ </control>
+ <control type="label">
+ <description>Artist Name (alt pos)</description>
+ <left>385</left>
+ <top>70</top>
+ <width>140</width>
+ <height>25</height>
+ <align>right</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>blue</textcolor>
+ <label>$LOCALIZE[29904]:</label>
+ <visible>!IsEmpty(RDS.Artist)+!IsEmpty(RDS.Band)</visible>
+ </control>
+ <control type="textbox">
+ <description>Artist Value (alt pos)</description>
+ <left>535</left>
+ <top>70</top>
+ <width>328</width>
+ <height>100</height>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <align>left</align>
+ <pagecontrol>-</pagecontrol>
+ <label>$INFO[RDS.Artist]</label>
+ <autoscroll time="2000" delay="3000" repeat="5000">true</autoscroll>
+ <visible>!IsEmpty(RDS.Artist)+!IsEmpty(RDS.Band)</visible>
+ </control>
+ <control type="label">
+ <description>Conductor Title</description>
+ <left>10</left>
+ <top>105</top>
+ <width>140</width>
+ <height>25</height>
+ <align>right</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>blue</textcolor>
+ <label>$LOCALIZE[29905]:</label>
+ <visible>!IsEmpty(RDS.Conductor)</visible>
+ </control>
+ <control type="fadelabel">
+ <description>Conductor Value</description>
+ <left>160</left>
+ <top>105</top>
+ <width>300</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <label fallback="161">$INFO[RDS.Conductor]</label>
+ <scrollout>false</scrollout>
+ <pauseatend>2000</pauseatend>
+ <visible>!IsEmpty(RDS.Conductor)</visible>
+ </control>
+ <control type="label">
+ <description>Programme style Name</description>
+ <left>10</left>
+ <top>105</top>
+ <width>140</width>
+ <height>25</height>
+ <align>right</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>blue</textcolor>
+ <label>$LOCALIZE[29902]:</label>
+ <visible>IsEmpty(RDS.Conductor)+!IsEmpty(RDS.ProgStyle)</visible>
+ </control>
+ <control type="fadelabel">
+ <description>Programme style Value</description>
+ <left>160</left>
+ <top>105</top>
+ <width>704</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <label>$INFO[RDS.ProgStyle]</label>
+ <visible>IsEmpty(RDS.Conductor)+!IsEmpty(RDS.ProgStyle)</visible>
+ </control>
+ <control type="label">
+ <description>Programme style Name</description>
+ <left>385</left>
+ <top>105</top>
+ <width>140</width>
+ <height>25</height>
+ <align>right</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>blue</textcolor>
+ <label>$LOCALIZE[29902]:</label>
+ <visible>!IsEmpty(RDS.Conductor)+!IsEmpty(RDS.ProgStyle)</visible>
+ </control>
+ <control type="fadelabel">
+ <description>Programme style Value</description>
+ <left>535</left>
+ <top>105</top>
+ <width>328</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <label>INFO[RDS.ProgStyle]</label>
+ <visible>!IsEmpty(RDS.Conductor)+!IsEmpty(RDS.ProgStyle)</visible>
+ </control>
+ </control>
+ <control type="label">
+ <description>Album Title</description>
+ <left>385</left>
+ <top>175</top>
+ <width>140</width>
+ <height>25</height>
+ <align>right</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>blue</textcolor>
+ <label>$LOCALIZE[558]:</label>
+ <visible>!IsEmpty(RDS.Album)</visible>
+ </control>
+ <control type="fadelabel">
+ <description>Album Value</description>
+ <left>535</left>
+ <top>175</top>
+ <width>328</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <label>$INFO[RDS.Album]</label>
+ <scrollout>false</scrollout>
+ <pauseatend>2000</pauseatend>
+ <visible>!IsEmpty(RDS.Album)</visible>
+ </control>
+ <control type="label">
+ <description>Programme host Name</description>
+ <left>10</left>
+ <top>210</top>
+ <width>140</width>
+ <height>25</height>
+ <align>right</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>blue</textcolor>
+ <label>$LOCALIZE[29906]:</label>
+ <visible>!IsEmpty(RDS.ProgHost)</visible>
+ </control>
+ <control type="fadelabel">
+ <description>Programme host Value</description>
+ <left>160</left>
+ <top>210</top>
+ <width>235</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <label>$INFO[RDS.ProgHost]</label>
+ <visible>!IsEmpty(RDS.ProgHost)</visible>
+ </control>
+ <control type="label">
+ <description>Comment Title</description>
+ <left>385</left>
+ <top>210</top>
+ <width>140</width>
+ <height>25</height>
+ <align>right</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>blue</textcolor>
+ <label>$LOCALIZE[569]:</label>
+ <visible>!IsEmpty(RDS.Comment)</visible>
+ </control>
+ <control type="fadelabel">
+ <description>Comment Value</description>
+ <left>535</left>
+ <top>210</top>
+ <width>328</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <label>$INFO[RDS.Comment]</label>
+ <scrollout>false</scrollout>
+ <pauseatend>2000</pauseatend>
+ <visible>!IsEmpty(RDS.Comment)</visible>
+ </control>
+ <control type="label">
+ <description>Channel Name</description>
+ <left>10</left>
+ <top>245</top>
+ <width>140</width>
+ <height>25</height>
+ <align>right</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>blue</textcolor>
+ <label>$LOCALIZE[19148]:</label>
+ </control>
+ <control type="fadelabel">
+ <description>Channel Value</description>
+ <left>160</left>
+ <top>245</top>
+ <width>235</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <label>$INFO[RDS.ProgStation]</label>
+ </control>
+ <control type="label">
+ <description>Editorial Staff Name</description>
+ <left>385</left>
+ <top>245</top>
+ <width>140</width>
+ <height>25</height>
+ <align>right</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>blue</textcolor>
+ <label>$LOCALIZE[29907]:</label>
+ <visible>!IsEmpty(RDS.ProgEditStaff)</visible>
+ </control>
+ <control type="fadelabel">
+ <description>Editorial Staff Value</description>
+ <left>535</left>
+ <top>245</top>
+ <width>328</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <label>$INFO[RDS.ProgEditStaff]</label>
+ <visible>!IsEmpty(RDS.ProgEditStaff)</visible>
+ </control>
+
+ <control type="grouplist">
+ <left>10</left>
+ <top>280</top>
+ <width>160</width>
+ <height>300</height>
+ <itemgap>8</itemgap>
+ <control type="label">
+ <description>Program basename</description>
+ <left>10</left>
+ <top>280</top>
+ <width>140</width>
+ <height>25</height>
+ <align>right</align>
+ <aligny>center</aligny>
+ <font>font13caps</font>
+ <textcolor>blue</textcolor>
+ <label>$LOCALIZE[29908]:</label>
+ <visible>!IsEmpty(RDS.ProgNow) | !IsEmpty(RDS.ProgNext)</visible>
+ </control>
+ <control type="label">
+ <description>blind label</description>
+ <left>10</left>
+ <top>280</top>
+ <width>140</width>
+ <height>25</height>
+ <label></label>
+ <visible>!IsEmpty(RDS.ProgNow) + !IsEmpty(RDS.ProgNext)</visible>
+ </control>
+ <control type="label">
+ <description>Studio basename</description>
+ <width>140</width>
+ <height>25</height>
+ <align>right</align>
+ <aligny>center</aligny>
+ <font>font13caps</font>
+ <textcolor>blue</textcolor>
+ <label>$LOCALIZE[29909]:</label>
+ <visible>!IsEmpty(RDS.PhoneStudio) | !IsEmpty(RDS.EmailStudio) | !IsEmpty(RDS.SMSStudio)</visible>
+ </control>
+ </control>
+ <control type="grouplist">
+ <left>160</left>
+ <top>280</top>
+ <width>160</width>
+ <height>300</height>
+ <itemgap>8</itemgap>
+ <control type="label">
+ <description>Program now Name</description>
+ <width>160</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <label>$LOCALIZE[19030]:</label>
+ <visible>!IsEmpty(RDS.ProgNow)</visible>
+ </control>
+ <control type="label">
+ <description>Program next Name</description>
+ <width>160</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <label>$LOCALIZE[19031]:</label>
+ <visible>!IsEmpty(RDS.ProgNext)</visible>
+ </control>
+ <control type="label">
+ <description>Studio phone Name</description>
+ <width>95</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <label>$LOCALIZE[29910]:</label>
+ <visible>!IsEmpty(RDS.PhoneStudio)</visible>
+ </control>
+ <control type="label">
+ <description>Studio email Name</description>
+ <width>95</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <label>$LOCALIZE[29911]:</label>
+ <visible>!IsEmpty(RDS.EmailStudio)</visible>
+ </control>
+ <control type="label">
+ <description>Studio SMS Name</description>
+ <width>95</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <label>$LOCALIZE[29912]:</label>
+ <visible>!IsEmpty(RDS.SMSStudio)</visible>
+ </control>
+ </control>
+ <control type="grouplist">
+ <left>230</left>
+ <top>280</top>
+ <width>620</width>
+ <height>300</height>
+ <itemgap>8</itemgap>
+ <control type="fadelabel">
+ <description>Program now Value</description>
+ <width>620</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>grey</textcolor>
+ <label>$INFO[RDS.ProgNow]</label>
+ <visible>!IsEmpty(RDS.ProgNow)</visible>
+ </control>
+ <control type="fadelabel">
+ <description>Program next Value</description>
+ <width>620</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>grey</textcolor>
+ <label>$INFO[RDS.ProgNext]</label>
+ <visible>!IsEmpty(RDS.ProgNext)</visible>
+ </control>
+ <control type="fadelabel">
+ <description>Studio phone Value</description>
+ <width>215</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>grey</textcolor>
+ <label>$INFO[RDS.PhoneStudio]</label>
+ <visible>!IsEmpty(RDS.PhoneStudio)</visible>
+ </control>
+ <control type="fadelabel">
+ <description>Studio email Value</description>
+ <width>215</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>grey</textcolor>
+ <label>$INFO[RDS.EmailStudio]</label>
+ <visible>!IsEmpty(RDS.EmailStudio)</visible>
+ </control>
+ <control type="fadelabel">
+ <description>Studio SMS Value</description>
+ <width>215</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>grey</textcolor>
+ <label>$INFO[RDS.SMSStudio]</label>
+ <visible>!IsEmpty(RDS.SMSStudio)</visible>
+ </control>
+ </control>
+ <control type="grouplist">
+ <left>385</left>
+ <top>280</top>
+ <width>520</width>
+ <height>300</height>
+ <itemgap>8</itemgap>
+ <control type="label">
+ <description>blind label</description>
+ <width>5</width>
+ <height>25</height>
+ <label></label>
+ <visible>!IsEmpty(RDS.ProgNow)</visible>
+ </control>
+ <control type="label">
+ <description>blind label</description>
+ <width>5</width>
+ <height>25</height>
+ <label></label>
+ <visible>!IsEmpty(RDS.ProgNext)</visible>
+ </control>
+ <control type="label">
+ <description>Hotline basename</description>
+ <width>140</width>
+ <height>25</height>
+ <align>right</align>
+ <aligny>center</aligny>
+ <font>font13caps</font>
+ <textcolor>blue</textcolor>
+ <label>$LOCALIZE[29913]:</label>
+ <visible>!IsEmpty(RDS.PhoneHotline) | !IsEmpty(RDS.EmailHotline)</visible>
+ </control>
+ <control type="label">
+ <description>blind label</description>
+ <width>140</width>
+ <height>25</height>
+ <label></label>
+ <visible>!IsEmpty(RDS.PhoneHotline) + !IsEmpty(RDS.EmailHotline)</visible>
+ </control>
+ <control type="label">
+ <description>Homepage Name</description>
+ <left>385</left>
+ <top>420</top>
+ <width>140</width>
+ <height>25</height>
+ <align>right</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>blue</textcolor>
+ <label>$LOCALIZE[29914]:</label>
+ <visible>!IsEmpty(RDS.ProgHomepage)</visible>
+ </control>
+ </control>
+ <control type="grouplist">
+ <left>535</left>
+ <top>280</top>
+ <width>520</width>
+ <height>300</height>
+ <itemgap>8</itemgap>
+ <control type="label">
+ <description>blind label</description>
+ <width>5</width>
+ <height>25</height>
+ <label></label>
+ <visible>!IsEmpty(RDS.ProgNow)</visible>
+ </control>
+ <control type="label">
+ <description>blind label</description>
+ <width>5</width>
+ <height>25</height>
+ <label></label>
+ <visible>!IsEmpty(RDS.ProgNext)</visible>
+ </control>
+ <control type="label">
+ <description>Hotline phone Name</description>
+ <width>160</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <label>$LOCALIZE[29910]:</label>
+ <visible>!IsEmpty(RDS.PhoneHotline)</visible>
+ </control>
+ <control type="label">
+ <description>Hotline email Name</description>
+ <width>160</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <label>$LOCALIZE[29911]:</label>
+ <visible>!IsEmpty(RDS.EmailHotline)</visible>
+ </control>
+ <control type="fadelabel">
+ <description>Homepage Value</description>
+ <width>320</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <label>$INFO[RDS.ProgHomepage]</label>
+ <visible>!IsEmpty(RDS.ProgHomepage)</visible>
+ </control>
+ </control>
+ <control type="grouplist">
+ <left>605</left>
+ <top>280</top>
+ <width>520</width>
+ <height>300</height>
+ <itemgap>8</itemgap>
+ <control type="label">
+ <description>blind label</description>
+ <width>5</width>
+ <height>25</height>
+ <label></label>
+ <visible>!IsEmpty(RDS.ProgNow)</visible>
+ </control>
+ <control type="label">
+ <description>blind label</description>
+ <width>140</width>
+ <height>25</height>
+ <label></label>
+ <visible>!IsEmpty(RDS.ProgNext)</visible>
+ </control>
+ <control type="fadelabel">
+ <description>Hotline phone Value</description>
+ <width>248</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>grey</textcolor>
+ <label>$INFO[RDS.PhoneHotline]</label>
+ <visible>!IsEmpty(RDS.PhoneHotline)</visible>
+ </control>
+ <control type="fadelabel">
+ <description>Hotline email Value</description>
+ <width>248</width>
+ <height>25</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font13</font>
+ <textcolor>grey</textcolor>
+ <label>$INFO[RDS.EmailHotline]</label>
+ <visible>!IsEmpty(RDS.EmailHotline)</visible>
+ </control>
+ </control>
+
+ <control type="group">
+ <description>Radio text info list</description>
+ <left>40</left>
+ <top>455</top>
+ <visible>false</visible>
+ <include>VisibleFadeEffect</include>
+ <control type="label">
+ <description>Info label</description>
+ <left>375</left>
+ <top>0</top>
+ <width>110</width>
+ <height>25</height>
+ <align>right</align>
+ <aligny>center</aligny>
+ <font>font13caps</font>
+ <textcolor>blue</textcolor>
+ <label>$LOCALIZE[29915]:</label>
+ </control>
+ <control type="spincontrol" id="21">
+ <description>Source Type</description>
+ <left>740</left>
+ <top>5</top>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <aligny>center</aligny>
+ <label>-</label>
+ <textoffsetx>10</textoffsetx>
+ <onright>21</onright>
+ <onleft>21</onleft>
+ <onup>9000</onup>
+ <ondown>9000</ondown>
+ </control>
+ <control type="spincontrol" id="60">
+ <description>Next page button</description>
+ <left>0</left>
+ <top>155</top>
+ <subtype>page</subtype>
+ <font>-</font>
+ <onright>9000</onright>
+ <onleft>9000</onleft>
+ <ondown>21</ondown>
+ <onup>21</onup>
+ <textcolor>-</textcolor>
+ <showonepage>true</showonepage>
+ </control>
+ <control type="textbox" id="22">
+ <description>PLOT</description>
+ <left>0</left>
+ <top>30</top>
+ <width>800</width>
+ <height>120</height>
+ <font>font11</font>
+ <align>justify</align>
+ <pagecontrol>60</pagecontrol>
+ <label>-</label>
+ </control>
+ </control>
+ <control type="grouplist" id="9000">
+ <left>40</left>
+ <top>620</top>
+ <width>790</width>
+ <height>40</height>
+ <itemgap>5</itemgap>
+ <align>center</align>
+ <orientation>horizontal</orientation>
+ <onleft>60</onleft>
+ <onright>60</onright>
+ <onup>21</onup>
+ <ondown>21</ondown>
+ <control type="button" id="10">
+ <description>OK</description>
+ <include>ButtonInfoDialogsCommonValues</include>
+ <label>186</label>
+ </control>
+ </control>
+ </controls>
+</window>
diff --git a/addons/skin.confluence/720p/Home.xml b/addons/skin.confluence/720p/Home.xml
index 4cab4c78b2..8fd7d2d7b9 100644
--- a/addons/skin.confluence/720p/Home.xml
+++ b/addons/skin.confluence/720p/Home.xml
@@ -669,13 +669,28 @@
<alttexturefocus>OSDPlayFO.png</alttexturefocus>
<alttexturenofocus>OSDPlayNF.png</alttexturenofocus>
<onleft>603</onleft>
- <onright>606</onright>
+ <onright>605</onright>
<onup>9003</onup>
<ondown>9000</ondown>
<onclick>PlayerControl(Play)</onclick>
<enable>Player.PauseEnabled</enable>
<animation effect="fade" start="100" end="30" time="75" condition="!Player.PauseEnabled">Conditional</animation>
</control>
+ <control type="button" id="605">
+ <left>130</left>
+ <top>2</top>
+ <width>30</width>
+ <height>30</height>
+ <label>-</label>
+ <texturefocus>OSDRadioRDSFO.png</texturefocus>
+ <texturenofocus>OSDRadioRDSNF.png</texturenofocus>
+ <onleft>604</onleft>
+ <onright>606</onright>
+ <onup>9003</onup>
+ <ondown>9000</ondown>
+ <onclick>ActivateWindow(PVRRadioRDSInfo)</onclick>
+ <visible>RDS.HasRadiotextPlus</visible>
+ </control>
<control type="button" id="606">
<left>160</left>
<top>2</top>
@@ -684,7 +699,7 @@
<label>-</label>
<texturefocus>OSDRecordOffFO.png</texturefocus>
<texturenofocus>OSDRecordOffNF.png</texturenofocus>
- <onleft>604</onleft>
+ <onleft>605</onleft>
<onright>607</onright>
<onup>9003</onup>
<ondown>9000</ondown>
@@ -1209,7 +1224,7 @@
<description>Date label</description>
<right>20</right>
<top>35</top>
- <width>200</width>
+ <width>300</width>
<height>15</height>
<align>right</align>
<aligny>center</aligny>
diff --git a/addons/skin.confluence/720p/MusicOSD.xml b/addons/skin.confluence/720p/MusicOSD.xml
index 506efcdc65..c6647de9e5 100644
--- a/addons/skin.confluence/720p/MusicOSD.xml
+++ b/addons/skin.confluence/720p/MusicOSD.xml
@@ -26,7 +26,7 @@
<ondown>100</ondown>
<animation effect="fade" time="150">VisibleChange</animation>
<animation effect="slide" start="0,0" end="-30,0" time="0" condition="Window.IsVisible(Mutebug)">conditional</animation>
- <visible>![Window.IsVisible(AddonSettings) | Window.IsVisible(SelectDialog) | Window.IsVisible(VisualisationPresetList) | Window.IsVisible(PVROSDChannels) | Window.IsVisible(PVROSDGuide) | Window.IsVisible(OSDAudioDSPSettings) | Window.IsVisible(Addon)]</visible>
+ <visible>![Window.IsVisible(AddonSettings) | Window.IsVisible(SelectDialog) | Window.IsVisible(VisualisationPresetList) | Window.IsVisible(PVROSDChannels) | Window.IsVisible(PVROSDGuide) | Window.IsVisible(PVRRadioRDSInfo) | Window.IsVisible(OSDAudioDSPSettings) | Window.IsVisible(Addon)]</visible>
</control>
<control type="slider" id="87">
<description>Seek Slider</description>
@@ -41,7 +41,7 @@
<textureslidernib>osd_slider_nibNF.png</textureslidernib>
<textureslidernibfocus>osd_slider_nib.png</textureslidernibfocus>
<animation effect="fade" time="150">VisibleChange</animation>
- <visible>![Window.IsVisible(AddonSettings) | Window.IsVisible(SelectDialog) | Window.IsVisible(VisualisationPresetList) | Window.IsVisible(PVROSDChannels) | Window.IsVisible(PVROSDGuide) | Window.IsVisible(OSDAudioDSPSettings) | Window.IsVisible(Addon)]</visible>
+ <visible>![Window.IsVisible(AddonSettings) | Window.IsVisible(SelectDialog) | Window.IsVisible(VisualisationPresetList) | Window.IsVisible(PVROSDChannels) | Window.IsVisible(PVROSDGuide) | Window.IsVisible(PVRRadioRDSInfo) | Window.IsVisible(OSDAudioDSPSettings) | Window.IsVisible(Addon)]</visible>
</control>
<control type="grouplist" id="100">
<left>325</left>
@@ -51,7 +51,7 @@
<orientation>horizontal</orientation>
<itemgap>0</itemgap>
<animation effect="fade" time="150">VisibleChange</animation>
- <visible>![Window.IsVisible(AddonSettings) | Window.IsVisible(SelectDialog) | Window.IsVisible(VisualisationPresetList) | Window.IsVisible(PVROSDChannels) | Window.IsVisible(PVROSDGuide) | Window.IsVisible(OSDAudioDSPSettings) | Window.IsVisible(Addon)]</visible>
+ <visible>![Window.IsVisible(AddonSettings) | Window.IsVisible(SelectDialog) | Window.IsVisible(VisualisationPresetList) | Window.IsVisible(PVROSDChannels) | Window.IsVisible(PVROSDGuide) | Window.IsVisible(PVRRadioRDSInfo) | Window.IsVisible(OSDAudioDSPSettings) | Window.IsVisible(Addon)]</visible>
<control type="button" id="300">
<width>55</width>
<height>55</height>
@@ -156,7 +156,18 @@
<texturefocus>OSDepgFO.png</texturefocus>
<texturenofocus>OSDepgNF.png</texturenofocus>
<onclick>ActivateWindow(PVROSDGuide)</onclick>
- <visible>MusicPlayer.Content(LiveTV)</visible>
+ <visible>MusicPlayer.Content(LiveTV) + !RDS.HasRadiotextPlus</visible>
+ </control>
+ <control type="button" id="308">
+ <visible>RDS.HasRadiotextPlus</visible>
+ <width>55</width>
+ <height>55</height>
+ <label>209</label>
+ <font>-</font>
+ <texturefocus>OSDRadioRDSFO.png</texturefocus>
+ <texturenofocus>OSDRadioRDSNF.png</texturenofocus>
+ <onclick>ActivateWindow(PVRRadioRDSInfo)</onclick>
+ <visible>MusicPlayer.Content(LiveTV) + RDS.HasRadiotextPlus</visible>
</control>
<control type="group" id="699">
<width>55</width>
diff --git a/addons/skin.confluence/720p/MusicVisualisation.xml b/addons/skin.confluence/720p/MusicVisualisation.xml
index 23d4d8dbcd..00c183fee3 100644
--- a/addons/skin.confluence/720p/MusicVisualisation.xml
+++ b/addons/skin.confluence/720p/MusicVisualisation.xml
@@ -25,7 +25,7 @@
<!-- media infos -->
<control type="group">
<animation effect="fade" time="150">VisibleChange</animation>
- <visible>[Player.ShowInfo | Window.IsActive(MusicOSD)] + ![Window.IsVisible(AddonSettings) | Window.IsVisible(SelectDialog) | Window.IsVisible(VisualisationPresetList) | Window.IsVisible(PVROSDChannels) | Window.IsVisible(PVROSDGuide) | Window.IsVisible(OSDAudioDSPSettings) | Window.IsVisible(Addon)]</visible>
+ <visible>[Player.ShowInfo | Window.IsActive(MusicOSD)] + ![Window.IsVisible(AddonSettings) | Window.IsVisible(SelectDialog) | Window.IsVisible(VisualisationPresetList) | Window.IsVisible(PVROSDChannels) | Window.IsVisible(PVROSDGuide) | Window.IsVisible(PVRRadioRDSInfo) | Window.IsVisible(OSDAudioDSPSettings) | Window.IsVisible(Addon)]</visible>
<control type="image">
<left>0</left>
<top>-150</top>
@@ -290,7 +290,7 @@
<control type="group" id="0">
<left>0</left>
<top>50</top>
- <visible>Player.ShowCodec + ![Window.IsVisible(script-cu-lrclyrics-main.xml) | Window.IsVisible(VisualisationSettings) | Window.IsVisible(VisualisationPresetList) | Window.IsVisible(PVROSDChannels) | Window.IsVisible(PVROSDGuide) | Window.IsVisible(OSDAudioDSPSettings) | Window.IsVisible(Addon)]</visible>
+ <visible>Player.ShowCodec + ![Window.IsVisible(script-cu-lrclyrics-main.xml) | Window.IsVisible(VisualisationSettings) | Window.IsVisible(VisualisationPresetList) | Window.IsVisible(PVROSDChannels) | Window.IsVisible(PVROSDGuide) | Window.IsVisible(PVRRadioRDSInfo) | Window.IsVisible(OSDAudioDSPSettings) | Window.IsVisible(Addon)]</visible>
<animation effect="fade" time="150">VisibleChange</animation>
<control type="image">
<description>media info background image</description>
diff --git a/addons/skin.confluence/720p/MyPVRChannels.xml b/addons/skin.confluence/720p/MyPVRChannels.xml
index 766b1751f3..fcc5e0c83b 100644
--- a/addons/skin.confluence/720p/MyPVRChannels.xml
+++ b/addons/skin.confluence/720p/MyPVRChannels.xml
@@ -3,7 +3,7 @@
<defaultcontrol always="true">50</defaultcontrol>
<menucontrol>9000</menucontrol>
<allowoverlay>no</allowoverlay>
- <views>50</views>
+ <views>50,51</views>
<controls>
<include>CommonBackground</include>
<control type="image">
@@ -17,8 +17,9 @@
</control>
<control type="group">
<include>Window_OpenClose_Animation</include>
+ <include>VisibleFadeEffect</include>
<control type="group">
- <include>VisibleFadeEffect</include>
+ <visible>Control.IsVisible(50)</visible>
<control type="image">
<left>50</left>
<top>60</top>
@@ -26,28 +27,45 @@
<height>600</height>
<texture border="15">ContentPanel.png</texture>
</control>
+ </control>
+ <control type="group">
+ <visible>Control.IsVisible(51)</visible>
<control type="image">
<left>50</left>
- <top>652</top>
- <width>450</width>
- <height>64</height>
- <texture border="15">ContentPanelMirror.png</texture>
- </control>
- <control type="image">
- <left>510</left>
<top>60</top>
- <width>730</width>
- <height>600</height>
+ <width>450</width>
+ <height>420</height>
<texture border="15">ContentPanel.png</texture>
</control>
<control type="image">
- <left>510</left>
- <top>652</top>
- <width>730</width>
- <height>64</height>
- <texture border="15">ContentPanelMirror.png</texture>
+ <left>50</left>
+ <top>480</top>
+ <width>450</width>
+ <height>180</height>
+ <texture border="15">ContentPanel.png</texture>
</control>
</control>
+ <control type="image">
+ <left>50</left>
+ <top>652</top>
+ <width>450</width>
+ <height>64</height>
+ <texture border="15">ContentPanelMirror.png</texture>
+ </control>
+ <control type="image">
+ <left>510</left>
+ <top>60</top>
+ <width>730</width>
+ <height>600</height>
+ <texture border="15">ContentPanel.png</texture>
+ </control>
+ <control type="image">
+ <left>510</left>
+ <top>652</top>
+ <width>730</width>
+ <height>64</height>
+ <texture border="15">ContentPanelMirror.png</texture>
+ </control>
</control>
<include>MainWindowMouseButtons</include>
<include>PVRHeader</include>
@@ -55,7 +73,7 @@
<description>Small Media Window</description>
<left>530</left>
<top>80</top>
- <visible>Control.IsVisible(50)</visible>
+ <visible>Control.IsVisible(50) | Control.IsVisible(51)</visible>
<include>VisibleFadeEffect</include>
<include>Window_OpenClose_Animation</include>
<control type="image">
@@ -108,11 +126,12 @@
<control type="group">
<include>Window_OpenClose_Animation</include>
<description>TV Channels group</description>
- <visible>Control.IsVisible(50)</visible>
+ <visible>Control.IsVisible(50) | Control.IsVisible(51)</visible>
<include>VisibleFadeEffect</include>
<control type="group">
<left>530</left>
<top>490</top>
+ <visible>Control.IsVisible(50) + !RDS.HasRDS</visible>
<control type="label">
<left>0</left>
<top>0</top>
@@ -187,230 +206,626 @@
<label>$LOCALIZE[19031]: $INFO[Container(50).ListItem.NextTitle]</label>
</control>
</control>
- <control type="list" id="50">
+ <control type="group">
<left>70</left>
- <top>85</top>
- <width>390</width>
- <height>541</height>
- <onleft>100</onleft>
- <onright>70</onright>
- <onup>50</onup>
- <ondown>50</ondown>
- <viewtype label="535">list</viewtype>
- <pagecontrol>70</pagecontrol>
- <scrolltime>200</scrolltime>
- <itemlayout height="60" width="390">
- <control type="image">
- <left>0</left>
- <top>0</top>
- <width>390</width>
- <height>61</height>
- <texture border="2">MenuItemNF.png</texture>
- <include>VisibleFadeEffect</include>
- </control>
- <control type="label">
- <left>5</left>
- <top>-4</top>
- <width>40</width>
- <height>35</height>
- <font>font12</font>
- <align>left</align>
- <aligny>center</aligny>
- <textcolor>grey</textcolor>
- <selectedcolor>grey</selectedcolor>
- <info>ListItem.ChannelNumberLabel</info>
- </control>
- <control type="label">
- <left>50</left>
- <top>0</top>
- <width>270</width>
- <height>25</height>
- <font>font13</font>
- <textcolor>white</textcolor>
- <selectedcolor>selected</selectedcolor>
- <align>left</align>
- <aligny>center</aligny>
- <label>$INFO[ListItem.Label]</label>
- </control>
- <control type="label">
- <left>50</left>
- <top>25</top>
- <width>330</width>
- <height>20</height>
- <font>font12</font>
- <textcolor>grey</textcolor>
- <selectedcolor>grey</selectedcolor>
- <align>left</align>
- <aligny>center</aligny>
- <label>$INFO[ListItem.Title]</label>
- <visible>IsEmpty(Listitem.Icon)</visible>
- </control>
- <control type="label">
- <left>50</left>
- <top>25</top>
- <width>280</width>
- <height>20</height>
- <font>font12</font>
- <textcolor>grey</textcolor>
- <selectedcolor>grey</selectedcolor>
- <align>left</align>
- <aligny>center</aligny>
- <label>$INFO[ListItem.Title]</label>
- <visible>!IsEmpty(Listitem.Icon)</visible>
- </control>
- <control type="progress">
- <description>Progressbar</description>
- <left>50</left>
- <top>48</top>
- <width>280</width>
- <height>6</height>
- <colordiffuse>88FFFFFF</colordiffuse>
- <visible>ListItem.HasEpg</visible>
- <info>ListItem.Progress</info>
- </control>
- <control type="image">
- <left>340</left>
- <top>4</top>
- <width>50</width>
- <height>50</height>
- <texture>$INFO[ListItem.Icon]</texture>
- <aspectratio>keep</aspectratio>
- </control>
- <control type="image">
- <left>5</left>
- <top>37</top>
- <width>30</width>
- <height>20</height>
- <texture>PVR-IsRecording.png</texture>
- <visible>ListItem.IsRecording</visible>
- </control>
- </itemlayout>
- <focusedlayout height="60" width="390">
- <control type="image">
- <left>0</left>
- <top>0</top>
- <width>390</width>
- <height>61</height>
- <texture border="2">MenuItemNF.png</texture>
- <visible>!Control.HasFocus(50)</visible>
- <include>VisibleFadeEffect</include>
- </control>
- <control type="image">
- <left>0</left>
- <top>0</top>
- <width>390</width>
- <height>61</height>
- <texture border="2">MenuItemFO.png</texture>
- <visible>Control.HasFocus(50)</visible>
- <include>VisibleFadeEffect</include>
- </control>
- <control type="label">
- <left>5</left>
- <top>-4</top>
- <width>40</width>
- <height>35</height>
- <font>font12</font>
- <align>left</align>
- <aligny>center</aligny>
- <textcolor>grey</textcolor>
- <selectedcolor>grey</selectedcolor>
- <info>ListItem.ChannelNumberLabel</info>
- </control>
- <control type="label">
- <left>50</left>
- <top>0</top>
- <width>270</width>
- <height>25</height>
- <font>font13</font>
- <textcolor>white</textcolor>
- <selectedcolor>selected</selectedcolor>
- <align>left</align>
- <aligny>center</aligny>
- <label>$INFO[ListItem.Label]</label>
- </control>
- <control type="label">
- <left>50</left>
- <top>25</top>
- <width>330</width>
- <height>20</height>
- <font>font12</font>
- <textcolor>grey</textcolor>
- <selectedcolor>grey</selectedcolor>
- <align>left</align>
- <aligny>center</aligny>
- <label>$INFO[ListItem.Title]</label>
- <visible>IsEmpty(Listitem.Icon)</visible>
- </control>
- <control type="label">
- <left>50</left>
- <top>25</top>
- <width>280</width>
- <height>20</height>
- <font>font12</font>
- <textcolor>grey</textcolor>
- <selectedcolor>grey</selectedcolor>
- <align>left</align>
- <aligny>center</aligny>
- <label>$INFO[ListItem.Title]</label>
- <visible>!IsEmpty(Listitem.Icon)</visible>
- </control>
- <control type="progress">
- <description>Progressbar</description>
- <left>50</left>
- <top>48</top>
- <width>280</width>
- <height>6</height>
- <colordiffuse>88FFFFFF</colordiffuse>
- <visible>ListItem.HasEpg</visible>
- <info>ListItem.Progress</info>
- </control>
- <control type="image">
- <left>340</left>
- <top>4</top>
- <width>50</width>
- <height>50</height>
- <texture>$INFO[ListItem.Icon]</texture>
- <aspectratio>keep</aspectratio>
- </control>
- <control type="image">
- <left>5</left>
- <top>37</top>
- <width>30</width>
- <height>20</height>
- <texture>PVR-IsRecording.png</texture>
- <visible>ListItem.IsRecording</visible>
- </control>
- </focusedlayout>
+ <top>490</top>
+ <visible>Control.IsVisible(51)</visible>
+ <control type="label">
+ <left>0</left>
+ <top>0</top>
+ <width>415</width>
+ <height>20</height>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <shadowcolor>black</shadowcolor>
+ <scroll>true</scroll>
+ <align>center</align>
+ <aligny>center</aligny>
+ <label>[B]$INFO[Container(51).ListItem.Title][/B]</label>
+ </control>
+ <control type="label">
+ <left>0</left>
+ <top>22</top>
+ <width>60</width>
+ <height>20</height>
+ <align>right</align>
+ <aligny>center</aligny>
+ <font>font10_title</font>
+ <textcolor>blue</textcolor>
+ <visible>Container(51).ListItem.HasEpg</visible>
+ <label>$INFO[Container(51).ListItem.StartTime]</label>
+ </control>
+ <control type="progress">
+ <description>Progressbar</description>
+ <left>65</left>
+ <top>30</top>
+ <width>275</width>
+ <height>8</height>
+ <visible>Container(51).ListItem.HasEpg</visible>
+ <info>Container(51).ListItem.Progress</info>
+ </control>
+ <control type="label">
+ <left>345</left>
+ <top>22</top>
+ <width>80</width>
+ <height>20</height>
+ <align>left</align>
+ <aligny>center</aligny>
+ <font>font10_title</font>
+ <textcolor>blue</textcolor>
+ <visible>Container(51).ListItem.HasEpg</visible>
+ <label>$INFO[Container(51).ListItem.EndTime]</label>
+ </control>
+ <control type="textbox">
+ <description>Plot Value for TVShow</description>
+ <left>0</left>
+ <top>50</top>
+ <width>415</width>
+ <height>74</height>
+ <font>font13</font>
+ <align>justify</align>
+ <textcolor>white</textcolor>
+ <shadowcolor>black</shadowcolor>
+ <pagecontrol>-</pagecontrol>
+ <label>$INFO[Container(51).ListItem.Plot]</label>
+ <autoscroll time="2000" delay="3000" repeat="5000">true</autoscroll>
+ </control>
+ <control type="label">
+ <left>0</left>
+ <top>140</top>
+ <width>400</width>
+ <height>20</height>
+ <font>font12</font>
+ <textcolor>grey2</textcolor>
+ <align>right</align>
+ <aligny>center</aligny>
+ <scroll>false</scroll>
+ <visible>!IsEmpty(Container(51).ListItem.NextTitle)</visible>
+ <label>$LOCALIZE[19031]: $INFO[Container(51).ListItem.NextTitle]</label>
+ </control>
</control>
- <control type="scrollbar" id="70">
- <left>465</left>
- <top>85</top>
- <width>25</width>
- <height>540</height>
- <texturesliderbackground border="0,14,0,14">ScrollBarV.png</texturesliderbackground>
- <texturesliderbar border="0,14,0,14">ScrollBarV_bar.png</texturesliderbar>
- <texturesliderbarfocus border="0,14,0,14">ScrollBarV_bar_focus.png</texturesliderbarfocus>
- <textureslidernib>ScrollBarNib.png</textureslidernib>
- <textureslidernibfocus>ScrollBarNib.png</textureslidernibfocus>
- <onleft>50</onleft>
- <onright>100</onright>
- <showonepage>false</showonepage>
- <orientation>vertical</orientation>
+ <control type="group">
+ <visible>Control.IsVisible(50)</visible>
+ <control type="list" id="50">
+ <left>70</left>
+ <top>85</top>
+ <width>390</width>
+ <height>541</height>
+ <onleft>100</onleft>
+ <onright>70</onright>
+ <onup>50</onup>
+ <ondown>50</ondown>
+ <viewtype label="535">list</viewtype>
+ <pagecontrol>70</pagecontrol>
+ <scrolltime>200</scrolltime>
+ <visible>!Control.IsVisible(51)</visible>
+ <itemlayout height="60" width="390">
+ <control type="image">
+ <left>0</left>
+ <top>0</top>
+ <width>390</width>
+ <height>61</height>
+ <texture border="2">MenuItemNF.png</texture>
+ <include>VisibleFadeEffect</include>
+ </control>
+ <control type="label">
+ <left>5</left>
+ <top>-4</top>
+ <width>40</width>
+ <height>35</height>
+ <font>font12</font>
+ <align>left</align>
+ <aligny>center</aligny>
+ <textcolor>grey</textcolor>
+ <selectedcolor>grey</selectedcolor>
+ <info>ListItem.ChannelNumberLabel</info>
+ </control>
+ <control type="label">
+ <left>50</left>
+ <top>0</top>
+ <width>270</width>
+ <height>25</height>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <selectedcolor>selected</selectedcolor>
+ <align>left</align>
+ <aligny>center</aligny>
+ <label>$INFO[ListItem.Label]</label>
+ </control>
+ <control type="label">
+ <left>50</left>
+ <top>25</top>
+ <width>330</width>
+ <height>20</height>
+ <font>font12</font>
+ <textcolor>grey</textcolor>
+ <selectedcolor>grey</selectedcolor>
+ <align>left</align>
+ <aligny>center</aligny>
+ <label>$INFO[ListItem.Title]</label>
+ <visible>IsEmpty(Listitem.Icon)</visible>
+ </control>
+ <control type="label">
+ <left>50</left>
+ <top>25</top>
+ <width>280</width>
+ <height>20</height>
+ <font>font12</font>
+ <textcolor>grey</textcolor>
+ <selectedcolor>grey</selectedcolor>
+ <align>left</align>
+ <aligny>center</aligny>
+ <label>$INFO[ListItem.Title]</label>
+ <visible>!IsEmpty(Listitem.Icon)</visible>
+ </control>
+ <control type="progress">
+ <description>Progressbar</description>
+ <left>50</left>
+ <top>48</top>
+ <width>280</width>
+ <height>6</height>
+ <colordiffuse>88FFFFFF</colordiffuse>
+ <visible>ListItem.HasEpg</visible>
+ <info>ListItem.Progress</info>
+ </control>
+ <control type="image">
+ <left>340</left>
+ <top>4</top>
+ <width>50</width>
+ <height>50</height>
+ <texture>$INFO[ListItem.Icon]</texture>
+ <aspectratio>keep</aspectratio>
+ </control>
+ <control type="image">
+ <left>5</left>
+ <top>37</top>
+ <width>30</width>
+ <height>20</height>
+ <texture>PVR-IsRecording.png</texture>
+ <visible>ListItem.IsRecording</visible>
+ </control>
+ </itemlayout>
+ <focusedlayout height="60" width="390">
+ <control type="image">
+ <left>0</left>
+ <top>0</top>
+ <width>390</width>
+ <height>61</height>
+ <texture border="2">MenuItemNF.png</texture>
+ <visible>!Control.HasFocus(50)</visible>
+ <include>VisibleFadeEffect</include>
+ </control>
+ <control type="image">
+ <left>0</left>
+ <top>0</top>
+ <width>390</width>
+ <height>61</height>
+ <texture border="2">MenuItemFO.png</texture>
+ <visible>Control.HasFocus(50)</visible>
+ <include>VisibleFadeEffect</include>
+ </control>
+ <control type="label">
+ <left>5</left>
+ <top>-4</top>
+ <width>40</width>
+ <height>35</height>
+ <font>font12</font>
+ <align>left</align>
+ <aligny>center</aligny>
+ <textcolor>grey</textcolor>
+ <selectedcolor>grey</selectedcolor>
+ <info>ListItem.ChannelNumberLabel</info>
+ </control>
+ <control type="label">
+ <left>50</left>
+ <top>0</top>
+ <width>270</width>
+ <height>25</height>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <selectedcolor>selected</selectedcolor>
+ <align>left</align>
+ <aligny>center</aligny>
+ <label>$INFO[ListItem.Label]</label>
+ </control>
+ <control type="label">
+ <left>50</left>
+ <top>25</top>
+ <width>330</width>
+ <height>20</height>
+ <font>font12</font>
+ <textcolor>grey</textcolor>
+ <selectedcolor>grey</selectedcolor>
+ <align>left</align>
+ <aligny>center</aligny>
+ <label>$INFO[ListItem.Title]</label>
+ <visible>IsEmpty(Listitem.Icon)</visible>
+ </control>
+ <control type="label">
+ <left>50</left>
+ <top>25</top>
+ <width>280</width>
+ <height>20</height>
+ <font>font12</font>
+ <textcolor>grey</textcolor>
+ <selectedcolor>grey</selectedcolor>
+ <align>left</align>
+ <aligny>center</aligny>
+ <label>$INFO[ListItem.Title]</label>
+ <visible>!IsEmpty(Listitem.Icon)</visible>
+ </control>
+ <control type="progress">
+ <description>Progressbar</description>
+ <left>50</left>
+ <top>48</top>
+ <width>280</width>
+ <height>6</height>
+ <colordiffuse>88FFFFFF</colordiffuse>
+ <visible>ListItem.HasEpg</visible>
+ <info>ListItem.Progress</info>
+ </control>
+ <control type="image">
+ <left>340</left>
+ <top>4</top>
+ <width>50</width>
+ <height>50</height>
+ <texture>$INFO[ListItem.Icon]</texture>
+ <aspectratio>keep</aspectratio>
+ </control>
+ <control type="image">
+ <left>5</left>
+ <top>37</top>
+ <width>30</width>
+ <height>20</height>
+ <texture>PVR-IsRecording.png</texture>
+ <visible>ListItem.IsRecording</visible>
+ </control>
+ </focusedlayout>
+ </control>
+ <control type="scrollbar" id="70">
+ <left>465</left>
+ <top>85</top>
+ <width>25</width>
+ <height>540</height>
+ <texturesliderbackground border="0,14,0,14">ScrollBarV.png</texturesliderbackground>
+ <texturesliderbar border="0,14,0,14">ScrollBarV_bar.png</texturesliderbar>
+ <texturesliderbarfocus border="0,14,0,14">ScrollBarV_bar_focus.png</texturesliderbarfocus>
+ <textureslidernib>ScrollBarNib.png</textureslidernib>
+ <textureslidernibfocus>ScrollBarNib.png</textureslidernibfocus>
+ <onleft>50</onleft>
+ <onright>61</onright>
+ <showonepage>false</showonepage>
+ <orientation>vertical</orientation>
+ </control>
+ <control type="label">
+ <animation effect="slide" start="0,0" end="-90,0" time="0" condition="system.getbool(input.enablemouse)">Conditional</animation>
+ <description>Page Count Label</description>
+ <right>40</right>
+ <top>53r</top>
+ <width>500</width>
+ <height>20</height>
+ <font>font12</font>
+ <textcolor>grey</textcolor>
+ <scroll>false</scroll>
+ <align>right</align>
+ <aligny>center</aligny>
+ <label>([COLOR=blue]$INFO[Container(50).NumItems][/COLOR]) $LOCALIZE[19019] - $LOCALIZE[31024] ([COLOR=blue]$INFO[Container(50).CurrentPage]/$INFO[Container(50).NumPages][/COLOR])</label>
+ <include>Window_OpenClose_Animation</include>
+ </control>
</control>
- <control type="label">
- <animation effect="slide" start="0,0" end="-90,0" time="0" condition="system.getbool(input.enablemouse)">Conditional</animation>
- <description>Page Count Label</description>
- <right>40</right>
- <top>53r</top>
- <width>500</width>
- <height>20</height>
- <font>font12</font>
- <textcolor>grey</textcolor>
- <scroll>false</scroll>
- <align>right</align>
- <aligny>center</aligny>
- <label>([COLOR=blue]$INFO[Container(50).NumItems][/COLOR]) $LOCALIZE[19019] - $LOCALIZE[31024] ([COLOR=blue]$INFO[Container(50).CurrentPage]/$INFO[Container(50).NumPages][/COLOR])</label>
- <include>Window_OpenClose_Animation</include>
+ <control type="group">
+ <visible>Control.IsVisible(51)</visible>
+ <control type="list" id="51">
+ <left>70</left>
+ <top>85</top>
+ <width>390</width>
+ <height>361</height>
+ <onleft>100</onleft>
+ <onright>70</onright>
+ <onup>51</onup>
+ <ondown>51</ondown>
+ <viewtype label="535">list</viewtype>
+ <pagecontrol>70</pagecontrol>
+ <scrolltime>200</scrolltime>
+ <visible>!IsEmpty(Window.Property(IsRadio)) + system.getbool(pvrplayback.enableradiords) + !Skin.HasSetting(HideEPGwithRDS)</visible>
+ <itemlayout height="60" width="390">
+ <control type="image">
+ <left>0</left>
+ <top>0</top>
+ <width>390</width>
+ <height>61</height>
+ <texture border="2">MenuItemNF.png</texture>
+ <include>VisibleFadeEffect</include>
+ </control>
+ <control type="label">
+ <left>5</left>
+ <top>-4</top>
+ <width>40</width>
+ <height>35</height>
+ <font>font12</font>
+ <align>left</align>
+ <aligny>center</aligny>
+ <textcolor>grey</textcolor>
+ <selectedcolor>grey</selectedcolor>
+ <info>ListItem.ChannelNumberLabel</info>
+ </control>
+ <control type="label">
+ <left>50</left>
+ <top>0</top>
+ <width>270</width>
+ <height>25</height>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <selectedcolor>selected</selectedcolor>
+ <align>left</align>
+ <aligny>center</aligny>
+ <label>$INFO[ListItem.Label]</label>
+ </control>
+ <control type="label">
+ <left>50</left>
+ <top>25</top>
+ <width>330</width>
+ <height>20</height>
+ <font>font12</font>
+ <textcolor>grey</textcolor>
+ <selectedcolor>grey</selectedcolor>
+ <align>left</align>
+ <aligny>center</aligny>
+ <label>$INFO[ListItem.Title]</label>
+ <visible>IsEmpty(Listitem.Icon)</visible>
+ </control>
+ <control type="label">
+ <left>50</left>
+ <top>25</top>
+ <width>280</width>
+ <height>20</height>
+ <font>font12</font>
+ <textcolor>grey</textcolor>
+ <selectedcolor>grey</selectedcolor>
+ <align>left</align>
+ <aligny>center</aligny>
+ <label>$INFO[ListItem.Title]</label>
+ <visible>!IsEmpty(Listitem.Icon)</visible>
+ </control>
+ <control type="progress">
+ <description>Progressbar</description>
+ <left>50</left>
+ <top>48</top>
+ <width>280</width>
+ <height>6</height>
+ <colordiffuse>88FFFFFF</colordiffuse>
+ <visible>ListItem.HasEpg</visible>
+ <info>ListItem.Progress</info>
+ </control>
+ <control type="image">
+ <left>340</left>
+ <top>4</top>
+ <width>50</width>
+ <height>50</height>
+ <texture>$INFO[ListItem.Icon]</texture>
+ <aspectratio>keep</aspectratio>
+ </control>
+ <control type="image">
+ <left>5</left>
+ <top>37</top>
+ <width>30</width>
+ <height>20</height>
+ <texture>PVR-IsRecording.png</texture>
+ <visible>ListItem.IsRecording</visible>
+ </control>
+ </itemlayout>
+ <focusedlayout height="60" width="390">
+ <control type="image">
+ <left>0</left>
+ <top>0</top>
+ <width>390</width>
+ <height>61</height>
+ <texture border="2">MenuItemNF.png</texture>
+ <visible>!Control.HasFocus(51)</visible>
+ <include>VisibleFadeEffect</include>
+ </control>
+ <control type="image">
+ <left>0</left>
+ <top>0</top>
+ <width>390</width>
+ <height>61</height>
+ <texture border="2">MenuItemFO.png</texture>
+ <visible>Control.HasFocus(51)</visible>
+ <include>VisibleFadeEffect</include>
+ </control>
+ <control type="label">
+ <left>5</left>
+ <top>-4</top>
+ <width>40</width>
+ <height>35</height>
+ <font>font12</font>
+ <align>left</align>
+ <aligny>center</aligny>
+ <textcolor>grey</textcolor>
+ <selectedcolor>grey</selectedcolor>
+ <info>ListItem.ChannelNumberLabel</info>
+ </control>
+ <control type="label">
+ <left>50</left>
+ <top>0</top>
+ <width>270</width>
+ <height>25</height>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <selectedcolor>selected</selectedcolor>
+ <align>left</align>
+ <aligny>center</aligny>
+ <label>$INFO[ListItem.Label]</label>
+ </control>
+ <control type="label">
+ <left>50</left>
+ <top>25</top>
+ <width>330</width>
+ <height>20</height>
+ <font>font12</font>
+ <textcolor>grey</textcolor>
+ <selectedcolor>grey</selectedcolor>
+ <align>left</align>
+ <aligny>center</aligny>
+ <label>$INFO[ListItem.Title]</label>
+ <visible>IsEmpty(Listitem.Icon)</visible>
+ </control>
+ <control type="label">
+ <left>50</left>
+ <top>25</top>
+ <width>280</width>
+ <height>20</height>
+ <font>font12</font>
+ <textcolor>grey</textcolor>
+ <selectedcolor>grey</selectedcolor>
+ <align>left</align>
+ <aligny>center</aligny>
+ <label>$INFO[ListItem.Title]</label>
+ <visible>!IsEmpty(Listitem.Icon)</visible>
+ </control>
+ <control type="progress">
+ <description>Progressbar</description>
+ <left>50</left>
+ <top>48</top>
+ <width>280</width>
+ <height>6</height>
+ <colordiffuse>88FFFFFF</colordiffuse>
+ <visible>ListItem.HasEpg</visible>
+ <info>ListItem.Progress</info>
+ </control>
+ <control type="image">
+ <left>340</left>
+ <top>4</top>
+ <width>50</width>
+ <height>50</height>
+ <texture>$INFO[ListItem.Icon]</texture>
+ <aspectratio>keep</aspectratio>
+ </control>
+ <control type="image">
+ <left>5</left>
+ <top>37</top>
+ <width>30</width>
+ <height>20</height>
+ <texture>PVR-IsRecording.png</texture>
+ <visible>ListItem.IsRecording</visible>
+ </control>
+ </focusedlayout>
+ </control>
+ <control type="scrollbar" id="70">
+ <left>465</left>
+ <top>85</top>
+ <width>25</width>
+ <height>360</height>
+ <texturesliderbackground border="0,14,0,14">ScrollBarV.png</texturesliderbackground>
+ <texturesliderbar border="0,14,0,14">ScrollBarV_bar.png</texturesliderbar>
+ <texturesliderbarfocus border="0,14,0,14">ScrollBarV_bar_focus.png</texturesliderbarfocus>
+ <textureslidernib>ScrollBarNib.png</textureslidernib>
+ <textureslidernibfocus>ScrollBarNib.png</textureslidernibfocus>
+ <onleft>51</onleft>
+ <onright>61</onright>
+ <showonepage>false</showonepage>
+ <orientation>vertical</orientation>
+ </control>
+ <control type="label">
+ <animation effect="slide" start="0,0" end="-90,0" time="0" condition="system.getbool(input.enablemouse)">Conditional</animation>
+ <description>Page Count Label</description>
+ <right>40</right>
+ <top>53r</top>
+ <width>500</width>
+ <height>20</height>
+ <font>font12</font>
+ <textcolor>grey</textcolor>
+ <scroll>false</scroll>
+ <align>right</align>
+ <aligny>center</aligny>
+ <label>([COLOR=blue]$INFO[Container(51).NumItems][/COLOR]) $LOCALIZE[19019] - $LOCALIZE[31024] ([COLOR=blue]$INFO[Container(51).CurrentPage]/$INFO[Container(51).NumPages][/COLOR])</label>
+ <include>Window_OpenClose_Animation</include>
+ </control>
+ </control>
+ <control type="group">
+ <left>530</left>
+ <top>490</top>
+ <visible>RDS.HasRDS</visible>
+ <control type="image">
+ <left>580</left>
+ <top>-3</top>
+ <width>104</width>
+ <height>40</height>
+ <visible>!RDS.HasRadioText</visible>
+ <texture>flagging/rds/rds-logo.png</texture>
+ </control>
+ <control type="image">
+ <left>580</left>
+ <top>-3</top>
+ <width>104</width>
+ <height>34</height>
+ <visible>RDS.HasRadioText + !RDS.HasRadioTextPlus</visible>
+ <texture>flagging/rds/rds-radiotext-logo.png</texture>
+ </control>
+ <control type="image">
+ <left>580</left>
+ <top>-3</top>
+ <width>104</width>
+ <height>40</height>
+ <visible>RDS.HasRadioTextPlus</visible>
+ <texture>flagging/rds/rds-radiotext-plus-logo.png</texture>
+ </control>
+ <control type="label">
+ <left>0</left>
+ <top>40</top>
+ <width>690</width>
+ <height>20</height>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <shadowcolor>black</shadowcolor>
+ <align>left</align>
+ <aligny>center</aligny>
+ <scroll>true</scroll>
+ <visible>RDS.HasRDS</visible>
+ <label>$INFO[RDS.Getline(3)]</label>
+ </control>
+ <control type="label">
+ <left>0</left>
+ <top>65</top>
+ <width>690</width>
+ <height>20</height>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <shadowcolor>black</shadowcolor>
+ <align>left</align>
+ <aligny>center</aligny>
+ <scroll>true</scroll>
+ <visible>RDS.HasRDS</visible>
+ <label>$INFO[RDS.Getline(2)]</label>
+ </control>
+ <control type="label">
+ <left>0</left>
+ <top>90</top>
+ <width>690</width>
+ <height>20</height>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <shadowcolor>black</shadowcolor>
+ <align>left</align>
+ <aligny>center</aligny>
+ <scroll>true</scroll>
+ <visible>RDS.HasRDS</visible>
+ <label>$INFO[RDS.Getline(1)]</label>
+ </control>
+ <control type="label">
+ <left>0</left>
+ <top>115</top>
+ <width>690</width>
+ <height>20</height>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <shadowcolor>black</shadowcolor>
+ <align>left</align>
+ <aligny>center</aligny>
+ <scroll>true</scroll>
+ <visible>RDS.HasRDS</visible>
+ <label>$INFO[RDS.Getline(0)]</label>
+ </control>
</control>
</control>
<include>CommonNowPlaying</include>
diff --git a/addons/skin.confluence/720p/PlayerControls.xml b/addons/skin.confluence/720p/PlayerControls.xml
index 0669746e2f..48aaf3e3ad 100644
--- a/addons/skin.confluence/720p/PlayerControls.xml
+++ b/addons/skin.confluence/720p/PlayerControls.xml
@@ -368,7 +368,7 @@
<texturefocus>OSDRecordOffFO.png</texturefocus>
<texturenofocus>OSDRecordOffNF.png</texturenofocus>
<onleft>705</onleft>
- <onright>701</onright>
+ <onright>707</onright>
<onup>300</onup>
<ondown>200</ondown>
<onclick>PlayerControl(record)</onclick>
@@ -376,6 +376,21 @@
<animation effect="fade" start="100" end="30" time="75" condition="!Player.CanRecord">Conditional</animation>
<visible>VideoPlayer.Content(LiveTV)</visible>
</control>
+ <control type="button" id="707">
+ <left>400</left>
+ <top>0</top>
+ <width>40</width>
+ <height>40</height>
+ <label>-</label>
+ <texturefocus>OSDRadioRDSFO.png</texturefocus>
+ <texturenofocus>OSDRadioRDSNF.png</texturenofocus>
+ <onleft>706</onleft>
+ <onright>701</onright>
+ <onup>300</onup>
+ <ondown>200</ondown>
+ <onclick>ActivateWindow(PVRRadioRDSInfo)</onclick>
+ <visible>VideoPlayer.Content(LiveTV) + RDS.HasRadiotextPlus</visible>
+ </control>
</control>
<control type="image">
<description>gradient</description>
diff --git a/addons/skin.confluence/720p/SkinSettings.xml b/addons/skin.confluence/720p/SkinSettings.xml
index f4a15cbc10..e2e193d560 100644
--- a/addons/skin.confluence/720p/SkinSettings.xml
+++ b/addons/skin.confluence/720p/SkinSettings.xml
@@ -308,6 +308,18 @@
<selected>Skin.HasSetting(ActivateTvTunes)</selected>
<visible>System.HasAddon(script.tvtunes)</visible>
</control>
+ <control type="radiobutton" id="116">
+ <width>750</width>
+ <height>40</height>
+ <font>font13</font>
+ <label>31122</label>
+ <textcolor>grey2</textcolor>
+ <focusedcolor>white</focusedcolor>
+ <texturefocus>MenuItemFO.png</texturefocus>
+ <texturenofocus>MenuItemNF.png</texturenofocus>
+ <onclick>Skin.ToggleSetting(HideEPGwithRDS)</onclick>
+ <selected>Skin.HasSetting(HideEPGwithRDS)</selected>
+ </control>
<control type="label" id="106">
<width>750</width>
<height>45</height>
diff --git a/addons/skin.confluence/720p/includes.xml b/addons/skin.confluence/720p/includes.xml
index 46ed05aeb9..6506ff7eb5 100644
--- a/addons/skin.confluence/720p/includes.xml
+++ b/addons/skin.confluence/720p/includes.xml
@@ -305,7 +305,7 @@
<pulseonselect>false</pulseonselect>
</include>
<include name="SideBladeLeft">
- <animation effect="slide" start="0,0" end="250,0" time="300" tween="quadratic" easing="out" condition="ControlGroup(9000).HasFocus | Control.HasFocus(9001) | Control.HasFocus(8999)">Conditional</animation>
+ <animation effect="slide" start="0,0" end="250,0" time="300" tween="quadratic" easing="out" condition="[ControlGroup(9000).HasFocus | Control.HasFocus(9001) | Control.HasFocus(8999)] + ![Window.IsActive(PVRGuideInfo) | Window.IsActive(PVRRadioRDSInfo)]">Conditional</animation>
<animation effect="slide" start="0,0" end="-300,0" time="300" tween="quadratic" easing="out" condition="ControlGroup(9000).HasFocus | Control.HasFocus(9001)">WindowClose</animation>
<animation effect="slide" start="0,0" end="-50,0" time="225" tween="quadratic" easing="out" condition="![ControlGroup(9000).HasFocus | Control.HasFocus(9001)]">WindowClose</animation>
<animation effect="slide" start="-50,0" end="0,0" time="225" tween="quadratic" easing="out">WindowOpen</animation>
@@ -790,7 +790,7 @@
<visible>VideoPlayer.Content(LiveTV)</visible>
<include>VisibleFadeEffect</include>
<control type="button" id="600">
- <left>20</left>
+ <left>5</left>
<top>2</top>
<width>39</width>
<height>39</height>
@@ -804,7 +804,7 @@
<onclick>ChannelDown</onclick>
</control>
<control type="button" id="601">
- <left>60</left>
+ <left>45</left>
<top>2</top>
<width>39</width>
<height>39</height>
@@ -818,7 +818,7 @@
<onclick>ChannelUp</onclick>
</control>
<control type="button" id="603">
- <left>100</left>
+ <left>85</left>
<top>2</top>
<width>39</width>
<height>39</height>
@@ -833,7 +833,7 @@
<onclick>PlayerControl(Stop)</onclick>
</control>
<control type="togglebutton" id="604">
- <left>140</left>
+ <left>125</left>
<top>2</top>
<width>39</width>
<height>39</height>
@@ -853,7 +853,7 @@
<animation effect="fade" start="100" end="30" time="75" condition="!Player.PauseEnabled">Conditional</animation>
</control>
<control type="button" id="605">
- <left>180</left>
+ <left>165</left>
<top>2</top>
<width>39</width>
<height>39</height>
@@ -861,13 +861,43 @@
<texturefocus>OSDRecordOffFO.png</texturefocus>
<texturenofocus>OSDRecordOffNF.png</texturenofocus>
<onleft>604</onleft>
- <onright>50</onright>
+ <onright>606</onright>
<onup>610</onup>
<ondown>611</ondown>
<onclick>PlayerControl(record)</onclick>
<enable>Player.CanRecord</enable>
<animation effect="fade" start="100" end="30" time="75" condition="!Player.CanRecord">Conditional</animation>
</control>
+ <control type="button" id="606">
+ <left>205</left>
+ <top>2</top>
+ <width>39</width>
+ <height>39</height>
+ <label>-</label>
+ <visible>RDS.HasRadiotextPlus</visible>
+ <texturefocus>OSDRadioRDSFO.png</texturefocus>
+ <texturenofocus>OSDRadioRDSNF.png</texturenofocus>
+ <onleft>605</onleft>
+ <onright>50</onright>
+ <onup>610</onup>
+ <ondown>611</ondown>
+ <onclick>ActivateWindow(PVRRadioRDSInfo)</onclick>
+ </control>
+ <control type="button" id="606">
+ <left>205</left>
+ <top>2</top>
+ <width>39</width>
+ <height>39</height>
+ <label>-</label>
+ <visible>!RDS.HasRadiotextPlus</visible>
+ <texturefocus>OSDChannelListFO.png</texturefocus>
+ <texturenofocus>OSDChannelListNF.png</texturenofocus>
+ <onleft>605</onleft>
+ <onright>50</onright>
+ <onup>610</onup>
+ <ondown>611</ondown>
+ <onclick>ActivateWindow(PVRGuideInfo)</onclick>
+ </control>
</control>
<control type="group" id="9005">
<visible>Player.HasMedia</visible>
diff --git a/addons/skin.confluence/language/resource.language.en_gb/strings.po b/addons/skin.confluence/language/resource.language.en_gb/strings.po
index 66020c58a5..7aaa300d1b 100644
--- a/addons/skin.confluence/language/resource.language.en_gb/strings.po
+++ b/addons/skin.confluence/language/resource.language.en_gb/strings.po
@@ -257,7 +257,15 @@ msgctxt "#31119"
msgid "Hide background fanart"
msgstr ""
-#empty strings from id 31120 to 31123
+#empty strings from id 31120 to 31121
+
+#. Boolean settings value
+#: system/settings/settings.xml
+msgctxt "#31122"
+msgid "Hide EPG if RDS is present on channel window"
+msgstr ""
+
+#empty string id 31123
msgctxt "#31124"
msgid "Show background \"Now playing\" video"
diff --git a/addons/skin.confluence/media/OSDRadioRDSFO.png b/addons/skin.confluence/media/OSDRadioRDSFO.png
new file mode 100644
index 0000000000..3a7cdb9fdc
--- /dev/null
+++ b/addons/skin.confluence/media/OSDRadioRDSFO.png
Binary files differ
diff --git a/addons/skin.confluence/media/OSDRadioRDSNF.png b/addons/skin.confluence/media/OSDRadioRDSNF.png
new file mode 100644
index 0000000000..9081ec017d
--- /dev/null
+++ b/addons/skin.confluence/media/OSDRadioRDSNF.png
Binary files differ
diff --git a/addons/skin.confluence/media/flagging/rds/rds-logo.png b/addons/skin.confluence/media/flagging/rds/rds-logo.png
new file mode 100644
index 0000000000..440b4901f9
--- /dev/null
+++ b/addons/skin.confluence/media/flagging/rds/rds-logo.png
Binary files differ
diff --git a/addons/skin.confluence/media/flagging/rds/rds-radiotext-logo.png b/addons/skin.confluence/media/flagging/rds/rds-radiotext-logo.png
new file mode 100644
index 0000000000..26951c1e9a
--- /dev/null
+++ b/addons/skin.confluence/media/flagging/rds/rds-radiotext-logo.png
Binary files differ
diff --git a/addons/skin.confluence/media/flagging/rds/rds-radiotext-plus-logo.png b/addons/skin.confluence/media/flagging/rds/rds-radiotext-plus-logo.png
new file mode 100644
index 0000000000..4def9c4790
--- /dev/null
+++ b/addons/skin.confluence/media/flagging/rds/rds-radiotext-plus-logo.png
Binary files differ
diff --git a/configure.ac b/configure.ac
index 1bed9bb18e..9aa736677d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -198,6 +198,8 @@ librtmp_not_found="== Could not find libRTMP. RTMP support disabled. =="
librtmp_disabled="== RTMP support disabled. =="
libnfs_not_found="== Could not find libnfs. NFS client support disabled. =="
libnfs_disabled="== NFS support disabled. =="
+libgif_not_found="== Could not find libgif. libgif support disabled. =="
+libgif_disabled="== libgif support disabled. =="
libshairplay_not_found="== Could not find libshairplay. =="
samba_disabled="== SAMBA support disabled. =="
libplist_not_found="== Could not find libplist. AirPlay support disabled. =="
@@ -364,6 +366,12 @@ AC_ARG_ENABLE([nfs],
[use_libnfs=$enableval],
[use_libnfs=auto])
+AC_ARG_ENABLE([gif],
+ [AS_HELP_STRING([--enable-gif],
+ [enable gif support via libgif (default is auto)])],
+ [use_libgif=$enableval],
+ [use_libgif=auto])
+
AC_ARG_ENABLE([airplay],
[AS_HELP_STRING([--enable-airplay],
[enable AirPlay support(default is auto)])],
@@ -677,18 +685,6 @@ case $host in
esac
AC_SUBST([ARCH])
-case $host in
- *-apple-darwin*)
- check_sdl_arch=[`file $NATIVE_ROOT/lib/libSDL_image.dylib | awk '{print $NF}'`]
- if test "x$check_sdl_arch" = "xi386" ; then
- DARWIN_NATIVE_ARCH=-m32
- elif test "x$check_sdl_arch" = "xx86_64" ; then
- DARWIN_NATIVE_ARCH=-m64
- fi
- ;;
-esac
-AC_SUBST([DARWIN_NATIVE_ARCH])
-
if test "$target_platform" = "target_android" ; then
USE_ANDROID=1
webserver_checkdepends=yes
@@ -1250,7 +1246,7 @@ if test "$host_vendor" = "apple" ; then
if test "$use_arch" != "arm"; then
AC_CHECK_LIB([SDL], [main],, AC_MSG_ERROR($missing_library))
AC_DEFINE([HAVE_SDL],[1],["Define to 1 if using sdl"])
- AC_DEFINE([SDL_VERSION],[1],["SDL major version"])
+ AC_DEFINE([HAVE_SDL_VERSION],[1],["SDL major version"])
fi
else
if test "$target_platform" != "target_android" ; then
@@ -1273,7 +1269,7 @@ fi
# joystick
if test "$use_joystick" != "no"; then
PKG_CHECK_MODULES([SDL2], [sdl2],
- [AC_DEFINE([SDL_VERSION],[2],["SDL major version"])
+ [AC_DEFINE([HAVE_SDL_VERSION],[2],["SDL major version"])
AC_DEFINE([HAVE_SDL],[1],["Define to 1 if using sdl"])
INCLUDES="$INCLUDES $SDL2_CFLAGS"; LIBS="$LIBS $SDL2_LIBS"; use_joystick="yes"],
[if test "$use_joystick" = "yes"; then
@@ -1477,6 +1473,29 @@ else
AC_MSG_NOTICE($libnfs_disabled)
fi
+# libgif
+if test "$use_libgif" != "no"; then
+ AC_CHECK_HEADERS([gif_lib.h],,
+ [if test "$use_libgif" = "yes"; then
+ AC_MSG_ERROR($libgif_not_found)
+ USE_LIBGIF=0
+ elif test "$use_libgif" != "no"; then
+ AC_MSG_NOTICE($libgif_not_found)
+ use_libgif="no"
+ USE_LIBGIF=0
+ fi
+ ])
+ if test "$use_libgif" != "no"; then
+ XB_FIND_SONAME([GIF], [gif], [use_libgif])
+ fi
+ if test "$use_libgif" != "no"; then
+ AC_DEFINE([HAVE_LIBGIF], [1], [Whether to use libgif library.])
+ USE_LIBGIF=1
+ fi
+else
+ USE_LIBGIF=0
+ AC_MSG_NOTICE($libgif_disabled)
+fi
# libplist for airplay feature
USE_AIRPLAY=0
@@ -2248,6 +2267,12 @@ else
final_message="$final_message\n libnfs client support:No"
fi
+if test "$use_libgif" != "no"; then
+ final_message="$final_message\n libgif support:\tYes"
+else
+ final_message="$final_message\n libgif support:\tNo"
+fi
+
if test "$use_airplay" != "no"; then
final_message="$final_message\n AirPlay support:\tYes"
else
@@ -2349,6 +2374,7 @@ OUTPUT_FILES="Makefile \
xbmc/cores/omxplayer/Makefile \
xbmc/cores/playercorefactory/Makefile \
xbmc/messaging/Makefile \
+ xbmc/messaging/helpers/Makefile \
xbmc/music/karaoke/Makefile \
xbmc/osx/Makefile \
xbmc/guilib/Makefile \
@@ -2489,6 +2515,7 @@ AC_SUBST(USE_VDPAU)
AC_SUBST(USE_VAAPI)
AC_SUBST(USE_LIBSMBCLIENT)
AC_SUBST(USE_LIBNFS)
+AC_SUBST(USE_LIBGIF)
AC_SUBST(USE_AIRPLAY)
AC_SUBST(USE_OPENMAX)
AC_SUBST(USE_PULSE)
diff --git a/project/BuildDependencies/scripts/0_package.list b/project/BuildDependencies/scripts/0_package.list
index b90fb285f1..c7d41dc812 100644
--- a/project/BuildDependencies/scripts/0_package.list
+++ b/project/BuildDependencies/scripts/0_package.list
@@ -14,7 +14,7 @@ dnssd-541-win32.zip
doxygen-1.8.2-win32.7z
fontconfig-2.8.0-win32.7z
freetype-2.4.6-win32-3.7z
-giflib-5.0.5p-win32.7z
+giflib-5.1.0-win32.7z
gnutls-3.2.3-win32.zip
jsonschemabuilder-1.0.0-win32-3.7z
libass-0.12.1-win32.7z
diff --git a/project/VS2010Express/XBMC.vcxproj b/project/VS2010Express/XBMC.vcxproj
index d516bcc833..1c16c3eded 100644
--- a/project/VS2010Express/XBMC.vcxproj
+++ b/project/VS2010Express/XBMC.vcxproj
@@ -434,13 +434,13 @@
<ClCompile Include="..\..\xbmc\filesystem\ZipManager.cpp" />
<ClCompile Include="..\..\xbmc\GUIInfoManager.cpp" />
<ClCompile Include="..\..\xbmc\GUILargeTextureManager.cpp" />
- <ClCompile Include="..\..\xbmc\guilib\AnimatedGif.cpp" />
<ClCompile Include="..\..\xbmc\guilib\cximage.cpp" />
<ClCompile Include="..\..\xbmc\guilib\D3DResource.cpp" />
<ClCompile Include="..\..\xbmc\guilib\DDSImage.cpp" />
<ClCompile Include="..\..\xbmc\guilib\DirectXGraphics.cpp" />
<ClCompile Include="..\..\xbmc\guilib\DirtyRegionSolvers.cpp" />
<ClCompile Include="..\..\xbmc\guilib\DirtyRegionTracker.cpp" />
+ <ClCompile Include="..\..\xbmc\guilib\Gif.cpp" />
<ClCompile Include="..\..\xbmc\guilib\GraphicContext.cpp" />
<ClCompile Include="..\..\xbmc\guilib\GUIAction.cpp" />
<ClCompile Include="..\..\xbmc\guilib\GUIAudioManager.cpp" />
@@ -574,6 +574,7 @@
<ClCompile Include="..\..\xbmc\interfaces\legacy\Dialog.cpp" />
<ClCompile Include="..\..\xbmc\interfaces\legacy\File.cpp" />
<ClCompile Include="..\..\xbmc\interfaces\legacy\InfoTagMusic.cpp" />
+ <ClCompile Include="..\..\xbmc\interfaces\legacy\InfoTagRadioRDS.cpp" />
<ClCompile Include="..\..\xbmc\interfaces\legacy\InfoTagVideo.cpp" />
<ClCompile Include="..\..\xbmc\interfaces\legacy\Keyboard.cpp" />
<ClCompile Include="..\..\xbmc\interfaces\legacy\LanguageHook.cpp" />
@@ -626,6 +627,7 @@
<ClCompile Include="..\..\xbmc\MediaSource.cpp" />
<ClCompile Include="..\..\xbmc\media\MediaType.cpp" />
<ClCompile Include="..\..\xbmc\messaging\ApplicationMessenger.cpp" />
+ <ClCompile Include="..\..\xbmc\messaging\helpers\DialogHelper.cpp" />
<ClCompile Include="..\..\xbmc\music\Album.cpp" />
<ClCompile Include="..\..\xbmc\music\Artist.cpp" />
<ClCompile Include="..\..\xbmc\music\CueInfoLoader.cpp" />
@@ -771,12 +773,14 @@
<ClCompile Include="..\..\xbmc\pvr\channels\PVRChannelGroupInternal.cpp" />
<ClCompile Include="..\..\xbmc\pvr\channels\PVRChannelGroups.cpp" />
<ClCompile Include="..\..\xbmc\pvr\channels\PVRChannelGroupsContainer.cpp" />
+ <ClCompile Include="..\..\xbmc\pvr\channels\PVRRadioRDSInfoTag.cpp" />
<ClCompile Include="..\..\xbmc\pvr\dialogs\GUIDialogPVRChannelManager.cpp" />
<ClCompile Include="..\..\xbmc\pvr\dialogs\GUIDialogPVRChannelsOSD.cpp" />
<ClCompile Include="..\..\xbmc\pvr\dialogs\GUIDialogPVRGroupManager.cpp" />
<ClCompile Include="..\..\xbmc\pvr\dialogs\GUIDialogPVRGuideInfo.cpp" />
<ClCompile Include="..\..\xbmc\pvr\dialogs\GUIDialogPVRGuideOSD.cpp" />
<ClCompile Include="..\..\xbmc\pvr\dialogs\GUIDialogPVRGuideSearch.cpp" />
+ <ClCompile Include="..\..\xbmc\pvr\dialogs\GUIDialogPVRRadioRDSInfo.cpp" />
<ClCompile Include="..\..\xbmc\pvr\dialogs\GUIDialogPVRRecordingInfo.cpp" />
<ClCompile Include="..\..\xbmc\pvr\dialogs\GUIDialogPVRTimerSettings.cpp" />
<ClCompile Include="..\..\xbmc\pvr\PVRActionListener.cpp" />
@@ -963,6 +967,7 @@
<ClInclude Include="..\..\xbmc\filesystem\XbtManager.h" />
<ClInclude Include="..\..\xbmc\guiinfo\GUIInfoLabels.h" />
<ClInclude Include="..\..\xbmc\guilib\cximage.h" />
+ <ClInclude Include="..\..\xbmc\guilib\Gif.h" />
<ClInclude Include="..\..\xbmc\guilib\GUIKeyboard.h" />
<ClInclude Include="..\..\xbmc\guilib\GUIKeyboardFactory.h" />
<ClInclude Include="..\..\xbmc\guilib\GUIShaderDX.h" />
@@ -1008,6 +1013,7 @@
<ClInclude Include="..\..\xbmc\interfaces\legacy\Exception.h" />
<ClInclude Include="..\..\xbmc\interfaces\legacy\File.h" />
<ClInclude Include="..\..\xbmc\interfaces\legacy\InfoTagMusic.h" />
+ <ClInclude Include="..\..\xbmc\interfaces\legacy\InfoTagRadioRDS.h" />
<ClInclude Include="..\..\xbmc\interfaces\legacy\InfoTagVideo.h" />
<ClInclude Include="..\..\xbmc\interfaces\legacy\Keyboard.h" />
<ClInclude Include="..\..\xbmc\interfaces\legacy\LanguageHook.h" />
@@ -1044,6 +1050,7 @@
<ClInclude Include="..\..\xbmc\main\win32\MessagePrinter.h" />
<ClInclude Include="..\..\xbmc\media\MediaType.h" />
<ClInclude Include="..\..\xbmc\messaging\ApplicationMessenger.h" />
+ <ClInclude Include="..\..\xbmc\messaging\helpers\DialogHelper.h" />
<ClInclude Include="..\..\xbmc\messaging\IMessageTarget.h" />
<ClInclude Include="..\..\xbmc\messaging\ThreadMessage.h" />
<ClInclude Include="..\..\xbmc\music\CueInfoLoader.h" />
@@ -1579,6 +1586,7 @@
<ClCompile Include="..\..\xbmc\cores\dvdplayer\DVDOverlayRenderer.cpp" />
<ClCompile Include="..\..\xbmc\cores\dvdplayer\DVDPlayer.cpp" />
<ClCompile Include="..\..\xbmc\cores\dvdplayer\DVDPlayerAudio.cpp" />
+ <ClCompile Include="..\..\xbmc\cores\dvdplayer\DVDPlayerRadioRDS.cpp" />
<ClCompile Include="..\..\xbmc\cores\dvdplayer\DVDPlayerSubtitle.cpp" />
<ClCompile Include="..\..\xbmc\cores\dvdplayer\DVDPlayerTeletext.cpp" />
<ClCompile Include="..\..\xbmc\cores\dvdplayer\DVDPlayerVideo.cpp" />
@@ -1813,13 +1821,13 @@
<ClInclude Include="..\..\xbmc\filesystem\PVRFile.h" />
<ClInclude Include="..\..\xbmc\GUIInfoManager.h" />
<ClInclude Include="..\..\xbmc\GUILargeTextureManager.h" />
- <ClInclude Include="..\..\xbmc\guilib\AnimatedGif.h" />
<ClInclude Include="..\..\xbmc\guilib\D3DResource.h" />
<ClInclude Include="..\..\xbmc\guilib\DDSImage.h" />
<ClInclude Include="..\..\xbmc\guilib\DirectXGraphics.h" />
<ClInclude Include="..\..\xbmc\guilib\DirtyRegion.h" />
<ClInclude Include="..\..\xbmc\guilib\DirtyRegionSolvers.h" />
<ClInclude Include="..\..\xbmc\guilib\DirtyRegionTracker.h" />
+ <ClInclude Include="..\..\xbmc\guilib\DllLibGif.h" />
<ClInclude Include="..\..\xbmc\guilib\Geometry.h" />
<ClInclude Include="..\..\xbmc\guilib\GraphicContext.h" />
<ClInclude Include="..\..\xbmc\guilib\gui3d.h" />
@@ -2053,12 +2061,14 @@
<ClInclude Include="..\..\xbmc\pvr\channels\PVRChannelGroupInternal.h" />
<ClInclude Include="..\..\xbmc\pvr\channels\PVRChannelGroups.h" />
<ClInclude Include="..\..\xbmc\pvr\channels\PVRChannelGroupsContainer.h" />
+ <ClInclude Include="..\..\xbmc\pvr\channels\PVRRadioRDSInfoTag.h" />
<ClInclude Include="..\..\xbmc\pvr\dialogs\GUIDialogPVRChannelManager.h" />
<ClInclude Include="..\..\xbmc\pvr\dialogs\GUIDialogPVRChannelsOSD.h" />
<ClInclude Include="..\..\xbmc\pvr\dialogs\GUIDialogPVRGroupManager.h" />
<ClInclude Include="..\..\xbmc\pvr\dialogs\GUIDialogPVRGuideInfo.h" />
<ClInclude Include="..\..\xbmc\pvr\dialogs\GUIDialogPVRGuideOSD.h" />
<ClInclude Include="..\..\xbmc\pvr\dialogs\GUIDialogPVRGuideSearch.h" />
+ <ClInclude Include="..\..\xbmc\pvr\dialogs\GUIDialogPVRRadioRDSInfo.h" />
<ClInclude Include="..\..\xbmc\pvr\dialogs\GUIDialogPVRRecordingInfo.h" />
<ClInclude Include="..\..\xbmc\pvr\dialogs\GUIDialogPVRTimerSettings.h" />
<ClInclude Include="..\..\xbmc\pvr\PVRActionListener.h" />
@@ -2241,6 +2251,7 @@
<ClInclude Include="..\..\xbmc\cores\dvdplayer\DVDOverlayRenderer.h" />
<ClInclude Include="..\..\xbmc\cores\dvdplayer\DVDPlayer.h" />
<ClInclude Include="..\..\xbmc\cores\dvdplayer\DVDPlayerAudio.h" />
+ <ClInclude Include="..\..\xbmc\cores\dvdplayer\DVDPlayerRadioRDS.h" />
<ClInclude Include="..\..\xbmc\cores\dvdplayer\DVDPlayerSubtitle.h" />
<ClInclude Include="..\..\xbmc\cores\dvdplayer\DVDPlayerTeletext.h" />
<ClInclude Include="..\..\xbmc\cores\dvdplayer\DVDPlayerVideo.h" />
diff --git a/project/VS2010Express/XBMC.vcxproj.filters b/project/VS2010Express/XBMC.vcxproj.filters
index 482566a9cf..003ad474e1 100644
--- a/project/VS2010Express/XBMC.vcxproj.filters
+++ b/project/VS2010Express/XBMC.vcxproj.filters
@@ -364,6 +364,9 @@
<Filter Include="events\windows">
<UniqueIdentifier>{87d4e872-1a96-49a2-9ef0-78dd9fc30da9}</UniqueIdentifier>
</Filter>
+ <Filter Include="messaging\helpers">
+ <UniqueIdentifier>{b0eadc46-feeb-4aca-9898-590e6b8d29b3}</UniqueIdentifier>
+ </Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\xbmc\win32\pch.cpp">
@@ -414,6 +417,9 @@
<ClCompile Include="..\..\xbmc\cores\dvdplayer\DVDPlayerAudio.cpp">
<Filter>cores\dvdplayer</Filter>
</ClCompile>
+ <ClCompile Include="..\..\xbmc\cores\dvdplayer\DVDPlayerRadioRDS.cpp">
+ <Filter>cores\dvdplayer</Filter>
+ </ClCompile>
<ClCompile Include="..\..\xbmc\cores\dvdplayer\DVDPlayerSubtitle.cpp">
<Filter>cores\dvdplayer</Filter>
</ClCompile>
@@ -934,9 +940,6 @@
<ClCompile Include="..\..\xbmc\MediaSource.cpp" />
<ClCompile Include="..\..\xbmc\SystemGlobals.cpp" />
<ClCompile Include="..\..\xbmc\xbmc.cpp" />
- <ClCompile Include="..\..\xbmc\guilib\AnimatedGif.cpp">
- <Filter>guilib</Filter>
- </ClCompile>
<ClCompile Include="..\..\xbmc\guilib\D3DResource.cpp">
<Filter>guilib</Filter>
</ClCompile>
@@ -1702,6 +1705,9 @@
<ClCompile Include="..\..\xbmc\pvr\dialogs\GUIDialogPVRGuideSearch.cpp">
<Filter>pvr\dialogs</Filter>
</ClCompile>
+ <ClCompile Include="..\..\xbmc\pvr\dialogs\GUIDialogPVRRadioRDSInfo.cpp">
+ <Filter>pvr\dialogs</Filter>
+ </ClCompile>
<ClCompile Include="..\..\xbmc\pvr\dialogs\GUIDialogPVRRecordingInfo.cpp">
<Filter>pvr\dialogs</Filter>
</ClCompile>
@@ -1723,6 +1729,9 @@
<ClCompile Include="..\..\xbmc\pvr\channels\PVRChannelGroupsContainer.cpp">
<Filter>pvr\channels</Filter>
</ClCompile>
+ <ClCompile Include="..\..\xbmc\pvr\channels\PVRRadioRDSInfoTag.cpp">
+ <Filter>pvr\channels</Filter>
+ </ClCompile>
<ClCompile Include="..\..\xbmc\pvr\addons\PVRClient.cpp">
<Filter>pvr\addons</Filter>
</ClCompile>
@@ -2533,6 +2542,9 @@
<ClCompile Include="..\..\xbmc\interfaces\legacy\InfoTagMusic.cpp">
<Filter>interfaces\legacy</Filter>
</ClCompile>
+ <ClCompile Include="..\..\xbmc\interfaces\legacy\InfoTagRadioRDS.cpp">
+ <Filter>interfaces\legacy</Filter>
+ </ClCompile>
<ClCompile Include="..\..\xbmc\interfaces\legacy\InfoTagVideo.cpp">
<Filter>interfaces\legacy</Filter>
</ClCompile>
@@ -3192,6 +3204,12 @@
<ClCompile Include="..\..\xbmc\video\jobs\VideoLibraryRefreshingJob.cpp">
<Filter>video\jobs</Filter>
</ClCompile>
+ <ClCompile Include="..\..\xbmc\guilib\Gif.cpp">
+ <Filter>guilib</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\xbmc\messaging\helpers\DialogHelper.cpp">
+ <Filter>messaging\helpers</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\xbmc\win32\pch.h">
@@ -3245,6 +3263,9 @@
<ClInclude Include="..\..\xbmc\cores\dvdplayer\DVDPlayerAudio.h">
<Filter>cores\dvdplayer</Filter>
</ClInclude>
+ <ClInclude Include="..\..\xbmc\cores\dvdplayer\DVDPlayerRadioRDS.h">
+ <Filter>cores\dvdplayer</Filter>
+ </ClInclude>
<ClInclude Include="..\..\xbmc\cores\dvdplayer\DVDPlayerSubtitle.h">
<Filter>cores\dvdplayer</Filter>
</ClInclude>
@@ -3856,9 +3877,6 @@
</ClInclude>
<ClInclude Include="..\..\xbmc\Application.h" />
<ClInclude Include="..\..\xbmc\system.h" />
- <ClInclude Include="..\..\xbmc\guilib\AnimatedGif.h">
- <Filter>guilib</Filter>
- </ClInclude>
<ClInclude Include="..\..\xbmc\guilib\D3DResource.h">
<Filter>guilib</Filter>
</ClInclude>
@@ -4720,6 +4738,9 @@
<ClInclude Include="..\..\xbmc\pvr\dialogs\GUIDialogPVRGuideSearch.h">
<Filter>pvr\dialogs</Filter>
</ClInclude>
+ <ClInclude Include="..\..\xbmc\pvr\dialogs\GUIDialogPVRRadioRDSInfo.h">
+ <Filter>pvr\dialogs</Filter>
+ </ClInclude>
<ClInclude Include="..\..\xbmc\pvr\dialogs\GUIDialogPVRRecordingInfo.h">
<Filter>pvr\dialogs</Filter>
</ClInclude>
@@ -4738,6 +4759,9 @@
<ClInclude Include="..\..\xbmc\pvr\channels\PVRChannelGroups.h">
<Filter>pvr\channels</Filter>
</ClInclude>
+ <ClInclude Include="..\..\xbmc\pvr\channels\PVRRadioRDSInfoTag.h">
+ <Filter>pvr\channels</Filter>
+ </ClInclude>
<ClInclude Include="..\..\xbmc\pvr\addons\PVRClient.h">
<Filter>pvr\addons</Filter>
</ClInclude>
@@ -4825,6 +4849,9 @@
<ClInclude Include="..\..\xbmc\guilib\DirtyRegionTracker.h">
<Filter>guilib</Filter>
</ClInclude>
+ <ClInclude Include="..\..\xbmc\guilib\DllLibGif.h">
+ <Filter>guilib</Filter>
+ </ClInclude>
<ClInclude Include="..\..\xbmc\guilib\DirtyRegion.h">
<Filter>guilib</Filter>
</ClInclude>
@@ -5449,6 +5476,9 @@
<ClInclude Include="..\..\xbmc\interfaces\legacy\InfoTagMusic.h">
<Filter>interfaces\legacy</Filter>
</ClInclude>
+ <ClInclude Include="..\..\xbmc\interfaces\legacy\InfoTagRadioRDS.h">
+ <Filter>interfaces\legacy</Filter>
+ </ClInclude>
<ClInclude Include="..\..\xbmc\interfaces\legacy\InfoTagVideo.h">
<Filter>interfaces\legacy</Filter>
</ClInclude>
@@ -6187,6 +6217,12 @@
<ClInclude Include="..\..\xbmc\utils\win32\memcpy_sse2.h">
<Filter>utils\win32</Filter>
</ClInclude>
+ <ClInclude Include="..\..\xbmc\guilib\Gif.h">
+ <Filter>guilib</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\xbmc\messaging\helpers\DialogHelper.h">
+ <Filter>messaging\helpers</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\..\xbmc\win32\XBMC_PC.rc">
diff --git a/project/VS2010Express/XbmcThreads.vcxproj b/project/VS2010Express/XbmcThreads.vcxproj
index 8ce0f502fe..a5cecd8f6e 100644
--- a/project/VS2010Express/XbmcThreads.vcxproj
+++ b/project/VS2010Express/XbmcThreads.vcxproj
@@ -13,7 +13,6 @@
<ItemGroup>
<ClCompile Include="..\..\xbmc\threads\Atomics.cpp" />
<ClCompile Include="..\..\xbmc\threads\Event.cpp" />
- <ClCompile Include="..\..\xbmc\threads\LockFree.cpp" />
<ClCompile Include="..\..\xbmc\threads\Timer.cpp" />
<ClInclude Include="..\..\xbmc\threads\platform\ThreadImpl.h" />
<ClInclude Include="..\..\xbmc\threads\platform\win\ThreadImpl.cpp" />
@@ -31,7 +30,6 @@
<ClInclude Include="..\..\xbmc\threads\Event.h" />
<ClInclude Include="..\..\xbmc\threads\Helpers.h" />
<ClInclude Include="..\..\xbmc\threads\Lockables.h" />
- <ClInclude Include="..\..\xbmc\threads\LockFree.h" />
<ClInclude Include="..\..\xbmc\threads\platform\Condition.h" />
<ClInclude Include="..\..\xbmc\threads\platform\CriticalSection.h" />
<ClInclude Include="..\..\xbmc\threads\platform\ThreadLocal.h" />
diff --git a/project/VS2010Express/XbmcThreads.vcxproj.filters b/project/VS2010Express/XbmcThreads.vcxproj.filters
index ba6170653d..7de0862be9 100644
--- a/project/VS2010Express/XbmcThreads.vcxproj.filters
+++ b/project/VS2010Express/XbmcThreads.vcxproj.filters
@@ -3,7 +3,6 @@
<ItemGroup>
<ClCompile Include="..\..\xbmc\threads\Atomics.cpp" />
<ClCompile Include="..\..\xbmc\threads\Event.cpp" />
- <ClCompile Include="..\..\xbmc\threads\LockFree.cpp" />
<ClCompile Include="..\..\xbmc\threads\Thread.cpp" />
<ClCompile Include="..\..\xbmc\threads\SystemClock.cpp" />
<ClCompile Include="..\..\xbmc\threads\platform\Implementation.cpp">
@@ -21,7 +20,6 @@
<ClInclude Include="..\..\xbmc\threads\Event.h" />
<ClInclude Include="..\..\xbmc\threads\Helpers.h" />
<ClInclude Include="..\..\xbmc\threads\Lockables.h" />
- <ClInclude Include="..\..\xbmc\threads\LockFree.h" />
<ClInclude Include="..\..\xbmc\threads\SharedSection.h" />
<ClInclude Include="..\..\xbmc\threads\SingleLock.h" />
<ClInclude Include="..\..\xbmc\threads\Thread.h" />
diff --git a/system/settings/settings.xml b/system/settings/settings.xml
index a22a44fc15..820687f273 100644
--- a/system/settings/settings.xml
+++ b/system/settings/settings.xml
@@ -1399,6 +1399,42 @@
<control type="spinner" format="string" />
</setting>
</group>
+ <group id="4">
+ <setting id="pvrplayback.enableradiords" type="boolean" label="29980" help="29981">
+ <level>1</level>
+ <default>true</default>
+ <control type="toggle" />
+ </setting>
+ <setting id="pvrplayback.trafficadvisory" type="boolean" label="29982" help="29983">
+ <level>1</level>
+ <default>false</default>
+ <control type="toggle" />
+ <dependencies>
+ <dependency type="enable" setting="pvrplayback.enableradiords">true</dependency>
+ </dependencies>
+ </setting>
+ <setting id="pvrplayback.trafficadvisoryvolume" type="integer" label="29984" help="29985">
+ <level>2</level>
+ <default>10</default>
+ <constraints>
+ <minimum>0</minimum>
+ <step>1</step>
+ <maximum>20</maximum>
+ </constraints>
+ <control type="spinner" format="string">
+ <formatlabel>14050</formatlabel>
+ </control>
+ <dependencies>
+ <dependency type="enable" setting="pvrplayback.enableradiords">true</dependency>
+ <dependency type="enable" setting="pvrplayback.trafficadvisory">true</dependency>
+ </dependencies>
+ </setting>
+ <setting id="pvrplayback.sendrdstrafficmsg" type="boolean" label="29986" help="29987">
+ <level>2</level>
+ <default>false</default>
+ <control type="toggle" />
+ </setting>
+ </group>
</category>
<category id="pvrrecord" label="19043" help="36233">
<group id="1">
diff --git a/tools/depends/native/Makefile b/tools/depends/native/Makefile
index 17536f7777..833a91381f 100644
--- a/tools/depends/native/Makefile
+++ b/tools/depends/native/Makefile
@@ -7,9 +7,9 @@ endif
NATIVE= m4-native gettext-native autoconf-native automake-native \
libtool-native pkg-config-native yasm-native cmake-native \
gas-preprocessor-native python26-native zlib-native \
- pcre-native swig-native rpl-native libsdl_image-native libsquish-native \
+ pcre-native swig-native rpl-native libsquish-native \
tiff-native libpng-native libjpeg-turbo-native liblzo2-native giflib-native \
- libsdl-native distribute-native distutilscross-native JsonSchemaBuilder TexturePacker \
+ distribute-native distutilscross-native JsonSchemaBuilder TexturePacker \
google-breakpad-native
@@ -33,7 +33,6 @@ libtool-native: automake-native
libpng-native: zlib-native
tiff-native: libjpeg-turbo-native
swig-native: pcre-native
-libsdl_image-native: libsdl-native libpng-native libjpeg-turbo-native tiff-native
distribute-native: python26-native
distutilscross-native: python26-native distribute-native
tar-native: xz-native
diff --git a/tools/depends/native/giflib-native/Makefile b/tools/depends/native/giflib-native/Makefile
index 03d2fd1fdc..0885272272 100644
--- a/tools/depends/native/giflib-native/Makefile
+++ b/tools/depends/native/giflib-native/Makefile
@@ -5,7 +5,7 @@ PLATFORM=$(NATIVEPLATFORM)
# lib name, version
LIBNAME=giflib
-VERSION=5.0.5
+VERSION=5.1.0
SOURCE=$(LIBNAME)-$(VERSION)
ARCHIVE=$(SOURCE).tar.bz2
diff --git a/tools/depends/native/libsdl-native/01-SDL_SetWidthHeight.patch b/tools/depends/native/libsdl-native/01-SDL_SetWidthHeight.patch
deleted file mode 100644
index 0e26023554..0000000000
--- a/tools/depends/native/libsdl-native/01-SDL_SetWidthHeight.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-Index: include/SDL_video.h
-===================================================================
---- include/SDL_video.h (revision 4116)
-+++ include/SDL_video.h (working copy)
-@@ -324,6 +324,11 @@
- extern DECLSPEC SDL_Rect ** SDLCALL SDL_ListModes(SDL_PixelFormat *format, Uint32 flags);
-
- /**
-+* Alter the width and height of the current surface to the given sizes.
-+*/
-+extern DECLSPEC void SDLCALL SDL_SetWidthHeight(int width, int height);
-+
-+/**
- * Set up a video mode with the specified width, height and bits-per-pixel.
- *
- * If 'bpp' is 0, it is treated as the current display bits per pixel.
-
-Index: src/video/SDL_video.c
-===================================================================
---- src/video/SDL_video.c (revision 4116)
-+++ src/video/SDL_video.c (working copy)
-@@ -1956,3 +1956,11 @@
- return(0);
- }
- }
-+
-+void SDL_SetWidthHeight(int width, int height)
-+{
-+ if (current_video != NULL && current_video->screen != NULL) {
-+ current_video->screen->w = width;
-+ current_video->screen->h = height;
-+ }
-+}
diff --git a/tools/depends/native/libsdl-native/02-OSX_interpretKeyEvents.patch b/tools/depends/native/libsdl-native/02-OSX_interpretKeyEvents.patch
deleted file mode 100644
index 7c4c8071e2..0000000000
--- a/tools/depends/native/libsdl-native/02-OSX_interpretKeyEvents.patch
+++ /dev/null
@@ -1,15 +0,0 @@
---- src/video/quartz/SDL_QuartzEvents.m 2009-10-13 07:07:14.000000000 +0800
-+++ src/video/quartz/SDL_QuartzEvents.m 2013-08-03 09:12:27.000000000 +0800
-@@ -280,7 +280,11 @@
- the scancode/keysym.
- */
- if (SDL_TranslateUNICODE && state == SDL_PRESSED) {
-- [field_edit interpretKeyEvents:[NSArray arrayWithObject:event]];
-+ NSResponder *firstResponder = [[NSApp keyWindow] firstResponder];
-+ if ([NSStringFromClass([firstResponder class]) isEqual:@"OSXTextInputResponder"])
-+ [firstResponder interpretKeyEvents:[NSArray arrayWithObject:event]];
-+ else
-+ [field_edit interpretKeyEvents:[NSArray arrayWithObject:event]];
- chars = [ event characters ];
- numChars = [ chars length ];
- if (numChars > 0)
diff --git a/tools/depends/native/libsdl-native/03-mavericks-compile.patch b/tools/depends/native/libsdl-native/03-mavericks-compile.patch
deleted file mode 100644
index 254b9e2c94..0000000000
--- a/tools/depends/native/libsdl-native/03-mavericks-compile.patch
+++ /dev/null
@@ -1,12 +0,0 @@
---- src/video/quartz/SDL_QuartzVideo.h.orig 2013-10-27 16:51:48.000000000 +0100
-+++ src/video/quartz/SDL_QuartzVideo.h 2013-10-27 16:52:13.000000000 +0100
-@@ -91,7 +91,9 @@
- CGDirectDisplayID display; /* 0 == main display (only support single display) */
- const void *mode; /* current mode of the display */
- const void *save_mode; /* original mode of the display */
-+#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
- CGDirectPaletteRef palette; /* palette of an 8-bit display */
-+#endif
- NSOpenGLContext *gl_context; /* OpenGL rendering context */
- NSGraphicsContext *nsgfx_context; /* Cocoa graphics context */
- Uint32 width, height, bpp; /* frequently used data about the display */
diff --git a/tools/depends/native/libsdl-native/Makefile b/tools/depends/native/libsdl-native/Makefile
deleted file mode 100644
index 12bc560097..0000000000
--- a/tools/depends/native/libsdl-native/Makefile
+++ /dev/null
@@ -1,43 +0,0 @@
-include ../../Makefile.include
-PREFIX=$(NATIVEPREFIX)
-PLATFORM=$(NATIVEPLATFORM)
-DEPS= ../../Makefile.include.in 01-SDL_SetWidthHeight.patch 02-OSX_interpretKeyEvents.patch 03-mavericks-compile.patch Makefile
-
-# lib name, version
-LIBNAME=SDL
-VERSION=1.2.15
-SOURCE=$(LIBNAME)-$(VERSION)
-ARCHIVE=$(SOURCE).tar.gz
-
-# configuration settings
-CONFIGURE=./configure --prefix=$(PREFIX) \
- --without-x --disable-video-x11 --disable-video-directfb --enable-nasm=no
-
-LIBDYLIB=$(PLATFORM)/build/.libs/lib$(LIBNAME).a
-
-all: .installed-$(PLATFORM)
-
-$(TARBALLS_LOCATION)/$(ARCHIVE):
- cd $(TARBALLS_LOCATION); $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE)
-
-$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS)
- rm -rf $(PLATFORM); mkdir -p $(PLATFORM)
- cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
- cd $(PLATFORM); patch -p0 < ../01-SDL_SetWidthHeight.patch
- cd $(PLATFORM); patch -p0 < ../02-OSX_interpretKeyEvents.patch
- cd $(PLATFORM); patch -p0 < ../03-mavericks-compile.patch
- cd $(PLATFORM); $(CONFIGURE)
-
-$(LIBDYLIB): $(PLATFORM)
- $(MAKE) -j 1 -C $(PLATFORM)
-
-.installed-$(PLATFORM): $(LIBDYLIB)
- $(MAKE) -C $(PLATFORM) install
- touch $@
-
-clean:
- $(MAKE) -C $(PLATFORM) clean
- rm -f .installed-$(PLATFORM)
-
-distclean::
- rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/native/libsdl_image-native/Makefile b/tools/depends/native/libsdl_image-native/Makefile
deleted file mode 100644
index 546bf43d63..0000000000
--- a/tools/depends/native/libsdl_image-native/Makefile
+++ /dev/null
@@ -1,41 +0,0 @@
-include ../../Makefile.include
-PREFIX=$(NATIVEPREFIX)
-PLATFORM=$(NATIVEPLATFORM)
-DEPS=Makefile ../../Makefile.include.in
-
-# lib name, version
-LIBNAME=SDL_image
-VERSION=1.2.7
-SOURCE=$(LIBNAME)-$(VERSION)
-ARCHIVE=$(SOURCE).tar.gz
-
-# configuration settings
-CONFIGURE=./configure --prefix=$(PREFIX) \
- --disable-jpg-shared --disable-png-shared --disable-tif-shared --disable-sdltest
-
-LIBDYLIB=$(PLATFORM)/.libs/lib$(LIBNAME).a
-
-all: .installed-$(PLATFORM)
-
-$(TARBALLS_LOCATION)/$(ARCHIVE):
- cd $(TARBALLS_LOCATION); $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE)
-
-$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS)
- rm -rf $(PLATFORM); mkdir -p $(PLATFORM)
- cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
- echo $(PLATFORM) > .gitignore
- cd $(PLATFORM); $(CONFIGURE)
-
-$(LIBDYLIB): $(PLATFORM)
- $(MAKE) -C $(PLATFORM)
-
-.installed-$(PLATFORM): $(LIBDYLIB)
- $(MAKE) -C $(PLATFORM) install
- touch $@
-
-clean:
- $(MAKE) -C $(PLATFORM) clean
- rm -f .installed-$(PLATFORM)
-
-distclean::
- rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/target/Makefile b/tools/depends/target/Makefile
index ba3e6a6f0c..edc7ab411e 100644
--- a/tools/depends/target/Makefile
+++ b/tools/depends/target/Makefile
@@ -15,7 +15,7 @@ DEPENDS = \
python26 libshairplay \
libplist libcec libbluray boost tinyxml dummy-libxbmc \
libamplayer libssh taglib libusb libnfs \
- pythonmodule-pil libxslt ffmpeg platform crossguid libdcadec
+ pythonmodule-pil libxslt ffmpeg platform crossguid libdcadec giflib
FFMPEG_DEPENDS = gnutls libdcadec
diff --git a/tools/depends/target/giflib/01-android.patch b/tools/depends/target/giflib/01-android.patch
new file mode 100644
index 0000000000..2f3a61cab8
--- /dev/null
+++ b/tools/depends/target/giflib/01-android.patch
@@ -0,0 +1,18 @@
+--- lib/egif_lib.c Thu Aug 29 19:56:40 2013
++++ lib/egif_libnew.c Thu Mar 13 10:08:38 2014
+@@ -22,6 +22,15 @@
+ #endif /* _WIN32 */
+ #include <sys/stat.h>
+
++#if defined(ANDROID)
++#if !defined(S_IREAD)
++#define S_IREAD S_IRUSR
++#endif
++#if !defined(S_IWRITE)
++#define S_IWRITE S_IWUSR
++#endif
++#endif
++
+ #include "gif_lib.h"
+ #include "gif_lib_private.h"
+
diff --git a/tools/depends/target/giflib/Makefile b/tools/depends/target/giflib/Makefile
new file mode 100644
index 0000000000..b2977af0c0
--- /dev/null
+++ b/tools/depends/target/giflib/Makefile
@@ -0,0 +1,48 @@
+include ../../Makefile.include
+DEPS= ../../Makefile.include Makefile
+
+# lib name, version
+LIBNAME=giflib
+VERSION=5.1.0
+SOURCE=$(LIBNAME)-$(VERSION)
+ARCHIVE=$(SOURCE).tar.bz2
+
+# configuration settings
+CONFIGURE=./configure --prefix=$(PREFIX)
+
+LIBDYLIB=$(PLATFORM)/lib/.libs/$(LIBNAME).a
+
+CLEAN_FILES=$(ARCHIVE) $(PLATFORM)
+
+all: .installed-$(PLATFORM)
+
+$(TARBALLS_LOCATION)/$(ARCHIVE):
+ cd $(TARBALLS_LOCATION); $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE)
+
+$(PLATFORM): $(TARBALLS_LOCATION)/$(ARCHIVE) $(DEPS)
+ -rm -rf $(PLATFORM); mkdir -p $(PLATFORM)
+ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE)
+ifeq ($(OS),android)
+ cd $(PLATFORM); patch -p0 < ../01-android.patch
+endif
+ cd $(PLATFORM); $(CONFIGURE)
+
+$(LIBDYLIB): $(PLATFORM)
+ $(MAKE) -C $(PLATFORM)
+
+.installed-$(PLATFORM): $(LIBDYLIB)
+ $(MAKE) -C $(PLATFORM) install
+ifeq ($(OS),android)
+ rm -f $(PREFIX)/lib/libgif.la $(PREFIX)/lib/libgif.so $(PREFIX)/lib/libgif.so.7
+ mv -f $(PREFIX)/lib/libgif.so.7.0.0 $(PREFIX)/lib/libgif.so
+ $(RPL) -e "libgif.so.7" "libgif.so\x00\x00" $(PREFIX)/lib/libgif.so
+ -$(READELF) --dynamic $(PREFIX)/lib/libgif.so | grep ibrary
+endif
+ touch $@
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+ rm -r .installed-$(PLATFORM)
+ rm -rf $(PLATFORM)
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
diff --git a/tools/depends/target/gmp/Makefile b/tools/depends/target/gmp/Makefile
index 11f8dcbd09..47653bd179 100644
--- a/tools/depends/target/gmp/Makefile
+++ b/tools/depends/target/gmp/Makefile
@@ -21,6 +21,9 @@ endif
ifeq ($(OS),ios)
CONFIGURE_FLAGS=CC_FOR_BUILD=llvm-gcc CPP_FOR_BUILD="llvm-gcc -E" --disable-assembly
endif
+ifeq ($(OS),osx)
+CONFIGURE_FLAGS=--with-pic
+endif
# configuration settings
CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \
diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp
index 0aa8a544e5..a6224c25b9 100644
--- a/xbmc/Application.cpp
+++ b/xbmc/Application.cpp
@@ -60,6 +60,7 @@
#include "input/InertialScrollingHandler.h"
#include "messaging/ThreadMessage.h"
#include "messaging/ApplicationMessenger.h"
+#include "messaging/helpers/DialogHelper.h"
#include "SectionLoader.h"
#include "cores/DllLoader/DllLoaderContainer.h"
#include "GUIUserMessages.h"
@@ -96,9 +97,9 @@
#include "input/KeyboardLayoutManager.h"
-#if SDL_VERSION == 1
+#if HAVE_SDL_VERSION == 1
#include <SDL/SDL.h>
-#elif SDL_VERSION == 2
+#elif HAVE_SDL_VERSION == 2
#include <SDL2/SDL.h>
#endif
@@ -149,7 +150,6 @@
// Dialog includes
#include "video/dialogs/GUIDialogVideoBookmarks.h"
-#include "dialogs/GUIDialogYesNo.h"
#include "dialogs/GUIDialogOK.h"
#include "dialogs/GUIDialogKaiToast.h"
#include "dialogs/GUIDialogSubMenu.h"
@@ -251,6 +251,8 @@ using namespace ActiveAE;
using namespace XbmcThreads;
+using KODI::MESSAGING::HELPERS::DialogResponse;
+
// uncomment this if you want to use release libs in the debug build.
// Atm this saves you 7 mb of memory
#define USE_RELEASE_LIBS
@@ -1569,8 +1571,8 @@ void CApplication::ReloadSkin(bool confirm/*=false*/)
user as to whether they want to keep the current skin. */
if (confirm && !m_skinReverting)
{
- bool cancelled;
- if (!CGUIDialogYesNo::ShowAndGetInput(CVariant{13123}, CVariant{13111}, cancelled, CVariant{""}, CVariant{""}, 10000))
+ if (HELPERS::ShowYesNoDialogText(CVariant{13123}, CVariant{13111}, CVariant{""}, CVariant{""}, 10000) !=
+ DialogResponse::YES)
{
m_skinReverting = true;
if (oldSkin.empty())
@@ -4261,7 +4263,7 @@ bool CApplication::OnMessage(CGUIMessage& message)
case GUI_MSG_PLAYBACK_STARTED:
{
-#ifdef TARGET_DARWIN
+#ifdef TARGET_DARWIN_IOS
CDarwinUtils::SetScheduling(message.GetMessage());
#endif
CPlayList playList = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
@@ -4379,7 +4381,7 @@ bool CApplication::OnMessage(CGUIMessage& message)
if (m_pKaraokeMgr )
m_pKaraokeMgr->Stop();
#endif
-#ifdef TARGET_DARWIN
+#ifdef TARGET_DARWIN_IOS
CDarwinUtils::SetScheduling(message.GetMessage());
#endif
// first check if we still have items in the stack to play
diff --git a/xbmc/ApplicationPlayer.cpp b/xbmc/ApplicationPlayer.cpp
index 0cb8b0f9fc..ac8520c092 100644
--- a/xbmc/ApplicationPlayer.cpp
+++ b/xbmc/ApplicationPlayer.cpp
@@ -171,6 +171,12 @@ int CApplicationPlayer::GetPreferredPlaylist() const
return PLAYLIST_NONE;
}
+bool CApplicationPlayer::HasRDS() const
+{
+ std::shared_ptr<IPlayer> player = GetInternal();
+ return (player && player->HasRDS());
+}
+
bool CApplicationPlayer::IsPaused() const
{
std::shared_ptr<IPlayer> player = GetInternal();
@@ -198,6 +204,11 @@ bool CApplicationPlayer::IsPlayingVideo() const
return (IsPlaying() && HasVideo());
}
+bool CApplicationPlayer::IsPlayingRDS() const
+{
+ return (IsPlaying() && HasRDS());
+}
+
void CApplicationPlayer::Pause()
{
std::shared_ptr<IPlayer> player = GetInternal();
@@ -406,6 +417,15 @@ TextCacheStruct_t* CApplicationPlayer::GetTeletextCache()
return NULL;
}
+std::string CApplicationPlayer::GetRadioText(unsigned int line)
+{
+ std::shared_ptr<IPlayer> player = GetInternal();
+ if (player)
+ return player->GetRadioText(line);
+ else
+ return "";
+}
+
int64_t CApplicationPlayer::GetTotalTime() const
{
std::shared_ptr<IPlayer> player = GetInternal();
diff --git a/xbmc/ApplicationPlayer.h b/xbmc/ApplicationPlayer.h
index 2f25ec077e..6b15c0acbf 100644
--- a/xbmc/ApplicationPlayer.h
+++ b/xbmc/ApplicationPlayer.h
@@ -112,6 +112,7 @@ public:
void GetSubtitleStreamInfo(int index, SPlayerSubtitleStreamInfo &info);
bool GetSubtitleVisible();
TextCacheStruct_t* GetTeletextCache();
+ std::string GetRadioText(unsigned int line);
int64_t GetTime() const;
int64_t GetDisplayTime() const;
int64_t GetTotalTime() const;
@@ -120,6 +121,7 @@ public:
bool HasAudio() const;
bool HasMenu() const;
bool HasVideo() const;
+ bool HasRDS() const;
bool IsCaching() const;
bool IsInMenu() const;
bool IsPaused() const;
@@ -128,6 +130,7 @@ public:
bool IsPlaying() const;
bool IsPlayingAudio() const;
bool IsPlayingVideo() const;
+ bool IsPlayingRDS() const;
bool IsRecording() const;
void LoadPage(int p, int sp, unsigned char* buffer);
bool OnAction(const CAction &action);
diff --git a/xbmc/Autorun.cpp b/xbmc/Autorun.cpp
index 14416c30fa..5d8a33942c 100644
--- a/xbmc/Autorun.cpp
+++ b/xbmc/Autorun.cpp
@@ -33,6 +33,8 @@
#include "filesystem/Directory.h"
#include "filesystem/DirectoryFactory.h"
#include "filesystem/File.h"
+#include "messaging/ApplicationMessenger.h"
+#include "messaging/helpers/DialogHelper.h"
#include "profiles/ProfilesManager.h"
#include "settings/Settings.h"
#include "playlists/PlayList.h"
@@ -40,7 +42,6 @@
#include "guilib/LocalizeStrings.h"
#include "storage/MediaManager.h"
#include "video/VideoDatabase.h"
-#include "dialogs/GUIDialogYesNo.h"
#include "utils/StringUtils.h"
#include "utils/URIUtils.h"
#include "utils/log.h"
@@ -52,6 +53,9 @@
using namespace XFILE;
using namespace PLAYLIST;
using namespace MEDIA_DETECT;
+using namespace KODI::MESSAGING;
+
+using KODI::MESSAGING::HELPERS::DialogResponse;
CAutorun::CAutorun()
{
@@ -491,7 +495,9 @@ bool CAutorun::IsEnabled() const
bool CAutorun::PlayDiscAskResume(const std::string& path)
{
- return PlayDisc(path, true, !CanResumePlayDVD(path) || CGUIDialogYesNo::ShowAndGetInput(CVariant{341}, CVariant{""}, CVariant{""}, CVariant{""}, CVariant{13404}, CVariant{12021}));
+ return PlayDisc(path, true, !CanResumePlayDVD(path) ||
+ HELPERS::ShowYesNoDialogText(CVariant{341}, CVariant{""}, CVariant{13404}, CVariant{12021}) ==
+ DialogResponse::YES);
}
bool CAutorun::CanResumePlayDVD(const std::string& path)
diff --git a/xbmc/DllPaths_generated.h.in b/xbmc/DllPaths_generated.h.in
index 262d485669..5384a0b04e 100644
--- a/xbmc/DllPaths_generated.h.in
+++ b/xbmc/DllPaths_generated.h.in
@@ -28,10 +28,11 @@
#define DLL_PATH_CPLUFF "special://xbmcbin/system/libcpluff-@ARCH@.so"
#define DLL_PATH_IMAGELIB "special://xbmcbin/system/ImageLib-@ARCH@.so"
#define DLL_PATH_LIBEXIF "special://xbmcbin/system/libexif-@ARCH@.so"
-#define DLL_PATH_MEDIAINFO "special://xbmcbin/system/mediainfo-@ARCH@.so"
#define DLL_PATH_LIBRTMP "@RTMP_SONAME@"
#define DLL_PATH_LIBNFS "@NFS_SONAME@"
+#define DLL_PATH_LIBGIF "@GIF_SONAME@"
+
#define DLL_PATH_LIBPLIST "@PLIST_SONAME@"
#define DLL_PATH_LIBSHAIRPLAY "@SHAIRPLAY_SONAME@"
#define DLL_PATH_LIBCEC "@LIBCEC_SONAME@"
diff --git a/xbmc/DllPaths_generated_android.h.in b/xbmc/DllPaths_generated_android.h.in
index 8e5b549292..edf6a04939 100644
--- a/xbmc/DllPaths_generated_android.h.in
+++ b/xbmc/DllPaths_generated_android.h.in
@@ -30,10 +30,10 @@
#define DLL_PATH_CPLUFF "libcpluff-@ARCH@.so"
#define DLL_PATH_IMAGELIB "libImageLib-@ARCH@.so"
#define DLL_PATH_LIBEXIF "libexif-@ARCH@.so"
-#define DLL_PATH_MEDIAINFO "libmediainfo-@ARCH@.so"
#define DLL_PATH_LIBRTMP "@RTMP_SONAME@"
#define DLL_PATH_LIBNFS "@NFS_SONAME@"
+#define DLL_PATH_LIBGIF "@GIF_SONAME@"
#define DLL_PATH_LIBPLIST "@PLIST_SONAME@"
#define DLL_PATH_LIBSHAIRPLAY "@SHAIRPLAY_SONAME@"
#define DLL_PATH_LIBCEC "@LIBCEC_SONAME@"
diff --git a/xbmc/DllPaths_win32.h b/xbmc/DllPaths_win32.h
index 991336ee09..c4ed9a3aaf 100644
--- a/xbmc/DllPaths_win32.h
+++ b/xbmc/DllPaths_win32.h
@@ -25,6 +25,7 @@
#define DLL_PATH_CPLUFF "special://xbmcbin/system/cpluff.dll"
#define DLL_PATH_IMAGELIB "special://xbmcbin/system/ImageLib.dll"
#define DLL_PATH_LIBEXIF "special://xbmcbin/system/libexif.dll"
+#define DLL_PATH_LIBGIF "special://xbmcbin/system/libgif.dll"
#define DLL_PATH_LIBCURL "special://xbmcbin/system/libcurl.dll"
#define DLL_PATH_LIBNFS "special://xbmcbin/system/libnfs.dll"
#define DLL_PATH_LIBPLIST "special://xbmcbin/system/airplay/libplist.dll"
diff --git a/xbmc/FileItem.cpp b/xbmc/FileItem.cpp
index 31d0dc71ec..163c4efee5 100644
--- a/xbmc/FileItem.cpp
+++ b/xbmc/FileItem.cpp
@@ -42,6 +42,7 @@
#include "music/MusicDatabase.h"
#include "epg/Epg.h"
#include "pvr/channels/PVRChannel.h"
+#include "pvr/channels/PVRRadioRDSInfoTag.h"
#include "pvr/recordings/PVRRecording.h"
#include "pvr/timers/PVRTimerInfoTag.h"
#include "video/VideoInfoTag.h"
@@ -384,6 +385,7 @@ const CFileItem& CFileItem::operator=(const CFileItem& item)
m_pvrChannelInfoTag = item.m_pvrChannelInfoTag;
m_pvrRecordingInfoTag = item.m_pvrRecordingInfoTag;
m_pvrTimerInfoTag = item.m_pvrTimerInfoTag;
+ m_pvrRadioRDSInfoTag = item.m_pvrRadioRDSInfoTag;
m_lStartOffset = item.m_lStartOffset;
m_lStartPartNumber = item.m_lStartPartNumber;
@@ -452,6 +454,7 @@ void CFileItem::Reset()
m_pvrChannelInfoTag.reset();
m_pvrRecordingInfoTag.reset();
m_pvrTimerInfoTag.reset();
+ m_pvrRadioRDSInfoTag.reset();
delete m_pictureInfoTag;
m_pictureInfoTag=NULL;
m_extrainfo.clear();
@@ -504,6 +507,13 @@ void CFileItem::Archive(CArchive& ar)
}
else
ar << 0;
+ if (m_pvrRadioRDSInfoTag)
+ {
+ ar << 1;
+ ar << *m_pvrRadioRDSInfoTag;
+ }
+ else
+ ar << 0;
if (m_pictureInfoTag)
{
ar << 1;
@@ -549,6 +559,9 @@ void CFileItem::Archive(CArchive& ar)
ar >> *GetVideoInfoTag();
ar >> iType;
if (iType == 1)
+ ar >> *m_pvrRadioRDSInfoTag;
+ ar >> iType;
+ if (iType == 1)
ar >> *GetPictureInfoTag();
SetInvalid();
@@ -574,6 +587,9 @@ void CFileItem::Serialize(CVariant& value) const
if (m_videoInfoTag)
(*m_videoInfoTag).Serialize(value["videoInfoTag"]);
+ if (m_pvrRadioRDSInfoTag)
+ m_pvrRadioRDSInfoTag->Serialize(value["rdsInfoTag"]);
+
if (m_pictureInfoTag)
(*m_pictureInfoTag).Serialize(value["pictureInfoTag"]);
}
@@ -739,6 +755,11 @@ bool CFileItem::IsPVRTimer() const
return HasPVRTimerInfoTag();
}
+bool CFileItem::IsPVRRadioRDS() const
+{
+ return HasPVRRadioRDSInfoTag();
+}
+
bool CFileItem::IsDiscStub() const
{
if (IsVideoDb() && HasVideoInfoTag())
@@ -1379,6 +1400,11 @@ void CFileItem::UpdateInfo(const CFileItem &item, bool replaceLabels /*=true*/)
*GetMusicInfoTag() = *item.GetMusicInfoTag();
SetInvalid();
}
+ if (item.HasPVRRadioRDSInfoTag())
+ {
+ m_pvrRadioRDSInfoTag = item.m_pvrRadioRDSInfoTag;
+ SetInvalid();
+ }
if (item.HasPictureInfoTag())
{
*GetPictureInfoTag() = *item.GetPictureInfoTag();
@@ -1425,6 +1451,7 @@ void CFileItem::SetFromAlbum(const CAlbum &album)
m_bIsFolder = true;
m_strLabel2 = StringUtils::Join(album.artist, g_advancedSettings.m_musicItemSeparator);
GetMusicInfoTag()->SetAlbum(album);
+ SetArt(album.art);
m_bIsAlbum = true;
CMusicDatabase::SetPropertiesFromAlbum(*this,album);
FillInMimeType(false);
diff --git a/xbmc/FileItem.h b/xbmc/FileItem.h
index 0837520aa7..72f3ab0bf3 100644
--- a/xbmc/FileItem.h
+++ b/xbmc/FileItem.h
@@ -51,9 +51,11 @@ namespace PVR
class CPVRChannel;
class CPVRRecording;
class CPVRTimerInfoTag;
+ class CPVRRadioRDSInfoTag;
typedef std::shared_ptr<PVR::CPVRRecording> CPVRRecordingPtr;
typedef std::shared_ptr<PVR::CPVRChannel> CPVRChannelPtr;
typedef std::shared_ptr<PVR::CPVRTimerInfoTag> CPVRTimerInfoTagPtr;
+ typedef std::shared_ptr<PVR::CPVRRadioRDSInfoTag> CPVRRadioRDSInfoTagPtr;
}
class CPictureInfoTag;
@@ -213,6 +215,7 @@ public:
bool IsUsablePVRRecording() const;
bool IsDeletedPVRRecording() const;
bool IsPVRTimer() const;
+ bool IsPVRRadioRDS() const;
bool IsType(const char *ext) const;
bool IsVirtualDirectoryRoot() const;
bool IsReadOnly() const;
@@ -307,6 +310,21 @@ public:
return m_pvrTimerInfoTag;
}
+ inline bool HasPVRRadioRDSInfoTag() const
+ {
+ return m_pvrRadioRDSInfoTag.get() != NULL;
+ }
+
+ inline const PVR::CPVRRadioRDSInfoTagPtr GetPVRRadioRDSInfoTag() const
+ {
+ return m_pvrRadioRDSInfoTag;
+ }
+
+ inline void SetPVRRadioRDSInfoTag(const PVR::CPVRRadioRDSInfoTagPtr& tag)
+ {
+ m_pvrRadioRDSInfoTag = tag;
+ }
+
/*!
\brief Test if this item has a valid resume point set.
\return True if this item has a resume point and it is set, false otherwise.
@@ -503,6 +521,7 @@ private:
PVR::CPVRChannelPtr m_pvrChannelInfoTag;
PVR::CPVRRecordingPtr m_pvrRecordingInfoTag;
PVR::CPVRTimerInfoTagPtr m_pvrTimerInfoTag;
+ PVR::CPVRRadioRDSInfoTagPtr m_pvrRadioRDSInfoTag;
CPictureInfoTag* m_pictureInfoTag;
bool m_bIsAlbum;
diff --git a/xbmc/GUIInfoManager.cpp b/xbmc/GUIInfoManager.cpp
index f12919c8fd..2664014c11 100644
--- a/xbmc/GUIInfoManager.cpp
+++ b/xbmc/GUIInfoManager.cpp
@@ -83,6 +83,7 @@
#include "pvr/PVRManager.h"
#include "pvr/channels/PVRChannelGroupsContainer.h"
+#include "pvr/channels/PVRRadioRDSInfoTag.h"
#include "epg/EpgContainer.h"
#include "pvr/timers/PVRTimers.h"
#include "pvr/recordings/PVRRecording.h"
@@ -731,6 +732,52 @@ const infomap adsp[] = {{ "isactive", ADSP_IS_ACTIVE }
{ "masterownicon", ADSP_MASTER_OWN_ICON },
{ "masteroverrideicon", ADSP_MASTER_OVERRIDE_ICON }};
+const infomap rds[] = {{ "hasrds", RDS_HAS_RDS },
+ { "hasradiotext", RDS_HAS_RADIOTEXT },
+ { "hasradiotextplus", RDS_HAS_RADIOTEXT_PLUS },
+ { "audiolanguage", RDS_AUDIO_LANG },
+ { "channelcountry", RDS_CHANNEL_COUNTRY },
+ { "title", RDS_TITLE },
+ { "getline", RDS_GET_RADIOTEXT_LINE },
+ { "artist", RDS_ARTIST },
+ { "band", RDS_BAND },
+ { "composer", RDS_COMPOSER },
+ { "conductor", RDS_CONDUCTOR },
+ { "album", RDS_ALBUM },
+ { "tracknumber", RDS_ALBUM_TRACKNUMBER },
+ { "radiostyle", RDS_GET_RADIO_STYLE },
+ { "comment", RDS_COMMENT },
+ { "infonews", RDS_INFO_NEWS },
+ { "infonewslocal", RDS_INFO_NEWS_LOCAL },
+ { "infostock", RDS_INFO_STOCK },
+ { "infostocksize", RDS_INFO_STOCK_SIZE },
+ { "infosport", RDS_INFO_SPORT },
+ { "infosportsize", RDS_INFO_SPORT_SIZE },
+ { "infolottery", RDS_INFO_LOTTERY },
+ { "infolotterysize", RDS_INFO_LOTTERY_SIZE },
+ { "infoweather", RDS_INFO_WEATHER },
+ { "infoweathersize", RDS_INFO_WEATHER_SIZE },
+ { "infocinema", RDS_INFO_CINEMA },
+ { "infocinemasize", RDS_INFO_CINEMA_SIZE },
+ { "infohoroscope", RDS_INFO_HOROSCOPE },
+ { "infohoroscopesize", RDS_INFO_HOROSCOPE_SIZE },
+ { "infoother", RDS_INFO_OTHER },
+ { "infoothersize", RDS_INFO_OTHER_SIZE },
+ { "progstation", RDS_PROG_STATION },
+ { "prognow", RDS_PROG_NOW },
+ { "prognext", RDS_PROG_NEXT },
+ { "proghost", RDS_PROG_HOST },
+ { "progeditstaff", RDS_PROG_EDIT_STAFF },
+ { "proghomepage", RDS_PROG_HOMEPAGE },
+ { "progstyle", RDS_PROG_STYLE },
+ { "phonehotline", RDS_PHONE_HOTLINE },
+ { "phonestudio", RDS_PHONE_STUDIO },
+ { "smsstudio", RDS_SMS_STUDIO },
+ { "emailhotline", RDS_EMAIL_HOTLINE },
+ { "emailstudio", RDS_EMAIL_STUDIO },
+ { "hashotline", RDS_HAS_HOTLINE_DATA },
+ { "hasstudio", RDS_HAS_STUDIO_DATA }};
+
const infomap slideshow[] = {{ "ispaused", SLIDESHOW_ISPAUSED },
{ "isactive", SLIDESHOW_ISACTIVE },
{ "isvideo", SLIDESHOW_ISVIDEO },
@@ -1306,6 +1353,20 @@ int CGUIInfoManager::TranslateSingleString(const std::string &strCondition, bool
return adsp[i].val;
}
}
+ else if (cat.name == "rds")
+ {
+ if (prop.name == "getline")
+ {
+ std::string cat = prop.param(0);
+ StringUtils::ToLower(cat);
+ return AddMultiInfo(GUIInfo(RDS_GET_RADIOTEXT_LINE, atoi(cat.c_str())));
+ }
+ for (size_t i = 0; i < sizeof(rds) / sizeof(infomap); i++)
+ {
+ if (prop.name == rds[i].str)
+ return rds[i].val;
+ }
+ }
}
else if (info.size() == 3 || info.size() == 4)
{
@@ -1603,6 +1664,15 @@ std::string CGUIInfoManager::GetLabel(int info, int contextWindow, std::string *
{
if(m_currentFile)
{
+ if (m_currentFile->HasPVRRadioRDSInfoTag())
+ {
+ /*! Load the RDS Radiotext+ if present */
+ if (!m_currentFile->GetPVRRadioRDSInfoTag()->GetTitle().empty())
+ return m_currentFile->GetPVRRadioRDSInfoTag()->GetTitle();
+ /*! If no plus present load the RDS Radiotext info line 0 if present */
+ if (!g_application.m_pPlayer->GetRadioText(0).empty())
+ return g_application.m_pPlayer->GetRadioText(0);
+ }
if (m_currentFile->HasPVRChannelInfoTag())
{
CEpgInfoTagPtr tag(m_currentFile->GetPVRChannelInfoTag()->GetEPGNow());
@@ -1758,6 +1828,47 @@ std::string CGUIInfoManager::GetLabel(int info, int contextWindow, std::string *
strLabel = info.language;
}
break;
+ case RDS_AUDIO_LANG:
+ case RDS_CHANNEL_COUNTRY:
+ case RDS_TITLE:
+ case RDS_BAND:
+ case RDS_COMPOSER:
+ case RDS_CONDUCTOR:
+ case RDS_ALBUM:
+ case RDS_ALBUM_TRACKNUMBER:
+ case RDS_GET_RADIO_STYLE:
+ case RDS_COMMENT:
+ case RDS_ARTIST:
+ case RDS_INFO_NEWS:
+ case RDS_INFO_NEWS_LOCAL:
+ case RDS_INFO_STOCK:
+ case RDS_INFO_STOCK_SIZE:
+ case RDS_INFO_SPORT:
+ case RDS_INFO_SPORT_SIZE:
+ case RDS_INFO_LOTTERY:
+ case RDS_INFO_LOTTERY_SIZE:
+ case RDS_INFO_WEATHER:
+ case RDS_INFO_WEATHER_SIZE:
+ case RDS_INFO_CINEMA:
+ case RDS_INFO_CINEMA_SIZE:
+ case RDS_INFO_HOROSCOPE:
+ case RDS_INFO_HOROSCOPE_SIZE:
+ case RDS_INFO_OTHER:
+ case RDS_INFO_OTHER_SIZE:
+ case RDS_PROG_STATION:
+ case RDS_PROG_NOW:
+ case RDS_PROG_NEXT:
+ case RDS_PROG_HOST:
+ case RDS_PROG_EDIT_STAFF:
+ case RDS_PROG_HOMEPAGE:
+ case RDS_PROG_STYLE:
+ case RDS_PHONE_HOTLINE:
+ case RDS_PHONE_STUDIO:
+ case RDS_SMS_STUDIO:
+ case RDS_EMAIL_HOTLINE:
+ case RDS_EMAIL_STUDIO:
+ strLabel = GetRadioRDSLabel(info);
+ break;
case PLAYLIST_LENGTH:
case PLAYLIST_POSITION:
case PLAYLIST_RANDOM:
@@ -2780,6 +2891,28 @@ bool CGUIInfoManager::GetBool(int condition1, int contextWindow, const CGUIListI
}
}
break;
+ case RDS_HAS_RDS:
+ bReturn = g_application.m_pPlayer->IsPlayingRDS();
+ break;
+ case RDS_HAS_RADIOTEXT:
+ if (m_currentFile->HasPVRRadioRDSInfoTag())
+ bReturn = m_currentFile->GetPVRRadioRDSInfoTag()->IsPlayingRadiotext();
+ break;
+ case RDS_HAS_RADIOTEXT_PLUS:
+ if (m_currentFile->HasPVRRadioRDSInfoTag())
+ bReturn = m_currentFile->GetPVRRadioRDSInfoTag()->IsPlayingRadiotextPlus();
+ break;
+ case RDS_HAS_HOTLINE_DATA:
+ if (m_currentFile->HasPVRRadioRDSInfoTag())
+ bReturn = (!m_currentFile->GetPVRRadioRDSInfoTag()->GetEMailHotline().empty() ||
+ !m_currentFile->GetPVRRadioRDSInfoTag()->GetPhoneHotline().empty());
+ break;
+ case RDS_HAS_STUDIO_DATA:
+ if (m_currentFile->HasPVRRadioRDSInfoTag())
+ bReturn = (!m_currentFile->GetPVRRadioRDSInfoTag()->GetEMailStudio().empty() ||
+ !m_currentFile->GetPVRRadioRDSInfoTag()->GetSMSStudio().empty() ||
+ !m_currentFile->GetPVRRadioRDSInfoTag()->GetPhoneStudio().empty());
+ break;
default: // default, use integer value different from 0 as true
{
int val;
@@ -3515,6 +3648,10 @@ std::string CGUIInfoManager::GetMultiInfoLabel(const GUIInfo &info, int contextW
if (playlistid > PLAYLIST_NONE)
return GetPlaylistLabel(info.m_info, playlistid);
}
+ else if (info.m_info == RDS_GET_RADIOTEXT_LINE)
+ {
+ return g_application.m_pPlayer->GetRadioText(info.GetData1());
+ }
return "";
}
@@ -3767,6 +3904,174 @@ std::string CGUIInfoManager::GetPlaylistLabel(int item, int playlistid /* = PLAY
return "";
}
+std::string CGUIInfoManager::GetRadioRDSLabel(int item)
+{
+ if (!g_application.m_pPlayer->IsPlaying() ||
+ !m_currentFile->HasPVRChannelInfoTag() ||
+ !m_currentFile->HasPVRRadioRDSInfoTag())
+ return "";
+
+ const PVR::CPVRRadioRDSInfoTag &tag = *m_currentFile->GetPVRRadioRDSInfoTag();
+ switch (item)
+ {
+ case RDS_CHANNEL_COUNTRY:
+ return tag.GetCountry();
+
+ case RDS_AUDIO_LANG:
+ {
+ if (!tag.GetLanguage().empty())
+ return tag.GetLanguage();
+
+ SPlayerAudioStreamInfo info;
+ g_application.m_pPlayer->GetAudioStreamInfo(g_application.m_pPlayer->GetAudioStream(), info);
+ return info.language;
+ }
+
+ case RDS_TITLE:
+ return tag.GetTitle();
+
+ case RDS_ARTIST:
+ return tag.GetArtist();
+
+ case RDS_BAND:
+ return tag.GetBand();
+
+ case RDS_COMPOSER:
+ return tag.GetComposer();
+
+ case RDS_CONDUCTOR:
+ return tag.GetConductor();
+
+ case RDS_ALBUM:
+ return tag.GetAlbum();
+
+ case RDS_ALBUM_TRACKNUMBER:
+ {
+ if (!tag.GetAlbumTrackNumber() > 0)
+ return StringUtils::Format("%i", tag.GetAlbumTrackNumber());
+ break;
+ }
+ case RDS_GET_RADIO_STYLE:
+ return tag.GetRadioStyle();
+
+ case RDS_COMMENT:
+ return tag.GetComment();
+
+ case RDS_INFO_NEWS:
+ return tag.GetInfoNews();
+
+ case RDS_INFO_NEWS_LOCAL:
+ return tag.GetInfoNewsLocal();
+
+ case RDS_INFO_STOCK:
+ return tag.GetInfoStock();
+
+ case RDS_INFO_STOCK_SIZE:
+ return StringUtils::Format("%i", (int)tag.GetInfoStock().size());
+
+ case RDS_INFO_SPORT:
+ return tag.GetInfoSport();
+
+ case RDS_INFO_SPORT_SIZE:
+ return StringUtils::Format("%i", (int)tag.GetInfoSport().size());
+
+ case RDS_INFO_LOTTERY:
+ return tag.GetInfoLottery();
+
+ case RDS_INFO_LOTTERY_SIZE:
+ return StringUtils::Format("%i", (int)tag.GetInfoLottery().size());
+
+ case RDS_INFO_WEATHER:
+ return tag.GetInfoWeather();
+
+ case RDS_INFO_WEATHER_SIZE:
+ return StringUtils::Format("%i", (int)tag.GetInfoWeather().size());
+
+ case RDS_INFO_HOROSCOPE:
+ return tag.GetInfoHoroscope();
+
+ case RDS_INFO_HOROSCOPE_SIZE:
+ return StringUtils::Format("%i", (int)tag.GetInfoHoroscope().size());
+
+ case RDS_INFO_CINEMA:
+ return tag.GetInfoCinema();
+
+ case RDS_INFO_CINEMA_SIZE:
+ return StringUtils::Format("%i", (int)tag.GetInfoCinema().size());
+
+ case RDS_INFO_OTHER:
+ return tag.GetInfoOther();
+
+ case RDS_INFO_OTHER_SIZE:
+ return StringUtils::Format("%i", (int)tag.GetInfoOther().size());
+
+ case RDS_PROG_STATION:
+ {
+ if (!tag.GetProgStation().empty())
+ return tag.GetProgStation();
+ const CPVRChannelPtr channeltag = m_currentFile->GetPVRChannelInfoTag();
+ if (channeltag)
+ return channeltag->ChannelName();
+ break;
+ }
+
+ case RDS_PROG_NOW:
+ {
+ if (!tag.GetProgNow().empty())
+ return tag.GetProgNow();
+
+ CEpgInfoTagPtr epgNow(m_currentFile->GetPVRChannelInfoTag()->GetEPGNow());
+ return epgNow ?
+ epgNow->Title() :
+ CSettings::GetInstance().GetBool("epg.hidenoinfoavailable") ? "" : g_localizeStrings.Get(19055); // no information available
+ break;
+ }
+
+ case RDS_PROG_NEXT:
+ {
+ if (!tag.GetProgNext().empty())
+ return tag.GetProgNext();
+
+ CEpgInfoTagPtr epgNext(m_currentFile->GetPVRChannelInfoTag()->GetEPGNext());
+ return epgNext ?
+ epgNext->Title() :
+ CSettings::GetInstance().GetBool("epg.hidenoinfoavailable") ? "" : g_localizeStrings.Get(19055); // no information available
+ break;
+ }
+
+ case RDS_PROG_HOST:
+ return tag.GetProgHost();
+
+ case RDS_PROG_EDIT_STAFF:
+ return tag.GetEditorialStaff();
+
+ case RDS_PROG_HOMEPAGE:
+ return tag.GetProgWebsite();
+
+ case RDS_PROG_STYLE:
+ return tag.GetProgStyle();
+
+ case RDS_PHONE_HOTLINE:
+ return tag.GetPhoneHotline();
+
+ case RDS_PHONE_STUDIO:
+ return tag.GetPhoneStudio();
+
+ case RDS_SMS_STUDIO:
+ return tag.GetSMSStudio();
+
+ case RDS_EMAIL_HOTLINE:
+ return tag.GetEMailHotline();
+
+ case RDS_EMAIL_STUDIO:
+ return tag.GetEMailStudio();
+
+ default:
+ break;
+ }
+ return "";
+}
+
std::string CGUIInfoManager::GetMusicLabel(int item)
{
if (!g_application.m_pPlayer->IsPlaying() || !m_currentFile->HasMusicInfoTag()) return "";
@@ -3875,7 +4180,15 @@ std::string CGUIInfoManager::GetMusicTagLabel(int info, const CFileItem *item)
case MUSICPLAYER_CHANNEL_NAME:
{
if (m_currentFile->HasPVRChannelInfoTag())
+ {
+ if (m_currentFile->HasPVRRadioRDSInfoTag())
+ {
+ const CPVRRadioRDSInfoTagPtr rdstag(m_currentFile->GetPVRRadioRDSInfoTag());
+ if (rdstag && !rdstag->GetProgStation().empty())
+ return rdstag->GetProgStation();
+ }
return m_currentFile->GetPVRChannelInfoTag()->ChannelName();
+ }
}
break;
case MUSICPLAYER_CHANNEL_NUMBER:
@@ -4281,6 +4594,8 @@ void CGUIInfoManager::SetCurrentItem(CFileItem &item)
else
SetCurrentMovie(item);
+ if (item.HasPVRRadioRDSInfoTag())
+ m_currentFile->SetPVRRadioRDSInfoTag(item.GetPVRRadioRDSInfoTag());
if (item.HasEPGInfoTag())
m_currentFile->SetEPGInfoTag(item.GetEPGInfoTag());
else if (item.HasPVRChannelInfoTag())
@@ -5775,6 +6090,15 @@ const MUSIC_INFO::CMusicInfoTag* CGUIInfoManager::GetCurrentSongTag() const
return NULL;
}
+const PVR::CPVRRadioRDSInfoTagPtr CGUIInfoManager::GetCurrentRadioRDSInfoTag() const
+{
+ if (m_currentFile->HasPVRRadioRDSInfoTag())
+ return m_currentFile->GetPVRRadioRDSInfoTag();
+
+ PVR::CPVRRadioRDSInfoTagPtr empty;
+ return empty;
+}
+
const CVideoInfoTag* CGUIInfoManager::GetCurrentMovieTag() const
{
if (m_currentFile->HasVideoInfoTag())
diff --git a/xbmc/GUIInfoManager.h b/xbmc/GUIInfoManager.h
index 80b152ba8c..e43d99a1ed 100644
--- a/xbmc/GUIInfoManager.h
+++ b/xbmc/GUIInfoManager.h
@@ -44,6 +44,11 @@ namespace MUSIC_INFO
{
class CMusicInfoTag;
}
+namespace PVR
+{
+ class CPVRRadioRDSInfoTag;
+ typedef std::shared_ptr<PVR::CPVRRadioRDSInfoTag> CPVRRadioRDSInfoTagPtr;
+}
class CVideoInfoTag;
class CFileItem;
class CGUIListItem;
@@ -160,8 +165,10 @@ public:
void SetCurrentVideoTag(const CVideoInfoTag &tag);
const MUSIC_INFO::CMusicInfoTag *GetCurrentSongTag() const;
+ const PVR::CPVRRadioRDSInfoTagPtr GetCurrentRadioRDSInfoTag() const;
const CVideoInfoTag* GetCurrentMovieTag() const;
+ std::string GetRadioRDSLabel(int item);
std::string GetMusicLabel(int item);
std::string GetMusicTagLabel(int info, const CFileItem *item);
std::string GetVideoLabel(int item);
diff --git a/xbmc/GUIUserMessages.h b/xbmc/GUIUserMessages.h
index ce4ee2ea68..fffad6b5d6 100644
--- a/xbmc/GUIUserMessages.h
+++ b/xbmc/GUIUserMessages.h
@@ -139,3 +139,6 @@
// Sent to CGUIWindowEventLog
#define GUI_MSG_EVENT_ADDED GUI_MSG_USER + 39
#define GUI_MSG_EVENT_REMOVED GUI_MSG_USER + 40
+
+// Send to RDS Radiotext handlers to inform about changed data
+#define GUI_MSG_UPDATE_RADIOTEXT GUI_MSG_USER + 41
diff --git a/xbmc/LangInfo.cpp b/xbmc/LangInfo.cpp
index b8f94e0d46..6b0289371d 100644
--- a/xbmc/LangInfo.cpp
+++ b/xbmc/LangInfo.cpp
@@ -668,7 +668,7 @@ bool CLangInfo::SetLanguage(bool& fallback, const std::string &strLanguage /* =
// try to get the proper language addon by its name from all available language addons
if (ADDON::CLanguageResource::FindLanguageAddonByName(language, newLanguage, languageAddons))
{
- if (CAddonInstaller::GetInstance().Install(newLanguage, true, "", false, false))
+ if (CAddonInstaller::GetInstance().InstallOrUpdate(newLanguage, false, false))
{
CLog::Log(LOGINFO, "CLangInfo: successfully installed language addon \"%s\" matching current language \"%s\"", newLanguage.c_str(), language.c_str());
foundMatchingAddon = true;
diff --git a/xbmc/addons/Addon.h b/xbmc/addons/Addon.h
index d0a40d367f..a45e95344b 100644
--- a/xbmc/addons/Addon.h
+++ b/xbmc/addons/Addon.h
@@ -204,7 +204,7 @@ public:
virtual void OnPostInstall(bool update, bool modal) {};
virtual void OnPreUnInstall() {};
virtual void OnPostUnInstall() {};
- virtual bool CanInstall(const std::string& referer) { return true; }
+ virtual bool CanInstall() { return true; }
protected:
friend class CAddonCallbacksAddon;
diff --git a/xbmc/addons/AddonCallbacksGUI.cpp b/xbmc/addons/AddonCallbacksGUI.cpp
index ed43564417..efc36fef59 100644
--- a/xbmc/addons/AddonCallbacksGUI.cpp
+++ b/xbmc/addons/AddonCallbacksGUI.cpp
@@ -20,6 +20,7 @@
#include "Application.h"
#include "messaging/ApplicationMessenger.h"
+#include "messaging/helpers/DialogHelper.h"
#include "Addon.h"
#include "AddonCallbacksGUI.h"
#include "utils/log.h"
@@ -40,7 +41,6 @@
#include "guilib/GUIKeyboardFactory.h"
#include "dialogs/GUIDialogNumeric.h"
#include "dialogs/GUIDialogOK.h"
-#include "dialogs/GUIDialogYesNo.h"
#include "dialogs/GUIDialogFileBrowser.h"
#include "dialogs/GUIDialogTextViewer.h"
#include "dialogs/GUIDialogSelect.h"
@@ -51,6 +51,7 @@
#define CONTROL_LABELFILES 12
using namespace KODI::MESSAGING;
+using KODI::MESSAGING::HELPERS::DialogResponse;
namespace ADDON
{
@@ -1862,17 +1863,22 @@ void CAddonCallbacksGUI::Dialog_OK_ShowAndGetInputLineText(const char *heading,
//@{
bool CAddonCallbacksGUI::Dialog_YesNo_ShowAndGetInputSingleText(const char *heading, const char *text, bool& bCanceled, const char *noLabel, const char *yesLabel)
{
- return CGUIDialogYesNo::ShowAndGetInput(CVariant{heading}, CVariant{text}, CVariant{bCanceled}, CVariant{noLabel}, CVariant{yesLabel});
+ DialogResponse result = HELPERS::ShowYesNoDialogText(heading, text, noLabel, yesLabel);
+ bCanceled = result == DialogResponse::CANCELLED;
+ return result == DialogResponse::YES;
}
bool CAddonCallbacksGUI::Dialog_YesNo_ShowAndGetInputLineText(const char *heading, const char *line0, const char *line1, const char *line2, const char *noLabel, const char *yesLabel)
{
- return CGUIDialogYesNo::ShowAndGetInput(CVariant{heading}, CVariant{line0}, CVariant{line1}, CVariant{line2}, CVariant{noLabel}, CVariant{yesLabel});
+ return HELPERS::ShowYesNoDialogLines(heading, line0, line1, line2, noLabel, yesLabel) ==
+ DialogResponse::YES;
}
bool CAddonCallbacksGUI::Dialog_YesNo_ShowAndGetInputLineButtonText(const char *heading, const char *line0, const char *line1, const char *line2, bool &bCanceled, const char *noLabel, const char *yesLabel)
{
- return CGUIDialogYesNo::ShowAndGetInput(CVariant{heading}, CVariant{line0}, CVariant{line1}, CVariant{line2}, bCanceled, CVariant{noLabel}, CVariant{yesLabel}, CGUIDialogYesNo::NO_TIMEOUT);
+ DialogResponse result = HELPERS::ShowYesNoDialogLines(heading, line0, line1, line2, noLabel, yesLabel);
+ bCanceled = result == DialogResponse::CANCELLED;
+ return result == DialogResponse::YES;
}
//@}
diff --git a/xbmc/addons/AddonInstaller.cpp b/xbmc/addons/AddonInstaller.cpp
index 972b5df1e8..76eeace881 100644
--- a/xbmc/addons/AddonInstaller.cpp
+++ b/xbmc/addons/AddonInstaller.cpp
@@ -32,9 +32,9 @@
#include "settings/AdvancedSettings.h"
#include "settings/Settings.h"
#include "messaging/ApplicationMessenger.h"
+#include "messaging/helpers/DialogHelper.h"
#include "filesystem/FavouritesDirectory.h"
#include "utils/JobManager.h"
-#include "dialogs/GUIDialogYesNo.h"
#include "addons/AddonManager.h"
#include "addons/Repository.h"
#include "guilib/GUIWindowManager.h" // for callback
@@ -50,6 +50,8 @@ using namespace XFILE;
using namespace ADDON;
using namespace KODI::MESSAGING;
+using KODI::MESSAGING::HELPERS::DialogResponse;
+
struct find_map : public std::binary_function<CAddonInstaller::JobMap::value_type, unsigned int, bool>
{
bool operator() (CAddonInstaller::JobMap::value_type t, unsigned int id) const
@@ -172,45 +174,42 @@ bool CAddonInstaller::InstallModal(const std::string &addonID, ADDON::AddonPtr &
return false;
// if specified ask the user if he wants it installed
- if (promptForInstall &&
- !CGUIDialogYesNo::ShowAndGetInput(CVariant{24076}, CVariant{24100}, CVariant{addon->Name()}, CVariant{24101}))
- return false;
+ if (promptForInstall)
+ {
+ if (HELPERS::ShowYesNoDialogLines(CVariant{24076}, CVariant{24100}, CVariant{addon->Name()}, CVariant{24101}) !=
+ DialogResponse::YES)
+ {
+ return false;
+ }
+ }
- if (!Install(addonID, true, "", false, true))
+ if (!InstallOrUpdate(addonID, false, true))
return false;
return CAddonMgr::GetInstance().GetAddon(addonID, addon);
}
-bool CAddonInstaller::Install(const std::string &addonID, bool force /* = false */, const std::string &referer /* = "" */, bool background /* = true */, bool modal /* = false */)
+bool CAddonInstaller::InstallOrUpdate(const std::string &addonID, bool background /* = true */, bool modal /* = false */)
{
AddonPtr addon;
- bool addonInstalled = CAddonMgr::GetInstance().GetAddon(addonID, addon, ADDON_UNKNOWN, false);
- if (addonInstalled && !force)
- return true;
-
- if (referer.empty())
- {
- if (!g_passwordManager.CheckMenuLock(WINDOW_ADDON_BROWSER))
- return false;
- }
+ CAddonMgr::GetInstance().GetAddon(addonID, addon, ADDON_UNKNOWN, false);
// check whether we have it available in a repository
std::string hash;
if (!CAddonInstallJob::GetAddonWithHash(addonID, addon, hash))
return false;
- return DoInstall(addon, hash, addonInstalled, referer, background, modal);
+ return DoInstall(addon, hash, background, modal);
}
-bool CAddonInstaller::DoInstall(const AddonPtr &addon, const std::string &hash /* = "" */, bool update /* = false */, const std::string &referer /* = "" */, bool background /* = true */, bool modal /* = false */)
+bool CAddonInstaller::DoInstall(const AddonPtr &addon, const std::string &hash /* = "" */, bool background /* = true */, bool modal /* = false */)
{
// check whether we already have the addon installing
CSingleLock lock(m_critSection);
if (m_downloadJobs.find(addon->ID()) != m_downloadJobs.end())
return false;
- CAddonInstallJob* installJob = new CAddonInstallJob(addon, hash, update, referer);
+ CAddonInstallJob* installJob = new CAddonInstallJob(addon, hash);
if (background)
{
unsigned int jobID = CJobManager::GetInstance().AddJob(installJob, this);
@@ -410,9 +409,7 @@ void CAddonInstaller::InstallUpdates()
{
for (const auto& addon : addons)
{
- std::string referer = StringUtils::Format("Referer=%s-%s.zip",
- addon->ID().c_str(), addon->Version().asString().c_str());
- CAddonInstaller::GetInstance().Install(addon->ID(), true, referer);
+ CAddonInstaller::GetInstance().InstallOrUpdate(addon->ID());
}
}
}
@@ -438,12 +435,13 @@ int64_t CAddonInstaller::EnumeratePackageFolder(std::map<std::string,CFileItemLi
return size;
}
-CAddonInstallJob::CAddonInstallJob(const AddonPtr &addon, const std::string &hash /* = "" */, bool update /* = false */, const std::string &referer /* = "" */)
+CAddonInstallJob::CAddonInstallJob(const AddonPtr &addon, const std::string &hash /* = "" */)
: m_addon(addon),
- m_hash(hash),
- m_update(update),
- m_referer(referer)
-{ }
+ m_hash(hash)
+{
+ AddonPtr dummy;
+ m_update = CAddonMgr::GetInstance().GetAddon(addon->ID(), dummy, ADDON_UNKNOWN, false);
+}
AddonPtr CAddonInstallJob::GetRepoForAddon(const AddonPtr& addon)
{
@@ -546,13 +544,6 @@ bool CAddonInstallJob::DoWork()
if (!CFile::Exists(package))
{
std::string path(m_addon->Path());
- if (!m_referer.empty() && URIUtils::IsInternetStream(path))
- {
- CURL url(path);
- url.SetProtocolOptions(m_referer);
- path = url.Get();
- }
-
if (!DownloadPackage(path, dest))
{
CFile::Delete(package);
@@ -695,7 +686,6 @@ bool CAddonInstallJob::Install(const std::string &installFrom, const AddonPtr& r
return false;
// The first thing we do is install dependencies
- std::string referer = StringUtils::Format("Referer=%s-%s.zip",m_addon->ID().c_str(),m_addon->Version().asString().c_str());
for (ADDONDEPS::iterator it = deps.begin(); it != deps.end(); ++it)
{
if (it->first != "xbmc.metadata")
@@ -704,11 +694,10 @@ bool CAddonInstallJob::Install(const std::string &installFrom, const AddonPtr& r
const AddonVersion &version = it->second.first;
bool optional = it->second.second;
AddonPtr dependency;
- bool haveAddon = CAddonMgr::GetInstance().GetAddon(addonID, dependency);
+ bool haveAddon = CAddonMgr::GetInstance().GetAddon(addonID, dependency, ADDON_UNKNOWN, false);
if ((haveAddon && !dependency->MeetsVersion(version)) || (!haveAddon && !optional))
{
// we have it but our version isn't good enough, or we don't have it and we need it
- bool force = dependency != NULL;
// dependency is already queued up for install - ::Install will fail
// instead we wait until the Job has finished. note that we
@@ -717,7 +706,6 @@ bool CAddonInstallJob::Install(const std::string &installFrom, const AddonPtr& r
{
while (CAddonInstaller::GetInstance().HasJob(addonID))
Sleep(50);
- force = false;
if (!CAddonMgr::GetInstance().IsAddonInstalled(addonID))
{
@@ -738,7 +726,7 @@ bool CAddonInstallJob::Install(const std::string &installFrom, const AddonPtr& r
return false;
}
- CAddonInstallJob dependencyJob(addon, hash, force, referer);
+ CAddonInstallJob dependencyJob(addon, hash);
// pass our progress indicators to the temporary job and don't allow it to
// show progress or information updates (no progress, title or text changes)
@@ -751,7 +739,7 @@ bool CAddonInstallJob::Install(const std::string &installFrom, const AddonPtr& r
return false;
}
}
- else if (!CAddonInstaller::GetInstance().Install(addonID, force, referer, false))
+ else if (!CAddonInstaller::GetInstance().InstallOrUpdate(addonID, false))
{
CLog::Log(LOGERROR, "CAddonInstallJob[%s]: failed to install dependency %s", m_addon->ID().c_str(), addonID.c_str());
ReportInstallError(m_addon->ID(), m_addon->ID(), g_localizeStrings.Get(24085));
@@ -850,11 +838,6 @@ void CAddonInstallJob::ReportInstallError(const std::string& addonID, const std:
CEventLog::GetInstance().Add(activity, !IsModal(), false);
}
-std::string CAddonInstallJob::AddonID() const
-{
- return m_addon ? m_addon->ID() : "";
-}
-
CAddonUnInstallJob::CAddonUnInstallJob(const AddonPtr &addon)
: m_addon(addon)
{ }
diff --git a/xbmc/addons/AddonInstaller.h b/xbmc/addons/AddonInstaller.h
index 85c5d8f86c..533259600e 100644
--- a/xbmc/addons/AddonInstaller.h
+++ b/xbmc/addons/AddonInstaller.h
@@ -55,14 +55,12 @@ public:
/*! \brief Install an addon if it is available in a repository
\param addonID the addon ID of the item to install
- \param force whether to force the install even if the addon is already installed (eg for updating). Defaults to false.
- \param referer string to use for referer for http fetch. Set to previous version when updating, parent when fetching a dependency
\param background whether to install in the background or not. Defaults to true.
\param modal whether to show a modal dialog when not installing in background
\return true on successful install, false on failure.
\sa DoInstall
*/
- bool Install(const std::string &addonID, bool force = false, const std::string &referer="", bool background = true, bool modal = false);
+ bool InstallOrUpdate(const std::string &addonID, bool background = true, bool modal = false);
/*! \brief Install an addon from the given zip path
\param path the zip file to install from
@@ -125,12 +123,10 @@ private:
/*! \brief Install an addon from a repository or zip
\param addon the AddonPtr describing the addon
\param hash the hash to verify the install. Defaults to "".
- \param update whether this is an update of an existing addon, or a new install. Defaults to false.
- \param referer string to use for referer for http fetch. Defaults to "".
\param background whether to install in the background or not. Defaults to true.
\return true on successful install, false on failure.
*/
- bool DoInstall(const ADDON::AddonPtr &addon, const std::string &hash = "", bool update = false, const std::string &referer = "", bool background = true, bool modal = false);
+ bool DoInstall(const ADDON::AddonPtr &addon, const std::string &hash = "", bool background = true, bool modal = false);
/*! \brief Check whether dependencies of an addon exist or are installable.
Iterates through the addon's dependencies, checking they're installed or installable.
@@ -153,15 +149,10 @@ private:
class CAddonInstallJob : public CFileOperationJob
{
public:
- CAddonInstallJob(const ADDON::AddonPtr &addon, const std::string &hash = "", bool update = false, const std::string &referer = "");
+ CAddonInstallJob(const ADDON::AddonPtr &addon, const std::string &hash = "");
virtual bool DoWork();
- /*! \brief return the id of the addon being installed
- \return id of the installing addon
- */
- std::string AddonID() const;
-
/*! \brief Find which repository hosts an add-on
* \param addon The add-on to find the repository for
* \return The hosting repository
@@ -199,7 +190,6 @@ private:
ADDON::AddonPtr m_addon;
std::string m_hash;
bool m_update;
- std::string m_referer;
};
class CAddonUnInstallJob : public CFileOperationJob
diff --git a/xbmc/addons/GUIDialogAddonInfo.cpp b/xbmc/addons/GUIDialogAddonInfo.cpp
index 17657f727c..b16e85c3b2 100644
--- a/xbmc/addons/GUIDialogAddonInfo.cpp
+++ b/xbmc/addons/GUIDialogAddonInfo.cpp
@@ -197,14 +197,16 @@ void CGUIDialogAddonInfo::UpdateControls()
void CGUIDialogAddonInfo::OnUpdate()
{
- std::string referer = StringUtils::Format("Referer=%s-%s.zip",m_localAddon->ID().c_str(),m_localAddon->Version().asString().c_str());
- CAddonInstaller::GetInstance().Install(m_addon->ID(), true, referer); // force install
+ CAddonInstaller::GetInstance().InstallOrUpdate(m_addon->ID());
Close();
}
void CGUIDialogAddonInfo::OnInstall()
{
- CAddonInstaller::GetInstance().Install(m_addon->ID());
+ if (!g_passwordManager.CheckMenuLock(WINDOW_ADDON_BROWSER))
+ return;
+
+ CAddonInstaller::GetInstance().InstallOrUpdate(m_addon->ID());
Close();
}
diff --git a/xbmc/addons/IAddon.h b/xbmc/addons/IAddon.h
index 029da0633d..48f0ed5511 100644
--- a/xbmc/addons/IAddon.h
+++ b/xbmc/addons/IAddon.h
@@ -127,7 +127,7 @@ namespace ADDON
virtual void OnPostInstall(bool update, bool modal) =0;
virtual void OnPreUnInstall() =0;
virtual void OnPostUnInstall() =0;
- virtual bool CanInstall(const std::string& referer) =0;
+ virtual bool CanInstall() =0;
protected:
virtual bool LoadSettings(bool bForce = false) =0;
diff --git a/xbmc/addons/ImageResource.cpp b/xbmc/addons/ImageResource.cpp
index 79b55646ce..e2bf64d49e 100644
--- a/xbmc/addons/ImageResource.cpp
+++ b/xbmc/addons/ImageResource.cpp
@@ -56,6 +56,10 @@ void CImageResource::OnPreUnInstall()
bool CImageResource::IsAllowed(const std::string &file) const
{
+ // check if the file path points to a directory
+ if (URIUtils::HasSlashAtEnd(file, true))
+ return true;
+
std::string ext = URIUtils::GetExtension(file);
return file.empty() ||
StringUtils::EqualsNoCase(ext, ".png") ||
diff --git a/xbmc/addons/LanguageResource.cpp b/xbmc/addons/LanguageResource.cpp
index 10f570e724..b3c6f986bf 100644
--- a/xbmc/addons/LanguageResource.cpp
+++ b/xbmc/addons/LanguageResource.cpp
@@ -21,11 +21,15 @@
#include "LangInfo.h"
#include "addons/AddonManager.h"
#include "dialogs/GUIDialogKaiToast.h"
-#include "dialogs/GUIDialogYesNo.h"
#include "guilib/GUIWindowManager.h"
#include "settings/Settings.h"
#include "utils/StringUtils.h"
#include "utils/Variant.h"
+#include "messaging/helpers/DialogHelper.h"
+
+using namespace KODI::MESSAGING;
+
+using KODI::MESSAGING::HELPERS::DialogResponse;
#define LANGUAGE_ADDON_PREFIX "resource.language."
@@ -109,7 +113,8 @@ bool CLanguageResource::IsInUse() const
void CLanguageResource::OnPostInstall(bool update, bool modal)
{
if (IsInUse() ||
- (!update && !modal && CGUIDialogYesNo::ShowAndGetInput(CVariant{Name()}, CVariant{24132})))
+ (!update && !modal &&
+ (HELPERS::ShowYesNoDialogText(CVariant{Name()}, CVariant{24132}) == DialogResponse::YES)))
{
CGUIDialogKaiToast *toast = (CGUIDialogKaiToast *)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST);
if (toast)
diff --git a/xbmc/addons/Repository.cpp b/xbmc/addons/Repository.cpp
index ceeaac9b58..8e4b10f733 100644
--- a/xbmc/addons/Repository.cpp
+++ b/xbmc/addons/Repository.cpp
@@ -30,6 +30,7 @@
#include "dialogs/GUIDialogKaiToast.h"
#include "filesystem/File.h"
#include "filesystem/Directory.h"
+#include "messaging/helpers/DialogHelper.h"
#include "settings/Settings.h"
#include "utils/log.h"
#include "utils/JobManager.h"
@@ -43,6 +44,9 @@
using namespace XFILE;
using namespace ADDON;
+using namespace KODI::MESSAGING;
+
+using KODI::MESSAGING::HELPERS::DialogResponse;
AddonPtr CRepository::Clone() const
{
@@ -249,12 +253,12 @@ bool CRepositoryUpdateJob::DoWork()
//unnecessary HEAD requests being sent to server. icons and fanart rarely
//change, and cannot change if there is no version bump.
{
- CTextureDatabase textureDB;
- textureDB.Open();
- textureDB.BeginMultipleExecute();
+ CTextureDatabase textureDB;
+ textureDB.Open();
+ textureDB.BeginMultipleExecute();
for (const auto& addon : addons)
- {
+ {
if (!addon->Props().fanart.empty())
textureDB.InvalidateCachedTexture(addon->Props().fanart);
if (!addon->Props().icon.empty())
@@ -288,11 +292,14 @@ bool CRepositoryUpdateJob::DoWork()
if (!addon->Props().broken.empty() && !brokenInDb)
{
//newly broken
- std::string line = g_localizeStrings.Get(24096);
+ int line = 24096;
if (addon->Props().broken == "DEPSNOTMET")
- line = g_localizeStrings.Get(24104);
- if (CGUIDialogYesNo::ShowAndGetInput(CVariant{addon->Name()}, CVariant{line}, CVariant{24097}, CVariant{""}))
+ line = 24104;
+ if (HELPERS::ShowYesNoDialogLines(CVariant{addon->Name()}, CVariant{line}, CVariant{24097}, CVariant{""})
+ == DialogResponse::YES)
+ {
CAddonMgr::GetInstance().DisableAddon(addon->ID());
+ }
CLog::Log(LOGDEBUG, "CRepositoryUpdateJob[%s] addon '%s' marked broken. reason: \"%s\"",
m_repo->ID().c_str(), addon->ID().c_str(), addon->Props().broken.c_str());
@@ -304,8 +311,8 @@ bool CRepositoryUpdateJob::DoWork()
//Unbroken
CLog::Log(LOGDEBUG, "CRepositoryUpdateJob[%s] addon '%s' unbroken",
m_repo->ID().c_str(), addon->ID().c_str());
- }
}
+ }
//Update broken status
database.BreakAddon(addon->ID(), addon->Props().broken);
@@ -342,21 +349,21 @@ CRepositoryUpdateJob::FetchStatus CRepositoryUpdateJob::FetchIfChanged(const std
if (oldChecksum == checksum && !oldChecksum.empty())
return STATUS_NOT_MODIFIED;
- std::map<std::string, AddonPtr> uniqueAddons;
+ std::map<std::string, AddonPtr> uniqueAddons;
for (auto it = m_repo->m_dirs.cbegin(); it != m_repo->m_dirs.cend(); ++it)
- {
+ {
if (ShouldCancel(m_repo->m_dirs.size() + std::distance(m_repo->m_dirs.cbegin(), it), total))
return STATUS_ERROR;
- VECADDONS addons;
- if (!CRepository::Parse(*it, addons))
+ VECADDONS addons;
+ if (!CRepository::Parse(*it, addons))
{
CLog::Log(LOGERROR, "CRepositoryUpdateJob[%s] failed to read or parse "
"directory '%s'", m_repo->ID().c_str(), it->info.c_str());
return STATUS_ERROR;
+ }
+ MergeAddons(uniqueAddons, addons);
}
- MergeAddons(uniqueAddons, addons);
- }
for (const auto& kv : uniqueAddons)
addons.push_back(kv.second);
diff --git a/xbmc/addons/Skin.cpp b/xbmc/addons/Skin.cpp
index e53a3228f2..0f964b4c15 100644
--- a/xbmc/addons/Skin.cpp
+++ b/xbmc/addons/Skin.cpp
@@ -22,13 +22,14 @@
#include "AddonManager.h"
#include "Util.h"
#include "dialogs/GUIDialogKaiToast.h"
-#include "dialogs/GUIDialogYesNo.h"
// fallback for new skin resolution code
#include "filesystem/Directory.h"
#include "filesystem/File.h"
#include "filesystem/SpecialProtocol.h"
#include "guilib/GUIWindowManager.h"
#include "guilib/WindowIDs.h"
+#include "messaging/ApplicationMessenger.h"
+#include "messaging/helpers/DialogHelper.h"
#include "settings/Settings.h"
#include "settings/lib/Setting.h"
#include "utils/log.h"
@@ -36,7 +37,6 @@
#include "utils/URIUtils.h"
#include "utils/XMLUtils.h"
#include "utils/Variant.h"
-#include "messaging/ApplicationMessenger.h"
#define XML_SETTINGS "settings"
#define XML_SETTING "setting"
@@ -47,6 +47,8 @@
using namespace XFILE;
using namespace KODI::MESSAGING;
+using KODI::MESSAGING::HELPERS::DialogResponse;
+
std::shared_ptr<ADDON::CSkinInfo> g_SkinInfo;
namespace ADDON
@@ -372,7 +374,8 @@ void CSkinInfo::OnPreInstall()
void CSkinInfo::OnPostInstall(bool update, bool modal)
{
- if (IsInUse() || (!update && !modal && CGUIDialogYesNo::ShowAndGetInput(CVariant{Name()}, CVariant{24099})))
+ if (IsInUse() || (!update && !modal &&
+ HELPERS::ShowYesNoDialogText(CVariant{Name()}, CVariant{24099}) == DialogResponse::YES))
{
CGUIDialogKaiToast *toast = (CGUIDialogKaiToast *)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST);
if (toast)
diff --git a/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSP.cpp b/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSP.cpp
index 02335f7450..2f5d6d7d47 100644
--- a/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSP.cpp
+++ b/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSP.cpp
@@ -31,7 +31,6 @@ extern "C" {
#include "cores/AudioEngine/Utils/AEUtil.h"
#include "Application.h"
-#include "messaging/ApplicationMessenger.h"
#include "guiinfo/GUIInfoLabels.h"
#include "GUIUserMessages.h"
#include "addons/AddonInstaller.h"
@@ -39,8 +38,9 @@ extern "C" {
#include "dialogs/GUIDialogOK.h"
#include "dialogs/GUIDialogSelect.h"
#include "dialogs/GUIDialogKaiToast.h"
-#include "dialogs/GUIDialogYesNo.h"
#include "guilib/GUIWindowManager.h"
+#include "messaging/ApplicationMessenger.h"
+#include "messaging/helpers/DialogHelper.h"
#include "settings/AdvancedSettings.h"
#include "settings/MediaSettings.h"
#include "settings/MediaSourceSettings.h"
@@ -53,6 +53,8 @@ using namespace ADDON;
using namespace ActiveAE;
using namespace KODI::MESSAGING;
+using KODI::MESSAGING::HELPERS::DialogResponse;
+
#define MIN_DSP_ARRAY_SIZE 4096
/*! @name Master audio dsp control class */
@@ -257,16 +259,16 @@ bool CActiveAEDSP::InstallAddonAllowed(const std::string &strAddonId) const
m_usedProcessesCnt == 0;
}
-void CActiveAEDSP::MarkAsOutdated(const std::string& strAddonId, const std::string& strReferer)
+void CActiveAEDSP::MarkAsOutdated(const std::string& strAddonId)
{
if (IsActivated() && CSettings::GetInstance().GetInt(CSettings::SETTING_GENERAL_ADDONUPDATES) == AUTO_UPDATES_ON)
{
CSingleLock lock(m_critSection);
- m_outdatedAddons.insert(make_pair(strAddonId, strReferer));
+ m_outdatedAddons.push_back(strAddonId);
}
}
-bool CActiveAEDSP::HasOutdatedAddons(std::map<std::string, std::string> &outdatedAddons)
+bool CActiveAEDSP::HasOutdatedAddons(std::vector<std::string> &outdatedAddons)
{
CSingleLock lock(m_critSection);
if (!m_outdatedAddons.empty())
@@ -330,7 +332,8 @@ void CActiveAEDSP::OnSettingAction(const CSetting *setting)
}
else if (settingId == CSettings::SETTING_AUDIOOUTPUT_DSPRESETDB)
{
- if (CGUIDialogYesNo::ShowAndGetInput(19098, 36440, 750, 0))
+ if (HELPERS::ShowYesNoDialogLines(CVariant{19098}, CVariant{36440}, CVariant{750}) ==
+ DialogResponse::YES)
{
CDateTime::ResetTimezoneBias();
ResetDatabase();
diff --git a/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSP.h b/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSP.h
index fc79aca3f1..bf9593b076 100644
--- a/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSP.h
+++ b/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSP.h
@@ -122,16 +122,15 @@ namespace ActiveAE
/*!
* @brief Mark an add-on as outdated so it will be upgrade when it's possible again
* @param strAddonId The add-on to mark as outdated
- * @param strReferer The referer to use when downloading
*/
- void MarkAsOutdated(const std::string& strAddonId, const std::string& strReferer);
+ void MarkAsOutdated(const std::string& strAddonId);
/*!
* @brief Mark an add-on as outdated so it will be upgrade when it's possible again
* @param outdatedAddons The generated list of outdated add-on's
* @return True when outdated addons are present.
*/
- bool HasOutdatedAddons(std::map<std::string, std::string> &outdatedAddons);
+ bool HasOutdatedAddons(std::vector<std::string> &outdatedAddons);
/*!
* @brief Get the audio dsp database pointer.
@@ -468,7 +467,7 @@ namespace ActiveAE
unsigned int m_activeProcessId; /*!< The currently active audio stream id of a playing file source */
bool m_isValidAudioDSPSettings; /*!< if settings load was successfull it becomes true */
AE_DSP_MODELIST m_modes[AE_DSP_MODE_TYPE_MAX]; /*!< list of currently used dsp processing calls */
- std::map<std::string, std::string> m_outdatedAddons;
+ std::vector<std::string> m_outdatedAddons;
};
//@}
}
diff --git a/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPAddon.cpp b/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPAddon.cpp
index 7656616f6e..e94ae5cce9 100644
--- a/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPAddon.cpp
+++ b/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPAddon.cpp
@@ -101,14 +101,14 @@ void CActiveAEDSPAddon::OnPostUnInstall()
CActiveAEDSP::GetInstance().Activate(true);
}
-bool CActiveAEDSPAddon::CanInstall(const std::string &referer)
+bool CActiveAEDSPAddon::CanInstall()
{
if (!CActiveAEDSP::GetInstance().InstallAddonAllowed(ID()))
{
- CActiveAEDSP::GetInstance().MarkAsOutdated(ID(), referer);
+ CActiveAEDSP::GetInstance().MarkAsOutdated(ID());
return false;
}
- return CAddon::CanInstall(referer);
+ return CAddon::CanInstall();
}
void CActiveAEDSPAddon::ResetProperties(int iClientId /* = AE_DSP_INVALID_ADDON_ID */)
diff --git a/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPAddon.h b/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPAddon.h
index cfdf1e0ab2..e4f63459b9 100644
--- a/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPAddon.h
+++ b/xbmc/cores/AudioEngine/DSPAddons/ActiveAEDSPAddon.h
@@ -51,7 +51,7 @@ namespace ActiveAE
virtual void OnPostInstall(bool restart, bool update);
virtual void OnPreUnInstall();
virtual void OnPostUnInstall();
- virtual bool CanInstall(const std::string &referer);
+ virtual bool CanInstall();
/** @name Audio DSP add-on methods */
//@{
diff --git a/xbmc/cores/DllLoader/SoLoader.cpp b/xbmc/cores/DllLoader/SoLoader.cpp
index 717ce66fc2..e337b38199 100644
--- a/xbmc/cores/DllLoader/SoLoader.cpp
+++ b/xbmc/cores/DllLoader/SoLoader.cpp
@@ -72,7 +72,6 @@ bool SoLoader::Load()
void SoLoader::Unload()
{
- CLog::Log(LOGDEBUG, "Unloading: %s\n", GetName());
if (m_soHandle)
{
diff --git a/xbmc/cores/IPlayer.h b/xbmc/cores/IPlayer.h
index f940f57461..c4eea294e2 100644
--- a/xbmc/cores/IPlayer.h
+++ b/xbmc/cores/IPlayer.h
@@ -141,6 +141,7 @@ public:
virtual bool IsPaused() const = 0;
virtual bool HasVideo() const = 0;
virtual bool HasAudio() const = 0;
+ virtual bool HasRDS() const { return false; }
virtual bool IsPassthrough() const { return false;}
virtual bool CanSeek() {return true;}
virtual void Seek(bool bPlus = true, bool bLargeStep = false, bool bChapterOverride = false) = 0;
@@ -185,6 +186,8 @@ public:
virtual TextCacheStruct_t* GetTeletextCache() { return NULL; };
virtual void LoadPage(int p, int sp, unsigned char* buffer) {};
+ virtual std::string GetRadioText(unsigned int line) { return ""; };
+
virtual int GetChapterCount() { return 0; }
virtual int GetChapter() { return -1; }
virtual void GetChapterName(std::string& strChapterName, int chapterIdx = -1) { return; }
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayCodecSSA.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayCodecSSA.cpp
index 83603a8f12..a955e9f072 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayCodecSSA.cpp
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayCodecSSA.cpp
@@ -19,15 +19,15 @@
*/
#include "DVDOverlayCodecSSA.h"
+#include <memory>
+
#include "DVDOverlaySSA.h"
#include "DVDStreamInfo.h"
#include "DVDCodecs/DVDCodecs.h"
#include "DVDClock.h"
#include "Util.h"
-#include "utils/AutoPtrHandle.h"
#include "utils/StringUtils.h"
-using namespace AUTOPTR;
CDVDOverlayCodecSSA::CDVDOverlayCodecSSA() : CDVDOverlayCodec("SSA Subtitle Decoder")
{
@@ -90,7 +90,7 @@ int CDVDOverlayCodecSSA::Decode(DemuxPacket *pPacket)
{
line = lines[i];
StringUtils::Trim(line);
- auto_aptr<char> layer(new char[line.length()+1]);
+ std::unique_ptr<char[]> layer(new char[line.length() + 1]);
if(sscanf(line.c_str(), "%*[^:]:%[^,],%d:%d:%d%*c%d,%d:%d:%d%*c%d"
, layer.get(), &sh, &sm, &ss, &sc, &eh,&em, &es, &ec) != 9)
diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.cpp
index dfdbe6dc48..0b687e3333 100644
--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.cpp
+++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.cpp
@@ -25,6 +25,11 @@ void CDemuxStreamTeletext::GetStreamInfo(std::string& strInfo)
strInfo = "Teletext Data Stream";
}
+void CDemuxStreamRadioRDS::GetStreamInfo(std::string& strInfo)
+{
+ strInfo = "Radio Data Stream (RDS)";
+}
+
void CDemuxStreamAudio::GetStreamType(std::string& strInfo)
{
char sInfo[64];
@@ -110,6 +115,19 @@ int CDVDDemux::GetNrOfTeletextStreams()
return iCounter;
}
+const int CDVDDemux::GetNrOfRadioRDSStreams()
+{
+ int iCounter = 0;
+
+ for (int i = 0; i < GetNrOfStreams(); i++)
+ {
+ CDemuxStream* pStream = GetStream(i);
+ if (pStream->type == STREAM_RADIO_RDS) iCounter++;
+ }
+
+ return iCounter;
+}
+
CDemuxStreamAudio* CDVDDemux::GetStreamFromAudioId(int iAudioIndex)
{
int counter = -1;
@@ -166,6 +184,20 @@ CDemuxStreamTeletext* CDVDDemux::GetStreamFromTeletextId(int iTeletextIndex)
return NULL;
}
+const CDemuxStreamRadioRDS* CDVDDemux::GetStreamFromRadioRDSId(int iRadioRDSIndex)
+{
+ int counter = -1;
+ for (int i = 0; i < GetNrOfStreams(); i++)
+ {
+ CDemuxStream* pStream = GetStream(i);
+
+ if (pStream->type == STREAM_RADIO_RDS) counter++;
+ if (iRadioRDSIndex == counter)
+ return (CDemuxStreamRadioRDS*)pStream;
+ }
+ return NULL;
+}
+
void CDemuxStream::GetStreamName( std::string& strInfo )
{
strInfo = "";
diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.h b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.h
index fca164d601..76f79321cf 100644
--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.h
+++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.h
@@ -52,7 +52,8 @@ enum StreamType
STREAM_VIDEO, // video stream
STREAM_DATA, // data stream
STREAM_SUBTITLE,// subtitle stream
- STREAM_TELETEXT // Teletext data stream
+ STREAM_TELETEXT, // Teletext data stream
+ STREAM_RADIO_RDS // Radio RDS data stream
};
enum StreamSource {
@@ -223,6 +224,16 @@ public:
virtual void GetStreamInfo(std::string& strInfo);
};
+class CDemuxStreamRadioRDS : public CDemuxStream
+{
+public:
+ CDemuxStreamRadioRDS() : CDemuxStream()
+ {
+ type = STREAM_RADIO_RDS;
+ }
+ virtual void GetStreamInfo(std::string& strInfo);
+};
+
class CDVDDemux
{
public:
@@ -333,6 +344,11 @@ public:
int GetNrOfTeletextStreams();
/*
+ * return nr of rds streams, 0 if none
+ */
+ const int GetNrOfRadioRDSStreams();
+
+ /*
* return the audio stream, or NULL if it does not exist
*/
CDemuxStreamAudio* GetStreamFromAudioId(int iAudioIndex);
@@ -353,6 +369,11 @@ public:
CDemuxStreamTeletext* GetStreamFromTeletextId(int iTeletextIndex);
/*
+ * return the rds stream, or NULL if it does not exist
+ */
+ const CDemuxStreamRadioRDS* GetStreamFromRadioRDSId(int iRadioRDSIndex);
+
+ /*
* return a user-presentable codec name of the given stream
*/
virtual void GetStreamCodecName(int iStreamId, std::string &strName) {};
diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
index 99debc993b..325057a942 100644
--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
+++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
@@ -1297,7 +1297,7 @@ CDemuxStream* CDVDDemuxFFmpeg::AddStream(int iId)
if (langTag)
strncpy(stream->language, langTag->value, 3);
- if( pStream->codec->extradata && pStream->codec->extradata_size > 0 )
+ if( stream->type != STREAM_NONE && pStream->codec->extradata && pStream->codec->extradata_size > 0 )
{
stream->ExtraSize = pStream->codec->extradata_size;
stream->ExtraData = new uint8_t[pStream->codec->extradata_size];
diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp
index 4ed2d5c428..f5319dc853 100644
--- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp
+++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp
@@ -24,6 +24,7 @@
#include "utils/log.h"
#include "pvr/PVRManager.h"
#include "pvr/addons/PVRClients.h"
+#include "settings/Settings.h"
#include "../DVDClock.h"
#define FF_MAX_EXTRADATA_SIZE ((1 << 28) - FF_INPUT_BUFFER_PADDING_SIZE)
@@ -384,6 +385,19 @@ void CDVDDemuxPVRClient::RequestStreams()
if (!m_streams[i])
m_streams[i] = new CDemuxStreamTeletext();
}
+ else if (props.stream[i].iCodecType == XBMC_CODEC_TYPE_RDS &&
+ CSettings::GetInstance().GetBool("pvrplayback.enableradiords"))
+ {
+ CDemuxStreamRadioRDS* st = NULL;
+ if (stm)
+ {
+ st = dynamic_cast<CDemuxStreamRadioRDS*>(stm);
+ if (!st || (st->codec != (AVCodecID)props.stream[i].iCodecId))
+ DisposeStream(i);
+ }
+ if (!m_streams[i])
+ m_streams[i] = new CDemuxStreamRadioRDS();
+ }
else if (props.stream[i].iCodecType == XBMC_CODEC_TYPE_SUBTITLE)
{
CDemuxStreamSubtitlePVRClient* st = NULL;
diff --git a/xbmc/cores/dvdplayer/DVDMessageQueue.cpp b/xbmc/cores/dvdplayer/DVDMessageQueue.cpp
index e4b3efe75a..b2239e9309 100644
--- a/xbmc/cores/dvdplayer/DVDMessageQueue.cpp
+++ b/xbmc/cores/dvdplayer/DVDMessageQueue.cpp
@@ -157,7 +157,7 @@ MsgQueueReturnCode CDVDMessageQueue::Get(CDVDMsg** pMsg, unsigned int iTimeoutIn
return MSGQ_NOT_INITIALIZED;
}
- if(m_list.empty() && m_bEmptied == false && priority == 0 && m_owner != "teletext")
+ if(m_list.empty() && m_bEmptied == false && priority == 0 && m_owner != "teletext" && m_owner != "rds")
{
#if !defined(TARGET_RASPBERRY_PI)
CLog::Log(LOGWARNING, "CDVDMessageQueue(%s)::Get - asked for new data packet, with nothing available", m_owner.c_str());
diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp
index 72ffc85a4e..5a838fda52 100644
--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp
+++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp
@@ -20,6 +20,7 @@
#include "system.h"
#include "DVDPlayer.h"
+#include "DVDPlayerRadioRDS.h"
#include "DVDInputStreams/DVDInputStream.h"
#include "DVDInputStreams/DVDFactoryInputStream.h"
@@ -376,6 +377,8 @@ int CSelectionStreams::IndexOf(StreamType type, CDVDPlayer& p) const
return IndexOf(type, p.m_CurrentSubtitle.source, p.m_CurrentSubtitle.id);
else if(type == STREAM_TELETEXT)
return IndexOf(type, p.m_CurrentTeletext.source, p.m_CurrentTeletext.id);
+ else if(type == STREAM_RADIO_RDS)
+ return IndexOf(type, p.m_CurrentRadioRDS.source, p.m_CurrentRadioRDS.id);
return -1;
}
@@ -557,6 +560,7 @@ void CDVDPlayer::CreatePlayers()
}
m_dvdPlayerSubtitle = new CDVDPlayerSubtitle(&m_overlayContainer);
m_dvdPlayerTeletext = new CDVDTeletextData();
+ m_dvdPlayerRadioRDS = new CDVDRadioRDSData();
m_players_created = true;
}
@@ -568,6 +572,7 @@ void CDVDPlayer::DestroyPlayers()
delete m_dvdPlayerAudio;
delete m_dvdPlayerSubtitle;
delete m_dvdPlayerTeletext;
+ delete m_dvdPlayerRadioRDS;
m_players_created = false;
}
@@ -578,6 +583,7 @@ CDVDPlayer::CDVDPlayer(IPlayerCallback& callback)
m_CurrentVideo(STREAM_VIDEO, DVDPLAYER_VIDEO),
m_CurrentSubtitle(STREAM_SUBTITLE, DVDPLAYER_SUBTITLE),
m_CurrentTeletext(STREAM_TELETEXT, DVDPLAYER_TELETEXT),
+ m_CurrentRadioRDS(STREAM_RADIO_RDS, DVDPLAYER_RDS),
m_messenger("player"),
m_ready(true),
m_DemuxerPausePending(false)
@@ -719,6 +725,7 @@ void CDVDPlayer::OnStartup()
m_CurrentAudio.Clear();
m_CurrentSubtitle.Clear();
m_CurrentTeletext.Clear();
+ m_CurrentRadioRDS.Clear();
m_messenger.Init();
@@ -913,6 +920,17 @@ void CDVDPlayer::OpenDefaultStreams(bool reset)
}
if(!valid)
CloseStream(m_CurrentTeletext, false);
+
+ // open RDS stream
+ streams = m_SelectionStreams.Get(STREAM_RADIO_RDS);
+ valid = false;
+ for(SelectionStreams::iterator it = streams.begin(); it != streams.end() && !valid; ++it)
+ {
+ if(OpenStream(m_CurrentRadioRDS, it->id, it->source))
+ valid = true;
+ }
+ if(!valid)
+ CloseStream(m_CurrentRadioRDS, false);
}
bool CDVDPlayer::ReadPacket(DemuxPacket*& packet, CDemuxStream*& stream)
@@ -1404,11 +1422,14 @@ void CDVDPlayer::Process()
m_dvdPlayerSubtitle->SendMessage(new CDVDMsg(CDVDMsg::GENERAL_EOF));
if(m_CurrentTeletext.inited)
m_dvdPlayerTeletext->SendMessage(new CDVDMsg(CDVDMsg::GENERAL_EOF));
+ if(m_CurrentRadioRDS.inited)
+ m_dvdPlayerRadioRDS->SendMessage(new CDVDMsg(CDVDMsg::GENERAL_EOF));
m_CurrentAudio.inited = false;
m_CurrentVideo.inited = false;
m_CurrentSubtitle.inited = false;
m_CurrentTeletext.inited = false;
+ m_CurrentRadioRDS.inited = false;
// if we are caching, start playing it again
SetCaching(CACHESTATE_DONE);
@@ -1435,6 +1456,7 @@ void CDVDPlayer::Process()
m_CurrentVideo.started = false;
m_CurrentSubtitle.started = false;
m_CurrentTeletext.started = false;
+ m_CurrentRadioRDS.started = false;
break;
}
@@ -1447,6 +1469,7 @@ void CDVDPlayer::Process()
CheckBetterStream(m_CurrentVideo, pStream);
CheckBetterStream(m_CurrentSubtitle, pStream);
CheckBetterStream(m_CurrentTeletext, pStream);
+ CheckBetterStream(m_CurrentRadioRDS, pStream);
// demux video stream
if (CSettings::GetInstance().GetBool(CSettings::SETTING_SUBTITLES_PARSECAPTIONS) && CheckIsCurrent(m_CurrentVideo, pStream, pPacket))
@@ -1527,6 +1550,8 @@ void CDVDPlayer::ProcessPacket(CDemuxStream* pStream, DemuxPacket* pPacket)
ProcessSubData(pStream, pPacket);
else if (CheckIsCurrent(m_CurrentTeletext, pStream, pPacket))
ProcessTeletextData(pStream, pPacket);
+ else if (CheckIsCurrent(m_CurrentRadioRDS, pStream, pPacket))
+ ProcessRadioRDSData(pStream, pPacket);
else
{
pStream->SetDiscard(AVDISCARD_ALL);
@@ -1647,6 +1672,22 @@ void CDVDPlayer::ProcessTeletextData(CDemuxStream* pStream, DemuxPacket* pPacket
m_dvdPlayerTeletext->SendMessage(new CDVDMsgDemuxerPacket(pPacket, drop));
}
+void CDVDPlayer::ProcessRadioRDSData(CDemuxStream* pStream, DemuxPacket* pPacket)
+{
+ CheckStreamChanges(m_CurrentRadioRDS, pStream);
+
+ UpdateTimestamps(m_CurrentRadioRDS, pPacket);
+
+ bool drop = false;
+ if (CheckPlayerInit(m_CurrentRadioRDS))
+ drop = true;
+
+ if (CheckSceneSkip(m_CurrentRadioRDS))
+ drop = true;
+
+ m_dvdPlayerRadioRDS->SendMessage(new CDVDMsgDemuxerPacket(pPacket, drop));
+}
+
bool CDVDPlayer::GetCachingTimes(double& level, double& delay, double& offset)
{
if(!m_pInputStream || !m_pDemuxer)
@@ -1952,6 +1993,8 @@ bool CDVDPlayer::CheckPlayerInit(CCurrentStream& current)
m_CurrentSubtitle.startpts = current.dts;
if(m_CurrentTeletext.startpts != DVD_NOPTS_VALUE)
m_CurrentTeletext.startpts = current.dts;
+ if(m_CurrentRadioRDS.startpts != DVD_NOPTS_VALUE)
+ m_CurrentRadioRDS.startpts = current.dts;
}
if(current.dts < current.startpts)
@@ -2255,6 +2298,8 @@ IDVDStreamPlayer* CDVDPlayer::GetStreamPlayer(unsigned int target)
return m_dvdPlayerSubtitle;
if(target == DVDPLAYER_TELETEXT)
return m_dvdPlayerTeletext;
+ if(target == DVDPLAYER_RDS)
+ return m_dvdPlayerRadioRDS;
return NULL;
}
@@ -2284,6 +2329,7 @@ void CDVDPlayer::OnExit()
CloseStream(m_CurrentSubtitle, false); // clear overlay container
CloseStream(m_CurrentTeletext, !m_bAbortRequest);
+ CloseStream(m_CurrentRadioRDS, !m_bAbortRequest);
// destroy objects
SAFE_DELETE(m_pDemuxer);
@@ -2825,6 +2871,11 @@ bool CDVDPlayer::HasAudio() const
return m_HasAudio;
}
+bool CDVDPlayer::HasRDS() const
+{
+ return m_CurrentRadioRDS.id >= 0;
+}
+
bool CDVDPlayer::IsPassthrough() const
{
return m_dvdPlayerAudio->IsPassthrough();
@@ -3196,6 +3247,14 @@ void CDVDPlayer::LoadPage(int p, int sp, unsigned char* buffer)
return m_dvdPlayerTeletext->LoadPage(p, sp, buffer);
}
+std::string CDVDPlayer::GetRadioText(unsigned int line)
+{
+ if (m_CurrentRadioRDS.id < 0)
+ return "";
+
+ return m_dvdPlayerRadioRDS->GetRadioText(line);
+}
+
void CDVDPlayer::SeekTime(int64_t iTime)
{
int seekOffset = (int)(iTime - GetTime());
@@ -3362,6 +3421,9 @@ bool CDVDPlayer::OpenStream(CCurrentStream& current, int iStream, int source, bo
case STREAM_TELETEXT:
res = OpenTeletextStream(hint);
break;
+ case STREAM_RADIO_RDS:
+ res = OpenRadioRDSStream(hint);
+ break;
default:
res = false;
break;
@@ -3539,6 +3601,17 @@ bool CDVDPlayer::OpenTeletextStream(CDVDStreamInfo& hint)
return true;
}
+bool CDVDPlayer::OpenRadioRDSStream(CDVDStreamInfo& hint)
+{
+ if (!m_dvdPlayerRadioRDS->CheckStream(hint))
+ return false;
+
+ if(!OpenStreamPlayer(m_CurrentRadioRDS, hint, true))
+ return false;
+
+ return true;
+}
+
bool CDVDPlayer::CloseStream(CCurrentStream& current, bool bWaitForBuffers)
{
if (current.id < 0)
@@ -3616,6 +3689,10 @@ void CDVDPlayer::FlushBuffers(bool queued, double pts, bool accurate, bool sync)
m_CurrentTeletext.dts = DVD_NOPTS_VALUE;
m_CurrentTeletext.startpts = startpts;
+ m_CurrentRadioRDS.inited = false;
+ m_CurrentRadioRDS.dts = DVD_NOPTS_VALUE;
+ m_CurrentRadioRDS.startpts = startpts;
+
if(queued)
{
m_dvdPlayerAudio->SendMessage(new CDVDMsg(CDVDMsg::GENERAL_RESET));
@@ -3623,6 +3700,7 @@ void CDVDPlayer::FlushBuffers(bool queued, double pts, bool accurate, bool sync)
m_dvdPlayerVideo->SendMessage(new CDVDMsg(CDVDMsg::VIDEO_NOSKIP));
m_dvdPlayerSubtitle->SendMessage(new CDVDMsg(CDVDMsg::GENERAL_RESET));
m_dvdPlayerTeletext->SendMessage(new CDVDMsg(CDVDMsg::GENERAL_RESET));
+ m_dvdPlayerRadioRDS->SendMessage(new CDVDMsg(CDVDMsg::GENERAL_RESET));
SynchronizePlayers(SYNCSOURCE_ALL);
}
else
@@ -3631,6 +3709,7 @@ void CDVDPlayer::FlushBuffers(bool queued, double pts, bool accurate, bool sync)
m_dvdPlayerVideo->Flush();
m_dvdPlayerSubtitle->Flush();
m_dvdPlayerTeletext->Flush();
+ m_dvdPlayerRadioRDS->Flush();
// clear subtitle and menu overlays
m_overlayContainer.Clear();
@@ -3654,6 +3733,7 @@ void CDVDPlayer::FlushBuffers(bool queued, double pts, bool accurate, bool sync)
m_CurrentVideo.started = false;
m_CurrentSubtitle.started = false;
m_CurrentTeletext.started = false;
+ m_CurrentRadioRDS.started = false;
}
if(pts != DVD_NOPTS_VALUE && sync)
diff --git a/xbmc/cores/dvdplayer/DVDPlayer.h b/xbmc/cores/dvdplayer/DVDPlayer.h
index ab6a228683..1e5f6c9e95 100644
--- a/xbmc/cores/dvdplayer/DVDPlayer.h
+++ b/xbmc/cores/dvdplayer/DVDPlayer.h
@@ -30,6 +30,7 @@
#include "DVDPlayerVideo.h"
#include "DVDPlayerSubtitle.h"
#include "DVDPlayerTeletext.h"
+#include "DVDPlayerRadioRDS.h"
#include "Edl.h"
#include "FileItem.h"
@@ -209,6 +210,7 @@ public:
#define DVDPLAYER_VIDEO 2
#define DVDPLAYER_SUBTITLE 3
#define DVDPLAYER_TELETEXT 4
+#define DVDPLAYER_RDS 5
class CDVDPlayer : public IPlayer, public CThread, public IDVDPlayer
{
@@ -222,6 +224,7 @@ public:
virtual bool IsPaused() const;
virtual bool HasVideo() const;
virtual bool HasAudio() const;
+ virtual bool HasRDS() const;
virtual bool IsPassthrough() const;
virtual bool CanSeek();
virtual void Seek(bool bPlus, bool bLargeStep, bool bChapterOverride);
@@ -260,6 +263,8 @@ public:
virtual TextCacheStruct_t* GetTeletextCache();
virtual void LoadPage(int p, int sp, unsigned char* buffer);
+ virtual std::string GetRadioText(unsigned int line);
+
virtual int GetChapterCount();
virtual int GetChapter();
virtual void GetChapterName(std::string& strChapterName, int chapterIdx=-1);
@@ -320,6 +325,7 @@ protected:
bool OpenVideoStream(CDVDStreamInfo& hint, bool reset = true);
bool OpenSubtitleStream(CDVDStreamInfo& hint);
bool OpenTeletextStream(CDVDStreamInfo& hint);
+ bool OpenRadioRDSStream(CDVDStreamInfo& hint);
/** \brief Switches forced subtitles to forced subtitles matching the language of the current audio track.
* If these are not available, subtitles are disabled.
@@ -334,6 +340,7 @@ protected:
void ProcessVideoData(CDemuxStream* pStream, DemuxPacket* pPacket);
void ProcessSubData(CDemuxStream* pStream, DemuxPacket* pPacket);
void ProcessTeletextData(CDemuxStream* pStream, DemuxPacket* pPacket);
+ void ProcessRadioRDSData(CDemuxStream* pStream, DemuxPacket* pPacket);
bool ShowPVRChannelInfo();
@@ -402,6 +409,7 @@ protected:
CCurrentStream m_CurrentVideo;
CCurrentStream m_CurrentSubtitle;
CCurrentStream m_CurrentTeletext;
+ CCurrentStream m_CurrentRadioRDS;
CSelectionStreams m_SelectionStreams;
@@ -423,6 +431,7 @@ protected:
IDVDStreamPlayerAudio *m_dvdPlayerAudio; // audio part
CDVDPlayerSubtitle *m_dvdPlayerSubtitle; // subtitle part
CDVDTeletextData *m_dvdPlayerTeletext; // teletext part
+ CDVDRadioRDSData *m_dvdPlayerRadioRDS; // rds part
CDVDClock m_clock; // master clock
CDVDOverlayContainer m_overlayContainer;
diff --git a/xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp b/xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
new file mode 100644
index 0000000000..7f2b89d5eb
--- /dev/null
+++ b/xbmc/cores/dvdplayer/DVDPlayerRadioRDS.cpp
@@ -0,0 +1,1748 @@
+/*
+ * Copyright (C) 2005-2015 Team KODI
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this Software; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+//#define RDS_IMPROVE_CHECK 1
+
+/*
+ * The RDS decoder bases partly on the source of the VDR radio plugin.
+ * http://www.egal-vdr.de/plugins/
+ * and reworked a bit with references from SPB 490, IEC62106
+ * and several other documents.
+ *
+ * A lot more information is sendet which is currently unused and partly
+ * not required.
+ */
+
+#include "Application.h"
+#include "DVDClock.h"
+#include "DVDStreamInfo.h"
+#include "GUIInfoManager.h"
+#include "GUIUserMessages.h"
+#include "DVDCodecs/DVDCodecs.h"
+#include "DVDCodecs/DVDFactoryCodec.h"
+#include "DVDCodecs/Video/DVDVideoCodecFFmpeg.h"
+#include "DVDDemuxers/DVDDemuxUtils.h"
+#include "DVDDemuxers/DVDFactoryDemuxer.h"
+#include "DVDInputStreams/DVDInputStream.h"
+#include "DVDInputStreams/DVDFactoryInputStream.h"
+#include "cores/FFmpeg.h"
+#include "dialogs/GUIDialogKaiToast.h"
+#include "filesystem/Directory.h"
+#include "filesystem/File.h"
+#include "filesystem/SpecialProtocol.h"
+#include "guilib/GUIWindowManager.h"
+#include "guilib/LocalizeStrings.h"
+#include "interfaces/AnnouncementManager.h"
+#include "messaging/ApplicationMessenger.h"
+#include "music/tags/MusicInfoTag.h"
+#include "pictures/Picture.h"
+#include "pvr/channels/PVRChannel.h"
+#include "pvr/channels/PVRRadioRDSInfoTag.h"
+#include "settings/Settings.h"
+#include "threads/SingleLock.h"
+#include "utils/CharsetConverter.h"
+#include "utils/StringUtils.h"
+#include "utils/log.h"
+
+#include "DVDPlayerRadioRDS.h"
+
+using namespace XFILE;
+using namespace PVR;
+using namespace KODI::MESSAGING;
+
+/**
+ * Universal Encoder Communication Protocol (UECP)
+ * List of defined commands
+ * iaw.: SPB 490
+ */
+
+/// UECP Message element pointers (different on several commands)
+#define UECP_ME_MEC 0 // Message Element Code
+#define UECP_ME_DSN 1 // Data Set Number
+#define UECP_ME_PSN 2 // Program Service Number
+#define UECP_ME_MEL 3 // Message Element data Length
+#define UECP_ME_DATA 4 //
+
+/// RDS message commands
+#define UECP_RDS_PI 0x01 // Program Identification
+#define UECP_RDS_PS 0x02 // Program Service name
+#define UECP_RDS_PIN 0x06 // Program Item Number
+#define UECP_RDS_DI 0x04 // Decoder Identification and dynamic PTY indicator
+#define UECP_RDS_TA_TP 0x03 // Traffic Announcement identification / Traffic Program identification
+#define UECP_RDS_MS 0x05 // Music/Speech switch
+#define UECP_RDS_PTY 0x07 // Program TYpe
+#define UECP_RDS_PTYN 0x3A // Program TYpe Name
+#define UECP_RDS_RT 0x0A // RadioText
+#define UECP_RDS_AF 0x13 // Alternative Frequencies list
+#define UECP_RDS_EON_AF 0x14 // Enhanced Other Networks information
+#define UECP_SLOW_LABEL_CODES 0x1A // Slow Labeling codes
+#define UECP_LINKAGE_INFO 0x2E // Linkage information
+
+/// Open Data Application commands
+#define UECP_ODA_CONF_SHORT_MSG_CMD 0x40 // ODA configuration and short message command
+#define UECP_ODA_IDENT_GROUP_USAGE_SEQ 0x41 // ODA identification group usage sequence
+#define UECP_ODA_FREE_FORMAT_GROUP 0x42 // ODA free-format group
+#define UECP_ODA_REL_PRIOR_GROUP_SEQ 0x43 // ODA relative priority group sequence
+#define UECP_ODA_BURST_MODE_CONTROL 0x44 // ODA “Burst mode” control
+#define UECP_ODA_SPINN_WHEEL_TIMING_CTL 0x45 // ODA “Spinning Wheel” timing control
+#define UECP_ODA_DATA 0x46 // ODA Data
+#define UECP_ODA_DATA_CMD_ACCESS_RIGHT 0x47 // ODA data command access right
+
+/// DAB
+#define UECP_DAB_DYN_LABEL_CMD 0x48 // DAB: Dynamic Label command
+#define UECP_DAB_DYN_LABEL_MSG 0xAA // DAB: Dynamic Label message (DL)
+
+/// Transparent data commands
+#define UECP_TDC_TDC 0x26 // TDC
+#define UECP_TDC_EWS 0x2B // EWS
+#define UECP_TDC_IH 0x25 // IH
+#define UECP_TDC_TMC 0x30 // TMC
+#define UECP_TDC_FREE_FMT_GROUP 0x24 // Free-format group
+
+/// Paging commands
+#define UECP_PAGING_CALL_WITHOUT_MESSAGE 0x0C
+#define UECP_PAGING_CALL_NUMERIC_MESSAGE_10DIGITS 0x08
+#define UECP_PAGING_CALL_NUMERIC_MESSAGE_18DIGITS 0x20
+#define UECP_PAGING_CALL_ALPHANUMERIC_MESSAGE_80CHARACTERS 0x1B
+#define UECP_INTERNATIONAL_PAGING_NUMERIC_MESSAGE_15DIGITS 0x11
+#define UECP_INTERNATIONAL_PAGING_FUNCTIONS_MESSAGE 0x10
+#define UECP_TRANSMITTER_NETWORK_GROUP_DESIGNATION 0x12
+#define UECP_EPP_TM_INFO 0x31
+#define UECP_EPP_CALL_WITHOUT_ADDITIONAL_MESSAGE 0x32
+#define UECP_EPP_NATIONAL_INTERNATIONAL_CALL_ALPHANUMERIC_MESSAGE 0x33
+#define UECP_EPP_NATIONAL_INTERNATIONAL_CALL_VARIABLE_LENGTH_NUMERIC_MESSAGE 0x34
+#define UECP_EPP_NATIONAL_INTERNATIONAL_CALL_VARIABLE_LENGTH_FUNCTIONS_MESSAGE 0x35
+
+/// Clock setting and control
+#define UECP_CLOCK_RTC 0x0D // Real time clock
+#define UECP_CLOCK_RTC_CORR 0x09 // Real time clock correction
+#define UECP_CLOCK_CT_ON_OFF 0x19 // CT On/Off
+
+/// RDS adjustment and control
+#define RDS_ON_OFF 0x1E
+#define RDS_PHASE 0x22
+#define RDS_LEVEL 0x0E
+
+/// ARI adjustment and control
+#define UECP_ARI_ARI_ON_OFF 0x21
+#define UECP_ARI_ARI_AREA (BK) 0x0F
+#define UECP_ARI_ARI_LEVEL 0x1F
+
+/// Control and set up commands
+#define UECP_CTR_SITE_ADDRESS 0x23
+#define UECP_CTR_ENCODER_ADDRESS 0x27
+#define UECP_CTR_MAKE_PSN_LIST 0x28
+#define UECP_CTR_PSN_ENABLE_DISABLE 0x0B
+#define UECP_CTR_COMMUNICATION_MODE 0x2C
+#define UECP_CTR_TA_CONTROL 0x2A
+#define UECP_CTR_EON_TA_CONTROL 0x15
+#define UECP_CTR_REFERENCE_INPUT_SEL 0x1D
+#define UECP_CTR_DATA_SET_SELECT 0x1C // Data set select
+#define UECP_CTR_GROUP_SEQUENCE 0x16
+#define UECP_CTR_GROUP_VAR_CODE_SEQ 0x29
+#define UECP_CTR_EXTENDED_GROUP_SEQ 0x38
+#define UECP_CTR_PS_CHAR_CODE_TBL_SEL 0x2F
+#define UECP_CTR_ENCODER_ACCESS_RIGHT 0x3A
+#define UECP_CTR_COM_PORT_CONF_MODE 0x3B
+#define UECP_CTR_COM_PORT_CONF_SPEED 0x3C
+#define UECP_CTR_COM_PORT_CONF_TMEOUT 0x3D
+
+/// Other commands
+#define UECP_OTHER_RASS 0xda
+
+/// Bi-directional commands (Remote and configuration commands)
+#define BIDIR_MESSAGE_ACKNOWLEDGMENT 0x18
+#define BIDIR_REQUEST_MESSAGE 0x17
+
+/// Specific message commands
+#define SPEC_MFG_SPECIFIC_CMD 0x2D
+
+/**
+ * RDS and RBDS relevant
+ */
+
+/// RDS Programm type id's
+enum {
+ RDS_PTY_NONE = 0,
+ RDS_PTY_NEWS,
+ RDS_PTY_CURRENT_AFFAIRS,
+ RDS_PTY_INFORMATION,
+ RDS_PTY_SPORT,
+ RDS_PTY_EDUCATION,
+ RDS_PTY_DRAMA,
+ RDS_PTY_CULTURE,
+ RDS_PTY_SCIENCE,
+ RDS_PTY_VARIED,
+ RDS_PTY_POP_MUSIC,
+ RDS_PTY_ROCK_MUSIC,
+ RDS_PTY_MOR_MUSIC,
+ RDS_PTY_LIGHT_CLASSICAL,
+ RDS_PTY_SERIOUS_CLASSICAL,
+ RDS_PTY_OTHER_MUSIC,
+ RDS_PTY_WEATHER,
+ RDS_PTY_FINANCE,
+ RDS_PTY_CHILDRENS_PROGRAMMES,
+ RDS_PTY_SOCIAL_AFFAIRS,
+ RDS_PTY_RELIGION,
+ RDS_PTY_PHONE_IN,
+ RDS_PTY_TRAVEL,
+ RDS_PTY_LEISURE,
+ RDS_PTY_JAZZ_MUSIC,
+ RDS_PTY_COUNTRY_MUSIC,
+ RDS_PTY_NATIONAL_MUSIC,
+ RDS_PTY_OLDIES_MUSIC,
+ RDS_PTY_FOLK_MUSIC,
+ RDS_PTY_DOCUMENTARY,
+ RDS_PTY_ALARM_TEST,
+ RDS_PTY_ALARM
+};
+
+/// RBDS Programm type id's
+enum {
+ RBDS_PTY_NONE = 0,
+ RBDS_PTY_NEWS,
+ RBDS_PTY_INFORMATION,
+ RBDS_PTY_SPORT,
+ RBDS_PTY_TALK,
+ RBDS_PTY_ROCK_MUSIC,
+ RBDS_PTY_CLASSIC_ROCK_MUSIC,
+ RBDS_PTY_ADULT_HITS,
+ RBDS_PTY_SOFT_ROCK,
+ RBDS_PTY_TOP_40,
+ RBDS_PTY_COUNTRY,
+ RBDS_PTY_OLDIES,
+ RBDS_PTY_SOFT,
+ RBDS_PTY_NOSTALGIA,
+ RBDS_PTY_JAZZ,
+ RBDS_PTY_CLASSICAL,
+ RBDS_PTY_R__B,
+ RBDS_PTY_SOFT_R__B,
+ RBDS_PTY_LANGUAGE,
+ RBDS_PTY_RELIGIOUS_MUSIC,
+ RBDS_PTY_RELIGIOUS_TALK,
+ RBDS_PTY_PERSONALITY,
+ RBDS_PTY_PUBLIC,
+ RBDS_PTY_COLLEGE,
+ RBDS_PTY_WEATHER = 29,
+ RBDS_PTY_EMERGENCY_TEST,
+ RBDS_PTY_EMERGENCY
+};
+
+/// RadioText+ message type id's
+enum {
+ RTPLUS_DUMMY_CLASS = 0,
+
+ RTPLUS_ITEM_TITLE = 1,
+ RTPLUS_ITEM_ALBUM = 2,
+ RTPLUS_ITEM_TRACKNUMBER = 3,
+ RTPLUS_ITEM_ARTIST = 4,
+ RTPLUS_ITEM_COMPOSITION = 5,
+ RTPLUS_ITEM_MOVEMENT = 6,
+ RTPLUS_ITEM_CONDUCTOR = 7,
+ RTPLUS_ITEM_COMPOSER = 8,
+ RTPLUS_ITEM_BAND = 9,
+ RTPLUS_ITEM_COMMENT = 10,
+ RTPLUS_ITEM_GENRE = 11,
+
+ RTPLUS_INFO_NEWS = 12,
+ RTPLUS_INFO_NEWS_LOCAL = 13,
+ RTPLUS_INFO_STOCKMARKET = 14,
+ RTPLUS_INFO_SPORT = 15,
+ RTPLUS_INFO_LOTTERY = 16,
+ RTPLUS_INFO_HOROSCOPE = 17,
+ RTPLUS_INFO_DAILY_DIVERSION = 18,
+ RTPLUS_INFO_HEALTH = 19,
+ RTPLUS_INFO_EVENT = 20,
+ RTPLUS_INFO_SZENE = 21,
+ RTPLUS_INFO_CINEMA = 22,
+ RTPLUS_INFO_STUPIDITY_MACHINE = 23,
+ RTPLUS_INFO_DATE_TIME = 24,
+ RTPLUS_INFO_WEATHER = 25,
+ RTPLUS_INFO_TRAFFIC = 26,
+ RTPLUS_INFO_ALARM = 27,
+ RTPLUS_INFO_ADVERTISEMENT = 28,
+ RTPLUS_INFO_URL = 29,
+ RTPLUS_INFO_OTHER = 30,
+
+ RTPLUS_STATIONNAME_SHORT = 31,
+ RTPLUS_STATIONNAME_LONG = 32,
+
+ RTPLUS_PROGRAMME_NOW = 33,
+ RTPLUS_PROGRAMME_NEXT = 34,
+ RTPLUS_PROGRAMME_PART = 35,
+ RTPLUS_PROGRAMME_HOST = 36,
+ RTPLUS_PROGRAMME_EDITORIAL_STAFF = 37,
+ RTPLUS_PROGRAMME_FREQUENCY= 38,
+ RTPLUS_PROGRAMME_HOMEPAGE = 39,
+ RTPLUS_PROGRAMME_SUBCHANNEL = 40,
+
+ RTPLUS_PHONE_HOTLINE = 41,
+ RTPLUS_PHONE_STUDIO = 42,
+ RTPLUS_PHONE_OTHER = 43,
+
+ RTPLUS_SMS_STUDIO = 44,
+ RTPLUS_SMS_OTHER = 45,
+
+ RTPLUS_EMAIL_HOTLINE = 46,
+ RTPLUS_EMAIL_STUDIO = 47,
+ RTPLUS_EMAIL_OTHER = 48,
+
+ RTPLUS_MMS_OTHER = 49,
+
+ RTPLUS_CHAT = 50,
+ RTPLUS_CHAT_CENTER = 51,
+
+ RTPLUS_VOTE_QUESTION = 52,
+ RTPLUS_VOTE_CENTER = 53,
+
+ RTPLUS_PLACE = 59,
+ RTPLUS_APPOINTMENT = 60,
+ RTPLUS_IDENTIFIER = 61,
+ RTPLUS_PURCHASE = 62,
+ RTPLUS_GET_DATA = 63
+};
+
+/* page 71, Annex D, table D.1 in the standard and Annex N */
+const char *piCountryCodes_A[15][7]=
+{
+ // 0 1 2 3 4 5 6
+ {"US","__","AI","BO","GT","__","__"}, // 1
+ {"US","__","AG","CO","HN","__","__"}, // 2
+ {"US","__","EC","JM","AW","__","__"}, // 3
+ {"US","__","FK","MQ","__","__","__"}, // 4
+ {"US","__","BB","GF","MS","__","__"}, // 5
+ {"US","__","BZ","PY","TT","__","__"}, // 6
+ {"US","__","KY","NI","PE","__","__"}, // 7
+ {"US","__","CR","__","SR","__","__"}, // 8
+ {"US","__","CU","PA","UY","__","__"}, // 9
+ {"US","__","AR","DM","KN","__","__"}, // A
+ {"US","CA","BR","DO","LC","MX","__"}, // B
+ {"__","CA","BM","CL","SV","VC","__"}, // C
+ {"US","CA","AN","GD","HT","MX","__"}, // D
+ {"US","CA","GP","TC","VE","MX","__"}, // E
+ {"__","GL","BS","GY","__","VG","PM"} // F
+};
+
+const char *piCountryCodes_D[15][7]=
+{
+ // 0 1 2 3 4 5 6
+ {"CM","NA","SL","__","__","__","__"}, // 1
+ {"CF","LR","ZW","__","__","__","__"}, // 2
+ {"DJ","GH","MZ","EH","__","__","__"}, // 3
+ {"MG","MR","UG","xx","__","__","__"}, // 4
+ {"ML","ST","SZ","RW","__","__","__"}, // 5
+ {"AO","CV","KE","LS","__","__","__"}, // 6
+ {"GQ","SN","SO","__","__","__","__"}, // 7
+ {"GA","GM","NE","SC","__","__","__"}, // 8
+ {"GN","BI","TD","__","__","__","__"}, // 9
+ {"ZA","AC","GW","MU","__","__","__"}, // A
+ {"BF","BW","ZR","__","__","__","__"}, // B
+ {"CG","KM","CI","SD","__","__","__"}, // C
+ {"TG","TZ","Zanzibar","__","__","__","__"}, // D
+ {"BJ","ET","ZM","__","__","__","__"}, // E
+ {"MW","NG","__","__","__","__","__"} // F
+};
+
+const char *piCountryCodes_E[15][7]=
+{
+ // 0 1 2 3 4 5 6
+ {"DE","GR","MA","__","MD","__","__"},
+ {"DZ","CY","CZ","IE","EE","__","__"},
+ {"AD","SM","PL","TR","KG","__","__"},
+ {"IL","CH","VA","MK","__","__","__"},
+ {"IT","JO","SK","TJ","__","__","__"},
+ {"BE","FI","SY","__","UA","__","__"},
+ {"RU","LU","TN","__","__","__","__"},
+ {"PS","BG","__","NL","PT","__","__"},
+ {"AL","DK","LI","LV","SI","__","__"}, // 9
+ {"AT","GI","IS","LB","AM","__","__"}, // A
+ {"HU","IQ","MC","AZ","UZ","__","__"}, // B
+ {"MT","GB","LT","HR","GE","__","__"}, // C
+ {"DE","LY","YU","KZ","__","__","__"}, // D
+ {"__","RO","ES","SE","TM","__","__"}, // E
+ {"EG","FR","NO","BY","BA","__","__"} // F
+};
+
+const char *piCountryCodes_F[15][7]=
+{
+ // 0 1 2 3 4 5 6
+ {"AU","KI","KW","LA","__","__","__"}, // 1
+ {"AU","BT","QA","TH","__","__","__"}, // 2
+ {"AU","BD","KH","TO","__","__","__"}, // 3
+ {"AU","PK","WS","__","__","__","__"}, // 4
+ {"AU","FJ","IN","__","__","__","__"}, // 5
+ {"AU","OM","MO","__","__","__","__"}, // 6
+ {"AU","NR","VN","__","__","__","__"}, // 7
+ {"AU","IR","PH","__","__","__","__"}, // 8
+ {"SA","NZ","JP","PG","__","__","__"}, // 9
+ {"AF","SB","SG","__","__","__","__"}, // A
+ {"MM","BN","MV","YE","__","__","__"}, // B
+ {"CN","LK","ID","__","__","__","__"}, // C
+ {"KP","TW","AE","__","__","__","__"}, // D
+ {"BH","KR","NP","FM","__","__","__"}, // E
+ {"MY","HK","VU","MN","__","__","__"} // F
+};
+
+/* see page 84, Annex J in the standard */
+const std::string piRDSLanguageCodes[128]=
+{
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ "___", "alb", "bre", "cat", "hrv", "wel", "cze", "dan", "ger", "eng", "spa", "epo", "est", "baq", "fae", "fre", // 0
+ "fry", "gle", "gla", "glg", "ice", "ita", "smi", "lat", "lav", "ltz", "lit", "hun", "mlt", "dut", "nor", "oci", // 1
+ "pol", "por", "rum", "rom", "srp", "slo", "slv", "fin", "swe", "tur", "nld", "wln", "___", "___", "___", "___", // 2
+ "___", "___", "___", "___", "___", "___", "___", "___", "___", "___", "___", "___", "___", "___", "___", "___", // 3
+ "___", "___", "___", "___", "___", "zul", "vie", "uzb", "urd", "ukr", "tha", "tel", "tat", "tam", "tgk", "swa", // 4
+ "srn", "som", "sin", "sna", "scc", "rue", "rus", "que", "pus", "pan", "per", "pap", "ori", "nep", "nde", "mar", // 5
+ "mol", "mys", "mlg", "mkd", "_?_", "kor", "khm", "kaz", "kan", "jpn", "ind", "hin", "heb", "hau", "grn", "guj", // 6
+ "gre", "geo", "ful", "prs", "chv", "chi", "bur", "bul", "ben", "bel", "bam", "aze", "asm", "arm", "ara", "amh" // 7
+};
+
+/* ----------------------------------------------------------------------------------------------------------- */
+
+#define EntityChars 56
+const char *entitystr[EntityChars] = { "&apos;", "&amp;", "&quot;", "&gt", "&lt", "&copy;", "&times;", "&nbsp;",
+ "&Auml;", "&auml;", "&Ouml;", "&ouml;", "&Uuml;", "&uuml;", "&szlig;", "&deg;",
+ "&Agrave;", "&Aacute;", "&Acirc;", "&Atilde;", "&agrave;", "&aacute;", "&acirc;", "&atilde;",
+ "&Egrave;", "&Eacute;", "&Ecirc;", "&Euml;", "&egrave;", "&eacute;", "&ecirc;", "&euml;",
+ "&Igrave;", "&Iacute;", "&Icirc;", "&Iuml;", "&igrave;", "&iacute;", "&icirc;", "&iuml;",
+ "&Ograve;", "&Oacute;", "&Ocirc;", "&Otilde;", "&ograve;", "&oacute;", "&ocirc;", "&otilde;",
+ "&Ugrave;", "&Uacute;", "&Ucirc;", "&Ntilde;", "&ugrave;", "&uacute;", "&ucirc;", "&ntilde;" };
+const char *entitychar[EntityChars] = { "'", "&", "\"", ">", "<", "c", "*", " ",
+ "Ä", "ä", "Ö", "ö", "Ü", "ü", "ß", "°",
+ "À", "Á", "Â", "Ã", "à", "á", "â", "ã",
+ "È", "É", "Ê", "Ë", "è", "é", "ê", "ë",
+ "Ì", "Í", "Î", "Ï", "ì", "í", "î", "ï",
+ "Ò", "Ó", "Ô", "Õ", "ò", "ó", "ô", "õ",
+ "Ù", "Ú", "Û", "Ñ", "ù", "ú", "û", "ñ" };
+
+// RDS-Chartranslation: 0x80..0xff
+unsigned char sRDSAddChar[128] =
+{
+ 0xe1, 0xe0, 0xe9, 0xe8, 0xed, 0xec, 0xf3, 0xf2,
+ 0xfa, 0xf9, 0xd1, 0xc7, 0x8c, 0xdf, 0x8e, 0x8f,
+ 0xe2, 0xe4, 0xea, 0xeb, 0xee, 0xef, 0xf4, 0xf6,
+ 0xfb, 0xfc, 0xf1, 0xe7, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xaa, 0xa1, 0xa9, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xa3, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xba, 0xb9, 0xb2, 0xb3, 0xb1, 0xa1, 0xb6, 0xb7,
+ 0xb5, 0xbf, 0xf7, 0xb0, 0xbc, 0xbd, 0xbe, 0xa7,
+ 0xc1, 0xc0, 0xc9, 0xc8, 0xcd, 0xcc, 0xd3, 0xd2,
+ 0xda, 0xd9, 0xca, 0xcb, 0xcc, 0xcd, 0xd0, 0xcf,
+ 0xc2, 0xc4, 0xca, 0xcb, 0xce, 0xcf, 0xd4, 0xd6,
+ 0xdb, 0xdc, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xc3, 0xc5, 0xc6, 0xe3, 0xe4, 0xdd, 0xd5, 0xd8,
+ 0xde, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xf0,
+ 0xe3, 0xe5, 0xe6, 0xf3, 0xf4, 0xfd, 0xf5, 0xf8,
+ 0xfe, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
+char *rds_entitychar(char *text)
+{
+ int i = 0, l, lof, lre, space;
+ char *temp;
+
+ while (i < EntityChars)
+ {
+ if ((temp = strstr(text, entitystr[i])) != NULL)
+ {
+ l = strlen(entitystr[i]);
+ lof = (temp-text);
+ if (strlen(text) < RT_MEL)
+ {
+ lre = strlen(text) - lof - l;
+ space = 1;
+ }
+ else
+ {
+ lre = RT_MEL - 1 - lof - l;
+ space = 0;
+ }
+ memmove(text+lof, entitychar[i], 1);
+ memmove(text+lof+1, temp+l, lre);
+ if (space != 0)
+ memmove(text+lof+1+lre, " ", l-1);
+ }
+ else
+ i++;
+ }
+
+ return text;
+}
+
+unsigned short crc16_ccitt(const unsigned char *daten, int len, bool skipfirst)
+{
+ // CRC16-CCITT: x^16 + x^12 + x^5 + 1
+ // with start 0xffff and result invers
+ register unsigned short crc = 0xffff;
+
+ if (skipfirst) daten++;
+ while (len--)
+ {
+ crc = (crc >> 8) | (crc << 8);
+ crc ^= *daten++;
+ crc ^= (crc & 0xff) >> 4;
+ crc ^= (crc << 8) << 4;
+ crc ^= ((crc & 0xff) << 4) << 1;
+ }
+
+ return ~(crc);
+}
+
+
+/// --- CDVDRadioRDSData ------------------------------------------------------------
+
+CDVDRadioRDSData::CDVDRadioRDSData()
+ : CThread("DVDRDSData")
+ , m_speed(DVD_PLAYSPEED_NORMAL)
+ , m_messageQueue("rds")
+{
+ CLog::Log(LOGDEBUG, "Radio UECP (RDS) Processor - new %s", __FUNCTION__);
+
+ m_messageQueue.SetMaxDataSize(40 * 256 * 1024);
+}
+
+CDVDRadioRDSData::~CDVDRadioRDSData()
+{
+ CLog::Log(LOGDEBUG, "Radio UECP (RDS) Processor - delete %s", __FUNCTION__);
+ StopThread();
+}
+
+bool CDVDRadioRDSData::CheckStream(CDVDStreamInfo &hints)
+{
+ if (hints.type == STREAM_RADIO_RDS)
+ return true;
+
+ return false;
+}
+
+bool CDVDRadioRDSData::OpenStream(CDVDStreamInfo &hints)
+{
+ m_messageQueue.Init();
+ if (hints.type == STREAM_RADIO_RDS)
+ {
+ Flush();
+ CLog::Log(LOGNOTICE, "Creating UECP (RDS) data thread");
+ Create();
+ }
+ return true;
+}
+
+void CDVDRadioRDSData::CloseStream(bool bWaitForBuffers)
+{
+ // wait until buffers are empty
+ if (bWaitForBuffers) m_messageQueue.WaitUntilEmpty();
+
+ m_messageQueue.Abort();
+
+ // wait for decode_video thread to end
+ CLog::Log(LOGNOTICE, "Radio UECP (RDS) Processor - waiting for data thread to exit");
+
+ StopThread(); // will set this->m_bStop to true
+
+ m_messageQueue.End();
+ m_currentInfoTag.reset();
+}
+
+void CDVDRadioRDSData::ResetRDSCache()
+{
+ CSingleLock lock(m_critSection);
+
+ m_currentFileUpdate = false;
+
+ m_UECPDataStart = false;
+ m_UECPDatabStuff = false;
+ m_UECPDataIndex = 0;
+
+ m_RDS_IsRBDS = false;
+ m_RDS_SlowLabelingCodesPresent = false;
+
+ m_PI_Current = 0;
+ m_PI_CountryCode = 0;
+ m_PI_ProgramType = 0;
+ m_PI_ProgramReferenceNumber = 0;
+
+ m_EPP_TM_INFO_ExtendedCountryCode = 0;
+
+ m_PS_Present = false;
+ m_PS_Index = 0;
+ for (int i = 0; i < PS_TEXT_ENTRIES; i++)
+ {
+ memset(m_PS_Text[i], 0x20, 8);
+ m_PS_Text[i][8] = 0;
+ }
+
+ m_DI_IsStereo = true;
+ m_DI_ArtificialHead = false;
+ m_DI_Compressed = false;
+ m_DI_DynamicPTY = false;
+
+ m_TA_TP_TrafficAdvisory = false;
+ m_TA_TP_TrafficVolume = 0.0;
+
+ m_MS_SpeechActive = false;
+
+ m_PTY = 0;
+ memset(m_PTYN, 0x20, 8);
+ m_PTYN[8] = 0;
+ m_PTYN_Present = false;
+
+ m_RT_Present = false;
+ m_RT_MaxSize = 4;
+ m_RT_NewItem = false;
+ m_RT_Index = 0;
+ for (int i = 0; i < 5; i++)
+ memset(m_RT_Text[i], 0, RT_MEL);
+ m_RT.clear();
+
+ m_RTPlus_TToggle = false;
+ m_RTPlus_Present = false;
+ m_RTPlus_Show = false;
+ m_RTPlus_iToggle = 0;
+ m_RTPlus_ItemToggle = 1;
+ m_RTPlus_Title[0] = 0;
+ m_RTPlus_Artist[0] = 0;
+ m_RTPlus_Starttime = time(NULL);
+ m_RTPlus_GenrePresent = false;
+
+ m_currentInfoTag = CPVRRadioRDSInfoTag::CreateDefaultTag();
+ m_currentChannel = g_application.CurrentFileItem().GetPVRChannelInfoTag();
+ g_application.CurrentFileItem().SetPVRRadioRDSInfoTag(m_currentInfoTag);
+ g_infoManager.SetCurrentItem(g_application.CurrentFileItem());
+
+ // send a message to all windows to tell them to update the radiotext
+ CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_RADIOTEXT);
+ g_windowManager.SendThreadMessage(msg);
+}
+
+void CDVDRadioRDSData::Process()
+{
+ CLog::Log(LOGNOTICE, "Radio UECP (RDS) Processor - running thread");
+
+ while (!m_bStop)
+ {
+ CDVDMsg* pMsg;
+ int iPriority = (m_speed == DVD_PLAYSPEED_PAUSE) ? 1 : 0;
+ MsgQueueReturnCode ret = m_messageQueue.Get(&pMsg, 2000, iPriority);
+
+ if (ret == MSGQ_TIMEOUT)
+ {
+ /* Timeout for RDS is not a bad thing, so we continue without error */
+ continue;
+ }
+
+ if (MSGQ_IS_ERROR(ret))
+ {
+ CLog::Log(LOGERROR, "Got MSGQ_ABORT or MSGO_IS_ERROR return true (%i)", ret);
+ break;
+ }
+
+ if (pMsg->IsType(CDVDMsg::DEMUXER_PACKET))
+ {
+ CSingleLock lock(m_critSection);
+
+ DemuxPacket* pPacket = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacket();
+
+ ProcessUECP(pPacket->pData, pPacket->iSize);
+ }
+ else if (pMsg->IsType(CDVDMsg::PLAYER_SETSPEED))
+ {
+ m_speed = static_cast<CDVDMsgInt*>(pMsg)->m_value;
+ }
+ else if (pMsg->IsType(CDVDMsg::GENERAL_FLUSH)
+ || pMsg->IsType(CDVDMsg::GENERAL_RESET))
+ {
+ ResetRDSCache();
+ }
+ pMsg->Release();
+ }
+}
+
+void CDVDRadioRDSData::Flush()
+{
+ if(!m_messageQueue.IsInited())
+ return;
+ /* flush using message as this get's called from dvdplayer thread */
+ /* and any demux packet that has been taken out of queue need to */
+ /* be disposed of before we flush */
+ m_messageQueue.Flush();
+ m_messageQueue.Put(new CDVDMsg(CDVDMsg::GENERAL_FLUSH));
+}
+
+void CDVDRadioRDSData::OnExit()
+{
+ CLog::Log(LOGNOTICE, "Radio UECP (RDS) Processor - thread end");
+}
+
+std::string CDVDRadioRDSData::GetRadioText(unsigned int line)
+{
+ std::string str = "";
+
+ if (m_RT_Present)
+ {
+ if (line > MAX_RADIOTEXT_LISTSIZE)
+ return "";
+
+ if ((int)line+1 > m_RT_MaxSize)
+ {
+ m_RT_MaxSize = line+1;
+ return "";
+ }
+ if (m_RT.size() <= line)
+ return "";
+
+ return m_RT[line];
+ }
+ else if (m_PS_Present)
+ {
+ std::string temp = "";
+ int ind = (m_PS_Index == 0) ? 11 : m_PS_Index - 1;
+ for (int i = ind+1; i < PS_TEXT_ENTRIES; i++)
+ {
+ temp += m_PS_Text[i];
+ temp += ' ';
+ }
+ for (int i = 0; i <= ind; i++)
+ {
+ temp += m_PS_Text[i];
+ temp += ' ';
+ }
+
+ if (line == 0)
+ str.insert(0, temp, 6*9, 6*9);
+ else if (line == 1)
+ str.insert(0, temp.c_str(), 6*9);
+ }
+ return str;
+}
+
+void CDVDRadioRDSData::SetRadioStyle(std::string genre)
+{
+ g_application.CurrentFileItem().GetMusicInfoTag()->SetGenre(genre);
+ m_currentInfoTag->SetProgStyle(genre);
+ m_currentFileUpdate = true;
+
+ CLog::Log(LOGDEBUG, "Radio UECP (RDS) Processor - %s - Stream genre set to %s", __FUNCTION__, genre.c_str());
+}
+
+void CDVDRadioRDSData::ProcessUECP(const unsigned char *data, unsigned int len)
+{
+ for (unsigned int i = 0; i < len; i++)
+ {
+ if (data[i] == UECP_DATA_START) //!< Start
+ {
+ m_UECPDataIndex = -1;
+ m_UECPDataStart = true;
+ m_UECPDatabStuff = false;
+ }
+
+ if (m_UECPDataStart)
+ {
+ //! byte-stuffing reverse: 0xfd00->0xfd, 0xfd01->0xfe, 0xfd02->0xff
+ if (m_UECPDatabStuff == true)
+ {
+ switch (data[i])
+ {
+ case 0x00: m_UECPData[m_UECPDataIndex] = 0xfd; break;
+ case 0x01: m_UECPData[m_UECPDataIndex] = 0xfe; break;
+ case 0x02: m_UECPData[m_UECPDataIndex] = 0xff; break;
+ default: m_UECPData[++m_UECPDataIndex] = data[i]; // should never be
+ }
+ m_UECPDatabStuff = false;
+ }
+ else
+ {
+ m_UECPData[++m_UECPDataIndex] = data[i];
+ }
+
+ if (data[i] == 0xfd && m_UECPDataIndex > 0) //!< stuffing found
+ m_UECPDatabStuff = true;
+
+ if (m_UECPDataIndex >= UECP_SIZE_MAX) //!< max. UECP data length, garbage ?
+ {
+ CLog::Log(LOGERROR, "Radio UECP (RDS) Processor - Error(TS): too long, garbage ?");
+ m_UECPDataStart = false;
+ }
+ }
+
+ if (m_UECPDataStart == true && data[i] == UECP_DATA_STOP && m_currentInfoTag) //!< End
+ {
+ m_UECPDataStart = false;
+
+ if (m_UECPDataIndex < 9)
+ {
+ CLog::Log(LOGERROR, "Radio UECP (RDS) Processor - Error(TS): too short -> garbage ?");
+ }
+ else
+ {
+ //! crc16-check
+ unsigned short crc16 = crc16_ccitt(m_UECPData, m_UECPDataIndex-3, 1);
+ if (crc16 != (m_UECPData[m_UECPDataIndex-2]<<8) + m_UECPData[m_UECPDataIndex-1])
+ {
+ CLog::Log(LOGERROR, "Radio UECP (RDS) Processor - Error(TS): wrong CRC # calc = %04x <> transmit = %02x%02x",
+ crc16, m_UECPData[m_UECPDataIndex-2], m_UECPData[m_UECPDataIndex-1]);
+ }
+ else
+ {
+ m_UECPDataDeadBreak = false;
+
+ unsigned int ret = 0;
+ unsigned int ptr = 5;
+ unsigned int len = m_UECPDataIndex-7;
+ do
+ {
+ uint8_t *msg = m_UECPData+ptr; //!< Current selected UECP message element (increased if more as one element is in frame)
+ switch (msg[UECP_ME_MEC])
+ {
+ case UECP_RDS_PI: ret = DecodePI(msg); break; //!< Program Identification
+ case UECP_RDS_PS: ret = DecodePS(msg); break; //!< Program Service name (PS)
+ case UECP_RDS_DI: ret = DecodeDI(msg); break; //!< Decoder Identification and dynamic PTY indicator
+ case UECP_RDS_TA_TP: ret = DecodeTA_TP(msg); break; //!< Traffic Announcement and Traffic Programme bits.
+ case UECP_RDS_MS: ret = DecodeMS(msg); break; //!< Music/Speech switch
+ case UECP_RDS_PTY: ret = DecodePTY(msg); break; //!< Program Type
+ case UECP_RDS_PTYN: ret = DecodePTYN(msg); break; //!< Program Type Name
+ case UECP_RDS_RT: ret = DecodeRT(msg, len); break; //!< RadioText
+ case UECP_ODA_DATA: ret = DecodeODA(msg, len); break; //!< Open Data Application
+ case UECP_OTHER_RASS: m_UECPDataDeadBreak = true; break; //!< Radio screen show (RaSS) (not present, before on SWR radio)
+ case UECP_CLOCK_RTC: ret = DecodeRTC(msg); break; //!< Real time clock
+ case UECP_TDC_TMC: ret = DecodeTMC(msg, len); break; //!< Traffic message channel
+ case UECP_EPP_TM_INFO: ret = DecodeEPPTransmitterInfo(msg); break; //!< EPP transmitter information
+ case UECP_SLOW_LABEL_CODES: ret = DecodeSlowLabelingCodes(msg); break; //!< Slow Labeling codes
+ case UECP_DAB_DYN_LABEL_CMD: ret = DecodeDABDynLabelCmd(msg, len); break; //!< DAB: Dynamic Label command
+ case UECP_DAB_DYN_LABEL_MSG: ret = DecodeDABDynLabelMsg(msg, len); break; //!< DAB: Dynamic Label message (DL)
+ case UECP_RDS_AF: ret = DecodeAF(msg, len); break; //!< Alternative Frequencies list
+ case UECP_RDS_EON_AF: ret = DecodeEonAF(msg, len); break; //!< EON Alternative Frequencies list
+ case UECP_TDC_TDC: ret = DecodeTDC(msg, len); break; //!< Transparent Data Channel
+ case UECP_LINKAGE_INFO: ret = 5; break; //!< Linkage information
+ case UECP_TDC_EWS: ret = 6; break; //!< Emergency warning system
+ case UECP_RDS_PIN: ret = 5; break; //!< Program Item Number
+ case UECP_TDC_IH: ret = 7; break; //!< In-house applications (Should be ignored)
+ case UECP_TDC_FREE_FMT_GROUP: ret = 7; break; //!< Free-format group (unused)
+ case UECP_ODA_CONF_SHORT_MSG_CMD: ret = 8; break; //!< ODA Configuration and Short Message Command (unused)
+ case UECP_CLOCK_RTC_CORR: ret = 3; break; //!< Real time clock correction (unused)
+ case UECP_CLOCK_CT_ON_OFF: ret = 2; break; //!< Real time clock on/off (unused)
+ default:
+#ifdef RDS_IMPROVE_CHECK
+ printf("Unknown UECP data packet = 0x%02X\n", msg[UECP_ME_MEC]);
+#endif
+ m_UECPDataDeadBreak = true;
+ break;
+ }
+ ptr += ret;
+ len -= ret;
+ }
+ while (ptr < m_UECPDataIndex-5 && !m_UECPDataDeadBreak && !m_bStop);
+
+ if (m_currentFileUpdate && !m_bStop)
+ {
+ g_infoManager.SetCurrentItem(g_application.CurrentFileItem());
+ m_currentFileUpdate = false;
+ }
+ }
+ }
+ }
+ }
+}
+
+unsigned int CDVDRadioRDSData::DecodePI(uint8_t *msgElement)
+{
+ uint16_t PICode = (msgElement[3] << 8) | msgElement[4];
+ if (m_PI_Current != PICode)
+ {
+ m_PI_Current = PICode;
+
+ m_PI_CountryCode = (m_PI_Current>>12) & 0x0F;
+ m_PI_ProgramType = (m_PI_Current>>8) & 0x0F;
+ m_PI_ProgramReferenceNumber = m_PI_Current & 0xFF;
+
+ CLog::Log(LOGINFO, "Radio UECP (RDS) Processor - PI code changed to Country %X, Type %X and reference no. %i", m_PI_CountryCode, m_PI_ProgramType, m_PI_ProgramReferenceNumber);
+ }
+
+ return 5;
+}
+
+unsigned int CDVDRadioRDSData::DecodePS(uint8_t *msgElement)
+{
+ uint8_t *text = msgElement+3;
+
+ for (int i = 0; i < 8; i++)
+ {
+ if (text[i] <= 0xfe)
+ m_PS_Text[m_PS_Index][i] = (text[i] >= 0x80) ? sRDSAddChar[text[i]-0x80] : text[i]; //!< additional rds-character, see RBDS-Standard, Annex E
+ }
+
+ m_PS_Index++;
+ if (m_PS_Index >= PS_TEXT_ENTRIES)
+ m_PS_Index = 0;
+
+ m_PS_Present = true;
+ return 11;
+}
+
+unsigned int CDVDRadioRDSData::DecodeDI(uint8_t *msgElement)
+{
+ bool value;
+
+ value = msgElement[3] & 1;
+ if (m_DI_IsStereo != value)
+ {
+ CLog::Log(LOGDEBUG, "Radio UECP (RDS) Processor - %s - Stream changed over to %s", __FUNCTION__, value ? "Stereo" : "Mono");
+ m_DI_IsStereo = value;
+ }
+
+ value = msgElement[3] & 2;
+ if (m_DI_ArtificialHead != value)
+ {
+ CLog::Log(LOGDEBUG, "Radio UECP (RDS) Processor - %s - Stream changed over to %sArtificial Head", __FUNCTION__, value ? "" : "Not ");
+ m_DI_ArtificialHead = value;
+ }
+
+ value = msgElement[3] & 4;
+ if (m_DI_ArtificialHead != value)
+ {
+ CLog::Log(LOGDEBUG, "Radio UECP (RDS) Processor - %s - Stream changed over to %sCompressed Head", __FUNCTION__, value ? "" : "Not ");
+ m_DI_ArtificialHead = value;
+ }
+
+ value = msgElement[3] & 8;
+ if (m_DI_DynamicPTY != value)
+ {
+ CLog::Log(LOGDEBUG, "Radio UECP (RDS) Processor - %s - Stream changed over to %s PTY", __FUNCTION__, value ? "dynamic" : "static");
+ m_DI_DynamicPTY = value;
+ }
+
+ return 4;
+}
+
+unsigned int CDVDRadioRDSData::DecodeTA_TP(uint8_t *msgElement)
+{
+ uint8_t dsn = msgElement[1];
+ bool traffic_announcement = msgElement[3] & 1;
+ bool traffic_programme = msgElement[3] & 2;
+
+ if (traffic_announcement && !m_TA_TP_TrafficAdvisory && traffic_programme && dsn == 0 && CSettings::GetInstance().GetBool("pvrplayback.trafficadvisory"))
+ {
+ CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Warning, g_localizeStrings.Get(19021), g_localizeStrings.Get(29930));
+ m_TA_TP_TrafficAdvisory = true;
+ m_TA_TP_TrafficVolume = g_application.GetVolume();
+ float trafAdvVol = (float)CSettings::GetInstance().GetInt("pvrplayback.trafficadvisoryvolume");
+ if (trafAdvVol)
+ g_application.SetVolume(m_TA_TP_TrafficVolume+trafAdvVol);
+
+ CVariant data(CVariant::VariantTypeObject);
+ data["on"] = true;
+ ANNOUNCEMENT::CAnnouncementManager::GetInstance().Announce(ANNOUNCEMENT::PVR, "xbmc", "RDSRadioTA", data);
+ }
+
+ if (!traffic_announcement && m_TA_TP_TrafficAdvisory && CSettings::GetInstance().GetBool("pvrplayback.trafficadvisory"))
+ {
+ m_TA_TP_TrafficAdvisory = false;
+ g_application.SetVolume(m_TA_TP_TrafficVolume);
+
+ CVariant data(CVariant::VariantTypeObject);
+ data["on"] = false;
+ ANNOUNCEMENT::CAnnouncementManager::GetInstance().Announce(ANNOUNCEMENT::PVR, "xbmc", "RDSRadioTA", data);
+ }
+
+ return 4;
+}
+
+unsigned int CDVDRadioRDSData::DecodeMS(uint8_t *msgElement)
+{
+ bool speechActive = msgElement[3] == 0;
+ if (m_MS_SpeechActive != speechActive)
+ {
+ m_currentInfoTag->SetSpeechActive(m_MS_SpeechActive);
+ CLog::Log(LOGDEBUG, "Radio UECP (RDS) Processor - %s - Stream changed over to %s", __FUNCTION__, speechActive ? "Speech" : "Music");
+ m_MS_SpeechActive = speechActive;
+ }
+
+ return 4;
+}
+
+/*!
+ * EBU - SPB 490 - 3.3.7 and 62106IEC:1999 - 3.2.1.2, Message Name: Programme Type
+ * Message Element Code: 07
+ */
+//! @todo Improve and test alarm message
+typedef struct { const char *style_name; int name; } pty_skin_info;
+pty_skin_info pty_skin_info_table[32][2] =
+{
+ { { "none", 29940 }, { "none", 29940 } },
+ { { "news", 29941 }, { "news", 29941 } },
+ { { "currentaffairs", 29942 }, { "information", 29943 } },
+ { { "information", 29943 }, { "sport", 29944 } },
+ { { "sport", 29944 }, { "talk", 29939 } },
+ { { "education", 29945 }, { "rockmusic", 29951 } },
+ { { "drama", 29946 }, { "classicrockmusic",29977 } },
+ { { "cultures", 29947 }, { "adulthits", 29937 } },
+ { { "science", 29948 }, { "softrock", 29938 } },
+ { { "variedspeech", 29949 }, { "top40", 29972 } },
+ { { "popmusic", 29950 }, { "countrymusic", 29965 } },
+ { { "rockmusic", 29951 }, { "oldiesmusic", 29967 } },
+ { { "easylistening", 29952 }, { "softmusic", 29936 } },
+ { { "lightclassics", 29953 }, { "nostalgia", 29979 } },
+ { { "seriousclassics",29954 }, { "jazzmusic", 29964 } },
+ { { "othermusic", 29955 }, { "classical", 29978 } },
+ { { "weather", 29956 }, { "randb", 29975 } },
+ { { "finance", 29957 }, { "softrandb", 29976 } },
+ { { "childrensprogs", 29958 }, { "language", 29932 } },
+ { { "socialaffairs", 29959 }, { "religiousmusic", 29973 } },
+ { { "religion", 29960 }, { "religioustalk", 29974 } },
+ { { "phonein", 29961 }, { "personality", 29934 } },
+ { { "travelandtouring",29962 },{ "public", 29935 } },
+ { { "leisureandhobby",29963 }, { "college", 29933 } },
+ { { "jazzmusic", 29964 }, { "spanishtalk", 29927 } },
+ { { "countrymusic", 29965 }, { "spanishmusic", 29928 } },
+ { { "nationalmusic", 29966 }, { "hiphop", 29929 } },
+ { { "oldiesmusic", 29967 }, { "", -1 } },
+ { { "folkmusic", 29968 }, { "", -1 } },
+ { { "documentary", 29969 }, { "weather", 29956 } },
+ { { "alarmtest", 29970 }, { "alarmtest", 29970 } },
+ { { "alarm-alarm", 29971 }, { "alarm-alarm", 29971 } }
+};
+
+unsigned int CDVDRadioRDSData::DecodePTY(uint8_t *msgElement)
+{
+ int pty = msgElement[3];
+ if (pty >= 0 && pty < 32 && m_PTY != pty)
+ {
+ m_PTY = pty;
+
+ // save info
+ m_currentInfoTag->SetRadioStyle(pty_skin_info_table[m_PTY][m_RDS_IsRBDS].style_name);
+ if (!m_RTPlus_GenrePresent && !m_PTYN_Present)
+ SetRadioStyle(g_localizeStrings.Get(pty_skin_info_table[m_PTY][m_RDS_IsRBDS].name));
+
+ if (m_PTY == RDS_PTY_ALARM_TEST)
+ CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(29931), g_localizeStrings.Get(29970), TOAST_DISPLAY_TIME, false);
+
+ if (m_PTY == RDS_PTY_ALARM)
+ {
+ CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Warning, g_localizeStrings.Get(29931), g_localizeStrings.Get(29971), TOAST_DISPLAY_TIME*2, true);
+ }
+ }
+
+ return 4;
+}
+
+unsigned int CDVDRadioRDSData::DecodePTYN(uint8_t *msgElement)
+{
+ // decode Text
+ uint8_t *text = msgElement+3;
+
+ for (int i = 0; i < 8; i++)
+ {
+ if (text[i] <= 0xfe)
+ m_PTYN[i] = (text[i] >= 0x80) ? sRDSAddChar[text[i]-0x80] : text[i];
+ }
+
+ m_PTYN_Present = true;
+
+ if (!m_RTPlus_GenrePresent)
+ {
+ std::string progTypeName = StringUtils::Format("%s: %s", g_localizeStrings.Get(pty_skin_info_table[m_PTY][m_RDS_IsRBDS].name).c_str(), m_PTYN);
+ SetRadioStyle(progTypeName);
+ }
+
+ return 11;
+}
+
+inline void rtrim_str(std::string &text)
+{
+ for (int i = text.length()-1; i >= 0; --i)
+ {
+ if (text[i] == ' ' || text[i] == '\t' || text[i] == '\n' || text[i] == '\r')
+ text[i] = 0;
+ else
+ break;
+ }
+}
+
+unsigned int CDVDRadioRDSData::DecodeRT(uint8_t *msgElement, unsigned int len)
+{
+ if (!m_RT_Present)
+ {
+ m_currentInfoTag->SetPlayingRadiotext(true);
+ m_RT_Present = true;
+ }
+
+ int bufConf = (msgElement[UECP_ME_DATA] >> 5) & 0x03;
+ unsigned int msgLength = msgElement[UECP_ME_MEL];
+ if (msgLength > len-2)
+ {
+ CLog::Log(LOGERROR, "Radio UECP (RDS) - %s - RT-Error: Length=0 or not correct (MFL= %d, MEL= %d)\n", __FUNCTION__, len, msgLength);
+ m_UECPDataDeadBreak = true;
+ return 0;
+ }
+ else if (msgLength == 0 || (msgLength == 1 && bufConf == 0))
+ {
+ m_RT.clear();
+ m_RT_Index = 0;
+ for (int i = 0; i < 5; i++)
+ memset(m_RT_Text[i], 0, RT_MEL);
+ }
+ else
+ {
+ // bool flagToogle = msgElement[UECP_ME_DATA] & 0x01 ? true : false;
+ // int txQty = (msgElement[UECP_ME_DATA] >> 1) & 0x0F;
+ // int bufConf = (msgElement[UECP_ME_DATA] >> 5) & 0x03;
+
+ //! byte 4 = RT-Status bitcodet (0=AB-flagcontrol, 1-4=Transmission-Number, 5+6=Buffer-Config, ingnored, always 0x01 ?)
+ char temptext[RT_MEL];
+ memset(temptext, 0x0, RT_MEL);
+ for (unsigned int i = 1, ii = 0; i < msgLength; i++)
+ {
+ if (msgElement[UECP_ME_DATA+i] <= 0xfe) // additional rds-character, see RBDS-Standard, Annex E
+ temptext[ii++] = (msgElement[UECP_ME_DATA+i] >= 0x80) ? sRDSAddChar[msgElement[UECP_ME_DATA+i]-0x80] : msgElement[UECP_ME_DATA+i];
+ }
+ memcpy(m_RTPlus_WorkText, temptext, RT_MEL);
+ rds_entitychar(temptext);
+
+ // check repeats
+ bool repeat = false;
+ for (int ind = 0; ind < m_RT_MaxSize; ind++)
+ {
+ if (memcmp(m_RT_Text[ind], temptext, RT_MEL) == 0)
+ repeat = true;
+ }
+ if (!repeat)
+ {
+ memcpy(m_RT_Text[m_RT_Index], temptext, RT_MEL);
+
+ std::string rdsline = m_RT_Text[m_RT_Index];
+ rtrim_str(rdsline);
+ g_charsetConverter.unknownToUTF8(rdsline);
+ m_RT.push_front(StringUtils::Trim(rdsline));
+
+ if ((int)m_RT.size() > m_RT_MaxSize)
+ m_RT.pop_back();
+
+ m_RT_Index++;
+ if (m_RT_Index >= m_RT_MaxSize)
+ m_RT_Index = 0;
+ }
+ m_RTPlus_iToggle = 0x03; // Bit 0/1 = Title/Artist
+ }
+ return msgLength+4;
+}
+
+#define UECP_CLOCK_YEAR 1
+#define UECP_CLOCK_MONTH 2
+#define UECP_CLOCK_DAY 3
+#define UECP_CLOCK_HOURS 4
+#define UECP_CLOCK_MINUTES 5
+#define UECP_CLOCK_SECONDS 6
+#define UECP_CLOCK_CENTSEC 7
+#define UECP_CLOCK_LOCALOFFSET 8
+unsigned int CDVDRadioRDSData::DecodeRTC(uint8_t *msgElement)
+{
+ uint8_t hours = msgElement[UECP_CLOCK_HOURS];
+ uint8_t minutes = msgElement[UECP_CLOCK_MINUTES];
+ bool minus = msgElement[UECP_CLOCK_LOCALOFFSET] & 0x20;
+ if (minus)
+ {
+ if (msgElement[UECP_CLOCK_LOCALOFFSET] >> 1)
+ hours -= msgElement[UECP_CLOCK_LOCALOFFSET] >> 1;
+ if (msgElement[UECP_CLOCK_LOCALOFFSET] & 1)
+ minutes -= 30;
+ }
+ else
+ {
+ if (msgElement[UECP_CLOCK_LOCALOFFSET] >> 1)
+ hours += msgElement[UECP_CLOCK_LOCALOFFSET] >> 1;
+ if (msgElement[UECP_CLOCK_LOCALOFFSET] & 1)
+ minutes += 30;
+ }
+ m_RTC_DateTime.SetDateTime(msgElement[UECP_CLOCK_YEAR], msgElement[UECP_CLOCK_MONTH], msgElement[UECP_CLOCK_DAY],
+ hours, minutes, msgElement[UECP_CLOCK_SECONDS]);
+
+ CLog::Log(LOGDEBUG, "Radio UECP (RDS) - %s - Current RDS Data Time: %02i.%02i.%02i - UTC: %02i:%02i:%02i,0.%is - Local: %c%i min",
+ __FUNCTION__, msgElement[UECP_CLOCK_DAY], msgElement[UECP_CLOCK_MONTH], msgElement[UECP_CLOCK_YEAR],
+ msgElement[UECP_CLOCK_HOURS], msgElement[UECP_CLOCK_MINUTES], msgElement[UECP_CLOCK_SECONDS],
+ msgElement[UECP_CLOCK_CENTSEC], minus ? '-' : '+', msgElement[UECP_CLOCK_LOCALOFFSET]*30);
+
+ CVariant data(CVariant::VariantTypeObject);
+ data["dateTime"] = (m_RTC_DateTime.IsValid()) ? m_RTC_DateTime.GetAsRFC1123DateTime() : "";
+ ANNOUNCEMENT::CAnnouncementManager::GetInstance().Announce(ANNOUNCEMENT::PVR, "xbmc", "RDSRadioRTC", data);
+
+ return 8;
+}
+
+unsigned int CDVDRadioRDSData::DecodeODA(uint8_t *msgElement, unsigned int len)
+{
+ unsigned int procData = msgElement[1];
+ if (procData == 0 || procData > len-2)
+ {
+ CLog::Log(LOGERROR, "Radio UECP (RDS) - Invalid ODA data size");
+ m_UECPDataDeadBreak = true;
+ return 0;
+ }
+
+ switch ((msgElement[2]<<8)+msgElement[3]) // ODA-ID
+ {
+ case 0x4bd7: //!< RT+
+ procData = DecodeRTPlus(msgElement, len);
+ break;
+ case 0x0d45: //!< TMC Alert-C
+ case 0xcd46:
+ SendTMCSignal(msgElement[4], msgElement+5);
+ break;
+ default:
+ m_UECPDataDeadBreak = true;
+#ifdef RDS_IMPROVE_CHECK
+ printf("[RDS-ODA AID '%02x%02x' not used -> End]\n", msgElement[2], msgElement[3]);
+#endif // RDS_IMPROVE_CHECK
+ break;
+ }
+ return procData;
+}
+
+unsigned int CDVDRadioRDSData::DecodeRTPlus(uint8_t *msgElement, unsigned int len)
+{
+ if (m_RTPlus_iToggle == 0) // RTplus tags V2.1, only if RT
+ return 10;
+
+ if (!m_RTPlus_Present)
+ {
+ m_currentInfoTag->SetPlayingRadiotextPlus(true);
+ m_RTPlus_Present = true;
+ }
+
+ if (msgElement[1] > len-2 || msgElement[1] != 8) // byte 6 = MEL, only 8 byte for 2 tags
+ {
+ CLog::Log(LOGERROR, "Radio UECP (RDS) - %s - RTp-Error: Length not correct (MEL= %d)", __FUNCTION__, msgElement[1]);
+ m_UECPDataDeadBreak = true;
+ return 0;
+ }
+ unsigned int rtp_typ[2], rtp_start[2], rtp_len[2];
+ // byte 2+3 = ApplicationID, always 0x4bd7
+ // byte 4 = Applicationgroup Typecode / PTY ?
+ // bit 10#4 = Item Togglebit
+ // bit 10#3 = Item Runningbit321
+ // Tag1: bit 10#2..11#5 = Contenttype, 11#4..12#7 = Startmarker, 12#6..12#1 = Length
+ rtp_typ[0] = (0x38 & msgElement[5]<<3) | msgElement[6]>>5;
+ rtp_start[0] = (0x3e & msgElement[6]<<1) | msgElement[7]>>7;
+ rtp_len[0] = 0x3f & msgElement[7]>>1;
+ // Tag2: bit 12#0..13#3 = Contenttype, 13#2..14#5 = Startmarker, 14#4..14#0 = Length(5bit)
+ rtp_typ[1] = (0x20 & msgElement[7]<<5) | msgElement[8]>>3;
+ rtp_start[1] = (0x38 & msgElement[8]<<3) | msgElement[9]>>5;
+ rtp_len[1] = 0x1f & msgElement[9];
+
+ /// Hack for error on BR Classic
+ if ((msgElement[5]&0x10) && (msgElement[5]&0x08) && rtp_typ[0] == RTPLUS_INFO_URL && rtp_typ[1] == RTPLUS_ITEM_ARTIST)
+ return 10;
+
+ // save info
+ MUSIC_INFO::CMusicInfoTag *currentMusic = g_application.CurrentFileItem().GetMusicInfoTag();
+
+ for (int i = 0; i < 2; i++)
+ {
+ if (rtp_start[i]+rtp_len[i]+1 >= RT_MEL) // length-error
+ {
+ CLog::Log(LOGERROR, "Radio UECP (RDS) - %s - (tag#%d = Typ/Start/Len): %d/%d/%d (Start+Length > 'RT-MEL' !)", __FUNCTION__, i+1, rtp_typ[i], rtp_start[i], rtp_len[i]);
+ }
+ else
+ {
+ // +Memory
+ memset(m_RTPlus_Temptext, 0x20, RT_MEL);
+ memcpy(m_RTPlus_Temptext, m_RTPlus_WorkText+rtp_start[i], rtp_len[i]+1);
+ m_RTPlus_Temptext[rtp_len[i]+1] = 0;
+ rds_entitychar(m_RTPlus_Temptext);
+ switch (rtp_typ[i])
+ {
+ case RTPLUS_DUMMY_CLASS:
+ break;
+ case RTPLUS_ITEM_TITLE: // Item-Title...
+ if ((msgElement[5] & 0x08) > 0 && (m_RTPlus_iToggle & 0x01) == 0x01)
+ {
+ m_RTPlus_iToggle -= 0x01;
+ if (memcmp(m_RTPlus_Title, m_RTPlus_Temptext, RT_MEL) != 0 || (msgElement[5] & 0x10) != m_RTPlus_ItemToggle)
+ {
+ memcpy(m_RTPlus_Title, m_RTPlus_Temptext, RT_MEL);
+ if (m_RTPlus_Show && m_RTPlus_iTime.GetElapsedSeconds() > 1)
+ m_RTPlus_iDiffs = (int) m_RTPlus_iTime.GetElapsedSeconds();
+ if (!m_RT_NewItem)
+ {
+ m_RTPlus_Starttime = time(NULL);
+ m_RTPlus_iTime.StartZero();
+ m_RTPlus_Artist[0] = 0;
+ }
+ m_RT_NewItem = (!m_RT_NewItem) ? true : false;
+ m_RTPlus_Show = m_RTPlus_TToggle = true;
+ }
+ }
+ break;
+ case RTPLUS_ITEM_ALBUM:
+ m_currentInfoTag->SetAlbum(m_RTPlus_Temptext);
+ currentMusic->SetAlbum(m_RTPlus_Temptext);
+ break;
+ case RTPLUS_ITEM_TRACKNUMBER:
+ m_currentInfoTag->SetAlbumTrackNumber(atoi(m_RTPlus_Temptext));
+ currentMusic->SetAlbumId(atoi(m_RTPlus_Temptext));
+ break;
+ case RTPLUS_ITEM_ARTIST: // Item-Artist..
+ if ((msgElement[5] & 0x08) > 0 && (m_RTPlus_iToggle & 0x02) == 0x02)
+ {
+ m_RTPlus_iToggle -= 0x02;
+ if (memcmp(m_RTPlus_Artist, m_RTPlus_Temptext, RT_MEL) != 0 || (msgElement[5] & 0x10) != m_RTPlus_ItemToggle)
+ {
+ memcpy(m_RTPlus_Artist, m_RTPlus_Temptext, RT_MEL);
+ if (m_RTPlus_Show && m_RTPlus_iTime.GetElapsedSeconds() > 1)
+ m_RTPlus_iDiffs = (int) m_RTPlus_iTime.GetElapsedSeconds();
+ if (!m_RT_NewItem)
+ {
+ m_RTPlus_Starttime = time(NULL);
+ m_RTPlus_iTime.StartZero();
+ m_RTPlus_Title[0] = 0;
+ }
+ m_RT_NewItem = (!m_RT_NewItem) ? true : false;
+ m_RTPlus_Show = m_RTPlus_TToggle = true;
+ }
+ }
+ break;
+ case RTPLUS_ITEM_CONDUCTOR:
+ m_currentInfoTag->SetConductor(m_RTPlus_Temptext);
+ break;
+ case RTPLUS_ITEM_COMPOSER:
+ case RTPLUS_ITEM_COMPOSITION:
+ m_currentInfoTag->SetComposer(m_RTPlus_Temptext);
+ if (m_currentInfoTag->GetRadioStyle() == "unknown")
+ m_currentInfoTag->SetRadioStyle("classical");
+ break;
+ case RTPLUS_ITEM_BAND:
+ m_currentInfoTag->SetBand(m_RTPlus_Temptext);
+ break;
+ case RTPLUS_ITEM_COMMENT:
+ m_currentInfoTag->SetComment(m_RTPlus_Temptext);
+ break;
+ case RTPLUS_ITEM_GENRE:
+ {
+ std::string str = m_RTPlus_Temptext;
+ g_charsetConverter.unknownToUTF8(str);
+ m_RTPlus_GenrePresent = true;
+ m_currentInfoTag->SetProgStyle(str);
+ }
+ break;
+ case RTPLUS_INFO_NEWS: // Info_News
+ m_currentInfoTag->SetInfoNews(m_RTPlus_Temptext);
+ break;
+ case RTPLUS_INFO_NEWS_LOCAL: // Info_NewsLocal
+ m_currentInfoTag->SetInfoNewsLocal(m_RTPlus_Temptext);
+ break;
+ case RTPLUS_INFO_STOCKMARKET: // Info_Stockmarket
+ m_currentInfoTag->SetInfoStock(m_RTPlus_Temptext);
+ break;
+ case RTPLUS_INFO_SPORT: // Info_Sport
+ m_currentInfoTag->SetInfoSport(m_RTPlus_Temptext);
+ break;
+ case RTPLUS_INFO_LOTTERY: // Info_Lottery
+ m_currentInfoTag->SetInfoLottery(m_RTPlus_Temptext);
+ break;
+ case RTPLUS_INFO_HOROSCOPE:
+ m_currentInfoTag->SetInfoHoroscope(m_RTPlus_Temptext);
+ break;
+ case RTPLUS_INFO_CINEMA:
+ m_currentInfoTag->SetInfoCinema(m_RTPlus_Temptext);
+ break;
+ case RTPLUS_INFO_WEATHER: // Info_Weather/
+ m_currentInfoTag->SetInfoWeather(m_RTPlus_Temptext);
+ break;
+ case RTPLUS_INFO_URL: // Info_Url
+ if (m_currentInfoTag->GetProgWebsite().empty())
+ m_currentInfoTag->SetProgWebsite(m_RTPlus_Temptext);
+ break;
+ case RTPLUS_INFO_OTHER: // Info_Other
+ m_currentInfoTag->SetInfoOther(m_RTPlus_Temptext);
+ break;
+ case RTPLUS_STATIONNAME_LONG: // Programme_Stationname.Long
+ m_currentInfoTag->SetProgStation(m_RTPlus_Temptext);
+ break;
+ case RTPLUS_PROGRAMME_NOW: // Programme_Now
+ m_currentInfoTag->SetProgNow(m_RTPlus_Temptext);
+ break;
+ case RTPLUS_PROGRAMME_NEXT: // Programme_Next
+ m_currentInfoTag->SetProgNext(m_RTPlus_Temptext);
+ break;
+ case RTPLUS_PROGRAMME_HOST: // Programme_Host
+ m_currentInfoTag->SetProgHost(m_RTPlus_Temptext);
+ break;
+ case RTPLUS_PROGRAMME_EDITORIAL_STAFF: // Programme_EditorialStaff
+ m_currentInfoTag->SetEditorialStaff(m_RTPlus_Temptext);
+ break;
+ case RTPLUS_PROGRAMME_HOMEPAGE: // Programme_Homepage
+ m_currentInfoTag->SetProgWebsite(m_RTPlus_Temptext);
+ break;
+ case RTPLUS_PHONE_HOTLINE: // Phone_Hotline
+ m_currentInfoTag->SetPhoneHotline(m_RTPlus_Temptext);
+ break;
+ case RTPLUS_PHONE_STUDIO: // Phone_Studio
+ m_currentInfoTag->SetPhoneStudio(m_RTPlus_Temptext);
+ break;
+ case RTPLUS_SMS_STUDIO: // SMS_Studio
+ m_currentInfoTag->SetSMSStudio(m_RTPlus_Temptext);
+ break;
+ case RTPLUS_EMAIL_HOTLINE: // Email_Hotline
+ m_currentInfoTag->SetEMailHotline(m_RTPlus_Temptext);
+ break;
+ case RTPLUS_EMAIL_STUDIO: // Email_Studio
+ m_currentInfoTag->SetEMailStudio(m_RTPlus_Temptext);
+ break;
+ /**
+ * Currently unused radiotext plus messages
+ * Must be check where present and if it is usable
+ */
+ case RTPLUS_ITEM_MOVEMENT:
+ case RTPLUS_INFO_DAILY_DIVERSION:
+ case RTPLUS_INFO_HEALTH:
+ case RTPLUS_INFO_EVENT:
+ case RTPLUS_INFO_SZENE:
+ case RTPLUS_INFO_STUPIDITY_MACHINE:
+ case RTPLUS_INFO_TRAFFIC:
+ case RTPLUS_INFO_ALARM:
+ case RTPLUS_INFO_ADVERTISEMENT:
+ case RTPLUS_PROGRAMME_PART:
+ case RTPLUS_PROGRAMME_FREQUENCY:
+ case RTPLUS_PROGRAMME_SUBCHANNEL:
+ case RTPLUS_PHONE_OTHER:
+ case RTPLUS_SMS_OTHER:
+ case RTPLUS_EMAIL_OTHER:
+ case RTPLUS_MMS_OTHER:
+ case RTPLUS_CHAT:
+ case RTPLUS_CHAT_CENTER:
+ case RTPLUS_VOTE_QUESTION:
+ case RTPLUS_VOTE_CENTER:
+ case RTPLUS_PLACE:
+ case RTPLUS_APPOINTMENT:
+ case RTPLUS_IDENTIFIER:
+ case RTPLUS_PURCHASE:
+ case RTPLUS_GET_DATA:
+#ifdef RDS_IMPROVE_CHECK
+ printf(" RTp-Unkn. : %02i - %s\n", rtp_typ[i], m_RTPlus_Temptext);
+ break;
+#endif // RDS_IMPROVE_CHECK
+ /// Unused and not needed data informations
+ case RTPLUS_STATIONNAME_SHORT: //!< Must be rechecked under DAB
+ case RTPLUS_INFO_DATE_TIME:
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ // Title-end @ no Item-Running'
+ if ((msgElement[5] & 0x08) == 0)
+ {
+ m_RTPlus_Title[0] = 0;
+ m_RTPlus_Artist[0] = 0;
+ m_currentInfoTag->ResetSongInformation();
+ currentMusic->SetAlbum("");
+ if (m_RTPlus_GenrePresent)
+ {
+ m_currentInfoTag->SetProgStyle("");
+ m_RTPlus_GenrePresent = false;
+ }
+
+ if (m_RTPlus_Show)
+ {
+ m_RTPlus_Show = false;
+ m_RTPlus_TToggle = true;
+ m_RTPlus_iDiffs = (int) m_RTPlus_iTime.GetElapsedSeconds();
+ m_RTPlus_Starttime = time(NULL);
+ }
+ m_RT_NewItem = false;
+ }
+
+ if (m_RTPlus_TToggle)
+ {
+#ifdef RDS_IMPROVE_CHECK
+ {
+ struct tm tm_store;
+ struct tm *ts = localtime_r(&m_RTPlus_Starttime, &tm_store);
+ if (m_RTPlus_iDiffs > 0)
+ printf(" StartTime : %02d:%02d:%02d (last Title elapsed = %d s)\n", ts->tm_hour, ts->tm_min, ts->tm_sec, m_RTPlus_iDiffs);
+ else
+ printf(" StartTime : %02d:%02d:%02d\n", ts->tm_hour, ts->tm_min, ts->tm_sec);
+ printf(" RTp-Title : %s\n RTp-Artist: %s\n", m_RTPlus_Title, m_RTPlus_Artist);
+ }
+#endif // RDS_IMPROVE_CHECK
+ m_RTPlus_ItemToggle = msgElement[5] & 0x10;
+ m_RTPlus_TToggle = false;
+ m_RTPlus_iDiffs = 0;
+
+ std::string str;
+
+ str = m_RTPlus_Artist;
+ m_currentInfoTag->SetArtist(str);
+ if (str.empty() && !m_currentInfoTag->GetComposer().empty())
+ str = m_currentInfoTag->GetComposer();
+ else if (str.empty() && !m_currentInfoTag->GetConductor().empty())
+ str = m_currentInfoTag->GetConductor();
+ else if (str.empty() && !m_currentInfoTag->GetBand().empty())
+ str = m_currentInfoTag->GetBand();
+
+ if (!str.empty())
+ g_charsetConverter.unknownToUTF8(str);
+ else if (m_currentChannel)
+ str = m_currentChannel->ChannelName();
+ currentMusic->SetArtist(str);
+
+ str = m_RTPlus_Title;
+ g_charsetConverter.unknownToUTF8(str);
+ currentMusic->SetTitle(str);
+ m_currentInfoTag->SetTitle(str);
+ m_currentFileUpdate = true;
+ }
+ m_RTPlus_iToggle = 0;
+
+ return 10;
+}
+
+unsigned int CDVDRadioRDSData::DecodeTMC(uint8_t *msgElement, unsigned int len)
+{
+ unsigned int msgElementLength = msgElement[1];
+ if (msgElementLength == 0)
+ msgElementLength = 6;
+ if (msgElementLength + 2 > len)
+ {
+ m_UECPDataDeadBreak = true;
+ return 0;
+ }
+
+ for (unsigned int i = 0; i < msgElementLength; i += 5)
+ SendTMCSignal(msgElement[2], msgElement+3+i);
+
+ return msgElementLength + 2;
+}
+
+unsigned int CDVDRadioRDSData::DecodeEPPTransmitterInfo(uint8_t *msgElement)
+{
+ if (!m_RDS_SlowLabelingCodesPresent && m_PI_CountryCode != 0)
+ {
+ int codeHigh = msgElement[2]&0xF0;
+ int codeLow = msgElement[2]&0x0F;
+ if (codeLow > 7)
+ {
+ CLog::Log(LOGERROR, "Radio RDS - %s - invalid country code 0x%02X%02X", __FUNCTION__, codeHigh, codeLow);
+ return 7;
+ }
+
+ std::string countryName;
+ switch (codeHigh)
+ {
+ case 0xA0:
+ countryName = piCountryCodes_A[m_PI_CountryCode-1][codeLow];
+ break;
+ case 0xD0:
+ countryName = piCountryCodes_D[m_PI_CountryCode-1][codeLow];
+ break;
+ case 0xE0:
+ countryName = piCountryCodes_E[m_PI_CountryCode-1][codeLow];
+ break;
+ case 0xF0:
+ countryName = piCountryCodes_F[m_PI_CountryCode-1][codeLow];
+ break;
+ default:
+ CLog::Log(LOGERROR, "Radio RDS - %s - invalid extended country region code:%02X%02X", __FUNCTION__, codeHigh, codeLow);
+ return 7;
+ }
+
+ m_RDS_IsRBDS = countryName == "US" ? true : false;
+
+ m_currentInfoTag->SetCountry(countryName);
+ }
+
+ return 7;
+}
+
+/* SLOW LABELLING: see page 23 in the standard
+ * for paging see page 90, Annex M in the standard (NOT IMPLEMENTED)
+ * for extended country codes see page 69, Annex D.2 in the standard
+ * for language codes see page 84, Annex J in the standard
+ * for emergency warning systems (EWS) see page 53 in the standard */
+#define VARCODE_PAGING_EXTCOUNTRYCODE 0
+#define VARCODE_TMC_IDENT 1
+#define VARCODE_PAGING_IDENT 2
+#define VARCODE_LANGUAGE_CODES 3
+#define VARCODE_OWN_BROADCASTER 6
+#define VARCODE_EWS_CHANNEL_IDENT 7
+unsigned int CDVDRadioRDSData::DecodeSlowLabelingCodes(uint8_t *msgElement)
+{
+ uint16_t slowLabellingCode = (msgElement[2]<<8 | msgElement[3]) & 0xfff;
+ int VariantCode = (msgElement[2]>>4) & 0x7;
+
+ switch (VariantCode)
+ {
+ case VARCODE_PAGING_EXTCOUNTRYCODE: // paging + ecc
+ {
+ // int paging = (slowLabellingCode>>8)&0x0f; unused
+
+ if (m_PI_CountryCode != 0)
+ {
+ int codeHigh = slowLabellingCode&0xF0;
+ int codeLow = slowLabellingCode&0x0F;
+ if (codeLow > 5)
+ {
+ CLog::Log(LOGERROR, "Radio RDS - %s - invalid country code 0x%02X%02X", __FUNCTION__, codeHigh, codeLow);
+ return 4;
+ }
+
+ std::string countryName;
+ switch (codeHigh)
+ {
+ case 0xA0:
+ countryName = piCountryCodes_A[m_PI_CountryCode-1][codeLow];
+ break;
+ case 0xD0:
+ countryName = piCountryCodes_D[m_PI_CountryCode-1][codeLow];
+ break;
+ case 0xE0:
+ countryName = piCountryCodes_E[m_PI_CountryCode-1][codeLow];
+ break;
+ case 0xF0:
+ countryName = piCountryCodes_F[m_PI_CountryCode-1][codeLow];
+ break;
+ default:
+ CLog::Log(LOGERROR, "Radio RDS - %s - invalid extended country region code:%02X%02X", __FUNCTION__, codeHigh, codeLow);
+ return 4;
+ }
+
+ m_currentInfoTag->SetCountry(countryName);
+ }
+ break;
+ }
+ case VARCODE_LANGUAGE_CODES: // language codes
+ if (slowLabellingCode > 1 && slowLabellingCode < 0x80)
+ m_currentInfoTag->SetLanguage(piRDSLanguageCodes[slowLabellingCode]);
+ else
+ CLog::Log(LOGERROR, "Radio RDS - %s - invalid language code %i", __FUNCTION__, slowLabellingCode);
+ break;
+
+ case VARCODE_TMC_IDENT: // TMC identification
+ case VARCODE_PAGING_IDENT: // Paging identification
+ case VARCODE_OWN_BROADCASTER:
+ case VARCODE_EWS_CHANNEL_IDENT:
+ default:
+ break;
+ }
+
+ m_RDS_SlowLabelingCodesPresent = true;
+ return 4;
+}
+
+/*!
+ * currently unused need to be checked on DAB, processed here to have length of it
+ */
+unsigned int CDVDRadioRDSData::DecodeDABDynLabelCmd(uint8_t *msgElement, unsigned int len)
+{
+ unsigned int msgElementLength = msgElement[1];
+ if (msgElementLength < 1 || msgElementLength + 2 > len)
+ {
+ m_UECPDataDeadBreak = true;
+ return 0;
+ }
+
+ return msgElementLength+2;
+}
+
+/*!
+ * currently unused need to be checked on DAB, processed here to have length of it
+ */
+unsigned int CDVDRadioRDSData::DecodeDABDynLabelMsg(uint8_t *msgElement, unsigned int len)
+{
+ unsigned int msgElementLength = msgElement[1];
+ if (msgElementLength < 2 || msgElementLength + 2 > len)
+ {
+ m_UECPDataDeadBreak = true;
+ return 0;
+ }
+
+ return msgElementLength+2;
+}
+
+/*!
+ * unused processed here to have length of it
+ */
+unsigned int CDVDRadioRDSData::DecodeAF(uint8_t *msgElement, unsigned int len)
+{
+ unsigned int msgElementLength = msgElement[3];
+ if (msgElementLength < 3 || msgElementLength + 4 > len)
+ {
+ m_UECPDataDeadBreak = true;
+ return 0;
+ }
+
+ return msgElementLength+4;
+}
+
+/*!
+ * unused processed here to have length of it
+ */
+unsigned int CDVDRadioRDSData::DecodeEonAF(uint8_t *msgElement, unsigned int len)
+{
+ unsigned int msgElementLength = msgElement[3];
+ if (msgElementLength < 4 || msgElementLength + 4 > len)
+ {
+ m_UECPDataDeadBreak = true;
+ return 0;
+ }
+
+ return msgElementLength+4;
+}
+
+/*!
+ * unused processed here to have length of it
+ */
+unsigned int CDVDRadioRDSData::DecodeTDC(uint8_t *msgElement, unsigned int len)
+{
+ unsigned int msgElementLength = msgElement[1];
+ if (msgElementLength < 2 || msgElementLength+2 > len)
+ {
+ m_UECPDataDeadBreak = true;
+ return 0;
+ }
+
+ return msgElementLength+2;
+}
+
+void CDVDRadioRDSData::SendTMCSignal(unsigned int flags, uint8_t *data)
+{
+ if (!CSettings::GetInstance().GetBool("pvrplayback.sendrdstrafficmsg"))
+ return;
+
+ if (!(flags & 0x80) && (memcmp(data, m_TMC_LastData, 5) == 0))
+ return;
+
+ memcpy(m_TMC_LastData, data, 5);
+
+ if (m_currentChannel)
+ {
+ CVariant msg(CVariant::VariantTypeObject);
+ msg["channel"] = m_currentChannel->ChannelName();
+ msg["ident"] = m_PI_Current;
+ msg["flags"] = flags;
+ msg["x"] = m_TMC_LastData[0];
+ msg["y"] = (unsigned int)(m_TMC_LastData[1]<<8 | m_TMC_LastData[2]);
+ msg["z"] = (unsigned int)(m_TMC_LastData[3]<<8 | m_TMC_LastData[4]);
+
+ ANNOUNCEMENT::CAnnouncementManager::GetInstance().Announce(ANNOUNCEMENT::PVR, "xbmc", "RDSRadioTMC", msg);
+ }
+}
diff --git a/xbmc/cores/dvdplayer/DVDPlayerRadioRDS.h b/xbmc/cores/dvdplayer/DVDPlayerRadioRDS.h
new file mode 100644
index 0000000000..42f2610ade
--- /dev/null
+++ b/xbmc/cores/dvdplayer/DVDPlayerRadioRDS.h
@@ -0,0 +1,161 @@
+#pragma once
+/*
+ * Copyright (C) 2005-2015 Team KODI
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this Software; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include <deque>
+
+#include "IDVDPlayer.h"
+#include "DVDMessageQueue.h"
+#include "FileItem.h"
+#include "threads/Thread.h"
+#include "utils/Stopwatch.h"
+
+class CDVDStreamInfo;
+
+/// --- CDVDRadioRDSData ------------------------------------------------------------
+
+#define UECP_DATA_START 0xFE /*!< A data record starts with the start byte */
+#define UECP_DATA_STOP 0xFF /*!< A data record stops with the stop byte */
+#define UECP_SIZE_MAX 263 /*!< The Max possible size of a UECP packet
+ max. 255(MSG)+4(ADD/SQC/MFL)+2(CRC)+2(Start/Stop) of RDS-data */
+#define RT_MEL 65
+#define MAX_RTPC 50
+#define MAX_RADIOTEXT_LISTSIZE 6
+
+class CDVDRadioRDSData : public CThread, public IDVDStreamPlayer
+{
+public:
+ CDVDRadioRDSData();
+ virtual ~CDVDRadioRDSData();
+
+ bool CheckStream(CDVDStreamInfo &hints);
+ bool OpenStream(CDVDStreamInfo &hints);
+ void CloseStream(bool bWaitForBuffers);
+ void Flush();
+
+ // waits until all available data has been rendered
+ void WaitForBuffers() { m_messageQueue.WaitUntilEmpty(); }
+ bool AcceptsData() const { return !m_messageQueue.IsFull(); }
+ void SendMessage(CDVDMsg* pMsg, int priority = 0) { if(m_messageQueue.IsInited()) m_messageQueue.Put(pMsg, priority); }
+ void FlushMessages() { m_messageQueue.Flush(); }
+ bool IsInited() const { return true; }
+ bool IsStalled() const { return true; }
+
+ std::string GetRadioText(unsigned int line);
+
+protected:
+ virtual void OnExit();
+ virtual void Process();
+
+private:
+ void ResetRDSCache();
+ void ProcessUECP(const unsigned char *Data, unsigned int Length);
+
+ inline unsigned int DecodePI(uint8_t *msgElement);
+ inline unsigned int DecodePS(uint8_t *msgElement);
+ inline unsigned int DecodeDI(uint8_t *msgElement);
+ inline unsigned int DecodeTA_TP(uint8_t *msgElement);
+ inline unsigned int DecodeMS(uint8_t *msgElement);
+ inline unsigned int DecodePTY(uint8_t *msgElement);
+ inline unsigned int DecodePTYN(uint8_t *msgElement);
+ inline unsigned int DecodeRT(uint8_t *msgElement, unsigned int len);
+ inline unsigned int DecodeRTC(uint8_t *msgElement);
+ inline unsigned int DecodeODA(uint8_t *msgElement, unsigned int len);
+ inline unsigned int DecodeRTPlus(uint8_t *msgElement, unsigned int len);
+ inline unsigned int DecodeTMC(uint8_t *msgElement, unsigned int len);
+ inline unsigned int DecodeEPPTransmitterInfo(uint8_t *msgElement);
+ inline unsigned int DecodeSlowLabelingCodes(uint8_t *msgElement);
+ inline unsigned int DecodeDABDynLabelCmd(uint8_t *msgElement, unsigned int len);
+ inline unsigned int DecodeDABDynLabelMsg(uint8_t *msgElement, unsigned int len);
+ inline unsigned int DecodeAF(uint8_t *msgElement, unsigned int len);
+ inline unsigned int DecodeEonAF(uint8_t *msgElement, unsigned int len);
+ inline unsigned int DecodeTDC(uint8_t *msgElement, unsigned int len);
+
+ void SendTMCSignal(unsigned int flags, uint8_t *data);
+ void SetRadioStyle(std::string genre);
+
+ PVR::CPVRRadioRDSInfoTagPtr m_currentInfoTag;
+ PVR::CPVRChannelPtr m_currentChannel;
+ bool m_currentFileUpdate;
+ int m_speed;
+ CCriticalSection m_critSection;
+ CDVDMessageQueue m_messageQueue;
+
+ uint8_t m_UECPData[UECP_SIZE_MAX+1];
+ unsigned int m_UECPDataIndex;
+ bool m_UECPDataStart;
+ bool m_UECPDatabStuff;
+ bool m_UECPDataDeadBreak;
+
+ bool m_RDS_IsRBDS;
+ bool m_RDS_SlowLabelingCodesPresent;
+
+ uint16_t m_PI_Current;
+ unsigned int m_PI_CountryCode;
+ unsigned int m_PI_ProgramType;
+ unsigned int m_PI_ProgramReferenceNumber;
+
+ unsigned int m_EPP_TM_INFO_ExtendedCountryCode;
+
+ #define PS_TEXT_ENTRIES 12
+ bool m_PS_Present;
+ int m_PS_Index;
+ char m_PS_Text[PS_TEXT_ENTRIES][9];
+
+ bool m_DI_IsStereo;
+ bool m_DI_ArtificialHead;
+ bool m_DI_Compressed;
+ bool m_DI_DynamicPTY;
+
+ bool m_TA_TP_TrafficAdvisory;
+ float m_TA_TP_TrafficVolume;
+
+ bool m_MS_SpeechActive;
+
+ int m_PTY;
+ char m_PTYN[9];
+ bool m_PTYN_Present;
+
+ bool m_RT_Present;
+ std::deque<std::string> m_RT;
+ int m_RT_Index;
+ int m_RT_MaxSize;
+ bool m_RT_NewItem;
+ char m_RT_Text[6][RT_MEL+1];
+
+ bool m_RTPlus_Present;
+ uint8_t m_RTPlus_WorkText[RT_MEL+1];
+ bool m_RTPlus_TToggle;
+ int m_RTPlus_iDiffs;
+ CStopWatch m_RTPlus_iTime;
+ bool m_RTPlus_GenrePresent;
+ char m_RTPlus_Temptext[RT_MEL];
+ bool m_RTPlus_Show;
+ char m_RTPlus_Title[RT_MEL];
+ char m_RTPlus_Artist[RT_MEL];
+ int m_RTPlus_iToggle;
+ unsigned int m_RTPlus_ItemToggle;
+ time_t m_RTPlus_Starttime;
+
+ CDateTime m_RTC_DateTime; ///< From RDS transmitted date / time data
+
+ uint8_t m_TMC_LastData[5];
+};
diff --git a/xbmc/cores/dvdplayer/Makefile.in b/xbmc/cores/dvdplayer/Makefile.in
index da92fad671..08b2e12277 100644
--- a/xbmc/cores/dvdplayer/Makefile.in
+++ b/xbmc/cores/dvdplayer/Makefile.in
@@ -10,6 +10,7 @@ SRCS += DVDOverlayContainer.cpp
SRCS += DVDOverlayRenderer.cpp
SRCS += DVDPlayer.cpp
SRCS += DVDPlayerAudio.cpp
+SRCS += DVDPlayerRadioRDS.cpp
SRCS += DVDPlayerSubtitle.cpp
SRCS += DVDPlayerTeletext.cpp
SRCS += DVDPlayerVideo.cpp
diff --git a/xbmc/dialogs/GUIDialogKeyboardGeneric.cpp b/xbmc/dialogs/GUIDialogKeyboardGeneric.cpp
index 2ec134dff8..8e06112c29 100644
--- a/xbmc/dialogs/GUIDialogKeyboardGeneric.cpp
+++ b/xbmc/dialogs/GUIDialogKeyboardGeneric.cpp
@@ -600,7 +600,7 @@ void CGUIDialogKeyboardGeneric::ChangeWordList(int direct)
else
{
ShowWordList(direct);
- if (direct > 0 && m_pos + m_num == m_words.size())
+ if (direct > 0 && m_pos + m_num == static_cast<int>(m_words.size()))
m_codingtable->GetWordListPage(m_hzcode, false);
}
}
@@ -619,9 +619,9 @@ void CGUIDialogKeyboardGeneric::ShowWordList(int direct)
{
if (direct > 0)
m_pos += m_num;
- if (m_pos > m_words.size() - 1)
+ if (m_pos > static_cast<int>(m_words.size()) - 1)
m_pos = 0;
- for (i = 0; m_pos + i < m_words.size(); i++)
+ for (i = 0; m_pos + i < static_cast<int>(m_words.size()); i++)
{
if ((i > 0 && width + GetStringWidth(m_words[m_pos + i]) + numwidth > m_listwidth) || i > 9)
break;
@@ -656,7 +656,7 @@ void CGUIDialogKeyboardGeneric::ShowWordList(int direct)
hzlist.erase(hzlist.find_last_not_of(L" ") + 1);
if (m_pos > 0)
hzlist.insert(0, 1, L'<');
- if (m_pos + m_num < m_words.size())
+ if (m_pos + m_num < static_cast<int>(m_words.size()))
hzlist.insert(hzlist.length(), 1, L'>');
std::string utf8String;
g_charsetConverter.wToUTF8(hzlist, utf8String);
diff --git a/xbmc/dialogs/GUIDialogYesNo.cpp b/xbmc/dialogs/GUIDialogYesNo.cpp
index b4860d91ce..04d5194c7f 100644
--- a/xbmc/dialogs/GUIDialogYesNo.cpp
+++ b/xbmc/dialogs/GUIDialogYesNo.cpp
@@ -21,6 +21,7 @@
#include "GUIDialogYesNo.h"
#include "guilib/GUIWindowManager.h"
#include "input/Key.h"
+#include "messaging/helpers/DialogHelper.h"
#define CONTROL_NO_BUTTON 10
#define CONTROL_YES_BUTTON 11
@@ -85,7 +86,7 @@ bool CGUIDialogYesNo::ShowAndGetInput(CVariant heading, CVariant line0, CVariant
bool CGUIDialogYesNo::ShowAndGetInput(CVariant heading, CVariant line0, CVariant line1, CVariant line2, bool &bCanceled, CVariant noLabel, CVariant yesLabel, unsigned int autoCloseTime)
{
- CGUIDialogYesNo *dialog = (CGUIDialogYesNo *)g_windowManager.GetWindow(WINDOW_DIALOG_YES_NO);
+ CGUIDialogYesNo *dialog = static_cast<CGUIDialogYesNo *>(g_windowManager.GetWindow(WINDOW_DIALOG_YES_NO));
if (!dialog)
return false;
@@ -112,7 +113,7 @@ bool CGUIDialogYesNo::ShowAndGetInput(CVariant heading, CVariant text)
bool CGUIDialogYesNo::ShowAndGetInput(CVariant heading, CVariant text, bool &bCanceled, CVariant noLabel /* = "" */, CVariant yesLabel /* = "" */, unsigned int autoCloseTime)
{
- CGUIDialogYesNo *dialog = (CGUIDialogYesNo *)g_windowManager.GetWindow(WINDOW_DIALOG_YES_NO);
+ CGUIDialogYesNo *dialog = static_cast<CGUIDialogYesNo *>(g_windowManager.GetWindow(WINDOW_DIALOG_YES_NO));
if (!dialog)
return false;
@@ -129,6 +130,36 @@ bool CGUIDialogYesNo::ShowAndGetInput(CVariant heading, CVariant text, bool &bCa
return (dialog->IsConfirmed()) ? true : false;
}
+int CGUIDialogYesNo::ShowAndGetInput(const KODI::MESSAGING::HELPERS::DialogYesNoMessage& options)
+{
+ //Set default yes/no labels, these might be overwritten further down if specified
+ //by the caller
+ SetChoice(0, 106);
+ SetChoice(1, 107);
+ if (!options.heading.isNull())
+ SetHeading(options.heading);
+ if (!options.text.isNull())
+ SetText(options.text);
+ if (!options.noLabel.isNull())
+ SetChoice(0, options.noLabel);
+ if (!options.yesLabel.isNull())
+ SetChoice(1, options.yesLabel);
+ if (options.autoclose > 0)
+ SetAutoClose(options.autoclose);
+
+ for (size_t i = 0; i < 3; ++i)
+ {
+ if (!options.lines[i].isNull())
+ SetLine(i, options.lines[i]);
+ }
+
+ Open();
+ if (m_bCanceled)
+ return -1;
+
+ return IsConfirmed() ? 1 : 0;
+}
+
int CGUIDialogYesNo::GetDefaultLabelID(int controlId) const
{
if (controlId == CONTROL_NO_BUTTON)
diff --git a/xbmc/dialogs/GUIDialogYesNo.h b/xbmc/dialogs/GUIDialogYesNo.h
index 2dcdc212a1..27d6279818 100644
--- a/xbmc/dialogs/GUIDialogYesNo.h
+++ b/xbmc/dialogs/GUIDialogYesNo.h
@@ -20,10 +20,20 @@
*
*/
-#include <string>
#include "GUIDialogBoxBase.h"
#include "utils/Variant.h"
+namespace KODI
+{
+ namespace MESSAGING
+ {
+ namespace HELPERS
+ {
+ struct DialogYesNoMessage;
+ }
+ }
+}
+
class CGUIDialogYesNo :
public CGUIDialogBoxBase
{
@@ -90,6 +100,17 @@ public:
*/
static bool ShowAndGetInput(CVariant heading, CVariant text, bool &bCanceled, CVariant noLabel, CVariant yesLabel, unsigned int autoCloseTime);
+ /*!
+ \brief Open a Yes/No dialog and wait for input
+
+ \param[in] options a struct of type DialogYesNoMessage containing
+ the options to set for this dialog.
+
+ \returns -1 for cancelled, 0 for No and 1 for Yes
+ \sa KODI::MESSAGING::HELPERS::DialogYesNoMessage
+ */
+ int ShowAndGetInput(const KODI::MESSAGING::HELPERS::DialogYesNoMessage& options);
+
protected:
virtual int GetDefaultLabelID(int controlId) const;
diff --git a/xbmc/filesystem/FileCache.cpp b/xbmc/filesystem/FileCache.cpp
index eb740be67e..ae7447dca7 100644
--- a/xbmc/filesystem/FileCache.cpp
+++ b/xbmc/filesystem/FileCache.cpp
@@ -32,8 +32,8 @@
#include <cassert>
#include <algorithm>
+#include <memory>
-using namespace AUTOPTR;
using namespace XFILE;
#define READ_CACHE_CHUNK_SIZE (64*1024)
@@ -249,7 +249,7 @@ void CFileCache::Process()
}
// create our read buffer
- auto_aptr<char> buffer(new char[m_chunkSize]);
+ std::unique_ptr<char[]> buffer(new char[m_chunkSize]);
if (buffer.get() == NULL)
{
CLog::Log(LOGERROR, "%s - failed to allocate read buffer", __FUNCTION__);
diff --git a/xbmc/filesystem/XbtFile.cpp b/xbmc/filesystem/XbtFile.cpp
index ec8d705c19..7839276afe 100644
--- a/xbmc/filesystem/XbtFile.cpp
+++ b/xbmc/filesystem/XbtFile.cpp
@@ -173,7 +173,7 @@ ssize_t CXbtFile::Read(void* lpBuf, size_t uiBufSize)
return 0;
// we can't read more than is left
- if (uiBufSize > GetLength() - m_positionTotal)
+ if (static_cast<int64_t>(uiBufSize) > GetLength() - m_positionTotal)
uiBufSize = static_cast<ssize_t>(GetLength() - m_positionTotal);
// we can't read more than we can signal with the return value
diff --git a/xbmc/guiinfo/GUIInfoLabels.h b/xbmc/guiinfo/GUIInfoLabels.h
index b8fe9237ca..e29ac9459e 100644
--- a/xbmc/guiinfo/GUIInfoLabels.h
+++ b/xbmc/guiinfo/GUIInfoLabels.h
@@ -495,6 +495,54 @@
#define ADSP_MASTER_OVERRIDE_ICON (ADSP_STRINGS_START + 10)
#define ADSP_STRINGS_END ADSP_MASTER_OVERRIDE_ICON
+#define RDS_DATA_START 1400
+#define RDS_HAS_RDS (RDS_DATA_START)
+#define RDS_HAS_RADIOTEXT (RDS_DATA_START + 1)
+#define RDS_HAS_RADIOTEXT_PLUS (RDS_DATA_START + 2)
+#define RDS_GET_RADIOTEXT_LINE (RDS_DATA_START + 3)
+#define RDS_TITLE (RDS_DATA_START + 4)
+#define RDS_BAND (RDS_DATA_START + 5)
+#define RDS_ARTIST (RDS_DATA_START + 6)
+#define RDS_COMPOSER (RDS_DATA_START + 7)
+#define RDS_CONDUCTOR (RDS_DATA_START + 8)
+#define RDS_ALBUM (RDS_DATA_START + 9)
+#define RDS_ALBUM_TRACKNUMBER (RDS_DATA_START + 10)
+#define RDS_GET_RADIO_STYLE (RDS_DATA_START + 11)
+#define RDS_COMMENT (RDS_DATA_START + 12)
+#define RDS_INFO_NEWS (RDS_DATA_START + 13)
+#define RDS_INFO_NEWS_LOCAL (RDS_DATA_START + 14)
+#define RDS_INFO_STOCK (RDS_DATA_START + 15)
+#define RDS_INFO_STOCK_SIZE (RDS_DATA_START + 16)
+#define RDS_INFO_SPORT (RDS_DATA_START + 17)
+#define RDS_INFO_SPORT_SIZE (RDS_DATA_START + 18)
+#define RDS_INFO_LOTTERY (RDS_DATA_START + 19)
+#define RDS_INFO_LOTTERY_SIZE (RDS_DATA_START + 20)
+#define RDS_INFO_WEATHER (RDS_DATA_START + 21)
+#define RDS_INFO_WEATHER_SIZE (RDS_DATA_START + 22)
+#define RDS_INFO_CINEMA (RDS_DATA_START + 23)
+#define RDS_INFO_CINEMA_SIZE (RDS_DATA_START + 24)
+#define RDS_INFO_HOROSCOPE (RDS_DATA_START + 25)
+#define RDS_INFO_HOROSCOPE_SIZE (RDS_DATA_START + 26)
+#define RDS_INFO_OTHER (RDS_DATA_START + 27)
+#define RDS_INFO_OTHER_SIZE (RDS_DATA_START + 28)
+#define RDS_PROG_STATION (RDS_DATA_START + 29)
+#define RDS_PROG_NOW (RDS_DATA_START + 30)
+#define RDS_PROG_NEXT (RDS_DATA_START + 31)
+#define RDS_PROG_HOST (RDS_DATA_START + 32)
+#define RDS_PROG_EDIT_STAFF (RDS_DATA_START + 33)
+#define RDS_PROG_HOMEPAGE (RDS_DATA_START + 34)
+#define RDS_PROG_STYLE (RDS_DATA_START + 35)
+#define RDS_PHONE_HOTLINE (RDS_DATA_START + 36)
+#define RDS_PHONE_STUDIO (RDS_DATA_START + 37)
+#define RDS_SMS_STUDIO (RDS_DATA_START + 38)
+#define RDS_EMAIL_HOTLINE (RDS_DATA_START + 39)
+#define RDS_EMAIL_STUDIO (RDS_DATA_START + 40)
+#define RDS_HAS_HOTLINE_DATA (RDS_DATA_START + 41)
+#define RDS_HAS_STUDIO_DATA (RDS_DATA_START + 42)
+#define RDS_AUDIO_LANG (RDS_DATA_START + 43)
+#define RDS_CHANNEL_COUNTRY (RDS_DATA_START + 44)
+#define RDS_DATA_END RDS_CHANNEL_COUNTRY
+
#define WINDOW_PROPERTY 9993
#define WINDOW_IS_TOPMOST 9994
#define WINDOW_IS_VISIBLE 9995
diff --git a/xbmc/guilib/AnimatedGif.cpp b/xbmc/guilib/AnimatedGif.cpp
deleted file mode 100644
index 8666a01efb..0000000000
--- a/xbmc/guilib/AnimatedGif.cpp
+++ /dev/null
@@ -1,663 +0,0 @@
-
-// ****************************************************************************
-//
-// WINIMAGE.CPP : Generic classes for raster images (MSWindows specialization)
-//
-// Content: Member definitions for:
-// - class CAnimatedGif : Storage class for single images
-// - class CAnimatedGifSet : Storage class for sets of images
-//
-// (Includes routines to Load and Save BMP files and to load GIF files into
-// these classes).
-//
-// --------------------------------------------------------------------------
-//
-// Copyright (c) 2000, Juan Soulie <jsoulie@cplusplus.com>
-//
-// Permission to use, copy, modify, distribute and sell this software or any
-// part thereof and/or its documentation for any purpose is granted without fee
-// provided that the above copyright notice and this permission notice appear
-// in all copies.
-//
-// This software is provided "as is" without express or implied warranty of
-// any kind. The author shall have no liability with respect to the
-// infringement of copyrights or patents that any modification to the content
-// of this file or this file itself may incur.
-//
-// ****************************************************************************
-
-#include "AnimatedGif.h"
-#include "filesystem/SpecialProtocol.h"
-#include "utils/EndianSwap.h"
-#include "utils/log.h"
-
-#ifdef TARGET_WINDOWS
-extern "C" FILE *fopen_utf8(const char *_Filename, const char *_Mode);
-#else
-#define fopen_utf8 fopen
-#endif
-
-#pragma pack(1)
-// Error processing macro (NO-OP by default):
-#define ERRORMSG(PARAM) {}
-
-#ifndef BI_RGB
- #define BI_RGB 0L
- #define BI_RLE8 1L
- #define BI_RLE4 2L
- #define BI_BITFIELDS 3L
-#endif
-
-#undef ALIGN
-#define ALIGN sizeof(int) ///< Windows GDI expects all int-aligned
-
-// Macros to swap data endianness
-#define SWAP16(X) X=Endian_SwapLE16(X)
-#define SWAP32(X) X=Endian_SwapLE32(X)
-
-// pre-declaration:
-int LZWDecoder (char*, char*, short, int, int, int, const int);
-
-// ****************************************************************************
-// * CAnimatedGif Member definitions *
-// ****************************************************************************
-
-CAnimatedGif::CAnimatedGif()
-{
- Height = Width = 0;
- Raster = NULL;
- Palette = NULL;
- pbmi = NULL;
- BPP = Transparent = BytesPerRow = 0;
- xPos = yPos = Delay = Transparency = 0;
- nLoops = 1; //default=play animation 1 time
-}
-
-CAnimatedGif::~CAnimatedGif()
-{
- delete [] pbmi;
- delete [] Raster;
- delete [] Palette;
-}
-
-// Init: Allocates space for raster and palette in GDI-compatible structures.
-void CAnimatedGif::Init(int iWidth, int iHeight, int iBPP, int iLoops)
-{
- delete[] Raster;
- Raster = NULL;
-
- delete[] pbmi;
- pbmi = NULL;
-
- delete[] Palette;
- Palette = NULL;
-
- // Standard members setup
- Transparent = -1;
- BytesPerRow = Width = iWidth;
- Height = iHeight;
- BPP = iBPP;
- // Animation Extra members setup:
- xPos = yPos = Delay = Transparency = 0;
- nLoops = iLoops;
-
- if (BPP == 24)
- {
- BytesPerRow *= 3;
- pbmi = (GUIBITMAPINFO*)new char [sizeof(GUIBITMAPINFO)];
- }
- else
- {
- pbmi = (GUIBITMAPINFO*)new char[sizeof(GUIBITMAPINFOHEADER)];
- Palette = new COLOR[256];
- }
-
- BytesPerRow += (ALIGN - Width % ALIGN) % ALIGN; // Align BytesPerRow
- int size = BytesPerRow * Height;
-
- Raster = new char [size];
-
- pbmi->bmiHeader.biSize = sizeof (GUIBITMAPINFOHEADER);
- pbmi->bmiHeader.biWidth = Width;
- pbmi->bmiHeader.biHeight = -Height; // negative means up-to-bottom
- pbmi->bmiHeader.biPlanes = 1;
- pbmi->bmiHeader.biBitCount = (BPP < 8 ? 8 : BPP); // Our raster is byte-aligned
- pbmi->bmiHeader.biCompression = BI_RGB;
- pbmi->bmiHeader.biSizeImage = 0;
- pbmi->bmiHeader.biXPelsPerMeter = 11811;
- pbmi->bmiHeader.biYPelsPerMeter = 11811;
- pbmi->bmiHeader.biClrUsed = 0;
- pbmi->bmiHeader.biClrImportant = 0;
-}
-
-// operator=: copies an object's content to another
-CAnimatedGif& CAnimatedGif::operator = (CAnimatedGif& rhs)
-{
- Init(rhs.Width, rhs.Height, rhs.BPP); // respects virtualization
- memcpy(Raster, rhs.Raster, BytesPerRow*Height);
- memcpy(Palette, rhs.Palette, 256*sizeof(COLOR));
- return *this;
-}
-
-
-
-CAnimatedGifSet::CAnimatedGifSet()
-{
- FrameHeight = FrameWidth = 0;
- nLoops = 1; //default=play animation 1 time
-}
-
-CAnimatedGifSet::~CAnimatedGifSet()
-{
- Release();
-}
-
-void CAnimatedGifSet::Release()
-{
- FrameWidth = 0;
- FrameHeight = 0;
- for (int i = 0; i < (int)m_vecimg.size(); ++i)
- {
- CAnimatedGif* pImage = m_vecimg[i];
- delete pImage;
- }
- m_vecimg.erase(m_vecimg.begin(), m_vecimg.end());
-
-}
-
-// ****************************************************************************
-// * CAnimatedGifSet Member definitions *
-// ****************************************************************************
-
-// AddImage: Adds an image object to the back of the img vector.
-void CAnimatedGifSet::AddImage (CAnimatedGif* newimage)
-{
- m_vecimg.push_back(newimage);
-}
-
-int CAnimatedGifSet::GetImageCount() const
-{
- return m_vecimg.size();
-}
-
-unsigned char CAnimatedGifSet::getbyte(FILE *fd)
-{
- unsigned char uchar;
- if (fread(&uchar, 1, 1, fd) == 1)
- return uchar;
- else
- return 0;
-}
-
-// ****************************************************************************
-// * LoadGIF *
-// * Load a GIF File into the CAnimatedGifSet object *
-// * (c) Nov 2000, Juan Soulie <jsoulie@cplusplus.com> *
-// ****************************************************************************
-int CAnimatedGifSet::LoadGIF (const char * szFileName)
-{
- int n;
- // Global GIF variables:
- int GlobalBPP; // Bits per Pixel.
- COLOR * GlobalColorMap; // Global colormap (allocate)
-
- struct GIFGCEtag
- { // GRAPHIC CONTROL EXTENSION
- unsigned char BlockSize; // Block Size: 4 bytes
- unsigned char PackedFields; // 3.. Packed Fields. Bits detail:
- // 0: Transparent Color Flag
- // 1: User Input Flag
- // 2-4: Disposal Method
- unsigned short Delay; // 4..5 Delay Time (1/100 seconds)
- unsigned char Transparent; // 6.. Transparent Color Index
- }
- gifgce;
-
- struct GIFNetscapeTag
- {
- unsigned char comment[11]; //4...14 NETSCAPE2.0
- unsigned char SubBlockLength; //15 0x3
- unsigned char reserved; //16 0x1
- unsigned short iIterations ; //17..18 number of iterations (lo-hi)
- }
- gifnetscape;
-
- int GraphicExtensionFound = 0;
-
- // OPEN FILE
- FILE *fd = fopen_utf8(CSpecialProtocol::TranslatePath(szFileName).c_str(), "rb");
- if (!fd)
- {
- return 0;
- }
-
- // *1* READ HEADERBLOCK (6bytes) (SIGNATURE + VERSION)
- char szSignature[6]; // First 6 bytes (GIF87a or GIF89a)
- int iRead = fread(szSignature, 1, 6, fd);
- if (iRead != 6)
- {
- fclose(fd);
- return 0;
- }
- if ( memcmp(szSignature, "GIF", 2) != 0)
- {
- fclose(fd);
- return 0;
- }
- // *2* READ LOGICAL SCREEN DESCRIPTOR
- struct GIFLSDtag
- {
- unsigned short ScreenWidth; // Logical Screen Width
- unsigned short ScreenHeight; // Logical Screen Height
- unsigned char PackedFields; // Packed Fields. Bits detail:
- // 0-2: Size of Global Color Table
- // 3: Sort Flag
- // 4-6: Color Resolution
- // 7: Global Color Table Flag
- unsigned char Background; // Background Color Index
- unsigned char PixelAspectRatio; // Pixel Aspect Ratio
- }
- giflsd;
-
- iRead = fread(&giflsd, 1, sizeof(giflsd), fd);
- if (iRead != sizeof(giflsd))
- {
- fclose(fd);
- return 0;
- }
- // endian swap
- SWAP16(giflsd.ScreenWidth);
- SWAP16(giflsd.ScreenHeight);
-
- GlobalBPP = (giflsd.PackedFields & 0x07) + 1;
-
- // fill some animation data:
- FrameWidth = giflsd.ScreenWidth;
- FrameHeight = giflsd.ScreenHeight;
- nLoops = 1; //default=play animation 1 time
-
- // *3* READ/GENERATE GLOBAL COLOR MAP
- GlobalColorMap = new COLOR [1 << GlobalBPP];
- if (giflsd.PackedFields & 0x80) // File has global color map?
- for (n = 0;n < 1 << GlobalBPP;n++)
- {
- GlobalColorMap[n].r = getbyte(fd);
- GlobalColorMap[n].g = getbyte(fd);
- GlobalColorMap[n].b = getbyte(fd);
- GlobalColorMap[n].x = 0;
- }
-
- else // GIF standard says to provide an internal default Palette:
- for (n = 0;n < 256;n++)
- {
- GlobalColorMap[n].r = GlobalColorMap[n].g = GlobalColorMap[n].b = n;
- GlobalColorMap[n].x = 0;
- }
-
- // *4* NOW WE HAVE 3 POSSIBILITIES:
- // 4a) Get and Extension Block (Blocks with additional information)
- // 4b) Get an Image Separator (Introductor to an image)
- // 4c) Get the trailer Char (End of GIF File)
- do
- {
- int charGot = getbyte(fd);
-
- if (charGot == 0x21) // *A* EXTENSION BLOCK
- {
- unsigned char extensionType = getbyte(fd);
- switch (extensionType)
- {
- case 0xF9: // Graphic Control Extension
- {
- if (fread((char*)&gifgce, 1, sizeof(gifgce), fd) == sizeof(gifgce))
- SWAP16(gifgce.Delay);
- GraphicExtensionFound++;
- getbyte(fd); // Block Terminator (always 0)
- }
- break;
-
- case 0xFE: // Comment Extension: Ignored
- {
- while (int nBlockLength = getbyte(fd))
- for (n = 0;n < nBlockLength;n++) getbyte(fd);
- }
- break;
-
- case 0x01: // PlainText Extension: Ignored
- {
- while (int nBlockLength = getbyte(fd))
- for (n = 0;n < nBlockLength;n++) getbyte(fd);
- }
- break;
-
- case 0xFF: // Application Extension: Ignored
- {
- int nBlockLength = getbyte(fd);
- if (nBlockLength == 0x0b)
- {
- struct GIFNetscapeTag tag;
- if (fread((char*)&tag, 1, sizeof(gifnetscape), fd) == sizeof(gifnetscape))
- {
- SWAP16(tag.iIterations);
- nLoops = tag.iIterations;
- }
- else
- nLoops = 0;
-
- if (nLoops) nLoops++;
- getbyte(fd);
- }
- else
- {
- do
- {
- for (n = 0;n < nBlockLength;n++) getbyte(fd);
- }
- while ((nBlockLength = getbyte(fd)) != 0);
- }
- }
- break;
-
- default: // Unknown Extension: Ignored
- {
- // read (and ignore) data sub-blocks
- while (int nBlockLength = getbyte(fd))
- for (n = 0;n < nBlockLength;n++) getbyte(fd);
- }
- break;
- }
- }
- else if (charGot == 0x2c)
- { // *B* IMAGE (0x2c Image Separator)
- // Create a new Image Object:
- CAnimatedGif* NextImage = new CAnimatedGif();
-
- // Read Image Descriptor
- struct GIFIDtag
- {
- unsigned short xPos; // Image Left Position
- unsigned short yPos; // Image Top Position
- unsigned short Width; // Image Width
- unsigned short Height; // Image Height
- unsigned char PackedFields; // Packed Fields. Bits detail:
- // 0-2: Size of Local Color Table
- // 3-4: (Reserved)
- // 5: Sort Flag
- // 6: Interlace Flag
- // 7: Local Color Table Flag
- }
- gifid;
-
- memset(&gifid, 0, sizeof(gifid));
-
- int LocalColorMap = 0;
- if (fread((char*)&gifid, 1, sizeof(gifid), fd) == sizeof(gifid))
- {
- SWAP16(gifid.xPos);
- SWAP16(gifid.yPos);
- SWAP16(gifid.Width);
- SWAP16(gifid.Height);
-
- LocalColorMap = (gifid.PackedFields & 0x08) ? 1 : 0;
- }
-
- NextImage->Init(gifid.Width, gifid.Height, LocalColorMap ? (gifid.PackedFields&7) + 1 : GlobalBPP);
-
- /* verify that all the image is inside the screen dimensions */
- if (gifid.xPos + gifid.Width > giflsd.ScreenWidth || gifid.yPos + gifid.Height > giflsd.ScreenHeight)
- return 0;
-
- // Fill NextImage Data
- NextImage->xPos = gifid.xPos;
- NextImage->yPos = gifid.yPos;
- if (GraphicExtensionFound)
- {
- NextImage->Transparent = (gifgce.PackedFields & 0x01) ? gifgce.Transparent : -1;
- NextImage->Transparency = (gifgce.PackedFields & 0x1c) > 1 ? 1 : 0;
- NextImage->Delay = gifgce.Delay * 10;
- }
-
- if (NextImage->Transparent != -1)
- memset(NextImage->Raster, NextImage->Transparent, NextImage->BytesPerRow * NextImage->Height);
- else
- memset(NextImage->Raster, giflsd.Background, NextImage->BytesPerRow * NextImage->Height);
-
- // Read Color Map (if descriptor says so)
- size_t palSize = sizeof(COLOR)*(1 << NextImage->BPP);
- bool isPalRead = false;
- if (LocalColorMap && fread((char*)NextImage->Palette, 1, palSize, fd) == palSize)
- isPalRead = true;
-
- // Copy global, if no palette
- if (!isPalRead)
- memcpy(NextImage->Palette, GlobalColorMap, palSize);
-
- short firstbyte = getbyte(fd); // 1st byte of img block (CodeSize)
-
- // Calculate compressed image block size
- // to fix: this allocates an extra byte per block
- long ImgStart, ImgEnd;
- ImgEnd = ImgStart = ftell(fd);
- while ((n = getbyte(fd)) != 0) fseek (fd, ImgEnd += n + 1, SEEK_SET );
- fseek (fd, ImgStart, SEEK_SET);
-
- // Allocate Space for Compressed Image
- char * pCompressedImage = new char [ImgEnd - ImgStart + 4];
-
- // Read and store Compressed Image
- char * pTemp = pCompressedImage;
- while (int nBlockLength = getbyte(fd))
- {
- if (fread(pTemp, 1, nBlockLength, fd) != (size_t)nBlockLength)
- {
- // Error?
- }
- pTemp += nBlockLength;
- }
-
- // Call LZW/GIF decompressor
- n = LZWDecoder(
- (char*) pCompressedImage,
- (char*) NextImage->Raster,
- firstbyte, NextImage->BytesPerRow, //NextImage->AlignedWidth,
- gifid.Width, gifid.Height,
- ((gifid.PackedFields & 0x40) ? 1 : 0) //Interlaced?
- );
-
- if (n)
- AddImage(NextImage);
- else
- {
- delete NextImage;
- CLog::Log(LOGERROR, "CAnimatedGifSet::LoadGIF: gif file corrupt: %s", szFileName);
- ERRORMSG("GIF File Corrupt");
- }
-
- // Some cleanup
- delete[] pCompressedImage;
- GraphicExtensionFound = 0;
- }
- else if (charGot == 0x3b)
- {
- // *C* TRAILER: End of GIF Info
- break; // Ok. Standard End.
- }
-
- }
- while ( !feof(fd) );
-
- delete[] GlobalColorMap;
- fclose(fd);
- if ( GetImageCount() == 0) ERRORMSG("Premature End Of File");
- return GetImageCount();
-}
-
-// ****************************************************************************
-// * LZWDecoder (C/C++) *
-// * Codec to perform LZW (GIF Variant) decompression. *
-// * (c) Nov2000, Juan Soulie <jsoulie@cplusplus.com> *
-// ****************************************************************************
-//
-// Parameter description:
-// - bufIn: Input buffer containing a "de-blocked" GIF/LZW compressed image.
-// - bufOut: Output buffer where result will be stored.
-// - InitCodeSize: Initial CodeSize to be Used
-// (GIF files include this as the first byte in a picture block)
-// - AlignedWidth : Width of a row in memory (including alignment if needed)
-// - Width, Height: Physical dimensions of image.
-// - Interlace: 1 for Interlaced GIFs.
-//
-int LZWDecoder (char * bufIn, char * bufOut,
- short InitCodeSize, int AlignedWidth,
- int Width, int Height, const int Interlace)
-{
- if (InitCodeSize < 1 || InitCodeSize >= LZW_MAXBITS)
- return 0;
- int n;
- int row = 0, col = 0; // used to point output if Interlaced
- int nPixels, maxPixels; // Output pixel counter
-
- short CodeSize; // Current CodeSize (size in bits of codes)
- short ClearCode; // Clear code : resets decompressor
- short EndCode; // End code : marks end of information
-
- long whichBit; // Index of next bit in bufIn
- long LongCode; // Temp. var. from which Code is retrieved
- short Code; // Code extracted
- short PrevCode; // Previous Code
- short OutCode; // Code to output
-
- // Translation Table:
- short Prefix[LZW_SIZETABLE] = {}; // Prefix: index of another Code
- unsigned char Suffix[LZW_SIZETABLE] = {}; // Suffix: terminating character
- short FirstEntry; // Index of first free entry in table
- short NextEntry; // Index of next free entry in table
-
- unsigned char OutStack[LZW_SIZETABLE + 1]; // Output buffer
- int OutIndex; // Characters in OutStack
-
- int RowOffset; // Offset in output buffer for current row
-
- // Set up values that depend on InitCodeSize Parameter.
- CodeSize = InitCodeSize + 1;
- ClearCode = (1 << InitCodeSize);
- EndCode = ClearCode + 1;
- NextEntry = FirstEntry = ClearCode + 2;
-
- whichBit = 0;
- nPixels = 0;
- maxPixels = Width * Height;
- RowOffset = 0;
- PrevCode = 0;
-
- while (nPixels < maxPixels)
- {
- OutIndex = 0; // Reset Output Stack
-
- // GET NEXT CODE FROM bufIn:
- // LZW compression uses code items longer than a single byte.
- // For GIF Files, code sizes are variable between 9 and 12 bits
- // That's why we must read data (Code) this way:
- LongCode = *((long*)(bufIn + whichBit / 8)); // Get some bytes from bufIn
- SWAP32(LongCode);
- LongCode >>= (whichBit&7); // Discard too low bits
- Code = (short)((LongCode & ((1 << CodeSize) - 1) )); // Discard too high bits
- whichBit += CodeSize; // Increase Bit Offset
-
- // SWITCH, DIFFERENT POSIBILITIES FOR CODE:
- if (Code == EndCode) // END CODE
- break; // Exit LZW Decompression loop
-
- if (Code == ClearCode)
- {
- // CLEAR CODE:
- CodeSize = InitCodeSize + 1; // Reset CodeSize
- NextEntry = FirstEntry; // Reset Translation Table
- PrevCode = Code; // Prevent next to be added to table.
- continue; // restart, to get another code
- }
- if (Code < NextEntry) // CODE IS IN TABLE
- OutCode = Code; // Set code to output.
-
- else
- { // CODE IS NOT IN TABLE:
- OutIndex++; // Keep "first" character of previous output.
- OutCode = PrevCode; // Set PrevCode to be output
- }
-
- // EXPAND OutCode IN OutStack
- // - Elements up to FirstEntry are Raw-Codes and are not expanded
- // - Table Prefices contain indexes to other codes
- // - Table Suffices contain the raw codes to be output
- while (OutCode >= FirstEntry)
- {
- if (OutIndex > LZW_SIZETABLE || OutCode >= LZW_SIZETABLE)
- return 0;
- OutStack[OutIndex++] = Suffix[OutCode]; // Add suffix to Output Stack
- OutCode = Prefix[OutCode]; // Loop with preffix
- }
-
- // NOW OutCode IS A RAW CODE, ADD IT TO OUTPUT STACK.
- if (OutIndex > LZW_SIZETABLE)
- return 0;
- OutStack[OutIndex++] = (unsigned char) OutCode;
-
- // ADD NEW ENTRY TO TABLE (PrevCode + OutCode)
- // (EXCEPT IF PREVIOUS CODE WAS A CLEARCODE)
- if (PrevCode != ClearCode)
- {
- // Prevent Translation table overflow:
- if (NextEntry >= LZW_SIZETABLE)
- return 0;
-
- Prefix[NextEntry] = PrevCode;
- Suffix[NextEntry] = (unsigned char) OutCode;
- NextEntry++;
-
- // INCREASE CodeSize IF NextEntry IS INVALID WITH CURRENT CodeSize
- if (NextEntry >= (1 << CodeSize))
- {
- if (CodeSize < LZW_MAXBITS) CodeSize++;
- else
- {
- ;
- } // Do nothing. Maybe next is Clear Code.
- }
- }
-
- PrevCode = Code;
-
- // Avoid the possibility of overflow on 'bufOut'.
- if (nPixels + OutIndex > maxPixels) OutIndex = maxPixels - nPixels;
-
- // OUTPUT OutStack (LAST-IN FIRST-OUT ORDER)
- for (n = OutIndex - 1; n >= 0; n--)
- {
- if (col == Width) // Check if new row.
- {
- if (Interlace)
- {
- // If interlaced::
- if ((row&7) == 0) {row += 8; if (row >= Height) row = 4;}
- else if ((row&3) == 0) {row += 8; if (row >= Height) row = 2;}
- else if ((row&1) == 0) {row += 4; if (row >= Height) row = 1;}
- else row += 2;
- }
- else // If not interlaced:
- row++;
-
- RowOffset = row * AlignedWidth; // Set new row offset
- col = 0;
- }
- bufOut[RowOffset + col] = OutStack[n]; // Write output
- col++; nPixels++; // Increase counters.
- }
-
- } // while (main decompressor loop)
-
- return whichBit;
-}
-
-// Refer to WINIMAGE.TXT for copyright and patent notices on GIF and LZW.
-
-#pragma pack()
diff --git a/xbmc/guilib/AnimatedGif.h b/xbmc/guilib/AnimatedGif.h
deleted file mode 100644
index 9e65c856d1..0000000000
--- a/xbmc/guilib/AnimatedGif.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/*!
-\file AnimatedGif.h
-\brief
-*/
-
-
-// ****************************************************************************
-//
-// WINIMAGE.H : Generic classes for raster images (MSWindows specialization)
-//
-// Content: Class declarations of:
-// - class CAnimatedGif : Storage class for single images
-// - class CAnimatedGifSet : Storage class for sets of images
-// - class C_AnimationWindow : Window Class to display animations
-//
-// (Includes declarations of routines to Load and Save BMP files and to load
-// GIF files into these classes).
-//
-// --------------------------------------------------------------------------
-//
-// Copyright (c) 2000, Juan Soulie <jsoulie@cplusplus.com>
-//
-// Permission to use, copy, modify, distribute and sell this software or any
-// part thereof and/or its documentation for any purpose is granted without fee
-// provided that the above copyright notice and this permission notice appear
-// in all copies.
-//
-// This software is provided "as is" without express or implied warranty of
-// any kind. The author shall have no liability with respect to the
-// infringement of copyrights or patents that any modification to the content
-// of this file or this file itself may incur.
-//
-// ****************************************************************************
-
-
-#include "Texture.h" // for COLOR
-
-#pragma pack(1)
-
-#define LZW_MAXBITS 12
-#define LZW_SIZETABLE (1<<LZW_MAXBITS)
-
-/*!
- \ingroup textures
- \brief
- */
-typedef struct tagGUIRGBQUAD
-{
- BYTE rgbBlue;
- BYTE rgbGreen;
- BYTE rgbRed;
- BYTE rgbReserved;
-}
-GUIRGBQUAD;
-
-/*!
- \ingroup textures
- \brief
- */
-typedef struct tagGUIBITMAPINFOHEADER
-{
- DWORD biSize;
- LONG biWidth;
- LONG biHeight;
- WORD biPlanes;
- WORD biBitCount;
- DWORD biCompression;
- DWORD biSizeImage;
- LONG biXPelsPerMeter;
- LONG biYPelsPerMeter;
- DWORD biClrUsed;
- DWORD biClrImportant;
-}
-GUIBITMAPINFOHEADER;
-
-/*!
- \ingroup textures
- \brief
- */
-typedef struct tagGUIBITMAPINFO
-{
- GUIBITMAPINFOHEADER bmiHeader;
- GUIRGBQUAD bmiColors[1];
-} GUIBITMAPINFO;
-
-#pragma pack()
-
-
-// ****************************************************************************
-// * CAnimatedGif *
-// * Storage class for single images *
-// ****************************************************************************
-/*!
- \ingroup textures
- \brief Storage class for single images
- */
-class CAnimatedGif
-{
-public:
- CAnimatedGif();
- virtual ~CAnimatedGif();
-
- // standard members:
- int Width, Height; ///< Dimensions in pixels
- int BPP; // Bits Per Pixel
- char* Raster; ///< Bits of Raster Data (Byte Aligned)
- COLOR* Palette; ///< Color Map
- int BytesPerRow; ///< Width (in bytes) including alignment!
- int Transparent; ///< Index of Transparent color (-1 for none)
-
- // Extra members for animations:
- int nLoops;
- int xPos, yPos; ///< Relative Position
- int Delay; ///< Delay after image in 1/1000 seconds.
- int Transparency; ///< Animation Transparency.
- // Windows GDI specific:
- GUIBITMAPINFO* pbmi; ///< BITMAPINFO structure
-
- // constructor and destructor:
-
- // operator= (object copy)
- CAnimatedGif& operator= (CAnimatedGif& rhs);
-
- /// \brief Image initializer (allocates space for raster and palette):
- void Init (int iWidth, int iHeight, int iBPP, int iLoops = 0);
-
- inline char& Pixel (int x, int y) { return Raster[y*BytesPerRow + x];}
-
-};
-
-// ****************************************************************************
-// * CAnimatedGifSet *
-// * Storage class for sets of images *
-// ****************************************************************************
-/*!
- \ingroup textures
- \brief Storage class for sets of images
- */
-class CAnimatedGifSet
-{
-public:
-
- // constructor and destructor:
- CAnimatedGifSet();
- virtual ~CAnimatedGifSet();
-
- int FrameWidth, FrameHeight; ///< Dimensions of ImageSet in pixels.
- int nLoops; // Number of Loops (0 = infinite)
-
- std::vector<CAnimatedGif*> m_vecimg; ///< Images' Vector.
-
- void AddImage (CAnimatedGif*); ///< Append new image to vector (push_back)
-
- int GetImageCount() const;
- // File Formats:
- int LoadGIF (const char* szFile);
-
- void Release();
-protected:
- static unsigned char getbyte(FILE *fd);
-};
-
diff --git a/xbmc/guilib/DllLibGif.h b/xbmc/guilib/DllLibGif.h
new file mode 100644
index 0000000000..284f52d715
--- /dev/null
+++ b/xbmc/guilib/DllLibGif.h
@@ -0,0 +1,187 @@
+#pragma once
+
+/*
+ * Copyright (C) 2005-2014 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include <gif_lib.h>
+#include "DynamicDll.h"
+#ifndef CONTINUE_EXT_FUNC_CODE
+#define CONTINUE_EXT_FUNC_CODE 0
+#endif
+
+#ifndef DISPOSAL_UNSPECIFIED
+#define DISPOSAL_UNSPECIFIED 0
+#endif
+
+#ifndef DISPOSE_DO_NOT
+#define DISPOSE_DO_NOT 1
+#endif
+
+#ifndef DISPOSE_BACKGROUND
+#define DISPOSE_BACKGROUND 2
+#endif
+
+#ifndef DISPOSE_PREVIOUS
+#define DISPOSE_PREVIOUS 3
+#endif
+
+class DllLibGifInterface
+{
+public:
+ virtual ~DllLibGifInterface() {}
+#if GIFLIB_MAJOR == 5
+ virtual const char* GifErrorString(int ErrorCode) = 0;
+ virtual GifFileType* DGifOpenFileName(const char *GifFileName, int *Error) = 0;
+ virtual GifFileType *DGifOpen(void *userPtr, InputFunc readFunc, int *Error) = 0;
+ virtual int DGifSavedExtensionToGCB(GifFileType *GifFile, int ImageIndex, GraphicsControlBlock *GCB) = 0;
+ virtual int DGifCloseFile(GifFileType* GifFile, int *Error)=0;
+#else
+ virtual GifFileType* DGifOpenFileName(const char *GifFileName) = 0;
+ virtual GifFileType *DGifOpen(void *userPtr, InputFunc readFunc)=0;
+ virtual int DGifGetExtension(GifFileType * GifFile, int *GifExtCode, GifByteType ** GifExtension) = 0;
+ virtual int DGifGetExtensionNext(GifFileType * GifFile, GifByteType ** GifExtension) = 0;
+ virtual int DGifCloseFile(GifFileType* GifFile)=0;
+#endif
+ virtual int DGifSlurp(GifFileType* GifFile)=0;
+};
+
+class DllLibGif : public DllDynamic, DllLibGifInterface
+{
+ DECLARE_DLL_WRAPPER(DllLibGif, DLL_PATH_LIBGIF)
+
+#if GIFLIB_MAJOR == 5
+ DEFINE_METHOD1(const char*, GifErrorString, (int p1))
+ DEFINE_METHOD2(GifFileType*, DGifOpenFileName, (const char *p1, int *p2))
+ DEFINE_METHOD3(GifFileType*, DGifOpen, (void *p1, InputFunc p2, int *p3))
+ DEFINE_METHOD3(int, DGifSavedExtensionToGCB, (GifFileType *p1, int p2, GraphicsControlBlock *p3))
+ DEFINE_METHOD2(int, DGifCloseFile, (GifFileType* p1, int *p2))
+#else
+ DEFINE_METHOD0(int, GifLastError)
+ DEFINE_METHOD1(GifFileType*, DGifOpenFileName, (const char *p1))
+ DEFINE_METHOD2(GifFileType*, DGifOpen, (void *p1, InputFunc p2))
+ DEFINE_METHOD3(int, DGifGetExtension, (GifFileType *p1, int *p2, GifByteType **p3))
+ DEFINE_METHOD2(int, DGifGetExtensionNext, (GifFileType *p1, GifByteType **p2))
+ DEFINE_METHOD1(int, DGifCloseFile, (GifFileType* p1))
+#endif
+ DEFINE_METHOD1(int, DGifSlurp, (GifFileType* p1))
+ BEGIN_METHOD_RESOLVE()
+ RESOLVE_METHOD(DGifOpenFileName)
+ RESOLVE_METHOD(DGifOpen)
+ RESOLVE_METHOD(DGifCloseFile)
+ RESOLVE_METHOD(DGifSlurp)
+#if GIFLIB_MAJOR == 5
+ RESOLVE_METHOD(DGifSavedExtensionToGCB)
+ RESOLVE_METHOD(GifErrorString)
+#else
+ RESOLVE_METHOD(GifLastError)
+ RESOLVE_METHOD(DGifGetExtension)
+ RESOLVE_METHOD(DGifGetExtensionNext)
+#endif
+ END_METHOD_RESOLVE()
+
+#if GIFLIB_MAJOR != 5
+public:
+ /*
+ taken from giflib 5.1.0
+ */
+ const char* GifErrorString(int ErrorCode)
+ {
+ const char *Err;
+
+ switch (ErrorCode) {
+ case E_GIF_ERR_OPEN_FAILED:
+ Err = "Failed to open given file";
+ break;
+ case E_GIF_ERR_WRITE_FAILED:
+ Err = "Failed to write to given file";
+ break;
+ case E_GIF_ERR_HAS_SCRN_DSCR:
+ Err = "Screen descriptor has already been set";
+ break;
+ case E_GIF_ERR_HAS_IMAG_DSCR:
+ Err = "Image descriptor is still active";
+ break;
+ case E_GIF_ERR_NO_COLOR_MAP:
+ Err = "Neither global nor local color map";
+ break;
+ case E_GIF_ERR_DATA_TOO_BIG:
+ Err = "Number of pixels bigger than width * height";
+ break;
+ case E_GIF_ERR_NOT_ENOUGH_MEM:
+ Err = "Failed to allocate required memory";
+ break;
+ case E_GIF_ERR_DISK_IS_FULL:
+ Err = "Write failed (disk full?)";
+ break;
+ case E_GIF_ERR_CLOSE_FAILED:
+ Err = "Failed to close given file";
+ break;
+ case E_GIF_ERR_NOT_WRITEABLE:
+ Err = "Given file was not opened for write";
+ break;
+ case D_GIF_ERR_OPEN_FAILED:
+ Err = "Failed to open given file";
+ break;
+ case D_GIF_ERR_READ_FAILED:
+ Err = "Failed to read from given file";
+ break;
+ case D_GIF_ERR_NOT_GIF_FILE:
+ Err = "Data is not in GIF format";
+ break;
+ case D_GIF_ERR_NO_SCRN_DSCR:
+ Err = "No screen descriptor detected";
+ break;
+ case D_GIF_ERR_NO_IMAG_DSCR:
+ Err = "No Image Descriptor detected";
+ break;
+ case D_GIF_ERR_NO_COLOR_MAP:
+ Err = "Neither global nor local color map";
+ break;
+ case D_GIF_ERR_WRONG_RECORD:
+ Err = "Wrong record type detected";
+ break;
+ case D_GIF_ERR_DATA_TOO_BIG:
+ Err = "Number of pixels bigger than width * height";
+ break;
+ case D_GIF_ERR_NOT_ENOUGH_MEM:
+ Err = "Failed to allocate required memory";
+ break;
+ case D_GIF_ERR_CLOSE_FAILED:
+ Err = "Failed to close given file";
+ break;
+ case D_GIF_ERR_NOT_READABLE:
+ Err = "Given file was not opened for read";
+ break;
+ case D_GIF_ERR_IMAGE_DEFECT:
+ Err = "Image is defective, decoding aborted";
+ break;
+ case D_GIF_ERR_EOF_TOO_SOON:
+ Err = "Image EOF detected before image complete";
+ break;
+ default:
+ Err = NULL;
+ break;
+ }
+ return Err;
+ }
+#endif
+};
+
diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp
index 0478cd1f24..088cdf5ca7 100644
--- a/xbmc/guilib/GUIFontTTF.cpp
+++ b/xbmc/guilib/GUIFontTTF.cpp
@@ -725,7 +725,7 @@ bool CGUIFontTTFBase::CacheCharacter(wchar_t letter, uint32_t style, Character *
m_posX += -bitGlyph->left;
// check we have enough room for the character
- if (m_posX + bitGlyph->left + bitmap.width > m_textureWidth)
+ if ((m_posX + bitGlyph->left + bitmap.width) > static_cast<int>(m_textureWidth))
{ // no space - gotta drop to the next line (which means creating a new texture and copying it across)
m_posX = 0;
m_posY += GetTextureLineHeight();
diff --git a/xbmc/guilib/GUITexture.cpp b/xbmc/guilib/GUITexture.cpp
index 5156d74f96..5e719217a7 100644
--- a/xbmc/guilib/GUITexture.cpp
+++ b/xbmc/guilib/GUITexture.cpp
@@ -73,9 +73,7 @@ CGUITextureBase::CGUITextureBase(float posX, float posY, float width, float heig
m_diffuseScaleV = 1.0f;
// anim gifs
- m_currentFrame = 0;
- m_frameCounter = (unsigned int) -1;
- m_currentLoop = 0;
+ ResetAnimState();
m_allocateDynamically = false;
m_isAllocated = NO;
@@ -112,9 +110,7 @@ CGUITextureBase::CGUITextureBase(const CGUITextureBase &right) :
m_diffuseScaleU = 1.0f;
m_diffuseScaleV = 1.0f;
- m_currentFrame = 0;
- m_frameCounter = (unsigned int) -1;
- m_currentLoop = 0;
+ ResetAnimState();
m_isAllocated = NO;
m_invalid = true;
@@ -136,9 +132,7 @@ bool CGUITextureBase::AllocateOnDemand()
if (m_allocateDynamically && IsAllocated())
FreeResources();
// reset animated textures (animgifs)
- m_currentLoop = 0;
- m_currentFrame = 0;
- m_frameCounter = 0;
+ ResetAnimState();
}
return false;
@@ -151,7 +145,7 @@ bool CGUITextureBase::Process(unsigned int currentTime)
changed |= AllocateOnDemand();
if (m_texture.size() > 1)
- changed |= UpdateAnimFrame();
+ changed |= UpdateAnimFrame(currentTime);
if (m_invalid)
changed |= CalculateSize();
@@ -294,9 +288,7 @@ bool CGUITextureBase::AllocResources()
return false; // already have our texture
// reset our animstate
- m_frameCounter = 0;
- m_currentFrame = 0;
- m_currentLoop = 0;
+ ResetAnimState();
bool changed = false;
bool useLarge = m_info.useLarge || !g_TextureManager.CanLoad(m_info.filename);
@@ -468,8 +460,8 @@ void CGUITextureBase::FreeResources(bool immediately /* = false */)
m_texture.Reset();
- m_currentFrame = 0;
- m_currentLoop = 0;
+ ResetAnimState();
+
m_texCoordsScaleU = 1.0f;
m_texCoordsScaleV = 1.0f;
@@ -489,39 +481,46 @@ void CGUITextureBase::SetInvalid()
m_invalid = true;
}
-bool CGUITextureBase::UpdateAnimFrame()
+bool CGUITextureBase::UpdateAnimFrame(unsigned int currentTime)
{
bool changed = false;
-
- m_frameCounter++;
unsigned int delay = m_texture.m_delays[m_currentFrame];
- if (!delay) delay = 100;
- if (m_frameCounter * 40 >= delay)
+
+ if (m_lasttime == 0)
+ {
+ m_lasttime = currentTime;
+ }
+ else
{
- m_frameCounter = 0;
- if (m_currentFrame + 1 >= m_texture.size())
+ if ((currentTime - m_lasttime) >= delay)
{
- if (m_texture.m_loops > 0)
+ if (m_currentFrame + 1 >= m_texture.size())
{
- if (m_currentLoop + 1 < m_texture.m_loops)
+ if (m_texture.m_loops > 0)
+ {
+ if (m_currentLoop + 1 < m_texture.m_loops)
+ {
+ m_currentLoop++;
+ m_currentFrame = 0;
+ m_lasttime = currentTime;
+ changed = true;
+ }
+ }
+ else
{
- m_currentLoop++;
+ // 0 == loop forever
m_currentFrame = 0;
+ m_lasttime = currentTime;
changed = true;
}
}
else
{
- // 0 == loop forever
- m_currentFrame = 0;
+ m_currentFrame++;
+ m_lasttime = currentTime;
changed = true;
}
}
- else
- {
- m_currentFrame++;
- changed = true;
- }
}
return changed;
@@ -591,6 +590,13 @@ void CGUITextureBase::OrientateTexture(CRect &rect, float width, float height, i
}
}
+void CGUITextureBase::ResetAnimState()
+{
+ m_lasttime = 0;
+ m_currentFrame = 0;
+ m_currentLoop = 0;
+}
+
bool CGUITextureBase::SetWidth(float width)
{
if (width < m_info.border.x1 + m_info.border.x2)
diff --git a/xbmc/guilib/GUITexture.h b/xbmc/guilib/GUITexture.h
index c98857403a..6e4c6f3b3c 100644
--- a/xbmc/guilib/GUITexture.h
+++ b/xbmc/guilib/GUITexture.h
@@ -126,9 +126,10 @@ protected:
bool CalculateSize();
void LoadDiffuseImage();
bool AllocateOnDemand();
- bool UpdateAnimFrame();
+ bool UpdateAnimFrame(unsigned int currentTime);
void Render(float left, float top, float bottom, float right, float u1, float v1, float u2, float v2, float u3, float v3);
static void OrientateTexture(CRect &rect, float width, float height, int orientation);
+ void ResetAnimState();
// functions that our implementation classes handle
virtual void Allocate() {}; ///< called after our textures have been allocated
@@ -156,7 +157,7 @@ protected:
// animations
int m_currentLoop;
unsigned int m_currentFrame;
- uint32_t m_frameCounter;
+ uint32_t m_lasttime;
float m_diffuseU, m_diffuseV; // size of the diffuse frame (in tex coords)
float m_diffuseScaleU, m_diffuseScaleV; // scale factor of the diffuse frame (from texture coords to diffuse tex coords)
diff --git a/xbmc/guilib/GUIWindowManager.cpp b/xbmc/guilib/GUIWindowManager.cpp
index 5a2d9adc14..95d95728ca 100644
--- a/xbmc/guilib/GUIWindowManager.cpp
+++ b/xbmc/guilib/GUIWindowManager.cpp
@@ -23,6 +23,7 @@
#include "GUIDialog.h"
#include "Application.h"
#include "messaging/ApplicationMessenger.h"
+#include "messaging/helpers/DialogHelper.h"
#include "GUIPassword.h"
#include "GUIInfoManager.h"
#include "threads/SingleLock.h"
@@ -127,6 +128,7 @@
#include "pvr/dialogs/GUIDialogPVRGuideInfo.h"
#include "pvr/dialogs/GUIDialogPVRGuideOSD.h"
#include "pvr/dialogs/GUIDialogPVRGuideSearch.h"
+#include "pvr/dialogs/GUIDialogPVRRadioRDSInfo.h"
#include "pvr/dialogs/GUIDialogPVRRecordingInfo.h"
#include "pvr/dialogs/GUIDialogPVRTimerSettings.h"
@@ -265,6 +267,7 @@ void CGUIWindowManager::CreateWindows()
Add(new CGUIWindowPVRRecordings(true));
Add(new CGUIWindowPVRGuide(true));
Add(new CGUIWindowPVRTimers(true));
+ Add(new CGUIDialogPVRRadioRDSInfo);
Add(new CGUIWindowPVRSearch(true));
Add(new CGUIDialogPVRGuideInfo);
Add(new CGUIDialogPVRRecordingInfo);
@@ -369,6 +372,7 @@ bool CGUIWindowManager::DestroyWindows()
Delete(WINDOW_DIALOG_PVR_CHANNEL_MANAGER);
Delete(WINDOW_DIALOG_PVR_GUIDE_SEARCH);
Delete(WINDOW_DIALOG_PVR_CHANNEL_SCAN);
+ Delete(WINDOW_DIALOG_PVR_RADIO_RDS_INFO);
Delete(WINDOW_DIALOG_PVR_UPDATE_PROGRESS);
Delete(WINDOW_DIALOG_PVR_OSD_CHANNELS);
Delete(WINDOW_DIALOG_PVR_OSD_GUIDE);
@@ -915,15 +919,33 @@ void CGUIWindowManager::OnApplicationMessage(ThreadMessage* pMsg)
break;
case TMSG_GUI_MESSAGE:
- {
if (pMsg->lpVoid)
{
CGUIMessage *message = static_cast<CGUIMessage *>(pMsg->lpVoid);
SendMessage(*message, pMsg->param1);
delete message;
}
- }
- break;
+ break;
+
+ case TMSG_GUI_DIALOG_YESNO:
+ if (!pMsg->lpVoid && pMsg->param1 < 0 && pMsg->param2 < 0)
+ return;
+
+ auto dialog = static_cast<CGUIDialogYesNo*>(GetWindow(WINDOW_DIALOG_YES_NO));
+ if (!dialog)
+ return;
+
+ if (pMsg->lpVoid)
+ pMsg->SetResult(dialog->ShowAndGetInput(*static_cast<HELPERS::DialogYesNoMessage*>(pMsg->lpVoid)));
+ else
+ {
+ HELPERS::DialogYesNoMessage options;
+ options.heading = pMsg->param1;
+ options.text = pMsg->param2;
+ pMsg->SetResult(dialog->ShowAndGetInput(options));
+ }
+
+ break;
}
}
diff --git a/xbmc/guilib/Gif.cpp b/xbmc/guilib/Gif.cpp
new file mode 100644
index 0000000000..6960070839
--- /dev/null
+++ b/xbmc/guilib/Gif.cpp
@@ -0,0 +1,627 @@
+/*
+* Copyright (C) 2005-2014 Team XBMC
+* http://www.xbmc.org
+*
+* This Program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2, or (at your option)
+* any later version.
+*
+* This Program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with XBMC; see the file COPYING. If not, see
+* <http://www.gnu.org/licenses/>.
+*
+*/
+#include "system.h"
+#if defined(HAS_GIFLIB)
+#include "Gif.h"
+#include "utils/log.h"
+#include "utils/StringUtils.h"
+#include "guilib/Texture.h"
+#include "filesystem/File.h"
+#include <algorithm>
+
+#define UNSIGNED_LITTLE_ENDIAN(lo, hi) ((lo) | ((hi) << 8))
+#define GIF_MAX_MEMORY 82944000U // about 79 MB, which is equivalent to 10 full hd frames.
+
+class Gifreader
+{
+public:
+ unsigned char* buffer;
+ unsigned int buffSize;
+ unsigned int readPosition;
+
+ Gifreader() : buffer(nullptr), buffSize(0), readPosition(0) {}
+};
+
+int ReadFromMemory(GifFileType* gif, GifByteType* gifbyte, int len)
+{
+ unsigned int alreadyRead = static_cast<Gifreader*>(gif->UserData)->readPosition;
+ int buffSizeLeft = static_cast<Gifreader*>(gif->UserData)->buffSize - alreadyRead;
+ int readBytes = len;
+
+ if (len <= 0)
+ readBytes = 0;
+
+ if (len > buffSizeLeft)
+ readBytes = buffSizeLeft;
+
+ if (readBytes > 0)
+ {
+ unsigned char* src = static_cast<Gifreader*>(gif->UserData)->buffer + alreadyRead;
+ memcpy(gifbyte, src, readBytes);
+ static_cast<Gifreader*>(gif->UserData)->readPosition += readBytes;
+ }
+ return readBytes;
+}
+
+int ReadFromVfs(GifFileType* gif, GifByteType* gifbyte, int len)
+{
+ XFILE::CFile *gifFile = static_cast<XFILE::CFile*>(gif->UserData);
+ return gifFile->Read(gifbyte, len);
+}
+
+
+Gif::Gif() :
+ m_imageSize(0),
+ m_pitch(0),
+ m_loops(0),
+ m_numFrames(0),
+ m_filename(""),
+ m_gif(nullptr),
+ m_hasBackground(false),
+ m_pTemplate(nullptr),
+ m_isAnimated(-1)
+{
+ if (!m_dll.Load())
+ CLog::Log(LOGERROR, "Gif::Gif(): Could not load giflib");
+ memset(&m_backColor, 0, sizeof(m_backColor));
+ m_gifFile = new XFILE::CFile();
+}
+
+Gif::~Gif()
+{
+ if (m_dll.IsLoaded())
+ {
+ Close(m_gif);
+
+ m_dll.Unload();
+ Release();
+ }
+ delete m_gifFile;
+}
+
+void Gif::Close(GifFileType* gif)
+{
+ int err = 0;
+ int reason = 0;
+#if GIFLIB_MAJOR == 5
+ err = m_dll.DGifCloseFile(gif, &reason);
+#else
+ err = m_dll.DGifCloseFile(gif);
+ reason = m_dll.GifLastError();
+ if (err == GIF_ERROR)
+ free(gif);
+#endif
+ if (err == GIF_ERROR)
+ PrettyPrintError(StringUtils::Format("Gif::~Gif(): closing file %s failed", memOrFile().c_str()), reason);
+}
+
+void Gif::Release()
+{
+ delete[] m_pTemplate;
+ m_pTemplate = nullptr;
+ m_globalPalette.clear();
+ m_frames.clear();
+}
+
+void Gif::ConvertColorTable(std::vector<GifColor> &dest, ColorMapObject* src, unsigned int size)
+{
+ for (unsigned int i = 0; i < size; ++i)
+ {
+ GifColor c;
+
+ c.r = src->Colors[i].Red;
+ c.g = src->Colors[i].Green;
+ c.b = src->Colors[i].Blue;
+ c.a = 0xff;
+ dest.push_back(c);
+ }
+}
+
+bool Gif::LoadGifMetaData(GifFileType* gif)
+{
+ if (!m_dll.IsLoaded() || !Slurp(gif))
+ return false;
+
+ m_height = gif->SHeight;
+ m_width = gif->SWidth;
+ if (!m_height || !m_width)
+ {
+ CLog::Log(LOGERROR, "Gif::LoadGif(): Zero sized image. File %s", memOrFile().c_str());
+ return false;
+ }
+
+ m_numFrames = gif->ImageCount;
+ if (m_numFrames > 0)
+ {
+ ExtensionBlock* extb = gif->SavedImages[0].ExtensionBlocks;
+ if (extb && extb->Function == APPLICATION_EXT_FUNC_CODE)
+ {
+ // Read number of loops
+ if (++extb && extb->Function == CONTINUE_EXT_FUNC_CODE)
+ {
+ m_loops = UNSIGNED_LITTLE_ENDIAN(extb->Bytes[1], extb->Bytes[2]);
+ }
+ }
+ }
+ else
+ {
+ CLog::Log(LOGERROR, "Gif::LoadGif(): No images found in file %s", memOrFile().c_str());
+ return false;
+ }
+
+ m_pitch = m_width * sizeof(GifColor);
+ m_imageSize = m_pitch * m_height;
+ unsigned long memoryUsage = m_numFrames * m_imageSize;
+ if (memoryUsage > GIF_MAX_MEMORY)
+ {
+ // at least 1 image
+ m_numFrames = std::max(1U, GIF_MAX_MEMORY / m_imageSize);
+ CLog::Log(LOGERROR, "Gif::LoadGif(): Memory consumption too high: %lu bytes. Restricting animation to %u. File %s", memoryUsage, m_numFrames, memOrFile().c_str());
+ }
+
+ return true;
+}
+
+bool Gif::LoadGifMetaData(const char* file)
+{
+ if (!m_dll.IsLoaded())
+ return false;
+
+ m_gifFile->Close();
+ if (!m_gifFile->Open(file) || !Open(m_gif, m_gifFile, ReadFromVfs))
+ return false;
+
+ return LoadGifMetaData(m_gif);
+}
+
+bool Gif::Slurp(GifFileType* gif)
+{
+ if (m_dll.DGifSlurp(gif) == GIF_ERROR)
+ {
+ int reason = 0;
+#if GIFLIB_MAJOR == 5
+ reason = gif->Error;
+#else
+ reason = m_dll.GifLastError();
+#endif
+ PrettyPrintError(StringUtils::Format("Gif::LoadGif(): Could not read file %s", memOrFile().c_str()), reason);
+ return false;
+ }
+
+ return true;
+}
+
+bool Gif::LoadGif(const char* file)
+{
+ m_filename = file;
+ if (!LoadGifMetaData(m_filename.c_str()))
+ return false;
+
+ try
+ {
+ InitTemplateAndColormap();
+
+ return ExtractFrames(m_numFrames);
+ }
+ catch (std::bad_alloc& ba)
+ {
+ CLog::Log(LOGERROR, "Gif::Load(): Out of memory while reading file %s - %s", memOrFile().c_str(), ba.what());
+ Release();
+ return false;
+ }
+}
+
+bool Gif::IsAnimated(const char* file)
+{
+ if (!m_dll.IsLoaded())
+ return false;
+
+ if (m_isAnimated < 0)
+ {
+ m_filename = file;
+ m_isAnimated = 0;
+
+ GifFileType* gif = nullptr;
+ XFILE::CFile gifFile;
+
+ if (!gifFile.Open(file) || !Open(gif, &gifFile, ReadFromVfs))
+ return false;
+
+ if (gif)
+ {
+ if (Slurp(gif) && gif->ImageCount > 1)
+ m_isAnimated = 1;
+
+ Close(gif);
+ gifFile.Close();
+ }
+ }
+ return m_isAnimated > 0;
+}
+
+bool Gif::Open(GifFileType*& gif, void *dataPtr, InputFunc readFunc)
+{
+ int err = 0;
+#if GIFLIB_MAJOR == 5
+ gif = m_dll.DGifOpen(dataPtr, readFunc, &err);
+#else
+ gif = m_dll.DGifOpen(dataPtr, readFunc);
+ if (!gif)
+ err = m_dll.GifLastError();
+#endif
+
+ if (!gif)
+ {
+ PrettyPrintError(StringUtils::Format("Gif::Open(): Could not open file %s", memOrFile().c_str()), err);
+ return false;
+ }
+
+ return true;
+}
+
+void Gif::InitTemplateAndColormap()
+{
+ m_pTemplate = new unsigned char[m_imageSize];
+ memset(m_pTemplate, 0, m_imageSize);
+
+ if (m_gif->SColorMap)
+ {
+ m_globalPalette.clear();
+ ConvertColorTable(m_globalPalette, m_gif->SColorMap, m_gif->SColorMap->ColorCount);
+
+ // draw the canvas
+ m_backColor = m_globalPalette[m_gif->SBackGroundColor];
+ m_hasBackground = true;
+
+ for (unsigned int i = 0; i < m_height * m_width; ++i)
+ {
+ unsigned char *dest = m_pTemplate + (i *sizeof(GifColor));
+ memcpy(dest, &m_backColor, sizeof(GifColor));
+ }
+ }
+ else
+ m_globalPalette.clear();
+}
+
+bool Gif::GcbToFrame(GifFrame &frame, unsigned int imgIdx)
+{
+ int transparent = -1;
+ frame.m_delay = 0;
+ frame.m_disposal = 0;
+
+ if (m_gif->ImageCount > 0)
+ {
+#if GIFLIB_MAJOR == 5
+ GraphicsControlBlock gcb;
+ if (!m_dll.DGifSavedExtensionToGCB(m_gif, imgIdx, &gcb))
+ {
+ PrettyPrintError(StringUtils::Format("Gif::GcbToFrame(): Could not read GraphicsControlBlock of frame %d in file %s",
+ imgIdx, memOrFile().c_str()), m_gif->Error);
+ return false;
+ }
+ // delay in ms
+ frame.m_delay = gcb.DelayTime * 10;
+ frame.m_disposal = gcb.DisposalMode;
+ transparent = gcb.TransparentColor;
+#else
+ ExtensionBlock* extb = m_gif->SavedImages[imgIdx].ExtensionBlocks;
+ while (extb && extb->Function != GRAPHICS_EXT_FUNC_CODE)
+ extb++;
+
+ if (!extb || extb->ByteCount != 4)
+ {
+ CLog::Log(LOGERROR, "Gif::GcbToFrame() : Could not read GraphicsControlBlock of frame %d in file %s",
+ imgIdx, memOrFile().c_str());
+ return false;
+ }
+ else
+ {
+ frame.m_delay = UNSIGNED_LITTLE_ENDIAN(extb->Bytes[1], extb->Bytes[2]) * 10;
+ frame.m_disposal = (extb->Bytes[0] >> 2) & 0x07;
+ if (extb->Bytes[0] & 0x01)
+ {
+ transparent = static_cast<int>(extb->Bytes[3]);
+ if (transparent < 0)
+ transparent += 256;
+ }
+ else
+ transparent = -1;
+ }
+
+#endif
+ }
+
+ if (transparent >= 0 && (unsigned)transparent < frame.m_palette.size())
+ frame.m_palette[transparent].a = 0;
+ return true;
+}
+
+bool Gif::ExtractFrames(unsigned int count)
+{
+ if (!m_gif)
+ return false;
+
+ if (!m_pTemplate)
+ {
+ CLog::Log(LOGDEBUG, "Gif::ExtractFrames(): No frame template available");
+ return false;
+ }
+
+ for (unsigned int i = 0; i < count; i++)
+ {
+ FramePtr frame(new GifFrame);
+ SavedImage savedImage = m_gif->SavedImages[i];
+ GifImageDesc imageDesc = m_gif->SavedImages[i].ImageDesc;
+ frame->m_height = imageDesc.Height;
+ frame->m_width = imageDesc.Width;
+ frame->m_top = imageDesc.Top;
+ frame->m_left = imageDesc.Left;
+
+ if (frame->m_top + frame->m_height > m_height || frame->m_left + frame->m_width > m_width
+ || !frame->m_width || !frame->m_height)
+ {
+ CLog::Log(LOGDEBUG, "Gif::ExtractFrames(): Illegal frame dimensions: width: %d, height: %d, left: %d, top: %d instead of (%d,%d)",
+ frame->m_width, frame->m_height, frame->m_left, frame->m_top, m_width, m_height);
+ return false;
+ }
+
+ if (imageDesc.ColorMap)
+ {
+ frame->m_palette.clear();
+ ConvertColorTable(frame->m_palette, imageDesc.ColorMap, imageDesc.ColorMap->ColorCount);
+ // TODO save a backup of the palette for frames without a table in case there's no gloabl table.
+ }
+ else if (m_gif->SColorMap)
+ {
+ frame->m_palette = m_globalPalette;
+ }
+
+ // fill delay, disposal and transparent color into frame
+ if (!GcbToFrame(*frame, i))
+ return false;
+
+ frame->m_pImage = new unsigned char[m_imageSize];
+ frame->m_imageSize = m_imageSize;
+ memcpy(frame->m_pImage, m_pTemplate, m_imageSize);
+
+ ConstructFrame(*frame, savedImage.RasterBits);
+
+ if (!PrepareTemplate(*frame))
+ return false;
+
+ m_frames.push_back(frame);
+ }
+ return true;
+}
+
+void Gif::ConstructFrame(GifFrame &frame, const unsigned char* src) const
+{
+ for (unsigned int dest_y = frame.m_top, src_y = 0; src_y < frame.m_height; ++dest_y, ++src_y)
+ {
+ unsigned char *to = frame.m_pImage + (dest_y * m_pitch) + (frame.m_left * sizeof(GifColor));
+
+ const unsigned char *from = src + (src_y * frame.m_width);
+ for (unsigned int src_x = 0; src_x < frame.m_width; ++src_x)
+ {
+ GifColor col = frame.m_palette[*from++];
+ if (col.a != 0)
+ {
+ *to++ = col.b;
+ *to++ = col.g;
+ *to++ = col.r;
+ *to++ = col.a;
+ }
+ else
+ {
+ to += 4;
+ }
+ }
+ }
+}
+
+bool Gif::PrepareTemplate(const GifFrame &frame)
+{
+ switch (frame.m_disposal)
+ {
+ /* No disposal specified. */
+ case DISPOSAL_UNSPECIFIED:
+ /* Leave image in place */
+ case DISPOSE_DO_NOT:
+ memcpy(m_pTemplate, frame.m_pImage, m_imageSize);
+ break;
+
+ /* Set area too background color */
+ case DISPOSE_BACKGROUND:
+ {
+ if (!m_hasBackground)
+ {
+ CLog::Log(LOGDEBUG, "Gif::PrepareTemplate(): Disposal method DISPOSE_BACKGROUND encountered, but the gif has no background.");
+ return false;
+ }
+ SetFrameAreaToBack(m_pTemplate, frame);
+ break;
+ }
+ /* Restore to previous content */
+ case DISPOSE_PREVIOUS:
+ {
+ bool valid = false;
+
+ for (int i = m_frames.size() - 1; i >= 0; --i)
+ {
+ if (m_frames[i]->m_disposal != DISPOSE_PREVIOUS)
+ {
+ memcpy(m_pTemplate, m_frames[i]->m_pImage, m_imageSize);
+ valid = true;
+ break;
+ }
+ }
+ if (!valid)
+ {
+ CLog::Log(LOGDEBUG, "Gif::PrepareTemplate(): Disposal method DISPOSE_PREVIOUS encountered, but could not find a suitable frame.");
+ return false;
+ }
+ break;
+ }
+ default:
+ {
+ CLog::Log(LOGDEBUG, "Gif::PrepareTemplate(): Unknown disposal method: %d", frame.m_disposal);
+ return false;
+ }
+ }
+ return true;
+}
+
+void Gif::SetFrameAreaToBack(unsigned char* dest, const GifFrame &frame)
+{
+ for (unsigned int dest_y = frame.m_top, src_y = 0; src_y < frame.m_height; ++dest_y, ++src_y)
+ {
+ unsigned char *to = dest + (dest_y * m_pitch) + (frame.m_left * sizeof(GifColor));
+ for (unsigned int src_x = 0; src_x < frame.m_width; ++src_x)
+ {
+ memcpy(to, &m_backColor, sizeof(m_backColor));
+ to += 4;
+ }
+ }
+}
+
+bool Gif::LoadImageFromMemory(unsigned char* buffer, unsigned int bufSize, unsigned int width, unsigned int height)
+{
+ if (!m_dll.IsLoaded())
+ return false;
+
+ if (!buffer || !bufSize || !width || !height)
+ return false;
+
+ Gifreader reader;
+ reader.buffer = buffer;
+ reader.buffSize = bufSize;
+
+ if (!Open(m_gif, static_cast<void *>(&reader), ReadFromMemory))
+ return false;
+
+ if (!LoadGifMetaData(m_gif))
+ return false;
+
+ m_originalWidth = m_width;
+ m_originalHeight = m_height;
+
+ try
+ {
+ InitTemplateAndColormap();
+
+ if (!ExtractFrames(m_numFrames))
+ return false;
+ }
+ catch (std::bad_alloc& ba)
+ {
+ CLog::Log(LOGERROR, "Gif::LoadImageFromMemory(): Out of memory while extracting gif frames - %s", ba.what());
+ Release();
+ return false;
+ }
+
+ return true;
+}
+
+bool Gif::Decode(unsigned char* const pixels, unsigned int pitch, unsigned int format)
+{
+ if (m_width == 0 || m_height == 0
+ || !m_dll.IsLoaded() || !m_gif
+ || format != XB_FMT_A8R8G8B8 || !m_numFrames)
+ return false;
+
+ const unsigned char *src = m_frames[0]->m_pImage;
+ unsigned char* dst = pixels;
+
+ if (pitch == m_pitch)
+ memcpy(dst, src, m_imageSize);
+ else
+ {
+ for (unsigned int y = 0; y < m_height; y++)
+ {
+ memcpy(dst, src, m_pitch);
+ src += m_pitch;
+ dst += pitch;
+ }
+ }
+ return true;
+}
+
+bool Gif::CreateThumbnailFromSurface(unsigned char* bufferin, unsigned int width, unsigned int height, unsigned int format, unsigned int pitch, const std::string& destFile,
+ unsigned char* &bufferout, unsigned int &bufferoutSize)
+{
+ CLog::Log(LOGERROR, "Gif::CreateThumbnailFromSurface(): Not implemented. Something went wrong, we don't store thumbnails as gifs!");
+ return false;
+}
+
+void Gif::PrettyPrintError(std::string messageTemplate, int reason)
+{
+ const char* error = m_dll.GifErrorString(reason);
+ std::string message;
+ if (error)
+ {
+ message = StringUtils::Format(messageTemplate.append(" - %s").c_str(), error);
+ }
+ else
+ {
+ message = messageTemplate.append(" (reason unknown)");
+ }
+ CLog::Log(LOGERROR, "%s", message.c_str());
+}
+
+GifFrame::GifFrame() :
+ m_pImage(nullptr),
+ m_delay(0),
+ m_imageSize(0),
+ m_height(0),
+ m_width(0),
+ m_top(0),
+ m_left(0),
+ m_disposal(0)
+{}
+
+
+GifFrame::GifFrame(const GifFrame& src) :
+ m_pImage(nullptr),
+ m_delay(src.m_delay),
+ m_imageSize(src.m_imageSize),
+ m_height(src.m_height),
+ m_width(src.m_width),
+ m_top(src.m_top),
+ m_left(src.m_left),
+ m_disposal(src.m_disposal)
+{
+ if (src.m_pImage)
+ {
+ m_pImage = new unsigned char[m_imageSize];
+ memcpy(m_pImage, src.m_pImage, m_imageSize);
+ }
+
+ if (src.m_palette.size())
+ {
+ m_palette = src.m_palette;
+ }
+}
+
+GifFrame::~GifFrame()
+{
+ delete[] m_pImage;
+ m_pImage = nullptr;
+}
+#endif//HAS_GIFLIB
diff --git a/xbmc/guilib/Gif.h b/xbmc/guilib/Gif.h
new file mode 100644
index 0000000000..959e076ec4
--- /dev/null
+++ b/xbmc/guilib/Gif.h
@@ -0,0 +1,121 @@
+#pragma once
+
+/*
+ * Copyright (C) 2005-2014 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "guilib/iimage.h"
+#include "DllLibGif.h"
+#include <memory>
+#include <vector>
+
+namespace XFILE
+{
+ class CFile;
+};
+
+#pragma pack(1)
+struct GifColor
+{
+ uint8_t b, g, r, a;
+};
+#pragma pack()
+
+
+class GifFrame
+{
+ friend class Gif;
+
+public:
+
+ GifFrame();
+ virtual ~GifFrame();
+
+ unsigned char* m_pImage;
+ unsigned int m_delay;
+
+private:
+ GifFrame(const GifFrame& src);
+
+ unsigned int m_imageSize;
+ unsigned int m_height;
+ unsigned int m_width;
+ unsigned int m_top;
+ unsigned int m_left;
+ std::vector<GifColor> m_palette;
+ unsigned int m_disposal;
+};
+
+class Gif : public IImage
+{
+public:
+ typedef std::shared_ptr<GifFrame> FramePtr;
+
+ Gif();
+ virtual ~Gif();
+
+ bool LoadGifMetaData(const char* file);
+ bool LoadGif(const char* file);
+
+ virtual bool LoadImageFromMemory(unsigned char* buffer, unsigned int bufSize, unsigned int width, unsigned int height);
+ virtual bool Decode(unsigned char* const pixels, unsigned int pitch, unsigned int format);
+ virtual bool CreateThumbnailFromSurface(unsigned char* bufferin, unsigned int width, unsigned int height, unsigned int format, unsigned int pitch, const std::string& destFile,
+ unsigned char* &bufferout, unsigned int &bufferoutSize);
+ bool IsAnimated(const char* file);
+ const std::vector<FramePtr>& GetFrames() const { return m_frames; }
+ unsigned int GetPitch() const { return m_pitch; }
+ unsigned int GetNumLoops() const { return m_loops; }
+
+private:
+ std::vector<FramePtr> m_frames;
+ unsigned int m_imageSize;
+ unsigned int m_pitch;
+ unsigned int m_loops;
+ unsigned int m_numFrames;
+
+ DllLibGif m_dll;
+ std::string m_filename;
+ GifFileType* m_gif;
+ bool m_hasBackground;
+ GifColor m_backColor;
+ std::vector<GifColor> m_globalPalette;
+ unsigned char* m_pTemplate;
+ int m_isAnimated;
+ XFILE::CFile* m_gifFile;
+
+ void InitTemplateAndColormap();
+ bool LoadGifMetaData(GifFileType* gif);
+ bool Open(GifFileType*& gif, void *dataPtr, InputFunc readFunc);
+ void Close(GifFileType* gif);
+ bool Slurp(GifFileType* gif);
+ static void ConvertColorTable(std::vector<GifColor> &dest, ColorMapObject* src, unsigned int size);
+ bool GcbToFrame(GifFrame &frame, unsigned int imgIdx);
+ bool ExtractFrames(unsigned int count);
+ void SetFrameAreaToBack(unsigned char* dest, const GifFrame &frame);
+ void ConstructFrame(GifFrame &frame, const unsigned char* src) const;
+ bool PrepareTemplate(const GifFrame &frame);
+ void Release();
+ void PrettyPrintError(std::string messageTemplate, int reason);
+
+ inline std::string memOrFile()
+ {
+ return m_filename.empty() ? std::string("memory file") : m_filename;
+ }
+
+};
diff --git a/xbmc/guilib/Makefile.in b/xbmc/guilib/Makefile.in
index 89a766d38f..6df600e36b 100644
--- a/xbmc/guilib/Makefile.in
+++ b/xbmc/guilib/Makefile.in
@@ -1,5 +1,4 @@
-SRCS = AnimatedGif.cpp
-SRCS += DDSImage.cpp
+SRCS = DDSImage.cpp
SRCS += DirectXGraphics.cpp
SRCS += DirtyRegionSolvers.cpp
SRCS += DirtyRegionTracker.cpp
@@ -78,6 +77,10 @@ SRCS += VisibleEffect.cpp
SRCS += XBTF.cpp
SRCS += XBTFReader.cpp
+ifeq (@USE_LIBGIF@,1)
+SRCS += Gif.cpp
+endif
+
ifeq (@USE_OPENGL@,1)
SRCS += TextureGL.cpp
SRCS += GUIFontTTFGL.cpp
diff --git a/xbmc/guilib/TextureBundleXBT.cpp b/xbmc/guilib/TextureBundleXBT.cpp
index 1fb21c8e25..ba7f49d5aa 100644
--- a/xbmc/guilib/TextureBundleXBT.cpp
+++ b/xbmc/guilib/TextureBundleXBT.cpp
@@ -313,7 +313,7 @@ uint8_t* CTextureBundleXBT::UnpackFrame(const CXBTFReader& reader, const CXBTFFr
return nullptr;
}
- delete packedBuffer;
+ delete[] packedBuffer;
return unpackedBuffer;
}
diff --git a/xbmc/guilib/TextureManager.cpp b/xbmc/guilib/TextureManager.cpp
index fcfe733f78..fd5614c76e 100644
--- a/xbmc/guilib/TextureManager.cpp
+++ b/xbmc/guilib/TextureManager.cpp
@@ -20,7 +20,9 @@
#include "TextureManager.h"
#include "Texture.h"
-#include "AnimatedGif.h"
+#if defined(HAS_GIFLIB)
+#include "guilib/Gif.h"
+#endif//HAS_GIFLIB
#include "GraphicContext.h"
#include "threads/SingleLock.h"
#include "utils/log.h"
@@ -89,7 +91,7 @@ void CTextureArray::Add(CBaseTexture *texture, int delay)
return;
m_textures.push_back(texture);
- m_delays.push_back(delay ? delay * 2 : 100);
+ m_delays.push_back(delay);
m_texWidth = texture->GetTextureWidth();
m_texHeight = texture->GetTextureHeight();
@@ -102,7 +104,7 @@ void CTextureArray::Set(CBaseTexture *texture, int width, int height)
m_width = width;
m_height = height;
m_orientation = texture ? texture->GetOrientation() : 0;
- Add(texture, 100);
+ Add(texture, 2);
}
void CTextureArray::Free()
@@ -322,7 +324,7 @@ const CTextureArray& CGUITextureManager::Load(const std::string& strTextureName,
if (StringUtils::EndsWithNoCase(strPath, ".gif"))
{
- CTextureMap* pMap;
+ CTextureMap* pMap = nullptr;
if (bundle >= 0)
{
@@ -349,42 +351,34 @@ const CTextureArray& CGUITextureManager::Load(const std::string& strTextureName,
}
else
{
- CAnimatedGifSet AnimatedGifSet;
- int iImages = AnimatedGifSet.LoadGIF(strPath.c_str());
- if (iImages == 0)
+#if defined(HAS_GIFLIB)
+ Gif gif;
+ if(!gif.LoadGif(strPath.c_str()))
{
if (StringUtils::StartsWith(strPath, g_SkinInfo->Path()))
CLog::Log(LOGERROR, "Texture manager unable to load file: %s", strPath.c_str());
return emptyTexture;
}
- int iWidth = AnimatedGifSet.FrameWidth;
- int iHeight = AnimatedGifSet.FrameHeight;
- // fixup our palette
- COLOR *palette = AnimatedGifSet.m_vecimg[0]->Palette;
- // set the alpha values to fully opaque
- for (int i = 0; i < 256; i++)
- palette[i].x = 0xff;
- // and set the transparent colour
- if (AnimatedGifSet.m_vecimg[0]->Transparency && AnimatedGifSet.m_vecimg[0]->Transparent >= 0)
- palette[AnimatedGifSet.m_vecimg[0]->Transparent].x = 0;
+ pMap = new CTextureMap(strTextureName, gif.Width(), gif.Height(), gif.GetNumLoops());
- pMap = new CTextureMap(strTextureName, iWidth, iHeight, AnimatedGifSet.nLoops);
-
- for (int iImage = 0; iImage < iImages; iImage++)
+ for (auto frame : gif.GetFrames())
{
CTexture *glTexture = new CTexture();
if (glTexture)
{
- CAnimatedGif* pImage = AnimatedGifSet.m_vecimg[iImage];
- glTexture->LoadPaletted(pImage->Width, pImage->Height, pImage->BytesPerRow, XB_FMT_A8R8G8B8, (unsigned char *)pImage->Raster, palette);
- pMap->Add(glTexture, pImage->Delay);
+ glTexture->LoadFromMemory(gif.Width(), gif.Height(), gif.GetPitch(), XB_FMT_A8R8G8B8, false, frame->m_pImage);
+ pMap->Add(glTexture, frame->m_delay);
}
- } // of for (int iImage=0; iImage < iImages; iImage++)
+ }
+#endif//HAS_GIFLIB
}
- m_vecTextures.push_back(pMap);
- return pMap->GetTexture();
+ if (pMap)
+ {
+ m_vecTextures.push_back(pMap);
+ return pMap->GetTexture();
+ }
} // of if (strPath.Right(4).ToLower()==".gif")
CBaseTexture *pTexture = NULL;
diff --git a/xbmc/guilib/WindowIDs.h b/xbmc/guilib/WindowIDs.h
index 10810ac761..60f9c88b48 100644
--- a/xbmc/guilib/WindowIDs.h
+++ b/xbmc/guilib/WindowIDs.h
@@ -138,6 +138,7 @@
#define WINDOW_RADIO_TIMERS 10623
#define WINDOW_RADIO_SEARCH 10624
#define WINDOW_FULLSCREEN_RADIO 10625 // virtual window for PVR radio specific keymaps with fallback to WINDOW_VISUALISATION
+#define WINDOW_DIALOG_PVR_RADIO_RDS_INFO 10626
//#define WINDOW_VIRTUAL_KEYBOARD 11000
// WINDOW_ID's from 11100 to 11199 reserved for Skins
diff --git a/xbmc/guilib/imagefactory.cpp b/xbmc/guilib/imagefactory.cpp
index 1033a82939..7fdead632c 100644
--- a/xbmc/guilib/imagefactory.cpp
+++ b/xbmc/guilib/imagefactory.cpp
@@ -22,6 +22,9 @@
#include "guilib/JpegIO.h"
#include "guilib/cximage.h"
#include "utils/Mime.h"
+#if defined(HAS_GIFLIB)
+#include "guilib/Gif.h"
+#endif//HAS_GIFLIB
IImage* ImageFactory::CreateLoader(const std::string& strFileName)
{
@@ -41,6 +44,11 @@ IImage* ImageFactory::CreateLoaderFromMimeType(const std::string& strMimeType)
{
if(strMimeType == "image/jpeg" || strMimeType == "image/tbn" || strMimeType == "image/jpg")
return new CJpegIO();
+#if defined(HAS_GIFLIB)
+ else if (strMimeType == "image/gif")
+ return new Gif();
+#endif//HAS_GIFLIB
+
return new CXImage(strMimeType);
}
diff --git a/xbmc/input/ButtonTranslator.cpp b/xbmc/input/ButtonTranslator.cpp
index 090e141e51..398fef7b0d 100644
--- a/xbmc/input/ButtonTranslator.cpp
+++ b/xbmc/input/ButtonTranslator.cpp
@@ -293,6 +293,7 @@ static const ActionMapping windows[] =
{ "radiosearch" , WINDOW_RADIO_SEARCH },
{ "pvrguideinfo" , WINDOW_DIALOG_PVR_GUIDE_INFO },
{ "pvrrecordinginfo" , WINDOW_DIALOG_PVR_RECORDING_INFO },
+ { "pvrradiordsinfo" , WINDOW_DIALOG_PVR_RADIO_RDS_INFO },
{ "pvrtimersetting" , WINDOW_DIALOG_PVR_TIMER_SETTING },
{ "pvrgroupmanager" , WINDOW_DIALOG_PVR_GROUP_MANAGER },
{ "pvrchannelmanager" , WINDOW_DIALOG_PVR_CHANNEL_MANAGER },
diff --git a/xbmc/input/InputManager.cpp b/xbmc/input/InputManager.cpp
index 7da002e38e..1eaffc25da 100644
--- a/xbmc/input/InputManager.cpp
+++ b/xbmc/input/InputManager.cpp
@@ -43,9 +43,9 @@
#include "input/windows/IRServerSuite.h"
#endif
-#if SDL_VERSION == 1
+#if HAVE_SDL_VERSION == 1
#include <SDL/SDL.h>
-#elif SDL_VERSION == 2
+#elif HAVE_SDL_VERSION == 2
#include <SDL2/SDL.h>
#endif
diff --git a/xbmc/interfaces/Builtins.cpp b/xbmc/interfaces/Builtins.cpp
index 6435efe946..cfe3ca6268 100644
--- a/xbmc/interfaces/Builtins.cpp
+++ b/xbmc/interfaces/Builtins.cpp
@@ -25,6 +25,7 @@
#include "utils/SeekHandler.h"
#include "Application.h"
#include "messaging/ApplicationMessenger.h"
+#include "messaging/helpers/DialogHelper.h"
#include "Autorun.h"
#include "Builtins.h"
#include "input/ButtonTranslator.h"
@@ -39,7 +40,6 @@
#include "dialogs/GUIDialogKaiToast.h"
#include "dialogs/GUIDialogNumeric.h"
#include "dialogs/GUIDialogProgress.h"
-#include "dialogs/GUIDialogYesNo.h"
#include "GUIUserMessages.h"
#include "windows/GUIWindowLoginScreen.h"
#include "video/windows/GUIWindowVideoBase.h"
@@ -117,6 +117,8 @@ using namespace KODI::MESSAGING;
using namespace MEDIA_DETECT;
#endif
+using KODI::MESSAGING::HELPERS::DialogResponse;
+
typedef struct
{
const char* command;
@@ -1594,7 +1596,11 @@ int CBuiltins::Execute(const std::string& execString)
if (params.size() > 1)
singleFile = StringUtils::EqualsNoCase(params[1], "true");
else
- singleFile = !CGUIDialogYesNo::ShowAndGetInput(CVariant{iHeading}, CVariant{20426}, cancelled, CVariant{20428}, CVariant{20429});
+ {
+ DialogResponse result = HELPERS::ShowYesNoDialogText(CVariant{iHeading}, CVariant{20426}, CVariant{20428}, CVariant{20429});
+ cancelled = result == DialogResponse::CANCELLED;
+ singleFile = result != DialogResponse::YES;
+ }
if (cancelled)
return -1;
@@ -1604,7 +1610,11 @@ int CBuiltins::Execute(const std::string& execString)
if (params.size() > 2)
thumbs = StringUtils::EqualsNoCase(params[2], "true");
else
- thumbs = CGUIDialogYesNo::ShowAndGetInput(CVariant{iHeading}, CVariant{20430}, cancelled, CVariant{""}, CVariant{""}, CGUIDialogYesNo::NO_TIMEOUT);
+ {
+ DialogResponse result = HELPERS::ShowYesNoDialogText(CVariant{iHeading}, CVariant{20430}, CVariant{20428}, CVariant{20429});
+ cancelled = result == DialogResponse::CANCELLED;
+ thumbs = result == DialogResponse::YES;
+ }
}
if (cancelled)
@@ -1615,7 +1625,11 @@ int CBuiltins::Execute(const std::string& execString)
if (params.size() > 4)
actorThumbs = StringUtils::EqualsNoCase(params[4], "true");
else
- actorThumbs = CGUIDialogYesNo::ShowAndGetInput(CVariant{iHeading}, CVariant{20436}, cancelled, CVariant{ "" }, CVariant{ "" }, CGUIDialogYesNo::NO_TIMEOUT);
+ {
+ DialogResponse result = HELPERS::ShowYesNoDialogText(CVariant{iHeading}, CVariant{20436});
+ cancelled = result == DialogResponse::CANCELLED;
+ actorThumbs = result == DialogResponse::YES;
+ }
}
if (cancelled)
@@ -1626,7 +1640,11 @@ int CBuiltins::Execute(const std::string& execString)
if (params.size() > 3)
overwrite = StringUtils::EqualsNoCase(params[3], "true");
else
- overwrite = CGUIDialogYesNo::ShowAndGetInput(CVariant{iHeading}, CVariant{20431}, cancelled, CVariant{ "" }, CVariant{ "" }, CGUIDialogYesNo::NO_TIMEOUT);
+ {
+ DialogResponse result = HELPERS::ShowYesNoDialogText(CVariant{iHeading}, CVariant{20431});
+ cancelled = result == DialogResponse::CANCELLED;
+ overwrite = result == DialogResponse::YES;
+ }
}
if (cancelled)
diff --git a/xbmc/interfaces/legacy/InfoTagRadioRDS.cpp b/xbmc/interfaces/legacy/InfoTagRadioRDS.cpp
new file mode 100644
index 0000000000..672bf61e54
--- /dev/null
+++ b/xbmc/interfaces/legacy/InfoTagRadioRDS.cpp
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2005-2015 Team KODI
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with KODI; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "InfoTagRadioRDS.h"
+#include "utils/StringUtils.h"
+
+namespace XBMCAddon
+{
+ namespace xbmc
+ {
+ InfoTagRadioRDS::InfoTagRadioRDS()
+ {
+ PVR::CPVRRadioRDSInfoTagPtr empty;
+ infoTag = empty;
+ }
+
+ InfoTagRadioRDS::InfoTagRadioRDS(const PVR::CPVRRadioRDSInfoTagPtr tag)
+ {
+ infoTag = tag;
+ }
+
+ InfoTagRadioRDS::~InfoTagRadioRDS()
+ {
+ }
+
+ String InfoTagRadioRDS::getTitle()
+ {
+ if (infoTag)
+ return infoTag->GetTitle();
+ return "";
+ }
+
+ String InfoTagRadioRDS::getBand()
+ {
+ if (infoTag)
+ return infoTag->GetBand();
+ return "";
+ }
+
+ String InfoTagRadioRDS::getArtist()
+ {
+ if (infoTag)
+ return infoTag->GetArtist();
+ return "";
+ }
+
+ String InfoTagRadioRDS::getComposer()
+ {
+ if (infoTag)
+ return infoTag->GetComposer();
+ return "";
+ }
+
+ String InfoTagRadioRDS::getConductor()
+ {
+ if (infoTag)
+ return infoTag->GetConductor();
+ return "";
+ }
+
+ String InfoTagRadioRDS::getAlbum()
+ {
+ if (infoTag)
+ return infoTag->GetAlbum();
+ return "";
+ }
+
+ String InfoTagRadioRDS::getComment()
+ {
+ if (infoTag)
+ return infoTag->GetComment();
+ return "";
+ }
+
+ int InfoTagRadioRDS::getAlbumTrackNumber()
+ {
+ if (infoTag)
+ return infoTag->GetAlbumTrackNumber();
+ return 0;
+ }
+
+ String InfoTagRadioRDS::getInfoNews()
+ {
+ if (infoTag)
+ return infoTag->GetInfoNews();
+ return "";
+ }
+
+ String InfoTagRadioRDS::getInfoNewsLocal()
+ {
+ if (infoTag)
+ return infoTag->GetInfoNewsLocal();
+ return "";
+ }
+
+ String InfoTagRadioRDS::getInfoSport()
+ {
+ if (infoTag)
+ return infoTag->GetInfoSport();
+ return "";
+ }
+
+ String InfoTagRadioRDS::getInfoStock()
+ {
+ if (infoTag)
+ return infoTag->GetInfoStock();
+ return "";
+ }
+
+ String InfoTagRadioRDS::getInfoWeather()
+ {
+ if (infoTag)
+ return infoTag->GetInfoWeather();
+ return "";
+ }
+
+ String InfoTagRadioRDS::getInfoHoroscope()
+ {
+ if (infoTag)
+ return infoTag->GetInfoHoroscope();
+ return "";
+ }
+
+ String InfoTagRadioRDS::getInfoCinema()
+ {
+ if (infoTag)
+ return infoTag->GetInfoCinema();
+ return "";
+ }
+
+ String InfoTagRadioRDS::getInfoLottery()
+ {
+ if (infoTag)
+ return infoTag->GetInfoLottery();
+ return "";
+ }
+
+ String InfoTagRadioRDS::getInfoOther()
+ {
+ if (infoTag)
+ return infoTag->GetInfoOther();
+ return "";
+ }
+
+ String InfoTagRadioRDS::getEditorialStaff()
+ {
+ if (infoTag)
+ return infoTag->GetEditorialStaff();
+ return "";
+ }
+
+ String InfoTagRadioRDS::getProgStation()
+ {
+ if (infoTag)
+ return infoTag->GetProgStation();
+ return "";
+ }
+
+ String InfoTagRadioRDS::getProgStyle()
+ {
+ if (infoTag)
+ return infoTag->GetProgStyle();
+ return "";
+ }
+
+ String InfoTagRadioRDS::getProgHost()
+ {
+ if (infoTag)
+ return infoTag->GetProgHost();
+ return "";
+ }
+
+ String InfoTagRadioRDS::getProgWebsite()
+ {
+ if (infoTag)
+ return infoTag->GetProgWebsite();
+ return "";
+ }
+
+ String InfoTagRadioRDS::getProgNow()
+ {
+ if (infoTag)
+ return infoTag->GetProgNow();
+ return "";
+ }
+
+ String InfoTagRadioRDS::getProgNext()
+ {
+ if (infoTag)
+ return infoTag->GetProgNext();
+ return "";
+ }
+
+ String InfoTagRadioRDS::getPhoneHotline()
+ {
+ if (infoTag)
+ return infoTag->GetPhoneHotline();
+ return "";
+ }
+
+ String InfoTagRadioRDS::getEMailHotline()
+ {
+ if (infoTag)
+ return infoTag->GetEMailHotline();
+ return "";
+ }
+
+ String InfoTagRadioRDS::getPhoneStudio()
+ {
+ if (infoTag)
+ return infoTag->GetPhoneStudio();
+ return "";
+ }
+
+ String InfoTagRadioRDS::getEMailStudio()
+ {
+ if (infoTag)
+ return infoTag->GetEMailStudio();
+ return "";
+ }
+
+ String InfoTagRadioRDS::getSMSStudio()
+ {
+ if (infoTag)
+ return infoTag->GetSMSStudio();
+ return "";
+ }
+
+ }
+}
+
diff --git a/xbmc/interfaces/legacy/InfoTagRadioRDS.h b/xbmc/interfaces/legacy/InfoTagRadioRDS.h
new file mode 100644
index 0000000000..bd376d5857
--- /dev/null
+++ b/xbmc/interfaces/legacy/InfoTagRadioRDS.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2005-2015 Team KODI
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with KODI; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "pvr/channels/PVRRadioRDSInfoTag.h"
+#include "AddonClass.h"
+
+#pragma once
+
+namespace XBMCAddon
+{
+ namespace xbmc
+ {
+ /**
+ * InfoTagRadioRDS class.\n
+ */
+ class InfoTagRadioRDS : public AddonClass
+ {
+ private:
+ PVR::CPVRRadioRDSInfoTagPtr infoTag;
+
+ public:
+#ifndef SWIG
+ InfoTagRadioRDS(const PVR::CPVRRadioRDSInfoTagPtr tag);
+#endif
+ InfoTagRadioRDS();
+ virtual ~InfoTagRadioRDS();
+
+ /**
+ * getTitle() -- returns a string.\n
+ */
+ String getTitle();
+ /**
+ * getBand() -- returns a string.\n
+ */
+ String getBand();
+ /**
+ * getArtist() -- returns a string.\n
+ */
+ String getArtist();
+ /**
+ * getComposer() -- returns a string.\n
+ */
+ String getComposer();
+ /**
+ * getConductor() -- returns a string.\n
+ */
+ String getConductor();
+ /**
+ * getAlbum() -- returns a string.\n
+ */
+ String getAlbum();
+ /**
+ * getComment() -- returns a string.\n
+ */
+ String getComment();
+ /**
+ * getAlbumTrackNumber() -- returns a integer.\n
+ */
+ int getAlbumTrackNumber();
+ /**
+ * getInfoNews() -- returns an string.\n
+ */
+ String getInfoNews();
+ /**
+ * getInfoNewsLocal() -- returns a string.\n
+ */
+ String getInfoNewsLocal();
+ /**
+ * getInfoSport() -- returns a string.\n
+ */
+ String getInfoSport();
+ /**
+ * getInfoStock() -- returns a string.\n
+ */
+ String getInfoStock();
+ /**
+ * getInfoWeather() -- returns a string.\n
+ */
+ String getInfoWeather();
+ /**
+ * getInfoHoroscope() -- returns a string.\n
+ */
+ String getInfoHoroscope();
+ /**
+ * getInfoCinema() -- returns a string.\n
+ */
+ String getInfoCinema();
+ /**
+ * getInfoLottery() -- returns a string.\n
+ */
+ String getInfoLottery();
+ /**
+ * getInfoOther() -- returns a string.\n
+ */
+ String getInfoOther();
+ /**
+ * getEditorialStaff() -- returns a string.\n
+ */
+ String getEditorialStaff();
+ /**
+ * getProgStation() -- returns a string.\n
+ */
+ String getProgStation();
+ /**
+ * getProgStyle() -- returns a string.\n
+ */
+ String getProgStyle();
+ /**
+ * getProgHost() -- returns a string.\n
+ */
+ String getProgHost();
+ /**
+ * getProgWebsite() -- returns a string.\n
+ */
+ String getProgWebsite();
+ /**
+ * getProgNow() -- returns a string.\n
+ */
+ String getProgNow();
+ /**
+ * getProgNext() -- returns a string.\n
+ */
+ String getProgNext();
+ /**
+ * getPhoneHotline() -- returns a string.\n
+ */
+ String getPhoneHotline();
+ /**
+ * getEMailHotline() -- returns a string.\n
+ */
+ String getEMailHotline();
+ /**
+ * getPhoneStudio() -- returns a string.\n
+ */
+ String getPhoneStudio();
+ /**
+ * getEMailStudio() -- returns a string.\n
+ */
+ String getEMailStudio();
+ /**
+ * getSMSStudio() -- returns a string.\n
+ */
+ String getSMSStudio();
+
+ };
+ }
+}
+
diff --git a/xbmc/interfaces/legacy/Makefile b/xbmc/interfaces/legacy/Makefile
index 60ef6dbd64..6f2717f9b5 100644
--- a/xbmc/interfaces/legacy/Makefile
+++ b/xbmc/interfaces/legacy/Makefile
@@ -10,6 +10,7 @@ SRCS= \
Dialog.cpp \
File.cpp \
InfoTagMusic.cpp \
+ InfoTagRadioRDS.cpp \
InfoTagVideo.cpp \
Keyboard.cpp \
LanguageHook.cpp \
diff --git a/xbmc/interfaces/legacy/Player.cpp b/xbmc/interfaces/legacy/Player.cpp
index 05d576a7df..67938158fe 100644
--- a/xbmc/interfaces/legacy/Player.cpp
+++ b/xbmc/interfaces/legacy/Player.cpp
@@ -319,6 +319,12 @@ namespace XBMCAddon
return g_application.m_pPlayer->IsPlayingVideo();
}
+ bool Player::isPlayingRDS()
+ {
+ XBMC_TRACE;
+ return g_application.m_pPlayer->IsPlayingRDS();
+ }
+
String Player::getPlayingFile()
{
XBMC_TRACE;
@@ -354,6 +360,19 @@ namespace XBMCAddon
return new InfoTagMusic();
}
+ InfoTagRadioRDS* Player::getRadioRDSInfoTag() throw (PlayerException)
+ {
+ XBMC_TRACE;
+ if (g_application.m_pPlayer->IsPlayingVideo() || !g_application.m_pPlayer->IsPlayingRDS())
+ throw PlayerException("XBMC is not playing any music file with RDS");
+
+ const PVR::CPVRRadioRDSInfoTagPtr tag = g_infoManager.GetCurrentRadioRDSInfoTag();
+ if (tag)
+ return new InfoTagRadioRDS(tag);
+
+ return new InfoTagRadioRDS();
+ }
+
double Player::getTotalTime()
{
XBMC_TRACE;
diff --git a/xbmc/interfaces/legacy/Player.h b/xbmc/interfaces/legacy/Player.h
index 4295220220..cae1f48b42 100644
--- a/xbmc/interfaces/legacy/Player.h
+++ b/xbmc/interfaces/legacy/Player.h
@@ -28,6 +28,7 @@
#include "Exception.h"
#include "AddonString.h"
#include "InfoTagMusic.h"
+#include "InfoTagRadioRDS.h"
#include "AddonCallback.h"
#include "Alternative.h"
@@ -218,6 +219,12 @@ namespace XBMCAddon
bool isPlayingVideo();
/**
+ * isPlayingRDS() -- returns True if xbmc is playing a radio data system (RDS).
+ */
+ // Player_IsPlayingRDS
+ bool isPlayingRDS();
+
+ /**
* getPlayingFile() -- returns the current playing file as a string.\n
* Note: For LiveTV, returns a pvr:// url which is not translatable to an OS specific file or external url\n
* \n
@@ -306,6 +313,14 @@ namespace XBMCAddon
InfoTagMusic* getMusicInfoTag();
/**
+ * getRadioRDSInfoTag() -- returns the RadioRDSInfoTag of the current playing 'Radio Song if present'.
+ *
+ * Throws: Exception, if player is not playing a file or current file is not a rds file.
+ */
+ // Player_GetRadioRDSInfoTag
+ InfoTagRadioRDS* getRadioRDSInfoTag() throw (PlayerException);
+
+ /**
* getTotalTime() -- Returns the total time of the current playing media in
* seconds. This is only accurate to the full second.
*
diff --git a/xbmc/interfaces/python/swig.cpp b/xbmc/interfaces/python/swig.cpp
index da0239f612..d8d5ad9a94 100644
--- a/xbmc/interfaces/python/swig.cpp
+++ b/xbmc/interfaces/python/swig.cpp
@@ -196,18 +196,29 @@ namespace PythonBindings
PyObject *tracebackModule = PyImport_ImportModule("traceback");
if (tracebackModule != NULL)
{
- PyObject *tbList = PyObject_CallMethod(tracebackModule, "format_exception", "OOO", exc_type, exc_value == NULL ? Py_None : exc_value, exc_traceback == NULL ? Py_None : exc_traceback);
- PyObject *emptyString = PyString_FromString("");
- PyObject *strRetval = PyObject_CallMethod(emptyString, "join", "O", tbList);
-
- str = PyString_AsString(strRetval);
- if (str != NULL)
- exceptionTraceback = str;
-
- Py_DECREF(tbList);
- Py_DECREF(emptyString);
- Py_DECREF(strRetval);
+ char format_exception[] = "format_exception";
+ char zeros[] = "000";
+ PyObject *tbList = PyObject_CallMethod(tracebackModule, format_exception, zeros, exc_type, exc_value == NULL ? Py_None : exc_value, exc_traceback == NULL ? Py_None : exc_traceback);
+
+ if (tbList)
+ {
+ PyObject *emptyString = PyString_FromString("");
+ char join[] = "join";
+ char zero[] = "O";
+ PyObject *strRetval = PyObject_CallMethod(emptyString, join, zero, tbList);
+ Py_DECREF(emptyString);
+
+ if (strRetval)
+ {
+ str = PyString_AsString(strRetval);
+ if (str != NULL)
+ exceptionTraceback = str;
+ Py_DECREF(strRetval);
+ }
+ Py_DECREF(tbList);
+ }
Py_DECREF(tracebackModule);
+
}
}
diff --git a/xbmc/interfaces/swig/AddonModuleXbmc.i b/xbmc/interfaces/swig/AddonModuleXbmc.i
index 9628e2e57d..9d99351542 100644
--- a/xbmc/interfaces/swig/AddonModuleXbmc.i
+++ b/xbmc/interfaces/swig/AddonModuleXbmc.i
@@ -58,6 +58,7 @@ using namespace xbmc;
%include "interfaces/legacy/RenderCapture.h"
%include "interfaces/legacy/InfoTagMusic.h"
+%include "interfaces/legacy/InfoTagRadioRDS.h"
%include "interfaces/legacy/InfoTagVideo.h"
%include "interfaces/legacy/Keyboard.h"
%include "interfaces/legacy/PlayList.h"
diff --git a/xbmc/main/osx/SDLMain.h b/xbmc/main/osx/SDLMain.h
index 8771e6cf66..db186a5e6f 100644
--- a/xbmc/main/osx/SDLMain.h
+++ b/xbmc/main/osx/SDLMain.h
@@ -13,6 +13,6 @@
#import <Cocoa/Cocoa.h>
-@interface XBMCDelegate : NSObject
+@interface XBMCDelegate : NSObject<NSApplicationDelegate>
@end
#endif
diff --git a/xbmc/main/osx/SDLMain.mm b/xbmc/main/osx/SDLMain.mm
index 07ca86af28..2a9de1d910 100644
--- a/xbmc/main/osx/SDLMain.mm
+++ b/xbmc/main/osx/SDLMain.mm
@@ -589,7 +589,7 @@ int main(int argc, char *argv[])
// Create XBMCDelegate and make it the app delegate
xbmc_delegate = [[XBMCDelegate alloc] init];
- [NSApp setDelegate:xbmc_delegate];
+ [[NSApplication sharedApplication] setDelegate:xbmc_delegate];
// Start the main event loop
[NSApp run];
diff --git a/xbmc/messaging/ApplicationMessenger.cpp b/xbmc/messaging/ApplicationMessenger.cpp
index aede9babe7..91294b7179 100644
--- a/xbmc/messaging/ApplicationMessenger.cpp
+++ b/xbmc/messaging/ApplicationMessenger.cpp
@@ -24,6 +24,7 @@
#include "threads/SingleLock.h"
#include "guilib/GraphicContext.h"
+#include <memory>
namespace KODI
{
@@ -88,35 +89,41 @@ void CApplicationMessenger::Cleanup()
}
}
-void CApplicationMessenger::SendMsg(ThreadMessage&& message, bool wait)
+int CApplicationMessenger::SendMsg(ThreadMessage&& message, bool wait)
{
std::shared_ptr<CEvent> waitEvent;
+ std::shared_ptr<int> result;
+
if (wait)
- { // check that we're not being called from our application thread, else we'll be waiting
+ {
+ //Initialize result here as it's not needed for posted messages
+ message.result = std::make_shared<int>(-1);
+ // check that we're not being called from our application thread, else we'll be waiting
// forever!
if (!g_application.IsCurrentThread())
{
message.waitEvent.reset(new CEvent(true));
waitEvent = message.waitEvent;
+ result = message.result;
}
else
{
//OutputDebugString("Attempting to wait on a SendMessage() from our application thread will cause lockup!\n");
//OutputDebugString("Sending immediately\n");
ProcessMessage(&message);
- return;
+ return *message.result;
}
}
if (g_application.m_bStop)
- return;
+ return -1;
ThreadMessage* msg = new ThreadMessage(std::move(message));
CSingleLock lock (m_critSection);
- if (msg->dwMessage == TMSG_GUI_MESSAGE)
+ if (msg->dwMessage & TMSG_MASK_WINDOWMANAGER)
m_vecWindowMessages.push(msg);
else
m_vecMessages.push(msg);
@@ -132,27 +139,30 @@ void CApplicationMessenger::SendMsg(ThreadMessage&& message, bool wait)
// ensure the thread doesn't hold the graphics lock
CSingleExit exit(g_graphicsContext);
waitEvent->Wait();
+ return *result;
}
+
+ return -1;
}
-void CApplicationMessenger::SendMsg(uint32_t messageId)
+int CApplicationMessenger::SendMsg(uint32_t messageId)
{
- SendMsg(ThreadMessage{ messageId }, true);
+ return SendMsg(ThreadMessage{ messageId }, true);
}
-void CApplicationMessenger::SendMsg(uint32_t messageId, int param1, int param2, void* payload)
+int CApplicationMessenger::SendMsg(uint32_t messageId, int param1, int param2, void* payload)
{
- SendMsg(ThreadMessage{ messageId, param1, param2, payload }, true);
+ return SendMsg(ThreadMessage{ messageId, param1, param2, payload }, true);
}
-void CApplicationMessenger::SendMsg(uint32_t messageId, int param1, int param2, void* payload, std::string strParam)
+int CApplicationMessenger::SendMsg(uint32_t messageId, int param1, int param2, void* payload, std::string strParam)
{
- SendMsg(ThreadMessage{ messageId, param1, param2, payload, strParam, std::vector<std::string>{} }, true);
+ return SendMsg(ThreadMessage{ messageId, param1, param2, payload, strParam, std::vector<std::string>{} }, true);
}
-void CApplicationMessenger::SendMsg(uint32_t messageId, int param1, int param2, void* payload, std::string strParam, std::vector<std::string> params)
+int CApplicationMessenger::SendMsg(uint32_t messageId, int param1, int param2, void* payload, std::string strParam, std::vector<std::string> params)
{
- SendMsg(ThreadMessage{ messageId, param1, param2, payload, strParam, params }, true);
+ return SendMsg(ThreadMessage{ messageId, param1, param2, payload, strParam, params }, true);
}
void CApplicationMessenger::PostMsg(uint32_t messageId)
@@ -192,6 +202,7 @@ void CApplicationMessenger::ProcessMessages()
lock.Leave(); // <- see the large comment in SendMessage ^
ProcessMessage(pMsg);
+
if (waitEvent)
waitEvent->Set();
delete pMsg;
diff --git a/xbmc/messaging/ApplicationMessenger.h b/xbmc/messaging/ApplicationMessenger.h
index cb6e285d90..8a4a2a3ff3 100644
--- a/xbmc/messaging/ApplicationMessenger.h
+++ b/xbmc/messaging/ApplicationMessenger.h
@@ -113,6 +113,28 @@
#define TMSG_GUI_ADDON_DIALOG TMSG_MASK_WINDOWMANAGER + 6
#define TMSG_GUI_MESSAGE TMSG_MASK_WINDOWMANAGER + 7
+/*!
+ \def TMSG_GUI_DIALOG_YESNO
+ \brief Message sent through CApplicationMessenger to open a yes/no dialog box
+
+ There's two ways to send this message, a short and concise way and a more
+ flexible way allowing more customization.
+
+ Option 1:
+ CApplicationMessenger::Get().SendMsg(TMSG_GUI_DIALOG_YESNO, 123, 456);
+ 123: This is the string id for the heading
+ 456: This is the string id for the text
+
+ Option 2:
+ \a HELPERS::DialogYesNoMessage options.
+ Fill in options
+ CApplicationMessenger::Get().SendMsg(TMSG_GUI_DIALOG_YESNO, -1, -1, static_cast<void*>(&options));
+
+ \returns -1 for cancelled, 0 for No and 1 for Yes
+ \sa HELPERS::DialogYesNoMessage
+*/
+#define TMSG_GUI_DIALOG_YESNO TMSG_MASK_WINDOWMANAGER + 8
+
#define TMSG_CALLBACK 800
@@ -155,10 +177,10 @@ public:
void Cleanup();
// if a message has to be send to the gui, use MSG_TYPE_WINDOW instead
- void SendMsg(uint32_t messageId);
- void SendMsg(uint32_t messageId, int param1, int param2 = -1, void* payload = nullptr);
- void SendMsg(uint32_t messageId, int param1, int param2, void* payload, std::string strParam);
- void SendMsg(uint32_t messageId, int param1, int param2, void* payload, std::string strParam, std::vector<std::string> params);
+ int SendMsg(uint32_t messageId);
+ int SendMsg(uint32_t messageId, int param1, int param2 = -1, void* payload = nullptr);
+ int SendMsg(uint32_t messageId, int param1, int param2, void* payload, std::string strParam);
+ int SendMsg(uint32_t messageId, int param1, int param2, void* payload, std::string strParam, std::vector<std::string> params);
void PostMsg(uint32_t messageId);
void PostMsg(uint32_t messageId, int param1, int param2 = -1, void* payload = nullptr);
@@ -185,7 +207,7 @@ private:
CApplicationMessenger const& operator=(CApplicationMessenger const&) = delete;
~CApplicationMessenger();
- void SendMsg(ThreadMessage&& msg, bool wait);
+ int SendMsg(ThreadMessage&& msg, bool wait);
void ProcessMessage(ThreadMessage *pMsg);
std::queue<ThreadMessage*> m_vecMessages;
diff --git a/xbmc/messaging/ThreadMessage.h b/xbmc/messaging/ThreadMessage.h
index 997dfdff2e..8299f7fc32 100644
--- a/xbmc/messaging/ThreadMessage.h
+++ b/xbmc/messaging/ThreadMessage.h
@@ -71,7 +71,8 @@ public:
lpVoid(other.lpVoid),
strParam(other.strParam),
params(other.params),
- waitEvent(other.waitEvent)
+ waitEvent(other.waitEvent),
+ result(other.result)
{
}
@@ -82,7 +83,8 @@ public:
lpVoid(other.lpVoid),
strParam(std::move(other.strParam)),
params(std::move(other.params)),
- waitEvent(std::move(other.waitEvent))
+ waitEvent(std::move(other.waitEvent)),
+ result(std::move(other.result))
{
}
@@ -97,6 +99,7 @@ public:
strParam = other.strParam;
params = other.params;
waitEvent = other.waitEvent;
+ result = other.result;
return *this;
}
@@ -111,6 +114,7 @@ public:
strParam = std::move(other.strParam);
params = std::move(other.params);
waitEvent = std::move(other.waitEvent);
+ result = std::move(other.result);
return *this;
}
@@ -121,8 +125,17 @@ public:
std::string strParam;
std::vector<std::string> params;
+ void SetResult(int res)
+ {
+ //On posted messages result will be zero, since they can't
+ //retreive the response we silently ignore this to let message
+ //handlers not have to worry about it
+ if (result)
+ *result = res;
+ }
protected:
std::shared_ptr<CEvent> waitEvent;
+ std::shared_ptr<int> result;
};
}
}
diff --git a/xbmc/messaging/helpers/DialogHelper.cpp b/xbmc/messaging/helpers/DialogHelper.cpp
new file mode 100644
index 0000000000..2b2583ebcd
--- /dev/null
+++ b/xbmc/messaging/helpers/DialogHelper.cpp
@@ -0,0 +1,89 @@
+/*
+* Copyright (C) 2005-2015 Team Kodi
+* http://kodi.tv
+*
+* This Program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2, or (at your option)
+* any later version.
+*
+* This Program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Kodi; see the file COPYING. If not, see
+* <http://www.gnu.org/licenses/>.
+*
+*/
+
+#include "DialogHelper.h"
+#include "messaging/ApplicationMessenger.h"
+
+#include <utility>
+#include <cassert>
+
+namespace KODI
+{
+namespace MESSAGING
+{
+namespace HELPERS
+{
+DialogResponse ShowYesNoDialogText(CVariant heading, CVariant text, CVariant noLabel, CVariant yesLabel, uint32_t autoCloseTimeout)
+{
+ DialogYesNoMessage options;
+ options.heading = std::move(heading);
+ options.text = std::move(text);
+ options.noLabel = std::move(noLabel);
+ options.yesLabel = std::move(yesLabel);
+ options.autoclose = autoCloseTimeout;
+
+ switch (CApplicationMessenger::GetInstance().SendMsg(TMSG_GUI_DIALOG_YESNO, -1, -1, static_cast<void*>(&options)))
+ {
+ case -1:
+ return DialogResponse::CANCELLED;
+ case 0:
+ return DialogResponse::NO;
+ case 1:
+ return DialogResponse::YES;
+ default:
+ //If we get here someone changed the return values without updating this code
+ assert(false);
+ }
+ //This is unreachable code but we need to return something to suppress warnings about
+ //no return
+ return DialogResponse::CANCELLED;
+}
+
+DialogResponse ShowYesNoDialogLines(CVariant heading, CVariant line0, CVariant line1, CVariant line2, CVariant noLabel, CVariant yesLabel, uint32_t autoCloseTimeout)
+{
+ DialogYesNoMessage options;
+ options.heading = std::move(heading);
+ options.lines[0] = std::move(line0);
+ options.lines[1] = std::move(line1);
+ options.lines[2] = std::move(line2);
+ options.noLabel = std::move(noLabel);
+ options.yesLabel = std::move(yesLabel);
+ options.autoclose = autoCloseTimeout;
+
+ switch (CApplicationMessenger::GetInstance().SendMsg(TMSG_GUI_DIALOG_YESNO, -1, -1, static_cast<void*>(&options)))
+ {
+ case -1:
+ return DialogResponse::CANCELLED;
+ case 0:
+ return DialogResponse::NO;
+ case 1:
+ return DialogResponse::YES;
+ default:
+ //If we get here someone changed the return values without updating this code
+ assert(false);
+ }
+ //This is unreachable code but we need to return something to suppress warnings about
+ //no return
+ return DialogResponse::CANCELLED;
+}
+
+}
+}
+} \ No newline at end of file
diff --git a/xbmc/messaging/helpers/DialogHelper.h b/xbmc/messaging/helpers/DialogHelper.h
new file mode 100644
index 0000000000..5f2f491964
--- /dev/null
+++ b/xbmc/messaging/helpers/DialogHelper.h
@@ -0,0 +1,98 @@
+#pragma once
+/*
+* Copyright (C) 2005-2015 Team Kodi
+* http://kodi.tv
+*
+* This Program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2, or (at your option)
+* any later version.
+*
+* This Program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Kodi; see the file COPYING. If not, see
+* <http://www.gnu.org/licenses/>.
+*
+*/
+
+#include "utils/Variant.h"
+
+#include <array>
+#include <string>
+
+namespace KODI
+{
+namespace MESSAGING
+{
+namespace HELPERS
+{
+
+enum class DialogResponse
+{
+ CANCELLED,
+ YES,
+ NO
+};
+
+/*! \struct DialogHelper.h "messaging/helpers/DialogHelper.h"
+ \brief Payload sent for message TMSG_GUI_DIALOG_YESNO
+
+ \sa ShowDialogText
+ \sa ShowDialogLines
+*/
+struct DialogYesNoMessage
+{
+ CVariant heading; //!< Heading to be displayed in the dialog box
+ CVariant text; //!< Body text to be displayed, this is mutually exclusive with lines below
+ std::array<CVariant, 3> lines; //!< Body text to be displayed, specified as three lines. This is mutually exclusive with the text above
+ CVariant yesLabel; //!< Text to show on the yes button
+ CVariant noLabel; //!< Text to show on the no button
+ uint32_t autoclose{0}; //!< Time in milliseconds before autoclosing the dialog, 0 means don't autoclose
+};
+
+/*!
+ \brief This is a helper method to send a threadmessage to open a Yes/No dialog box
+
+ \param[in] heading The text to display as the dialog box header
+ \param[in] text The text to display in the dialog body
+ \param[in] noLabel The text to display on the No button
+ defaults to No
+ \param[in] yesLabel The text to display on the Yes button
+ defaults to Yes
+ \param[in] autoCloseTimeout The time before the dialog closes
+ defaults to 0 show indefinitely
+ \return -1 on cancelled, 0 on no and 1 on yes
+ \sa ShowYesNoDialogLines
+ \sa CGUIDialogYesNo::ShowAndGetInput
+ \sa DialogYesNoMessage
+*/
+DialogResponse ShowYesNoDialogText(CVariant heading, CVariant text, CVariant noLabel = "", CVariant yesLabel = "", uint32_t autoCloseTimeout = 0);
+
+/*!
+ \brief This is a helper method to send a threadmessage to open a Yes/No dialog box
+
+ \param[in] heading The text to display as the dialog box header
+ \param[in] line0 The text to display on the first line
+ \param[in] line1 The text to display on the second line
+ \param[in] line2 The text to display on the third line
+ \param[in] noLabel The text to display on the No button
+ defaults to No
+ \param[in] yesLabel The text to display on the Yes button
+ defaults to Yes
+ \param[in] autoCloseTimeout The time before the dialog closes
+ defaults to 0 show indefinitely
+ \return -1 on cancelled, 0 on no and 1 on yes
+ \sa ShowYesNoDialogText
+ \sa CGUIDialogYesNo::ShowAndGetInput
+ \sa DialogYesNoMessage
+*/
+DialogResponse ShowYesNoDialogLines(CVariant heading, CVariant line0, CVariant line1 = "",
+ CVariant line2 = "", CVariant noLabel = "", CVariant yesLabel = "", uint32_t autoCloseTimeout = 0);
+
+}
+}
+} \ No newline at end of file
diff --git a/xbmc/messaging/helpers/Makefile.in b/xbmc/messaging/helpers/Makefile.in
new file mode 100644
index 0000000000..e3194029e5
--- /dev/null
+++ b/xbmc/messaging/helpers/Makefile.in
@@ -0,0 +1,6 @@
+SRCS = DialogHelper.cpp
+
+LIB = messagingHelpers.a
+
+include @abs_top_srcdir@/Makefile.include
+-include $(patsubst %.cpp,%.P,$(patsubst %c,%.P,$(patsubst %.S,,$(SRCS))))
diff --git a/xbmc/music/GUIViewStateMusic.cpp b/xbmc/music/GUIViewStateMusic.cpp
index 7c2b91bd79..d903ef9f7e 100644
--- a/xbmc/music/GUIViewStateMusic.cpp
+++ b/xbmc/music/GUIViewStateMusic.cpp
@@ -356,6 +356,8 @@ CGUIViewStateMusicSmartPlaylist::CGUIViewStateMusicSmartPlaylist(const CFileItem
if (CSettings::GetInstance().GetBool(CSettings::SETTING_FILELISTS_IGNORETHEWHENSORTING))
sortAttribute = SortAttributeIgnoreArticle;
+ const CViewState *viewState = CViewStateSettings::GetInstance().Get("musicnavsongs");
+
if (items.GetContent() == "songs" || items.GetContent() == "mixed")
{
std::string strTrackLeft=CSettings::GetInstance().GetString(CSettings::SETTING_MUSICFILES_TRACKFORMAT);
@@ -369,7 +371,14 @@ CGUIViewStateMusicSmartPlaylist::CGUIViewStateMusicSmartPlaylist(const CFileItem
AddSortMethod(SortByLabel, sortAttribute, 551, LABEL_MASKS(strTrackLeft, strTrackRight));
AddSortMethod(SortByTime, 180, LABEL_MASKS("%T - %A", "%D")); // Titel, Artist, Duration| empty, empty
AddSortMethod(SortByRating, 563, LABEL_MASKS("%T - %A", "%R")); // Titel, Artist, Rating| empty, empty
- AddPlaylistOrder(items, LABEL_MASKS(strTrackLeft, strTrackRight));
+
+ if (items.IsSmartPlayList() || items.IsLibraryFolder())
+ AddPlaylistOrder(items, LABEL_MASKS(strTrackLeft, strTrackRight));
+ else
+ {
+ SetSortMethod(viewState->m_sortDescription);
+ SetSortOrder(viewState->m_sortDescription.sortOrder);
+ }
SetViewAsControl(CViewStateSettings::GetInstance().Get("musicnavsongs")->m_viewMode);
}
@@ -391,7 +400,13 @@ CGUIViewStateMusicSmartPlaylist::CGUIViewStateMusicSmartPlaylist(const CFileItem
// year
AddSortMethod(SortByYear, 562, LABEL_MASKS("%F", "", strAlbumLeft, strAlbumRight));
- AddPlaylistOrder(items, LABEL_MASKS("%F", "", strAlbumLeft, strAlbumRight));
+ if (items.IsSmartPlayList() || items.IsLibraryFolder())
+ AddPlaylistOrder(items, LABEL_MASKS("%F", "", strAlbumLeft, strAlbumRight));
+ else
+ {
+ SetSortMethod(viewState->m_sortDescription);
+ SetSortOrder(viewState->m_sortDescription.sortOrder);
+ }
SetViewAsControl(CViewStateSettings::GetInstance().Get("musicnavalbums")->m_viewMode);
}
diff --git a/xbmc/music/MusicDatabase.cpp b/xbmc/music/MusicDatabase.cpp
index 292873bc7f..4e2d9b505c 100644
--- a/xbmc/music/MusicDatabase.cpp
+++ b/xbmc/music/MusicDatabase.cpp
@@ -38,7 +38,6 @@
#include "guilib/GUIWindowManager.h"
#include "dialogs/GUIDialogOK.h"
#include "dialogs/GUIDialogProgress.h"
-#include "dialogs/GUIDialogYesNo.h"
#include "dialogs/GUIDialogKaiToast.h"
#include "dialogs/GUIDialogSelect.h"
#include "filesystem/File.h"
@@ -67,13 +66,17 @@
#include "playlists/SmartPlayList.h"
#include "CueInfoLoader.h"
#include "guiinfo/GUIInfoLabels.h"
+#include "messaging/helpers/DialogHelper.h"
#include <utility>
using namespace AUTOPTR;
using namespace XFILE;
using namespace MUSICDATABASEDIRECTORY;
+using namespace KODI::MESSAGING;
+
using ADDON::AddonPtr;
+using KODI::MESSAGING::HELPERS::DialogResponse;
#define RECENTLY_PLAYED_LIMIT 25
#define MIN_FULL_SEARCH_LENGTH 3
@@ -2975,8 +2978,8 @@ void CMusicDatabase::Clean()
CGUIDialogOK::ShowAndGetInput(CVariant{189}, CVariant{14057});
return;
}
-
- if (CGUIDialogYesNo::ShowAndGetInput(CVariant{313}, CVariant{333}))
+
+ if (HELPERS::ShowYesNoDialogText(CVariant{313}, CVariant{333}) == DialogResponse::YES)
{
CMusicDatabase musicdatabase;
if (musicdatabase.Open())
@@ -5597,10 +5600,7 @@ bool CMusicDatabase::GetFilter(CDbUrl &musicUrl, Filter &filter, SortDescription
" OR artistview.idArtist IN ";
// and always show any artists linked to an album (may be different from above due to album artist tag)
- strSQL += "(SELECT album_artist.idArtist FROM album_artist"; // All artists linked to an album
- if (albumArtistsOnly)
- strSQL += " JOIN album ON album.idAlbum = album_artist.idAlbum WHERE album.bCompilation = 0 "; // then exclude those that have no extra artists
- strSQL += ")";
+ strSQL += "(SELECT album_artist.idArtist FROM album_artist)"; // Includes compliation albums hence "Various artists"
}
// remove the null string
diff --git a/xbmc/music/dialogs/GUIDialogMusicOSD.cpp b/xbmc/music/dialogs/GUIDialogMusicOSD.cpp
index 8c4c76c5f5..36c10b7a6d 100644
--- a/xbmc/music/dialogs/GUIDialogMusicOSD.cpp
+++ b/xbmc/music/dialogs/GUIDialogMusicOSD.cpp
@@ -91,7 +91,8 @@ void CGUIDialogMusicOSD::FrameMove()
if (CInputManager::GetInstance().IsMouseActive() ||
g_windowManager.IsWindowActive(WINDOW_DIALOG_VIS_SETTINGS) ||
g_windowManager.IsWindowActive(WINDOW_DIALOG_VIS_PRESET_LIST) ||
- g_windowManager.IsWindowActive(WINDOW_DIALOG_AUDIO_DSP_OSD_SETTINGS))
+ g_windowManager.IsWindowActive(WINDOW_DIALOG_AUDIO_DSP_OSD_SETTINGS) ||
+ g_windowManager.IsWindowActive(WINDOW_DIALOG_PVR_RADIO_RDS_INFO))
// extend show time by original value
SetAutoClose(m_showDuration);
}
diff --git a/xbmc/music/tags/MusicInfoTag.cpp b/xbmc/music/tags/MusicInfoTag.cpp
index 06a8dd73af..113ec153d0 100644
--- a/xbmc/music/tags/MusicInfoTag.cpp
+++ b/xbmc/music/tags/MusicInfoTag.cpp
@@ -581,11 +581,13 @@ void CMusicInfoTag::SetArtist(const CArtist& artist)
{
SetArtist(artist.strArtist);
SetAlbumArtist(artist.strArtist);
+ SetMusicBrainzArtistID({ artist.strMusicBrainzArtistID });
SetGenre(artist.genre);
- m_dateAdded = artist.dateAdded;
- m_iDbId = artist.idArtist;
- m_type = MediaTypeArtist;
- m_bLoaded = true;
+ SetMood(StringUtils::Join(artist.moods, g_advancedSettings.m_musicItemSeparator));
+ SetDateAdded(artist.dateAdded);
+ SetDatabaseId(artist.idArtist, MediaTypeArtist);
+
+ SetLoaded();
}
void CMusicInfoTag::SetAlbum(const CAlbum& album)
@@ -595,18 +597,21 @@ void CMusicInfoTag::SetAlbum(const CAlbum& album)
SetAlbum(album.strAlbum);
SetTitle(album.strAlbum);
SetAlbumArtist(album.artist);
+ SetMusicBrainzAlbumID(album.strMusicBrainzAlbumID);
SetGenre(album.genre);
+ SetMood(StringUtils::Join(album.moods, g_advancedSettings.m_musicItemSeparator));
SetRating('0' + album.iRating);
SetCompilation(album.bCompilation);
SYSTEMTIME stTime;
stTime.wYear = album.iYear;
SetReleaseDate(stTime);
SetAlbumReleaseType(album.releaseType);
- m_dateAdded = album.dateAdded;
- m_iTimesPlayed = album.iTimesPlayed;
- m_iDbId = album.idAlbum;
- m_type = MediaTypeAlbum;
- m_bLoaded = true;
+ SetDateAdded(album.dateAdded);
+ SetPlayCount(album.iTimesPlayed);
+ SetCompilation(album.bCompilation);
+ SetDatabaseId(album.idAlbum, MediaTypeAlbum);
+
+ SetLoaded();
}
void CMusicInfoTag::SetSong(const CSong& song)
@@ -623,23 +628,25 @@ void CMusicInfoTag::SetSong(const CSong& song)
SetLastPlayed(song.lastPlayed);
SetDateAdded(song.dateAdded);
SetCoverArtInfo(song.embeddedArt.size, song.embeddedArt.mime);
- m_rating = song.rating;
- m_strURL = song.strFileName;
+ SetRating(song.rating);
+ SetURL(song.strFileName);
SYSTEMTIME stTime;
stTime.wYear = song.iYear;
SetReleaseDate(stTime);
- m_iTrack = song.iTrack;
- m_iDuration = song.iDuration;
- m_iDbId = song.idSong;
- m_type = MediaTypeSong;
- m_bLoaded = true;
- m_iTimesPlayed = song.iTimesPlayed;
- m_iAlbumId = song.idAlbum;
+ SetTrackNumber(song.iTrack);
+ SetDuration(song.iDuration);
+ SetPlayCount(song.iTimesPlayed);
+ SetMood(song.strMood);
+ SetCompilation(song.bCompilation);
+ SetAlbumId(song.idAlbum);
+ SetDatabaseId(song.idSong, MediaTypeSong);
if (song.replayGain.Get(ReplayGain::TRACK).Valid())
m_replayGain.Set(ReplayGain::TRACK, song.replayGain.Get(ReplayGain::TRACK));
if (song.replayGain.Get(ReplayGain::ALBUM).Valid())
m_replayGain.Set(ReplayGain::ALBUM, song.replayGain.Get(ReplayGain::ALBUM));
+
+ SetLoaded();
}
void CMusicInfoTag::Serialize(CVariant& value) const
diff --git a/xbmc/network/NetworkServices.cpp b/xbmc/network/NetworkServices.cpp
index 0a8b9bceff..67474c4172 100644
--- a/xbmc/network/NetworkServices.cpp
+++ b/xbmc/network/NetworkServices.cpp
@@ -21,12 +21,12 @@
#include "NetworkServices.h"
#include "Application.h"
#include "messaging/ApplicationMessenger.h"
+#include "messaging/helpers/DialogHelper.h"
#ifdef TARGET_LINUX
#include "Util.h"
#endif
#include "dialogs/GUIDialogKaiToast.h"
#include "dialogs/GUIDialogOK.h"
-#include "dialogs/GUIDialogYesNo.h"
#include "guilib/LocalizeStrings.h"
#include "network/Network.h"
@@ -95,6 +95,8 @@ using namespace EVENTSERVER;
using namespace UPNP;
#endif // HAS_UPNP
+using KODI::MESSAGING::HELPERS::DialogResponse;
+
CNetworkServices::CNetworkServices()
#ifdef HAS_WEB_SERVER
:
@@ -413,7 +415,7 @@ void CNetworkServices::OnSettingChanged(const CSetting *setting)
{
// okey we really don't need to restart, only deinit samba, but that could be damn hard if something is playing
// TODO - General way of handling setting changes that require restart
- if (CGUIDialogYesNo::ShowAndGetInput(CVariant{14038}, CVariant{14039}))
+ if (HELPERS::ShowYesNoDialogText(CVariant{14038}, CVariant{14039}) == DialogResponse::YES)
{
CSettings::GetInstance().Save();
CApplicationMessenger::GetInstance().PostMsg(TMSG_RESTARTAPP);
@@ -755,9 +757,8 @@ bool CNetworkServices::StopEventServer(bool bWait, bool promptuser)
{
if (server->GetNumberOfClients() > 0)
{
- bool cancelled = false;
- if (!CGUIDialogYesNo::ShowAndGetInput(CVariant{13140}, CVariant{13141}, cancelled, CVariant{""}, CVariant{""}, 10000)
- || cancelled)
+ if (HELPERS::ShowYesNoDialogText(CVariant{13140}, CVariant{13141}, CVariant{""}, CVariant{""}, 10000) !=
+ DialogResponse::YES)
{
CLog::Log(LOGNOTICE, "ES: Not stopping event server");
return false;
diff --git a/xbmc/network/WakeOnAccess.cpp b/xbmc/network/WakeOnAccess.cpp
index 316e411e65..44c7ced4e8 100644
--- a/xbmc/network/WakeOnAccess.cpp
+++ b/xbmc/network/WakeOnAccess.cpp
@@ -170,12 +170,6 @@ public:
m_dialog->SetLine(0, CVariant{""});
m_dialog->SetLine(1, CVariant{""});
m_dialog->SetLine(2, CVariant{""});
-
- int nest_level = NestDetect::Level();
- if (nest_level > 1)
- {
- m_dialog->SetLine(2, CVariant{StringUtils::Format("Nesting:%d", nest_level)});
- }
}
}
~ProgressDialogHelper ()
@@ -194,7 +188,7 @@ public:
if (m_dialog)
{
- m_dialog->SetLine(1, CVariant{line1});
+ m_dialog->SetLine(0, CVariant{line1});
m_dialog->SetPercentage(1); // avoid flickering by starting at 1% ..
}
diff --git a/xbmc/network/cddb.cpp b/xbmc/network/cddb.cpp
index 3c8ae1d764..4515dea3d0 100644
--- a/xbmc/network/cddb.cpp
+++ b/xbmc/network/cddb.cpp
@@ -42,12 +42,12 @@
#include "utils/log.h"
#include "utils/SystemInfo.h"
+#include <memory>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
using namespace MEDIA_DETECT;
-using namespace AUTOPTR;
using namespace CDDB;
//-------------------------------------------------------------------------------------------------------------------
@@ -133,7 +133,7 @@ bool Xcddb::closeSocket()
//-------------------------------------------------------------------------------------------------------------------
bool Xcddb::Send( const void *buffer, int bytes )
{
- auto_aptr<char> tmp_buffer (new char[bytes + 10]);
+ std::unique_ptr<char[]> tmp_buffer(new char[bytes + 10]);
strcpy(tmp_buffer.get(), (const char*)buffer);
tmp_buffer.get()[bytes] = '.';
tmp_buffer.get()[bytes + 1] = 0x0d;
diff --git a/xbmc/network/upnp/UPnPPlayer.cpp b/xbmc/network/upnp/UPnPPlayer.cpp
index 92d9e4c9c8..760e250a24 100644
--- a/xbmc/network/upnp/UPnPPlayer.cpp
+++ b/xbmc/network/upnp/UPnPPlayer.cpp
@@ -35,14 +35,16 @@
#include "video/VideoThumbLoader.h"
#include "music/MusicThumbLoader.h"
#include "messaging/ApplicationMessenger.h"
+#include "messaging/helpers/DialogHelper.h"
#include "Application.h"
#include "dialogs/GUIDialogBusy.h"
#include "guilib/GUIWindowManager.h"
#include "input/Key.h"
-#include "dialogs/GUIDialogYesNo.h"
using namespace KODI::MESSAGING;
+using KODI::MESSAGING::HELPERS::DialogResponse;
+
NPT_SET_LOCAL_LOGGER("xbmc.upnp.player")
namespace UPNP
@@ -605,10 +607,9 @@ bool CUPnPPlayer::OnAction(const CAction &action)
case ACTION_STOP:
if(IsPlaying())
{
- if(CGUIDialogYesNo::ShowAndGetInput(CVariant{37022}, CVariant{37023})) /* stop on remote system */
- m_stopremote = true;
- else
- m_stopremote = false;
+ //stop on remote system
+ m_stopremote = HELPERS::ShowYesNoDialogText(CVariant{37022}, CVariant{37023}) == DialogResponse::YES;
+
return false; /* let normal code handle the action */
}
default:
diff --git a/xbmc/osx/CocoaInterface.h b/xbmc/osx/CocoaInterface.h
index e7953fccff..ea19edc3cd 100644
--- a/xbmc/osx/CocoaInterface.h
+++ b/xbmc/osx/CocoaInterface.h
@@ -57,13 +57,8 @@ extern "C"
// Version.
//
bool Cocoa_GPUForDisplayIsNvidiaPureVideo3();
- int Cocoa_GetOSVersion();
-
- void Cocoa_MakeChildWindow();
- void Cocoa_DestroyChildWindow();
-
- const char *Cocoa_Paste() ;
+ const char *Cocoa_Paste() ;
#ifdef __cplusplus
}
diff --git a/xbmc/osx/CocoaInterface.mm b/xbmc/osx/CocoaInterface.mm
index 252d9d385e..ed6cf5d23f 100644
--- a/xbmc/osx/CocoaInterface.mm
+++ b/xbmc/osx/CocoaInterface.mm
@@ -41,9 +41,6 @@
#import "AutoPool.h"
-// hack for Cocoa_GL_ResizeWindow
-//extern "C" void SDL_SetWidthHeight(int w, int h);
-
//#define MAX_DISPLAYS 32
//static NSWindow* blankingWindows[MAX_DISPLAYS];
@@ -246,7 +243,6 @@ const char* Cocoa_GetIconFromBundle(const char *_bundlePath, const char* _iconNa
NSBitmapImageRep* rep = [[NSBitmapImageRep alloc] initWithData:[icon TIFFRepresentation]];
NSData* png = [rep representationUsingType:NSPNGFileType properties:nil];
[png writeToFile:pngFile atomically:YES];
- [png release];
[rep release];
[icon release];
}
@@ -404,50 +400,7 @@ bool Cocoa_GPUForDisplayIsNvidiaPureVideo3()
return(result);
}
-int Cocoa_GetOSVersion()
-{
- static SInt32 version = -1;
-
- if (version == -1)
- Gestalt(gestaltSystemVersion, &version);
-
- return(version);
-}
-
-
-NSWindow* childWindow = nil;
-NSWindow* mainWindow = nil;
-
-
-void Cocoa_MakeChildWindow()
-{
- NSOpenGLContext* context = Cocoa_GL_GetCurrentContext();
- NSView* view = [context view];
- NSWindow* window = [view window];
-
- // Create a child window.
- childWindow = [[NSWindow alloc] initWithContentRect:[window frame]
- styleMask:NSBorderlessWindowMask
- backing:NSBackingStoreBuffered
- defer:NO];
-
- [childWindow setContentSize:[view frame].size];
- [childWindow setBackgroundColor:[NSColor blackColor]];
- [window addChildWindow:childWindow ordered:NSWindowAbove];
- mainWindow = window;
- //childWindow.alphaValue = 0.5;
-}
-
-void Cocoa_DestroyChildWindow()
-{
- if (childWindow != nil)
- {
- [mainWindow removeChildWindow:childWindow];
- [childWindow close];
- childWindow = nil;
- }
-}
-const char *Cocoa_Paste()
+const char *Cocoa_Paste()
{
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
NSString *type = [pasteboard availableTypeFromArray:[NSArray arrayWithObject:NSStringPboardType]];
diff --git a/xbmc/osx/DarwinUtils.mm b/xbmc/osx/DarwinUtils.mm
index 75ece9f8b5..8d836dcf77 100644
--- a/xbmc/osx/DarwinUtils.mm
+++ b/xbmc/osx/DarwinUtils.mm
@@ -537,6 +537,8 @@ int CDarwinUtils::BatteryLevel(void)
batteryLevel = (double)curLevel/(double)maxLevel;
}
+ CFRelease(powerSources);
+ CFRelease(powerSourceInfo);
#endif
return batteryLevel * 100;
}
@@ -547,7 +549,7 @@ void CDarwinUtils::SetScheduling(int message)
struct sched_param param;
pthread_t this_pthread_self = pthread_self();
- int32_t result = pthread_getschedparam(this_pthread_self, &policy, &param );
+ pthread_getschedparam(this_pthread_self, &policy, &param );
policy = SCHED_OTHER;
thread_extended_policy_data_t theFixedPolicy={true};
@@ -558,12 +560,12 @@ void CDarwinUtils::SetScheduling(int message)
theFixedPolicy.timeshare = false;
}
- result = thread_policy_set(pthread_mach_thread_np(this_pthread_self),
+ thread_policy_set(pthread_mach_thread_np(this_pthread_self),
THREAD_EXTENDED_POLICY,
(thread_policy_t)&theFixedPolicy,
THREAD_EXTENDED_POLICY_COUNT);
- result = pthread_setschedparam(this_pthread_self, policy, &param );
+ pthread_setschedparam(this_pthread_self, policy, &param );
}
bool CFStringRefToStringWithEncoding(CFStringRef source, std::string &destination, CFStringEncoding encoding)
diff --git a/xbmc/osx/OSXTextInputResponder.mm b/xbmc/osx/OSXTextInputResponder.mm
index 60ef2a2a00..baa0938499 100644
--- a/xbmc/osx/OSXTextInputResponder.mm
+++ b/xbmc/osx/OSXTextInputResponder.mm
@@ -177,7 +177,7 @@ void SendEditingText(const char *text, unsigned int location, unsigned int lengt
// CLog::Log(LOGDEBUG, "firstRectForCharacterRange: (%lu, %lu): windowHeight = %g, rect = %s",
// theRange.location, theRange.length, windowHeight,
// [NSStringFromRect(rect) UTF8String]);
- rect.origin = [[self window] convertBaseToScreen: rect.origin];
+ rect.origin = [[self window] convertRectToScreen:rect].origin;
return rect;
}
diff --git a/xbmc/pvr/PVRManager.cpp b/xbmc/pvr/PVRManager.cpp
index 531b75b641..dbb360873e 100644
--- a/xbmc/pvr/PVRManager.cpp
+++ b/xbmc/pvr/PVRManager.cpp
@@ -20,6 +20,7 @@
#include "Application.h"
#include "messaging/ApplicationMessenger.h"
+#include "messaging/helpers/DialogHelper.h"
#include "GUIInfoManager.h"
#include "Util.h"
#include "dialogs/GUIDialogOK.h"
@@ -27,7 +28,6 @@
#include "dialogs/GUIDialogProgress.h"
#include "dialogs/GUIDialogExtendedProgressBar.h"
#include "dialogs/GUIDialogKaiToast.h"
-#include "dialogs/GUIDialogYesNo.h"
#include "guilib/GUIWindowManager.h"
#include "guilib/LocalizeStrings.h"
#include "music/tags/MusicInfoTag.h"
@@ -68,6 +68,8 @@ using namespace EPG;
using namespace ANNOUNCEMENT;
using namespace KODI::MESSAGING;
+using KODI::MESSAGING::HELPERS::DialogResponse;
+
int CPVRManager::m_pvrWindowIds[10] = {
WINDOW_TV_CHANNELS,
WINDOW_TV_GUIDE,
@@ -184,7 +186,7 @@ void CPVRManager::OnSettingAction(const CSetting *setting)
else if (settingId == CSettings::SETTING_PVRMANAGER_RESETDB)
{
if (CheckParentalPIN(g_localizeStrings.Get(19262)) &&
- CGUIDialogYesNo::ShowAndGetInput(CVariant{19098}, CVariant{19186}))
+ HELPERS::ShowYesNoDialogText(CVariant{19098}, CVariant{19186}) == DialogResponse::YES)
{
CDateTime::ResetTimezoneBias();
ResetDatabase(false);
@@ -192,7 +194,7 @@ void CPVRManager::OnSettingAction(const CSetting *setting)
}
else if (settingId == CSettings::SETTING_EPG_RESETEPG)
{
- if (CGUIDialogYesNo::ShowAndGetInput(CVariant{19098}, CVariant{19188}))
+ if (HELPERS::ShowYesNoDialogText(CVariant{19098}, CVariant{19188}) == DialogResponse::YES)
{
CDateTime::ResetTimezoneBias();
ResetDatabase(true);
@@ -271,12 +273,12 @@ bool CPVRManager::InstallAddonAllowed(const std::string& strAddonId) const
(!IsPVRWindowActive() && !IsPlaying());
}
-void CPVRManager::MarkAsOutdated(const std::string& strAddonId, const std::string& strReferer)
+void CPVRManager::MarkAsOutdated(const std::string& strAddonId)
{
if (IsStarted() && CSettings::GetInstance().GetInt(CSettings::SETTING_GENERAL_ADDONUPDATES) == AUTO_UPDATES_ON)
{
CSingleLock lock(m_critSection);
- m_outdatedAddons.insert(make_pair(strAddonId, strReferer));
+ m_outdatedAddons.push_back(strAddonId);
}
}
@@ -287,9 +289,9 @@ bool CPVRManager::UpgradeOutdatedAddons(void)
return true;
// there's add-ons that couldn't be updated
- for (std::map<std::string, std::string>::iterator it = m_outdatedAddons.begin(); it != m_outdatedAddons.end(); ++it)
+ for (auto it = m_outdatedAddons.begin(); it != m_outdatedAddons.end(); ++it)
{
- if (!InstallAddonAllowed(it->first))
+ if (!InstallAddonAllowed(*it))
{
// we can't upgrade right now
return true;
@@ -299,7 +301,7 @@ bool CPVRManager::UpgradeOutdatedAddons(void)
// all outdated add-ons can be upgraded now
CLog::Log(LOGINFO, "PVR - upgrading outdated add-ons");
- std::map<std::string, std::string> outdatedAddons = m_outdatedAddons;
+ auto outdatedAddons = m_outdatedAddons;
// stop threads and unload
SetState(ManagerStateInterrupted);
g_EpgContainer.Stop();
@@ -308,10 +310,10 @@ bool CPVRManager::UpgradeOutdatedAddons(void)
Cleanup();
// upgrade all add-ons
- for (std::map<std::string, std::string>::iterator it = outdatedAddons.begin(); it != outdatedAddons.end(); ++it)
+ for (auto it = outdatedAddons.begin(); it != outdatedAddons.end(); ++it)
{
- CLog::Log(LOGINFO, "PVR - updating add-on '%s'", it->first.c_str());
- CAddonInstaller::GetInstance().Install(it->first, true, it->second, false);
+ CLog::Log(LOGINFO, "PVR - updating add-on '%s'", (*it).c_str());
+ CAddonInstaller::GetInstance().InstallOrUpdate(*it, false);
}
// reload
@@ -1506,13 +1508,12 @@ bool CPVRManager::CanSystemPowerdown(bool bAskUser /*= true*/) const
}
// Inform user about PVR being busy. Ask if user wants to powerdown anyway.
- bool bCanceled = false;
- bReturn = CGUIDialogYesNo::ShowAndGetInput(CVariant{19685}, // "Confirm shutdown"
- CVariant{text},
- bCanceled,
- CVariant{222}, // "Cancel"
- CVariant{19696}, // "Shutdown anyway"
- 10000); //This is a timeout and IS NOT a CVariant
+ bReturn = HELPERS::DialogResponse::YES ==
+ HELPERS::ShowYesNoDialogText(CVariant{19685}, // "Confirm shutdown"
+ CVariant{text},
+ CVariant{222}, // "Shutdown anyway",
+ CVariant{19696}, // "Cancel"
+ 10000); // timeout value before closing
}
else
bReturn = false; // do not powerdown (busy, but no user interaction requested).
diff --git a/xbmc/pvr/PVRManager.h b/xbmc/pvr/PVRManager.h
index 4f7ea2826a..47f22bcbf0 100644
--- a/xbmc/pvr/PVRManager.h
+++ b/xbmc/pvr/PVRManager.h
@@ -182,9 +182,8 @@ namespace PVR
/*!
* @brief Mark an add-on as outdated so it will be upgrade when it's possible again
* @param strAddonId The add-on to mark as outdated
- * @param strReferer The referer to use when downloading
*/
- void MarkAsOutdated(const std::string& strAddonId, const std::string& strReferer);
+ void MarkAsOutdated(const std::string& strAddonId);
/*!
* @return True when updated, false when the pvr manager failed to load after the attempt
@@ -679,7 +678,7 @@ namespace PVR
CCriticalSection m_managerStateMutex;
ManagerState m_managerState;
CStopWatch *m_parentalTimer;
- std::map<std::string, std::string> m_outdatedAddons;
+ std::vector<std::string> m_outdatedAddons;
static int m_pvrWindowIds[10];
};
diff --git a/xbmc/pvr/addons/PVRClient.cpp b/xbmc/pvr/addons/PVRClient.cpp
index df7331dac5..869f4062f7 100644
--- a/xbmc/pvr/addons/PVRClient.cpp
+++ b/xbmc/pvr/addons/PVRClient.cpp
@@ -20,7 +20,8 @@
#include "Application.h"
#include "PVRClient.h"
-#include "dialogs/GUIDialogYesNo.h"
+#include "messaging/ApplicationMessenger.h"
+#include "messaging/helpers/DialogHelper.h"
#include "pvr/PVRManager.h"
#include "pvr/addons/PVRClients.h"
#include "epg/Epg.h"
@@ -37,10 +38,14 @@
#include <assert.h>
#include <memory>
+#include <algorithm>
using namespace ADDON;
using namespace PVR;
using namespace EPG;
+using namespace KODI::MESSAGING;
+
+using KODI::MESSAGING::HELPERS::DialogResponse;
#define DEFAULT_INFO_STRING_VALUE "unknown"
@@ -122,14 +127,14 @@ void CPVRClient::OnPostUnInstall()
PVR::CPVRManager::GetInstance().Start(true);
}
-bool CPVRClient::CanInstall(const std::string &referer)
+bool CPVRClient::CanInstall()
{
if (!PVR::CPVRManager::GetInstance().InstallAddonAllowed(ID()))
{
- PVR::CPVRManager::GetInstance().MarkAsOutdated(ID(), referer);
+ PVR::CPVRManager::GetInstance().MarkAsOutdated(ID());
return false;
}
- return CAddon::CanInstall(referer);
+ return CAddon::CanInstall();
}
void CPVRClient::ResetProperties(int iClientId /* = PVR_INVALID_CLIENT_ID */)
@@ -1943,10 +1948,10 @@ bool CPVRClient::Autoconfigure(void)
std::string strLogLine(StringUtils::Format(g_localizeStrings.Get(19689).c_str(), (*it).GetName().c_str(), (*it).GetIP().c_str()));
CLog::Log(LOGDEBUG, "%s - %s", __FUNCTION__, strLogLine.c_str());
- if (!CGUIDialogYesNo::ShowAndGetInput(CVariant{19688}, // Scanning for PVR services
- CVariant{strLogLine},
- CVariant{19690}, // Do you want to use this service?
- CVariant{""}))
+ if (DialogResponse::YES !=
+ HELPERS::ShowYesNoDialogLines(CVariant{19688}, // Scanning for PVR services
+ CVariant{strLogLine},
+ CVariant{19690})) // Do you want to use this service?
{
CLog::Log(LOGDEBUG, "%s - %s service found but not enabled by the user", __FUNCTION__, (*it).GetName().c_str());
m_rejectedAvahiHosts.push_back(*it);
diff --git a/xbmc/pvr/addons/PVRClient.h b/xbmc/pvr/addons/PVRClient.h
index 933715e6e9..7f20a28a1c 100644
--- a/xbmc/pvr/addons/PVRClient.h
+++ b/xbmc/pvr/addons/PVRClient.h
@@ -69,7 +69,7 @@ namespace PVR
virtual void OnPostInstall(bool update, bool modal);
virtual void OnPreUnInstall();
virtual void OnPostUnInstall();
- virtual bool CanInstall(const std::string &referer);
+ virtual bool CanInstall();
bool NeedsConfiguration(void) const { return m_bNeedsConfiguration; }
/** @name PVR add-on methods */
diff --git a/xbmc/pvr/channels/Makefile b/xbmc/pvr/channels/Makefile
index cb8566321f..06a035faec 100644
--- a/xbmc/pvr/channels/Makefile
+++ b/xbmc/pvr/channels/Makefile
@@ -2,7 +2,8 @@ SRCS=PVRChannel.cpp \
PVRChannelGroup.cpp \
PVRChannelGroupInternal.cpp \
PVRChannelGroups.cpp \
- PVRChannelGroupsContainer.cpp
+ PVRChannelGroupsContainer.cpp \
+ PVRRadioRDSInfoTag.cpp
LIB=pvrchannels.a
diff --git a/xbmc/pvr/channels/PVRRadioRDSInfoTag.cpp b/xbmc/pvr/channels/PVRRadioRDSInfoTag.cpp
new file mode 100644
index 0000000000..c817988271
--- /dev/null
+++ b/xbmc/pvr/channels/PVRRadioRDSInfoTag.cpp
@@ -0,0 +1,908 @@
+/*
+ * Copyright (C) 2005-2015 Team KODI
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with KODI; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "Application.h"
+#include "GUIUserMessages.h"
+#include "PVRRadioRDSInfoTag.h"
+#include "guilib/GUIMessage.h"
+#include "guilib/GUIWindowManager.h"
+#include "messaging/ApplicationMessenger.h"
+#include "settings/AdvancedSettings.h"
+#include "utils/Archive.h"
+#include "utils/CharsetConverter.h"
+#include "utils/StringUtils.h"
+#include "utils/Variant.h"
+
+using namespace PVR;
+
+CPVRRadioRDSInfoTagPtr CPVRRadioRDSInfoTag::CreateDefaultTag()
+{
+ return CPVRRadioRDSInfoTagPtr(new CPVRRadioRDSInfoTag());
+}
+
+CPVRRadioRDSInfoTag::CPVRRadioRDSInfoTag(void)
+{
+ Clear();
+}
+
+CPVRRadioRDSInfoTag::~CPVRRadioRDSInfoTag()
+{}
+
+void CPVRRadioRDSInfoTag::Serialize(CVariant& value) const
+{
+ value["strLanguage"] = m_strLanguage;
+ value["strCountry"] = m_strCountry;
+ value["strTitle"] = m_strTitle;
+ value["strBand"] = m_strBand;
+ value["strArtist"] = m_strArtist;
+ value["strComposer"] = m_strComposer;
+ value["strConductor"] = m_strConductor;
+ value["strAlbum"] = m_strAlbum;
+ value["iAlbumTracknumber"] = m_iAlbumTracknumber;
+ value["strProgStation"] = m_strProgStation;
+ value["strProgStyle"] = m_strProgStyle;
+ value["strProgHost"] = m_strProgHost;
+ value["strProgWebsite"] = m_strProgWebsite;
+ value["strProgNow"] = m_strProgNow;
+ value["strProgNext"] = m_strProgNext;
+ value["strPhoneHotline"] = m_strPhoneHotline;
+ value["strEMailHotline"] = m_strEMailHotline;
+ value["strPhoneStudio"] = m_strPhoneStudio;
+ value["strEMailStudio"] = m_strEMailStudio;
+ value["strSMSStudio"] = m_strSMSStudio;
+ value["strRadioStyle"] = m_strRadioStyle;
+}
+
+void CPVRRadioRDSInfoTag::Archive(CArchive& ar)
+{
+ if (ar.IsStoring())
+ {
+ ar << m_strLanguage;
+ ar << m_strCountry;
+ ar << m_strTitle;
+ ar << m_strBand;
+ ar << m_strArtist;
+ ar << m_strComposer;
+ ar << m_strConductor;
+ ar << m_strAlbum;
+ ar << m_iAlbumTracknumber;
+ ar << m_strProgStation;
+ ar << m_strProgStyle;
+ ar << m_strProgHost;
+ ar << m_strProgWebsite;
+ ar << m_strProgNow;
+ ar << m_strProgNext;
+ ar << m_strPhoneHotline;
+ ar << m_strEMailHotline;
+ ar << m_strPhoneStudio;
+ ar << m_strEMailStudio;
+ ar << m_strSMSStudio;
+ ar << m_strRadioStyle;
+ }
+ else
+ {
+ ar >> m_strLanguage;
+ ar >> m_strCountry;
+ ar >> m_strTitle;
+ ar >> m_strBand;
+ ar >> m_strArtist;
+ ar >> m_strComposer;
+ ar >> m_strConductor;
+ ar >> m_strAlbum;
+ ar >> m_iAlbumTracknumber;
+ ar >> m_strProgStation;
+ ar >> m_strProgStyle;
+ ar >> m_strProgHost;
+ ar >> m_strProgWebsite;
+ ar >> m_strProgNow;
+ ar >> m_strProgNext;
+ ar >> m_strPhoneHotline;
+ ar >> m_strEMailHotline;
+ ar >> m_strPhoneStudio;
+ ar >> m_strEMailStudio;
+ ar >> m_strSMSStudio;
+ ar >> m_strRadioStyle;
+ }
+}
+
+bool CPVRRadioRDSInfoTag::operator==(const CPVRRadioRDSInfoTag &right) const
+{
+ return !(*this != right);
+}
+
+bool CPVRRadioRDSInfoTag::operator !=(const CPVRRadioRDSInfoTag& tag) const
+{
+ if (this == &tag) return false;
+ if (m_strLanguage != tag.m_strLanguage) return true;
+ if (m_strCountry != tag.m_strCountry) return true;
+ if (m_strTitle != tag.m_strTitle) return true;
+ if (m_strBand != tag.m_strBand) return true;
+ if (m_strArtist != tag.m_strArtist) return true;
+ if (m_strComposer != tag.m_strComposer) return true;
+ if (m_strConductor != tag.m_strConductor) return true;
+ if (m_strAlbum != tag.m_strAlbum) return true;
+ if (m_iAlbumTracknumber != tag.m_iAlbumTracknumber) return true;
+ if (m_strInfoNews != tag.m_strInfoNews) return true;
+ if (m_strInfoNewsLocal != tag.m_strInfoNewsLocal) return true;
+ if (m_strInfoSport != tag.m_strInfoSport) return true;
+ if (m_strInfoStock != tag.m_strInfoStock) return true;
+ if (m_strInfoWeather != tag.m_strInfoWeather) return true;
+ if (m_strInfoLottery != tag.m_strInfoLottery) return true;
+ if (m_strInfoOther != tag.m_strInfoOther) return true;
+ if (m_strProgStyle != tag.m_strProgStyle) return true;
+ if (m_strProgHost != tag.m_strProgHost) return true;
+ if (m_strProgStation != tag.m_strProgStation) return true;
+ if (m_strProgWebsite != tag.m_strProgWebsite) return true;
+ if (m_strProgNow != tag.m_strProgNow) return true;
+ if (m_strProgNext != tag.m_strProgNext) return true;
+ if (m_strPhoneHotline != tag.m_strPhoneHotline) return true;
+ if (m_strEMailHotline != tag.m_strEMailHotline) return true;
+ if (m_strPhoneStudio != tag.m_strPhoneStudio) return true;
+ if (m_strEMailStudio != tag.m_strEMailStudio) return true;
+ if (m_strSMSStudio != tag.m_strSMSStudio) return true;
+ if (m_strRadioStyle != tag.m_strRadioStyle) return true;
+ if (m_strInfoHoroscope != tag.m_strInfoHoroscope) return true;
+ if (m_strInfoCinema != tag.m_strInfoCinema) return true;
+ if (m_strComment != tag.m_strComment) return true;
+ if (m_strEditorialStaff != tag.m_strEditorialStaff) return true;
+
+ if (m_bHaveRadiotext != tag.m_bHaveRadiotext) return true;
+ if (m_bHaveRadiotextPlus != tag.m_bHaveRadiotextPlus) return true;
+
+ return false;
+}
+
+void CPVRRadioRDSInfoTag::Clear()
+{
+ m_RDS_SpeechActive = false;
+
+ m_strLanguage.erase();
+ m_strCountry.erase();
+ m_strTitle.erase();
+ m_strBand.erase();
+ m_strArtist.erase();
+ m_strComposer.erase();
+ m_strConductor.erase();
+ m_strAlbum.erase();
+ m_strComment.erase();
+ m_iAlbumTracknumber = 0;
+ m_strInfoNews.clear();
+ m_strInfoNewsLocal.clear();
+ m_strInfoSport.clear();
+ m_strInfoStock.clear();
+ m_strInfoWeather.clear();
+ m_strInfoLottery.clear();
+ m_strInfoOther.clear();
+ m_strInfoHoroscope.clear();
+ m_strInfoCinema.clear();
+ m_strProgStyle.erase();
+ m_strProgHost.erase();
+ m_strProgStation.erase();
+ m_strProgWebsite.erase();
+ m_strPhoneHotline.erase();
+ m_strEMailHotline.erase();
+ m_strPhoneStudio.erase();
+ m_strEMailStudio.erase();
+ m_strSMSStudio.erase();
+ m_strRadioStyle = "unknown";
+ m_strEditorialStaff.clear();
+
+ m_bHaveRadiotext = false;
+ m_bHaveRadiotextPlus = false;
+}
+
+void CPVRRadioRDSInfoTag::ResetSongInformation()
+{
+ m_strTitle.erase();
+ m_strBand.erase();
+ m_strArtist.erase();
+ m_strComposer.erase();
+ m_strConductor.erase();
+ m_strAlbum.erase();
+ m_iAlbumTracknumber = 0;
+}
+
+void CPVRRadioRDSInfoTag::SetSpeechActive(bool active)
+{
+ m_RDS_SpeechActive = active;
+}
+
+bool CPVRRadioRDSInfoTag::IsSpeechActive()
+{
+ return m_RDS_SpeechActive;
+}
+
+void CPVRRadioRDSInfoTag::SetLanguage(const std::string& strLanguage)
+{
+ m_strLanguage = Trim(strLanguage);
+}
+
+const std::string& CPVRRadioRDSInfoTag::GetLanguage() const
+{
+ return m_strLanguage;
+}
+
+void CPVRRadioRDSInfoTag::SetCountry(const std::string& strCountry)
+{
+ m_strCountry = Trim(strCountry);
+}
+
+const std::string& CPVRRadioRDSInfoTag::GetCountry() const
+{
+ return m_strCountry;
+}
+
+void CPVRRadioRDSInfoTag::SetTitle(const std::string& strTitle)
+{
+ m_strTitle = Trim(strTitle);
+}
+
+void CPVRRadioRDSInfoTag::SetArtist(const std::string& strArtist)
+{
+ m_strArtist = Trim(strArtist);
+}
+
+void CPVRRadioRDSInfoTag::SetBand(const std::string& strBand)
+{
+ m_strBand = Trim(strBand);
+ g_charsetConverter.unknownToUTF8(m_strBand);
+}
+
+void CPVRRadioRDSInfoTag::SetComposer(const std::string& strComposer)
+{
+ m_strComposer = Trim(strComposer);
+ g_charsetConverter.unknownToUTF8(m_strComposer);
+}
+
+void CPVRRadioRDSInfoTag::SetConductor(const std::string& strConductor)
+{
+ m_strConductor = Trim(strConductor);
+ g_charsetConverter.unknownToUTF8(m_strConductor);
+}
+
+void CPVRRadioRDSInfoTag::SetAlbum(const std::string& strAlbum)
+{
+ m_strAlbum = Trim(strAlbum);
+ g_charsetConverter.unknownToUTF8(m_strAlbum);
+}
+
+void CPVRRadioRDSInfoTag::SetAlbumTrackNumber(int track)
+{
+ m_iAlbumTracknumber = track;
+}
+
+void CPVRRadioRDSInfoTag::SetComment(const std::string& strComment)
+{
+ m_strComment = Trim(strComment);
+ g_charsetConverter.unknownToUTF8(m_strComment);
+}
+
+const std::string& CPVRRadioRDSInfoTag::GetTitle() const
+{
+ return m_strTitle;
+}
+
+const std::string& CPVRRadioRDSInfoTag::GetArtist() const
+{
+ return m_strArtist;
+}
+
+const std::string& CPVRRadioRDSInfoTag::GetBand() const
+{
+ return m_strBand;
+}
+
+const std::string& CPVRRadioRDSInfoTag::GetComposer() const
+{
+ return m_strComposer;
+}
+
+const std::string& CPVRRadioRDSInfoTag::GetConductor() const
+{
+ return m_strConductor;
+}
+
+const std::string& CPVRRadioRDSInfoTag::GetAlbum() const
+{
+ return m_strAlbum;
+}
+
+int CPVRRadioRDSInfoTag::GetAlbumTrackNumber() const
+{
+ return m_iAlbumTracknumber;
+}
+
+const std::string& CPVRRadioRDSInfoTag::GetComment() const
+{
+ return m_strComment;
+}
+
+void CPVRRadioRDSInfoTag::SetInfoNews(const std::string& strNews)
+{
+ std::string tmpStr = Trim(strNews);
+ g_charsetConverter.unknownToUTF8(tmpStr);
+
+ for (unsigned i = 0; i < m_strInfoNews.size(); i++)
+ {
+ if (m_strInfoNews[i].compare(tmpStr) == 0)
+ return;
+ }
+
+ if (m_strInfoNews.size() >= 10)
+ m_strInfoNews.pop_front();
+
+ m_strInfoNews.push_back(tmpStr);
+
+ // send a message to all windows to tell them to update the radiotext
+ CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_RADIOTEXT);
+ g_windowManager.SendThreadMessage(msg);
+}
+
+void CPVRRadioRDSInfoTag::ClearInfoNews()
+{
+ m_strInfoNews.clear();
+}
+
+const std::deque<std::string>& CPVRRadioRDSInfoTag::GetInfoNewsDeque() const
+{
+ return m_strInfoNews;
+}
+
+const std::string CPVRRadioRDSInfoTag::GetInfoNews() const
+{
+ std::string retStr = "";
+ for (unsigned i = 0; i < m_strInfoNews.size(); i++)
+ {
+ std::string tmpStr = m_strInfoNews[i];
+ tmpStr.insert(0, "- ");
+ tmpStr.insert(tmpStr.end(),'\n');
+ retStr += tmpStr;
+ }
+
+ return retStr;
+}
+
+void CPVRRadioRDSInfoTag::SetInfoNewsLocal(const std::string& strNews)
+{
+ std::string tmpStr = Trim(strNews);
+ g_charsetConverter.unknownToUTF8(tmpStr);
+
+ for (unsigned i = 0; i < m_strInfoNewsLocal.size(); i++)
+ {
+ if (m_strInfoNewsLocal[i].compare(tmpStr) == 0)
+ return;
+ }
+
+ if (m_strInfoNewsLocal.size() >= 10)
+ m_strInfoNewsLocal.pop_back();
+
+ m_strInfoNewsLocal.push_front(tmpStr);
+
+ // send a message to all windows to tell them to update the radiotext
+ CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_RADIOTEXT);
+ g_windowManager.SendThreadMessage(msg);
+}
+
+void CPVRRadioRDSInfoTag::ClearInfoNewsLocal()
+{
+ m_strInfoNewsLocal.clear();
+}
+
+const std::deque<std::string>& CPVRRadioRDSInfoTag::GetInfoNewsLocalDeque() const
+{
+ return m_strInfoNewsLocal;
+}
+
+const std::string CPVRRadioRDSInfoTag::GetInfoNewsLocal() const
+{
+ std::string retStr = "";
+ for (unsigned i = 0; i < m_strInfoNewsLocal.size(); i++)
+ {
+ std::string tmpStr = m_strInfoNewsLocal[i];
+ tmpStr.insert(0, "- ");
+ tmpStr.insert(tmpStr.end(),'\n');
+ retStr += tmpStr;
+ }
+
+ return retStr;
+}
+
+void CPVRRadioRDSInfoTag::SetInfoSport(const std::string& strSport)
+{
+ std::string tmpStr = Trim(strSport);
+ g_charsetConverter.unknownToUTF8(tmpStr);
+
+ for (unsigned i = 0; i < m_strInfoSport.size(); i++)
+ {
+ if (m_strInfoSport[i].compare(tmpStr) == 0)
+ return;
+ }
+
+ if (m_strInfoSport.size() >= 10)
+ m_strInfoSport.pop_back();
+
+ m_strInfoSport.push_front(tmpStr);
+
+ // send a message to all windows to tell them to update the radiotext
+ CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_RADIOTEXT);
+ g_windowManager.SendThreadMessage(msg);
+}
+
+void CPVRRadioRDSInfoTag::ClearInfoSport()
+{
+ m_strInfoSport.clear();
+}
+
+const std::deque<std::string>& CPVRRadioRDSInfoTag::GetInfoSportDeque() const
+{
+ return m_strInfoSport;
+}
+
+const std::string CPVRRadioRDSInfoTag::GetInfoSport() const
+{
+ std::string retStr = "";
+ for (unsigned i = 0; i < m_strInfoSport.size(); i++)
+ {
+ std::string tmpStr = m_strInfoSport[i];
+ tmpStr.insert(0, "- ");
+ tmpStr.insert(tmpStr.end(),'\n');
+ retStr += tmpStr;
+ }
+
+ return retStr;
+}
+
+void CPVRRadioRDSInfoTag::SetInfoStock(const std::string& strStock)
+{
+ std::string tmpStr = Trim(strStock);
+ g_charsetConverter.unknownToUTF8(tmpStr);
+
+ for (unsigned i = 0; i < m_strInfoStock.size(); i++)
+ {
+ if (m_strInfoStock[i].compare(tmpStr) == 0)
+ return;
+ }
+
+ if (m_strInfoStock.size() >= 10)
+ m_strInfoStock.pop_back();
+
+ m_strInfoStock.push_front(tmpStr);
+
+ // send a message to all windows to tell them to update the radiotext
+ CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_RADIOTEXT);
+ g_windowManager.SendThreadMessage(msg);
+}
+
+void CPVRRadioRDSInfoTag::ClearInfoStock()
+{
+ m_strInfoStock.clear();
+}
+
+const std::deque<std::string>& CPVRRadioRDSInfoTag::GetInfoStockDeque() const
+{
+ return m_strInfoStock;
+}
+
+const std::string CPVRRadioRDSInfoTag::GetInfoStock() const
+{
+ std::string retStr = "";
+ for (unsigned i = 0; i < m_strInfoStock.size(); i++)
+ {
+ std::string tmpStr = m_strInfoStock[i];
+ tmpStr.insert(0, "- ");
+ tmpStr.insert(tmpStr.end(),'\n');
+ retStr += tmpStr;
+ }
+
+ return retStr;
+}
+
+void CPVRRadioRDSInfoTag::SetInfoWeather(const std::string& strWeather)
+{
+ std::string tmpStr = Trim(strWeather);
+ g_charsetConverter.unknownToUTF8(tmpStr);
+
+ for (unsigned i = 0; i < m_strInfoWeather.size(); i++)
+ {
+ if (m_strInfoWeather[i].compare(tmpStr) == 0)
+ return;
+ }
+
+ if (m_strInfoWeather.size() >= 10)
+ m_strInfoWeather.pop_back();
+
+ m_strInfoWeather.push_front(tmpStr);
+ // send a message to all windows to tell them to update the radiotext
+ CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_RADIOTEXT);
+ g_windowManager.SendThreadMessage(msg);
+}
+
+void CPVRRadioRDSInfoTag::ClearInfoWeather()
+{
+ m_strInfoWeather.clear();
+}
+
+const std::deque<std::string>& CPVRRadioRDSInfoTag::GetInfoWeatherDeque() const
+{
+ return m_strInfoWeather;
+}
+
+const std::string CPVRRadioRDSInfoTag::GetInfoWeather() const
+{
+ std::string retStr = "";
+ for (unsigned i = 0; i < m_strInfoWeather.size(); i++)
+ {
+ std::string tmpStr = m_strInfoWeather[i];
+ tmpStr.insert(0, "- ");
+ tmpStr.insert(tmpStr.end(),'\n');
+ retStr += tmpStr;
+ }
+
+ return retStr;
+}
+
+void CPVRRadioRDSInfoTag::SetInfoLottery(const std::string& strLottery)
+{
+ std::string tmpStr = Trim(strLottery);
+ g_charsetConverter.unknownToUTF8(tmpStr);
+
+ for (unsigned i = 0; i < m_strInfoLottery.size(); i++)
+ {
+ if (m_strInfoLottery[i].compare(tmpStr) == 0)
+ return;
+ }
+
+ if (m_strInfoLottery.size() >= 10)
+ m_strInfoLottery.pop_back();
+
+ m_strInfoLottery.push_front(tmpStr);
+ // send a message to all windows to tell them to update the radiotext
+ CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_RADIOTEXT);
+ g_windowManager.SendThreadMessage(msg);
+}
+
+void CPVRRadioRDSInfoTag::ClearInfoLottery()
+{
+ m_strInfoLottery.clear();
+}
+
+const std::deque<std::string>& CPVRRadioRDSInfoTag::GetInfoLotteryDeque() const
+{
+ return m_strInfoLottery;
+}
+
+const std::string CPVRRadioRDSInfoTag::GetInfoLottery() const
+{
+ std::string retStr = "";
+ for (unsigned i = 0; i < m_strInfoLottery.size(); i++)
+ {
+ std::string tmpStr = m_strInfoLottery[i];
+ tmpStr.insert(0, "- ");
+ tmpStr.insert(tmpStr.end(),'\n');
+ retStr += tmpStr;
+ }
+
+ return retStr;
+}
+
+void CPVRRadioRDSInfoTag::SetEditorialStaff(const std::string& strEditorialStaff)
+{
+ std::string tmpStr = Trim(strEditorialStaff);
+ g_charsetConverter.unknownToUTF8(tmpStr);
+
+ for (unsigned i = 0; i < m_strEditorialStaff.size(); i++)
+ {
+ if (m_strEditorialStaff[i].compare(tmpStr) == 0)
+ return;
+ }
+
+ if (m_strEditorialStaff.size() >= 10)
+ m_strEditorialStaff.pop_back();
+
+ m_strEditorialStaff.push_front(tmpStr);
+ // send a message to all windows to tell them to update the radiotext
+ CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_RADIOTEXT);
+ g_windowManager.SendThreadMessage(msg);
+}
+
+void CPVRRadioRDSInfoTag::ClearEditorialStaff()
+{
+ m_strEditorialStaff.clear();
+}
+
+const std::deque<std::string>& CPVRRadioRDSInfoTag::GetEditorialStaffDeque() const
+{
+ return m_strEditorialStaff;
+}
+
+const std::string CPVRRadioRDSInfoTag::GetEditorialStaff() const
+{
+ std::string retStr = "";
+ for (unsigned i = 0; i < m_strEditorialStaff.size(); i++)
+ {
+ std::string tmpStr = m_strEditorialStaff[i];
+ tmpStr.insert(0, "- ");
+ tmpStr.insert(tmpStr.end(),'\n');
+ retStr += tmpStr;
+ }
+
+ return retStr;
+}
+
+void CPVRRadioRDSInfoTag::SetInfoHoroscope(const std::string& strHoroscope)
+{
+ std::string tmpStr = Trim(strHoroscope);
+ g_charsetConverter.unknownToUTF8(tmpStr);
+
+ for (unsigned i = 0; i < m_strInfoHoroscope.size(); i++)
+ {
+ if (m_strInfoHoroscope[i].compare(tmpStr) == 0)
+ return;
+ }
+
+ if (m_strInfoHoroscope.size() >= 10)
+ m_strInfoHoroscope.pop_back();
+
+ m_strInfoHoroscope.push_front(tmpStr);
+ // send a message to all windows to tell them to update the radiotext
+ CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_RADIOTEXT);
+ g_windowManager.SendThreadMessage(msg);
+}
+
+void CPVRRadioRDSInfoTag::ClearInfoHoroscope()
+{
+ m_strInfoHoroscope.clear();
+}
+
+const std::deque<std::string>& CPVRRadioRDSInfoTag::GetInfoHoroscopeDeque() const
+{
+ return m_strInfoHoroscope;
+}
+
+const std::string CPVRRadioRDSInfoTag::GetInfoHoroscope() const
+{
+ std::string retStr = "";
+ for (unsigned i = 0; i < m_strInfoHoroscope.size(); i++)
+ {
+ std::string tmpStr = m_strInfoHoroscope[i];
+ tmpStr.insert(0, "- ");
+ tmpStr.insert(tmpStr.end(),'\n');
+ retStr += tmpStr;
+ }
+
+ return retStr;
+}
+
+void CPVRRadioRDSInfoTag::SetInfoCinema(const std::string& strCinema)
+{
+ std::string tmpStr = Trim(strCinema);
+ g_charsetConverter.unknownToUTF8(tmpStr);
+
+ for (unsigned i = 0; i < m_strInfoCinema.size(); i++)
+ {
+ if (m_strInfoCinema[i].compare(tmpStr) == 0)
+ return;
+ }
+
+ if (m_strInfoCinema.size() >= 10)
+ m_strInfoCinema.pop_back();
+
+ m_strInfoCinema.push_front(tmpStr);
+ // send a message to all windows to tell them to update the fileitem radiotext
+ CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_RADIOTEXT);
+ g_windowManager.SendThreadMessage(msg);
+}
+
+void CPVRRadioRDSInfoTag::ClearInfoCinema()
+{
+ m_strInfoCinema.clear();
+}
+
+const std::deque<std::string>& CPVRRadioRDSInfoTag::GetInfoCinemaDeque() const
+{
+ return m_strInfoCinema;
+}
+
+const std::string CPVRRadioRDSInfoTag::GetInfoCinema() const
+{
+ std::string retStr = "";
+ for (unsigned i = 0; i < m_strInfoCinema.size(); i++)
+ {
+ std::string tmpStr = m_strInfoCinema[i];
+ tmpStr.insert(0, "- ");
+ tmpStr.insert(tmpStr.end(),'\n');
+ retStr += tmpStr;
+ }
+
+ return retStr;
+}
+
+void CPVRRadioRDSInfoTag::SetInfoOther(const std::string& strOther)
+{
+ std::string tmpStr = Trim(strOther);
+ g_charsetConverter.unknownToUTF8(tmpStr);
+
+ for (unsigned i = 0; i < m_strInfoOther.size(); i++)
+ {
+ if (m_strInfoOther[i].compare(tmpStr) == 0)
+ return;
+ }
+
+ if (m_strInfoOther.size() >= 10)
+ m_strInfoOther.pop_back();
+
+ m_strInfoOther.push_front(tmpStr);
+ // send a message to all windows to tell them to update the fileitem radiotext
+ CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_RADIOTEXT);
+ g_windowManager.SendThreadMessage(msg);
+}
+
+void CPVRRadioRDSInfoTag::ClearInfoOther()
+{
+ m_strInfoOther.clear();
+}
+
+const std::deque<std::string>& CPVRRadioRDSInfoTag::GetInfoOtherDeque() const
+{
+ return m_strInfoOther;
+}
+
+const std::string CPVRRadioRDSInfoTag::GetInfoOther() const
+{
+ std::string retStr = "";
+ for (unsigned i = 0; i < m_strInfoOther.size(); i++)
+ {
+ std::string tmpStr = m_strInfoOther[i];
+ tmpStr.insert(0, "- ");
+ tmpStr.insert(tmpStr.end(),'\n');
+ retStr += tmpStr;
+ }
+
+ return retStr;
+}
+
+void CPVRRadioRDSInfoTag::SetProgStation(const std::string& strProgStation)
+{
+ m_strProgStation = Trim(strProgStation);
+ g_charsetConverter.unknownToUTF8(m_strProgStation);
+}
+
+void CPVRRadioRDSInfoTag::SetProgHost(const std::string& strProgHost)
+{
+ m_strProgHost = Trim(strProgHost);
+ g_charsetConverter.unknownToUTF8(m_strProgHost);
+}
+
+void CPVRRadioRDSInfoTag::SetProgStyle(const std::string& strProgStyle)
+{
+ m_strProgStyle = Trim(strProgStyle);
+ g_charsetConverter.unknownToUTF8(m_strProgStyle);
+}
+
+void CPVRRadioRDSInfoTag::SetProgWebsite(const std::string& strWebsite)
+{
+ m_strProgWebsite = Trim(strWebsite);
+ g_charsetConverter.unknownToUTF8(m_strProgWebsite);
+}
+
+void CPVRRadioRDSInfoTag::SetProgNow(const std::string& strNow)
+{
+ m_strProgNow = Trim(strNow);
+ g_charsetConverter.unknownToUTF8(m_strProgNow);
+}
+
+void CPVRRadioRDSInfoTag::SetProgNext(const std::string& strNext)
+{
+ m_strProgNext = Trim(strNext);
+ g_charsetConverter.unknownToUTF8(m_strProgNext);
+}
+
+void CPVRRadioRDSInfoTag::SetPhoneHotline(const std::string& strHotline)
+{
+ m_strPhoneHotline = Trim(strHotline);
+ g_charsetConverter.unknownToUTF8(m_strPhoneHotline);
+}
+
+void CPVRRadioRDSInfoTag::SetEMailHotline(const std::string& strHotline)
+{
+ m_strEMailHotline = Trim(strHotline);
+ g_charsetConverter.unknownToUTF8(m_strEMailHotline);
+}
+
+void CPVRRadioRDSInfoTag::SetPhoneStudio(const std::string& strPhone)
+{
+ m_strPhoneStudio = Trim(strPhone);
+ g_charsetConverter.unknownToUTF8(m_strPhoneStudio);
+}
+
+void CPVRRadioRDSInfoTag::SetEMailStudio(const std::string& strEMail)
+{
+ m_strEMailStudio = Trim(strEMail);
+ g_charsetConverter.unknownToUTF8(m_strEMailStudio);
+}
+
+void CPVRRadioRDSInfoTag::SetSMSStudio(const std::string& strSMS)
+{
+ m_strSMSStudio = Trim(strSMS);
+ g_charsetConverter.unknownToUTF8(m_strSMSStudio);
+}
+
+const std::string& CPVRRadioRDSInfoTag::GetProgStyle() const
+{
+ return m_strProgStyle;
+}
+
+const std::string& CPVRRadioRDSInfoTag::GetProgHost() const
+{
+ return m_strProgHost;
+}
+
+const std::string& CPVRRadioRDSInfoTag::GetProgStation() const
+{
+ return m_strProgStation;
+}
+
+const std::string& CPVRRadioRDSInfoTag::GetProgWebsite() const
+{
+ return m_strProgWebsite;
+}
+
+const std::string& CPVRRadioRDSInfoTag::GetProgNow() const
+{
+ return m_strProgNow;
+}
+
+const std::string& CPVRRadioRDSInfoTag::GetProgNext() const
+{
+ return m_strProgNext;
+}
+
+const std::string& CPVRRadioRDSInfoTag::GetPhoneHotline() const
+{
+ return m_strPhoneHotline;
+}
+
+const std::string& CPVRRadioRDSInfoTag::GetEMailHotline() const
+{
+ return m_strEMailHotline;
+}
+
+const std::string& CPVRRadioRDSInfoTag::GetPhoneStudio() const
+{
+ return m_strPhoneStudio;
+}
+
+const std::string& CPVRRadioRDSInfoTag::GetEMailStudio() const
+{
+ return m_strEMailStudio;
+}
+
+const std::string& CPVRRadioRDSInfoTag::GetSMSStudio() const
+{
+ return m_strSMSStudio;
+}
+
+std::string CPVRRadioRDSInfoTag::Trim(const std::string &value) const
+{
+ std::string trimmedValue(value);
+ StringUtils::TrimLeft(trimmedValue);
+ StringUtils::TrimRight(trimmedValue, " \n\r");
+ return trimmedValue;
+}
diff --git a/xbmc/pvr/channels/PVRRadioRDSInfoTag.h b/xbmc/pvr/channels/PVRRadioRDSInfoTag.h
new file mode 100644
index 0000000000..87211fe712
--- /dev/null
+++ b/xbmc/pvr/channels/PVRRadioRDSInfoTag.h
@@ -0,0 +1,231 @@
+#pragma once
+/*
+ * Copyright (C) 2005-2015 Team KODI
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with KODI; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <vector>
+#include <deque>
+#include <string>
+#include <stdint.h>
+
+#include "FileItem.h"
+#include "utils/IArchivable.h"
+#include "utils/ISerializable.h"
+#include "XBDateTime.h"
+
+namespace PVR
+{
+
+class CPVRRadioRDSInfoTag : public IArchivable, public ISerializable
+{
+public:
+ /*!
+ * @brief Create a new empty event .
+ */
+ static CPVRRadioRDSInfoTagPtr CreateDefaultTag();
+
+private:
+ /*!
+ * @brief Create a new empty event.
+ */
+ CPVRRadioRDSInfoTag(void);
+
+ /*!
+ * @brief Prevent copy construction, even for CEpgInfoTag instances and friends.
+ * Note: Only declared, but intentionally not implemented
+ * to prevent compiler generated copy ctor and to force.
+ * a linker error in case somebody tries to call it.
+ */
+ CPVRRadioRDSInfoTag(const CPVRRadioRDSInfoTag& tag);
+
+ /*!
+ * @brief Prevent copy construction, even for CEpgInfoTag instances and friends.
+ * Note: Only declared, but intentionally not implemented
+ * to prevent compiler generated copy ctor and to force.
+ * a linker error in case somebody tries to call it.
+ */
+ const CPVRRadioRDSInfoTag& operator =(const CPVRRadioRDSInfoTag& tag);
+
+public:
+ virtual ~CPVRRadioRDSInfoTag();
+
+ bool operator ==(const CPVRRadioRDSInfoTag& tag) const;
+ bool operator !=(const CPVRRadioRDSInfoTag& tag) const;
+
+ virtual void Archive(CArchive& ar);
+ virtual void Serialize(CVariant& value) const;
+
+ void Clear();
+ void ResetSongInformation();
+
+ /**! Basic RDS related information */
+ void SetSpeechActive(bool active);
+ bool IsSpeechActive();
+ void SetLanguage(const std::string& strLanguage);
+ const std::string& GetLanguage() const;
+ void SetCountry(const std::string& strCountry);
+ const std::string& GetCountry() const;
+
+ /**! RDS Radiotext related information */
+ void SetTitle(const std::string& strTitle);
+ void SetBand(const std::string& strBand);
+ void SetArtist(const std::string& strArtist);
+ void SetComposer(const std::string& strComposer);
+ void SetConductor(const std::string& strConductor);
+ void SetAlbum(const std::string& strAlbum);
+ void SetComment(const std::string& strComment);
+ void SetAlbumTrackNumber(int track);
+
+ const std::string& GetTitle() const;
+ const std::string& GetBand() const;
+ const std::string& GetArtist() const;
+ const std::string& GetComposer() const;
+ const std::string& GetConductor() const;
+ const std::string& GetAlbum() const;
+ const std::string& GetComment() const;
+ int GetAlbumTrackNumber() const;
+
+ void SetProgStation(const std::string& strProgStation);
+ void SetProgStyle(const std::string& strProgStyle);
+ void SetProgHost(const std::string& strProgHost);
+ void SetProgWebsite(const std::string& strWebsite);
+ void SetProgNow(const std::string& strNow);
+ void SetProgNext(const std::string& strNext);
+ void SetPhoneHotline(const std::string& strHotline);
+ void SetEMailHotline(const std::string& strHotline);
+ void SetPhoneStudio(const std::string& strPhone);
+ void SetEMailStudio(const std::string& strEMail);
+ void SetSMSStudio(const std::string& strSMS);
+
+ const std::string& GetProgStation() const;
+ const std::string& GetProgStyle() const;
+ const std::string& GetProgHost() const;
+ const std::string& GetProgWebsite() const;
+ const std::string& GetProgNow() const;
+ const std::string& GetProgNext() const;
+ const std::string& GetPhoneHotline() const;
+ const std::string& GetEMailHotline() const;
+ const std::string& GetPhoneStudio() const;
+ const std::string& GetEMailStudio() const;
+ const std::string& GetSMSStudio() const;
+
+ void SetInfoNews(const std::string& strNews);
+ void ClearInfoNews();
+ const std::string GetInfoNews() const;
+ const std::deque<std::string>& GetInfoNewsDeque() const;
+
+ void SetInfoNewsLocal(const std::string& strNews);
+ void ClearInfoNewsLocal();
+ const std::string GetInfoNewsLocal() const;
+ const std::deque<std::string>& GetInfoNewsLocalDeque() const;
+
+ void SetInfoSport(const std::string& strSport);
+ void ClearInfoSport();
+ const std::string GetInfoSport() const;
+ const std::deque<std::string>& GetInfoSportDeque() const;
+
+ void SetInfoStock(const std::string& strSport);
+ void ClearInfoStock();
+ const std::string GetInfoStock() const;
+ const std::deque<std::string>& GetInfoStockDeque() const;
+
+ void SetInfoWeather(const std::string& strWeather);
+ void ClearInfoWeather();
+ const std::string GetInfoWeather() const;
+ const std::deque<std::string>& GetInfoWeatherDeque() const;
+
+ void SetInfoHoroscope(const std::string& strHoroscope);
+ void ClearInfoHoroscope();
+ const std::string GetInfoHoroscope() const;
+ const std::deque<std::string>& GetInfoHoroscopeDeque() const;
+
+ void SetInfoCinema(const std::string& strCinema);
+ void ClearInfoCinema();
+ const std::string GetInfoCinema() const;
+ const std::deque<std::string>& GetInfoCinemaDeque() const;
+
+ void SetInfoLottery(const std::string& strLottery);
+ void ClearInfoLottery();
+ const std::string GetInfoLottery() const;
+ const std::deque<std::string>& GetInfoLotteryDeque() const;
+
+ void SetInfoOther(const std::string& strOther);
+ void ClearInfoOther();
+ const std::string GetInfoOther() const;
+ const std::deque<std::string>& GetInfoOtherDeque() const;
+
+ void SetEditorialStaff(const std::string& strEditorialStaff);
+ void ClearEditorialStaff();
+ const std::string GetEditorialStaff() const;
+ const std::deque<std::string>& GetEditorialStaffDeque() const;
+
+ void SetRadioStyle(const std::string& style) { m_strRadioStyle = style; }
+ const std::string GetRadioStyle() const { return m_strRadioStyle; }
+ void SetPlayingRadiotext(bool yesNo) { m_bHaveRadiotext = yesNo; }
+ bool IsPlayingRadiotext() { return m_bHaveRadiotext; }
+ void SetPlayingRadiotextPlus(bool yesNo) { m_bHaveRadiotextPlus = yesNo; }
+ bool IsPlayingRadiotextPlus() { return m_bHaveRadiotextPlus; }
+
+protected:
+ /*! \brief Trim whitespace off the given string
+ * \param value string to trim
+ * \return trimmed value, with spaces removed from left and right, as well as carriage returns from the right.
+ */
+ std::string Trim(const std::string &value) const;
+
+ bool m_RDS_SpeechActive;
+
+ std::string m_strLanguage;
+ std::string m_strCountry;
+ std::string m_strTitle;
+ std::string m_strBand;
+ std::string m_strArtist;
+ std::string m_strComposer;
+ std::string m_strConductor;
+ std::string m_strAlbum;
+ std::string m_strComment;
+ int m_iAlbumTracknumber;
+ std::string m_strRadioStyle;
+
+ std::deque<std::string> m_strInfoNews;
+ std::deque<std::string> m_strInfoNewsLocal;
+ std::deque<std::string> m_strInfoSport;
+ std::deque<std::string> m_strInfoStock;
+ std::deque<std::string> m_strInfoWeather;
+ std::deque<std::string> m_strInfoLottery;
+ std::deque<std::string> m_strInfoOther;
+ std::deque<std::string> m_strInfoHoroscope;
+ std::deque<std::string> m_strInfoCinema;
+ std::deque<std::string> m_strEditorialStaff;
+ std::string m_strProgStyle;
+ std::string m_strProgHost;
+ std::string m_strProgStation;
+ std::string m_strProgWebsite;
+ std::string m_strProgNow;
+ std::string m_strProgNext;
+ std::string m_strPhoneHotline;
+ std::string m_strEMailHotline;
+ std::string m_strPhoneStudio;
+ std::string m_strEMailStudio;
+ std::string m_strSMSStudio;
+
+ bool m_bHaveRadiotext;
+ bool m_bHaveRadiotextPlus;
+};
+}
diff --git a/xbmc/pvr/dialogs/GUIDialogPVRRadioRDSInfo.cpp b/xbmc/pvr/dialogs/GUIDialogPVRRadioRDSInfo.cpp
new file mode 100644
index 0000000000..3451b90731
--- /dev/null
+++ b/xbmc/pvr/dialogs/GUIDialogPVRRadioRDSInfo.cpp
@@ -0,0 +1,416 @@
+/*
+ * Copyright (C) 2012-2015 Team KODI
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with KODI; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "Application.h"
+#include "FileItem.h"
+#include "GUIDialogPVRRadioRDSInfo.h"
+#include "GUIUserMessages.h"
+#include "guilib/GUIWindowManager.h"
+#include "guilib/GUISpinControl.h"
+#include "guilib/GUIMessage.h"
+#include "guilib/GUITextBox.h"
+#include "guilib/LocalizeStrings.h"
+#include "messaging/ApplicationMessenger.h"
+#include "pvr/channels/PVRRadioRDSInfoTag.h"
+
+using namespace PVR;
+
+#define CONTROL_BTN_OK 10
+#define SPIN_CONTROL_INFO 21
+#define TEXT_INFO 22
+#define CONTROL_NEXT_PAGE 60
+#define CONTROL_INFO_LIST 70
+
+#define INFO_NEWS 1
+#define INFO_NEWS_LOCAL 2
+#define INFO_SPORT 3
+#define INFO_WEATHER 4
+#define INFO_LOTTERY 5
+#define INFO_STOCK 6
+#define INFO_OTHER 7
+#define INFO_CINEMA 8
+#define INFO_HOROSCOPE 9
+
+CGUIDialogPVRRadioRDSInfo::CGUIDialogPVRRadioRDSInfo(void)
+ : CGUIDialog(WINDOW_DIALOG_PVR_RADIO_RDS_INFO, "DialogPVRRadioRDSInfo.xml")
+ , m_rdsItem(new CFileItem)
+{
+}
+
+bool CGUIDialogPVRRadioRDSInfo::OnMessage(CGUIMessage& message)
+{
+ if (message.GetMessage() == GUI_MSG_CLICKED)
+ {
+ int iControl = message.GetSenderId();
+
+ if (iControl == CONTROL_BTN_OK)
+ {
+ Close();
+ return true;
+ }
+ else if (iControl == SPIN_CONTROL_INFO)
+ {
+ CGUISpinControl *spin = (CGUISpinControl *)GetControl(SPIN_CONTROL_INFO);
+ if (!spin) return true;
+
+ CGUITextBox *textbox = (CGUITextBox *)GetControl(TEXT_INFO);
+ if (!textbox) return true;
+
+ PVR::CPVRRadioRDSInfoTagPtr currentRDS = g_application.CurrentFileItem().GetPVRRadioRDSInfoTag();
+ switch (spin->GetValue())
+ {
+ case INFO_NEWS:
+ textbox->SetInfo(currentRDS->GetInfoNews());
+ break;
+ case INFO_NEWS_LOCAL:
+ textbox->SetInfo(currentRDS->GetInfoNewsLocal());
+ break;
+ case INFO_SPORT:
+ textbox->SetInfo(currentRDS->GetInfoSport());
+ break;
+ case INFO_WEATHER:
+ textbox->SetInfo(currentRDS->GetInfoWeather());
+ break;
+ case INFO_LOTTERY:
+ textbox->SetInfo(currentRDS->GetInfoLottery());
+ break;
+ case INFO_STOCK:
+ textbox->SetInfo(currentRDS->GetInfoStock());
+ break;
+ case INFO_OTHER:
+ textbox->SetInfo(currentRDS->GetInfoOther());
+ break;
+ case INFO_CINEMA:
+ textbox->SetInfo(currentRDS->GetInfoCinema());
+ break;
+ case INFO_HOROSCOPE:
+ textbox->SetInfo(currentRDS->GetInfoHoroscope());
+ break;
+ }
+
+ SET_CONTROL_VISIBLE(CONTROL_INFO_LIST);
+ }
+ }
+ else if (message.GetMessage() == GUI_MSG_NOTIFY_ALL)
+ {
+ if (IsActive() && message.GetParam1() == GUI_MSG_UPDATE_RADIOTEXT &&
+ g_application.m_pPlayer->IsPlaying() &&
+ g_application.CurrentFileItem().HasPVRRadioRDSInfoTag())
+ {
+ PVR::CPVRRadioRDSInfoTagPtr currentRDS = g_application.CurrentFileItem().GetPVRRadioRDSInfoTag();
+ CGUISpinControl *spin = (CGUISpinControl *)GetControl(SPIN_CONTROL_INFO);
+ CGUITextBox *textbox = (CGUITextBox *)GetControl(TEXT_INFO);
+
+ if (currentRDS->GetInfoNews().size())
+ {
+ if (!m_LabelInfoNewsPresent)
+ {
+ spin->AddLabel(g_localizeStrings.Get(29916), INFO_NEWS);
+ m_LabelInfoNewsPresent = true;
+ m_InfoPresent = true;
+ }
+
+ if (m_LabelInfoNews != currentRDS->GetInfoNews())
+ {
+ spin->SetValue(INFO_NEWS);
+ m_LabelInfoNews = currentRDS->GetInfoNews();
+ textbox->SetInfo(m_LabelInfoNews);
+ }
+ }
+ if (currentRDS->GetInfoNewsLocal().size())
+ {
+ if (!m_LabelInfoNewsLocalPresent)
+ {
+ spin->AddLabel(g_localizeStrings.Get(29917), INFO_NEWS_LOCAL);
+ m_LabelInfoNewsLocalPresent = true;
+ m_InfoPresent = true;
+ }
+
+ if (m_LabelInfoNewsLocal != currentRDS->GetInfoNewsLocal())
+ {
+ spin->SetValue(INFO_NEWS_LOCAL);
+ m_LabelInfoNewsLocal = currentRDS->GetInfoNewsLocal();
+ textbox->SetInfo(m_LabelInfoNewsLocal);
+ }
+ }
+ if (currentRDS->GetInfoSport().size())
+ {
+ if (!m_LabelInfoSportPresent)
+ {
+ spin->AddLabel(g_localizeStrings.Get(29918), INFO_SPORT);
+ m_LabelInfoSportPresent = true;
+ m_InfoPresent = true;
+ }
+
+ if (m_LabelInfoSport != currentRDS->GetInfoSport())
+ {
+ spin->SetValue(INFO_SPORT);
+ m_LabelInfoSport = currentRDS->GetInfoSport();
+ textbox->SetInfo(m_LabelInfoSport);
+ }
+ }
+ if (currentRDS->GetInfoWeather().size())
+ {
+ if (!m_LabelInfoWeatherPresent)
+ {
+ spin->AddLabel(g_localizeStrings.Get(400), INFO_WEATHER);
+ m_LabelInfoWeatherPresent = true;
+ m_InfoPresent = true;
+ }
+
+ if (m_LabelInfoWeather != currentRDS->GetInfoWeather())
+ {
+ spin->SetValue(INFO_WEATHER);
+ m_LabelInfoWeather = currentRDS->GetInfoWeather();
+ textbox->SetInfo(m_LabelInfoWeather);
+ }
+ }
+ if (currentRDS->GetInfoLottery().size())
+ {
+ if (!m_LabelInfoLotteryPresent)
+ {
+ spin->AddLabel(g_localizeStrings.Get(29919), INFO_LOTTERY);
+ m_LabelInfoLotteryPresent = true;
+ m_InfoPresent = true;
+ }
+
+ if (m_LabelInfoLottery != currentRDS->GetInfoLottery())
+ {
+ spin->SetValue(INFO_LOTTERY);
+ m_LabelInfoLottery = currentRDS->GetInfoLottery();
+ textbox->SetInfo(m_LabelInfoLottery);
+ }
+ }
+ if (currentRDS->GetInfoStock().size())
+ {
+ if (!m_LabelInfoStockPresent)
+ {
+ spin->AddLabel(g_localizeStrings.Get(29920), INFO_STOCK);
+ m_LabelInfoStockPresent = true;
+ m_InfoPresent = true;
+ }
+
+ if (m_LabelInfoStock != currentRDS->GetInfoStock())
+ {
+ spin->SetValue(INFO_STOCK);
+ m_LabelInfoStock = currentRDS->GetInfoStock();
+ textbox->SetInfo(m_LabelInfoStock);
+ }
+ }
+ if (currentRDS->GetInfoOther().size())
+ {
+ if (!m_LabelInfoOtherPresent)
+ {
+ spin->AddLabel(g_localizeStrings.Get(29921), INFO_OTHER);
+ m_LabelInfoOtherPresent = true;
+ m_InfoPresent = true;
+ }
+
+ if (m_LabelInfoOther != currentRDS->GetInfoOther())
+ {
+ spin->SetValue(INFO_OTHER);
+ m_LabelInfoOther = currentRDS->GetInfoOther();
+ textbox->SetInfo(m_LabelInfoOther);
+ }
+ }
+ if (currentRDS->GetInfoCinema().size())
+ {
+ if (!m_LabelInfoCinemaPresent)
+ {
+ spin->AddLabel(g_localizeStrings.Get(19602), INFO_CINEMA);
+ m_LabelInfoCinemaPresent = true;
+ m_InfoPresent = true;
+ }
+
+ if (m_LabelInfoCinema != currentRDS->GetInfoCinema())
+ {
+ spin->SetValue(INFO_CINEMA);
+ m_LabelInfoCinema = currentRDS->GetInfoCinema();
+ textbox->SetInfo(m_LabelInfoCinema);
+ }
+ }
+ if (currentRDS->GetInfoHoroscope().size())
+ {
+ if (!m_LabelInfoHoroscopePresent)
+ {
+ spin->AddLabel(g_localizeStrings.Get(29922), INFO_HOROSCOPE);
+ m_LabelInfoHoroscopePresent = true;
+ m_InfoPresent = true;
+ }
+
+ if (m_LabelInfoHoroscope != currentRDS->GetInfoHoroscope())
+ {
+ spin->SetValue(INFO_HOROSCOPE);
+ m_LabelInfoHoroscope = currentRDS->GetInfoHoroscope();
+ textbox->SetInfo(m_LabelInfoHoroscope);
+ }
+ }
+ if (m_InfoPresent)
+ SET_CONTROL_VISIBLE(CONTROL_INFO_LIST);
+ else
+ SET_CONTROL_HIDDEN(CONTROL_INFO_LIST);
+ }
+ }
+
+ return CGUIDialog::OnMessage(message);
+}
+
+void CGUIDialogPVRRadioRDSInfo::OnInitWindow()
+{
+ // call init
+ CGUIDialog::OnInitWindow();
+
+ m_LabelInfoNewsPresent = false;
+ m_LabelInfoNewsLocalPresent = false;
+ m_LabelInfoSportPresent = false;
+ m_LabelInfoWeatherPresent = false;
+ m_LabelInfoLotteryPresent = false;
+ m_LabelInfoStockPresent = false;
+ m_LabelInfoOtherPresent = false;
+ m_LabelInfoHoroscopePresent = false;
+ m_LabelInfoCinemaPresent = false;
+ m_InfoPresent = false;
+
+ PVR::CPVRRadioRDSInfoTagPtr currentRDS = g_application.CurrentFileItem().GetPVRRadioRDSInfoTag();
+
+ CGUISpinControl *spin = (CGUISpinControl *)GetControl(SPIN_CONTROL_INFO);
+ if (!spin) return;
+ spin->Clear();
+
+ CGUITextBox *textbox = (CGUITextBox *)GetControl(TEXT_INFO);
+ if (!textbox) return;
+
+ if (currentRDS->GetInfoNews().size())
+ {
+ spin->AddLabel(g_localizeStrings.Get(29916), INFO_NEWS);
+ textbox->SetInfo(currentRDS->GetInfoNews());
+ spin->SetValue(INFO_NEWS);
+ m_LabelInfoNewsPresent = true;
+ m_InfoPresent = true;
+ }
+ if (currentRDS->GetInfoNewsLocal().size())
+ {
+ spin->AddLabel(g_localizeStrings.Get(29917), INFO_NEWS_LOCAL);
+ if (!m_InfoPresent)
+ {
+ textbox->SetInfo(currentRDS->GetInfoNewsLocal());
+ spin->SetValue(INFO_NEWS_LOCAL);
+ m_LabelInfoNewsLocalPresent = true;
+ m_InfoPresent = true;
+ }
+ }
+ if (currentRDS->GetInfoSport().size())
+ {
+ spin->AddLabel(g_localizeStrings.Get(29918), INFO_SPORT);
+ if (!m_InfoPresent)
+ {
+ textbox->SetInfo(currentRDS->GetInfoSport());
+ spin->SetValue(INFO_SPORT);
+ m_LabelInfoSportPresent = true;
+ m_InfoPresent = true;
+ }
+ }
+ if (currentRDS->GetInfoWeather().size())
+ {
+ spin->AddLabel(g_localizeStrings.Get(400), INFO_WEATHER);
+ if (!m_InfoPresent)
+ {
+ textbox->SetInfo(currentRDS->GetInfoWeather());
+ spin->SetValue(INFO_WEATHER);
+ m_LabelInfoWeatherPresent = true;
+ m_InfoPresent = true;
+ }
+ }
+ if (currentRDS->GetInfoLottery().size())
+ {
+ spin->AddLabel(g_localizeStrings.Get(29919), INFO_LOTTERY);
+ if (!m_InfoPresent)
+ {
+ textbox->SetInfo(currentRDS->GetInfoLottery());
+ spin->SetValue(INFO_LOTTERY);
+ m_LabelInfoLotteryPresent = true;
+ m_InfoPresent = true;
+ }
+ }
+ if (currentRDS->GetInfoStock().size())
+ {
+ spin->AddLabel(g_localizeStrings.Get(29920), INFO_STOCK);
+ if (!m_InfoPresent)
+ {
+ textbox->SetInfo(currentRDS->GetInfoStock());
+ spin->SetValue(INFO_STOCK);
+ m_LabelInfoStockPresent = true;
+ m_InfoPresent = true;
+ }
+ }
+ if (currentRDS->GetInfoOther().size())
+ {
+ spin->AddLabel(g_localizeStrings.Get(29921), INFO_OTHER);
+ if (!m_InfoPresent)
+ {
+ textbox->SetInfo(currentRDS->GetInfoOther());
+ spin->SetValue(INFO_OTHER);
+ m_LabelInfoOtherPresent = true;
+ m_InfoPresent = true;
+ }
+ }
+ if (currentRDS->GetInfoCinema().size())
+ {
+ spin->AddLabel(g_localizeStrings.Get(19602), INFO_CINEMA);
+ if (!m_InfoPresent)
+ {
+ textbox->SetInfo(currentRDS->GetInfoCinema());
+ spin->SetValue(INFO_CINEMA);
+ m_LabelInfoCinemaPresent = true;
+ m_InfoPresent = true;
+ }
+ }
+ if (currentRDS->GetInfoHoroscope().size())
+ {
+ spin->AddLabel(g_localizeStrings.Get(29922), INFO_HOROSCOPE);
+ if (!m_InfoPresent)
+ {
+ textbox->SetInfo(currentRDS->GetInfoHoroscope());
+ spin->SetValue(INFO_HOROSCOPE);
+ m_LabelInfoHoroscopePresent = true;
+ m_InfoPresent = true;
+ }
+ }
+
+ if (m_InfoPresent)
+ SET_CONTROL_VISIBLE(CONTROL_INFO_LIST);
+ else
+ SET_CONTROL_HIDDEN(CONTROL_INFO_LIST);
+}
+
+void CGUIDialogPVRRadioRDSInfo::OnDeinitWindow(int nextWindowID)
+{
+ CGUIDialog::OnDeinitWindow(nextWindowID);
+}
+
+void CGUIDialogPVRRadioRDSInfo::SetRadioRDS(const CFileItem *item)
+{
+ *m_rdsItem = *item;
+}
+
+CFileItemPtr CGUIDialogPVRRadioRDSInfo::GetCurrentListItem(int offset)
+{
+ return m_rdsItem;
+}
diff --git a/xbmc/pvr/dialogs/GUIDialogPVRRadioRDSInfo.h b/xbmc/pvr/dialogs/GUIDialogPVRRadioRDSInfo.h
new file mode 100644
index 0000000000..e451f5566a
--- /dev/null
+++ b/xbmc/pvr/dialogs/GUIDialogPVRRadioRDSInfo.h
@@ -0,0 +1,72 @@
+#pragma once
+/*
+ * Copyright (C) 2012-2015 Team KODI
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with KODI; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "guilib/GUIDialog.h"
+
+namespace PVR
+{
+ class CGUIDialogPVRRadioRDSInfo : public CGUIDialog
+ {
+ public:
+ CGUIDialogPVRRadioRDSInfo(void);
+ virtual ~CGUIDialogPVRRadioRDSInfo(void) {}
+ virtual bool OnMessage(CGUIMessage& message);
+ virtual bool HasListItems() const { return true; };
+ virtual CFileItemPtr GetCurrentListItem(int offset = 0);
+
+ void SetRadioRDS(const CFileItem *item);
+
+ protected:
+ virtual void OnInitWindow();
+ virtual void OnDeinitWindow(int nextWindowID);
+
+ CFileItemPtr m_rdsItem;
+
+ private:
+ bool m_InfoPresent;
+ bool m_LabelInfoNewsPresent;
+ std::string m_LabelInfoNews;
+
+ bool m_LabelInfoNewsLocalPresent;
+ std::string m_LabelInfoNewsLocal;
+
+ bool m_LabelInfoWeatherPresent;
+ std::string m_LabelInfoWeather;
+
+ bool m_LabelInfoLotteryPresent;
+ std::string m_LabelInfoLottery;
+
+ bool m_LabelInfoSportPresent;
+ std::string m_LabelInfoSport;
+
+ bool m_LabelInfoStockPresent;
+ std::string m_LabelInfoStock;
+
+ bool m_LabelInfoOtherPresent;
+ std::string m_LabelInfoOther;
+
+ bool m_LabelInfoCinemaPresent;
+ std::string m_LabelInfoCinema;
+
+ bool m_LabelInfoHoroscopePresent;
+ std::string m_LabelInfoHoroscope;
+ };
+}
diff --git a/xbmc/pvr/dialogs/Makefile b/xbmc/pvr/dialogs/Makefile
index b20f20bf07..b9d33f9934 100644
--- a/xbmc/pvr/dialogs/Makefile
+++ b/xbmc/pvr/dialogs/Makefile
@@ -4,6 +4,7 @@ SRCS=GUIDialogPVRChannelManager.cpp \
GUIDialogPVRGuideInfo.cpp \
GUIDialogPVRGuideOSD.cpp \
GUIDialogPVRGuideSearch.cpp \
+ GUIDialogPVRRadioRDSInfo.cpp \
GUIDialogPVRRecordingInfo.cpp \
GUIDialogPVRTimerSettings.cpp
diff --git a/xbmc/pvr/timers/PVRTimerInfoTag.cpp b/xbmc/pvr/timers/PVRTimerInfoTag.cpp
index 9fb6bba435..5bcaef27f7 100644
--- a/xbmc/pvr/timers/PVRTimerInfoTag.cpp
+++ b/xbmc/pvr/timers/PVRTimerInfoTag.cpp
@@ -20,7 +20,8 @@
#include "dialogs/GUIDialogKaiToast.h"
#include "dialogs/GUIDialogOK.h"
-#include "dialogs/GUIDialogYesNo.h"
+#include "messaging/ApplicationMessenger.h"
+#include "messaging/helpers/DialogHelper.h"
#include "settings/AdvancedSettings.h"
#include "settings/Settings.h"
#include "utils/log.h"
@@ -37,6 +38,9 @@
using namespace PVR;
using namespace EPG;
+using namespace KODI::MESSAGING;
+
+using KODI::MESSAGING::HELPERS::DialogResponse;
CPVRTimerInfoTag::CPVRTimerInfoTag(bool bRadio /* = false */) :
m_strTitle(g_localizeStrings.Get(19056)), // New Timer
@@ -528,7 +532,7 @@ bool CPVRTimerInfoTag::DeleteFromClient(bool bForce /* = false */ , bool bDelete
if (error == PVR_ERROR_RECORDING_RUNNING)
{
// recording running. ask the user if it should be deleted anyway
- if (!CGUIDialogYesNo::ShowAndGetInput(CVariant{122}, CVariant{19122}))
+ if (HELPERS::ShowYesNoDialogText(CVariant{122}, CVariant{19122}) != DialogResponse::YES)
return false;
error = g_PVRClients->DeleteTimer(*this, true, bDeleteSchedule);
diff --git a/xbmc/pvr/timers/PVRTimers.cpp b/xbmc/pvr/timers/PVRTimers.cpp
index 8d37799c42..6fd9bbc928 100644
--- a/xbmc/pvr/timers/PVRTimers.cpp
+++ b/xbmc/pvr/timers/PVRTimers.cpp
@@ -636,7 +636,7 @@ CPVRTimerInfoTagPtr CPVRTimers::GetByClient(int iClientId, unsigned int iClientT
for (VecTimerInfoTag::const_iterator timerIt = it->second->begin(); timerIt != it->second->end(); ++timerIt)
{
if ((*timerIt)->m_iClientId == iClientId &&
- (*timerIt)->m_iClientIndex == iClientTimerId)
+ (*timerIt)->m_iClientIndex == static_cast<int>(iClientTimerId))
return *timerIt;
}
}
diff --git a/xbmc/settings/DisplaySettings.cpp b/xbmc/settings/DisplaySettings.cpp
index ba608d0456..12c4859e3e 100644
--- a/xbmc/settings/DisplaySettings.cpp
+++ b/xbmc/settings/DisplaySettings.cpp
@@ -27,11 +27,12 @@
#include <float.h>
#include "DisplaySettings.h"
-#include "dialogs/GUIDialogYesNo.h"
#include "guilib/GraphicContext.h"
#include "guilib/gui3d.h"
#include "guilib/LocalizeStrings.h"
#include "guilib/StereoscopicsManager.h"
+#include "messaging/ApplicationMessenger.h"
+#include "messaging/helpers/DialogHelper.h"
#include "settings/AdvancedSettings.h"
#include "settings/lib/Setting.h"
#include "settings/Settings.h"
@@ -42,6 +43,10 @@
#include "utils/XMLUtils.h"
#include "windowing/WindowingFactory.h"
+using namespace KODI::MESSAGING;
+
+using KODI::MESSAGING::HELPERS::DialogResponse;
+
// 0.1 second increments
#define MAX_REFRESH_CHANGE_DELAY 200
@@ -257,8 +262,8 @@ bool CDisplaySettings::OnSettingChanging(const CSetting *setting)
{
if (!m_resolutionChangeAborted)
{
- bool cancelled = false;
- if (!CGUIDialogYesNo::ShowAndGetInput(CVariant{13110}, CVariant{13111}, cancelled, CVariant{""}, CVariant{""}, 10000))
+ if (HELPERS::ShowYesNoDialogText(CVariant{13110}, CVariant{13111}, CVariant{""}, CVariant{""}, 10000) !=
+ DialogResponse::YES)
{
m_resolutionChangeAborted = true;
return false;
@@ -278,8 +283,8 @@ bool CDisplaySettings::OnSettingChanging(const CSetting *setting)
if (!m_resolutionChangeAborted)
{
- bool cancelled = false;
- if (!CGUIDialogYesNo::ShowAndGetInput(CVariant{13110}, CVariant{13111}, cancelled, CVariant{""}, CVariant{""}, 10000))
+ if (HELPERS::ShowYesNoDialogText(CVariant{13110}, CVariant{13111}, CVariant{""}, CVariant{""}, 10000) !=
+ DialogResponse::YES)
{
m_resolutionChangeAborted = true;
return false;
diff --git a/xbmc/settings/MediaSettings.cpp b/xbmc/settings/MediaSettings.cpp
index 5cef1a0208..abf5714713 100644
--- a/xbmc/settings/MediaSettings.cpp
+++ b/xbmc/settings/MediaSettings.cpp
@@ -27,9 +27,10 @@
#include "PlayListPlayer.h"
#include "dialogs/GUIDialogContextMenu.h"
#include "dialogs/GUIDialogFileBrowser.h"
-#include "dialogs/GUIDialogYesNo.h"
#include "interfaces/Builtins.h"
#include "music/MusicDatabase.h"
+#include "messaging/ApplicationMessenger.h"
+#include "messaging/helpers/DialogHelper.h"
#include "profiles/ProfilesManager.h"
#include "settings/lib/Setting.h"
#include "settings/Settings.h"
@@ -43,6 +44,10 @@
#include "video/VideoDatabase.h"
#include "cores/AudioEngine/DSPAddons/ActiveAEDSP.h"
+using namespace KODI::MESSAGING;
+
+using KODI::MESSAGING::HELPERS::DialogResponse;
+
CMediaSettings::CMediaSettings()
{
m_watchedModes["files"] = WatchedModeAll;
@@ -359,7 +364,7 @@ void CMediaSettings::OnSettingAction(const CSetting *setting)
}
else if (settingId == CSettings::SETTING_MUSICLIBRARY_CLEANUP)
{
- if (CGUIDialogYesNo::ShowAndGetInput(CVariant{313}, CVariant{333}))
+ if (HELPERS::ShowYesNoDialogText(CVariant{313}, CVariant{333}) == DialogResponse::YES)
g_application.StartMusicCleanup(true);
}
else if (settingId == CSettings::SETTING_MUSICLIBRARY_EXPORT)
@@ -382,7 +387,7 @@ void CMediaSettings::OnSettingAction(const CSetting *setting)
}
else if (settingId == CSettings::SETTING_VIDEOLIBRARY_CLEANUP)
{
- if (CGUIDialogYesNo::ShowAndGetInput(CVariant{313}, CVariant{333}))
+ if (HELPERS::ShowYesNoDialogText(CVariant{313}, CVariant{333}) == DialogResponse::YES)
g_application.StartVideoCleanup(true);
}
else if (settingId == CSettings::SETTING_VIDEOLIBRARY_EXPORT)
diff --git a/xbmc/settings/SettingAddon.cpp b/xbmc/settings/SettingAddon.cpp
index e05f427316..490c0607ea 100644
--- a/xbmc/settings/SettingAddon.cpp
+++ b/xbmc/settings/SettingAddon.cpp
@@ -38,7 +38,7 @@ CSettingAddon::CSettingAddon(const std::string &id, int label, const std::string
CSettingAddon::CSettingAddon(const std::string &id, const CSettingAddon &setting)
: CSettingString(id, setting)
{
- copy(setting);
+ copyaddontype(setting);
}
CSetting* CSettingAddon::Clone(const std::string &id) const
@@ -83,7 +83,7 @@ bool CSettingAddon::Deserialize(const TiXmlNode *node, bool update /* = false */
return true;
}
-void CSettingAddon::copy(const CSettingAddon &setting)
+void CSettingAddon::copyaddontype(const CSettingAddon &setting)
{
CSettingString::Copy(setting);
diff --git a/xbmc/settings/SettingAddon.h b/xbmc/settings/SettingAddon.h
index a84eea77f1..417968b8b3 100644
--- a/xbmc/settings/SettingAddon.h
+++ b/xbmc/settings/SettingAddon.h
@@ -38,7 +38,7 @@ public:
void SetAddonType(ADDON::TYPE addonType) { m_addonType = addonType; }
private:
- void copy(const CSettingAddon &setting);
+ void copyaddontype(const CSettingAddon &setting);
ADDON::TYPE m_addonType;
};
diff --git a/xbmc/system.h b/xbmc/system.h
index c97785c573..15e3563b3a 100644
--- a/xbmc/system.h
+++ b/xbmc/system.h
@@ -84,6 +84,10 @@
#define HAS_MDNS_EMBEDDED
#endif
+#if defined(HAVE_LIBGIF)
+ #define HAS_GIFLIB
+#endif
+
/**********************
* Non-free Components
**********************/
@@ -124,6 +128,7 @@
#define HAVE_LIBVORBISENC
#define HAS_MYSQL
#define HAS_UPNP
+#define HAS_GIFLIB
#define DECLARE_UNUSED(a,b) a b;
#endif
diff --git a/xbmc/threads/LockFree.cpp b/xbmc/threads/LockFree.cpp
deleted file mode 100644
index d0ae78a6b7..0000000000
--- a/xbmc/threads/LockFree.cpp
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (C) 2005-2013 Team XBMC
- * http://xbmc.org
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with XBMC; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifdef __ppc__
-#pragma GCC optimization_level 0
-#endif
-
-#include "LockFree.h"
-#include <stdlib.h>
-
-///////////////////////////////////////////////////////////////////////////
-// Fast stack implementation
-// NOTE: non-locking only on systems that support atomic cas2 operations
-///////////////////////////////////////////////////////////////////////////
-void lf_stack_init(lf_stack* pStack)
-{
- pStack->top.ptr = NULL;
- pStack->count = 0;
-}
-
-void lf_stack_push(lf_stack* pStack, lf_node* pNode)
-{
- atomic_ptr top, newTop;
- do
- {
- top = pStack->top;
- pNode->next.ptr = top.ptr; // Link in the new node
- newTop.ptr = pNode;
-#if defined(__ppc__) || defined(__powerpc__) || defined(__arm__)
- } while(cas((long*)&pStack->top, atomic_ptr_to_long(top), atomic_ptr_to_long(newTop)) != atomic_ptr_to_long(top));
-#else
- newTop.version = top.version + 1;
- } while(cas2((long long*)&pStack->top, atomic_ptr_to_long_long(top), atomic_ptr_to_long_long(newTop)) != atomic_ptr_to_long_long(top));
-#endif
- AtomicIncrement(&pStack->count);
-}
-
-lf_node* lf_stack_pop(lf_stack* pStack)
-{
- atomic_ptr top, newTop;
- do
- {
- top = pStack->top;
- if (top.ptr == NULL)
- return NULL;
- newTop.ptr = ((lf_node*)top.ptr)->next.ptr; // Unlink the current top node
-#if defined(__ppc__) || defined(__powerpc__) || defined(__arm__)
- } while(cas((long*)&pStack->top, atomic_ptr_to_long(top), atomic_ptr_to_long(newTop)) != atomic_ptr_to_long(top));
-#else
- newTop.version = top.version + 1;
- } while(cas2((long long*)&pStack->top, atomic_ptr_to_long_long(top), atomic_ptr_to_long_long(newTop)) != atomic_ptr_to_long_long(top));
-#endif
- AtomicDecrement(&pStack->count);
- return (lf_node*)top.ptr;
-}
-
-///////////////////////////////////////////////////////////////////////////
-// Fast heap implementation
-// NOTE: non-locking only on systems that support atomic cas2 operations
-///////////////////////////////////////////////////////////////////////////
-// TODO: Implement auto-shrink based on chunk reference counts
-
-// TODO: Read the page size from the OS or allow caller to specify
-// Maybe have a minimum number of blocks...
-#define MIN_ALLOC 4096
-
-void lf_heap_init(lf_heap* pHeap, size_t blockSize, size_t initialSize /*= 0*/)
-{
- pHeap->alloc_lock = 0; // Initialize the allocation lock
- pHeap->top_chunk = NULL;
-
- lf_stack_init(&pHeap->free_list); // Initialize the free-list stack
-
- // Perform a few sanity checks on the parameters
- if (blockSize < sizeof(lf_node)) // Make sure we have blocks big enough to store in the free-list
- blockSize = sizeof(lf_node);
- pHeap->block_size = blockSize;
-
- if (initialSize < 10 * blockSize)
- initialSize = 10 * blockSize; // TODO: This should be more intelligent
-
- lf_heap_grow(pHeap, initialSize); // Allocate the first chunk
-}
-
-void lf_heap_grow(lf_heap* pHeap, size_t size /*= 0*/)
-{
-
- long blockSize = pHeap->block_size; // This has already been checked for sanity
- if (!size || size < MIN_ALLOC - sizeof(lf_heap_chunk)) // Allocate at least one page from the OS (TODO: Try valloc)
- size = MIN_ALLOC - sizeof(lf_heap_chunk);
- unsigned int blockCount = size / blockSize;
- if (size % blockSize) // maxe sure we have complete blocks
- size = blockSize * ++blockCount;
-
- // Allocate the first chunk from the general heap and link it into the chunk list
- long mallocSize = size + sizeof(lf_heap_chunk);
- lf_heap_chunk* pChunk = (lf_heap_chunk*) malloc(mallocSize);
- if (!pChunk)
- return;
- pChunk->size = mallocSize;
- SPINLOCK_ACQUIRE(pHeap->alloc_lock); // Lock the chunk list. Contention here is VERY unlikely, so use the simplest possible sync mechanism.
- pChunk->next = pHeap->top_chunk;
- pHeap->top_chunk = pChunk; // Link it into the list
- SPINLOCK_RELEASE(pHeap->alloc_lock); // The list is now consistent
-
- // Add all blocks to the free-list
- unsigned char* pBlock = (unsigned char*)pChunk + sizeof(lf_heap_chunk);
- for ( unsigned int block = 0; block < blockCount; block++)
- {
- lf_stack_push(&pHeap->free_list, (lf_node*)pBlock);
- pBlock += blockSize;
- }
-}
-
-void lf_heap_deinit(lf_heap* pHeap)
-{
- // Free all allocated chunks
- lf_heap_chunk* pNext;
- for(lf_heap_chunk* pChunk = pHeap->top_chunk; pChunk; pChunk = pNext)
- {
- pNext = pChunk->next;
- free(pChunk);
- }
-}
-
-void* lf_heap_alloc(lf_heap* pHeap)
-{
- void * p = lf_stack_pop(&pHeap->free_list);
- if (!p)
- {
- lf_heap_grow(pHeap, 0);
- // TODO: should we just call in recursively?
- return lf_stack_pop(&pHeap->free_list); // If growing didn't help, something is wrong (or someone else took them all REALLY fast)
- }
- return p;
-}
-
-void lf_heap_free(lf_heap* pHeap, void* p)
-{
- if (!p) // Allow for NULL to pass safely
- return;
- lf_stack_push(&pHeap->free_list, (lf_node*)p); // Return the block to the free list
-}
-
-///////////////////////////////////////////////////////////////////////////
-// Lock-free queue
-///////////////////////////////////////////////////////////////////////////
-void lf_queue_init(lf_queue* pQueue)
-{
- pQueue->len = 0;
- lf_heap_init(&pQueue->node_heap, sizeof(lf_queue_node)); // Intialize the node heap
- lf_queue_node* pNode = lf_queue_new_node(pQueue); // Create the 'empty' node
- pNode->next.ptr = NULL;
- pNode->value = (void*)0xdeadf00d;
- pQueue->head.ptr = pQueue->tail.ptr = pNode;
-}
-
-void lf_queue_deinit(lf_queue* pQueue)
-{
- lf_heap_deinit(&pQueue->node_heap); // Clean up the node heap
-}
-
-// TODO: template-ize
-void lf_queue_enqueue(lf_queue* pQueue, void* value)
-{
- lf_queue_node* pNode = lf_queue_new_node(pQueue); // Get a container
- pNode->value = value;
- pNode->next.ptr = NULL;
- atomic_ptr tail, next, node;
- do
- {
- tail = pQueue->tail;
- next = ((lf_queue_node*)tail.ptr)->next;
-#if defined(__ppc__) || defined(__powerpc__) || defined(__arm__)
- if (atomic_ptr_to_long(tail) == atomic_ptr_to_long(pQueue->tail)) // Check consistency
-#else
- if (atomic_ptr_to_long_long(tail) == atomic_ptr_to_long_long(pQueue->tail)) // Check consistency
-#endif
- {
- if (next.ptr == NULL) // Was tail pointing to the last node?
- {
- node.ptr = pNode;
-#if defined(__ppc__) || defined(__powerpc__) || defined(__arm__)
- if (cas((long*)&((lf_queue_node*)tail.ptr)->next, atomic_ptr_to_long(next), atomic_ptr_to_long(node)) == atomic_ptr_to_long(next)) // Try to link node at end
-#else
- node.version = next.version + 1;
- if (cas2((long long*)&((lf_queue_node*)tail.ptr)->next, atomic_ptr_to_long_long(next), atomic_ptr_to_long_long(node)) == atomic_ptr_to_long_long(next)) // Try to link node at end
-#endif
- break; // enqueue is done.
- }
- else // tail was lagging, try to help...
- {
- node.ptr = next.ptr;
-#if defined(__ppc__) || defined(__powerpc__) || defined(__arm__)
- cas((long*)&pQueue->tail, atomic_ptr_to_long(tail), atomic_ptr_to_long(node)); // We don't care if we are successful or not
-#else
- node.version = tail.version + 1;
- cas2((long long*)&pQueue->tail, atomic_ptr_to_long_long(tail), atomic_ptr_to_long_long(node)); // We don't care if we are successful or not
-#endif
- }
- }
- } while (true); // Keep trying until the enqueue is done
- node.ptr = pNode;
-#if defined(__ppc__) || defined(__powerpc__) || defined(__arm__)
- cas((long*)&pQueue->tail, atomic_ptr_to_long(tail), atomic_ptr_to_long(node)); // Try to swing the tail to the new node
-#else
- node.version = tail.version + 1;
- cas2((long long*)&pQueue->tail, atomic_ptr_to_long_long(tail), atomic_ptr_to_long_long(node)); // Try to swing the tail to the new node
-#endif
- AtomicIncrement(&pQueue->len);
-}
-
-// TODO: template-ize
-void* lf_queue_dequeue(lf_queue* pQueue)
-{
- atomic_ptr head, tail, next, node;
- void* pVal = NULL;
- do
- {
- head = pQueue->head;
- tail = pQueue->tail;
- next = ((lf_queue_node*)head.ptr)->next;
-#if defined(__ppc__) || defined(__powerpc__) || defined(__arm__)
- if (atomic_ptr_to_long(head) == atomic_ptr_to_long(pQueue->head)) // Check consistency
-#else
- if (atomic_ptr_to_long_long(head) == atomic_ptr_to_long_long(pQueue->head)) // Check consistency
-#endif
- {
- if (head.ptr == tail.ptr) // Queue is empty or tail is lagging
- {
- if (next.ptr == NULL) // Queue is empty
- return NULL;
- node.ptr = next.ptr;
-#if defined(__ppc__) || defined(__powerpc__) || defined(__arm__)
- cas((long*)&pQueue->tail, atomic_ptr_to_long(tail), atomic_ptr_to_long(node)); // Tail is lagging. Try to advance it.
-#else
- node.version = tail.version + 1;
- cas2((long long*)&pQueue->tail, atomic_ptr_to_long_long(tail), atomic_ptr_to_long_long(node)); // Tail is lagging. Try to advance it.
-#endif
- }
- else // Tail is consistent. No need to deal with it.
- {
- pVal = ((lf_queue_node*)next.ptr)->value;
- node.ptr = next.ptr;
-#if defined(__ppc__) || defined(__powerpc__) || defined(__arm__)
- if (cas((long*)&pQueue->head, atomic_ptr_to_long(head), atomic_ptr_to_long(node)) == atomic_ptr_to_long(head))
-#else
- node.version = head.version + 1;
- if (cas2((long long*)&pQueue->head, atomic_ptr_to_long_long(head), atomic_ptr_to_long_long(node)) == atomic_ptr_to_long_long(head))
-#endif
- break; // Dequeue is done
- }
- }
- } while (true); // Keep trying until the dequeue is done or the queue empties
- lf_queue_free_node(pQueue, head.ptr);
- AtomicDecrement(&pQueue->len);
- return pVal;
-}
-
-#ifdef __ppc__
-#pragma GCC optimization_level reset
-#endif
diff --git a/xbmc/threads/LockFree.h b/xbmc/threads/LockFree.h
deleted file mode 100644
index d440eaaf02..0000000000
--- a/xbmc/threads/LockFree.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2005-2013 Team XBMC
- * http://xbmc.org
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with XBMC; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef __LOCK_FREE_H__
-#define __LOCK_FREE_H__
-
-#include <cstring>
-#include "Atomics.h"
-
-#define SPINLOCK_ACQUIRE(l) while(cas(&l, 0, 1)) {}
-#define SPINLOCK_RELEASE(l) l = 0
-
-// A unique-valued pointer. Version is incremented with each write.
-union atomic_ptr
-{
-#if !defined(__ppc__) && !defined(__powerpc__) && !defined(__arm__)
- long long d;
- struct {
- void* ptr;
- long version;
- };
-#else
- long d;
- struct {
- void* ptr;
- };
-#endif
-};
-
-#if defined(__ppc__) || defined(__powerpc__) || defined(__arm__)
- #define atomic_ptr_to_long(p) (long) *((long*)&p)
-#else
- // This is ugly but correct as long as sizeof(void*) == sizeof(long)...
- #define atomic_ptr_to_long_long(p) (long long) *((long long*)&p)
-#endif
-
-struct lf_node
-{
- atomic_ptr next;
-};
-
-///////////////////////////////////////////////////////////////////////////
-// Fast Stack
-///////////////////////////////////////////////////////////////////////////
-
-
-struct lf_stack
-{
- atomic_ptr top;
- long count;
-};
-
-
-void lf_stack_init(lf_stack* pStack);
-void lf_stack_push(lf_stack* pStack, lf_node* pNode);
-lf_node* lf_stack_pop(lf_stack* pStack);
-
-///////////////////////////////////////////////////////////////////////////
-// Fast Heap for Fixed-size Blocks
-///////////////////////////////////////////////////////////////////////////
-struct lf_heap_chunk
-{
- lf_heap_chunk* next;
- long size;
-};
-
-struct lf_heap
-{
- lf_stack free_list;
- long alloc_lock;
- lf_heap_chunk* top_chunk;
- long block_size;
-};
-
-
-void lf_heap_init(lf_heap* pHeap, size_t blockSize, size_t initialSize = 0);
-void lf_heap_grow(lf_heap* pHeap, size_t size = 0);
-void lf_heap_deinit(lf_heap* pHeap);
-void* lf_heap_alloc(lf_heap* pHeap);
-void lf_heap_free(lf_heap* pHeap, void* p);
-
-///////////////////////////////////////////////////////////////////////////
-// Lock-free queue
-///////////////////////////////////////////////////////////////////////////
-struct lf_queue_node
-{
- atomic_ptr next;
- void* value; // TODO: Convert to a template
-};
-
-struct lf_queue
-{
- atomic_ptr head;
- atomic_ptr tail;
- lf_heap node_heap;
- long len;
-};
-
-#define lf_queue_new_node(q) (lf_queue_node*)lf_heap_alloc(&q->node_heap)
-#define lf_queue_free_node(q,n) lf_heap_free(&q->node_heap, n)
-
-void lf_queue_init(lf_queue* pQueue);
-void lf_queue_deinit(lf_queue* pQueue);
-void lf_queue_enqueue(lf_queue* pQueue, void* pVal);
-void* lf_queue_dequeue(lf_queue* pQueue);
-
-#endif
diff --git a/xbmc/threads/Makefile b/xbmc/threads/Makefile
index d0bd2951d7..fc2c02d6f1 100644
--- a/xbmc/threads/Makefile
+++ b/xbmc/threads/Makefile
@@ -1,6 +1,5 @@
SRCS=Atomics.cpp \
Event.cpp \
- LockFree.cpp \
Thread.cpp \
Timer.cpp \
SystemClock.cpp \
diff --git a/xbmc/utils/AutoPtrHandle.h b/xbmc/utils/AutoPtrHandle.h
index 8a3b4dcf9e..945e59cc78 100644
--- a/xbmc/utils/AutoPtrHandle.h
+++ b/xbmc/utils/AutoPtrHandle.h
@@ -65,46 +65,4 @@ protected:
SOCKET m_hSocket;
};
-/*
- * This template class is very similar to the standard "unique_ptr", but it is
- * used for *array* pointers rather than *object* pointers, i.e. the pointer
- * passed to it must have been allocated with "new[]", and "auto_aptr" will
- * delete it with "delete[]".
- *
- * Class released under GPL and was taken from:
- * http://userpage.fu-berlin.de/~mbayer/tools/html2text.html
- */
-template <class T>
-class auto_aptr
-{
-
-public:
-
- // Constructor/copy/destroy
-
- explicit auto_aptr(T *x = 0) : p(x) {}
- auto_aptr(const auto_aptr<T> &x) : p(x.p) { ((auto_aptr<T> *) &x)->p = 0; }
- auto_aptr<T>& operator=(const auto_aptr<T> &x)
- { delete[] p; p = x.p; ((auto_aptr<T> *) &x)->p = 0; return *this; }
- // Extension: "operator=(T *)" is identical to "auto_aptr::reset(T *)".
- void operator=(T *x) { delete[] p; p = x; }
- ~auto_aptr() { delete[] p; }
-
- // Members
-
- T &operator[](size_t idx) const { if (!p) abort(); return p[idx]; }
-T *get() const { return (T *) p; }
- T *release() { T *tmp = p; p = 0; return tmp; }
- void reset(T *x = 0) { delete[] p; p = x; }
-
- // These would make a nice extension, but are not provided by many other
- // implementations.
- //operator const void *() const { return p; }
- //int operator!() const { return p == 0; }
-
-private:
- T *p;
-};
-
-
}
diff --git a/xbmc/utils/CryptThreading.cpp b/xbmc/utils/CryptThreading.cpp
index 49a24e557f..1d2deca763 100644
--- a/xbmc/utils/CryptThreading.cpp
+++ b/xbmc/utils/CryptThreading.cpp
@@ -40,9 +40,12 @@
#include <gcrypt.h>
#include <errno.h>
+#if GCRYPT_VERSION_NUMBER < 0x010600
GCRY_THREAD_OPTION_PTHREAD_IMPL;
#endif
+#endif
+
/* ========================================================================= */
/* openssl locking implementation for curl */
static CCriticalSection* getlock(int index)
@@ -82,10 +85,12 @@ CryptThreadingInitializer::CryptThreadingInitializer()
locks[i] = NULL;
#ifdef HAVE_GCRYPT
+#if GCRYPT_VERSION_NUMBER < 0x010600
// set up gcrypt
gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
attemptedToSetSSLMTHook = true;
#endif
+#endif
if (!attemptedToSetSSLMTHook)
CLog::Log(LOGWARNING, "Could not determine the libcurl security library to set the locking scheme. This may cause problem with multithreaded use of ssl or libraries that depend on it (libcurl).");
diff --git a/xbmc/utils/RssManager.cpp b/xbmc/utils/RssManager.cpp
index 12218df785..f6820f5224 100644
--- a/xbmc/utils/RssManager.cpp
+++ b/xbmc/utils/RssManager.cpp
@@ -21,9 +21,10 @@
#include "RssManager.h"
#include "addons/AddonInstaller.h"
#include "addons/AddonManager.h"
-#include "dialogs/GUIDialogYesNo.h"
#include "filesystem/File.h"
#include "interfaces/Builtins.h"
+#include "messaging/ApplicationMessenger.h"
+#include "messaging/helpers/DialogHelper.h"
#include "profiles/ProfilesManager.h"
#include "settings/lib/Setting.h"
#include "settings/Settings.h"
@@ -34,6 +35,9 @@
#include "utils/Variant.h"
using namespace XFILE;
+using namespace KODI::MESSAGING;
+
+using KODI::MESSAGING::HELPERS::DialogResponse;
CRssManager::CRssManager()
{
@@ -70,12 +74,10 @@ void CRssManager::OnSettingAction(const CSetting *setting)
if (settingId == CSettings::SETTING_LOOKANDFEEL_RSSEDIT)
{
ADDON::AddonPtr addon;
- ADDON::CAddonMgr::GetInstance().GetAddon("script.rss.editor",addon);
- if (!addon)
+ if (!ADDON::CAddonMgr::GetInstance().GetAddon("script.rss.editor", addon))
{
- if (!CGUIDialogYesNo::ShowAndGetInput(CVariant{24076}, CVariant{24100}, CVariant{"RSS Editor"}, CVariant{24101}))
+ if (!CAddonInstaller::GetInstance().InstallModal("script.rss.editor", addon))
return;
- CAddonInstaller::GetInstance().Install("script.rss.editor", true, "", false);
}
CBuiltins::Execute("RunScript(script.rss.editor)");
}
diff --git a/xbmc/utils/SystemInfo.cpp b/xbmc/utils/SystemInfo.cpp
index 2680621c69..f37cc7192e 100644
--- a/xbmc/utils/SystemInfo.cpp
+++ b/xbmc/utils/SystemInfo.cpp
@@ -818,10 +818,10 @@ std::string CSysInfo::GetModelName(void)
modelName = CDarwinUtils::getIosPlatformString();
#elif defined(TARGET_DARWIN_OSX)
size_t nameLen = 0; // 'nameLen' should include terminating null
- if (sysctlbyname("hw.model", NULL, &nameLen, NULL, NULL) == 0 && nameLen > 1)
+ if (sysctlbyname("hw.model", NULL, &nameLen, NULL, 0) == 0 && nameLen > 1)
{
XUTILS::auto_buffer buf(nameLen);
- if (sysctlbyname("hw.model", buf.get(), &nameLen, NULL, NULL) == 0 && nameLen == buf.size())
+ if (sysctlbyname("hw.model", buf.get(), &nameLen, NULL, 0) == 0 && nameLen == buf.size())
modelName.assign(buf.get(), nameLen - 1); // assign exactly 'nameLen-1' characters to 'modelName'
}
#elif defined(TARGET_WINDOWS)
diff --git a/xbmc/video/Teletext.cpp b/xbmc/video/Teletext.cpp
index b4205a9eb7..765c75b98e 100644
--- a/xbmc/video/Teletext.cpp
+++ b/xbmc/video/Teletext.cpp
@@ -32,9 +32,9 @@
#include "filesystem/SpecialProtocol.h"
#include "guilib/GraphicContext.h"
-#if SDL_VERSION == 1
+#if HAVE_SDL_VERSION == 1
#include <SDL/SDL_stdinc.h>
-#elif SDL_VERSION == 2
+#elif HAVE_SDL_VERSION == 2
#include <SDL2/SDL_stdinc.h>
#else
#define SDL_memset4(dst, val, len) \
diff --git a/xbmc/video/VideoInfoScanner.cpp b/xbmc/video/VideoInfoScanner.cpp
index 02692fff65..7a55af74ed 100644
--- a/xbmc/video/VideoInfoScanner.cpp
+++ b/xbmc/video/VideoInfoScanner.cpp
@@ -35,9 +35,10 @@
#include "filesystem/File.h"
#include "dialogs/GUIDialogExtendedProgressBar.h"
#include "dialogs/GUIDialogProgress.h"
-#include "dialogs/GUIDialogYesNo.h"
#include "dialogs/GUIDialogOK.h"
#include "interfaces/AnnouncementManager.h"
+#include "messaging/ApplicationMessenger.h"
+#include "messaging/helpers/DialogHelper.h"
#include "settings/AdvancedSettings.h"
#include "settings/Settings.h"
#include "utils/StringUtils.h"
@@ -54,6 +55,9 @@
using namespace XFILE;
using namespace ADDON;
+using namespace KODI::MESSAGING;
+
+using KODI::MESSAGING::HELPERS::DialogResponse;
namespace VIDEO
{
@@ -2051,7 +2055,7 @@ namespace VIDEO
CGUIDialogOK::ShowAndGetInput(CVariant{20448}, CVariant{20449});
return false;
}
- return CGUIDialogYesNo::ShowAndGetInput(CVariant{20448}, CVariant{20450});
+ return HELPERS::ShowYesNoDialogText(CVariant{20448}, CVariant{20450}) == DialogResponse::YES;
}
bool CVideoInfoScanner::ProgressCancelled(CGUIDialogProgress* progress, int heading, const std::string &line1)
diff --git a/xbmc/windowing/WinEventsSDL.h b/xbmc/windowing/WinEventsSDL.h
index 42fd1467a3..6a23658e5a 100644
--- a/xbmc/windowing/WinEventsSDL.h
+++ b/xbmc/windowing/WinEventsSDL.h
@@ -25,9 +25,9 @@
#include "system.h"
#ifdef HAS_SDL
-#if SDL_VERSION == 1
+#if HAVE_SDL_VERSION == 1
#include <SDL/SDL_events.h>
-#elif SDL_VERSION == 2
+#elif HAVE_SDL_VERSION == 2
#include <SDL/SDL_events.h>
#endif