diff options
762 files changed, 26814 insertions, 15538 deletions
diff --git a/.gitignore b/.gitignore index fefd31f52e..14ff73fdb2 100644 --- a/.gitignore +++ b/.gitignore @@ -92,11 +92,7 @@ config.log /xbmc.old.log /Makefile.depend /config.status -/xbmc/config.h -/xbmc/config.h.in -/xbmc/config.h.in~ /configure -/xbmc/stamp-h1 /xbmc.bin /xbmc-test /xbmc-xrandr @@ -126,32 +122,6 @@ config.log /addons/script.module.pil/ /addons/pvr.* -# /xbmc/android -/xbmc/android/Makefile -/xbmc/android/activity/Makefile -/xbmc/android/loader/Makefile - -# /xbmc/guilib/ -/xbmc/guilib/Makefile -/xbmc/guilib/*.obj -/xbmc/guilib/*.idb -/xbmc/guilib/*.pdb -/xbmc/guilib/*.bak -/xbmc/guilib/Debug (Win32) -/xbmc/guilib/Release (Win32) -/xbmc/guilib/Release -/xbmc/guilib/Release_LTCG -/xbmc/guilib/Debug -/xbmc/guilib/Profile -/xbmc/guilib/Profile_FastCap - -# /xbmc/peripherals/ -/xbmc/peripherals/bus/Makefile -/xbmc/peripherals/devices/Makefile - -# /xbmc/main/ -/xbmc/main/Makefile - # /lib/ /lib/Makefile @@ -422,7 +392,6 @@ lib/cmyth/Makefile /system/libnfs.dll /system/dnssd.dll /system/libcec.dll -/system/pthreadVC2.dll # /system/cdrip /system/cdrip/lame_enc.dll @@ -551,42 +520,191 @@ lib/cmyth/Makefile /visualisations/projectM/ # /xbmc/ +/xbmc/config.h +/xbmc/config.h.in +/xbmc/config.h.in~ /xbmc/DllPaths_generated.h /xbmc/DllPaths_generated_android.h /xbmc/Makefile +/xbmc/stamp-h1 # /xbmc/addons/ /xbmc/addons/Makefile /xbmc/addons/visualization.waveform -# /xbmc/osx/ -/xbmc/osx/Makefile - -# /xbmc/linux/ -/xbmc/linux/Makefile - -# /xbmc/freebsd/ -/xbmc/freebsd/Makefile +# /xbmc/android +/xbmc/android/Makefile +/xbmc/android/activity/Makefile +/xbmc/android/loader/Makefile # /xbmc/cdrip/ /xbmc/cdrip/Makefile -# /xbmc/cores/AudioEngine/ +# /xbmc/cores/ /xbmc/cores/AudioEngine/Makefile - -# /xbmc/cores/DllLoader/exports/ +/xbmc/cores/amlplayer/Makefile /xbmc/cores/DllLoader/exports/build_wrapper.sh /xbmc/cores/DllLoader/exports/wrapper.def /xbmc/cores/DllLoader/Makefile /xbmc/cores/DllLoader/exports/Makefile - +/xbmc/cores/dvdplayer/Makefile +/xbmc/cores/dvdplayer/DVDCodecs/Audio/Makefile +/xbmc/cores/dvdplayer/DVDCodecs/Makefile +/xbmc/cores/dvdplayer/DVDCodecs/Overlay/Makefile +/xbmc/cores/dvdplayer/DVDCodecs/Video/CrystalHD/Makefile +/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile +/xbmc/cores/dvdplayer/DVDDemuxers/Makefile +/xbmc/cores/dvdplayer/DVDSubtitles/Makefile +/xbmc/cores/omxplayer/Makefile +/xbmc/cores/paplayer/Makefile +/xbmc/cores/playercorefactory/Makefile /xbmc/cores/Makefile - /xbmc/cores/VideoRenderers/Makefile -/xbmc/cores/dvdplayer/Makefile -/xbmc/cores/amlplayer/Makefile -/xbmc/cores/omxplayer/Makefile +# /xbmc/filesystem/ +/xbmc/filesystem/Makefile + +# /xbmc/freebsd/ +/xbmc/freebsd/Makefile + +# /xbmc/guilib/ +/xbmc/guilib/Makefile +/xbmc/guilib/*.obj +/xbmc/guilib/*.idb +/xbmc/guilib/*.pdb +/xbmc/guilib/*.bak +/xbmc/guilib/Debug (Win32) +/xbmc/guilib/Release (Win32) +/xbmc/guilib/Release +/xbmc/guilib/Release_LTCG +/xbmc/guilib/Debug +/xbmc/guilib/Profile +/xbmc/guilib/Profile_FastCap + +# /xbmc/interfaces/ +/xbmc/interfaces/Makefile +/xbmc/interfaces/python/Makefile +/xbmc/interfaces/python/generated/ +/xbmc/interfaces/python/test/Makefile + +# /xbmc/linux/ +/xbmc/linux/Makefile + +# /xbmc/main/ +/xbmc/main/Makefile + +# /xbmc/music/ +/xbmc/music/karaoke/Makefile + +# /xbmc/network/ +/xbmc/network/Makefile +/xbmc/network/upnp/Makefile + +# /xbmc/osx/ +/xbmc/osx/Makefile + +# /xbmc/peripherals/ +/xbmc/peripherals/bus/Makefile +/xbmc/peripherals/devices/Makefile + +#/xbmc/screensavers/ +/xbmc/screensavers/Makefile +/xbmc/screensavers/rsxs-0.9/Makefile +/xbmc/screensavers/rsxs-0.9/configure +/xbmc/screensavers/rsxs-0.9/config.h +/xbmc/screensavers/rsxs-0.9/config.log +/xbmc/screensavers/rsxs-0.9/config/Makefile +/xbmc/screensavers/rsxs-0.9/lib/Makefile +/xbmc/screensavers/rsxs-0.9/libltdl/Makefile +/xbmc/screensavers/rsxs-0.9/src/Makefile +/xbmc/screensavers/rsxs-0.9/src/cyclone/Makefile +/xbmc/screensavers/rsxs-0.9/src/euphoria/Makefile +/xbmc/screensavers/rsxs-0.9/src/fieldlines/Makefile +/xbmc/screensavers/rsxs-0.9/src/flocks/Makefile +/xbmc/screensavers/rsxs-0.9/src/flux/Makefile +/xbmc/screensavers/rsxs-0.9/src/helios/Makefile +/xbmc/screensavers/rsxs-0.9/src/hyperspace/Makefile +/xbmc/screensavers/rsxs-0.9/src/lattice/Makefile +/xbmc/screensavers/rsxs-0.9/src/plasma/Makefile +/xbmc/screensavers/rsxs-0.9/src/skyrocket/Makefile +/xbmc/screensavers/rsxs-0.9/src/solarwinds/Makefile +/xbmc/screensavers/rsxs-0.9/xbmc/Makefile +/xbmc/screensavers/rsxs-0.9/autom4te.cache/ +/xbmc/screensavers/rsxs-0.9/lib/alloca.h +/xbmc/screensavers/rsxs-0.9/lib/argz.h +/xbmc/screensavers/rsxs-0.9/lib/getopt.h +/xbmc/screensavers/rsxs-0.9/rsxs.spec +/xbmc/screensavers/rsxs-0.9/src/.dirstamp +/xbmc/screensavers/rsxs-0.9/src/euphoria/rs-euphoria +/xbmc/screensavers/rsxs-0.9/src/plasma/rs-plasma +/xbmc/screensavers/rsxs-0.9/src/solarwinds/rs-solarwinds +/xbmc/screensavers/rsxs-0.9/stamp-h1 +/xbmc/screensavers/rsxs-0.9/aclocal.m4 +/xbmc/screensavers/rsxs-0.9/compile +/xbmc/screensavers/rsxs-0.9/config.guess +/xbmc/screensavers/rsxs-0.9/config.h.in +/xbmc/screensavers/rsxs-0.9/config.h.in~ +/xbmc/screensavers/rsxs-0.9/config.sub +/xbmc/screensavers/rsxs-0.9/config/Makefile.in +/xbmc/screensavers/rsxs-0.9/depcomp +/xbmc/screensavers/rsxs-0.9/INSTALL +/xbmc/screensavers/rsxs-0.9/install-sh +/xbmc/screensavers/rsxs-0.9/lib/Makefile.in +/xbmc/screensavers/rsxs-0.9/libltdl/Makefile.in +/xbmc/screensavers/rsxs-0.9/Makefile.in +/xbmc/screensavers/rsxs-0.9/missing +/xbmc/screensavers/rsxs-0.9/src/cyclone/Makefile.in +/xbmc/screensavers/rsxs-0.9/src/euphoria/Makefile.in +/xbmc/screensavers/rsxs-0.9/src/fieldlines/Makefile.in +/xbmc/screensavers/rsxs-0.9/src/flocks/Makefile.in +/xbmc/screensavers/rsxs-0.9/src/flux/Makefile.in +/xbmc/screensavers/rsxs-0.9/src/helios/Makefile.in +/xbmc/screensavers/rsxs-0.9/src/hyperspace/Makefile.in +/xbmc/screensavers/rsxs-0.9/src/lattice/Makefile.in +/xbmc/screensavers/rsxs-0.9/src/Makefile.in +/xbmc/screensavers/rsxs-0.9/src/plasma/Makefile.in +/xbmc/screensavers/rsxs-0.9/src/skyrocket/Makefile.in +/xbmc/screensavers/rsxs-0.9/src/solarwinds/Makefile.in + +#/xbmc/utils +/xbmc/utils/Makefile + +#/xbmc/visualizations/ +/xbmc/visualizations/DirectXSpectrum/Debug (DirectX) +/xbmc/visualizations/DirectXSpectrum/Release (DirectX) +/xbmc/visualizations/EGLHelpers/Makefile +/xbmc/visualizations/Goom/Makefile +/xbmc/visualizations/Goom/goom2k4-0/aclocal.m4 +/xbmc/visualizations/Goom/goom2k4-0/configure +/xbmc/visualizations/Goom/goom2k4-0/INSTALL +/xbmc/visualizations/Goom/goom2k4-0/Makefile.in +/xbmc/visualizations/Goom/goom2k4-0/config.guess +/xbmc/visualizations/Goom/goom2k4-0/config.sub +/xbmc/visualizations/Goom/goom2k4-0/depcomp +/xbmc/visualizations/Goom/goom2k4-0/install-sh +/xbmc/visualizations/Goom/goom2k4-0/ltmain.sh +/xbmc/visualizations/Goom/goom2k4-0/missing +/xbmc/visualizations/Goom/goom2k4-0/sdl-goom/Makefile.in +/xbmc/visualizations/Goom/goom2k4-0/src/Makefile.in +/xbmc/visualizations/Goom/goom2k4-0/xmms-goom/Makefile.in +/xbmc/visualizations/Goom/goom2k4-0/ylwrap +/xbmc/visualizations/Milkdrop/Debug +/xbmc/visualizations/Milkdrop/Release +/xbmc/visualizations/OpenGLSpectrum/Makefile +/xbmc/visualizations/WaveForm/Makefile +/xbmc/visualizations/WaveForm/Debug (DirectX) +/xbmc/visualizations/WaveForm/Release (DirectX) +/xbmc/visualizations/iTunes/Makefile +/xbmc/visualizations/XBMCProjectM/Makefile +/xbmc/visualizations/XBMCProjectM/libprojectM/Makefile +/xbmc/visualizations/XBMCProjectM/libprojectM/CMakeCache.txt +/xbmc/visualizations/XBMCProjectM/libprojectM/CMakeFiles/ +/xbmc/visualizations/XBMCProjectM/libprojectM/cmake_install.cmake +/xbmc/visualizations/XBMCProjectM/libprojectM/config.inp +/xbmc/visualizations/fishBMC/Makefile + +#/xbmc/win32/ +/xbmc/win32/git_rev.h # /lib/ffmpeg/ /lib/ffmpeg/config.h @@ -599,8 +717,6 @@ lib/cmyth/Makefile /lib/ffmpeg/libavutil/avconfig.h /lib/ffmpeg/doc/ffmpeg.pod /lib/ffmpeg/doc/ffplay.pod - -# /lib/ffmpeg/doc/ /lib/ffmpeg/doc/*.html /lib/ffmpeg/doc/*.1 @@ -762,20 +878,6 @@ lib/cmyth/Makefile # /lib/libmpeg2/vc++/ /lib/libmpeg2/vc++/Makefile -# /xbmc/cores/dvdplayer/DVDCodecs -/xbmc/cores/dvdplayer/DVDCodecs/Audio/Makefile -/xbmc/cores/dvdplayer/DVDCodecs/Makefile -/xbmc/cores/dvdplayer/DVDCodecs/Overlay/Makefile -/xbmc/cores/dvdplayer/DVDCodecs/Video/CrystalHD/Makefile -/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile - -/xbmc/cores/dvdplayer/DVDDemuxers/Makefile - -/xbmc/cores/dvdplayer/DVDSubtitles/Makefile - -# /xbmc/cores/paplayer/ -/xbmc/cores/paplayer/Makefile - # /lib/xbadpcm/ /lib/xbadpcm/Makefile /lib/xbadpcm/adpcm.lib @@ -1054,13 +1156,6 @@ lib/cmyth/Makefile /lib/win32/vorbisfile/ogg/win32/Static_Debug /lib/win32/vorbisfile/ogg/win32/Static_Release -/xbmc/cores/playercorefactory/Makefile - -/xbmc/filesystem/Makefile - -# /xbmc/music/karaoke/ -/xbmc/music/karaoke/Makefile - # /lib/cmyth/ /lib/cmyth/Makefile.depend /lib/cmyth/Win32/libcmyth.lib @@ -1093,16 +1188,6 @@ lib/cmyth/Makefile /lib/libhts/Win32/Release -# /xbmc/interfaces/ -/xbmc/interfaces/Makefile -/xbmc/interfaces/python/Makefile -/xbmc/interfaces/python/generated/ -/xbmc/interfaces/python/test/Makefile - -# /xbmc/network/ -/xbmc/network/Makefile -/xbmc/network/upnp/Makefile - # /lib/libRTV/ /lib/libRTV/Makefile /lib/libRTV/Debug @@ -1121,113 +1206,9 @@ lib/cmyth/Makefile /lib/libXDAAP/libXDAAP_win32/Debug /lib/libXDAAP/libXDAAP_win32/Release -# /xbmc/osx/ -/xbmc/osx/Makefile - # /portable_data /portable_data -/xbmc/screensavers/Makefile - -/xbmc/screensavers/rsxs-0.9/Makefile -/xbmc/screensavers/rsxs-0.9/configure -/xbmc/screensavers/rsxs-0.9/config.h -/xbmc/screensavers/rsxs-0.9/config.log -/xbmc/screensavers/rsxs-0.9/config/Makefile -/xbmc/screensavers/rsxs-0.9/lib/Makefile -/xbmc/screensavers/rsxs-0.9/libltdl/Makefile -/xbmc/screensavers/rsxs-0.9/src/Makefile -/xbmc/screensavers/rsxs-0.9/src/cyclone/Makefile -/xbmc/screensavers/rsxs-0.9/src/euphoria/Makefile -/xbmc/screensavers/rsxs-0.9/src/fieldlines/Makefile -/xbmc/screensavers/rsxs-0.9/src/flocks/Makefile -/xbmc/screensavers/rsxs-0.9/src/flux/Makefile -/xbmc/screensavers/rsxs-0.9/src/helios/Makefile -/xbmc/screensavers/rsxs-0.9/src/hyperspace/Makefile -/xbmc/screensavers/rsxs-0.9/src/lattice/Makefile -/xbmc/screensavers/rsxs-0.9/src/plasma/Makefile -/xbmc/screensavers/rsxs-0.9/src/skyrocket/Makefile -/xbmc/screensavers/rsxs-0.9/src/solarwinds/Makefile -/xbmc/screensavers/rsxs-0.9/xbmc/Makefile -/xbmc/screensavers/rsxs-0.9/autom4te.cache/ -/xbmc/screensavers/rsxs-0.9/lib/alloca.h -/xbmc/screensavers/rsxs-0.9/lib/argz.h -/xbmc/screensavers/rsxs-0.9/lib/getopt.h -/xbmc/screensavers/rsxs-0.9/rsxs.spec -/xbmc/screensavers/rsxs-0.9/src/.dirstamp -/xbmc/screensavers/rsxs-0.9/src/euphoria/rs-euphoria -/xbmc/screensavers/rsxs-0.9/src/plasma/rs-plasma -/xbmc/screensavers/rsxs-0.9/src/solarwinds/rs-solarwinds -/xbmc/screensavers/rsxs-0.9/stamp-h1 -/xbmc/screensavers/rsxs-0.9/aclocal.m4 -/xbmc/screensavers/rsxs-0.9/compile -/xbmc/screensavers/rsxs-0.9/config.guess -/xbmc/screensavers/rsxs-0.9/config.h.in -/xbmc/screensavers/rsxs-0.9/config.h.in~ -/xbmc/screensavers/rsxs-0.9/config.sub -/xbmc/screensavers/rsxs-0.9/config/Makefile.in -/xbmc/screensavers/rsxs-0.9/depcomp -/xbmc/screensavers/rsxs-0.9/INSTALL -/xbmc/screensavers/rsxs-0.9/install-sh -/xbmc/screensavers/rsxs-0.9/lib/Makefile.in -/xbmc/screensavers/rsxs-0.9/libltdl/Makefile.in -/xbmc/screensavers/rsxs-0.9/Makefile.in -/xbmc/screensavers/rsxs-0.9/missing -/xbmc/screensavers/rsxs-0.9/src/cyclone/Makefile.in -/xbmc/screensavers/rsxs-0.9/src/euphoria/Makefile.in -/xbmc/screensavers/rsxs-0.9/src/fieldlines/Makefile.in -/xbmc/screensavers/rsxs-0.9/src/flocks/Makefile.in -/xbmc/screensavers/rsxs-0.9/src/flux/Makefile.in -/xbmc/screensavers/rsxs-0.9/src/helios/Makefile.in -/xbmc/screensavers/rsxs-0.9/src/hyperspace/Makefile.in -/xbmc/screensavers/rsxs-0.9/src/lattice/Makefile.in -/xbmc/screensavers/rsxs-0.9/src/Makefile.in -/xbmc/screensavers/rsxs-0.9/src/plasma/Makefile.in -/xbmc/screensavers/rsxs-0.9/src/skyrocket/Makefile.in -/xbmc/screensavers/rsxs-0.9/src/solarwinds/Makefile.in - -/xbmc/visualizations/DirectXSpectrum/Debug (DirectX) -/xbmc/visualizations/DirectXSpectrum/Release (DirectX) - -xbmc/visualizations/EGLHelpers/Makefile - -/xbmc/visualizations/Goom/Makefile -/xbmc/visualizations/Goom/goom2k4-0/aclocal.m4 -/xbmc/visualizations/Goom/goom2k4-0/configure -/xbmc/visualizations/Goom/goom2k4-0/INSTALL -/xbmc/visualizations/Goom/goom2k4-0/Makefile.in -/xbmc/visualizations/Goom/goom2k4-0/config.guess -/xbmc/visualizations/Goom/goom2k4-0/config.sub -/xbmc/visualizations/Goom/goom2k4-0/depcomp -/xbmc/visualizations/Goom/goom2k4-0/install-sh -/xbmc/visualizations/Goom/goom2k4-0/ltmain.sh -/xbmc/visualizations/Goom/goom2k4-0/missing -/xbmc/visualizations/Goom/goom2k4-0/sdl-goom/Makefile.in -/xbmc/visualizations/Goom/goom2k4-0/src/Makefile.in -/xbmc/visualizations/Goom/goom2k4-0/xmms-goom/Makefile.in -/xbmc/visualizations/Goom/goom2k4-0/ylwrap - -/xbmc/visualizations/Milkdrop/Debug -/xbmc/visualizations/Milkdrop/Release - -/xbmc/visualizations/OpenGLSpectrum/Makefile - -/xbmc/visualizations/WaveForm/Makefile -/xbmc/visualizations/WaveForm/Debug (DirectX) -/xbmc/visualizations/WaveForm/Release (DirectX) - -/xbmc/visualizations/iTunes/Makefile - -/xbmc/visualizations/XBMCProjectM/Makefile -/xbmc/visualizations/XBMCProjectM/libprojectM/Makefile -/xbmc/visualizations/XBMCProjectM/libprojectM/CMakeCache.txt -/xbmc/visualizations/XBMCProjectM/libprojectM/CMakeFiles/ -/xbmc/visualizations/XBMCProjectM/libprojectM/cmake_install.cmake -/xbmc/visualizations/XBMCProjectM/libprojectM/config.inp -/xbmc/visualizations/fishBMC/Makefile - -/xbmc/win32/git_rev.h - /addons/library.xbmc.addon/libXBMC_addon.dll /addons/library.xbmc.addon/libXBMC_addon.lib /addons/library.xbmc.gui/libXBMC_gui.dll diff --git a/XBMC-ATV2.xcodeproj/project.pbxproj b/XBMC-ATV2.xcodeproj/project.pbxproj index 576285a57d..564ced5cef 100644 --- a/XBMC-ATV2.xcodeproj/project.pbxproj +++ b/XBMC-ATV2.xcodeproj/project.pbxproj @@ -132,6 +132,7 @@ DF404AA816B98E6300D8023E /* imagefactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF404AA516B98E6300D8023E /* imagefactory.cpp */; }; DF4485351400651B0069344B /* PipesManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF4485321400651B0069344B /* PipesManager.cpp */; }; DF4485381400654A0069344B /* AirTunesServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF4485361400654A0069344B /* AirTunesServer.cpp */; }; + DF52568B1732C4620094A464 /* DVDDemuxCDDA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5256891732C4620094A464 /* DVDDemuxCDDA.cpp */; }; DF527780151BAFD600B5B63B /* WebSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF527777151BAFD600B5B63B /* WebSocket.cpp */; }; DF527781151BAFD600B5B63B /* WebSocketManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF527779151BAFD600B5B63B /* WebSocketManager.cpp */; }; DF527782151BAFD600B5B63B /* WebSocketV13.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF52777B151BAFD600B5B63B /* WebSocketV13.cpp */; }; @@ -259,6 +260,21 @@ DFDB004A1516408F005079A4 /* DirectoryCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFDB00431516408F005079A4 /* DirectoryCache.cpp */; }; DFDB004B1516408F005079A4 /* FileCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFDB00451516408F005079A4 /* FileCache.cpp */; }; DFDB004C1516408F005079A4 /* MemBufferCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFDB00471516408F005079A4 /* MemBufferCache.cpp */; }; + DFECFB69172D9E2B00A43CF7 /* GUIControlSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB67172D9E2B00A43CF7 /* GUIControlSettings.cpp */; }; + DFECFB84172D9E4C00A43CF7 /* ISetting.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB6A172D9E4C00A43CF7 /* ISetting.cpp */; }; + DFECFB85172D9E4C00A43CF7 /* Setting.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB6E172D9E4C00A43CF7 /* Setting.cpp */; }; + DFECFB86172D9E4C00A43CF7 /* SettingAddon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB70172D9E4C00A43CF7 /* SettingAddon.cpp */; }; + DFECFB87172D9E4C00A43CF7 /* SettingCategoryAccess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB72172D9E4C00A43CF7 /* SettingCategoryAccess.cpp */; }; + DFECFB88172D9E4C00A43CF7 /* SettingConditions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB74172D9E4C00A43CF7 /* SettingConditions.cpp */; }; + DFECFB89172D9E4C00A43CF7 /* SettingControl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB76172D9E4C00A43CF7 /* SettingControl.cpp */; }; + DFECFB8A172D9E4C00A43CF7 /* SettingDependency.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB78172D9E4C00A43CF7 /* SettingDependency.cpp */; }; + DFECFB8B172D9E4C00A43CF7 /* SettingPath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB7A172D9E4C00A43CF7 /* SettingPath.cpp */; }; + DFECFB8C172D9E4C00A43CF7 /* SettingSection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB7C172D9E4C00A43CF7 /* SettingSection.cpp */; }; + DFECFB8D172D9E4C00A43CF7 /* SettingsManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB7E172D9E4C00A43CF7 /* SettingsManager.cpp */; }; + DFECFB8E172D9E4C00A43CF7 /* SettingUpdate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB80172D9E4C00A43CF7 /* SettingUpdate.cpp */; }; + DFECFB8F172D9E4C00A43CF7 /* SettingVisibility.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB82172D9E4C00A43CF7 /* SettingVisibility.cpp */; }; + DFECFB92172D9E6D00A43CF7 /* BooleanLogic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB90172D9E6D00A43CF7 /* BooleanLogic.cpp */; }; + DFECFBFD172DA58800A43CF7 /* NetworkServices.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFBFB172DA58800A43CF7 /* NetworkServices.cpp */; }; DFFD594F1506B6300088DE4B /* IOSEAGLView.mm in Sources */ = {isa = PBXBuildFile; fileRef = DFFD594C1506B6300088DE4B /* IOSEAGLView.mm */; }; DFFEFBDB151606CB001294DC /* IOSScreenManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = DFFEFBDA151606CB001294DC /* IOSScreenManager.mm */; }; DFFEFC2215160927001294DC /* IOSExternalTouchController.mm in Sources */ = {isa = PBXBuildFile; fileRef = DFFEFC2115160927001294DC /* IOSExternalTouchController.mm */; }; @@ -268,7 +284,6 @@ F563530316E5442F00D21BAD /* UPnPSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F563530116E5442F00D21BAD /* UPnPSettings.cpp */; }; F563530F16E5446300D21BAD /* GUIDialogContentSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F563530716E5446300D21BAD /* GUIDialogContentSettings.cpp */; }; F563531216E5446300D21BAD /* GUIDialogSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F563530D16E5446300D21BAD /* GUIDialogSettings.cpp */; }; - F563531F16E5446C00D21BAD /* GUISettingControls.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F563531316E5446C00D21BAD /* GUISettingControls.cpp */; }; F563532016E5446C00D21BAD /* GUIWindowSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F563531516E5446C00D21BAD /* GUIWindowSettings.cpp */; }; F563532116E5446C00D21BAD /* GUIWindowSettingsCategory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F563531716E5446C00D21BAD /* GUIWindowSettingsCategory.cpp */; }; F563532316E5446C00D21BAD /* GUIWindowSettingsScreenCalibration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F563531B16E5446C00D21BAD /* GUIWindowSettingsScreenCalibration.cpp */; }; @@ -421,7 +436,6 @@ F56C7912131EC154000AD0F6 /* DVDPerformanceCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C72D2131EC151000AD0F6 /* DVDPerformanceCounter.cpp */; }; F56C7913131EC154000AD0F6 /* DVDPlayer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C72D4131EC151000AD0F6 /* DVDPlayer.cpp */; }; F56C7914131EC154000AD0F6 /* DVDPlayerAudio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C72D6131EC151000AD0F6 /* DVDPlayerAudio.cpp */; }; - F56C7915131EC154000AD0F6 /* DVDPlayerAudioResampler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C72D8131EC151000AD0F6 /* DVDPlayerAudioResampler.cpp */; }; F56C7916131EC154000AD0F6 /* DVDPlayerSubtitle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C72DA131EC151000AD0F6 /* DVDPlayerSubtitle.cpp */; }; F56C7917131EC154000AD0F6 /* DVDPlayerTeletext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C72DC131EC151000AD0F6 /* DVDPlayerTeletext.cpp */; }; F56C7918131EC154000AD0F6 /* DVDPlayerVideo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C72DE131EC151000AD0F6 /* DVDPlayerVideo.cpp */; }; @@ -443,7 +457,6 @@ F56C7928131EC154000AD0F6 /* DVDPlayerCodec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C7306131EC151000AD0F6 /* DVDPlayerCodec.cpp */; }; F56C7929131EC154000AD0F6 /* ADPCMCodec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C7308131EC151000AD0F6 /* ADPCMCodec.cpp */; }; F56C792B131EC154000AD0F6 /* AudioDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C730C131EC151000AD0F6 /* AudioDecoder.cpp */; }; - F56C792C131EC154000AD0F6 /* CDDAcodec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C730F131EC151000AD0F6 /* CDDAcodec.cpp */; }; F56C792D131EC154000AD0F6 /* CodecFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C7311131EC151000AD0F6 /* CodecFactory.cpp */; }; F56C792E131EC154000AD0F6 /* VGMCodec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C7313131EC151000AD0F6 /* VGMCodec.cpp */; }; F56C792F131EC154000AD0F6 /* FLACcodec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C7315131EC151000AD0F6 /* FLACcodec.cpp */; }; @@ -771,7 +784,6 @@ F56C7AED131EC155000AD0F6 /* GUIViewStatePrograms.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C76B5131EC153000AD0F6 /* GUIViewStatePrograms.cpp */; }; F56C7AEE131EC155000AD0F6 /* GUIWindowPrograms.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C76B7131EC153000AD0F6 /* GUIWindowPrograms.cpp */; }; F56C7AF3131EC155000AD0F6 /* RenderSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C76C3131EC153000AD0F6 /* RenderSystem.cpp */; }; - F56C7AF9131EC155000AD0F6 /* GUISettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C76D1131EC153000AD0F6 /* GUISettings.cpp */; }; F56C7AFA131EC155000AD0F6 /* AdvancedSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C76D3131EC153000AD0F6 /* AdvancedSettings.cpp */; }; F56C7B00131EC155000AD0F6 /* Settings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C76DF131EC153000AD0F6 /* Settings.cpp */; }; F56C7B02131EC155000AD0F6 /* VideoSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C76E3131EC153000AD0F6 /* VideoSettings.cpp */; }; @@ -1007,6 +1019,7 @@ F5B13E0113344F310045076D /* DarwinUtils.mm in Sources */ = {isa = PBXBuildFile; fileRef = F5B13E0013344F310045076D /* DarwinUtils.mm */; }; F5BD033A148D4923001B5583 /* CryptThreading.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5BD0338148D4923001B5583 /* CryptThreading.cpp */; }; F5CEE72C13D3F9AC00225F72 /* DVDOverlayCodecTX3G.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5CEE72B13D3F9AC00225F72 /* DVDOverlayCodecTX3G.cpp */; }; + F5DB701317322DF700D4DF21 /* FavouritesOperations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5DB701117322DF700D4DF21 /* FavouritesOperations.cpp */; }; F5E1131D14357B6500175026 /* PeripheralBusUSB.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E112FF14357B6500175026 /* PeripheralBusUSB.cpp */; }; F5E1131E14357B6500175026 /* PeripheralBus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E1130114357B6500175026 /* PeripheralBus.cpp */; }; F5E1131F14357B6500175026 /* Peripheral.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E1130514357B6500175026 /* Peripheral.cpp */; }; @@ -1331,6 +1344,8 @@ DF4485331400651B0069344B /* PipesManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PipesManager.h; sourceTree = "<group>"; }; DF4485361400654A0069344B /* AirTunesServer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AirTunesServer.cpp; sourceTree = "<group>"; }; DF4485371400654A0069344B /* AirTunesServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AirTunesServer.h; sourceTree = "<group>"; }; + DF5256891732C4620094A464 /* DVDDemuxCDDA.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DVDDemuxCDDA.cpp; sourceTree = "<group>"; }; + DF52568A1732C4620094A464 /* DVDDemuxCDDA.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DVDDemuxCDDA.h; sourceTree = "<group>"; }; DF527777151BAFD600B5B63B /* WebSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebSocket.cpp; sourceTree = "<group>"; }; DF527778151BAFD600B5B63B /* WebSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSocket.h; sourceTree = "<group>"; }; DF527779151BAFD600B5B63B /* WebSocketManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebSocketManager.cpp; sourceTree = "<group>"; }; @@ -1550,6 +1565,38 @@ DFDB00461516408F005079A4 /* FileCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileCache.h; sourceTree = "<group>"; }; DFDB00471516408F005079A4 /* MemBufferCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MemBufferCache.cpp; sourceTree = "<group>"; }; DFDB00481516408F005079A4 /* MemBufferCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemBufferCache.h; sourceTree = "<group>"; }; + DFECFB67172D9E2B00A43CF7 /* GUIControlSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GUIControlSettings.cpp; path = windows/GUIControlSettings.cpp; sourceTree = "<group>"; }; + DFECFB68172D9E2B00A43CF7 /* GUIControlSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GUIControlSettings.h; path = windows/GUIControlSettings.h; sourceTree = "<group>"; }; + DFECFB6A172D9E4C00A43CF7 /* ISetting.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ISetting.cpp; sourceTree = "<group>"; }; + DFECFB6B172D9E4C00A43CF7 /* ISetting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ISetting.h; sourceTree = "<group>"; }; + DFECFB6C172D9E4C00A43CF7 /* ISettingCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ISettingCallback.h; sourceTree = "<group>"; }; + DFECFB6D172D9E4C00A43CF7 /* ISettingCreator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ISettingCreator.h; sourceTree = "<group>"; }; + DFECFB6E172D9E4C00A43CF7 /* Setting.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Setting.cpp; sourceTree = "<group>"; }; + DFECFB6F172D9E4C00A43CF7 /* Setting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Setting.h; sourceTree = "<group>"; }; + DFECFB70172D9E4C00A43CF7 /* SettingAddon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingAddon.cpp; sourceTree = "<group>"; }; + DFECFB71172D9E4C00A43CF7 /* SettingAddon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingAddon.h; sourceTree = "<group>"; }; + DFECFB72172D9E4C00A43CF7 /* SettingCategoryAccess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingCategoryAccess.cpp; sourceTree = "<group>"; }; + DFECFB73172D9E4C00A43CF7 /* SettingCategoryAccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingCategoryAccess.h; sourceTree = "<group>"; }; + DFECFB74172D9E4C00A43CF7 /* SettingConditions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingConditions.cpp; sourceTree = "<group>"; }; + DFECFB75172D9E4C00A43CF7 /* SettingConditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingConditions.h; sourceTree = "<group>"; }; + DFECFB76172D9E4C00A43CF7 /* SettingControl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingControl.cpp; sourceTree = "<group>"; }; + DFECFB77172D9E4C00A43CF7 /* SettingControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingControl.h; sourceTree = "<group>"; }; + DFECFB78172D9E4C00A43CF7 /* SettingDependency.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingDependency.cpp; sourceTree = "<group>"; }; + DFECFB79172D9E4C00A43CF7 /* SettingDependency.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingDependency.h; sourceTree = "<group>"; }; + DFECFB7A172D9E4C00A43CF7 /* SettingPath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingPath.cpp; sourceTree = "<group>"; }; + DFECFB7B172D9E4C00A43CF7 /* SettingPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingPath.h; sourceTree = "<group>"; }; + DFECFB7C172D9E4C00A43CF7 /* SettingSection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingSection.cpp; sourceTree = "<group>"; }; + DFECFB7D172D9E4C00A43CF7 /* SettingSection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingSection.h; sourceTree = "<group>"; }; + DFECFB7E172D9E4C00A43CF7 /* SettingsManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingsManager.cpp; sourceTree = "<group>"; }; + DFECFB7F172D9E4C00A43CF7 /* SettingsManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsManager.h; sourceTree = "<group>"; }; + DFECFB80172D9E4C00A43CF7 /* SettingUpdate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingUpdate.cpp; sourceTree = "<group>"; }; + DFECFB81172D9E4C00A43CF7 /* SettingUpdate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingUpdate.h; sourceTree = "<group>"; }; + DFECFB82172D9E4C00A43CF7 /* SettingVisibility.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingVisibility.cpp; sourceTree = "<group>"; }; + DFECFB83172D9E4C00A43CF7 /* SettingVisibility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingVisibility.h; sourceTree = "<group>"; }; + DFECFB90172D9E6D00A43CF7 /* BooleanLogic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BooleanLogic.cpp; sourceTree = "<group>"; }; + DFECFB91172D9E6D00A43CF7 /* BooleanLogic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BooleanLogic.h; sourceTree = "<group>"; }; + DFECFBFB172DA58800A43CF7 /* NetworkServices.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkServices.cpp; sourceTree = "<group>"; }; + DFECFBFC172DA58800A43CF7 /* NetworkServices.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkServices.h; sourceTree = "<group>"; }; DFFD594B1506B6300088DE4B /* IOSEAGLView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOSEAGLView.h; sourceTree = "<group>"; }; DFFD594C1506B6300088DE4B /* IOSEAGLView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = IOSEAGLView.mm; sourceTree = "<group>"; }; DFFEFBD9151606CB001294DC /* IOSScreenManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOSScreenManager.h; sourceTree = "<group>"; }; @@ -1579,8 +1626,6 @@ F563530816E5446300D21BAD /* GUIDialogContentSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GUIDialogContentSettings.h; path = dialogs/GUIDialogContentSettings.h; sourceTree = "<group>"; }; F563530D16E5446300D21BAD /* GUIDialogSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GUIDialogSettings.cpp; path = dialogs/GUIDialogSettings.cpp; sourceTree = "<group>"; }; F563530E16E5446300D21BAD /* GUIDialogSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GUIDialogSettings.h; path = dialogs/GUIDialogSettings.h; sourceTree = "<group>"; }; - F563531316E5446C00D21BAD /* GUISettingControls.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GUISettingControls.cpp; path = windows/GUISettingControls.cpp; sourceTree = "<group>"; }; - F563531416E5446C00D21BAD /* GUISettingControls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GUISettingControls.h; path = windows/GUISettingControls.h; sourceTree = "<group>"; }; F563531516E5446C00D21BAD /* GUIWindowSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GUIWindowSettings.cpp; path = windows/GUIWindowSettings.cpp; sourceTree = "<group>"; }; F563531616E5446C00D21BAD /* GUIWindowSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GUIWindowSettings.h; path = windows/GUIWindowSettings.h; sourceTree = "<group>"; }; F563531716E5446C00D21BAD /* GUIWindowSettingsCategory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GUIWindowSettingsCategory.cpp; path = windows/GUIWindowSettingsCategory.cpp; sourceTree = "<group>"; }; @@ -1973,8 +2018,6 @@ F56C72D5131EC151000AD0F6 /* DVDPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DVDPlayer.h; sourceTree = "<group>"; }; F56C72D6131EC151000AD0F6 /* DVDPlayerAudio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DVDPlayerAudio.cpp; sourceTree = "<group>"; }; F56C72D7131EC151000AD0F6 /* DVDPlayerAudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DVDPlayerAudio.h; sourceTree = "<group>"; }; - F56C72D8131EC151000AD0F6 /* DVDPlayerAudioResampler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DVDPlayerAudioResampler.cpp; sourceTree = "<group>"; }; - F56C72D9131EC151000AD0F6 /* DVDPlayerAudioResampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DVDPlayerAudioResampler.h; sourceTree = "<group>"; }; F56C72DA131EC151000AD0F6 /* DVDPlayerSubtitle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DVDPlayerSubtitle.cpp; sourceTree = "<group>"; }; F56C72DB131EC151000AD0F6 /* DVDPlayerSubtitle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DVDPlayerSubtitle.h; sourceTree = "<group>"; }; F56C72DC131EC151000AD0F6 /* DVDPlayerTeletext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DVDPlayerTeletext.cpp; sourceTree = "<group>"; }; @@ -2023,8 +2066,6 @@ F56C730C131EC151000AD0F6 /* AudioDecoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AudioDecoder.cpp; sourceTree = "<group>"; }; F56C730D131EC151000AD0F6 /* AudioDecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioDecoder.h; sourceTree = "<group>"; }; F56C730E131EC151000AD0F6 /* CachingCodec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CachingCodec.h; sourceTree = "<group>"; }; - F56C730F131EC151000AD0F6 /* CDDAcodec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CDDAcodec.cpp; sourceTree = "<group>"; }; - F56C7310131EC151000AD0F6 /* CDDAcodec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDDAcodec.h; sourceTree = "<group>"; }; F56C7311131EC151000AD0F6 /* CodecFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodecFactory.cpp; sourceTree = "<group>"; }; F56C7312131EC151000AD0F6 /* CodecFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodecFactory.h; sourceTree = "<group>"; }; F56C7313131EC151000AD0F6 /* VGMCodec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VGMCodec.cpp; sourceTree = "<group>"; }; @@ -2701,8 +2742,6 @@ F56C76B8131EC153000AD0F6 /* GUIWindowPrograms.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIWindowPrograms.h; sourceTree = "<group>"; }; F56C76C3131EC153000AD0F6 /* RenderSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSystem.cpp; sourceTree = "<group>"; }; F56C76C4131EC153000AD0F6 /* RenderSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSystem.h; sourceTree = "<group>"; }; - F56C76D1131EC153000AD0F6 /* GUISettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUISettings.cpp; sourceTree = "<group>"; }; - F56C76D2131EC153000AD0F6 /* GUISettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUISettings.h; sourceTree = "<group>"; }; F56C76D3131EC153000AD0F6 /* AdvancedSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AdvancedSettings.cpp; sourceTree = "<group>"; }; F56C76D4131EC153000AD0F6 /* AdvancedSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AdvancedSettings.h; sourceTree = "<group>"; }; F56C76DF131EC153000AD0F6 /* Settings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Settings.cpp; sourceTree = "<group>"; }; @@ -3193,6 +3232,8 @@ F5BD0339148D4923001B5583 /* CryptThreading.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CryptThreading.h; sourceTree = "<group>"; }; F5CEE72B13D3F9AC00225F72 /* DVDOverlayCodecTX3G.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DVDOverlayCodecTX3G.cpp; sourceTree = "<group>"; }; F5CEE72D13D3F9B300225F72 /* DVDOverlayCodecTX3G.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DVDOverlayCodecTX3G.h; sourceTree = "<group>"; }; + F5DB701117322DF700D4DF21 /* FavouritesOperations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FavouritesOperations.cpp; sourceTree = "<group>"; }; + F5DB701217322DF700D4DF21 /* FavouritesOperations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FavouritesOperations.h; sourceTree = "<group>"; }; F5E112FF14357B6500175026 /* PeripheralBusUSB.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PeripheralBusUSB.cpp; sourceTree = "<group>"; }; F5E1130014357B6500175026 /* PeripheralBusUSB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PeripheralBusUSB.h; sourceTree = "<group>"; }; F5E1130114357B6500175026 /* PeripheralBus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PeripheralBus.cpp; sourceTree = "<group>"; }; @@ -3791,8 +3832,8 @@ F563530616E5444500D21BAD /* windows */ = { isa = PBXGroup; children = ( - F563531316E5446C00D21BAD /* GUISettingControls.cpp */, - F563531416E5446C00D21BAD /* GUISettingControls.h */, + DFECFB67172D9E2B00A43CF7 /* GUIControlSettings.cpp */, + DFECFB68172D9E2B00A43CF7 /* GUIControlSettings.h */, F563531516E5446C00D21BAD /* GUIWindowSettings.cpp */, F563531616E5446C00D21BAD /* GUIWindowSettings.h */, F563531716E5446C00D21BAD /* GUIWindowSettingsCategory.cpp */, @@ -4345,8 +4386,6 @@ F56C72D5131EC151000AD0F6 /* DVDPlayer.h */, F56C72D6131EC151000AD0F6 /* DVDPlayerAudio.cpp */, F56C72D7131EC151000AD0F6 /* DVDPlayerAudio.h */, - F56C72D8131EC151000AD0F6 /* DVDPlayerAudioResampler.cpp */, - F56C72D9131EC151000AD0F6 /* DVDPlayerAudioResampler.h */, F56C72DA131EC151000AD0F6 /* DVDPlayerSubtitle.cpp */, F56C72DB131EC151000AD0F6 /* DVDPlayerSubtitle.h */, F56C72DC131EC151000AD0F6 /* DVDPlayerTeletext.cpp */, @@ -4483,6 +4522,8 @@ F56C7299131EC151000AD0F6 /* DVDDemux.h */, DF24EAC51621E58D00034265 /* DVDDemuxBXA.cpp */, DF24EAC61621E58D00034265 /* DVDDemuxBXA.h */, + DF5256891732C4620094A464 /* DVDDemuxCDDA.cpp */, + DF52568A1732C4620094A464 /* DVDDemuxCDDA.h */, F56C7294131EC151000AD0F6 /* DVDDemuxFFmpeg.cpp */, F56C7295131EC151000AD0F6 /* DVDDemuxFFmpeg.h */, F56C7296131EC151000AD0F6 /* DVDDemuxHTSP.cpp */, @@ -4604,8 +4645,6 @@ F56C730C131EC151000AD0F6 /* AudioDecoder.cpp */, F56C730D131EC151000AD0F6 /* AudioDecoder.h */, F56C730E131EC151000AD0F6 /* CachingCodec.h */, - F56C730F131EC151000AD0F6 /* CDDAcodec.cpp */, - F56C7310131EC151000AD0F6 /* CDDAcodec.h */, F56C7311131EC151000AD0F6 /* CodecFactory.cpp */, F56C7312131EC151000AD0F6 /* CodecFactory.h */, F56C7306131EC151000AD0F6 /* DVDPlayerCodec.cpp */, @@ -5494,6 +5533,8 @@ F56C7662131EC153000AD0F6 /* GUIDialogNetworkSetup.h */, F56C7663131EC153000AD0F6 /* Network.cpp */, F56C7664131EC153000AD0F6 /* Network.h */, + DFECFBFB172DA58800A43CF7 /* NetworkServices.cpp */, + DFECFBFC172DA58800A43CF7 /* NetworkServices.h */, F56C7665131EC153000AD0F6 /* Socket.cpp */, F56C7666131EC153000AD0F6 /* Socket.h */, F56C7667131EC153000AD0F6 /* TCPServer.cpp */, @@ -5661,16 +5702,40 @@ F56C76D4131EC153000AD0F6 /* AdvancedSettings.h */, DF28EE14170E1E8D005FA9D2 /* DisplaySettings.cpp */, DF28EE15170E1E8D005FA9D2 /* DisplaySettings.h */, - F56C76D1131EC153000AD0F6 /* GUISettings.cpp */, - F56C76D2131EC153000AD0F6 /* GUISettings.h */, + DFECFB6A172D9E4C00A43CF7 /* ISetting.cpp */, + DFECFB6B172D9E4C00A43CF7 /* ISetting.h */, + DFECFB6C172D9E4C00A43CF7 /* ISettingCallback.h */, + DFECFB6D172D9E4C00A43CF7 /* ISettingCreator.h */, DF898FFC1709B95B00B35C21 /* ISettingsHandler.h */, DF898FFD1709B95B00B35C21 /* ISubSettings.h */, DF898FFE1709B95B00B35C21 /* MediaSettings.cpp */, DF898FFF1709B95B00B35C21 /* MediaSettings.h */, DF8990001709B95B00B35C21 /* MediaSourceSettings.cpp */, DF8990011709B95B00B35C21 /* MediaSourceSettings.h */, + DFECFB6E172D9E4C00A43CF7 /* Setting.cpp */, + DFECFB6F172D9E4C00A43CF7 /* Setting.h */, + DFECFB70172D9E4C00A43CF7 /* SettingAddon.cpp */, + DFECFB71172D9E4C00A43CF7 /* SettingAddon.h */, + DFECFB72172D9E4C00A43CF7 /* SettingCategoryAccess.cpp */, + DFECFB73172D9E4C00A43CF7 /* SettingCategoryAccess.h */, + DFECFB74172D9E4C00A43CF7 /* SettingConditions.cpp */, + DFECFB75172D9E4C00A43CF7 /* SettingConditions.h */, + DFECFB76172D9E4C00A43CF7 /* SettingControl.cpp */, + DFECFB77172D9E4C00A43CF7 /* SettingControl.h */, + DFECFB78172D9E4C00A43CF7 /* SettingDependency.cpp */, + DFECFB79172D9E4C00A43CF7 /* SettingDependency.h */, + DFECFB7A172D9E4C00A43CF7 /* SettingPath.cpp */, + DFECFB7B172D9E4C00A43CF7 /* SettingPath.h */, F56C76DF131EC153000AD0F6 /* Settings.cpp */, F56C76E0131EC153000AD0F6 /* Settings.h */, + DFECFB7C172D9E4C00A43CF7 /* SettingSection.cpp */, + DFECFB7D172D9E4C00A43CF7 /* SettingSection.h */, + DFECFB7E172D9E4C00A43CF7 /* SettingsManager.cpp */, + DFECFB7F172D9E4C00A43CF7 /* SettingsManager.h */, + DFECFB80172D9E4C00A43CF7 /* SettingUpdate.cpp */, + DFECFB81172D9E4C00A43CF7 /* SettingUpdate.h */, + DFECFB82172D9E4C00A43CF7 /* SettingVisibility.cpp */, + DFECFB83172D9E4C00A43CF7 /* SettingVisibility.h */, DF8990021709B95B00B35C21 /* SkinSettings.cpp */, DF8990031709B95B00B35C21 /* SkinSettings.h */, F56C76E3131EC153000AD0F6 /* VideoSettings.cpp */, @@ -5749,6 +5814,8 @@ DF527785151BAFEE00B5B63B /* Base64.h */, F56C7727131EC154000AD0F6 /* BitstreamStats.cpp */, F56C7728131EC154000AD0F6 /* BitstreamStats.h */, + DFECFB90172D9E6D00A43CF7 /* BooleanLogic.cpp */, + DFECFB91172D9E6D00A43CF7 /* BooleanLogic.h */, F56C7729131EC154000AD0F6 /* CharsetConverter.cpp */, F56C772A131EC154000AD0F6 /* CharsetConverter.h */, F56C772B131EC154000AD0F6 /* CPUInfo.cpp */, @@ -6433,6 +6500,8 @@ 18968DE714155E1D005BA742 /* ApplicationOperations.h */, F5AE40ED1341751E0004BD79 /* AudioLibrary.cpp */, F5AE40EE1341751E0004BD79 /* AudioLibrary.h */, + F5DB701117322DF700D4DF21 /* FavouritesOperations.cpp */, + F5DB701217322DF700D4DF21 /* FavouritesOperations.h */, F5AE40F31341751E0004BD79 /* FileItemHandler.cpp */, F5AE40F41341751E0004BD79 /* FileItemHandler.h */, F5AE40F51341751E0004BD79 /* FileOperations.cpp */, @@ -6832,7 +6901,6 @@ F56C7912131EC154000AD0F6 /* DVDPerformanceCounter.cpp in Sources */, F56C7913131EC154000AD0F6 /* DVDPlayer.cpp in Sources */, F56C7914131EC154000AD0F6 /* DVDPlayerAudio.cpp in Sources */, - F56C7915131EC154000AD0F6 /* DVDPlayerAudioResampler.cpp in Sources */, F56C7916131EC154000AD0F6 /* DVDPlayerSubtitle.cpp in Sources */, F56C7917131EC154000AD0F6 /* DVDPlayerTeletext.cpp in Sources */, F56C7918131EC154000AD0F6 /* DVDPlayerVideo.cpp in Sources */, @@ -6854,7 +6922,6 @@ F56C7928131EC154000AD0F6 /* DVDPlayerCodec.cpp in Sources */, F56C7929131EC154000AD0F6 /* ADPCMCodec.cpp in Sources */, F56C792B131EC154000AD0F6 /* AudioDecoder.cpp in Sources */, - F56C792C131EC154000AD0F6 /* CDDAcodec.cpp in Sources */, F56C792D131EC154000AD0F6 /* CodecFactory.cpp in Sources */, F56C792E131EC154000AD0F6 /* VGMCodec.cpp in Sources */, F56C792F131EC154000AD0F6 /* FLACcodec.cpp in Sources */, @@ -7182,7 +7249,6 @@ F56C7AED131EC155000AD0F6 /* GUIViewStatePrograms.cpp in Sources */, F56C7AEE131EC155000AD0F6 /* GUIWindowPrograms.cpp in Sources */, F56C7AF3131EC155000AD0F6 /* RenderSystem.cpp in Sources */, - F56C7AF9131EC155000AD0F6 /* GUISettings.cpp in Sources */, F56C7AFA131EC155000AD0F6 /* AdvancedSettings.cpp in Sources */, F56C7B00131EC155000AD0F6 /* Settings.cpp in Sources */, F56C7B02131EC155000AD0F6 /* VideoSettings.cpp in Sources */, @@ -7665,7 +7731,6 @@ F563530316E5442F00D21BAD /* UPnPSettings.cpp in Sources */, F563530F16E5446300D21BAD /* GUIDialogContentSettings.cpp in Sources */, F563531216E5446300D21BAD /* GUIDialogSettings.cpp in Sources */, - F563531F16E5446C00D21BAD /* GUISettingControls.cpp in Sources */, F563532016E5446C00D21BAD /* GUIWindowSettings.cpp in Sources */, F563532116E5446C00D21BAD /* GUIWindowSettingsCategory.cpp in Sources */, F563532316E5446C00D21BAD /* GUIWindowSettingsScreenCalibration.cpp in Sources */, @@ -7685,6 +7750,23 @@ 7C87B2EE162CE3F400EF897D /* PlayerController.cpp in Sources */, F52CC6481713ADE900113454 /* DirectoryNodeGrouped.cpp in Sources */, F52CC6D51713BE0D00113454 /* DirectoryNodeGrouped.cpp in Sources */, + DFECFB69172D9E2B00A43CF7 /* GUIControlSettings.cpp in Sources */, + DFECFB84172D9E4C00A43CF7 /* ISetting.cpp in Sources */, + DFECFB85172D9E4C00A43CF7 /* Setting.cpp in Sources */, + DFECFB86172D9E4C00A43CF7 /* SettingAddon.cpp in Sources */, + DFECFB87172D9E4C00A43CF7 /* SettingCategoryAccess.cpp in Sources */, + DFECFB88172D9E4C00A43CF7 /* SettingConditions.cpp in Sources */, + DFECFB89172D9E4C00A43CF7 /* SettingControl.cpp in Sources */, + DFECFB8A172D9E4C00A43CF7 /* SettingDependency.cpp in Sources */, + DFECFB8B172D9E4C00A43CF7 /* SettingPath.cpp in Sources */, + DFECFB8C172D9E4C00A43CF7 /* SettingSection.cpp in Sources */, + DFECFB8D172D9E4C00A43CF7 /* SettingsManager.cpp in Sources */, + DFECFB8E172D9E4C00A43CF7 /* SettingUpdate.cpp in Sources */, + DFECFB8F172D9E4C00A43CF7 /* SettingVisibility.cpp in Sources */, + DFECFB92172D9E6D00A43CF7 /* BooleanLogic.cpp in Sources */, + DFECFBFD172DA58800A43CF7 /* NetworkServices.cpp in Sources */, + F5DB701317322DF700D4DF21 /* FavouritesOperations.cpp in Sources */, + DF52568B1732C4620094A464 /* DVDDemuxCDDA.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/XBMC-IOS.xcodeproj/project.pbxproj b/XBMC-IOS.xcodeproj/project.pbxproj index 354e9a91bf..b7781dfb42 100644 --- a/XBMC-IOS.xcodeproj/project.pbxproj +++ b/XBMC-IOS.xcodeproj/project.pbxproj @@ -138,6 +138,7 @@ DF404A9516B98E4A00D8023E /* imagefactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF404A9216B98E4A00D8023E /* imagefactory.cpp */; }; DF448572140065E10069344B /* PipesManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF44856F140065E10069344B /* PipesManager.cpp */; }; DF4485751400662D0069344B /* AirTunesServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF4485731400662D0069344B /* AirTunesServer.cpp */; }; + DF52567A1732C43E0094A464 /* DVDDemuxCDDA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF5256781732C43E0094A464 /* DVDDemuxCDDA.cpp */; }; DF527757151BAF8200B5B63B /* WebSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF52774E151BAF8200B5B63B /* WebSocket.cpp */; }; DF527758151BAF8200B5B63B /* WebSocketManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF527750151BAF8200B5B63B /* WebSocketManager.cpp */; }; DF527759151BAF8200B5B63B /* WebSocketV13.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF527752151BAF8200B5B63B /* WebSocketV13.cpp */; }; @@ -264,6 +265,21 @@ DFDB00271516403A005079A4 /* MemBufferCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFDB00221516403A005079A4 /* MemBufferCache.cpp */; }; DFDD077316C0B58B000A1F73 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DFDD077216C0B58B000A1F73 /* Default-568h@2x.png */; }; DFE3505B1532535500F84CAA /* IOSKeyboardView.mm in Sources */ = {isa = PBXBuildFile; fileRef = DFE3505A1532535500F84CAA /* IOSKeyboardView.mm */; }; + DFECFAEB172D9C7B00A43CF7 /* GUIControlSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFAE9172D9C7B00A43CF7 /* GUIControlSettings.cpp */; }; + DFECFB39172D9D2800A43CF7 /* ISetting.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB1F172D9D2800A43CF7 /* ISetting.cpp */; }; + DFECFB3A172D9D2800A43CF7 /* Setting.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB23172D9D2800A43CF7 /* Setting.cpp */; }; + DFECFB3B172D9D2800A43CF7 /* SettingAddon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB25172D9D2800A43CF7 /* SettingAddon.cpp */; }; + DFECFB3C172D9D2800A43CF7 /* SettingCategoryAccess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB27172D9D2800A43CF7 /* SettingCategoryAccess.cpp */; }; + DFECFB3D172D9D2800A43CF7 /* SettingConditions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB29172D9D2800A43CF7 /* SettingConditions.cpp */; }; + DFECFB3E172D9D2800A43CF7 /* SettingControl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB2B172D9D2800A43CF7 /* SettingControl.cpp */; }; + DFECFB3F172D9D2800A43CF7 /* SettingDependency.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB2D172D9D2800A43CF7 /* SettingDependency.cpp */; }; + DFECFB40172D9D2800A43CF7 /* SettingPath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB2F172D9D2800A43CF7 /* SettingPath.cpp */; }; + DFECFB41172D9D2800A43CF7 /* SettingSection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB31172D9D2800A43CF7 /* SettingSection.cpp */; }; + DFECFB42172D9D2800A43CF7 /* SettingsManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB33172D9D2800A43CF7 /* SettingsManager.cpp */; }; + DFECFB43172D9D2800A43CF7 /* SettingUpdate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB35172D9D2800A43CF7 /* SettingUpdate.cpp */; }; + DFECFB44172D9D2800A43CF7 /* SettingVisibility.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB37172D9D2800A43CF7 /* SettingVisibility.cpp */; }; + DFECFB47172D9D4900A43CF7 /* BooleanLogic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB45172D9D4900A43CF7 /* BooleanLogic.cpp */; }; + DFECFB4F172D9D8E00A43CF7 /* NetworkServices.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB4D172D9D8E00A43CF7 /* NetworkServices.cpp */; }; DFF7A92315F7C62900D316E9 /* PltMimeType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFF7A91F15F7C62900D316E9 /* PltMimeType.cpp */; }; DFF7A92415F7C62900D316E9 /* PltProtocolInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFF7A92115F7C62900D316E9 /* PltProtocolInfo.cpp */; }; DFF7A93215F7C73B00D316E9 /* NptPosixTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFF7A93015F7C73B00D316E9 /* NptPosixTime.cpp */; }; @@ -276,7 +292,6 @@ F52CC6361713AD5100113454 /* DirectoryNodeGrouped.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F52CC6341713AD5100113454 /* DirectoryNodeGrouped.cpp */; }; F52CC6C71713BDEE00113454 /* DirectoryNodeGrouped.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F52CC6C51713BDEE00113454 /* DirectoryNodeGrouped.cpp */; }; F56352D916E543BD00D21BAD /* UPnPSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56352D716E543BD00D21BAD /* UPnPSettings.cpp */; }; - F56352E916E543F800D21BAD /* GUISettingControls.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56352DD16E543F800D21BAD /* GUISettingControls.cpp */; }; F56352EA16E543F800D21BAD /* GUIWindowSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56352DF16E543F800D21BAD /* GUIWindowSettings.cpp */; }; F56352EB16E543F800D21BAD /* GUIWindowSettingsCategory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56352E116E543F800D21BAD /* GUIWindowSettingsCategory.cpp */; }; F56352ED16E543F800D21BAD /* GUIWindowSettingsScreenCalibration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56352E516E543F800D21BAD /* GUIWindowSettingsScreenCalibration.cpp */; }; @@ -508,7 +523,6 @@ F56C88FF131F42ED000AD0F6 /* DVDPerformanceCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C82B8131F42E7000AD0F6 /* DVDPerformanceCounter.cpp */; }; F56C8900131F42ED000AD0F6 /* DVDPlayer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C82BA131F42E7000AD0F6 /* DVDPlayer.cpp */; }; F56C8901131F42ED000AD0F6 /* DVDPlayerAudio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C82BC131F42E7000AD0F6 /* DVDPlayerAudio.cpp */; }; - F56C8902131F42ED000AD0F6 /* DVDPlayerAudioResampler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C82BE131F42E7000AD0F6 /* DVDPlayerAudioResampler.cpp */; }; F56C8903131F42ED000AD0F6 /* DVDPlayerSubtitle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C82C0131F42E7000AD0F6 /* DVDPlayerSubtitle.cpp */; }; F56C8904131F42ED000AD0F6 /* DVDPlayerTeletext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C82C2131F42E7000AD0F6 /* DVDPlayerTeletext.cpp */; }; F56C8905131F42ED000AD0F6 /* DVDPlayerVideo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C82C4131F42E7000AD0F6 /* DVDPlayerVideo.cpp */; }; @@ -541,7 +555,6 @@ F56C8921131F42ED000AD0F6 /* DVDPlayerCodec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C8308131F42E7000AD0F6 /* DVDPlayerCodec.cpp */; }; F56C8922131F42ED000AD0F6 /* ADPCMCodec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C830A131F42E7000AD0F6 /* ADPCMCodec.cpp */; }; F56C8924131F42ED000AD0F6 /* AudioDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C830E131F42E7000AD0F6 /* AudioDecoder.cpp */; }; - F56C8925131F42ED000AD0F6 /* CDDAcodec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C8311131F42E7000AD0F6 /* CDDAcodec.cpp */; }; F56C8926131F42ED000AD0F6 /* CodecFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C8313131F42E7000AD0F6 /* CodecFactory.cpp */; }; F56C8927131F42ED000AD0F6 /* VGMCodec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C8315131F42E7000AD0F6 /* VGMCodec.cpp */; }; F56C8928131F42ED000AD0F6 /* FLACcodec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C8317131F42E7000AD0F6 /* FLACcodec.cpp */; }; @@ -864,7 +877,6 @@ F56C8ADC131F42ED000AD0F6 /* GUIWindowPrograms.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C86A4131F42EB000AD0F6 /* GUIWindowPrograms.cpp */; }; F56C8ADF131F42ED000AD0F6 /* RenderSystemGLES.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C86AC131F42EB000AD0F6 /* RenderSystemGLES.cpp */; }; F56C8AE0131F42ED000AD0F6 /* RenderSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C86AE131F42EB000AD0F6 /* RenderSystem.cpp */; }; - F56C8AE6131F42ED000AD0F6 /* GUISettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C86BC131F42EB000AD0F6 /* GUISettings.cpp */; }; F56C8AE7131F42ED000AD0F6 /* AdvancedSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C86BE131F42EB000AD0F6 /* AdvancedSettings.cpp */; }; F56C8AED131F42ED000AD0F6 /* Settings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C86CA131F42EB000AD0F6 /* Settings.cpp */; }; F56C8AEF131F42ED000AD0F6 /* VideoSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56C86CE131F42EB000AD0F6 /* VideoSettings.cpp */; }; @@ -1014,6 +1026,7 @@ F5B13DCF1334490D0045076D /* DarwinUtils.mm in Sources */ = {isa = PBXBuildFile; fileRef = F5B13DCE1334490D0045076D /* DarwinUtils.mm */; }; F5BD034F148D496A001B5583 /* CryptThreading.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5BD034D148D496A001B5583 /* CryptThreading.cpp */; }; F5CEE73013D3F9D100225F72 /* DVDOverlayCodecTX3G.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5CEE72F13D3F9D100225F72 /* DVDOverlayCodecTX3G.cpp */; }; + F5DB701A17322E0C00D4DF21 /* FavouritesOperations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5DB701817322E0C00D4DF21 /* FavouritesOperations.cpp */; }; F5E112DB143577A000175026 /* PeripheralBusUSB.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E112B2143577A000175026 /* PeripheralBusUSB.cpp */; }; F5E112DC143577A000175026 /* PeripheralBus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E112B4143577A000175026 /* PeripheralBus.cpp */; }; F5E112E0143577A000175026 /* Peripheral.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E112BD143577A000175026 /* Peripheral.cpp */; }; @@ -1353,6 +1366,8 @@ DF448570140065E10069344B /* PipesManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PipesManager.h; sourceTree = "<group>"; }; DF4485731400662D0069344B /* AirTunesServer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AirTunesServer.cpp; sourceTree = "<group>"; }; DF4485741400662D0069344B /* AirTunesServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AirTunesServer.h; sourceTree = "<group>"; }; + DF5256781732C43E0094A464 /* DVDDemuxCDDA.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DVDDemuxCDDA.cpp; sourceTree = "<group>"; }; + DF5256791732C43E0094A464 /* DVDDemuxCDDA.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DVDDemuxCDDA.h; sourceTree = "<group>"; }; DF52774E151BAF8200B5B63B /* WebSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebSocket.cpp; sourceTree = "<group>"; }; DF52774F151BAF8200B5B63B /* WebSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSocket.h; sourceTree = "<group>"; }; DF527750151BAF8200B5B63B /* WebSocketManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebSocketManager.cpp; sourceTree = "<group>"; }; @@ -1571,6 +1586,38 @@ DFDD077216C0B58B000A1F73 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = "<group>"; }; DFE350591532535500F84CAA /* IOSKeyboardView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOSKeyboardView.h; sourceTree = "<group>"; }; DFE3505A1532535500F84CAA /* IOSKeyboardView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = IOSKeyboardView.mm; sourceTree = "<group>"; }; + DFECFAE9172D9C7B00A43CF7 /* GUIControlSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GUIControlSettings.cpp; path = windows/GUIControlSettings.cpp; sourceTree = "<group>"; }; + DFECFAEA172D9C7B00A43CF7 /* GUIControlSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GUIControlSettings.h; path = windows/GUIControlSettings.h; sourceTree = "<group>"; }; + DFECFB1F172D9D2800A43CF7 /* ISetting.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ISetting.cpp; sourceTree = "<group>"; }; + DFECFB20172D9D2800A43CF7 /* ISetting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ISetting.h; sourceTree = "<group>"; }; + DFECFB21172D9D2800A43CF7 /* ISettingCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ISettingCallback.h; sourceTree = "<group>"; }; + DFECFB22172D9D2800A43CF7 /* ISettingCreator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ISettingCreator.h; sourceTree = "<group>"; }; + DFECFB23172D9D2800A43CF7 /* Setting.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Setting.cpp; sourceTree = "<group>"; }; + DFECFB24172D9D2800A43CF7 /* Setting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Setting.h; sourceTree = "<group>"; }; + DFECFB25172D9D2800A43CF7 /* SettingAddon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingAddon.cpp; sourceTree = "<group>"; }; + DFECFB26172D9D2800A43CF7 /* SettingAddon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingAddon.h; sourceTree = "<group>"; }; + DFECFB27172D9D2800A43CF7 /* SettingCategoryAccess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingCategoryAccess.cpp; sourceTree = "<group>"; }; + DFECFB28172D9D2800A43CF7 /* SettingCategoryAccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingCategoryAccess.h; sourceTree = "<group>"; }; + DFECFB29172D9D2800A43CF7 /* SettingConditions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingConditions.cpp; sourceTree = "<group>"; }; + DFECFB2A172D9D2800A43CF7 /* SettingConditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingConditions.h; sourceTree = "<group>"; }; + DFECFB2B172D9D2800A43CF7 /* SettingControl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingControl.cpp; sourceTree = "<group>"; }; + DFECFB2C172D9D2800A43CF7 /* SettingControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingControl.h; sourceTree = "<group>"; }; + DFECFB2D172D9D2800A43CF7 /* SettingDependency.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingDependency.cpp; sourceTree = "<group>"; }; + DFECFB2E172D9D2800A43CF7 /* SettingDependency.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingDependency.h; sourceTree = "<group>"; }; + DFECFB2F172D9D2800A43CF7 /* SettingPath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingPath.cpp; sourceTree = "<group>"; }; + DFECFB30172D9D2800A43CF7 /* SettingPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingPath.h; sourceTree = "<group>"; }; + DFECFB31172D9D2800A43CF7 /* SettingSection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingSection.cpp; sourceTree = "<group>"; }; + DFECFB32172D9D2800A43CF7 /* SettingSection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingSection.h; sourceTree = "<group>"; }; + DFECFB33172D9D2800A43CF7 /* SettingsManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingsManager.cpp; sourceTree = "<group>"; }; + DFECFB34172D9D2800A43CF7 /* SettingsManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsManager.h; sourceTree = "<group>"; }; + DFECFB35172D9D2800A43CF7 /* SettingUpdate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingUpdate.cpp; sourceTree = "<group>"; }; + DFECFB36172D9D2800A43CF7 /* SettingUpdate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingUpdate.h; sourceTree = "<group>"; }; + DFECFB37172D9D2800A43CF7 /* SettingVisibility.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingVisibility.cpp; sourceTree = "<group>"; }; + DFECFB38172D9D2800A43CF7 /* SettingVisibility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingVisibility.h; sourceTree = "<group>"; }; + DFECFB45172D9D4900A43CF7 /* BooleanLogic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BooleanLogic.cpp; sourceTree = "<group>"; }; + DFECFB46172D9D4900A43CF7 /* BooleanLogic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BooleanLogic.h; sourceTree = "<group>"; }; + DFECFB4D172D9D8E00A43CF7 /* NetworkServices.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkServices.cpp; sourceTree = "<group>"; }; + DFECFB4E172D9D8E00A43CF7 /* NetworkServices.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkServices.h; sourceTree = "<group>"; }; DFF7A91F15F7C62900D316E9 /* PltMimeType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PltMimeType.cpp; sourceTree = "<group>"; }; DFF7A92015F7C62900D316E9 /* PltMimeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PltMimeType.h; sourceTree = "<group>"; }; DFF7A92115F7C62900D316E9 /* PltProtocolInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PltProtocolInfo.cpp; sourceTree = "<group>"; }; @@ -1604,8 +1651,6 @@ F558F61013AFDC3000631E12 /* ThreadLocal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadLocal.h; sourceTree = "<group>"; }; F56352D716E543BD00D21BAD /* UPnPSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UPnPSettings.cpp; sourceTree = "<group>"; }; F56352D816E543BD00D21BAD /* UPnPSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UPnPSettings.h; sourceTree = "<group>"; }; - F56352DD16E543F800D21BAD /* GUISettingControls.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GUISettingControls.cpp; path = windows/GUISettingControls.cpp; sourceTree = "<group>"; }; - F56352DE16E543F800D21BAD /* GUISettingControls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GUISettingControls.h; path = windows/GUISettingControls.h; sourceTree = "<group>"; }; F56352DF16E543F800D21BAD /* GUIWindowSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GUIWindowSettings.cpp; path = windows/GUIWindowSettings.cpp; sourceTree = "<group>"; }; F56352E016E543F800D21BAD /* GUIWindowSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GUIWindowSettings.h; path = windows/GUIWindowSettings.h; sourceTree = "<group>"; }; F56352E116E543F800D21BAD /* GUIWindowSettingsCategory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GUIWindowSettingsCategory.cpp; path = windows/GUIWindowSettingsCategory.cpp; sourceTree = "<group>"; }; @@ -2168,8 +2213,6 @@ F56C82BB131F42E7000AD0F6 /* DVDPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DVDPlayer.h; sourceTree = "<group>"; }; F56C82BC131F42E7000AD0F6 /* DVDPlayerAudio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DVDPlayerAudio.cpp; sourceTree = "<group>"; }; F56C82BD131F42E7000AD0F6 /* DVDPlayerAudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DVDPlayerAudio.h; sourceTree = "<group>"; }; - F56C82BE131F42E7000AD0F6 /* DVDPlayerAudioResampler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DVDPlayerAudioResampler.cpp; sourceTree = "<group>"; }; - F56C82BF131F42E7000AD0F6 /* DVDPlayerAudioResampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DVDPlayerAudioResampler.h; sourceTree = "<group>"; }; F56C82C0131F42E7000AD0F6 /* DVDPlayerSubtitle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DVDPlayerSubtitle.cpp; sourceTree = "<group>"; }; F56C82C1131F42E7000AD0F6 /* DVDPlayerSubtitle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DVDPlayerSubtitle.h; sourceTree = "<group>"; }; F56C82C2131F42E7000AD0F6 /* DVDPlayerTeletext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DVDPlayerTeletext.cpp; sourceTree = "<group>"; }; @@ -2241,8 +2284,6 @@ F56C830E131F42E7000AD0F6 /* AudioDecoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AudioDecoder.cpp; sourceTree = "<group>"; }; F56C830F131F42E7000AD0F6 /* AudioDecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioDecoder.h; sourceTree = "<group>"; }; F56C8310131F42E7000AD0F6 /* CachingCodec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CachingCodec.h; sourceTree = "<group>"; }; - F56C8311131F42E7000AD0F6 /* CDDAcodec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CDDAcodec.cpp; sourceTree = "<group>"; }; - F56C8312131F42E7000AD0F6 /* CDDAcodec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDDAcodec.h; sourceTree = "<group>"; }; F56C8313131F42E7000AD0F6 /* CodecFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodecFactory.cpp; sourceTree = "<group>"; }; F56C8314131F42E7000AD0F6 /* CodecFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodecFactory.h; sourceTree = "<group>"; }; F56C8315131F42E7000AD0F6 /* VGMCodec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VGMCodec.cpp; sourceTree = "<group>"; }; @@ -2909,8 +2950,6 @@ F56C86AD131F42EB000AD0F6 /* RenderSystemGLES.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSystemGLES.h; sourceTree = "<group>"; }; F56C86AE131F42EB000AD0F6 /* RenderSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSystem.cpp; sourceTree = "<group>"; }; F56C86AF131F42EB000AD0F6 /* RenderSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSystem.h; sourceTree = "<group>"; }; - F56C86BC131F42EB000AD0F6 /* GUISettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUISettings.cpp; sourceTree = "<group>"; }; - F56C86BD131F42EB000AD0F6 /* GUISettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUISettings.h; sourceTree = "<group>"; }; F56C86BE131F42EB000AD0F6 /* AdvancedSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AdvancedSettings.cpp; sourceTree = "<group>"; }; F56C86BF131F42EB000AD0F6 /* AdvancedSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AdvancedSettings.h; sourceTree = "<group>"; }; F56C86CA131F42EB000AD0F6 /* Settings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Settings.cpp; sourceTree = "<group>"; }; @@ -3217,6 +3256,8 @@ F5BD034E148D496A001B5583 /* CryptThreading.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CryptThreading.h; sourceTree = "<group>"; }; F5CEE72F13D3F9D100225F72 /* DVDOverlayCodecTX3G.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DVDOverlayCodecTX3G.cpp; sourceTree = "<group>"; }; F5CEE73113D3F9D800225F72 /* DVDOverlayCodecTX3G.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DVDOverlayCodecTX3G.h; sourceTree = "<group>"; }; + F5DB701817322E0C00D4DF21 /* FavouritesOperations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FavouritesOperations.cpp; sourceTree = "<group>"; }; + F5DB701917322E0C00D4DF21 /* FavouritesOperations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FavouritesOperations.h; sourceTree = "<group>"; }; F5E112B2143577A000175026 /* PeripheralBusUSB.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PeripheralBusUSB.cpp; sourceTree = "<group>"; }; F5E112B3143577A000175026 /* PeripheralBusUSB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PeripheralBusUSB.h; sourceTree = "<group>"; }; F5E112B4143577A000175026 /* PeripheralBus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PeripheralBus.cpp; sourceTree = "<group>"; }; @@ -3828,8 +3869,8 @@ F56352DB16E543DE00D21BAD /* windows */ = { isa = PBXGroup; children = ( - F56352DD16E543F800D21BAD /* GUISettingControls.cpp */, - F56352DE16E543F800D21BAD /* GUISettingControls.h */, + DFECFAE9172D9C7B00A43CF7 /* GUIControlSettings.cpp */, + DFECFAEA172D9C7B00A43CF7 /* GUIControlSettings.h */, F56352DF16E543F800D21BAD /* GUIWindowSettings.cpp */, F56352E016E543F800D21BAD /* GUIWindowSettings.h */, F56352E116E543F800D21BAD /* GUIWindowSettingsCategory.cpp */, @@ -4732,8 +4773,6 @@ F56C82BB131F42E7000AD0F6 /* DVDPlayer.h */, F56C82BC131F42E7000AD0F6 /* DVDPlayerAudio.cpp */, F56C82BD131F42E7000AD0F6 /* DVDPlayerAudio.h */, - F56C82BE131F42E7000AD0F6 /* DVDPlayerAudioResampler.cpp */, - F56C82BF131F42E7000AD0F6 /* DVDPlayerAudioResampler.h */, F56C82C0131F42E7000AD0F6 /* DVDPlayerSubtitle.cpp */, F56C82C1131F42E7000AD0F6 /* DVDPlayerSubtitle.h */, F56C82C2131F42E7000AD0F6 /* DVDPlayerTeletext.cpp */, @@ -4870,6 +4909,8 @@ F56C827F131F42E7000AD0F6 /* DVDDemux.h */, DF24EADC1621E67200034265 /* DVDDemuxBXA.cpp */, DF24EADD1621E67200034265 /* DVDDemuxBXA.h */, + DF5256781732C43E0094A464 /* DVDDemuxCDDA.cpp */, + DF5256791732C43E0094A464 /* DVDDemuxCDDA.h */, F56C827A131F42E7000AD0F6 /* DVDDemuxFFmpeg.cpp */, F56C827B131F42E7000AD0F6 /* DVDDemuxFFmpeg.h */, F56C827C131F42E7000AD0F6 /* DVDDemuxHTSP.cpp */, @@ -5029,8 +5070,6 @@ F56C830E131F42E7000AD0F6 /* AudioDecoder.cpp */, F56C830F131F42E7000AD0F6 /* AudioDecoder.h */, F56C8310131F42E7000AD0F6 /* CachingCodec.h */, - F56C8311131F42E7000AD0F6 /* CDDAcodec.cpp */, - F56C8312131F42E7000AD0F6 /* CDDAcodec.h */, F56C8313131F42E7000AD0F6 /* CodecFactory.cpp */, F56C8314131F42E7000AD0F6 /* CodecFactory.h */, F56C8308131F42E7000AD0F6 /* DVDPlayerCodec.cpp */, @@ -5896,6 +5935,8 @@ F56C8645131F42EB000AD0F6 /* GUIDialogNetworkSetup.h */, F56C8646131F42EB000AD0F6 /* Network.cpp */, F56C8647131F42EB000AD0F6 /* Network.h */, + DFECFB4D172D9D8E00A43CF7 /* NetworkServices.cpp */, + DFECFB4E172D9D8E00A43CF7 /* NetworkServices.h */, F56C8648131F42EB000AD0F6 /* Socket.cpp */, F56C8649131F42EB000AD0F6 /* Socket.h */, F56C864A131F42EB000AD0F6 /* TCPServer.cpp */, @@ -6072,16 +6113,40 @@ F56C86BF131F42EB000AD0F6 /* AdvancedSettings.h */, DF28EE0A170E1E78005FA9D2 /* DisplaySettings.cpp */, DF28EE0B170E1E78005FA9D2 /* DisplaySettings.h */, - F56C86BC131F42EB000AD0F6 /* GUISettings.cpp */, - F56C86BD131F42EB000AD0F6 /* GUISettings.h */, + DFECFB1F172D9D2800A43CF7 /* ISetting.cpp */, + DFECFB20172D9D2800A43CF7 /* ISetting.h */, + DFECFB21172D9D2800A43CF7 /* ISettingCallback.h */, + DFECFB22172D9D2800A43CF7 /* ISettingCreator.h */, DF898FBA1709B8E600B35C21 /* ISettingsHandler.h */, DF898FBB1709B8E600B35C21 /* ISubSettings.h */, DF898FBC1709B8E600B35C21 /* MediaSettings.cpp */, DF898FBD1709B8E600B35C21 /* MediaSettings.h */, DF898FBE1709B8E600B35C21 /* MediaSourceSettings.cpp */, DF898FBF1709B8E600B35C21 /* MediaSourceSettings.h */, + DFECFB23172D9D2800A43CF7 /* Setting.cpp */, + DFECFB24172D9D2800A43CF7 /* Setting.h */, + DFECFB25172D9D2800A43CF7 /* SettingAddon.cpp */, + DFECFB26172D9D2800A43CF7 /* SettingAddon.h */, + DFECFB27172D9D2800A43CF7 /* SettingCategoryAccess.cpp */, + DFECFB28172D9D2800A43CF7 /* SettingCategoryAccess.h */, + DFECFB29172D9D2800A43CF7 /* SettingConditions.cpp */, + DFECFB2A172D9D2800A43CF7 /* SettingConditions.h */, + DFECFB2B172D9D2800A43CF7 /* SettingControl.cpp */, + DFECFB2C172D9D2800A43CF7 /* SettingControl.h */, + DFECFB2D172D9D2800A43CF7 /* SettingDependency.cpp */, + DFECFB2E172D9D2800A43CF7 /* SettingDependency.h */, + DFECFB2F172D9D2800A43CF7 /* SettingPath.cpp */, + DFECFB30172D9D2800A43CF7 /* SettingPath.h */, F56C86CA131F42EB000AD0F6 /* Settings.cpp */, F56C86CB131F42EB000AD0F6 /* Settings.h */, + DFECFB31172D9D2800A43CF7 /* SettingSection.cpp */, + DFECFB32172D9D2800A43CF7 /* SettingSection.h */, + DFECFB33172D9D2800A43CF7 /* SettingsManager.cpp */, + DFECFB34172D9D2800A43CF7 /* SettingsManager.h */, + DFECFB35172D9D2800A43CF7 /* SettingUpdate.cpp */, + DFECFB36172D9D2800A43CF7 /* SettingUpdate.h */, + DFECFB37172D9D2800A43CF7 /* SettingVisibility.cpp */, + DFECFB38172D9D2800A43CF7 /* SettingVisibility.h */, DF898FC01709B8E600B35C21 /* SkinSettings.cpp */, DF898FC11709B8E600B35C21 /* SkinSettings.h */, F56C86CE131F42EB000AD0F6 /* VideoSettings.cpp */, @@ -6160,6 +6225,8 @@ DF52775D151BAFA000B5B63B /* Base64.h */, F56C8716131F42EC000AD0F6 /* BitstreamStats.cpp */, F56C8717131F42EC000AD0F6 /* BitstreamStats.h */, + DFECFB45172D9D4900A43CF7 /* BooleanLogic.cpp */, + DFECFB46172D9D4900A43CF7 /* BooleanLogic.h */, F56C8718131F42EC000AD0F6 /* CharsetConverter.cpp */, F56C8719131F42EC000AD0F6 /* CharsetConverter.h */, F56C871A131F42EC000AD0F6 /* CPUInfo.cpp */, @@ -6492,6 +6559,8 @@ 18968DDD14155E01005BA742 /* ApplicationOperations.h */, F5AE4140134175520004BD79 /* AudioLibrary.cpp */, F5AE4141134175520004BD79 /* AudioLibrary.h */, + F5DB701817322E0C00D4DF21 /* FavouritesOperations.cpp */, + F5DB701917322E0C00D4DF21 /* FavouritesOperations.h */, F5AE4146134175520004BD79 /* FileItemHandler.cpp */, F5AE4147134175520004BD79 /* FileItemHandler.h */, F5AE4148134175520004BD79 /* FileOperations.cpp */, @@ -6975,7 +7044,6 @@ F56C88FF131F42ED000AD0F6 /* DVDPerformanceCounter.cpp in Sources */, F56C8900131F42ED000AD0F6 /* DVDPlayer.cpp in Sources */, F56C8901131F42ED000AD0F6 /* DVDPlayerAudio.cpp in Sources */, - F56C8902131F42ED000AD0F6 /* DVDPlayerAudioResampler.cpp in Sources */, F56C8903131F42ED000AD0F6 /* DVDPlayerSubtitle.cpp in Sources */, F56C8904131F42ED000AD0F6 /* DVDPlayerTeletext.cpp in Sources */, F56C8905131F42ED000AD0F6 /* DVDPlayerVideo.cpp in Sources */, @@ -7008,7 +7076,6 @@ F56C8921131F42ED000AD0F6 /* DVDPlayerCodec.cpp in Sources */, F56C8922131F42ED000AD0F6 /* ADPCMCodec.cpp in Sources */, F56C8924131F42ED000AD0F6 /* AudioDecoder.cpp in Sources */, - F56C8925131F42ED000AD0F6 /* CDDAcodec.cpp in Sources */, F56C8926131F42ED000AD0F6 /* CodecFactory.cpp in Sources */, F56C8927131F42ED000AD0F6 /* VGMCodec.cpp in Sources */, F56C8928131F42ED000AD0F6 /* FLACcodec.cpp in Sources */, @@ -7331,7 +7398,6 @@ F56C8ADC131F42ED000AD0F6 /* GUIWindowPrograms.cpp in Sources */, F56C8ADF131F42ED000AD0F6 /* RenderSystemGLES.cpp in Sources */, F56C8AE0131F42ED000AD0F6 /* RenderSystem.cpp in Sources */, - F56C8AE6131F42ED000AD0F6 /* GUISettings.cpp in Sources */, F56C8AE7131F42ED000AD0F6 /* AdvancedSettings.cpp in Sources */, F56C8AED131F42ED000AD0F6 /* Settings.cpp in Sources */, F56C8AEF131F42ED000AD0F6 /* VideoSettings.cpp in Sources */, @@ -7731,7 +7797,6 @@ DFD5813116C829350008EEA0 /* DAVCommon.cpp in Sources */, DFD5813216C829350008EEA0 /* DAVFile.cpp in Sources */, F56352D916E543BD00D21BAD /* UPnPSettings.cpp in Sources */, - F56352E916E543F800D21BAD /* GUISettingControls.cpp in Sources */, F56352EA16E543F800D21BAD /* GUIWindowSettings.cpp in Sources */, F56352EB16E543F800D21BAD /* GUIWindowSettingsCategory.cpp in Sources */, F56352ED16E543F800D21BAD /* GUIWindowSettingsScreenCalibration.cpp in Sources */, @@ -7756,6 +7821,23 @@ 7C87B2DA162CE3C300EF897D /* PlayerController.cpp in Sources */, F52CC6361713AD5100113454 /* DirectoryNodeGrouped.cpp in Sources */, F52CC6C71713BDEE00113454 /* DirectoryNodeGrouped.cpp in Sources */, + DFECFAEB172D9C7B00A43CF7 /* GUIControlSettings.cpp in Sources */, + DFECFB39172D9D2800A43CF7 /* ISetting.cpp in Sources */, + DFECFB3A172D9D2800A43CF7 /* Setting.cpp in Sources */, + DFECFB3B172D9D2800A43CF7 /* SettingAddon.cpp in Sources */, + DFECFB3C172D9D2800A43CF7 /* SettingCategoryAccess.cpp in Sources */, + DFECFB3D172D9D2800A43CF7 /* SettingConditions.cpp in Sources */, + DFECFB3E172D9D2800A43CF7 /* SettingControl.cpp in Sources */, + DFECFB3F172D9D2800A43CF7 /* SettingDependency.cpp in Sources */, + DFECFB40172D9D2800A43CF7 /* SettingPath.cpp in Sources */, + DFECFB41172D9D2800A43CF7 /* SettingSection.cpp in Sources */, + DFECFB42172D9D2800A43CF7 /* SettingsManager.cpp in Sources */, + DFECFB43172D9D2800A43CF7 /* SettingUpdate.cpp in Sources */, + DFECFB44172D9D2800A43CF7 /* SettingVisibility.cpp in Sources */, + DFECFB47172D9D4900A43CF7 /* BooleanLogic.cpp in Sources */, + DFECFB4F172D9D8E00A43CF7 /* NetworkServices.cpp in Sources */, + F5DB701A17322E0C00D4DF21 /* FavouritesOperations.cpp in Sources */, + DF52567A1732C43E0094A464 /* DVDDemuxCDDA.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/XBMC.xcodeproj/project.pbxproj b/XBMC.xcodeproj/project.pbxproj index 7d41f3f165..2bff3c31c8 100644 --- a/XBMC.xcodeproj/project.pbxproj +++ b/XBMC.xcodeproj/project.pbxproj @@ -137,7 +137,6 @@ 18B7C8A0129423A7009E7A26 /* MusicInfoTagLoaderSPC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B7C87E129423A7009E7A26 /* MusicInfoTagLoaderSPC.cpp */; }; 18B7C8A1129423A7009E7A26 /* MusicInfoTagLoaderWav.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B7C880129423A7009E7A26 /* MusicInfoTagLoaderWav.cpp */; }; 18B7C8A4129423A7009E7A26 /* MusicInfoTagLoaderYM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B7C886129423A7009E7A26 /* MusicInfoTagLoaderYM.cpp */; }; - 18B7C8C412942451009E7A26 /* GUISettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B7C8C212942451009E7A26 /* GUISettings.cpp */; }; 18B7C8D712942546009E7A26 /* ButtonTranslator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B7C8CB12942546009E7A26 /* ButtonTranslator.cpp */; }; 18B7C8D812942546009E7A26 /* KeyboardLayoutConfiguration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B7C8CD12942546009E7A26 /* KeyboardLayoutConfiguration.cpp */; }; 18B7C8D912942546009E7A26 /* KeyboardStat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B7C8CF12942546009E7A26 /* KeyboardStat.cpp */; }; @@ -396,6 +395,7 @@ DF404A3A16B9896C00D8023E /* imagefactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF404A3716B9896C00D8023E /* imagefactory.cpp */; }; DF448457140048A60069344B /* AirTunesServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF448455140048A60069344B /* AirTunesServer.cpp */; }; DF44845E140048C80069344B /* PipesManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF44845B140048C80069344B /* PipesManager.cpp */; }; + DF52566D1732C1890094A464 /* DVDDemuxCDDA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF52566B1732C1890094A464 /* DVDDemuxCDDA.cpp */; }; DF5276E1151BAEDA00B5B63B /* Base64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF52769A151BAEDA00B5B63B /* Base64.cpp */; }; DF5276E2151BAEDA00B5B63B /* HttpResponse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF52769C151BAEDA00B5B63B /* HttpResponse.cpp */; }; DF527734151BAF4C00B5B63B /* WebSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF52772B151BAF4C00B5B63B /* WebSocket.cpp */; }; @@ -502,6 +502,21 @@ DFD5812616C828500008EEA0 /* DAVFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFD5812316C828500008EEA0 /* DAVFile.cpp */; }; DFD928F316384B6800709DAE /* Timer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFD928F116384B6800709DAE /* Timer.cpp */; }; DFDA3153160E34230047A626 /* DVDOverlayCodec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFDA3152160E34230047A626 /* DVDOverlayCodec.cpp */; }; + DFECFADF172D9C5100A43CF7 /* GUIControlSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFADD172D9C5100A43CF7 /* GUIControlSettings.cpp */; }; + DFECFB07172D9CAB00A43CF7 /* ISetting.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFAEE172D9CAB00A43CF7 /* ISetting.cpp */; }; + DFECFB08172D9CAB00A43CF7 /* Setting.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFAF2172D9CAB00A43CF7 /* Setting.cpp */; }; + DFECFB09172D9CAB00A43CF7 /* SettingAddon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFAF4172D9CAB00A43CF7 /* SettingAddon.cpp */; }; + DFECFB0A172D9CAB00A43CF7 /* SettingCategoryAccess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFAF6172D9CAB00A43CF7 /* SettingCategoryAccess.cpp */; }; + DFECFB0B172D9CAB00A43CF7 /* SettingConditions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFAF8172D9CAB00A43CF7 /* SettingConditions.cpp */; }; + DFECFB0C172D9CAB00A43CF7 /* SettingControl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFAFA172D9CAB00A43CF7 /* SettingControl.cpp */; }; + DFECFB0D172D9CAB00A43CF7 /* SettingDependency.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFAFC172D9CAB00A43CF7 /* SettingDependency.cpp */; }; + DFECFB0E172D9CAB00A43CF7 /* SettingPath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFAFE172D9CAB00A43CF7 /* SettingPath.cpp */; }; + DFECFB0F172D9CAB00A43CF7 /* SettingSection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB00172D9CAB00A43CF7 /* SettingSection.cpp */; }; + DFECFB10172D9CAB00A43CF7 /* SettingsManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB02172D9CAB00A43CF7 /* SettingsManager.cpp */; }; + DFECFB11172D9CAB00A43CF7 /* SettingUpdate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB03172D9CAB00A43CF7 /* SettingUpdate.cpp */; }; + DFECFB12172D9CAB00A43CF7 /* SettingVisibility.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB05172D9CAB00A43CF7 /* SettingVisibility.cpp */; }; + DFECFB1C172D9D0100A43CF7 /* BooleanLogic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB1A172D9D0100A43CF7 /* BooleanLogic.cpp */; }; + DFECFB4C172D9D6D00A43CF7 /* NetworkServices.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFECFB4A172D9D6D00A43CF7 /* NetworkServices.cpp */; }; E306D12E0DDF7B590052C2AD /* XBMCHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E306D12C0DDF7B590052C2AD /* XBMCHelper.cpp */; }; E33206380D5070AA00435CE3 /* DVDDemuxVobsub.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E33206370D5070AA00435CE3 /* DVDDemuxVobsub.cpp */; }; E33466A60D2E5103005A65EC /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E33466A50D2E5103005A65EC /* IOKit.framework */; }; @@ -586,7 +601,6 @@ E38E1FAF0D25F9FD00618676 /* DVDSubtitleStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38E15960D25F9FA00618676 /* DVDSubtitleStream.cpp */; }; E38E1FC10D25F9FD00618676 /* ADPCMCodec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38E15DB0D25F9FA00618676 /* ADPCMCodec.cpp */; }; E38E1FC50D25F9FD00618676 /* AudioDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38E15E30D25F9FA00618676 /* AudioDecoder.cpp */; }; - E38E1FC60D25F9FD00618676 /* CDDAcodec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38E15E60D25F9FA00618676 /* CDDAcodec.cpp */; }; E38E1FC70D25F9FD00618676 /* CodecFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38E15E80D25F9FA00618676 /* CodecFactory.cpp */; }; E38E1FCB0D25F9FD00618676 /* FLACcodec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38E160A0D25F9FA00618676 /* FLACcodec.cpp */; }; E38E1FCF0D25F9FD00618676 /* MP3codec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38E16130D25F9FA00618676 /* MP3codec.cpp */; }; @@ -948,7 +962,6 @@ F563529616E53FAB00D21BAD /* UPnPSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F563529416E53FAB00D21BAD /* UPnPSettings.cpp */; settings = {COMPILER_FLAGS = "-I$SRCROOT/lib/libUPnP/Platinum/Source/Core -I$SRCROOT/lib/libUPnP/Platinum/Source/Platinum -I$SRCROOT/lib/libUPnP/Platinum/Source/Devices/MediaConnect -I$SRCROOT/lib/libUPnP/Platinum/Source/Devices/MediaRenderer -I$SRCROOT/lib/libUPnP/Platinum/Source/Devices/MediaServer -I$SRCROOT/lib/libUPnP/Platinum/Source/Extras -I$SRCROOT/lib/libUPnP/Neptune/Source/System/Posix -I$SRCROOT/lib/libUPnP/Neptune/Source/Core"; }; }; F56352AA16E5402100D21BAD /* GUIDialogContentSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56352A216E5402100D21BAD /* GUIDialogContentSettings.cpp */; }; F56352AD16E5402100D21BAD /* GUIDialogSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56352A816E5402100D21BAD /* GUIDialogSettings.cpp */; }; - F56352BA16E5403400D21BAD /* GUISettingControls.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56352AE16E5403400D21BAD /* GUISettingControls.cpp */; }; F56352BB16E5403400D21BAD /* GUIWindowSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56352B016E5403400D21BAD /* GUIWindowSettings.cpp */; }; F56352BC16E5403400D21BAD /* GUIWindowSettingsCategory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56352B216E5403400D21BAD /* GUIWindowSettingsCategory.cpp */; }; F56352BE16E5403400D21BAD /* GUIWindowSettingsScreenCalibration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F56352B616E5403400D21BAD /* GUIWindowSettingsScreenCalibration.cpp */; }; @@ -965,7 +978,6 @@ F58E293911FFC103006F4D46 /* DVDInputStreamBluray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F58E293711FFC103006F4D46 /* DVDInputStreamBluray.cpp */; }; F592568810FBF2E100D2C91D /* ConvolutionKernels.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F592568710FBF2E100D2C91D /* ConvolutionKernels.cpp */; }; F595994510E9F322004B58B3 /* DVDVideoCodecCrystalHD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F595994410E9F322004B58B3 /* DVDVideoCodecCrystalHD.cpp */; }; - F59876BC0FBA34C0008EF4FB /* DVDPlayerAudioResampler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F59876BA0FBA34C0008EF4FB /* DVDPlayerAudioResampler.cpp */; }; F59876C00FBA351D008EF4FB /* VideoReferenceClock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F59876BF0FBA351D008EF4FB /* VideoReferenceClock.cpp */; }; F59879080FBAA0C3008EF4FB /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F59879070FBAA0C3008EF4FB /* QuartzCore.framework */; }; F5987F050FBDF274008EF4FB /* DPMSSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5987F040FBDF274008EF4FB /* DPMSSupport.cpp */; }; @@ -998,6 +1010,7 @@ F5D8D732102BB3B1004A11AB /* OverlayRendererGL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5D8D72F102BB3B1004A11AB /* OverlayRendererGL.cpp */; }; F5D8D733102BB3B1004A11AB /* OverlayRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5D8D731102BB3B1004A11AB /* OverlayRenderer.cpp */; }; F5D8EF5B103912A4004A11AB /* DVDSubtitleParserVplayer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5D8EF59103912A4004A11AB /* DVDSubtitleParserVplayer.cpp */; }; + F5DB700217322DBB00D4DF21 /* FavouritesOperations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5DB700017322DBB00D4DF21 /* FavouritesOperations.cpp */; }; F5DC87E2110A287400EE1B15 /* RingBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5DC87E1110A287400EE1B15 /* RingBuffer.cpp */; }; F5DC8801110A46C700EE1B15 /* ModplugCodec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5DC8800110A46C700EE1B15 /* ModplugCodec.cpp */; }; F5E10537140AA38100175026 /* PeripheralBusUSB.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E10513140AA38000175026 /* PeripheralBusUSB.cpp */; }; @@ -1302,8 +1315,6 @@ 18B7C881129423A7009E7A26 /* MusicInfoTagLoaderWav.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MusicInfoTagLoaderWav.h; sourceTree = "<group>"; }; 18B7C886129423A7009E7A26 /* MusicInfoTagLoaderYM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MusicInfoTagLoaderYM.cpp; sourceTree = "<group>"; }; 18B7C887129423A7009E7A26 /* MusicInfoTagLoaderYM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MusicInfoTagLoaderYM.h; sourceTree = "<group>"; }; - 18B7C8C212942451009E7A26 /* GUISettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUISettings.cpp; sourceTree = "<group>"; }; - 18B7C8C312942451009E7A26 /* GUISettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUISettings.h; sourceTree = "<group>"; }; 18B7C8CB12942546009E7A26 /* ButtonTranslator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ButtonTranslator.cpp; sourceTree = "<group>"; }; 18B7C8CC12942546009E7A26 /* ButtonTranslator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ButtonTranslator.h; sourceTree = "<group>"; }; 18B7C8CD12942546009E7A26 /* KeyboardLayoutConfiguration.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KeyboardLayoutConfiguration.cpp; sourceTree = "<group>"; }; @@ -1912,6 +1923,8 @@ DF448456140048A60069344B /* AirTunesServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AirTunesServer.h; sourceTree = "<group>"; }; DF44845B140048C80069344B /* PipesManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PipesManager.cpp; sourceTree = "<group>"; }; DF44845C140048C80069344B /* PipesManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PipesManager.h; sourceTree = "<group>"; }; + DF52566B1732C1890094A464 /* DVDDemuxCDDA.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DVDDemuxCDDA.cpp; sourceTree = "<group>"; }; + DF52566C1732C1890094A464 /* DVDDemuxCDDA.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DVDDemuxCDDA.h; sourceTree = "<group>"; }; DF52769A151BAEDA00B5B63B /* Base64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Base64.cpp; sourceTree = "<group>"; }; DF52769B151BAEDA00B5B63B /* Base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Base64.h; sourceTree = "<group>"; }; DF52769C151BAEDA00B5B63B /* HttpResponse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HttpResponse.cpp; sourceTree = "<group>"; }; @@ -2083,6 +2096,37 @@ DFD928F116384B6800709DAE /* Timer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Timer.cpp; sourceTree = "<group>"; }; DFD928F216384B6800709DAE /* Timer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Timer.h; sourceTree = "<group>"; }; DFDA3152160E34230047A626 /* DVDOverlayCodec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DVDOverlayCodec.cpp; sourceTree = "<group>"; }; + DFECFADD172D9C5100A43CF7 /* GUIControlSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GUIControlSettings.cpp; path = windows/GUIControlSettings.cpp; sourceTree = "<group>"; }; + DFECFADE172D9C5100A43CF7 /* GUIControlSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GUIControlSettings.h; path = windows/GUIControlSettings.h; sourceTree = "<group>"; }; + DFECFAEE172D9CAB00A43CF7 /* ISetting.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ISetting.cpp; sourceTree = "<group>"; }; + DFECFAEF172D9CAB00A43CF7 /* ISetting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ISetting.h; sourceTree = "<group>"; }; + DFECFAF0172D9CAB00A43CF7 /* ISettingCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ISettingCallback.h; sourceTree = "<group>"; }; + DFECFAF1172D9CAB00A43CF7 /* ISettingCreator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ISettingCreator.h; sourceTree = "<group>"; }; + DFECFAF2172D9CAB00A43CF7 /* Setting.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Setting.cpp; sourceTree = "<group>"; }; + DFECFAF3172D9CAB00A43CF7 /* Setting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Setting.h; sourceTree = "<group>"; }; + DFECFAF4172D9CAB00A43CF7 /* SettingAddon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingAddon.cpp; sourceTree = "<group>"; }; + DFECFAF5172D9CAB00A43CF7 /* SettingAddon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingAddon.h; sourceTree = "<group>"; }; + DFECFAF6172D9CAB00A43CF7 /* SettingCategoryAccess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingCategoryAccess.cpp; sourceTree = "<group>"; }; + DFECFAF7172D9CAB00A43CF7 /* SettingCategoryAccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingCategoryAccess.h; sourceTree = "<group>"; }; + DFECFAF8172D9CAB00A43CF7 /* SettingConditions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingConditions.cpp; sourceTree = "<group>"; }; + DFECFAF9172D9CAB00A43CF7 /* SettingConditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingConditions.h; sourceTree = "<group>"; }; + DFECFAFA172D9CAB00A43CF7 /* SettingControl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingControl.cpp; sourceTree = "<group>"; }; + DFECFAFB172D9CAB00A43CF7 /* SettingControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingControl.h; sourceTree = "<group>"; }; + DFECFAFC172D9CAB00A43CF7 /* SettingDependency.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingDependency.cpp; sourceTree = "<group>"; }; + DFECFAFD172D9CAB00A43CF7 /* SettingDependency.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingDependency.h; sourceTree = "<group>"; }; + DFECFAFE172D9CAB00A43CF7 /* SettingPath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingPath.cpp; sourceTree = "<group>"; }; + DFECFAFF172D9CAB00A43CF7 /* SettingPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingPath.h; sourceTree = "<group>"; }; + DFECFB00172D9CAB00A43CF7 /* SettingSection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingSection.cpp; sourceTree = "<group>"; }; + DFECFB01172D9CAB00A43CF7 /* SettingSection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingSection.h; sourceTree = "<group>"; }; + DFECFB02172D9CAB00A43CF7 /* SettingsManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingsManager.cpp; sourceTree = "<group>"; }; + DFECFB03172D9CAB00A43CF7 /* SettingUpdate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingUpdate.cpp; sourceTree = "<group>"; }; + DFECFB04172D9CAB00A43CF7 /* SettingUpdate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingUpdate.h; sourceTree = "<group>"; }; + DFECFB05172D9CAB00A43CF7 /* SettingVisibility.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingVisibility.cpp; sourceTree = "<group>"; }; + DFECFB06172D9CAB00A43CF7 /* SettingVisibility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingVisibility.h; sourceTree = "<group>"; }; + DFECFB1A172D9D0100A43CF7 /* BooleanLogic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BooleanLogic.cpp; sourceTree = "<group>"; }; + DFECFB1B172D9D0100A43CF7 /* BooleanLogic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BooleanLogic.h; sourceTree = "<group>"; }; + DFECFB4A172D9D6D00A43CF7 /* NetworkServices.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkServices.cpp; sourceTree = "<group>"; }; + DFECFB4B172D9D6D00A43CF7 /* NetworkServices.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkServices.h; sourceTree = "<group>"; }; E306D12C0DDF7B590052C2AD /* XBMCHelper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XBMCHelper.cpp; sourceTree = "<group>"; }; E306D12D0DDF7B590052C2AD /* XBMCHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XBMCHelper.h; sourceTree = "<group>"; }; E33206370D5070AA00435CE3 /* DVDDemuxVobsub.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DVDDemuxVobsub.cpp; sourceTree = "<group>"; }; @@ -2280,8 +2324,6 @@ E38E15E30D25F9FA00618676 /* AudioDecoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AudioDecoder.cpp; sourceTree = "<group>"; }; E38E15E40D25F9FA00618676 /* AudioDecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioDecoder.h; sourceTree = "<group>"; }; E38E15E50D25F9FA00618676 /* CachingCodec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CachingCodec.h; sourceTree = "<group>"; }; - E38E15E60D25F9FA00618676 /* CDDAcodec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CDDAcodec.cpp; sourceTree = "<group>"; }; - E38E15E70D25F9FA00618676 /* CDDAcodec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDDAcodec.h; sourceTree = "<group>"; }; E38E15E80D25F9FA00618676 /* CodecFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodecFactory.cpp; sourceTree = "<group>"; }; E38E15E90D25F9FA00618676 /* CodecFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodecFactory.h; sourceTree = "<group>"; }; E38E15EF0D25F9FA00618676 /* DllAdpcm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DllAdpcm.h; sourceTree = "<group>"; }; @@ -3080,8 +3122,6 @@ F56352A316E5402100D21BAD /* GUIDialogContentSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GUIDialogContentSettings.h; path = dialogs/GUIDialogContentSettings.h; sourceTree = "<group>"; }; F56352A816E5402100D21BAD /* GUIDialogSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GUIDialogSettings.cpp; path = dialogs/GUIDialogSettings.cpp; sourceTree = "<group>"; }; F56352A916E5402100D21BAD /* GUIDialogSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GUIDialogSettings.h; path = dialogs/GUIDialogSettings.h; sourceTree = "<group>"; }; - F56352AE16E5403400D21BAD /* GUISettingControls.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GUISettingControls.cpp; path = windows/GUISettingControls.cpp; sourceTree = "<group>"; }; - F56352AF16E5403400D21BAD /* GUISettingControls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GUISettingControls.h; path = windows/GUISettingControls.h; sourceTree = "<group>"; }; F56352B016E5403400D21BAD /* GUIWindowSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GUIWindowSettings.cpp; path = windows/GUIWindowSettings.cpp; sourceTree = "<group>"; }; F56352B116E5403400D21BAD /* GUIWindowSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GUIWindowSettings.h; path = windows/GUIWindowSettings.h; sourceTree = "<group>"; }; F56352B216E5403400D21BAD /* GUIWindowSettingsCategory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GUIWindowSettingsCategory.cpp; path = windows/GUIWindowSettingsCategory.cpp; sourceTree = "<group>"; }; @@ -3112,8 +3152,6 @@ F592568710FBF2E100D2C91D /* ConvolutionKernels.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConvolutionKernels.cpp; sourceTree = "<group>"; }; F595994310E9F322004B58B3 /* DVDVideoCodecCrystalHD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DVDVideoCodecCrystalHD.h; sourceTree = "<group>"; }; F595994410E9F322004B58B3 /* DVDVideoCodecCrystalHD.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DVDVideoCodecCrystalHD.cpp; sourceTree = "<group>"; }; - F59876BA0FBA34C0008EF4FB /* DVDPlayerAudioResampler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DVDPlayerAudioResampler.cpp; sourceTree = "<group>"; }; - F59876BB0FBA34C0008EF4FB /* DVDPlayerAudioResampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DVDPlayerAudioResampler.h; sourceTree = "<group>"; }; F59876BE0FBA351D008EF4FB /* VideoReferenceClock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VideoReferenceClock.h; sourceTree = "<group>"; }; F59876BF0FBA351D008EF4FB /* VideoReferenceClock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VideoReferenceClock.cpp; sourceTree = "<group>"; }; F59879070FBAA0C3008EF4FB /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = /System/Library/Frameworks/QuartzCore.framework; sourceTree = "<absolute>"; }; @@ -3181,6 +3219,8 @@ F5D8D731102BB3B1004A11AB /* OverlayRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OverlayRenderer.cpp; sourceTree = "<group>"; }; F5D8EF59103912A4004A11AB /* DVDSubtitleParserVplayer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DVDSubtitleParserVplayer.cpp; sourceTree = "<group>"; }; F5D8EF5A103912A4004A11AB /* DVDSubtitleParserVplayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DVDSubtitleParserVplayer.h; sourceTree = "<group>"; }; + F5DB700017322DBB00D4DF21 /* FavouritesOperations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FavouritesOperations.cpp; sourceTree = "<group>"; }; + F5DB700117322DBB00D4DF21 /* FavouritesOperations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FavouritesOperations.h; sourceTree = "<group>"; }; F5DC87E0110A287400EE1B15 /* RingBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RingBuffer.h; sourceTree = "<group>"; }; F5DC87E1110A287400EE1B15 /* RingBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RingBuffer.cpp; sourceTree = "<group>"; }; F5DC87FF110A46C700EE1B15 /* ModplugCodec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModplugCodec.h; sourceTree = "<group>"; }; @@ -3984,6 +4024,8 @@ E38E17C10D25F9FA00618676 /* GUIDialogNetworkSetup.h */, E38E1E6B0D25F9FD00618676 /* Network.cpp */, E38E1E6C0D25F9FD00618676 /* Network.h */, + DFECFB4A172D9D6D00A43CF7 /* NetworkServices.cpp */, + DFECFB4B172D9D6D00A43CF7 /* NetworkServices.h */, E3E91FFC0D8C61DF002BF43D /* Socket.cpp */, 6E97BDC40DA2B620003A2A89 /* Socket.h */, 432D7CF612D870E800CE4C49 /* TCPServer.cpp */, @@ -4999,8 +5041,6 @@ E38E15850D25F9FA00618676 /* DVDPlayer.h */, E38E15860D25F9FA00618676 /* DVDPlayerAudio.cpp */, E38E15870D25F9FA00618676 /* DVDPlayerAudio.h */, - F59876BA0FBA34C0008EF4FB /* DVDPlayerAudioResampler.cpp */, - F59876BB0FBA34C0008EF4FB /* DVDPlayerAudioResampler.h */, E38E15880D25F9FA00618676 /* DVDPlayerSubtitle.cpp */, E38E15890D25F9FA00618676 /* DVDPlayerSubtitle.h */, F5E55B5B10741272006E788A /* DVDPlayerTeletext.cpp */, @@ -5135,6 +5175,8 @@ E38E154A0D25F9F900618676 /* DVDDemux.h */, AE89ACA41621DAB800E17DBC /* DVDDemuxBXA.cpp */, AE89ACA51621DAB800E17DBC /* DVDDemuxBXA.h */, + DF52566B1732C1890094A464 /* DVDDemuxCDDA.cpp */, + DF52566C1732C1890094A464 /* DVDDemuxCDDA.h */, E38E25C20D263DE200618676 /* DVDDemuxFFmpeg.cpp */, E38E154C0D25F9F900618676 /* DVDDemuxFFmpeg.h */, F55110440F5C3C0000955236 /* DVDDemuxHTSP.cpp */, @@ -5247,8 +5289,6 @@ E38E15E30D25F9FA00618676 /* AudioDecoder.cpp */, E38E15E40D25F9FA00618676 /* AudioDecoder.h */, E38E15E50D25F9FA00618676 /* CachingCodec.h */, - E38E15E60D25F9FA00618676 /* CDDAcodec.cpp */, - E38E15E70D25F9FA00618676 /* CDDAcodec.h */, E38E15E80D25F9FA00618676 /* CodecFactory.cpp */, E38E15E90D25F9FA00618676 /* CodecFactory.h */, E36578860D3AA7B40033CC1C /* DVDPlayerCodec.cpp */, @@ -6103,16 +6143,39 @@ 18B7C3A712942132009E7A26 /* AdvancedSettings.h */, DF28EE01170E1E51005FA9D2 /* DisplaySettings.cpp */, DF28EE02170E1E51005FA9D2 /* DisplaySettings.h */, - 18B7C8C212942451009E7A26 /* GUISettings.cpp */, - 18B7C8C312942451009E7A26 /* GUISettings.h */, + DFECFAEE172D9CAB00A43CF7 /* ISetting.cpp */, + DFECFAEF172D9CAB00A43CF7 /* ISetting.h */, + DFECFAF0172D9CAB00A43CF7 /* ISettingCallback.h */, + DFECFAF1172D9CAB00A43CF7 /* ISettingCreator.h */, DF8990141709BB2D00B35C21 /* ISettingsHandler.h */, DF8990151709BB2D00B35C21 /* ISubSettings.h */, DF8990161709BB2D00B35C21 /* MediaSettings.cpp */, DF8990171709BB2D00B35C21 /* MediaSettings.h */, DF8990181709BB2D00B35C21 /* MediaSourceSettings.cpp */, DF8990191709BB2D00B35C21 /* MediaSourceSettings.h */, + DFECFAF2172D9CAB00A43CF7 /* Setting.cpp */, + DFECFAF3172D9CAB00A43CF7 /* Setting.h */, + DFECFAF4172D9CAB00A43CF7 /* SettingAddon.cpp */, + DFECFAF5172D9CAB00A43CF7 /* SettingAddon.h */, + DFECFAF6172D9CAB00A43CF7 /* SettingCategoryAccess.cpp */, + DFECFAF7172D9CAB00A43CF7 /* SettingCategoryAccess.h */, + DFECFAF8172D9CAB00A43CF7 /* SettingConditions.cpp */, + DFECFAF9172D9CAB00A43CF7 /* SettingConditions.h */, + DFECFAFA172D9CAB00A43CF7 /* SettingControl.cpp */, + DFECFAFB172D9CAB00A43CF7 /* SettingControl.h */, + DFECFAFC172D9CAB00A43CF7 /* SettingDependency.cpp */, + DFECFAFD172D9CAB00A43CF7 /* SettingDependency.h */, + DFECFAFE172D9CAB00A43CF7 /* SettingPath.cpp */, + DFECFAFF172D9CAB00A43CF7 /* SettingPath.h */, 18B7C38E129420E5009E7A26 /* Settings.cpp */, 18B7C38F129420E5009E7A26 /* Settings.h */, + DFECFB00172D9CAB00A43CF7 /* SettingSection.cpp */, + DFECFB01172D9CAB00A43CF7 /* SettingSection.h */, + DFECFB02172D9CAB00A43CF7 /* SettingsManager.cpp */, + DFECFB03172D9CAB00A43CF7 /* SettingUpdate.cpp */, + DFECFB04172D9CAB00A43CF7 /* SettingUpdate.h */, + DFECFB05172D9CAB00A43CF7 /* SettingVisibility.cpp */, + DFECFB06172D9CAB00A43CF7 /* SettingVisibility.h */, DF89901A1709BB2D00B35C21 /* SkinSettings.cpp */, DF89901B1709BB2D00B35C21 /* SkinSettings.h */, E38E1E010D25F9FD00618676 /* VideoSettings.cpp */, @@ -6140,6 +6203,8 @@ F56353BE16E9BB3500D21BAD /* BitstreamConverter.h */, E38E1E270D25F9FD00618676 /* BitstreamStats.cpp */, E38E1E280D25F9FD00618676 /* BitstreamStats.h */, + DFECFB1A172D9D0100A43CF7 /* BooleanLogic.cpp */, + DFECFB1B172D9D0100A43CF7 /* BooleanLogic.h */, E38E1E290D25F9FD00618676 /* CharsetConverter.cpp */, E38E1E2A0D25F9FD00618676 /* CharsetConverter.h */, E38E1E2B0D25F9FD00618676 /* CPUInfo.cpp */, @@ -6310,6 +6375,8 @@ F563529F16E53FE900D21BAD /* dialogs */ = { isa = PBXGroup; children = ( + DFECFADD172D9C5100A43CF7 /* GUIControlSettings.cpp */, + DFECFADE172D9C5100A43CF7 /* GUIControlSettings.h */, F56352A216E5402100D21BAD /* GUIDialogContentSettings.cpp */, F56352A316E5402100D21BAD /* GUIDialogContentSettings.h */, F56352A816E5402100D21BAD /* GUIDialogSettings.cpp */, @@ -6321,8 +6388,6 @@ F56352A016E53FF300D21BAD /* windows */ = { isa = PBXGroup; children = ( - F56352AE16E5403400D21BAD /* GUISettingControls.cpp */, - F56352AF16E5403400D21BAD /* GUISettingControls.h */, F56352B016E5403400D21BAD /* GUIWindowSettings.cpp */, F56352B116E5403400D21BAD /* GUIWindowSettings.h */, F56352B216E5403400D21BAD /* GUIWindowSettingsCategory.cpp */, @@ -6355,6 +6420,8 @@ 18968DC714155D7C005BA742 /* ApplicationOperations.h */, F5AE408013415D9E0004BD79 /* AudioLibrary.cpp */, F5AE408113415D9E0004BD79 /* AudioLibrary.h */, + F5DB700017322DBB00D4DF21 /* FavouritesOperations.cpp */, + F5DB700117322DBB00D4DF21 /* FavouritesOperations.h */, F5AE408613415D9E0004BD79 /* FileItemHandler.cpp */, F5AE408713415D9E0004BD79 /* FileItemHandler.h */, F5AE408813415D9E0004BD79 /* FileOperations.cpp */, @@ -6827,7 +6894,6 @@ E38E1FAF0D25F9FD00618676 /* DVDSubtitleStream.cpp in Sources */, E38E1FC10D25F9FD00618676 /* ADPCMCodec.cpp in Sources */, E38E1FC50D25F9FD00618676 /* AudioDecoder.cpp in Sources */, - E38E1FC60D25F9FD00618676 /* CDDAcodec.cpp in Sources */, E38E1FC70D25F9FD00618676 /* CodecFactory.cpp in Sources */, E38E1FCB0D25F9FD00618676 /* FLACcodec.cpp in Sources */, E38E1FCF0D25F9FD00618676 /* MP3codec.cpp in Sources */, @@ -7197,7 +7263,6 @@ E43196180FB2382E0030E150 /* HTSPSession.cpp in Sources */, F5AACA680FB3DE2D00DBB77C /* GUIDialogSelect.cpp in Sources */, F5AACA970FB3E2B800DBB77C /* GUIDialogSlider.cpp in Sources */, - F59876BC0FBA34C0008EF4FB /* DVDPlayerAudioResampler.cpp in Sources */, F59876C00FBA351D008EF4FB /* VideoReferenceClock.cpp in Sources */, 83A72B970FBC8E3B00171871 /* LockFree.cpp in Sources */, F5987F050FBDF274008EF4FB /* DPMSSupport.cpp in Sources */, @@ -7424,7 +7489,6 @@ 18B7C8A0129423A7009E7A26 /* MusicInfoTagLoaderSPC.cpp in Sources */, 18B7C8A1129423A7009E7A26 /* MusicInfoTagLoaderWav.cpp in Sources */, 18B7C8A4129423A7009E7A26 /* MusicInfoTagLoaderYM.cpp in Sources */, - 18B7C8C412942451009E7A26 /* GUISettings.cpp in Sources */, 18B7C8D712942546009E7A26 /* ButtonTranslator.cpp in Sources */, 18B7C8D812942546009E7A26 /* KeyboardLayoutConfiguration.cpp in Sources */, 18B7C8D912942546009E7A26 /* KeyboardStat.cpp in Sources */, @@ -7735,7 +7799,6 @@ F563529616E53FAB00D21BAD /* UPnPSettings.cpp in Sources */, F56352AA16E5402100D21BAD /* GUIDialogContentSettings.cpp in Sources */, F56352AD16E5402100D21BAD /* GUIDialogSettings.cpp in Sources */, - F56352BA16E5403400D21BAD /* GUISettingControls.cpp in Sources */, F56352BB16E5403400D21BAD /* GUIWindowSettings.cpp in Sources */, F56352BC16E5403400D21BAD /* GUIWindowSettingsCategory.cpp in Sources */, F56352BE16E5403400D21BAD /* GUIWindowSettingsScreenCalibration.cpp in Sources */, @@ -7756,6 +7819,23 @@ 7C87B2CE162CE39600EF897D /* PlayerController.cpp in Sources */, F52CC5F01713AAA200113454 /* DirectoryNodeGrouped.cpp in Sources */, F52CC6AA1713BD2B00113454 /* DirectoryNodeGrouped.cpp in Sources */, + DFECFADF172D9C5100A43CF7 /* GUIControlSettings.cpp in Sources */, + DFECFB07172D9CAB00A43CF7 /* ISetting.cpp in Sources */, + DFECFB08172D9CAB00A43CF7 /* Setting.cpp in Sources */, + DFECFB09172D9CAB00A43CF7 /* SettingAddon.cpp in Sources */, + DFECFB0A172D9CAB00A43CF7 /* SettingCategoryAccess.cpp in Sources */, + DFECFB0B172D9CAB00A43CF7 /* SettingConditions.cpp in Sources */, + DFECFB0C172D9CAB00A43CF7 /* SettingControl.cpp in Sources */, + DFECFB0D172D9CAB00A43CF7 /* SettingDependency.cpp in Sources */, + DFECFB0E172D9CAB00A43CF7 /* SettingPath.cpp in Sources */, + DFECFB0F172D9CAB00A43CF7 /* SettingSection.cpp in Sources */, + DFECFB10172D9CAB00A43CF7 /* SettingsManager.cpp in Sources */, + DFECFB11172D9CAB00A43CF7 /* SettingUpdate.cpp in Sources */, + DFECFB12172D9CAB00A43CF7 /* SettingVisibility.cpp in Sources */, + DFECFB1C172D9D0100A43CF7 /* BooleanLogic.cpp in Sources */, + DFECFB4C172D9D6D00A43CF7 /* NetworkServices.cpp in Sources */, + F5DB700217322DBB00D4DF21 /* FavouritesOperations.cpp in Sources */, + DF52566D1732C1890094A464 /* DVDDemuxCDDA.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/addons/metadata.album.universal/addon.xml b/addons/metadata.album.universal/addon.xml index b4b3f1704c..248230c990 100644 --- a/addons/metadata.album.universal/addon.xml +++ b/addons/metadata.album.universal/addon.xml @@ -1,26 +1,28 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon id="metadata.album.universal" name="Universal Album Scraper" - version="1.6.4" + version="1.7.6" provider-name="Olympia, Team XBMC"> <requires> - <import addon="xbmc.metadata" version="1.0"/> - <import addon="metadata.common.last.fm" version="1.3.2"/> - <import addon="metadata.common.allmusic.com" version="2.3.1"/> + <import addon="xbmc.metadata" version="2.1.0"/> + <import addon="metadata.common.last.fm" version="1.5.1"/> + <import addon="metadata.common.allmusic.com" version="2.5.2"/> <import addon="metadata.common.musicbrainz.org" version="1.2.3"/> - <import addon="metadata.common.fanart.tv" version="2.0.0"/> + <import addon="metadata.common.fanart.tv" version="2.1.2"/> <import addon="metadata.common.amazon.de" version="1.0.0"/> - <import addon="metadata.common.theaudiodb.com" version="1.3.0"/> + <import addon="metadata.common.theaudiodb.com" version="1.4.0"/> </requires> <extension point="xbmc.metadata.scraper.albums" language="en" library="albumuniversal.xml"/> <extension point="xbmc.addon.metadata"> <summary lang="af">Universele Skraper vir Albums</summary> + <summary lang="ast">Scraper universal pa álbumes</summary> <summary lang="be">Universal Scraper for Albums</summary> <summary lang="bg">УниверÑален източник за Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° албуми</summary> <summary lang="ca">Arreplegador universal per à lbums</summary> <summary lang="cs">Univerzálnà zdroj zÃskávánà dat pro alba</summary> + <summary lang="cy">Crafwr Albymau Cyffredinol</summary> <summary lang="da">Universel Scraper til Albummer</summary> <summary lang="de">Universeller Scraper für Alben</summary> <summary lang="el">Universal Scraper Άλμπουμ</summary> @@ -28,9 +30,10 @@ <summary lang="es">Scraper universal para álbumes</summary> <summary lang="es_AR">Scraper Universal para Albumes</summary> <summary lang="es_MX">Scraper Universal para Ãlbumes</summary> + <summary lang="et">Universaalne albumite kraabits</summary> <summary lang="fi">Universaali tiedonhakija albumitiedoille</summary> <summary lang="fr">Scraper universel pour les Albums</summary> - <summary lang="gl">Scraper universal para os álbumes</summary> + <summary lang="gl">Scraper Universal para Ãlbums</summary> <summary lang="he">סקרייפר ××•× ×™×‘×¨×¡×œ×™ עבור ×לבומי×</summary> <summary lang="hu">Univerzális album leolvasó</summary> <summary lang="it">Ricercatore Universale per Albums</summary> @@ -48,12 +51,18 @@ <summary lang="sk">Univerzálny zdroj zÃskavania dát pre albumy</summary> <summary lang="sl">Univerzalni ponudnik informacij o albumih</summary> <summary lang="sv">Universiell albumskrapa</summary> + <summary lang="ta_IN">ஆலà¯à®ªà®™à¯à®•à®³à®¿à®©à¯ ஒடà¯à®Ÿà¯ மொதà¯à®¤à®®à®¾à®© சà¯à®°à®£à¯à®Ÿà®¿</summary> + <summary lang="uk">УніверÑальний здирач Ð´Ð»Ñ Ð°Ð»ÑŒÐ±Ð¾Ð¼Ñ–Ð²</summary> + <summary lang="vi">Trình lấy dữ liệu album từ nhiá»u nguồn</summary> <summary lang="zh">通用音ä¹ä¸“辑信æ¯åˆ®å‰Šå™¨</summary> + <summary lang="zh_TW">通用音樂專輯訊æ¯æœåˆ®å™¨</summary> <description lang="af">Hierdie skraper kollekteer inligting vanaf die volgende ondersteunde werwe: MusicBrainz, last.fm, allmusic.com en amazon.de, terwyl kunswerke gegryp word vanaf: fanart.tv, last.fm en allmusic.com. Dit kan veld vir veld gestel word vanaf watter werf jy die spesifieke inligting wil hê. Die aanvaklike soektog word altyd op MusicBrainz gedoen. Ingeval skakels van allmusic en/of amazon.de nie bygevoeg is op die MusicBrainz werf, kan velde vanaf allmusic.com en/of amazon.de nie gaan haal word nie (egter baie maklik om daardie ontbrekende skakels by te voeg).</description> + <description lang="ast">Esti scraper recueye información de les siguientes webs: MusicBrainz, last.fm, allmusic.com y amazon.de, mentanto obtién les imáxenes de fanart.tv, last.fm y allmusic.com. Permite especificar de qué web se quier obtener la información pa cada campu. ⎠⎠La gueta inicial faise siempre en MusicBrainz. En casu de que los enllaces a allmusic y/o amazon.de nun tean amestaos na web de MusicBrainz, nun van poder obtenese los campos d'información d' estos dos sitios (magar que ye mui fácil amestar esos enllaces que falten)</description> <description lang="be">This scraper collects information from the following supported sites: MusicBrainz, last.fm, allmusic.com and amazon.de, while grabs artwork from: fanart.tv, last.fm and allmusic.com. It can be set field by field that from which site you want that specific information. The initial search is always done on MusicBrainz. In case allmusic and/or amazon.de links are not added on the MusicBrainz site, fields from allmusic.com and/or amazon.de cannot be fetched (very easy to add those missing links though).</description> <description lang="bg">Ð¡Ð²Ð°Ð»Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾Ñ‚ Ñледните Ñайтове: MusicBrainz, last.fm, allmusic.com и amazon.de. Ð˜Ð·Ð¾Ð±Ñ€Ð°Ð½Ð¸Ñ Ð¸Ð·Ð²Ð»Ð¸Ñ‡Ð° от: fanart.tv, last.fm и allmusic.com. Можете да определите от кой Ñайт каква Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð´Ð° Ñе ÑвалÑ. Първоначалното Ñ‚ÑŠÑ€Ñене винаги Ñе прави в MusicBrainz. Когато не Ñа налични препратки към allmusic и/или amazon.de на Ñайта на MusicBrainz извличането на Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾Ñ‚ allmusic.com и/или amazon.de Ñтава невъзможно (добавÑнето им е много леÑно).</description> <description lang="ca">Aquest arreplegador recull informació dels següents llocs: MusicBrainz, last.fm, allmusic.com i amazon.de, alhora que agafa art de: fanart.tv, last.fm i allmusic.com. Es pot configurar camp a camp des de quin lloc voleu aquella informació especÃfica. La cerca inicial es realitza sempre a MusicBrainz. En el cas que els enllaços d'allmusic i amazon.de no s'afegeixin al lloc MusicBrainz els camps d'allmusic i amazon.de i/o amazon.com no es poden obtenir (tot i que són fà cils d'afegir aquests enllaços restants).</description> <description lang="cs">Tento zdroj zÃskává data z následujÃcÃch podporovaných stránek: MusicBrainz, last.fm, allmusic.com and amazon.de, while grabs artwork from: fanart.tv, last.fm a allmusic.com. Je možno podrobnÄ› nastavit, které informace si pÅ™ejete zÃskat ze kterých stránek. Prvotnà vyhledánà je vžy provedeno na MusicBrainz. V pÅ™ÃpadÄ›, že odkaz pro allmusic a nebo amazon.de nenà pÅ™idaný na stránku MusicBrainz, nenà možné údaje z allmusic.com a amazon.de stáhnout (avÅ¡ak je velmi snadné tyto chybÄ›jÃcà odkazy pÅ™idat).</description> + <description lang="cy">Mae'r crafwr yn casglu gwybodaeth o'r gwefannau canlynol: MusicBrainz, last.fm, allmusic.com ac amazon.de, tra'n cipio gwaith celf o: fanart.tv, last.fm and allmusic.com. Mae modd ei osod fesul maes i ddewis pa wefan i gasglu gwybodaeth benodol. Bydd y chwilio cychwynnol yn cael ei wneud ar MusicBrainz. Rhag ofn nad yw dolen allmusic wedi ei osod ar wefan MusicBrainz nid oes modd estyn meysydd o allmusic.com (mae'n hawdd gosod y dolenni coll hynny)</description> <description lang="da">Denne scraper samler information fra følgende sider: MusicBrainz, last.fm, allmusic.com og amazon.de og henter illustrationer fra: fanart.tv, last.fm og allmusic.com. Det kan vælges felt for felt, hvilke sider du ønsker, at fÃ¥ den pÃ¥gældende information fra. Den første søgning er altid pÃ¥ MusicBrainz. Hvis ikke allmusic og/eller amazon.de linkene er tilføjet pÃ¥ MusicBrainz side, kan felter fra allmusic.com og/eller amazon.de ikke hentes (men det er helt enkelt at tilføje de manglende links).</description> <description lang="de">Dieser Scaper sammelt Informationen von den folgenden unterstützten Seiten: MusicBrainz, Last.fm, Allmusic.com und Amazon.de und lädt dabei Grafiken von: Fanart.tv, Last.fm und Allmusic.com. Es kann eingestellt werden, von welcher Seite die spezifischen Informationen stammen.⎠⎠Die initialie Suche wird immer über MusicBrainz durchgeführt. Sollten keine Allmusic- und/oder Amazon.de-Links auf der MusicBrainz-Seite gesetzt worden sein, können Felder von Allmusic.com und/oder Amazon.de nicht geladen werden (fehlende Links können jedoch sehr einfach hinzugefügt werden).</description> <description lang="el">Αυτό το scraper συλλÎγει πληÏοφοÏίες από τις ακόλουθες υποστηÏιζόμενες ιστοσελίδες: MusicBrainz, last.fm, allmusic.com και amazon.de, ενώ λαμβάνει εικόνες από τα: fanart.tv, last.fm και allmusic.com. ΜποÏεί να οÏιστεί πεδίο ανά πεδίο αναλόγως των πληÏοφοÏιών που επιθυμείτε από την εκάστοτε ιστοσελίδα. Η αÏχική αναζήτηση γίνεται πάντα στο MusicBrainz. Σε πεÏίπτωση που δεν Îχουν Ï€Ïοστεθεί σÏνδεσμοι για το allmusic ή/και το amazon.de στο MusicBrainz, δε θα μποÏοÏν να ληφθοÏν πεδία από το allmusic.com ή/και το amazon.de (ωστόσο είναι Ï€Î¿Î»Ï ÎµÏκολο να Ï€ÏοστεθοÏν αυτοί οι ελλιπείς σÏνδεσμοι).</description> @@ -61,6 +70,7 @@ <description lang="es">Este scraper recolecta información de las siguientes webs: MusicBrainz, last.fm, allmusic.com y amazon.de, mientras obtiene las imágenes de fanart.tv, last.fm y allmusic.com. Permite especificar de qué web se quiere obtener la información para cada campo. ⎠⎠La búsqueda inicial se realiza siempre en MusicBrainz. En caso de que los enlaces a allmusic y/o amazon.de no estén añadidos en la web de MusicBrainz, no se podrán obtener los campos de información de estos dos sitios (aunque es muy fácil añadir esos enlaces que faltan).</description> <description lang="es_AR">Este scraper recolecta información de las siguientes webs: MusicBrainz, last.fm, allmusic.com y amazon.de, mientras obtiene las imágenes de fanart.tv, last.fm y allmusic.com. Permite especificar de qué web se quiere obtener la información para cada campo. ⎠⎠La búsqueda inicial se realiza siempre en MusicBrainz. En caso de que los enlaces a allmusic y/o amazon.de no estén añadidos en la web de MusicBrainz, no se podrán obtener los campos de información de estos dos sitios (aunque es muy fácil añadir esos enlaces que faltan).</description> <description lang="es_MX">Este scraper obtiene información de los siguientes sitios soportados: MusicBrainz, last.fm, allmusic.com y amazon.de, mientras obtiene artwork de: fanart.tv, last.fm y allmusic.com. Puede ser configurado campo por campo de que sitio quieres esa información especÃfica.⎠⎠La búsqueda inicial siempre es hecha en MusicBrainz. En el caso en que los enlaces de allmusic y/o amazon.de no son agregados en el sitio de MusicBrainz, campos de allmusic.com y/o amazon.de no pueden ser obtenidos. (De cualquier manera es muy fácil agregar esos enlaces no encontrados).</description> + <description lang="et">See kraabits kogub infot järgmistelt lehtedelt: MusicBrainz, last.fm, allmusic.com ja amazon.de, pilte: fanart.tv, last.fm ja allmusic.com. Saad välja kaupa määrata, milliselt lehelt mis infot soovid. Esmane otsing tehakse alati saidilt MusicBrainz. Kui MusicBrainz lehele pole allmusic ja/või amazon.de linke lisatud, siis neilt lehtedelt sisu hankida ei saa (puuduvaid linke saad ise lihtsalt lisada).</description> <description lang="fi">Tämä tiedonhakija käyttää tietolähteinään seuraavia sivustoja:MusicBrainz, last.fm, allmusic.com ja amazon.de. Kuvat ja grafiikat haetaan seuraavilta sivustoilta: fanart.tv, last.fm ja allmusic.com. Voit määrittää tarkasti, miltä sivustoilta mitäkin tietoa haetaan. Ensimmäinen haku tehdään aina lähteestä MusicBrainz. Mikäli allmusic- ja/tai amazon.de-linkkejä ei ole lisätty MusicBrainz-sivustolle, haku ei onnistu (mutta puuttuvien linkkien lisääminen on helppoa).</description> <description lang="fr">Ce collecteur utilise les informations des sites suivant : MusicBrainz, last.fm, allmusic.com et amazon.de et télécharge les artwork depuis : fanart.tv, last.fm et allmusic.com. Vous pouvez spécifier quel site utiliser pour chaque information à employer. Le premier résultat est toujours en provenance de MusicBrainz. Dans le cas où allmusic et/ou amazon.de ne sont pas ajoutés sur le site MusicBrainz, les champs de allmusic.com et/ou amazon.de ne peuvent pas être traités (il est toutefois très simple d'ajouter ces liens manquants).</description> <description lang="gl">Este scraper obtén a información dende os seguintes sitios soportados: MusicBrainz, last.fm, allmusic.com e amazon.de, mentres que as ilustracións as obtén dende: fanart.tv, last.fm e allmusic.com. Pódese definir dende que sitios se obterá a información especÃfica de cada campo. A busca inicial faise sempre en MusicBrainz. No caso de non estar engadidas as ligazón de allmusic e/ou amazon.de no sitio de MusicBrainz, os campos de allmusic.com e/ou amazon.de non se poderán obter (aÃnda que é moi doado de engadir as ligazóns).</description> @@ -68,7 +78,7 @@ <description lang="hu">A leolvasó szöveges infókat gyűjt a támogatott oldalakról: MusicBrainz, last.fm, allmusic.com and amazon.de, valamint képeket a : fanart.tv, last.fm and allmusic.com-ról. BeállÃtható hogy honnan, és milyen infót gyűjtsön. A keresés mindig a MusicBrainz-on folyik, de könnyen hozzáadhatjuk a hiányzó találatokat az allmusic.com, vagy az amazon.de-rÅ‘l.</description> <description lang="it">Questo ricercatore prende informazioni dai seguenti siti: MusicBrainz, last.fm, allmusic.com e amazon.de, mentre prende grafica da: fanart.tv, last.fm e allmusic.com. Puoi impostare campo per campo cosa prendere e da dove.⎠âŽLa ricerca iniziale viene sempre fatta su MusicBrainz. In caso i links a allmusic e/o amazon.de non sono stati messi su MusicBrainz, i campi da questi siti non possono essere recuperati (è molto facile aggiungere quei link, comunque).</description> <description lang="ja">ã“ã®ã‚¹ã‚¯ãƒ¬ãƒ¼ãƒ‘ーã¯ã€ä»¥ä¸‹ã®ã‚µã‚¤ãƒˆã‹ã‚‰æƒ…å ±ã‚’å–å¾—ã—ã¾ã™ï¼šMusicBrainz, last.fm, allmusic.com, amazon.de。アートワークã¯ä»¥ä¸‹ã®ã‚µã‚¤ãƒˆã‹ã‚‰å–å¾—ã—ã¾ã™ï¼šfanart.tv, last.fm, allmusic.com。å„フィールドã”ã¨ã«ã€ã©ã®æƒ…å ±ã‚’ã©ã®ã‚µã‚¤ãƒˆã‹ã‚‰å–å¾—ã™ã‚‹ã‹ã€å€‹åˆ¥ã«æŒ‡å®šã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚ 最åˆã¯ MusicBrainz を使ã£ã¦æ¤œç´¢ãŒè¡Œã‚ã‚Œã¾ã™ã€‚MusicBrainz サイト㫠allmusic ã‚„ amazon.de ã®ãƒªãƒ³ã‚¯ãŒè¿½åŠ ã•ã‚Œã¦ã„ãªã„å ´åˆã¯ã€allmusic.com / amazon.de ã‹ã‚‰ã®ãƒ•ã‚£ãƒ¼ãƒ«ãƒ‰ã¯å–å¾—ã§ãã¾ã›ã‚“ (ãƒªãƒ³ã‚¯ã‚’è¿½åŠ ã™ã‚‹ã®ã¯ç°¡å˜ã§ã™ãŒ)。</description> - <description lang="ko">This scraper collects information from the following supported sites: MusicBrainz, last.fm, allmusic.com and amazon.de, while grabs artwork from: fanart.tv, last.fm and allmusic.com. It can be set field by field that from which site you want that specific information. The initial search is always done on MusicBrainz. In case allmusic and/or amazon.de links are not added on the MusicBrainz site, fields from allmusic.com and/or amazon.de cannot be fetched (very easy to add those missing links though).</description> + <description lang="ko">ì´ ìžë£Œìˆ˜ì§‘기는 다ìŒì˜ 사ì´íŠ¸ì—ì„œ ì •ë³´ë¥¼ ê°€ì ¸ì˜µë‹ˆë‹¤: MusicBrainz, last.fm, allmusic.com, amazon.de. 아트워í¬ëŠ” 다ìŒì˜ 사ì´íŠ¸ì—ì„œ ê°€ì ¸ì˜µë‹ˆë‹¤: fanart.tv, last.fm and allmusic.com. íŠ¹ì • ì •ë³´ë¥¼ ì§€ì •í•œ 사ì´íŠ¸ì—ì„œ ê°€ì ¸ì˜¤ë„ë¡ í•„ë“œë³„ë¡œ ì„¤ì •í• ìˆ˜ 있습니다 The initial search is always done on MusicBrainz. In case allmusic and/or amazon.de links are not added on the MusicBrainz site, fields from allmusic.com and/or amazon.de cannot be fetched (very easy to add those missing links though).</description> <description lang="lt">Å is Scrapers renka informacijÄ… iÅ¡ Å¡ių palaikomų svetainių: MusicBrainz, last.fm, allmusic.com ir/arba amazon.de, o scrap meno kÅ«rinius iÅ¡: fanart.tv, last.fm ir/arba allmusic.com. Jis gali bÅ«ti nustatytas srities lauke, iÅ¡ kurio puslapio norite, kad konkreÄiÄ… informacijÄ… paimtu. PradinÄ— paieÅ¡ka visada atliekama remiantis MusicBrainz. Jei Allmusic ir/ar amazon.de nuorodos nÄ—ra įdÄ—tos MusicBrainz svetainÄ—je, laukuose allmusic.com ir/arba amazon.de negali bÅ«ti realÅ«s (nors įtraukti tas trÅ«kstamas grandis labai lengva).</description> <description lang="mk">This scraper collects information from the following supported sites: MusicBrainz, last.fm, allmusic.com and amazon.de, while grabs artwork from: fanart.tv, last.fm and allmusic.com. It can be set field by field that from which site you want that specific information.⎠⎠The initial search is always done on MusicBrainz. In case allmusic and/or amazon.de links are not added on the MusicBrainz site, fields from allmusic.com and/or amazon.de cannot be fetched (very easy to add those missing links though).</description> <description lang="nl">Deze scraper verzamelt informatie van de volgende ondersteunde sites: MusicBrainz, Last.fm, allmusic.com en amazon.de. Afbeeldingen worden verzameld van de volgende sites: fanart.tv, Last.fm en allmusic.com. Per veld kan aangegeven worden van welke site je de specifieke informatie wil halen. De initiële zoekopdracht wordt altijd gedaan van MusicBrainz. In het geval dat links naar allmusic en/of amazon.de niet zijn toegevoegd op de MusicBrainz site, kunnen velden niet worden opgehaald bij deze sites. (Het is niet moeilijk om de ontbrekende links toe te voegen.)</description> @@ -81,7 +91,11 @@ <description lang="sk">Tento zdroj zÃskavania dát zbiera informácie z nasledujúcich podporovaných stránok: MusicBrainz, last.fm, allmusic.com a amazon.de, zatiaľ Äo umeleckú grafiku zÃskava zo stránok: fanart.tv, last.fm a allmusic.com. Je možné podrobne nastaviÅ¥, z ktorej stránky chcete zÃskaÅ¥ konkrétne informácie. PoÄiatoÄné hľadanie je vždy na stránke MusicBrainz. V prÃpade, že odkaz pre allmusic a/alebo amazon.de nie je pridaný na stránku MusicBrainz, nie je možné zÃskaÅ¥ údaje zo stránky allmusic.com a/alebo amazon.de (je ale veľmi jednoduché tieto chýbajúce odkazy pridaÅ¥).</description> <description lang="sl">Ta ponudnik združuje informacije s sledeÄih strani: MusicBrainz, last.fm, allmusic.com in amazon.de; grafike prenaÅ¡a z: fanart.tv, last.fm in allmusic.com. Vsako informacijo lahko prenesete z razliÄne strani. ZaÄeno iskanje je vedn na MusicBrainz. V primeru, da na MusicBrainz ni povezave do allmusic.com in/ali amazon.de, informacij od tam ne morete prenesti (a to težavo hitro lahko odpravite).</description> <description lang="sv">Denna skrapa samlar information frÃ¥n följande sajter: MusicBrainz, last.fm, allmusic.com och amazon.de, och konstverk frÃ¥n: fanart.tv, last.fm och allmusic.com. Det kan anges fält för fält vilken sajt du vill fÃ¥ den specifika informationen.⎠⎠Den initiala sökningen är alltid utförd pÃ¥ MusicBrainz sajt, fälten frÃ¥n allmusic.com och/eller amazon.de länkarna läggs inte till pÃ¥ MusicBrainz sajten, fälten frÃ¥n allmusic.com och/eller amazon.de kan inte hämtas (väldigt enkelt att lägga till dom saknade länkarna dock).</description> + <description lang="ta_IN">இநà¯à®¤ சà¯à®°à®£à¯à®Ÿà®¿à®¯à®¾à®©à®¤à¯ MusicBrainz, last.fm, allmusic.com மறà¯à®±à¯à®®à¯ amazon.de ஆகிய இணையதளதà¯à®¤à®¿à®²à¯ இரà¯à®¨à¯à®¤à¯ தகவலà¯à®•à®³à¯ˆ சேகரிகà¯à®•à¯à®®à¯. திரை கà¯à®±à¯à®®à¯à®ªà®Ÿà®™à¯à®•à®³à¯ˆ fanart.tv, last.fm மறà¯à®±à¯à®®à¯ allmusic.com ஆகிய இணையதளதà¯à®¤à®¿à®²à¯ இரà¯à®¨à¯à®¤à¯ தகவலà¯à®•à®³à¯ˆ சேகரிகà¯à®•à¯à®®à¯. ⎠⎠மà¯à®¤à®©à¯à®®à¯ˆ தேடல௠எபà¯à®ªà¯‹à®¤à¯à®®à¯ MusicBrainz தான௠நடகà¯à®•à¯à®®à¯. allmusic மறà¯à®±à¯à®®à¯ amazon.de சேரà¯à®•à¯à®•à®ªà®Ÿà®¾à®µà®¿à®Ÿà¯à®Ÿà®¾à®²à¯ அவறà¯à®±à®¿à®²à¯ இரà¯à®¨à¯à®¤à¯ தகவலà¯à®•à®³à¯ செமிகà¯à®•à®ªà®Ÿà®®à®¾à®Ÿà¯à®Ÿà®¤à¯ (தவறிய இணைபà¯à®ªà¯à®•à®³à¯ˆ சேரà¯à®ªà¯à®ªà®¤à¯ மிகவà¯à®®à¯ எளிதà¯).</description> + <description lang="uk">Здирач збирає інформацію з наÑтупних Ñторінок: MusicBrainz, last.fm, allmusic.com та amazon.de, тоді Ñк отримує обкладинки з: fanart.tv, last.fm та allmusic.com. Початковий пошук завжди робитьÑÑ Ð½Ð° MusicBrainz. Якщо поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð· allmusic Ñ–/або amazon.de не додаютьÑÑ Ð½Ð° Ñторінку MusicBrainz, тоді Ð¿Ð¾Ð»Ñ Ð· allmusic.com Ñ–/або amazon.de неможливо отримати (однак дуже легко додати ці пропущені поÑиланнÑ).</description> + <description lang="vi">Trình nà y thu tháºp thông tin từ những site được há»— trợ nhÆ°: MusicBrainz, last.fm, allmusic.com, amazon.de, và lấy ảnh bìa từ các nguồn: fanart.tv, last.fm và allmusic.com. Bạn có thể tùy chỉnh chá»n từng thứ riêng biệt để lấy từ site bạn muốn.\n \n Lần tìm kiếm đầu tiên luôn luôn được sá» dụng từ MusicBrainz. Trong trÆ°á»ng hợp các link allmusic và /hoặc amazon.de không có trên MusicBrainz, các trÆ°á»ng từ allmusic.com và /hoặc amazon.de sẽ không thể lấy vỠđược (tuy nhiên rất dá»… để tá»± thêm và o các link nà y bằng tay).</description> <description lang="zh">本刮削器支æŒä»Žä»¥ä¸‹ç½‘站获å–ä¿¡æ¯ï¼šMusicBrainzã€last.fmã€allmusic.comå’Œamazon.de,并从以下网站获å–艺术图片:fanart.tvã€last.fmå’Œallmusic.comã€‚ä½ å¯ä»¥æŒ‡å®šæ¯ä¸€é¡¹å†…容的æ¥æºç½‘站。 åˆå§‹ç»“果总是先从MusicBrainz获å–。如果MusicBrainz网站没有到allmusicå’Œ/或amazon.deçš„å¤–éƒ¨é“¾æŽ¥ï¼Œåˆ™æ— æ³•èŽ·å–allmusic.comçš„/或amazon.deçš„ä¿¡æ¯ï¼ˆå½“ç„¶ä½ èƒ½å¾ˆå®¹æ˜“åœ°åŠ å…¥ç¼ºå¤±çš„é“¾æŽ¥ï¼‰ã€‚</description> + <description lang="zh_TW">本æœåˆ®å™¨æ”¯æ´å¾žä»¥ä¸‹ç¶²ç«™å–得資訊:MusicBrainzã€last.fmã€allmusic.comå’Œamazon.de,並從以下網站å–得專輯照片:fanart.tvã€last.fmå’Œallmusic.com。您並å¯ä»¥æŒ‡å®šæ¯ä¸€é …內容的來æºç¶²ç«™ã€‚ åˆå§‹æœå°‹çµæžœç¸½æ˜¯å…ˆå¾žMusicBrainzå–得。如果MusicBrainzç¶²ç«™æ²’æœ‰åŠ å…¥åˆ°allmusicå’Œ/或amazon.de的外部連çµï¼Œå‰‡ç„¡æ³•å–å¾—allmusic.comçš„/或amazon.deçš„ä¿¡æ¯(ç•¶ç„¶æ‚¨èƒ½å¾ˆè¼•æ˜“åœ°åŠ å…¥éºå¤±çš„連çµ)。</description> <platform>all</platform> </extension> </addon> diff --git a/addons/metadata.album.universal/albumuniversal.xml b/addons/metadata.album.universal/albumuniversal.xml index 05afe2a952..b42a21ed5a 100644 --- a/addons/metadata.album.universal/albumuniversal.xml +++ b/addons/metadata.album.universal/albumuniversal.xml @@ -5,8 +5,13 @@ <expression>release/(.+)</expression> </RegExp> </NfoUrl> + <ResolveIDToUrl dest="3"> + <RegExp input="$$1" output="<url>http://musicbrainz.org/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings</url>" dest="3"> + <expression>(.+)</expression> + </RegExp> + </ResolveIDToUrl> <CreateAlbumSearchUrl dest="3"> - <RegExp input="$$1" output="<url>http://search.musicbrainz.org/ws/2/release/?fmt=xml&query=release:\1%20AND%20artist:$$4</url>" dest="3"> + <RegExp input="$$1" output="<url>http://search.musicbrainz.org/ws/2/release/?fmt=xml&query=release:\1%20AND%20artist:"$$4"</url>" dest="3"> <RegExp input="$$2" output="\1" dest="4"> <expression noclean="1">(.+)</expression> </RegExp> @@ -20,18 +25,18 @@ </RegExp> </CreateAlbumSearchUrl> <GetAlbumSearchResults dest="8"> - <RegExp input="$$5" output="<results>\1</results>" dest="8"> + <RegExp input="$$5" output="<results sorted="yes">\1</results>" dest="8"> <RegExp input="$$1" output="<entity><year>\5-\4-T#\6</year><artist>\3</artist><title>\2</title><url cache="mb-\1-album.xml">http://musicbrainz.org/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings</url></entity>" dest="5"> - <expression repeat="yes">id="([^"]*)"><title>([^<]*)</title><status>Official</status><text-representation><language>[^<]*</language><script>[^<]*</script></text-representation><artist-credit><name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>([^<]*)</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>.*?</alias-list>)*</artist></name-credit>(?:<name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>[^<]*</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>.*?</alias-list>)*</artist></name-credit>)*</artist-credit><release-group\stype="Album"\sid="[^"]*">(?:<primary-type>[^<]*</primary-type>)*(?:<secondary-type-list><secondary-type>[^<]*</secondary-type></secondary-type-list>)*</release-group><date>(\d{4})[^<]*</date>(?:<country>)*([^<]*)?.*?<track-list\scount="(\d+)</expression> + <expression repeat="yes">id="([^"]*)"><title>([^<]*)</title><status>Official</status><text-representation>(?:<language>[^<]*</language>)*(?:<script>[^<]*</script>)*</text-representation><artist-credit><name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>([^<]*)</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>.*?</alias-list>)*</artist></name-credit>(?:<name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>[^<]*</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>.*?</alias-list>)*</artist></name-credit>)*</artist-credit><release-group\stype="Album"\sid="[^"]*">(?:<primary-type>[^<]*</primary-type>)*(?:<secondary-type-list><secondary-type>[^<]*</secondary-type></secondary-type-list>)*</release-group><date>(\d{4})[^<]*</date>(?:<country>)*([^<]*)?.*?<track-list\scount="(\d+)</expression> </RegExp> <RegExp input="$$1" output="<entity><year>\5-\4-T#\6</year><artist>\3</artist><title>\2</title><url cache="mb-\1-album.xml">http://musicbrainz.org/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings</url></entity>" dest="5+"> - <expression repeat="yes">id="([^"]*)"><title>([^<]*)</title><status>Official</status><text-representation><language>[^<]*</language><script>[^<]*</script></text-representation><artist-credit><name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>([^<]*)</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>.*?</alias-list>)*</artist></name-credit>(?:<name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>[^<]*</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>.*?</alias-list>)*</artist></name-credit>)*</artist-credit><release-group(?:\stype="[^"]*")*\sid="[^"]*">(?:<primary-type>[^<]*</primary-type>)*(?:<secondary-type-list><secondary-type>[^<]*</secondary-type></secondary-type-list>)*</release-group><date>(\d{4})[^<]*</date>(?:<country>)*([^<]*)?.*?<track-list\scount="(\d+)</expression> + <expression repeat="yes">id="([^"]*)"><title>([^<]*)</title><status>Official</status><text-representation>(?:<language>[^<]*</language>)*(?:<script>[^<]*</script>)*</text-representation><artist-credit><name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>([^<]*)</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>.*?</alias-list>)*</artist></name-credit>(?:<name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>[^<]*</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>.*?</alias-list>)*</artist></name-credit>)*</artist-credit><release-group(?:\stype="[^"]*")*\sid="[^"]*">(?:<primary-type>[^<]*</primary-type>)*(?:<secondary-type-list><secondary-type>[^<]*</secondary-type></secondary-type-list>)*</release-group><date>(\d{4})[^<]*</date>(?:<country>)*([^<]*)?.*?<track-list\scount="(\d+)</expression> </RegExp> <RegExp input="$$1" output="<entity><year>\5-\4-T#\6</year><artist>\3</artist><title>\2</title><url cache="mb-\1-album.xml">http://musicbrainz.org/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings</url></entity>" dest="5"> - <expression repeat="yes">id="([^"]*)" ext:score="[^"]*"><title>([^<]*)</title><status>Official</status><text-representation><language>[^<]*</language><script>[^<]*</script></text-representation><artist-credit><name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>([^<]*)</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>.*?</alias-list>)*</artist></name-credit>(?:<name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>[^<]*</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>.*?</alias-list>)*</artist></name-credit>)*</artist-credit><release-group\sid="[^"]*"\stype="Album">(?:<primary-type>[^<]*</primary-type>)*(?:<secondary-type-list><secondary-type>[^<]*</secondary-type></secondary-type-list>)*</release-group><date>(\d{4})[^<]*</date>(?:<country>)*([^<]*)?.*?<track-list\scount="(\d+)</expression> + <expression repeat="yes">id="([^"]*)" ext:score="[^"]*"><title>([^<]*)</title><status>Official</status><text-representation>(?:<language>[^<]*</language>)*(?:<script>[^<]*</script>)*</text-representation><artist-credit><name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>([^<]*)</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>.*?</alias-list>)*</artist></name-credit>(?:<name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>[^<]*</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>.*?</alias-list>)*</artist></name-credit>)*</artist-credit><release-group\sid="[^"]*"\stype="Album">(?:<primary-type>[^<]*</primary-type>)*(?:<secondary-type-list><secondary-type>[^<]*</secondary-type></secondary-type-list>)*</release-group><date>(\d{4})[^<]*</date>(?:<country>)*([^<]*)?.*?<track-list\scount="(\d+)</expression> </RegExp> <RegExp input="$$1" output="<entity><year>\5-\4-T#\6</year><artist>\3</artist><title>\2</title><url cache="mb-\1-album.xml">http://musicbrainz.org/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings</url></entity>" dest="5+"> - <expression repeat="yes">id="([^"]*)" ext:score="[^"]*"><title>([^<]*)</title><status>Official</status><text-representation><language>[^<]*</language><script>[^<]*</script></text-representation><artist-credit><name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>([^<]*)</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>.*?</alias-list>)*</artist></name-credit>(?:<name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>[^<]*</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>.*?</alias-list>)*</artist></name-credit>)*</artist-credit><release-group\sid="[^"]*"(?:\stype="[^"]*")*>(?:<primary-type>[^<]*</primary-type>)*(?:<secondary-type-list><secondary-type>[^<]*</secondary-type></secondary-type-list>)*</release-group><date>(\d{4})[^<]*</date>(?:<country>)*([^<]*)?.*?<track-list\scount="(\d+)</expression> + <expression repeat="yes">id="([^"]*)" ext:score="[^"]*"><title>([^<]*)</title><status>Official</status><text-representation>(?:<language>[^<]*</language>)*(?:<script>[^<]*<)*/script></text-representation><artist-credit><name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>([^<]*)</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>.*?</alias-list>)*</artist></name-credit>(?:<name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>[^<]*</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>.*?</alias-list>)*</artist></name-credit>)*</artist-credit><release-group\sid="[^"]*"(?:\stype="[^"]*")*>(?:<primary-type>[^<]*</primary-type>)*(?:<secondary-type-list><secondary-type>[^<]*</secondary-type></secondary-type-list>)*</release-group><date>(\d{4})[^<]*</date>(?:<country>)*([^<]*)?.*?<track-list\scount="(\d+)</expression> </RegExp> <expression noclean="1" /> </RegExp> @@ -57,6 +62,9 @@ <RegExp input="$$3" output="<chain function="GetMBAlbumTitleByMBID">\1</chain>" dest="5"> <expression noclean="1">(.+)</expression> </RegExp> + <RegExp input="$$3" output="<chain function="GetMBAlbumArtistsByMBID">\1</chain>" dest="5+"> + <expression noclean="1">(.+)</expression> + </RegExp> <RegExp input="$$3" output="<chain function="GetMBAlbumArtistByMBID">\1</chain>" dest="5+"> <expression noclean="1">(.+)</expression> </RegExp> diff --git a/addons/metadata.album.universal/changelog.txt b/addons/metadata.album.universal/changelog.txt index c3dc51782d..5624e3ee43 100644 --- a/addons/metadata.album.universal/changelog.txt +++ b/addons/metadata.album.universal/changelog.txt @@ -1,3 +1,25 @@ +[B]1.7.6[/B] +Updated language files from Transifex + +[B]1.7.5[/B] +Re-aply changes in 1.7.3 what lost in space with 1.7.4 + +[B]1.7.4[/B] +Changed: tighten search query and trust musicbrainz results sorting + +[B]1.7.3[/B] +Fixed: album won't find some times (thanks and credits to crankylemur) + +[B]1.7.2[/B] +Fix settings after last.fm removal + +[B]1.7.1[/B] +Disable last.fm options because last.fm is now truncating biogs + +[B]1.7.0[/B] +Added: option to select language from TheAudioDB.com +Added back the option to scrape from last.fm + [B]1.6.4[/B] Disable last.fm options because last.fm suspended XBMC's API account diff --git a/addons/metadata.album.universal/resources/language/Amharic/strings.xml b/addons/metadata.album.universal/resources/language/Amharic/strings.xml new file mode 100644 index 0000000000..65938f6340 --- /dev/null +++ b/addons/metadata.album.universal/resources/language/Amharic/strings.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Amharic language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/am/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30003">የመረጡት ቋንቋ </string> +</strings> diff --git a/addons/metadata.album.universal/resources/language/Asturian/strings.xml b/addons/metadata.album.universal/resources/language/Asturian/strings.xml new file mode 100644 index 0000000000..a40a002cb0 --- /dev/null +++ b/addons/metadata.album.universal/resources/language/Asturian/strings.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Asturian language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/ast/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">Obtener miniatures d'álbum de fanart.tv</string> + <string id="30001">Obtener miniatures d'álbum de Last.fm</string> + <string id="30002">Obtener reseña del álbum de</string> + <string id="30003">Llingua preferida</string> + <string id="30004">Obtener calificación del álbum de</string> + <string id="30005">Obtener estilos del álbum de</string> + <string id="30006">Obtener estaos d'ánimu del álbum de</string> + <string id="30007">Obtener temes del álbum de</string> + <string id="30008">Conseguir miniatures de álbum de allmusic.com</string> + <string id="30009">Imáxenes</string> + <string id="30010">Descargar miniatures de álbum dende theaudiodb.com</string> +</strings> diff --git a/addons/metadata.album.universal/resources/language/Belarusian/strings.po b/addons/metadata.album.universal/resources/language/Belarusian/strings.po deleted file mode 100644 index b49c655cde..0000000000 --- a/addons/metadata.album.universal/resources/language/Belarusian/strings.po +++ /dev/null @@ -1,58 +0,0 @@ -# XBMC Media Center language file -# Addon Name: Universal Album Scraper -# Addon id: metadata.album.universal -# Addon version: 1.6.0 -# Addon Provider: Olympia, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main Translation Project (Frodo)\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" -"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: XBMC Translation Team\n" -"Language-Team: Belarusian (http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/be/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: be\n" -"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" - -msgctxt "#30000" -msgid "Grab Album Thumbs from fanart.tv" -msgstr "Grab Album Thumbs from fanart.tv" - -msgctxt "#30001" -msgid "Grab Album Thumbs from Last.fm" -msgstr "Grab Album Thumbs from Last.fm" - -msgctxt "#30002" -msgid "Get Album Review from" -msgstr "Get Album Review from" - -msgctxt "#30003" -msgid " Preferred Language" -msgstr " ÐŸÐµÑ€Ð°Ð²Ð°Ð¶Ð½Ð°Ñ Ð¼Ð¾Ð²Ð°" - -msgctxt "#30004" -msgid "Get Album Rating from" -msgstr "Get Album Rating from" - -msgctxt "#30005" -msgid "Get Album Styles from" -msgstr "Get Album Styles from" - -msgctxt "#30006" -msgid "Get Album Moods from" -msgstr "Get Album Moods from" - -msgctxt "#30007" -msgid "Get Album Themes from" -msgstr "Get Album Themes from" - -msgctxt "#30008" -msgid "Grab Album Thumbs from allmusic.com" -msgstr "Grab Album Thumbs from allmusic.com" - -msgctxt "#30009" -msgid "Artwork" -msgstr "Artwork" diff --git a/addons/metadata.album.universal/resources/language/Bulgarian/strings.po b/addons/metadata.album.universal/resources/language/Bulgarian/strings.po deleted file mode 100644 index cd1671e5a5..0000000000 --- a/addons/metadata.album.universal/resources/language/Bulgarian/strings.po +++ /dev/null @@ -1,58 +0,0 @@ -# XBMC Media Center language file -# Addon Name: Universal Album Scraper -# Addon id: metadata.album.universal -# Addon version: 1.6.0 -# Addon Provider: Olympia, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main Translation Project (Frodo)\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" -"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: XBMC Translation Team\n" -"Language-Team: Bulgarian (http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/bg/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: bg\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Grab Album Thumbs from fanart.tv" -msgstr "СвалÑй миниатюри за албумите от fanart.tv" - -msgctxt "#30001" -msgid "Grab Album Thumbs from Last.fm" -msgstr "СвалÑй миниатюри за албумите от Last.fm" - -msgctxt "#30002" -msgid "Get Album Review from" -msgstr "СвалÑй отзиви за албумите от" - -msgctxt "#30003" -msgid " Preferred Language" -msgstr "Предпочитан език" - -msgctxt "#30004" -msgid "Get Album Rating from" -msgstr "СвалÑй рейтинги за албумите от" - -msgctxt "#30005" -msgid "Get Album Styles from" -msgstr "СвалÑй Ñтилове на албумите от" - -msgctxt "#30006" -msgid "Get Album Moods from" -msgstr "СвалÑй наÑÑ‚Ñ€Ð¾ÐµÐ½Ð¸Ñ Ð·Ð° албумите от" - -msgctxt "#30008" -msgid "Grab Album Thumbs from allmusic.com" -msgstr "СвалÑй миниатюри за албумите от allmusic.com" - -msgctxt "#30009" -msgid "Artwork" -msgstr "ИзображениÑ" - -msgctxt "#30010" -msgid "Grab Album Thumbs from theaudiodb.com" -msgstr "СвалÑй миниатюри за албумите от theaudiodb.com" diff --git a/addons/metadata.album.universal/resources/language/Burmese/strings.xml b/addons/metadata.album.universal/resources/language/Burmese/strings.xml new file mode 100644 index 0000000000..69708df005 --- /dev/null +++ b/addons/metadata.album.universal/resources/language/Burmese/strings.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Burmese language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/my/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30003">သင့်လျှော်သော ဘာသာစကား</string> + <string id="30009">အနုပညာလက်ရာ</string> +</strings> diff --git a/addons/metadata.album.universal/resources/language/Catalan/strings.po b/addons/metadata.album.universal/resources/language/Catalan/strings.po deleted file mode 100644 index 1995c9a034..0000000000 --- a/addons/metadata.album.universal/resources/language/Catalan/strings.po +++ /dev/null @@ -1,58 +0,0 @@ -# XBMC Media Center language file -# Addon Name: Universal Album Scraper -# Addon id: metadata.album.universal -# Addon version: 1.6.0 -# Addon Provider: Olympia, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main Translation Project (Frodo)\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" -"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: XBMC Translation Team\n" -"Language-Team: Catalan (http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/ca/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ca\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Grab Album Thumbs from fanart.tv" -msgstr "Obté les miniatures d'à lbums des de fanart.tv" - -msgctxt "#30001" -msgid "Grab Album Thumbs from Last.fm" -msgstr "Obté les miniatures d'à lbums des de Last.fm" - -msgctxt "#30002" -msgid "Get Album Review from" -msgstr "Obté l'anà lisi d'à lbums des de" - -msgctxt "#30003" -msgid " Preferred Language" -msgstr "Idioma preferit" - -msgctxt "#30004" -msgid "Get Album Rating from" -msgstr "Obté la qualificació d'à lbums des de" - -msgctxt "#30005" -msgid "Get Album Styles from" -msgstr "Obté els estils d'à lbums des de" - -msgctxt "#30006" -msgid "Get Album Moods from" -msgstr "Obté l'estat d'à nim dels à lbums des de" - -msgctxt "#30007" -msgid "Get Album Themes from" -msgstr "Obté el temes dels à lbums des de" - -msgctxt "#30008" -msgid "Grab Album Thumbs from allmusic.com" -msgstr "Obté les miniatures dels à lbums des de allmusic.com" - -msgctxt "#30009" -msgid "Artwork" -msgstr "Art" diff --git a/addons/metadata.album.universal/resources/language/Chinese (Simple)/strings.po b/addons/metadata.album.universal/resources/language/Chinese (Simple)/strings.po deleted file mode 100644 index e2d165b515..0000000000 --- a/addons/metadata.album.universal/resources/language/Chinese (Simple)/strings.po +++ /dev/null @@ -1,62 +0,0 @@ -# XBMC Media Center language file -# Addon Name: Universal Album Scraper -# Addon id: metadata.album.universal -# Addon version: 1.6.0 -# Addon Provider: Olympia, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main Translation Project (Frodo)\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" -"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: XBMC Translation Team\n" -"Language-Team: Chinese (Simple) (http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/zh/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: zh\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -msgctxt "#30000" -msgid "Grab Album Thumbs from fanart.tv" -msgstr "å¯ç”¨fanart.tv专辑图片" - -msgctxt "#30001" -msgid "Grab Album Thumbs from Last.fm" -msgstr "å¯ç”¨Last.fm专辑图片" - -msgctxt "#30002" -msgid "Get Album Review from" -msgstr "专辑评论获å–于" - -msgctxt "#30003" -msgid " Preferred Language" -msgstr " 首选è¯è¨€" - -msgctxt "#30004" -msgid "Get Album Rating from" -msgstr "专辑评分获å–于" - -msgctxt "#30005" -msgid "Get Album Styles from" -msgstr "ä¸“è¾‘é£Žæ ¼èŽ·å–于" - -msgctxt "#30006" -msgid "Get Album Moods from" -msgstr "专辑心情获å–于" - -msgctxt "#30007" -msgid "Get Album Themes from" -msgstr "专辑主题获å–于" - -msgctxt "#30008" -msgid "Grab Album Thumbs from allmusic.com" -msgstr "å¯ç”¨allmusic.com专辑图片" - -msgctxt "#30009" -msgid "Artwork" -msgstr "艺术图片" - -msgctxt "#30010" -msgid "Grab Album Thumbs from theaudiodb.com" -msgstr "å¯ç”¨ theaudiodb.com 专辑图片" diff --git a/addons/metadata.album.universal/resources/language/Chinese (Traditional)/strings.xml b/addons/metadata.album.universal/resources/language/Chinese (Traditional)/strings.xml new file mode 100644 index 0000000000..848708f2dd --- /dev/null +++ b/addons/metadata.album.universal/resources/language/Chinese (Traditional)/strings.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Chinese (Traditional) language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/zh_TW/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">啟用fanart.tv專輯縮圖</string> + <string id="30001">啟用 Last.fm專輯縮圖</string> + <string id="30002">專輯評論å–å¾—æ–¼</string> + <string id="30003">å好的語言</string> + <string id="30004">專輯評分å–å¾—æ–¼</string> + <string id="30005">å°ˆè¼¯é¢¨æ ¼å–å¾—æ–¼</string> + <string id="30006">專輯æ„境å–å¾—æ–¼</string> + <string id="30007">專輯主題å–å¾—æ–¼</string> + <string id="30008">從allmusic.comå–得專輯縮圖</string> + <string id="30009">圖片</string> + <string id="30010">從 theaudiodb.comå–得專輯縮圖</string> +</strings> diff --git a/addons/metadata.album.universal/resources/language/Croatian/strings.xml b/addons/metadata.album.universal/resources/language/Croatian/strings.xml new file mode 100644 index 0000000000..02ac12cb87 --- /dev/null +++ b/addons/metadata.album.universal/resources/language/Croatian/strings.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Croatian language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/hr/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">Dohvati </string> +</strings> diff --git a/addons/metadata.album.universal/resources/language/Czech/strings.po b/addons/metadata.album.universal/resources/language/Czech/strings.po deleted file mode 100644 index dd416df541..0000000000 --- a/addons/metadata.album.universal/resources/language/Czech/strings.po +++ /dev/null @@ -1,58 +0,0 @@ -# XBMC Media Center language file -# Addon Name: Universal Album Scraper -# Addon id: metadata.album.universal -# Addon version: 1.6.0 -# Addon Provider: Olympia, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main Translation Project (Frodo)\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" -"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: XBMC Translation Team\n" -"Language-Team: Czech (http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/cs/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: cs\n" -"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" - -msgctxt "#30000" -msgid "Grab Album Thumbs from fanart.tv" -msgstr "ZÃskat náhledy alb z fanart.tv" - -msgctxt "#30001" -msgid "Grab Album Thumbs from Last.fm" -msgstr "ZÃskat náhledy alb z Last.fm" - -msgctxt "#30002" -msgid "Get Album Review from" -msgstr "ZÃskat recenzi alba z" - -msgctxt "#30003" -msgid " Preferred Language" -msgstr "UpÅ™ednostňovaný jazyk" - -msgctxt "#30004" -msgid "Get Album Rating from" -msgstr "ZÃskat hodnocenà alba z" - -msgctxt "#30005" -msgid "Get Album Styles from" -msgstr "ZÃskat styly alba z" - -msgctxt "#30006" -msgid "Get Album Moods from" -msgstr "ZÃskat náladu alba z" - -msgctxt "#30007" -msgid "Get Album Themes from" -msgstr "ZÃskat téma alba z" - -msgctxt "#30008" -msgid "Grab Album Thumbs from allmusic.com" -msgstr "ZÃskat náhledy alb z allmusic.com" - -msgctxt "#30009" -msgid "Artwork" -msgstr "Grafika" diff --git a/addons/metadata.album.universal/resources/language/Danish/strings.po b/addons/metadata.album.universal/resources/language/Danish/strings.po deleted file mode 100644 index 3a72ef84c8..0000000000 --- a/addons/metadata.album.universal/resources/language/Danish/strings.po +++ /dev/null @@ -1,58 +0,0 @@ -# XBMC Media Center language file -# Addon Name: Universal Album Scraper -# Addon id: metadata.album.universal -# Addon version: 1.6.0 -# Addon Provider: Olympia, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main Translation Project (Frodo)\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" -"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: XBMC Translation Team\n" -"Language-Team: Danish (http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/da/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: da\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Grab Album Thumbs from fanart.tv" -msgstr "Hent album miniaturebilleder fra fanart.tv" - -msgctxt "#30001" -msgid "Grab Album Thumbs from Last.fm" -msgstr "Hent album miniaturebilleder fra Last.fm" - -msgctxt "#30002" -msgid "Get Album Review from" -msgstr "Hent album anmeldelse fra" - -msgctxt "#30003" -msgid " Preferred Language" -msgstr "Foretrukken sprog" - -msgctxt "#30004" -msgid "Get Album Rating from" -msgstr "Hent album bedømmelse fra" - -msgctxt "#30005" -msgid "Get Album Styles from" -msgstr "Hent album stilarter fra" - -msgctxt "#30006" -msgid "Get Album Moods from" -msgstr "Hent album stemning fra" - -msgctxt "#30007" -msgid "Get Album Themes from" -msgstr "Hent album temaer fra" - -msgctxt "#30008" -msgid "Grab Album Thumbs from allmusic.com" -msgstr "Hent album miniaturebilleder fra allmusic.com" - -msgctxt "#30009" -msgid "Artwork" -msgstr "Illustrationer" diff --git a/addons/metadata.album.universal/resources/language/Dutch/strings.po b/addons/metadata.album.universal/resources/language/Dutch/strings.po deleted file mode 100644 index da8b8fccf4..0000000000 --- a/addons/metadata.album.universal/resources/language/Dutch/strings.po +++ /dev/null @@ -1,26 +0,0 @@ -# XBMC Media Center language file -# Addon Name: Universal Album Scraper -# Addon id: metadata.album.universal -# Addon version: 1.6.0 -# Addon Provider: Olympia, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main Translation Project (Frodo)\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" -"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: XBMC Translation Team\n" -"Language-Team: Dutch (http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/nl/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: nl\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30003" -msgid " Preferred Language" -msgstr "Voorkeurs- taal" - -msgctxt "#30009" -msgid "Artwork" -msgstr "Artwork" diff --git a/addons/metadata.album.universal/resources/language/Estonian/strings.xml b/addons/metadata.album.universal/resources/language/Estonian/strings.xml index 407dcfe0ca..bd00442169 100644 --- a/addons/metadata.album.universal/resources/language/Estonian/strings.xml +++ b/addons/metadata.album.universal/resources/language/Estonian/strings.xml @@ -4,5 +4,15 @@ <!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> <strings> + <string id="30000">Hangi albumi pisipildid fanart.tv-st</string> + <string id="30001">Hangi albumi pisipildid Last.fm-st</string> + <string id="30002">Hangi albumi arvustused</string> + <string id="30003">Eelistatud keel</string> + <string id="30004">Hangi albumi hinnang</string> + <string id="30005">Hangi albumi stiil</string> + <string id="30006">Hangi albumi meeleolu</string> + <string id="30007">Hangi albumi teema</string> + <string id="30008">Hangi albumi pisipildid allmusic.com-st</string> <string id="30009">Kunst</string> + <string id="30010">Hangi albumi pisipildid theaudiodb.com-st</string> </strings> diff --git a/addons/metadata.album.universal/resources/language/French/strings.po b/addons/metadata.album.universal/resources/language/French/strings.po deleted file mode 100644 index bbcbc69c8e..0000000000 --- a/addons/metadata.album.universal/resources/language/French/strings.po +++ /dev/null @@ -1,62 +0,0 @@ -# XBMC Media Center language file -# Addon Name: Universal Album Scraper -# Addon id: metadata.album.universal -# Addon version: 1.6.0 -# Addon Provider: Olympia, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main Translation Project (Frodo)\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" -"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: XBMC Translation Team\n" -"Language-Team: French (http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/fr/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: fr\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" - -msgctxt "#30000" -msgid "Grab Album Thumbs from fanart.tv" -msgstr " Récupérer les vignettes d'albums depuis fanart.tv" - -msgctxt "#30001" -msgid "Grab Album Thumbs from Last.fm" -msgstr "Récupérer les vignettes d'albums depuis Last.fm" - -msgctxt "#30002" -msgid "Get Album Review from" -msgstr "Récupérer les critiques des album depuis " - -msgctxt "#30003" -msgid " Preferred Language" -msgstr "Langue préférée" - -msgctxt "#30004" -msgid "Get Album Rating from" -msgstr "Récupérer les notes des albums depuis " - -msgctxt "#30005" -msgid "Get Album Styles from" -msgstr "Récupérer les styles des albums depuis " - -msgctxt "#30006" -msgid "Get Album Moods from" -msgstr "Récupérer les ambiances des albums depuis " - -msgctxt "#30007" -msgid "Get Album Themes from" -msgstr "Récupérer les thèmes des albums depuis " - -msgctxt "#30008" -msgid "Grab Album Thumbs from allmusic.com" -msgstr "Récupérer les vignettes d'albums depuis allmusic.com" - -msgctxt "#30009" -msgid "Artwork" -msgstr "Artwork" - -msgctxt "#30010" -msgid "Grab Album Thumbs from theaudiodb.com" -msgstr "Récupérer les vignettes d'albums depuis theaudiodb.com" diff --git a/addons/metadata.album.universal/resources/language/German/strings.po b/addons/metadata.album.universal/resources/language/German/strings.po deleted file mode 100644 index 02b01dbfd1..0000000000 --- a/addons/metadata.album.universal/resources/language/German/strings.po +++ /dev/null @@ -1,62 +0,0 @@ -# XBMC Media Center language file -# Addon Name: Universal Album Scraper -# Addon id: metadata.album.universal -# Addon version: 1.6.0 -# Addon Provider: Olympia, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main Translation Project (Frodo)\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" -"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: XBMC Translation Team\n" -"Language-Team: German (http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/de/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: de\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Grab Album Thumbs from fanart.tv" -msgstr "Lade Albenvorschaubilder von Fanart.tv" - -msgctxt "#30001" -msgid "Grab Album Thumbs from Last.fm" -msgstr "Lade Albenvorschaubilder von Last.fm" - -msgctxt "#30002" -msgid "Get Album Review from" -msgstr "Lade Albenrezensionen von" - -msgctxt "#30003" -msgid " Preferred Language" -msgstr "Bevorzugte Sprache" - -msgctxt "#30004" -msgid "Get Album Rating from" -msgstr "Lade Albrenbewertung von" - -msgctxt "#30005" -msgid "Get Album Styles from" -msgstr "Lade Albenstile von" - -msgctxt "#30006" -msgid "Get Album Moods from" -msgstr "Lade Albenstimmungen von" - -msgctxt "#30007" -msgid "Get Album Themes from" -msgstr "Lade Albenthemen von" - -msgctxt "#30008" -msgid "Grab Album Thumbs from allmusic.com" -msgstr "Lade Albenvorschaubilder von Allmusic.com" - -msgctxt "#30009" -msgid "Artwork" -msgstr "Grafiken" - -msgctxt "#30010" -msgid "Grab Album Thumbs from theaudiodb.com" -msgstr "Albumvorschaubilder von theaudiodb.com übernehmen" diff --git a/addons/metadata.album.universal/resources/language/Greek/strings.po b/addons/metadata.album.universal/resources/language/Greek/strings.po deleted file mode 100644 index 46df4ce0d5..0000000000 --- a/addons/metadata.album.universal/resources/language/Greek/strings.po +++ /dev/null @@ -1,62 +0,0 @@ -# XBMC Media Center language file -# Addon Name: Universal Album Scraper -# Addon id: metadata.album.universal -# Addon version: 1.6.0 -# Addon Provider: Olympia, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main Translation Project (Frodo)\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" -"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: XBMC Translation Team\n" -"Language-Team: Greek (http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/el/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: el\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Grab Album Thumbs from fanart.tv" -msgstr "ΜικÏογÏαφίες Άλμπουμ από το fanart.tv" - -msgctxt "#30001" -msgid "Grab Album Thumbs from Last.fm" -msgstr "ΜικÏογÏαφίες Άλμπουμ από το Last.fm" - -msgctxt "#30002" -msgid "Get Album Review from" -msgstr "ΚÏιτική Άλμπουμ από" - -msgctxt "#30003" -msgid " Preferred Language" -msgstr "Î Ïοτιμώμενη Γλώσσα" - -msgctxt "#30004" -msgid "Get Album Rating from" -msgstr "Αξιολόγηση Άλμπουμ από" - -msgctxt "#30005" -msgid "Get Album Styles from" -msgstr "Στυλ Άλμπουμ από" - -msgctxt "#30006" -msgid "Get Album Moods from" -msgstr "ΔιαθÎσεις Άλμπουμ από" - -msgctxt "#30007" -msgid "Get Album Themes from" -msgstr "ΘÎματα Άλμπουμ από" - -msgctxt "#30008" -msgid "Grab Album Thumbs from allmusic.com" -msgstr "ΜικÏογÏαφίες Άλμπουμ από το allmusic.com" - -msgctxt "#30009" -msgid "Artwork" -msgstr "Εικόνες" - -msgctxt "#30010" -msgid "Grab Album Thumbs from theaudiodb.com" -msgstr "ΜικÏογÏαφίες Άλμπουμ από το theaudiodb.com" diff --git a/addons/metadata.album.universal/resources/language/Hebrew/strings.po b/addons/metadata.album.universal/resources/language/Hebrew/strings.po deleted file mode 100644 index b465fdad81..0000000000 --- a/addons/metadata.album.universal/resources/language/Hebrew/strings.po +++ /dev/null @@ -1,62 +0,0 @@ -# XBMC Media Center language file -# Addon Name: Universal Album Scraper -# Addon id: metadata.album.universal -# Addon version: 1.6.0 -# Addon Provider: Olympia, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main Translation Project (Frodo)\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" -"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: XBMC Translation Team\n" -"Language-Team: Hebrew (http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/he/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: he\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Grab Album Thumbs from fanart.tv" -msgstr "משוך ×ª×ž×•× ×•×ª ××œ×‘×•× ×ž- fanart.tv" - -msgctxt "#30001" -msgid "Grab Album Thumbs from Last.fm" -msgstr "משוך ×ª×ž×•× ×•×ª ××œ×‘×•× ×ž- Last.fm" - -msgctxt "#30002" -msgid "Get Album Review from" -msgstr "השג סקירת ××œ×‘×•× ×ž-" - -msgctxt "#30003" -msgid " Preferred Language" -msgstr " שפה מועדפת" - -msgctxt "#30004" -msgid "Get Album Rating from" -msgstr "השג דירוג ××œ×‘×•× ×ž-" - -msgctxt "#30005" -msgid "Get Album Styles from" -msgstr "השג ×¡×’× ×•× ×•×ª ××œ×‘×•× ×ž-" - -msgctxt "#30006" -msgid "Get Album Moods from" -msgstr "השג מצבי ××œ×‘×•× ×ž-" - -msgctxt "#30007" -msgid "Get Album Themes from" -msgstr "השג ערכות × ×•×©× ××œ×‘×•× ×ž-" - -msgctxt "#30008" -msgid "Grab Album Thumbs from allmusic.com" -msgstr "משוך ×ª×ž×•× ×•×ª ××œ×‘×•× ×ž- allmusic.com" - -msgctxt "#30009" -msgid "Artwork" -msgstr "גרפיקה" - -msgctxt "#30010" -msgid "Grab Album Thumbs from theaudiodb.com" -msgstr "משוך ×ª×ž×•× ×•×ª ××œ×‘×•× ×ž- theaudiodb.com" diff --git a/addons/metadata.album.universal/resources/language/Hungarian/strings.po b/addons/metadata.album.universal/resources/language/Hungarian/strings.po deleted file mode 100644 index 3dd7aba0df..0000000000 --- a/addons/metadata.album.universal/resources/language/Hungarian/strings.po +++ /dev/null @@ -1,58 +0,0 @@ -# XBMC Media Center language file -# Addon Name: Universal Album Scraper -# Addon id: metadata.album.universal -# Addon version: 1.6.0 -# Addon Provider: Olympia, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main Translation Project (Frodo)\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" -"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: XBMC Translation Team\n" -"Language-Team: Hungarian (http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/hu/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: hu\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Grab Album Thumbs from fanart.tv" -msgstr "Album miniképek letöltése a fanart.tv-rÅ‘l" - -msgctxt "#30001" -msgid "Grab Album Thumbs from Last.fm" -msgstr "Album miniképek letöltése a Last.fm-rÅ‘l" - -msgctxt "#30002" -msgid "Get Album Review from" -msgstr "Album értékelése" - -msgctxt "#30003" -msgid " Preferred Language" -msgstr "Használni kÃvánt nyelv" - -msgctxt "#30004" -msgid "Get Album Rating from" -msgstr "Album értékelés" - -msgctxt "#30005" -msgid "Get Album Styles from" -msgstr "Album stÃlus" - -msgctxt "#30006" -msgid "Get Album Moods from" -msgstr "Album hangulatok a " - -msgctxt "#30007" -msgid "Get Album Themes from" -msgstr "Album témák" - -msgctxt "#30008" -msgid "Grab Album Thumbs from allmusic.com" -msgstr "Album miniképek az allmusic.com-ról" - -msgctxt "#30009" -msgid "Artwork" -msgstr "Artwork" diff --git a/addons/metadata.album.universal/resources/language/Italian/strings.po b/addons/metadata.album.universal/resources/language/Italian/strings.po deleted file mode 100644 index bdaa7e9238..0000000000 --- a/addons/metadata.album.universal/resources/language/Italian/strings.po +++ /dev/null @@ -1,58 +0,0 @@ -# XBMC Media Center language file -# Addon Name: Universal Album Scraper -# Addon id: metadata.album.universal -# Addon version: 1.6.0 -# Addon Provider: Olympia, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main Translation Project (Frodo)\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" -"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: XBMC Translation Team\n" -"Language-Team: Italian (http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/it/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: it\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Grab Album Thumbs from fanart.tv" -msgstr "Prendi i Provini degli Album da fanart.tv" - -msgctxt "#30001" -msgid "Grab Album Thumbs from Last.fm" -msgstr "Prendi i Provini degli Album da Last.fm" - -msgctxt "#30002" -msgid "Get Album Review from" -msgstr "Prendi Recensioni Albums da" - -msgctxt "#30003" -msgid " Preferred Language" -msgstr "Lingua Preferita" - -msgctxt "#30004" -msgid "Get Album Rating from" -msgstr "Prendi Votazioni Albums da" - -msgctxt "#30005" -msgid "Get Album Styles from" -msgstr "Prendi Generi Musicali Albums da" - -msgctxt "#30006" -msgid "Get Album Moods from" -msgstr "Prendi Atmosfere Albums da" - -msgctxt "#30007" -msgid "Get Album Themes from" -msgstr "Prendi Temi Albums da" - -msgctxt "#30008" -msgid "Grab Album Thumbs from allmusic.com" -msgstr "Prendi i Provini degli Album da allmusic.com" - -msgctxt "#30009" -msgid "Artwork" -msgstr "Artwork" diff --git a/addons/metadata.album.universal/resources/language/Korean/strings.po b/addons/metadata.album.universal/resources/language/Korean/strings.po deleted file mode 100644 index 73a1c954f9..0000000000 --- a/addons/metadata.album.universal/resources/language/Korean/strings.po +++ /dev/null @@ -1,58 +0,0 @@ -# XBMC Media Center language file -# Addon Name: Universal Album Scraper -# Addon id: metadata.album.universal -# Addon version: 1.6.0 -# Addon Provider: Olympia, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main Translation Project (Frodo)\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" -"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: XBMC Translation Team\n" -"Language-Team: Korean (http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/ko/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ko\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -msgctxt "#30000" -msgid "Grab Album Thumbs from fanart.tv" -msgstr "fanart.tv ì—ì„œ 앨범 커버 ê°€ì ¸ì˜¤ê¸°" - -msgctxt "#30001" -msgid "Grab Album Thumbs from Last.fm" -msgstr "Last.fm ì—ì„œ 앨범 커버 ê°€ì ¸ì˜¤ê¸°" - -msgctxt "#30002" -msgid "Get Album Review from" -msgstr "앨범 리뷰 ê°€ì ¸ì˜¤ê¸°" - -msgctxt "#30003" -msgid " Preferred Language" -msgstr "ì„ í˜¸ 언어" - -msgctxt "#30004" -msgid "Get Album Rating from" -msgstr "앨범 í‰ì ê°€ì ¸ì˜¤ê¸°" - -msgctxt "#30005" -msgid "Get Album Styles from" -msgstr "앨범 ìŠ¤íƒ€ì¼ ê°€ì ¸ì˜¤ê¸°" - -msgctxt "#30006" -msgid "Get Album Moods from" -msgstr "앨범 분위기 ê°€ì ¸ì˜¤ê¸°" - -msgctxt "#30007" -msgid "Get Album Themes from" -msgstr "앨범 테마 ê°€ì ¸ì˜¤ê¸°" - -msgctxt "#30008" -msgid "Grab Album Thumbs from allmusic.com" -msgstr "allmusic.com ì—ì„œ 앨범 커버 ê°€ì ¸ì˜¤ê¸°" - -msgctxt "#30009" -msgid "Artwork" -msgstr "아트워í¬" diff --git a/addons/metadata.album.universal/resources/language/Lithuanian/strings.po b/addons/metadata.album.universal/resources/language/Lithuanian/strings.po deleted file mode 100644 index b9e1017cc9..0000000000 --- a/addons/metadata.album.universal/resources/language/Lithuanian/strings.po +++ /dev/null @@ -1,58 +0,0 @@ -# XBMC Media Center language file -# Addon Name: Universal Album Scraper -# Addon id: metadata.album.universal -# Addon version: 1.6.0 -# Addon Provider: Olympia, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main Translation Project (Frodo)\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" -"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: XBMC Translation Team\n" -"Language-Team: Lithuanian (http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/lt/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: lt\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);\n" - -msgctxt "#30000" -msgid "Grab Album Thumbs from fanart.tv" -msgstr "Paimti albumų miniatiÅ«ras iÅ¡ fanart.tv" - -msgctxt "#30001" -msgid "Grab Album Thumbs from Last.fm" -msgstr "Paimti albumų miniatiÅ«ras iÅ¡ Last.fm" - -msgctxt "#30002" -msgid "Get Album Review from" -msgstr "Gauti albumo apžvalgÄ… iÅ¡" - -msgctxt "#30003" -msgid " Preferred Language" -msgstr " Pageidaujama kalba" - -msgctxt "#30004" -msgid "Get Album Rating from" -msgstr "Gauti albumo reitingÄ… iÅ¡" - -msgctxt "#30005" -msgid "Get Album Styles from" -msgstr "Gauti albumo stilių iÅ¡" - -msgctxt "#30006" -msgid "Get Album Moods from" -msgstr "Gauti albumo žanrÄ… iÅ¡" - -msgctxt "#30007" -msgid "Get Album Themes from" -msgstr "Gauti albumo temÄ… iÅ¡" - -msgctxt "#30008" -msgid "Grab Album Thumbs from allmusic.com" -msgstr "Paimti albumų miniatiÅ«ras iÅ¡ allmusic.com" - -msgctxt "#30009" -msgid "Artwork" -msgstr "Iliustracijos" diff --git a/addons/metadata.album.universal/resources/language/Macedonian/strings.po b/addons/metadata.album.universal/resources/language/Macedonian/strings.po deleted file mode 100644 index 297c3e981c..0000000000 --- a/addons/metadata.album.universal/resources/language/Macedonian/strings.po +++ /dev/null @@ -1,58 +0,0 @@ -# XBMC Media Center language file -# Addon Name: Universal Album Scraper -# Addon id: metadata.album.universal -# Addon version: 1.6.0 -# Addon Provider: Olympia, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main Translation Project (Frodo)\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" -"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: XBMC Translation Team\n" -"Language-Team: Macedonian (http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/mk/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: mk\n" -"Plural-Forms: nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;\n" - -msgctxt "#30000" -msgid "Grab Album Thumbs from fanart.tv" -msgstr "Грабни Сликички за Ðлбум од fanart.tv" - -msgctxt "#30001" -msgid "Grab Album Thumbs from Last.fm" -msgstr "Грабни Сликички за Ðлбум од Last.fm" - -msgctxt "#30002" -msgid "Get Album Review from" -msgstr "Грабни преглед на Ðлбум од" - -msgctxt "#30003" -msgid " Preferred Language" -msgstr "ПоÑакуван јазик" - -msgctxt "#30004" -msgid "Get Album Rating from" -msgstr "Превземи рејтинг за албум од" - -msgctxt "#30005" -msgid "Get Album Styles from" -msgstr "Превземи Ñтилови на албум од" - -msgctxt "#30006" -msgid "Get Album Moods from" -msgstr "Get Album Moods from" - -msgctxt "#30007" -msgid "Get Album Themes from" -msgstr "Превземи Теми на албуми од" - -msgctxt "#30008" -msgid "Grab Album Thumbs from allmusic.com" -msgstr "Превземи Ñликички на албуми од allmusic.com" - -msgctxt "#30009" -msgid "Artwork" -msgstr "Уметнини" diff --git a/addons/metadata.album.universal/resources/language/Norwegian/strings.po b/addons/metadata.album.universal/resources/language/Norwegian/strings.po deleted file mode 100644 index dfdb771e9d..0000000000 --- a/addons/metadata.album.universal/resources/language/Norwegian/strings.po +++ /dev/null @@ -1,58 +0,0 @@ -# XBMC Media Center language file -# Addon Name: Universal Album Scraper -# Addon id: metadata.album.universal -# Addon version: 1.6.0 -# Addon Provider: Olympia, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main Translation Project (Frodo)\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" -"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: XBMC Translation Team\n" -"Language-Team: Norwegian (http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/no/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: no\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Grab Album Thumbs from fanart.tv" -msgstr "Hent Album Thumbs fra fanart.tv" - -msgctxt "#30001" -msgid "Grab Album Thumbs from Last.fm" -msgstr "Hent Album Thumbs fra Last.fm" - -msgctxt "#30002" -msgid "Get Album Review from" -msgstr "Hent Album Omtaler fra" - -msgctxt "#30003" -msgid " Preferred Language" -msgstr "Foretrukket SprÃ¥k" - -msgctxt "#30004" -msgid "Get Album Rating from" -msgstr "Hent Album Omtale fra" - -msgctxt "#30005" -msgid "Get Album Styles from" -msgstr "Hent Album Stiler fra" - -msgctxt "#30006" -msgid "Get Album Moods from" -msgstr "Hent Album Humør fra" - -msgctxt "#30007" -msgid "Get Album Themes from" -msgstr "Hent Album Temaer fra" - -msgctxt "#30008" -msgid "Grab Album Thumbs from allmusic.com" -msgstr "Hent Album Thumbs fra allmusic.com" - -msgctxt "#30009" -msgid "Artwork" -msgstr "Artwork" diff --git a/addons/metadata.album.universal/resources/language/Polish/strings.po b/addons/metadata.album.universal/resources/language/Polish/strings.po deleted file mode 100644 index e542ca0fec..0000000000 --- a/addons/metadata.album.universal/resources/language/Polish/strings.po +++ /dev/null @@ -1,58 +0,0 @@ -# XBMC Media Center language file -# Addon Name: Universal Album Scraper -# Addon id: metadata.album.universal -# Addon version: 1.6.0 -# Addon Provider: Olympia, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main Translation Project (Frodo)\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" -"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: XBMC Translation Team\n" -"Language-Team: Polish (http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/pl/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: pl\n" -"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" - -msgctxt "#30000" -msgid "Grab Album Thumbs from fanart.tv" -msgstr "Pobierz miniatury Albumu z fanart.tv" - -msgctxt "#30001" -msgid "Grab Album Thumbs from Last.fm" -msgstr "Pobierz miniatury Albumu z Last.fm" - -msgctxt "#30002" -msgid "Get Album Review from" -msgstr "Pobierz recenzje albumu z " - -msgctxt "#30003" -msgid " Preferred Language" -msgstr "Preferowany jÄ™zyk" - -msgctxt "#30004" -msgid "Get Album Rating from" -msgstr "Pobierz ocene albumu z" - -msgctxt "#30005" -msgid "Get Album Styles from" -msgstr "Pobierz style Albumu z" - -msgctxt "#30006" -msgid "Get Album Moods from" -msgstr "Pobierz nastroje Albumu z" - -msgctxt "#30007" -msgid "Get Album Themes from" -msgstr "Pobierz motywy Albumu z" - -msgctxt "#30008" -msgid "Grab Album Thumbs from allmusic.com" -msgstr "Pobierz miniatury Albumu z allmusic.com" - -msgctxt "#30009" -msgid "Artwork" -msgstr "Artwork" diff --git a/addons/metadata.album.universal/resources/language/Portuguese (Brazil)/strings.po b/addons/metadata.album.universal/resources/language/Portuguese (Brazil)/strings.po deleted file mode 100644 index bab8c1a275..0000000000 --- a/addons/metadata.album.universal/resources/language/Portuguese (Brazil)/strings.po +++ /dev/null @@ -1,58 +0,0 @@ -# XBMC Media Center language file -# Addon Name: Universal Album Scraper -# Addon id: metadata.album.universal -# Addon version: 1.6.0 -# Addon Provider: Olympia, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main Translation Project (Frodo)\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" -"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: XBMC Translation Team\n" -"Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/pt_BR/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: pt_BR\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" - -msgctxt "#30000" -msgid "Grab Album Thumbs from fanart.tv" -msgstr "Pegar Miniaturas dos Ãlbuns de fanart.tv" - -msgctxt "#30001" -msgid "Grab Album Thumbs from Last.fm" -msgstr "Pegar Miniaturas dos Ãlbuns do Last.fm" - -msgctxt "#30002" -msgid "Get Album Review from" -msgstr "Pegar Review dos Ãlbuns de" - -msgctxt "#30003" -msgid " Preferred Language" -msgstr " Linguagem Preferida" - -msgctxt "#30004" -msgid "Get Album Rating from" -msgstr "Pegar Avaliação dos álbuns de" - -msgctxt "#30005" -msgid "Get Album Styles from" -msgstr "Obter Estilos dos Ãlbuns de" - -msgctxt "#30006" -msgid "Get Album Moods from" -msgstr "Obter Moods dos Ãlbuns de " - -msgctxt "#30007" -msgid "Get Album Themes from" -msgstr "Obter Temas dos Ãlbuns de" - -msgctxt "#30008" -msgid "Grab Album Thumbs from allmusic.com" -msgstr "Pegar Miniaturas Ãlbuns de allmusic.com" - -msgctxt "#30009" -msgid "Artwork" -msgstr "Artwork" diff --git a/addons/metadata.album.universal/resources/language/Portuguese/strings.po b/addons/metadata.album.universal/resources/language/Portuguese/strings.po deleted file mode 100644 index 49b4298517..0000000000 --- a/addons/metadata.album.universal/resources/language/Portuguese/strings.po +++ /dev/null @@ -1,62 +0,0 @@ -# XBMC Media Center language file -# Addon Name: Universal Album Scraper -# Addon id: metadata.album.universal -# Addon version: 1.6.0 -# Addon Provider: Olympia, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main Translation Project (Frodo)\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" -"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: XBMC Translation Team\n" -"Language-Team: Portuguese (http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/pt/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: pt\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Grab Album Thumbs from fanart.tv" -msgstr "Obter as miniaturas do álbum de fanart.tv" - -msgctxt "#30001" -msgid "Grab Album Thumbs from Last.fm" -msgstr "Obter as miniaturas do álbum de Last.fm" - -msgctxt "#30002" -msgid "Get Album Review from" -msgstr "Obter a critica do álbum de" - -msgctxt "#30003" -msgid " Preferred Language" -msgstr "Idioma preferido" - -msgctxt "#30004" -msgid "Get Album Rating from" -msgstr "Obter a classificação do álbum de" - -msgctxt "#30005" -msgid "Get Album Styles from" -msgstr "Obter o estilo do álbum de" - -msgctxt "#30006" -msgid "Get Album Moods from" -msgstr "Obter Ambiências do Album de" - -msgctxt "#30007" -msgid "Get Album Themes from" -msgstr "Obter o tema do álbum de" - -msgctxt "#30008" -msgid "Grab Album Thumbs from allmusic.com" -msgstr "Obter as miniaturas do álbum de allmusic.com" - -msgctxt "#30009" -msgid "Artwork" -msgstr "Artwork" - -msgctxt "#30010" -msgid "Grab Album Thumbs from theaudiodb.com" -msgstr "Obter miniaturas de álbum de theaudiodb.com" diff --git a/addons/metadata.album.universal/resources/language/Russian/strings.po b/addons/metadata.album.universal/resources/language/Russian/strings.po deleted file mode 100644 index 87a7c45feb..0000000000 --- a/addons/metadata.album.universal/resources/language/Russian/strings.po +++ /dev/null @@ -1,58 +0,0 @@ -# XBMC Media Center language file -# Addon Name: Universal Album Scraper -# Addon id: metadata.album.universal -# Addon version: 1.6.0 -# Addon Provider: Olympia, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main Translation Project (Frodo)\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" -"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: XBMC Translation Team\n" -"Language-Team: Russian (http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/ru/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ru\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" - -msgctxt "#30000" -msgid "Grab Album Thumbs from fanart.tv" -msgstr "Получать иконки альбома Ñ fanart.tv" - -msgctxt "#30001" -msgid "Grab Album Thumbs from Last.fm" -msgstr "Получать иконки альбома Ñ Last.fm" - -msgctxt "#30002" -msgid "Get Album Review from" -msgstr "Получать обзор альбома Ñ" - -msgctxt "#30003" -msgid " Preferred Language" -msgstr "Язык предпочтениÑ" - -msgctxt "#30004" -msgid "Get Album Rating from" -msgstr "Получать рейтинг альбома Ñ" - -msgctxt "#30005" -msgid "Get Album Styles from" -msgstr "Получать Ñтиль альбома Ñ" - -msgctxt "#30006" -msgid "Get Album Moods from" -msgstr "Получать направление альбома Ñ" - -msgctxt "#30007" -msgid "Get Album Themes from" -msgstr "Получать темы альбома Ñ" - -msgctxt "#30008" -msgid "Grab Album Thumbs from allmusic.com" -msgstr "Получать иконки альбома Ñ allmusic.com" - -msgctxt "#30009" -msgid "Artwork" -msgstr "Обложка" diff --git a/addons/metadata.album.universal/resources/language/Slovak/strings.po b/addons/metadata.album.universal/resources/language/Slovak/strings.po deleted file mode 100644 index 4d0b0706d1..0000000000 --- a/addons/metadata.album.universal/resources/language/Slovak/strings.po +++ /dev/null @@ -1,58 +0,0 @@ -# XBMC Media Center language file -# Addon Name: Universal Album Scraper -# Addon id: metadata.album.universal -# Addon version: 1.6.0 -# Addon Provider: Olympia, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main Translation Project (Frodo)\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" -"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: XBMC Translation Team\n" -"Language-Team: Slovak (http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/sk/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: sk\n" -"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" - -msgctxt "#30000" -msgid "Grab Album Thumbs from fanart.tv" -msgstr "ZÃskaÅ¥ náhľady albumu zo stránky fanart.tv" - -msgctxt "#30001" -msgid "Grab Album Thumbs from Last.fm" -msgstr "ZÃskaÅ¥ náhľady albumu zo stránky Last.fm" - -msgctxt "#30002" -msgid "Get Album Review from" -msgstr "ZÃskaÅ¥ recenziu na album zo stránky" - -msgctxt "#30003" -msgid " Preferred Language" -msgstr "Uprednostňovaný jazyk" - -msgctxt "#30004" -msgid "Get Album Rating from" -msgstr "ZÃskaÅ¥ hodnotenie albumu zo stránky" - -msgctxt "#30005" -msgid "Get Album Styles from" -msgstr "ZÃskaÅ¥ Å¡týly albumu zo stránky" - -msgctxt "#30006" -msgid "Get Album Moods from" -msgstr "ZÃskaÅ¥ náladu albumu zo stránky" - -msgctxt "#30007" -msgid "Get Album Themes from" -msgstr "ZÃskaÅ¥ motÃvy albumu zo stránky" - -msgctxt "#30008" -msgid "Grab Album Thumbs from allmusic.com" -msgstr "ZÃskaÅ¥ náhľady albumu zo stránky allmusic.com" - -msgctxt "#30009" -msgid "Artwork" -msgstr "Umelecká grafika" diff --git a/addons/metadata.album.universal/resources/language/Spanish (Argentina)/strings.po b/addons/metadata.album.universal/resources/language/Spanish (Argentina)/strings.po deleted file mode 100644 index a22e3a2387..0000000000 --- a/addons/metadata.album.universal/resources/language/Spanish (Argentina)/strings.po +++ /dev/null @@ -1,58 +0,0 @@ -# XBMC Media Center language file -# Addon Name: Universal Album Scraper -# Addon id: metadata.album.universal -# Addon version: 1.6.0 -# Addon Provider: Olympia, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main Translation Project (Frodo)\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" -"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: XBMC Translation Team\n" -"Language-Team: Spanish (Argentina) (http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/es_AR/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: es_AR\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Grab Album Thumbs from fanart.tv" -msgstr "Obtener Miniaturas de Ãlbum de fanart.tv" - -msgctxt "#30001" -msgid "Grab Album Thumbs from Last.fm" -msgstr "Obtener Miniaturas de Ãlbum de Last.fm" - -msgctxt "#30002" -msgid "Get Album Review from" -msgstr "Obtener Reseña del Ãlbum de" - -msgctxt "#30003" -msgid " Preferred Language" -msgstr "Idioma Preferido" - -msgctxt "#30004" -msgid "Get Album Rating from" -msgstr "Obtener Calificación del Ãlbum de " - -msgctxt "#30005" -msgid "Get Album Styles from" -msgstr "Obtener Estilos del Ãlbum de" - -msgctxt "#30006" -msgid "Get Album Moods from" -msgstr "Obtener Estados de Ãnimo del Ãlbum de" - -msgctxt "#30007" -msgid "Get Album Themes from" -msgstr "Obtener Temas del Ãlbum de" - -msgctxt "#30008" -msgid "Grab Album Thumbs from allmusic.com" -msgstr "Conseguir Miniaturas de Ãlbum de allmusic.com" - -msgctxt "#30009" -msgid "Artwork" -msgstr "Imágenes" diff --git a/addons/metadata.album.universal/resources/language/Spanish (Mexico)/strings.po b/addons/metadata.album.universal/resources/language/Spanish (Mexico)/strings.po deleted file mode 100644 index e1f311b990..0000000000 --- a/addons/metadata.album.universal/resources/language/Spanish (Mexico)/strings.po +++ /dev/null @@ -1,58 +0,0 @@ -# XBMC Media Center language file -# Addon Name: Universal Album Scraper -# Addon id: metadata.album.universal -# Addon version: 1.6.0 -# Addon Provider: Olympia, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main Translation Project (Frodo)\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" -"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: XBMC Translation Team\n" -"Language-Team: Spanish (Mexico) (http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/es_MX/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: es_MX\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Grab Album Thumbs from fanart.tv" -msgstr "Obtener Miniaturas de Ãlbumes de fanart.tv" - -msgctxt "#30001" -msgid "Grab Album Thumbs from Last.fm" -msgstr "Obtener Miniaturas de Ãlbumes de Last.fm" - -msgctxt "#30002" -msgid "Get Album Review from" -msgstr "Obtener Reviews de Ãlbumes de" - -msgctxt "#30003" -msgid " Preferred Language" -msgstr "Lenguaje Preferido" - -msgctxt "#30004" -msgid "Get Album Rating from" -msgstr "Obtener Ratings de Ãlbumes de" - -msgctxt "#30005" -msgid "Get Album Styles from" -msgstr "Obtener Estilos de Ãlbumes de" - -msgctxt "#30006" -msgid "Get Album Moods from" -msgstr "Obtener Atmósfera de Ãlbumes de" - -msgctxt "#30007" -msgid "Get Album Themes from" -msgstr "Obtener Temas de Ãlbumes de" - -msgctxt "#30008" -msgid "Grab Album Thumbs from allmusic.com" -msgstr "Obtener Miniaturas de Ãlbumes de allmusic.com" - -msgctxt "#30009" -msgid "Artwork" -msgstr "Artwork" diff --git a/addons/metadata.album.universal/resources/language/Spanish/strings.po b/addons/metadata.album.universal/resources/language/Spanish/strings.po deleted file mode 100644 index a418921e27..0000000000 --- a/addons/metadata.album.universal/resources/language/Spanish/strings.po +++ /dev/null @@ -1,58 +0,0 @@ -# XBMC Media Center language file -# Addon Name: Universal Album Scraper -# Addon id: metadata.album.universal -# Addon version: 1.6.0 -# Addon Provider: Olympia, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main Translation Project (Frodo)\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" -"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: XBMC Translation Team\n" -"Language-Team: Spanish (http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/es/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: es\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Grab Album Thumbs from fanart.tv" -msgstr "Obtener miniaturas de álbum de fanart.tv" - -msgctxt "#30001" -msgid "Grab Album Thumbs from Last.fm" -msgstr "Obtener miniaturas de álbum de Last.fm" - -msgctxt "#30002" -msgid "Get Album Review from" -msgstr "Obtener reseña del álbum de" - -msgctxt "#30003" -msgid " Preferred Language" -msgstr "Idioma preferido" - -msgctxt "#30004" -msgid "Get Album Rating from" -msgstr "Obtener calificación del álbum de " - -msgctxt "#30005" -msgid "Get Album Styles from" -msgstr "Obtener estilos del álbum de" - -msgctxt "#30006" -msgid "Get Album Moods from" -msgstr "Obtener estados de ánimo del álbum de" - -msgctxt "#30007" -msgid "Get Album Themes from" -msgstr "Obtener temas del álbum de" - -msgctxt "#30008" -msgid "Grab Album Thumbs from allmusic.com" -msgstr "Conseguir miniaturas de álbum de allmusic.com" - -msgctxt "#30009" -msgid "Artwork" -msgstr "Imágenes" diff --git a/addons/metadata.album.universal/resources/language/Swedish/strings.po b/addons/metadata.album.universal/resources/language/Swedish/strings.po deleted file mode 100644 index ed20b3da73..0000000000 --- a/addons/metadata.album.universal/resources/language/Swedish/strings.po +++ /dev/null @@ -1,62 +0,0 @@ -# XBMC Media Center language file -# Addon Name: Universal Album Scraper -# Addon id: metadata.album.universal -# Addon version: 1.6.0 -# Addon Provider: Olympia, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main Translation Project (Frodo)\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" -"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: XBMC Translation Team\n" -"Language-Team: Swedish (http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/sv/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: sv\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Grab Album Thumbs from fanart.tv" -msgstr "Hämta albumminiatyrer frÃ¥n fanart.tv" - -msgctxt "#30001" -msgid "Grab Album Thumbs from Last.fm" -msgstr "Hämta albumminiatyrer frÃ¥n Last.fm" - -msgctxt "#30002" -msgid "Get Album Review from" -msgstr "Hämta albumrecensioner frÃ¥n" - -msgctxt "#30003" -msgid " Preferred Language" -msgstr "Föredraget sprÃ¥k" - -msgctxt "#30004" -msgid "Get Album Rating from" -msgstr "Hämta albumbetyg frÃ¥n" - -msgctxt "#30005" -msgid "Get Album Styles from" -msgstr "Hämta albumstilar frÃ¥n" - -msgctxt "#30006" -msgid "Get Album Moods from" -msgstr "Hämta albumstämningar frÃ¥n" - -msgctxt "#30007" -msgid "Get Album Themes from" -msgstr "Hämta albumteman frÃ¥n" - -msgctxt "#30008" -msgid "Grab Album Thumbs from allmusic.com" -msgstr "Hämta albumminiatyrer frÃ¥n allmusic.com" - -msgctxt "#30009" -msgid "Artwork" -msgstr "Konstverk" - -msgctxt "#30010" -msgid "Grab Album Thumbs from theaudiodb.com" -msgstr "Hämta albumminiatyrer frÃ¥n theaudiodb.com" diff --git a/addons/metadata.album.universal/resources/language/Tamil (India)/strings.xml b/addons/metadata.album.universal/resources/language/Tamil (India)/strings.xml new file mode 100644 index 0000000000..e130bbd28d --- /dev/null +++ b/addons/metadata.album.universal/resources/language/Tamil (India)/strings.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Tamil (India) language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/ta_IN/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">ஆலà¯à®ªà®®à¯ கà¯à®°à¯à®ªà®Ÿà®™à¯à®•à®³à¯ˆ fanart.tv இரà¯à®¨à¯à®¤à¯ கைபà¯à®ªà®±à¯à®±à¯</string> + <string id="30001">ஆலà¯à®ªà®®à¯ கà¯à®°à¯à®ªà®Ÿà®™à¯à®•à®³à¯ˆ Last.fm இரà¯à®¨à¯à®¤à¯ கைபà¯à®ªà®±à¯à®±à¯</string> + <string id="30002">ஆலà¯à®ªà®®à¯ விமரà¯à®šà®©à®¤à¯à®¤à¯ˆ கைபà¯à®ªà®±à¯à®±à¯</string> + <string id="30003">விரà¯à®®à¯à®ªà®¿à®¯ மொழி</string> + <string id="30004">ஆலà¯à®ªà®®à¯ தரதà¯à®¤à¯ˆ கைபà¯à®ªà®±à¯à®±à¯</string> + <string id="30005">ஆலà¯à®ªà®®à¯ பாணி கைபà¯à®ªà®±à¯à®±à¯</string> + <string id="30006">ஆலà¯à®ªà®®à¯ விதமà¯à®•à®³à¯ கைபà¯à®ªà®±à¯à®±à¯</string> + <string id="30007">ஆலà¯à®ªà®®à¯ அலஙà¯à®•à®¾à®°à®™à¯à®•à®³à¯ கைபà¯à®ªà®±à¯à®±à¯</string> + <string id="30008">ஆலà¯à®ªà®®à¯ கà¯à®°à¯à®ªà®Ÿà®™à¯à®•à®³à¯ˆ allmusic.com இரà¯à®¨à¯à®¤à¯ கைபà¯à®ªà®±à¯à®±à¯</string> + <string id="30009">கà¯à®±à¯à®ªà¯à®ªà®Ÿà®®à¯</string> + <string id="30010">ஆலà¯à®ªà®®à¯ கà¯à®°à¯à®ªà®Ÿà®™à¯à®•à®³à¯ˆ theaudiodb.com இரà¯à®¨à¯à®¤à¯ கைபà¯à®ªà®±à¯à®±à¯</string> +</strings> diff --git a/addons/metadata.album.universal/resources/language/Turkish/strings.xml b/addons/metadata.album.universal/resources/language/Turkish/strings.xml new file mode 100644 index 0000000000..ea037785f9 --- /dev/null +++ b/addons/metadata.album.universal/resources/language/Turkish/strings.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Turkish language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/tr/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">Albüm Kapaklarını fanart.tv'den al</string> + <string id="30003">Tercih Edilen Dil</string> + <string id="30009">Çizim</string> +</strings> diff --git a/addons/metadata.album.universal/resources/language/Ukrainian/strings.xml b/addons/metadata.album.universal/resources/language/Ukrainian/strings.xml new file mode 100644 index 0000000000..4fc1e7e264 --- /dev/null +++ b/addons/metadata.album.universal/resources/language/Ukrainian/strings.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Ukrainian language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/uk/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">Отримати малюнки альбомів з fanart.tv</string> + <string id="30001">Отримати малюнки альбому з Last.fm</string> + <string id="30002">Отримати оглÑд альбому з</string> + <string id="30003">Улюблена мова</string> + <string id="30004">Отримати рейтинг альбому з</string> + <string id="30005">Отримати Ñтилі альбому з</string> + <string id="30006">Отримати наÑтрої альбому з</string> + <string id="30007">Отримати теми альбому з</string> + <string id="30008">Отримати малюнки альбому з allmusic.com</string> + <string id="30009">Обкладинка</string> + <string id="30010">Отримати малюнки альбому з theaudiodb.com</string> +</strings> diff --git a/addons/metadata.album.universal/resources/language/Vietnamese/strings.xml b/addons/metadata.album.universal/resources/language/Vietnamese/strings.xml new file mode 100644 index 0000000000..06d7dbc247 --- /dev/null +++ b/addons/metadata.album.universal/resources/language/Vietnamese/strings.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Vietnamese language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/vi/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">Lấy hình đại diện album từ nguồn fanart.tv</string> + <string id="30001">Lấy hình đại diện album từ nguồn Last.fm</string> + <string id="30002">Lấy bà i đánh giá album từ</string> + <string id="30003">Ưu tiên ngôn ngữ</string> + <string id="30004">Lấy Album Rating từ</string> + <string id="30005">Lấy Album Styles từ</string> + <string id="30006">Lấy Album Moods từ</string> + <string id="30007">Lấy Album Themes từ</string> + <string id="30008">Lấy hình đại diện album từ nguồn allmusic.com</string> + <string id="30009">Ảnh bìa</string> + <string id="30010">Lấy hình đại diện album từ nguồn theaudiodb.com</string> +</strings> diff --git a/addons/metadata.album.universal/resources/language/Welsh/strings.xml b/addons/metadata.album.universal/resources/language/Welsh/strings.xml new file mode 100644 index 0000000000..2dbc969d27 --- /dev/null +++ b/addons/metadata.album.universal/resources/language/Welsh/strings.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Welsh language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/cy/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">Estyn Lluniau Bach Album o fanart.tv</string> + <string id="30001">Estyn Lluniau Bach Album o Last.fm</string> + <string id="30002">Estyn Adolygiad Album</string> + <string id="30003">Dewis Iaith</string> + <string id="30004">Estyn Graddio Album o</string> + <string id="30005">Estyn Arddulliau Album o</string> + <string id="30006">Estyn Naws Album o</string> + <string id="30007">Estyn Themau Album o</string> + <string id="30008">Estyn Lluniau Bach Album o allmusic.com</string> + <string id="30009">Gwaith Celf</string> + <string id="30010">Estyn Lluniau Bach Album o theaudiodb.com</string> +</strings> diff --git a/addons/metadata.album.universal/resources/settings.xml b/addons/metadata.album.universal/resources/settings.xml index b77bc72696..f75639eb20 100644 --- a/addons/metadata.album.universal/resources/settings.xml +++ b/addons/metadata.album.universal/resources/settings.xml @@ -3,6 +3,7 @@ <category label="128"> <setting type="lsep" label="General Settings"/> <setting label="30002" type="labelenum" values="TheAudioDb.com|amazon.de|None" id="albumreviewsource" default="TheAudioDb.com"/> + <setting label="30003" type="labelenum" values="en|de|es|fr|it|cn|jp|ru|pt|se|nl|hu" id="tadbalbumlanguage" default="en" visible="eq(-1,0)"/> <setting type="sep"/> <setting label="30004" type="labelenum" values="MusicBrainz|allmusic.com|None" id="albumratingsource" default="MusicBrainz"/> <setting label="30005" type="labelenum" values="allmusic.com|None" id="albumstylessource" default="allmusic.com"/> @@ -14,6 +15,7 @@ <setting type="lsep" label="Artwork Settings"/> <setting label="30000" type="bool" id="fanarttvalbumthumbs" default="true"/> <setting label="30010" type="bool" id="tadbalbumthumbs" default="true"/> - <setting label="30008" type="bool" id="allmusicalbumthumbs" default="true"/> + <setting label="30001" type="bool" id="lastfmalbumthumbs" default="false"/> + <setting label="30008" type="bool" id="allmusicalbumthumbs" default="false"/> </category> </settings> diff --git a/addons/metadata.artists.universal/addon.xml b/addons/metadata.artists.universal/addon.xml index 2fe29b9a8b..1bc15a7e2a 100644 --- a/addons/metadata.artists.universal/addon.xml +++ b/addons/metadata.artists.universal/addon.xml @@ -1,26 +1,28 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon id="metadata.artists.universal" name="Universal Artist Scraper" - version="2.4.3" - provider-name="Team XBMC"> + version="2.6.5" + provider-name="Olympia, Team XBMC"> <requires> - <import addon="xbmc.metadata" version="1.0"/> - <import addon="metadata.common.last.fm" version="1.5.1"/> - <import addon="metadata.common.allmusic.com" version="2.5.2"/> - <import addon="metadata.common.musicbrainz.org" version="1.2.1"/> + <import addon="xbmc.metadata" version="2.1.0"/> + <import addon="metadata.common.last.fm" version="1.6.0"/> + <import addon="metadata.common.allmusic.com" version="2.6.0"/> + <import addon="metadata.common.musicbrainz.org" version="1.3.0"/> <import addon="metadata.common.htbackdrops.com" version="1.2.0"/> - <import addon="metadata.common.fanart.tv" version="2.0.0"/> - <import addon="metadata.common.theaudiodb.com" version="1.3.0"/> + <import addon="metadata.common.fanart.tv" version="2.1.2"/> + <import addon="metadata.common.theaudiodb.com" version="1.5.0"/> </requires> <extension point="xbmc.metadata.scraper.artists" language="en" library="artistuniversal.xml"/> <extension point="xbmc.addon.metadata"> <summary lang="af">Universal Skraper vir Kunstenaars</summary> + <summary lang="ar">ماسØØ© الÙنان العالمية</summary> <summary lang="be">Universal Scraper for Artists</summary> <summary lang="bg">УниверÑален източник за Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° артиÑти</summary> <summary lang="ca">Arreplegador universal per artistes</summary> <summary lang="cs">Univerzálnà zdroj zÃskávánà dat pro umÄ›lce</summary> + <summary lang="cy">Crafwr Cyffredinol ar gyfer Artistiaid</summary> <summary lang="da">Universel Scraper til Kunstnere</summary> <summary lang="de">Universal Scraper für Interpreten</summary> <summary lang="el">Universal Scraper Καλλιτεχνών</summary> @@ -28,6 +30,7 @@ <summary lang="es">Scraper universal para artistas</summary> <summary lang="es_AR">Scraper Universal para Artistas</summary> <summary lang="es_MX">Scraper Universal de Artistas</summary> + <summary lang="et">Universaalne artistide kraabits</summary> <summary lang="fi">Universaali artistien tiedonhakija</summary> <summary lang="fr">Collecteur universel d'artistes</summary> <summary lang="gl">Scraper Universal para Artistas</summary> @@ -38,7 +41,9 @@ <summary lang="ko">Universal Scraper for Artists</summary> <summary lang="lt">Universalus Artistų Scrapers</summary> <summary lang="mk">Universal Scraper for Artists</summary> + <summary lang="my">အနုပညာရှင်များအá€á€½á€€á€º Universal Scraper</summary> <summary lang="nl">Universele scraper voor artiesten</summary> + <summary lang="no">Universalskraper for artister</summary> <summary lang="pl">Universal Scraper dla Artystów muzycznych</summary> <summary lang="pt">Scraper universal para Artistas</summary> <summary lang="pt_BR">Scraper Universal para Artistas</summary> @@ -47,12 +52,18 @@ <summary lang="sk">Univerzálny zdroj zÃskavania dát pre umelcov</summary> <summary lang="sl">Univerzalen ponudnik informacij o izvajalcih</summary> <summary lang="sv">Universiell artistskrapa</summary> + <summary lang="ta_IN">கலைஞரà¯à®•à®³à®¿à®©à¯ ஒடà¯à®Ÿà¯ மொதà¯à®¤à®®à®¾à®© சà¯à®°à®£à¯à®Ÿà®¿</summary> + <summary lang="uk">УніверÑальний здирач Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð²Ñ†Ñ–Ð²</summary> + <summary lang="vi">Trình lấy dữ liệu Nghệ sÄ© từ nhiá»u nguồn</summary> <summary lang="zh">通用艺术家信æ¯åˆ®å‰Šå™¨</summary> + <summary lang="zh_TW">通用演出者訊æ¯æœæ‹¬å™¨</summary> <description lang="af">Hierdie skraper versamel informasie van die volgende ondersteunde werwe: TheAudioDb.com, MusicBrainz, last.fm, en allmusic.com, terwyl kunswerke gryp van: fanart.tv, htbackdrops.com, last.fm en allmusic.com. Dit kan veld vir veld gestel word vanaf watter werf jy die spesifike informasie wil hê. Die aanvanklike soektog word altyd op MusicBrainz gedoen. Ingeval die allmusic skakel nie bygevoeg is op die MusicBrainz werf, kan velde van allmusic.com nie gaan haal word nie (egter baie maklik om daardie ontbrekende skakels by te voeg).</description> + <description lang="ar">هذه الماسØØ© تجمع المعلومات من المواقع المدعومة التالية: TheAudioDb.com, MusicBrainz, last.fm, and allmusic.com, ÙÙŠ Øين تأخذ عناوين الأعمال الÙنية من: fanart.tv, htbackdrops.com, last.fm and allmusic.com. يمكن أن ترتب Øقل تلو Øقل Øسب الموقع الذي تريد منه تلك المعلومة المØددة. البØØ« الابتدائي يتم دائما على ميوزك برينز. ÙÙŠ Øال أن رابط كل الموسيقى غير مضا٠على Øقول موقع ميوزك برينز من allmusic.com لا يمكن الØصول عليها(على الرغم من سهولة إضاÙØ© هذه الروابط المÙقودة).</description> <description lang="be">This scraper collects information from the following supported sites: TheAudioDb.com, MusicBrainz, last.fm, and allmusic.com, while grabs artwork from: fanart.tv, htbackdrops.com, last.fm and allmusic.com. It can be set field by field that from which site you want that specific information. The initial search is always done on MusicBrainz. In case allmusic link is not added on the MusicBrainz site fields from allmusic.com cannot be fetched (very easy to add those missing links though).</description> <description lang="bg">Ð¡Ð²Ð°Ð»Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾Ñ‚ Ñледните Ñайтове: TheAudioDb.com, MusicBrainz, last.fm, and allmusic.com. Ð˜Ð·Ð¾Ð±Ñ€Ð°Ð½Ð¸Ñ Ð¸Ð·Ð²Ð»Ð¸Ñ‡Ð° от: fanart.tv, htbackdrops.com, last.fm and allmusic.com. Можете да определите от кой Ñайт каква Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð´Ð° Ñе ÑвалÑ. Първоначалното Ñ‚ÑŠÑ€Ñене винаги Ñе прави в MusicBrainz. Когато не е налична препратка към allmusic.com на Ñайта на MusicBrainz извличането на Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾Ñ‚ allmusic.com Ñтава невъзможно (добавÑнето на препратка е много леÑно).</description> <description lang="ca">Aquest arreplegador recull informació dels següents llocs suportats</description> <description lang="cs">Tento zdroj dat zÃskává informace z následujÃcÃch podporovaných stránek: TheAudioDb.com, MusicBrainz, last.fm, and allmusic.com, while grabs artwork from: fanart.tv, htbackdrops.com, last.fm a allmusic.com. Lze nastavit jakou informaci stahovat z jakých stránek. Základnà hledánà je vždy provedeno na MusicBrainz. V pÅ™ÃpadÄ›, že scházà odkaz allmusic na stránce MusicBrains, nelze stáhnout informace z allmusic.com (avÅ¡ak je velmi snadné chybÄ›jÃcà odkazy pÅ™idat).</description> + <description lang="cy">Mae'r crafwr yn casglu gwybodaeth o'r gwefannau canlynol: TheAudioDb.com, MusicBrainz, last.fm, a allmusic.com, tra'n cipio gwaith celf o: fanart.tv, htbackdrops.com, last.fm a allmusic.com. Mae modd ei osod fesul maes i ddewis pa wefan i gasglu gwybodaeth benodol. Bydd y chwilio cychwynnol yn cael ei wneud ar MusicBrainz. Rhag ofn nad yw dolen allmusic wedi ei osod ar wefan MusicBrainz nid oes modd estyn meysydd o allmusic.com (mae'n hawdd gosod y dolenni coll hynny).</description> <description lang="da">Denne scraper samler information fra følgende sider: TheAudioDb.com, MusicBrainz, last.fm, og allmusic.com, og henter illustrationer fra: fanart.tv, htbackdrops.com, last.fm og allmusic.com. Det kan vælges felt for felt, fra hvilke sider du ønsker, at fÃ¥ de pÃ¥gældende informationer fra. Den første søgning er altid pÃ¥ MusicBrainz. Hvis ikke allmusic linket er tilføjet pÃ¥ MusicBrainz side, kan felter fra allmusic.com ikke hentes (men det er helt enkelt at tilføje de manglende links).</description> <description lang="de">Dieser Scraper unterstützt das Sammeln von Informationen von den folgenden Seiten: TheAudioDb.com, MusicBrainz, last.fm, und allmusic.com, Grafiken werden geladen von: fanart.tv, htbackdrops.com, last.fm und allmusic.com. Es kann Feld für Feld festgelegt werden welche Information von welcher Seite geladen werden soll. Die erste Suche wird immer auf MusicBrainz durchgeführt. Sollte der allmusic link auf der MusicBrainz Seite fehlen, können keine Informationen von allmusic geladen werden. (diese fehlenden links können sehr leicht nachgetragen werden).</description> <description lang="el">Αυτό το scraper συλλÎγει πληÏοφοÏίες από τις ακόλουθες υποστηÏιζόμενες ιστοσελίδες: TheAudioDb.com, MusicBrainz, last.fm και allmusic.com, ενώ λαμβάνει εικόνες από τα: fanart.tv, htbackdrops.com, last.fm και allmusic.com. ΜποÏεί να οÏιστεί πεδίο ανά πεδίο αναλόγως των πληÏοφοÏιών που επιθυμείτε από την εκάστοτε ιστοσελίδα. Η αÏχική αναζήτηση γίνεται πάντα στο MusicBrainz. Σε πεÏίπτωση που δεν Îχουν Ï€Ïοστεθεί σÏνδεσμοι για το allmusic στο MusicBrainz, δε θα μποÏοÏν να ληφθοÏν πεδία από το allmusic.com (ωστόσο είναι Ï€Î¿Î»Ï ÎµÏκολο να Ï€ÏοστεθοÏν αυτοί οι ελλιπείς σÏνδεσμοι).</description> @@ -60,6 +71,7 @@ <description lang="es">Este scraper recopila información de las siguientes webs: TheAudioDb.com, MusicBrainz, last.fm y allmusic.com, mientras obtiene las imágenes de fanart.tv, htbackdrops.com, last.fm y allmusic.com. Permite especificar de qué web se quiere obtener la información especÃfica. ⎠⎠La búsqueda inicial se realiza siempre en MusicBrainz. En caso de que los enlaces a allmusic no estén añadidos en la web de MusicBrainz, no se podrán obtener los campos de información de este sitio (aunque es muy fácil añadir esos enlaces que faltan).</description> <description lang="es_AR">Este scraper recopila información de las siguientes webs: TheAudioDb.com, MusicBrainz, last.fm y allmusic.com, mientras que obtiene las imágenes de fanart.tv, htbackdrops.com, last.fm y allmusic.com. Permite especificar de qué web se quiere obtener la información especÃfica. ⎠⎠La búsqueda inicial se realiza siempre en MusicBrainz. En caso de que los enlaces a allmusic no estén añadidos en la web de MusicBrainz, no se podrán obtener los campos de información de este sitio (aunque es muy fácil añadir esos enlaces que faltan).</description> <description lang="es_MX">Este scraper obtiene información de los siguientes sitios soportados: TheAudioDb.com, MusicBrainz, last.fm y allmusic.com, mientras obtiene artwork de: fanart.tv, htbackdrops.com, last.fm y allmusic.com. Puede ser configurado campo por campo de que sitio quieres esa información especÃfica.⎠⎠La búsqueda inicial siempre es hecha en MusicBrainz. En el caso en que los enlaces de allmusic no son agregados en el sitio de MusicBrainz, campos de allmusic.com no pueden ser obtenidos. (De cualquier manera es muy fácil agregar esos enlaces no encontrados).</description> + <description lang="et">See kraabits kogub infot järgmistelt lehtedelt: TheAudioDb.com, MusicBrainz, last.fm ja allmusic.com, pilte: fanart.tv, htbackdrops.com, last.fm ja allmusic.com. Saad välja kaupa määrata, milliselt lehelt mis infot soovid. Esmane otsing tehakse alati saidilt MusicBrainz. Kui MusicBrainz lehele pole allmusic linki lisatud, siis allmusic.com lehelt sisu hankida ei saa (puuduvaid linke saad ise lihtsalt lisada).</description> <description lang="fi">Tämä tiedonhakija käyttää tietolähteinään seuraavia sivustoja: TheAudioDb.com, MusicBrainz, last.fm, and allmusic.com. Kuvat ja grafiikat haetaan seuraavilta sivustoilta: fanart.tv, htbackdrops.com, last.fm and allmusic.com. Voit määrittää tarkasti, miltä sivustoilta mitäkin tietoa haetaan. Ensimmäinen haku tehdään aina lähteestä MusicBrainz. Mikäli allmusic-linkkiä ei ole lisätty MusicBrainz-sivustolle allmusic.com-osoitteessa, haku ei onnistu (mutta puuttuvien linkkien lisääminen on helppoa).</description> <description lang="fr">Ce collecteur répertorie les informations des sites suivants : TheAudioDb.com, MusicBrainz, Last.fm et allmusic.com tout en assemblant les illustrations depuis : fanart.tv, htbackdrops.com, last.fm et allmusic.com. Vous pouvez définir la source d'information pour chaque champ. La recherche initiale est toujours faite à partir de MusicBrainz. xxxxxxxx (en attente du retour de l'équipe xbmc) xxxxxxxxxxx</description> <description lang="gl">Este scraper recolle información dos seguintes sitios: TheAudioDb.com, MusicBrainz, last.fm e allmusic.com, mentres que, obtén as imaxes de: fanart.tv, htbackdrops.com, last.fm e allmusic.com. Pode definir en cada campo o sitio de onde quere obter a información. A busca inicial é feita sempre no MusicBrainz, no caso de que a ligazón a allmusic non se teña engadido nos campos do sÃtio MusicBrainz dende allmusic.com, non se poderán obter (aÃnda que, é moi doado engadir as ligazóns que faltan).</description> @@ -67,10 +79,11 @@ <description lang="hu">Ez a leolvasó a következÅ‘ weboldalakról gyűjti be az adatokat: TheAudioDb.com, MusicBrainz, last.fm és allmusic.com, mÃg képeket a következÅ‘ oldalakról gyűjt: fanart.tv, htbackdrops.com, last.fm és allmusic.com. Egyenként beállÃtható, hogy az adott mezÅ‘t melyik weboldalról töltse fel⎠⎠A kiinduló keresés mindig a MusicBrainz. Amennyiben az allmusic utalás nincs hozzáadva MusicBrainz oldalhoz, a mezÅ‘k nem tölthetÅ‘k le az allmusic.com oldalról (a hiányzó utalások hozzáadása azonban nagyon egyszerű).</description> <description lang="it">Lo scraper colleziona informazioni da questi siti supportati: TheAudioDb.com, MusicBrainz, last.fm, e allmusic.com, mentre ottiene le grafiche da: fanart.tv, htbackdrops.com, last.fm e allmusic.com. Può essere impostato campo per campo da quale sito vuoi la specifica informazione. La ricerca iniziale è sempre fatta su MusicBrainz. Nel caso che il link allmusic non è stato aggiunto al campo del sito MusicBrainz da allmusic.com; non possono essere ottenute (è comunque veramente facile aggiungere questi link mancanti).</description> <description lang="ja">ã“ã®ã‚¹ã‚¯ãƒ¬ãƒ¼ãƒ‘ーã¯ã€ä»¥ä¸‹ã®ã‚µã‚¤ãƒˆã‹ã‚‰æƒ…å ±ã‚’å–å¾—ã—ã¾ã™ï¼šTheAudioDb.com, MusicBrainz, last.fm, allmusic.com。アートワークã¯ä»¥ä¸‹ã®ã‚µã‚¤ãƒˆã‹ã‚‰å–å¾—ã—ã¾ã™ï¼šfanart.tv, htbackdrops.com, last.fm, allmusic.com。å„フィールドã”ã¨ã«ã€ã©ã®æƒ…å ±ã‚’ã©ã®ã‚µã‚¤ãƒˆã‹ã‚‰å–å¾—ã™ã‚‹ã‹ã€å€‹åˆ¥ã«æŒ‡å®šã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚ 最åˆã¯ MusicBrainz を使ã£ã¦æ¤œç´¢ãŒè¡Œã‚ã‚Œã¾ã™ã€‚MusicBrainz サイト㫠allmusic ã®ãƒªãƒ³ã‚¯ãŒè¿½åŠ ã•ã‚Œã¦ã„ãªã„å ´åˆã¯ã€allmusic.com ã‹ã‚‰ã®ãƒ•ã‚£ãƒ¼ãƒ«ãƒ‰ã¯å–å¾—ã§ãã¾ã›ã‚“ (ãƒªãƒ³ã‚¯ã‚’è¿½åŠ ã™ã‚‹ã®ã¯ç°¡å˜ã§ã™ãŒ)。</description> - <description lang="ko">This scraper collects information from the following supported sites: TheAudioDb.com, MusicBrainz, last.fm, and allmusic.com, while grabs artwork from: fanart.tv, htbackdrops.com, last.fm and allmusic.com. It can be set field by field that from which site you want that specific information. The initial search is always done on MusicBrainz. In case allmusic link is not added on the MusicBrainz site fields from allmusic.com cannot be fetched (very easy to add those missing links though).</description> + <description lang="ko">ì´ ìžë£Œìˆ˜ì§‘기는 다ìŒì˜ 사ì´íŠ¸ì—ì„œ ì •ë³´ë¥¼ ê°€ì ¸ì˜µë‹ˆë‹¤: TheAudioDb.com, MusicBrainz, last.fm, allmusic.com.아트워í¬ëŠ” 다ìŒì˜ 사ì´íŠ¸ì—ì„œ ê°€ì ¸ì˜µë‹ˆë‹¤: fanart.tv, htbackdrops.com, last.fm, allmusic.com. íŠ¹ì • ì •ë³´ë¥¼ ì§€ì •í•œ 사ì´íŠ¸ì—ì„œ ê°€ì ¸ì˜¤ë„ë¡ í•„ë“œë³„ë¡œ ì„¤ì •í• ìˆ˜ 있습니다. The initial search is always done on MusicBrainz. In case allmusic link is not added on the MusicBrainz site fields from allmusic.com cannot be fetched (very easy to add those missing links though).</description> <description lang="lt">Å is Scrapers renka informacijÄ… iÅ¡ Å¡ių palaikomų svetainių: TheAudioDb.com, MusicBrainz, last.fm, ir allmusic.com, ir atsiunÄia meno kÅ«rinius iÅ¡: fanart.tv, htbackdrops.com, last.fm ir allmusic.com. Jis gali bÅ«ti nustatyti lauko srityje, kurioje svetainÄ—je norite, kad konkreÄiu atveju pradinÄ— informacijos pradinis paieÅ¡ka visada bus atlikta remiantis MusicBrainz. Allmusic nuoroda įdÄ—ta į MusicBrainz vietoje laukų allmusic.com negali bÅ«ti (nors tas trÅ«kstamas grandis labai lengva įtraukti).</description> <description lang="mk">This scraper collects information from the following supported sites: TheAudioDb.com, MusicBrainz, last.fm, and allmusic.com, while grabs artwork from: fanart.tv, htbackdrops.com, last.fm and allmusic.com. It can be set field by field that from which site you want that specific information. The initial search is always done on MusicBrainz. In case allmusic link is not added on the MusicBrainz site fields from allmusic.com cannot be fetched (very easy to add those missing links though).</description> <description lang="nl">Deze scraper verzamelt informatie van de volgende ondersteunde websites: TheAudioDb.com, MusicBrainz, last.fm, en allmusic.com en tevens pakt hij afbeeldingen van fanart.tv, htbackdrops.com, last.fm en allmusic.com. Het is mogelijk om per veld aan te geven van welke website je de specifieke informatie wil halen. De initiële zoekopdracht wordt altijd uitgevoerd op MusicBrainz. Wanneer de allmusic link niet is toegevoegd in de juiste velden op de MusicBrainz website kan de informatie van allmusic.com niet worden opgehaald. (Het is erg makkelijk om deze ontbrekende links toe te voegen.)</description> + <description lang="no">Denne skraperen samler informasjon fra følgende støttede steder: TheAudioDb.com, MusicBrainz, last.fm og allmusic.com, mens den henter artwork fra: fanart.tv, htbackdrops.com, last.fm og allmusic.com. Du kan stegvis velge hvilken kilde du ønsker og hente spesifikk informasjon fra. Det første søket er alltid gjort hos MusicBrainz. I tilfeller hvor allmusic-linker ikke er lagt til hos MusicBrainz-siden, kan ikke felter fra allmusic.com hentes (det er veldig lett Ã¥ legge til de manglende linkene).</description> <description lang="pl">Ten scraper zbiera informacje z nastÄ™pujÄ…cych stron: TheAudioDb.com, MusicBrainz, last.fm, and allmusic.com, a grafiki pobiera z: </description> <description lang="pt">Este scraper recolhe informações dos seguintes sÃtios: TheAudioDb.com, MusicBrainz, last.fm e allmusic.com, enquanto obtém artwork de: fanart.tv, htbackdrops.com, last.fm e allmusic.com. Pode definir em cada campo o sÃtio de onde quer obter as informações.⎠⎠A pesquisa inicial é sempre feita no MusicBrainz. Caso uma ligação allmusic não tenha sido adicionada no sÃtio MusicBrainz, os campos do allmusic.com não serão obtidos (no entanto, é muito fácil adicionar os links em falta).</description> <description lang="pt_BR">Este scraper coleta informações nos seguintes sites: MusicBrainz, last.fm, allmusic.com e amazon.de, enquanto pega os artwork de: fanart.tv, last.fm and allmusic.com. O Mesmo pode ser configurara campo a campo em que site você quer obter informações especÃficas. A procura inicial é sempre feita no MusicBrainz. No caso allmusic e/ou amazon.de não terem sido adicionados no site MusicBrainz, campos de allmusic.com e/ou amazona.de não serão buscados (embora seja muito fácil adicionar os links faltantes). </description> @@ -79,7 +92,10 @@ <description lang="sk">Tento zdroj zÃskavania dát zbiera infomácie z nasledujúcich podporovaných stránok: TheAudioDb.com, MusicBrainz, last.fm a allmusic.com. Grafiku zÃskava zo stránok: fanart.tv, htbackdrops.com, last.fm a allmusic.com. Je možné podrobne nastaviÅ¥, z ktorej stránky chcete zÃskaÅ¥ konkrétne informácie. PoÄiatoÄné hľadanie je vždy na stránke MusicBrainz. V prÃpade, že odkaz pre allmusic nie je pridaný na stránku MusicBrainz, nie je možné zÃskaÅ¥ údaje zo stránky allmusic.com (je ale veľmi jednoduché tieto chýbajúce odkazy pridaÅ¥).</description> <description lang="sl">Ta ponudnik združuje informacije s sledeÄih strani: TheAudioDb.com, MusicBrainz, last.fm in allmusic.com; grafike prenaÅ¡a z: fanart.tv, htbackdrops.com, last.fm in allmusic.com. Vsako informacijo lahko prenesete z razliÄne strani. ZaÄeno iskanje je vedn na MusicBrainz. V primeru, da na MusicBrainz ni povezave do allmusic.com, informacij od tam ne morete prenesti (a to težavo hitro lahko odpravite).</description> <description lang="sv">Denna skrapa samlar information frÃ¥n följande sajter: TheAudioDb.com, MusicBrainz, last.fm och allmusic.com, medans den samlar konstverk frÃ¥n: fanart.tv, htbackdrops.com, last.fm och allmusic.com. Du kan ange fält för fält frÃ¥n vilken sajt du vill ha den specifika inforamtionen frÃ¥n. Den initiala sökningen är alltid gjord pÃ¥ MusicBrainz. Om inte allmusic.com länken läggs till pÃ¥ MusicBrainz sajten, kan inte fält frÃ¥n allmusic.com hämtas (väldigt enkelt att lägga till dom saknade länkarna dock).</description> + <description lang="ta_IN">இநà¯à®¤ சà¯à®°à®£à¯à®Ÿà®¿à®¯à®¾à®©à®¤à¯ TheAudioDb.com, MusicBrainz, last.fm, allmusic.com ஆகிய இணையதளதà¯à®¤à®¿à®²à¯ இரà¯à®¨à¯à®¤à¯ தகவலà¯à®•à®³à¯ˆ சேகரிகà¯à®•à¯à®®à¯. திரை கà¯à®±à¯à®®à¯à®ªà®Ÿà®™à¯à®•à®³à¯ˆ fanart.tv, htbackdrops.com, last.fm மறà¯à®±à¯à®®à¯ allmusic.com ஆகிய இணையதளதà¯à®¤à®¿à®²à¯ இரà¯à®¨à¯à®¤à¯ தகவலà¯à®•à®³à¯ˆ சேகரிகà¯à®•à¯à®®à¯. ⎠⎠மà¯à®¤à®©à¯à®®à¯ˆ தேடல௠எபà¯à®ªà¯‹à®¤à¯à®®à¯ MusicBrainz தான௠நடகà¯à®•à¯à®®à¯. allmusic மறà¯à®±à¯à®®à¯ amazon.de சேரà¯à®•à¯à®•à®ªà®Ÿà®¾à®µà®¿à®Ÿà¯à®Ÿà®¾à®²à¯ அவறà¯à®±à®¿à®²à¯ இரà¯à®¨à¯à®¤à¯ தகவலà¯à®•à®³à¯ செமிகà¯à®•à®ªà®Ÿà®®à®¾à®Ÿà¯à®Ÿà®¤à¯ (தவறிய இணைபà¯à®ªà¯à®•à®³à¯ˆ சேரà¯à®ªà¯à®ªà®¤à¯ மிகவà¯à®®à¯ எளிதà¯).</description> + <description lang="vi">Trình nà y thu tháºp thông tin từ những site được há»— trợ nhÆ°: TheAudioDb.com, MusicBrainz, last.fm, allmusic.com, và lấy ảnh bìa từ các nguồn: fanart.tv, htbackdrops.com, last.fm và allmusic.com. Bạn có thể tùy chỉnh chá»n từng thứ riêng biệt để lấy từ site bạn muốn.\n \n Lần tìm kiếm đầu tiên luôn luôn được sá» dụng từ MusicBrainz. Trong trÆ°á»ng hợp các link allmusic không có trên MusicBrainz, các trÆ°á»ng từ allmusic.com sẽ không thể lấy vỠđược (tuy nhiên rất dá»… để tá»± thêm và o các link nà y bằng tay).</description> <description lang="zh">本刮削器支æŒä»Žä»¥ä¸‹ç½‘站获å–ä¿¡æ¯ï¼šTheAudioDb.comã€MusicBrainzã€last.fmå’Œallmusic.com,并从以下网站获å–艺术图片:fanart.tvã€htbackdrops.comã€last.fmå’Œallmusic.comã€‚ä½ å¯ä»¥æŒ‡å®šæ¯ä¸€é¡¹å†…容的æ¥æºç½‘站。 åˆå§‹ç»“果总是先从MusicBrainz获å–,如果MusicBrainzç½‘ç«™æœªåŠ å…¥åˆ°allmusicçš„å¤–éƒ¨é“¾æŽ¥ï¼Œåˆ™æ— æ³•èŽ·å–allmusic.comçš„ä¿¡æ¯ï¼ˆå½“ç„¶ä½ èƒ½å¾ˆå®¹æ˜“åœ°åŠ å…¥ç¼ºå¤±çš„é“¾æŽ¥ï¼‰ã€‚</description> + <description lang="zh_TW">本æœåˆ®å™¨æ”¯æ´å¾žä»¥ä¸‹ç¶²ç«™å–得資訊:TheAudioDb.comã€MusicBrainzã€last.fmå’Œallmusic.com,並從以下網站å–得專輯圖片:fanart.tvã€htbackdrops.comã€last.fmå’Œallmusic.com。您å¯ä»¥æŒ‡å®šæ¯ä¸€é …內容的來æºç¶²ç«™ã€‚ åˆå§‹æœå°‹çµæžœç¸½æ˜¯å…ˆå¾žMusicBrainzå–得,如果MusicBrainzç¶²ç«™æœªåŠ å…¥åˆ°allmusic的外部連çµï¼Œå‰‡ç„¡æ³•å–å¾—allmusic.com的資訊 (ç•¶ç„¶æ‚¨èƒ½å¾ˆè¼•æ˜“åœ°åŠ å…¥éºå¤±çš„連çµ)。</description> <platform>all</platform> </extension> </addon> diff --git a/addons/metadata.artists.universal/artistuniversal.xml b/addons/metadata.artists.universal/artistuniversal.xml index ea4c514351..8f303211e8 100644 --- a/addons/metadata.artists.universal/artistuniversal.xml +++ b/addons/metadata.artists.universal/artistuniversal.xml @@ -1,12 +1,18 @@ <?xml version="1.0" encoding="UTF-8"?> -<scraper framework="1.1" date="2012-05-28"> +<scraper framework="1.1" date="2013-02-27"> <NfoUrl dest="3"> - <RegExp input="$$1" output="<url>http://www.musicbrainz.org/ws/2/artist/\1?inc=url-rels</url>" dest="3"> + <RegExp input="$$1" output="<url>http://musicbrainz.org/ws/2/artist/\1?inc=url-rels</url>" dest="3"> <expression>http://musicbrainz.org/artist/(.+)</expression> </RegExp> </NfoUrl> + <ResolveIDToUrl dest="3"> + <RegExp input="$$1" output="<url>http://musicbrainz.org/ws/2/artist/\1?inc=url-rels</url>" dest="3"> + <expression>(.+)</expression> + </RegExp> + </ResolveIDToUrl> + <CreateArtistSearchUrl dest="3"> - <RegExp input="$$1" output="<url>http://search.musicbrainz.org/ws/2/artist/?fmt=xml&query=artist:$$4&limit=100</url>" dest="3"> + <RegExp input="$$1" output="<url>http://search.musicbrainz.org/ws/2/artist/?fmt=xml&query=artist:"$$4"&limit=100</url>" dest="3"> <RegExp input="$$1" output="\1" dest="4"> <expression noclean="1">(.+)</expression> </RegExp> @@ -20,11 +26,11 @@ </RegExp> </CreateArtistSearchUrl> <GetArtistSearchResults dest="8"> - <RegExp input="$$5" output="<results>\1</results>" dest="8"> - <RegExp input="$$1" output="<entity><title>\2</title><genre>\7</genre><url cache="mb-\1-artist.xml">http://www.musicbrainz.org/ws/2/artist/\1?inc=url-rels</url></entity>" dest="9"> + <RegExp input="$$5" output="<results sorted="yes">\1</results>" dest="8"> + <RegExp input="$$1" output="<entity><title>\2</title><genre>\7</genre><url cache="mb-\1-artist.xml">http://musicbrainz.org/ws/2/artist/\1?inc=url-rels</url></entity>" dest="9"> <expression repeat="yes" noclean="1">artist id="([^"]*)"(?:\stype="[^"]*")* ext:score="[^"]*"><name>([^<]*)</name>(<sort-name>[^<]*</sort-name>)?(<gender>[^<]*</gender>)?(<country>[^<]*</country>)?(<disambiguation>([^<]*))?</expression> </RegExp> - <RegExp input="$$1" output="<entity><title>\2</title><genre>\7</genre><url cache="mb-\1-artist.xml">http://www.musicbrainz.org/ws/2/artist/\1?inc=url-rels</url></entity>" dest="9"> + <RegExp input="$$1" output="<entity><title>\2</title><genre>\7</genre><url cache="mb-\1-artist.xml">http://musicbrainz.org/ws/2/artist/\1?inc=url-rels</url></entity>" dest="9"> <expression repeat="yes" noclean="1">artist ext:score="[^"]*"(?:\stype="[^"]*")* id="([^"]*)"><name>([^<]*)</name>(<sort-name>[^<]*</sort-name>)?(<gender>[^<]*</gender>)?(<country>[^<]*</country>)?(<disambiguation>([^<]*))?</expression> </RegExp> <RegExp input="$$9" output="\1" dest="5"> @@ -41,10 +47,10 @@ </RegExp> <!--AMGID - Artist--> <RegExp input="$$1" output="\2" dest="9"> - <expression noclean="1">><relation type="allmusic"><target>http://(www.)?allmusic.com/artist/([^<]*)</expression> + <expression noclean="1">>http://(www.)?allmusic.com/artist/([^<]*)</expression> </RegExp> - <RegExp input="$$1" output="<name>\1</name>" dest="5"> - <expression noclean="1"><artist(?:\stype="[^"]*")* id="[^"]*"><name>([^<]*)</expression> + <RegExp input="$$1" output="<musicBrainzArtistID>\1</musicBrainzArtistID><name>\2</name>" dest="5"> + <expression noclean="1"><artist(?:\stype="[^"]*")* id="([^"]*)"><name>([^<]*)</expression> </RegExp> <RegExp input="$$8" conditional="fanarttvthumbs" output="<chain function="GetFanartTvArtistThumbsByMBID">\1</chain>" dest="5+"> <expression/> @@ -94,6 +100,15 @@ <RegExp input="$INFO[biogsource]" output="<chain function="GetTADBBiographyByMBID">$$8</chain>" dest="5+"> <expression>TheAudioDb.com</expression> </RegExp> + <RegExp input="$INFO[genressource]" output="<chain function="GetTADBArtistGenresByMBID">$$8</chain>" dest="5+"> + <expression>TheAudioDb.com</expression> + </RegExp> + <RegExp input="$INFO[discogsource]" output="<chain function="GetTADBDiscographyByMBID">$$8</chain>" dest="5+"> + <expression>TheAudioDb.com</expression> + </RegExp> + <RegExp input="$INFO[lifespansource]" output="<chain function="GetTADBLifeSpanByMBID">$$8</chain>" dest="5+"> + <expression>TheAudioDb.com</expression> + </RegExp> <expression noclean="1"/> </RegExp> </GetArtistDetails> diff --git a/addons/metadata.artists.universal/changelog.txt b/addons/metadata.artists.universal/changelog.txt index e51222cb4d..34f7905b00 100644 --- a/addons/metadata.artists.universal/changelog.txt +++ b/addons/metadata.artists.universal/changelog.txt @@ -1,3 +1,25 @@ +[B]2.6.5[/B] +Updated language files from Transifex + +[B]2.6.4[/B] +Changed: tighten search query and trust musicbrainz results sorting + +[B]2.6.3[/B] +Fixed: AMGData + +[B]2.6.2[/B] +Added: option to fall back on artist life span from TheAudioDb.com + +[B]2.6.1[/B] +Disable last.fm options because last.fm is now truncating biogs + +[B]2.6.0[/B] +Added: option to fetch discography and artist life span from TheAudioDb.com + +[B]2.5.0[/B] +Added: option to select language from TheAudioDB.com +Added back the option to scrape from last.fm + [B]2.4.3[/B] Disable last.fm options because last.fm suspended XBMC's API account diff --git a/addons/metadata.artists.universal/resources/language/Amharic/strings.xml b/addons/metadata.artists.universal/resources/language/Amharic/strings.xml new file mode 100644 index 0000000000..f063fe1374 --- /dev/null +++ b/addons/metadata.artists.universal/resources/language/Amharic/strings.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Amharic language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/am/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30015">የመረጡት ቋንቋ </string> +</strings> diff --git a/addons/metadata.artists.universal/resources/language/Arabic/strings.xml b/addons/metadata.artists.universal/resources/language/Arabic/strings.xml new file mode 100644 index 0000000000..152d4894d4 --- /dev/null +++ b/addons/metadata.artists.universal/resources/language/Arabic/strings.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Arabic language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/ar/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">تمكين Ùان آرتس الÙنان من HTBackdrops.com</string> + <string id="30001">تمكين مصغرات الÙنان من allmusic.com</string> + <string id="30002">تمكين مصغرات الÙنان من last.fm</string> +</strings> diff --git a/addons/metadata.artists.universal/resources/language/Asturian/strings.xml b/addons/metadata.artists.universal/resources/language/Asturian/strings.xml new file mode 100644 index 0000000000..34f5f63ada --- /dev/null +++ b/addons/metadata.artists.universal/resources/language/Asturian/strings.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Asturian language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/ast/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30007">Imáxenes</string> + <string id="30015">Llingua preferida</string> +</strings> diff --git a/addons/metadata.artists.universal/resources/language/Burmese/strings.xml b/addons/metadata.artists.universal/resources/language/Burmese/strings.xml new file mode 100644 index 0000000000..57e4b67bab --- /dev/null +++ b/addons/metadata.artists.universal/resources/language/Burmese/strings.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Burmese language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/my/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">HTBackdrops.com မှ Artist Fanarts ကá€á€¯á€–ွင့်ထားမည်</string> + <string id="30001">allmusic.com မှ အနုပညာရှင် Thumbs ကá€á€¯á€–ွင့်မည်</string> + <string id="30002">last.fm မှ အနုပညာရှင် Thumbs ကá€á€¯á€–ွင့်မည်</string> + <string id="30003">HTBackdrops.com မှ အနုပညာရှင် Thumbs ကá€á€¯á€–ွင့်မည်</string> + <string id="30004">fanart.tv မှArtist Fanarts ကá€á€¯á€–ွင့်ထားမည်</string> + <string id="30005">fanart.tv မှ အနုပညာရှင် Thumbs ကá€á€¯á€–ွင့်မည်</string> + <string id="30006">အနုပညာရှင် အá€á€¹á€‘ုပá€á€¹á€á€á€€á€á€¯á€›á€šá€°á€›á€”်</string> + <string id="30007">အနုပညာလက်ရာ</string> + <string id="30010">အနုပညာရှင်စá€á€á€¯á€„်များရယူရန်</string> + <string id="30015">သင့်လျှော်သော ဘာသာစကား</string> + <string id="30022">theaudiodb.com မှ အနုပညာရှင် Thumb များဖွင့်ထားမည်</string> + <string id="30023">theaudiodb.com မှ Artist Fanarts ကá€á€¯á€–ွင့်ထားမည်</string> +</strings> diff --git a/addons/metadata.artists.universal/resources/language/Chinese (Traditional)/strings.xml b/addons/metadata.artists.universal/resources/language/Chinese (Traditional)/strings.xml new file mode 100644 index 0000000000..d38b611fb2 --- /dev/null +++ b/addons/metadata.artists.universal/resources/language/Chinese (Traditional)/strings.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Chinese (Traditional) language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/zh_TW/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">啟用HTBackdrops.com演出者資訊</string> + <string id="30001">啟用allmusic.com演出者縮圖</string> + <string id="30002">啟用last.fm演出者縮圖</string> + <string id="30003">啟用HTBackdrops.com演出者縮圖</string> + <string id="30004">啟用fanart.tv演出者資料庫</string> + <string id="30005">啟用 fanart.tv演出者縮圖</string> + <string id="30006">演出者簡介å–å¾—æ–¼</string> + <string id="30007">圖片</string> + <string id="30008">演出者專輯目錄å–å¾—æ–¼</string> + <string id="30009">演出者類型å–å¾—æ–¼</string> + <string id="30010">æ¼”å‡ºè€…é¢¨æ ¼å–å¾—æ–¼</string> + <string id="30011">演出者生日資訊å–å¾—æ–¼</string> + <string id="30012">演出者æ„境å–å¾—æ–¼</string> + <string id="30014">演出者活èºçš„年代å–å¾—æ–¼</string> + <string id="30015">å好的語言</string> + <string id="30016">å‚™é¸æ¼”出者簡介å–å¾—æ–¼</string> + <string id="30017">å‚™é¸æ¼”出者專輯目錄å–å¾—æ–¼</string> + <string id="30018">å‚™é¸æ¼”出者類型å–å¾—æ–¼</string> + <string id="30019">å‚™é¸æ¼”å‡ºè€…é¢¨æ ¼å–å¾—æ–¼</string> + <string id="30020">å‚™é¸æ¼”出者生日資訊å–å¾—æ–¼</string> + <string id="30021">å‚™é¸</string> + <string id="30022">啟用theaudiaodb.com演出者縮圖</string> + <string id="30023">啟用theaudiaodb.com演出者專輯資訊</string> +</strings> diff --git a/addons/metadata.artists.universal/resources/language/Croatian/strings.xml b/addons/metadata.artists.universal/resources/language/Croatian/strings.xml new file mode 100644 index 0000000000..171099c700 --- /dev/null +++ b/addons/metadata.artists.universal/resources/language/Croatian/strings.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Croatian language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/hr/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30004">Omogućite Fanart-s iz fanart.tv</string> + <string id="30005">Omogućite Umjetnine iz fanart.tv</string> + <string id="30023">Omogućiti Artist Fanarts iz theaudiodb.com</string> +</strings> diff --git a/addons/metadata.artists.universal/resources/language/Estonian/strings.xml b/addons/metadata.artists.universal/resources/language/Estonian/strings.xml index 94c3a943e3..1397a59256 100644 --- a/addons/metadata.artists.universal/resources/language/Estonian/strings.xml +++ b/addons/metadata.artists.universal/resources/language/Estonian/strings.xml @@ -4,5 +4,18 @@ <!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> <strings> + <string id="30000">Võimalda HTBackdrops.com artisti fännikunst</string> + <string id="30001">Võimalda allmusic.com artisti pisipildid</string> + <string id="30002">Võimalda last.fm artisti pisipildid</string> + <string id="30003">Võimalda HTBackdrops.com artisti pisipildid</string> + <string id="30004">Võimalda fanart.tv artisti fännikunst</string> + <string id="30005">Võimalda fanart.tv artisti pisipildid</string> + <string id="30006">Hangi artisti elulugu</string> <string id="30007">Kunst</string> + <string id="30008">Hangi artisti diskograafia</string> + <string id="30009">Hangi artisti žanr</string> + <string id="30010">Hangi artisti stiilid</string> + <string id="30015">Eelistatud keel</string> + <string id="30022">Hangi artistide pisipildid theaudiodb.com-st</string> + <string id="30023">Võimalda theaudiodb.com artisti fännikunst</string> </strings> diff --git a/addons/metadata.artists.universal/resources/language/Icelandic/strings.xml b/addons/metadata.artists.universal/resources/language/Icelandic/strings.xml index 28eb80690e..2cf66fb81e 100644 --- a/addons/metadata.artists.universal/resources/language/Icelandic/strings.xml +++ b/addons/metadata.artists.universal/resources/language/Icelandic/strings.xml @@ -5,4 +5,5 @@ <strings> <string id="30007">Myndskreytingar</string> + <string id="30021">Til vara</string> </strings> diff --git a/addons/metadata.artists.universal/resources/language/Korean/strings.xml b/addons/metadata.artists.universal/resources/language/Korean/strings.xml index b63ab4ebc0..46936682fb 100644 --- a/addons/metadata.artists.universal/resources/language/Korean/strings.xml +++ b/addons/metadata.artists.universal/resources/language/Korean/strings.xml @@ -15,7 +15,7 @@ <string id="30008">아티스트 디스코그래피 ê°€ì ¸ì˜¤ê¸°</string> <string id="30009">아티스트 장르 ê°€ì ¸ì˜¤ê¸°</string> <string id="30010">아티스트 ìŠ¤íƒ€ì¼ ê°€ì ¸ì˜¤ê¸°</string> - <string id="30011">아티스트 수명 ê°€ì ¸ì˜¤ê¸°</string> + <string id="30011">아티스트 ìƒëª° ê°€ì ¸ì˜¤ê¸°</string> <string id="30012">아티스트 분위기 ê°€ì ¸ì˜¤ê¸°</string> <string id="30014">아티스트 í™œë™ ê¸°ê°„ ê°€ì ¸ì˜¤ê¸°</string> <string id="30015">ì„ í˜¸ 언어</string> @@ -23,7 +23,7 @@ <string id="30017">아티스트 디스코그래피 ê°€ì ¸ì˜¤ê¸° 대체</string> <string id="30018">아티스트 장르 ê°€ì ¸ì˜¤ê¸° 대체</string> <string id="30019">아티스트 ìŠ¤íƒ€ì¼ ê°€ì ¸ì˜¤ê¸° 대체</string> - <string id="30020">아티스트 수명 ê°€ì ¸ì˜¤ê¸° 대체</string> + <string id="30020">아티스트 ìƒëª° ê°€ì ¸ì˜¤ê¸° 대체</string> <string id="30021">대체</string> <string id="30022">theaudiodb.com ì—ì„œ 아티스트 미리보기 ê°€ì ¸ì˜¤ê¸°</string> <string id="30023">theaudiodb.com ì—ì„œ 아티스트 팬아트 ê°€ì ¸ì˜¤ê¸°</string> diff --git a/addons/metadata.artists.universal/resources/language/Norwegian/strings.xml b/addons/metadata.artists.universal/resources/language/Norwegian/strings.xml index 6cc07bc1ce..0981e082ac 100644 --- a/addons/metadata.artists.universal/resources/language/Norwegian/strings.xml +++ b/addons/metadata.artists.universal/resources/language/Norwegian/strings.xml @@ -4,6 +4,27 @@ <!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> <strings> + <string id="30000">Aktiv artist-fanart fra HTBackdrops.com</string> + <string id="30001">Aktiver Artist Thumbs fra allmusic.com</string> + <string id="30002">Aktiver Artist Thumbs fra last.fm</string> + <string id="30003">Aktiver Artist Thumbs fra HTBackdrops.com</string> + <string id="30004">Aktiver Artist Fanarts fra fanart.tv</string> + <string id="30005">Aktiv artist-forhÃ¥ndsvisninger fra fanart.tv</string> + <string id="30006">Hent artistbiografi fra</string> <string id="30007">Artwork</string> - <string id="30015">Foretrukket SprÃ¥k</string> + <string id="30008">Hent artist-diskografi fra</string> + <string id="30009">Hent artistsjangere fra</string> + <string id="30010">Hent artiststiler fra</string> + <string id="30011">Hent artistlevetid fra</string> + <string id="30012">Hent artisthumør fra</string> + <string id="30014">Hent artistens aktive Ã¥r fra</string> + <string id="30015">Foretrukket sprÃ¥k</string> + <string id="30016">Fall tilbake til artistbiografi fra</string> + <string id="30017">Fall tilbake til artist-diskografi fra</string> + <string id="30018">Fall tilbake til artistsjangere fra</string> + <string id="30019">Fall tilbake til artiststiler fra</string> + <string id="30020">Fall tilbake til artistlevetid fra</string> + <string id="30021">Tilbakefallinger</string> + <string id="30022">Aktiver artist-forhÃ¥ndsvisning fra theaudiodb.com</string> + <string id="30023">Aktiver artist-fanart fra theaudiodb.com</string> </strings> diff --git a/addons/metadata.artists.universal/resources/language/Tamil (India)/strings.xml b/addons/metadata.artists.universal/resources/language/Tamil (India)/strings.xml new file mode 100644 index 0000000000..89bc8a780a --- /dev/null +++ b/addons/metadata.artists.universal/resources/language/Tamil (India)/strings.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Tamil (India) language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/ta_IN/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">HTBackdrops.com இரà¯à®¨à¯à®¤à¯ கலைஞர௠விசிறிபடஙà¯à®•à®³à¯ˆ செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯</string> + <string id="30001">allmusic.com இரà¯à®¨à¯à®¤à¯ கலைஞர௠கà¯à®±à¯à®®à¯à®ªà®Ÿà®®à¯à®•à®³à¯ˆ செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯</string> + <string id="30002">last.fm இரà¯à®¨à¯à®¤à¯ கலைஞர௠கà¯à®±à¯à®®à¯à®ªà®Ÿà®®à¯à®•à®³à¯ˆ செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯</string> + <string id="30003">HTBackdrops.com இரà¯à®¨à¯à®¤à¯ கலைஞர௠கà¯à®±à¯à®®à¯à®ªà®Ÿà®®à¯à®•à®³à¯ˆ செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯</string> + <string id="30004">Fanart.tv இரà¯à®¨à¯à®¤à¯ கலைஞர௠விசிறிபடஙà¯à®•à®³à¯ˆ செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯</string> + <string id="30005">Fanart.tv இரà¯à®¨à¯à®¤à¯ கலைஞர௠கà¯à®±à¯à®®à¯à®ªà®Ÿà®®à¯à®•à®³à¯ˆ செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯</string> + <string id="30006">கலைஞர௠வாழà¯à®•à¯à®•à¯ˆ வரலாற௠கைபà¯à®ªà®±à¯à®±à¯</string> + <string id="30007">கà¯à®±à¯à®ªà¯à®ªà®Ÿà®®à¯</string> + <string id="30008">கலைஞர௠டிஸà¯à®•à¯‡à®¾à®•à®¿à®°à®¾à®ªà®¿ கைபà¯à®ªà®±à¯à®±à¯</string> + <string id="30009">கலைஞர௠வகைகள௠கைபà¯à®ªà®±à¯à®±à¯</string> + <string id="30010">கலைஞர௠பாணிகள௠கைபà¯à®ªà®±à¯à®±à¯</string> + <string id="30011">கலைஞர௠ஆயà¯à®³à¯ கைபà¯à®ªà®±à¯à®±à¯</string> + <string id="30012">கலைஞர௠மனநிலை கைபà¯à®ªà®±à¯à®±à¯</string> + <string id="30014">கலைஞர௠எநà¯à®¤ ஆணà¯à®Ÿà¯ à®®à¯à®¤à®²à¯ நடிகà¯à®• தà¯à®µà®™à¯à®•à®¿à®¯à®¤à¯ˆ கைபà¯à®ªà®±à¯à®±à¯</string> + <string id="30015">விரà¯à®®à¯à®ªà®¿à®¯ மொழி</string> + <string id="30016">கலைஞர௠வாழà¯à®•à¯à®•à¯ˆ வரலாற௠இதறà¯à®•à¯à®•à¯ பினà¯à®¤à®³à¯à®³à¯</string> + <string id="30017">கலைஞர௠டிஸà¯à®•à¯‡à®¾à®•à®¿à®°à®¾à®ªà®¿ இதறà¯à®•à¯à®•à¯ பினà¯à®¤à®³à¯à®³à¯</string> + <string id="30018">கலைஞர௠வகைகள௠இதறà¯à®•à¯à®•à¯ பினà¯à®¤à®³à¯à®³à¯</string> + <string id="30019">கலைஞர௠பாணிகள௠இதறà¯à®•à¯à®•à¯ பினà¯à®¤à®³à¯à®³à¯</string> + <string id="30020">கலைஞர௠ஆயà¯à®³à¯ இதறà¯à®•à¯à®•à¯ பினà¯à®¤à®³à¯à®³à¯</string> + <string id="30021">பினà¯à®¤à®³à¯à®³à¯</string> + <string id="30022">theaudiodb.com இரà¯à®¨à¯à®¤à¯ கலைஞர௠கà¯à®±à¯à®®à¯à®ªà®Ÿà®®à¯à®•à®³à¯ˆ செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯</string> + <string id="30023">theaudiodb.com இரà¯à®¨à¯à®¤à¯ கலைஞர௠விசிறிபடஙà¯à®•à®³à¯ˆ செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯</string> +</strings> diff --git a/addons/metadata.artists.universal/resources/language/Turkish/strings.xml b/addons/metadata.artists.universal/resources/language/Turkish/strings.xml new file mode 100644 index 0000000000..258edb0a48 --- /dev/null +++ b/addons/metadata.artists.universal/resources/language/Turkish/strings.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Turkish language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/tr/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30007">Çizim</string> + <string id="30015">Tercih Edilen Dil</string> +</strings> diff --git a/addons/metadata.artists.universal/resources/language/Ukrainian/strings.xml b/addons/metadata.artists.universal/resources/language/Ukrainian/strings.xml new file mode 100644 index 0000000000..b1de3c2231 --- /dev/null +++ b/addons/metadata.artists.universal/resources/language/Ukrainian/strings.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Ukrainian language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/uk/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30004">Отримати обкладинки Ð²Ð¸ÐºÐ¾Ð½Ð°Ð²Ñ†Ñ Ð· fanart.tv</string> + <string id="30005">Включити малюнки Ð²Ð¸ÐºÐ¾Ð½Ð°Ð²Ñ†Ñ Ð· fanart.tv</string> + <string id="30006">Отримати біографію Ð²Ð¸ÐºÐ¾Ð½Ð°Ð²Ñ†Ñ Ð·</string> + <string id="30007">Обкладинка</string> + <string id="30008">Отримати диÑкографію Ð²Ð¸ÐºÐ¾Ð½Ð°Ð²Ñ†Ñ Ð·</string> + <string id="30009">Отримати жанри Ð²Ð¸ÐºÐ¾Ð½Ð°Ð²Ñ†Ñ Ð·</string> + <string id="30010">Отримати Ñтилі Ð²Ð¸ÐºÐ¾Ð½Ð°Ð²Ñ†Ñ Ð·</string> + <string id="30012">Отримати наÑтрої Ð²Ð¸ÐºÐ¾Ð½Ð°Ð²Ñ†Ñ Ð·</string> + <string id="30014">Отримати роки активноÑÑ‚Ñ– Ð²Ð¸ÐºÐ¾Ð½Ð°Ð²Ñ†Ñ Ð·</string> + <string id="30015">Улюблена мова</string> +</strings> diff --git a/addons/metadata.artists.universal/resources/language/Vietnamese/strings.xml b/addons/metadata.artists.universal/resources/language/Vietnamese/strings.xml new file mode 100644 index 0000000000..308024fbe0 --- /dev/null +++ b/addons/metadata.artists.universal/resources/language/Vietnamese/strings.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Vietnamese language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/vi/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">Lấy Fanart từ nguồn HTBackdrops.com</string> + <string id="30001">Lấy hình đại diện từ nguồn allmusic.com</string> + <string id="30002">Lấy hình đại diện từ nguồn last.fm</string> + <string id="30003">Lấy hình đại diện cho nghệ sÄ© từ nguồn HTBackdrops.com</string> + <string id="30004">Sá» dụng Fanart từ fanart.tv</string> + <string id="30005">Lấy hình đại diện từ nguồn fanart.tv</string> + <string id="30006">Lấy tiểu sá» nghệ sÄ© từ</string> + <string id="30007">Ảnh bìa</string> + <string id="30008">Lấy quá trình nghệ thuáºt cho nghệ sÄ© từ</string> + <string id="30009">Lấy thể loại nhạc cho nghệ sÄ© từ</string> + <string id="30010">Lấy phong cách nhạc cho nghệ sÄ© từ</string> + <string id="30011">Lấy tuổi Ä‘á»i nghệ sÄ© từ</string> + <string id="30012">Lấy tÃnh miêu tả âm nhạc từ</string> + <string id="30014">Lấy năm hoạt Ä‘á»™ng nhạc cho nghệ sÄ© từ</string> + <string id="30015">Ưu tiên ngôn ngữ</string> + <string id="30016">Dá»± trữ tiểu sá» từ</string> + <string id="30017">Dá»± trữ quá trình nghệ thuáºt nhạc từ</string> + <string id="30018">Dá»± trữ thể loại nhạc từ</string> + <string id="30019">Dá»± trữ phong cách nhạc từ</string> + <string id="30020">Dá»± trữ tuổi Ä‘á»i từ</string> + <string id="30021">Dá»± trữ</string> + <string id="30022">Lấy hình đại diện từ nguồn theaudiodb.com</string> + <string id="30023">Lấy hình Fanart từ nguồn theaudiodb.com</string> +</strings> diff --git a/addons/metadata.artists.universal/resources/language/Welsh/strings.xml b/addons/metadata.artists.universal/resources/language/Welsh/strings.xml new file mode 100644 index 0000000000..e34aa58e2f --- /dev/null +++ b/addons/metadata.artists.universal/resources/language/Welsh/strings.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Welsh language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/cy/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">Galluogi celf artisiaid o HTBackdrops.com</string> + <string id="30001">Galluogi lluniau bach artistiaid o allmusic.com</string> + <string id="30002">Galluogi lluniau bach artistiaid o last.fm</string> + <string id="30003">Galluogi lluniau bach artistiaid o HTBackdrops.com</string> + <string id="30004">Galluogi celf artistiaid o fanart.tv</string> + <string id="30005">Galluogi lluniau bach artistiaid o fanart.tv</string> + <string id="30006">Estyn bywgraffiad artist o</string> + <string id="30007">Gwaith Celf</string> + <string id="30008">Estyn disgograffeg artist o</string> + <string id="30009">Estyn Genres Artistiaid o</string> + <string id="30010">Estyn Arddulliau Artistiaid o</string> + <string id="30011">Estyn Hyd Oes Artistiaid o</string> + <string id="30012">Estyn Naws Artistiaid o</string> + <string id="30014">Estyn Blynyddoedd Cynhyrchiol Artistiaid o</string> + <string id="30015">Dewis Iaith</string> + <string id="30016">Camu nol Bywgraffiad Artist o</string> + <string id="30017">Cammu nol i Ddisgograffeg Artist o</string> + <string id="30018">Cammu nol i Genres Artistiaid o</string> + <string id="30019">Cammu nol i Arddulliau Artistiaid o</string> + <string id="30020">Cammu nol i Hyd Oes Artisitiaid o</string> + <string id="30021">Cammu nol</string> + <string id="30022">Galluogi lluniau bach artistiaid o theaudiodb.com</string> + <string id="30023">Galluogi Celf Artistiaid o theaudiodb.com</string> +</strings> diff --git a/addons/metadata.artists.universal/resources/settings.xml b/addons/metadata.artists.universal/resources/settings.xml index 5030489b18..434725a8d8 100644 --- a/addons/metadata.artists.universal/resources/settings.xml +++ b/addons/metadata.artists.universal/resources/settings.xml @@ -2,23 +2,26 @@ <settings> <category label="128"> <setting label="30006" type="labelenum" values="TheAudioDb.com|None" id="biogsource" default="TheAudioDb.com"/> + <setting label="30015" type="labelenum" values="en|de|es|fr|it|cn|jp|ru|pt|se|nl|hu" id="tadbartistlanguage" default="en" visible="eq(-1,0)"/> <setting type="sep"/> - <setting label="30008" type="labelenum" values="MusicBrainz|allmusic.com|None" id="discogsource" default="MusicBrainz"/> + <setting label="30008" type="labelenum" values="MusicBrainz|allmusic.com|TheAudioDb.com|None" id="discogsource" default="MusicBrainz"/> <setting type="sep"/> - <setting label="30009" type="labelenum" values="allmusic.com|None" id="genressource" default="allmusic.com"/> + <setting label="30011" type="labelenum" values="TheAudioDb.com|allmusic.com|MusicBrainz|None" id="lifespansource" default="TheAudioDb.com"/> + <setting label="30014" type="labelenum" values="allmusic.com|None" id="yearsasource" default="allmusic.com"/> + <setting type="sep"/> + <setting label="30009" type="labelenum" values="TheAudioDb.com|allmusic.com|None" id="genressource" default="TheAudioDb.com"/> <setting label="30010" type="labelenum" values="allmusic.com|None" id="stylessource" default="allmusic.com"/> - <setting label="30011" type="labelenum" values="allmusic.com|MusicBrainz|None" id="lifespansource" default="allmusic.com"/> <setting label="30012" type="labelenum" values="allmusic.com|None" id="moodssource" default="allmusic.com"/> - <setting label="30014" type="labelenum" values="allmusic.com|None" id="yearsasource" default="allmusic.com"/> </category> <category label="30021"> <setting label="30016" type="labelenum" values="TheAudioDb.com|None" id="biogfbsource" default="None"/> + <setting label="30015" type="labelenum" values="en|de|es|fr|it|cn|jp|ru|pt|se|nl|hu" id="tadbartistlanguage" default="en" visible="eq(-1,0)"/> + <setting type="sep"/> + <setting label="30020" type="labelenum" values="TheAudioDb.com|MusicBrainz|allmusic.com|None" id="lifespanfbsource" default="None"/> <setting type="sep"/> - <setting label="30017" type="labelenum" values="MusicBrainz|None" id="discogfbsource" default="None" visible="false"/> - <setting label="30018" type="labelenum" values="allmusic.com|None" id="genresfbsource" default="None"/> + <setting label="30018" type="labelenum" values="TheAudioDb.com|allmusic.com|None" id="genresfbsource" default="None"/> <setting label="30019" type="labelenum" values="allmusic.com|None" id="stylesfbsource" default="None"/> - <setting label="30020" type="labelenum" values="MusicBrainz|allmusic.com|None" id="lifespanfbsource" default="None"/> </category> <category label="30007"> @@ -26,6 +29,7 @@ <setting label="30005" type="bool" id="fanarttvthumbs" default="true"/> <setting label="30022" type="bool" id="tadbthumbs" default="true"/> <setting label="30003" type="bool" id="htbthumbs" default="true"/> + <setting label="30002" type="bool" id="lastfmartistthumbs" default="false"/> <setting label="30001" type="bool" id="allmusicartistthumbs" default="true"/> <setting type="lsep" label="Fanart Sources"/> <setting label="30004" type="bool" id="fanarttvfanart" default="true"/> diff --git a/addons/metadata.common.allmusic.com/addon.xml b/addons/metadata.common.allmusic.com/addon.xml index 68f2b21da7..750870ebbd 100644 --- a/addons/metadata.common.allmusic.com/addon.xml +++ b/addons/metadata.common.allmusic.com/addon.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon id="metadata.common.allmusic.com" name="AllMusic" - version="2.5.2" + version="2.6.0" provider-name="Team XBMC"> <requires> - <import addon="xbmc.metadata" version="1.0"/> + <import addon="xbmc.metadata" version="2.1.0"/> </requires> <extension point="xbmc.metadata.scraper.library" library="allmusic.xml"/> diff --git a/addons/metadata.common.allmusic.com/allmusic.xml b/addons/metadata.common.allmusic.com/allmusic.xml index edcd5081a9..51d57fbaf3 100644 --- a/addons/metadata.common.allmusic.com/allmusic.xml +++ b/addons/metadata.common.allmusic.com/allmusic.xml @@ -105,6 +105,9 @@ <RegExp input="$INFO[lifespanfbsource]" output="<chain function="GetMBFallbackLafeSpanByMBID">$$8</chain>" dest="12"> <expression>MusicBrainz</expression> </RegExp> + <RegExp input="$INFO[lifespanfbsource]" output="<chain function="GetTADBFallbackLifeSpanByMBID">$$8</chain>" dest="12"> + <expression>TheAudioDb.com</expression> + </RegExp> <expression>^$</expression> </RegExp> <RegExp input="$$11" output="$$11" dest="2"> @@ -180,6 +183,9 @@ <RegExp input="$INFO[genresfbsource]" output="<chain function="GetLastFMFallbackArtistGenresByMBID">$$8</chain>" dest="12"> <expression>last.fm</expression> </RegExp> + <RegExp input="$INFO[genresfbsource]" output="<chain function="GetTADBFallbackArtistGenresByMBID">$$8</chain>" dest="12"> + <expression>TheAudioDb.com</expression> + </RegExp> <expression><genre></genre></expression> </RegExp> <RegExp input="$$11" output="$$11" dest="2"> @@ -277,10 +283,10 @@ <RegExp input="" output="" dest="2"> <expression /> </RegExp> - <RegExp input="$$1" output="\1" dest="8"> + <RegExp input="$$1" output="\1" dest="10"> <expression noclean="1"><h4>artist moods</h4>(.*?)</ul></expression> </RegExp> - <RegExp input="$$8" output="<mood>\1</mood>" dest="2"> + <RegExp input="$$10" output="<mood>\1</mood>" dest="2"> <expression repeat="yes" noclean="1"><li>[^>]*>([^<]*)</a></li></expression> </RegExp> <expression noclean="1" /> diff --git a/addons/metadata.common.fanart.tv/addon.xml b/addons/metadata.common.fanart.tv/addon.xml index ef673f184d..b88455c675 100644 --- a/addons/metadata.common.fanart.tv/addon.xml +++ b/addons/metadata.common.fanart.tv/addon.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon id="metadata.common.fanart.tv" name="fanart.tv" - version="2.1.1" + version="2.1.2" provider-name="Team XBMC"> <requires> - <import addon="xbmc.metadata" version="1.0"/> + <import addon="xbmc.metadata" version="2.1.0"/> </requires> <extension point="xbmc.metadata.scraper.library" library="fanarttv.xml"/> diff --git a/addons/metadata.common.fanart.tv/fanarttv.xml b/addons/metadata.common.fanart.tv/fanarttv.xml index caff441454..09120f610f 100644 --- a/addons/metadata.common.fanart.tv/fanarttv.xml +++ b/addons/metadata.common.fanart.tv/fanarttv.xml @@ -39,7 +39,7 @@ <expression /> </RegExp> <RegExp input="$$1" output="\1" dest="16"> - <expression noclean="1">"artistbackground":\[(.*?)\],"</expression> + <expression noclean="1">"artistbackground":\[(.*?)\}\]</expression> </RegExp> <RegExp input="$$16" output="<thumb preview="\1/preview">\1</thumb>" dest="14"> <expression repeat="yes" noclean="1">"id":"\d*","url":"([^"]*)</expression> diff --git a/addons/metadata.common.hdtrailers.net/addon.xml b/addons/metadata.common.hdtrailers.net/addon.xml index 199d3a6da1..0a71e092de 100644 --- a/addons/metadata.common.hdtrailers.net/addon.xml +++ b/addons/metadata.common.hdtrailers.net/addon.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon id="metadata.common.hdtrailers.net" name="HD-Trailers common scraper functions" - version="1.0.8" + version="1.0.9" provider-name="Bence Nádas (olympia)"> <requires> - <import addon="xbmc.metadata" version="1.0"/> + <import addon="xbmc.metadata" version="2.1.0"/> </requires> <extension point="xbmc.metadata.scraper.library" library="hdtrailers.xml"/> diff --git a/addons/metadata.common.hdtrailers.net/hdtrailers.xml b/addons/metadata.common.hdtrailers.net/hdtrailers.xml index 98a179e115..485e72b4a3 100644 --- a/addons/metadata.common.hdtrailers.net/hdtrailers.xml +++ b/addons/metadata.common.hdtrailers.net/hdtrailers.xml @@ -27,10 +27,10 @@ <RegExp input="$$6" output="<details><trailer>\1</trailer></details>" dest="5"> <!--fetch 480p trailer link from hdtrailers.net--> <RegExp input="$$1" output="http://playlist.yahoo.com/makeplaylist.dll?sdm=web&pt=rd&sid=\2" dest="6"> - <expression noclean="1">">(Theatrical )?Trailer</td>.*?sid=(\d*)" rel="lightbox\[res480p</expression> + <expression noclean="1">">(Theatrical )?Trailer</span></td>.*?sid=(\d*)" rel="lightbox\[res480p</expression> </RegExp> <RegExp input="$$1" output="http://playlist.yahoo.com/makeplaylist.dll?sdm=web&pt=rd&sid=\2" dest="6+"> - <expression noclean="1">">(Teaser )?Trailer</td>.*?sid=(\d*)" rel="lightbox\[res480p</expression> + <expression noclean="1">">(Teaser )?Trailer</span></td>.*?sid=(\d*)" rel="lightbox\[res480p</expression> </RegExp> <expression noclean="1" /> </RegExp> @@ -39,17 +39,17 @@ <RegExp input="$$6" output="<details><trailer>\1</trailer></details>" dest="5"> <!--Fallback to fetch 480p trailer link if 720p is not available--> <RegExp input="$$1" output="http://playlist.yahoo.com/makeplaylist.dll?sdm=web&pt=rd&sid=\2" dest="6"> - <expression noclean="1">">(Theatrical )?Trailer</td>.*?sid=(\d*)" rel="lightbox\[res480p</expression> + <expression noclean="1">">(Theatrical )?Trailer</span></td>.*?sid=(\d*)" rel="lightbox\[res480p</expression> </RegExp> <RegExp input="$$1" output="http://playlist.yahoo.com/makeplaylist.dll?sdm=web&pt=rd&sid=\2" dest="6+"> - <expression noclean="1">">(Teaser )?Trailer</td>.*?sid=(\d*)" rel="lightbox\[res480p</expression> + <expression noclean="1">">(Teaser )?Trailer</span></td>.*?sid=(\d*)" rel="lightbox\[res480p</expression> </RegExp> <!--Fetch 720p trailer link from hdtrailers.net--> <RegExp input="$$1" output="http://playlist.yahoo.com/makeplaylist.dll?sdm=web&pt=rd&sid=\2" dest="6"> - <expression noclean="1">">(Theatrical )?Trailer</td>.*?sid=(\d*)" rel="lightbox\[res720p</expression> + <expression noclean="1">">(Theatrical )?Trailer</span></td>.*?sid=(\d*)" rel="lightbox\[res720p</expression> </RegExp> <RegExp input="$$1" output="http://playlist.yahoo.com/makeplaylist.dll?sdm=web&pt=rd&sid=\2" dest="6+"> - <expression noclean="1">">(Teaser )?Trailer</td>.*?sid=(\d*)" rel="lightbox\[res720p</expression> + <expression noclean="1">">(Teaser )?Trailer</span></td>.*?sid=(\d*)" rel="lightbox\[res720p</expression> </RegExp> <expression noclean="1" /> </RegExp> @@ -58,24 +58,24 @@ <RegExp input="$$6" output="<details><trailer>\1</trailer></details>" dest="5"> <!--Fallback to fetch 480p trailer link if 720p and 1080p are not available--> <RegExp input="$$1" output="http://playlist.yahoo.com/makeplaylist.dll?sdm=web&pt=rd&sid=\2" dest="6"> - <expression noclean="1">">(Theatrical )?Trailer</td>.*?sid=(\d*)" rel="lightbox\[res480p</expression> + <expression noclean="1">">(Theatrical )?Trailer</span></td>.*?sid=(\d*)" rel="lightbox\[res480p</expression> </RegExp> <RegExp input="$$1" output="http://playlist.yahoo.com/makeplaylist.dll?sdm=web&pt=rd&sid=\2" dest="6+"> - <expression noclean="1">">(Teaser )?Trailer</td>.*?sid=(\d*)" rel="lightbox\[res480p</expression> + <expression noclean="1">">(Teaser )?Trailer</span></td>.*?sid=(\d*)" rel="lightbox\[res480p</expression> </RegExp> <!--Fallback to fetch 720p trailer link if 1080p is not available--> <RegExp input="$$1" output="http://playlist.yahoo.com/makeplaylist.dll?sdm=web&pt=rd&sid=\2" dest="6"> - <expression noclean="1">">(Theatrical )?Trailer</td>.*?sid=(\d*)" rel="lightbox\[res720p</expression> + <expression noclean="1">">(Theatrical )?Trailer</span></td>.*?sid=(\d*)" rel="lightbox\[res720p</expression> </RegExp> <RegExp input="$$1" output="http://playlist.yahoo.com/makeplaylist.dll?sdm=web&pt=rd&sid=\2" dest="6+"> - <expression noclean="1">">(Teaser )?Trailer</td>.*?sid=(\d*)" rel="lightbox\[res720p</expression> + <expression noclean="1">">(Teaser )?Trailer</span></td>.*?sid=(\d*)" rel="lightbox\[res720p</expression> </RegExp> <!--Fetch 1080p trailer link from hdtrailers.net--> <RegExp input="$$1" output="http://playlist.yahoo.com/makeplaylist.dll?sdm=web&pt=rd&sid=\2" dest="6"> - <expression noclean="1">">(Theatrical )?Trailer</td>.*?sid=(\d*)" rel="lightbox\[res1080p</expression> + <expression noclean="1">">(Theatrical )?Trailer</span></td>.*?sid=(\d*)" rel="lightbox\[res1080p</expression> </RegExp> <RegExp input="$$1" output="http://playlist.yahoo.com/makeplaylist.dll?sdm=web&pt=rd&sid=\2" dest="6+"> - <expression noclean="1">">(Teaser )?Trailer</td>.*?sid=(\d*)" rel="lightbox\[res1080p</expression> + <expression noclean="1">">(Teaser )?Trailer</span></td>.*?sid=(\d*)" rel="lightbox\[res1080p</expression> </RegExp> <expression noclean="1" /> </RegExp> diff --git a/addons/metadata.common.imdb.com/addon.xml b/addons/metadata.common.imdb.com/addon.xml index 6bc71f8585..4658980204 100644 --- a/addons/metadata.common.imdb.com/addon.xml +++ b/addons/metadata.common.imdb.com/addon.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon id="metadata.common.imdb.com" - name="IMDB common scraper functions" - version="2.6.2" + name="IMDB Scraper Library" + version="2.7.6" provider-name="Team XBMC"> <requires> - <import addon="xbmc.metadata" version="1.0"/> + <import addon="xbmc.metadata" version="2.1.0"/> </requires> <extension point="xbmc.metadata.scraper.library" library="imdb.xml"/> diff --git a/addons/metadata.common.imdb.com/changelog.txt b/addons/metadata.common.imdb.com/changelog.txt index fc2a75779c..95d20ec2b6 100644 --- a/addons/metadata.common.imdb.com/changelog.txt +++ b/addons/metadata.common.imdb.com/changelog.txt @@ -1,3 +1,25 @@ +[B]2.7.6[/B] +- fixed: IMDb studio/director/writer after layout change + +[B]2.7.5[/B] +- fixed: OutlineToPlot function +- fixed: USACert + +[B]2.7.4[/B] +- fixed: MetaCritic Score + +[B]2.7.3[/B] +- fixed: orginal title won't scrape in some cases + +[B]2.7.2[/B] +- changed: make sure to parse the intended page + +[B]2.7.1[/B] +- fixed: IMDb genre after layout change + +[B]2.7.0[/B] +- fixed: IMDb scraping after layout changes + [B]2.6.2[/B] - fixed: director(s) and writer(s) scraping in case of IMDbFull is selected diff --git a/addons/metadata.common.imdb.com/imdb.xml b/addons/metadata.common.imdb.com/imdb.xml index 6c321bf66a..7d92f3647c 100644 --- a/addons/metadata.common.imdb.com/imdb.xml +++ b/addons/metadata.common.imdb.com/imdb.xml @@ -1,34 +1,34 @@ <scraperfunctions> <GetIMDBGenresById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBGenres">http://akas.imdb.com/title/$$1/</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBGenres">http://akas.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBGenresById> <ParseIMDBGenres dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="$$1" output="<genre>\1</genre>" dest="2"> - <expression repeat="yes">itemprop="genre"[^>]+>([^<]+)</a></expression> + <expression repeat="yes">tt_stry_gnr"\s>\s([^<]+)</expression> </RegExp> <expression noclean="1" /> </RegExp> </ParseIMDBGenres> <GetIMDBRatingById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBRating">http://akas.imdb.com/title/$$1/</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBRating">http://akas.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBRatingById> <ParseIMDBRating dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="$$1" output="<rating>\1</rating><votes>\2</votes>" dest="2"> - <expression><span itemprop="ratingValue">([0-9.]+).*?>.*?title="([0-9,]+)\s</expression> + <expression><span\sitemprop="ratingValue">([0-9.]+).*?>.*?title="([0-9,]+)\s</expression> </RegExp> <expression noclean="1" /> </RegExp> </ParseIMDBRating> <GetIMDBTOP250ById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBTOP250">http://akas.imdb.com/title/$$1/</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBTOP250">http://akas.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBTOP250ById> @@ -42,21 +42,21 @@ </ParseIMDBTOP250> <GetIMDBStudioById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBStudio">http://akas.imdb.com/title/$$1/</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBStudio">http://akas.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBStudioById> <ParseIMDBStudio dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="$$1" output="<studio>\1</studio>" dest="2"> - <expression>"/company/[^>]+>([^<]+)</a></expression> + <expression>"/company/[^>]+>[^<]*<[^>]*>([^<]+)</span></expression> </RegExp> <expression noclean="1" /> </RegExp> </ParseIMDBStudio> <GetIMDBCountryById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBCountry">http://akas.imdb.com/title/$$1/</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBCountry">http://akas.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBCountryById> @@ -70,35 +70,35 @@ </ParseIMDBCountry> <GetMetaCriticRatingById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseMetaCriticRating">http://akas.imdb.com/title/$$1/</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseMetaCriticRating">http://akas.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetMetaCriticRatingById> <ParseMetaCriticRating dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="$$1" output="<rating>\1.\2</rating>" dest="2"> - <expression><a href="criticreviews">(\d)(\d*)</expression> + <expression><a\shref="criticreviews[^"]*?"\stitle[^>]*?>\s(\d)(\d*)</expression> </RegExp> <expression noclean="1" /> </RegExp> </ParseMetaCriticRating> <GetIMDBPlotById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBPlot">http://akas.imdb.com/title/$$1/</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBPlot">http://akas.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBPlotById> <ParseIMDBPlot dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="$$1" output="<plot>\1</plot>" dest="2"> - <expression fixchars="1" trim="1"><h2>Storyline</h2>\n+<p>(.*?)<[^a/]</expression> + <expression fixchars="1" trim="1"><h2>Storyline</h2>\s+<div\sclass="inline\scanwrap"\sitemprop="description">\s+<p>(.*?)<[^a/]</expression> </RegExp> <expression noclean="1" /> </RegExp> </ParseIMDBPlot> <GetIMDBTaglineById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBTagline">http://akas.imdb.com/title/$$1/</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBTagline">http://akas.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBTaglineById> @@ -112,34 +112,48 @@ </ParseIMDBTagline> <GetIMDBOutlineById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBOutline">http://akas.imdb.com/title/$$1/</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBOutline">http://akas.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBOutlineById> <ParseIMDBOutline dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="$$1" output="<outline>\1</outline>" dest="2"> - <expression fixchars="1" trim="1"><p>\n?<p itemprop="description">([^<]+)</p></expression> + <expression fixchars="1" trim="1"></p>\n?\s+<p\sitemprop="description">([^<]+)</p></expression> </RegExp> <expression noclean="1" /> </RegExp> </ParseIMDBOutline> + <GetIMDBOutlineToPlotById dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBOutlineToPlot">http://akas.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> + <expression noclean="1" /> + </RegExp> + </GetIMDBOutlineToPlotById> + <ParseIMDBOutlineToPlot dest="5"> + <RegExp input="$$2" output="<details>\1</details>" dest="5"> + <RegExp input="$$1" output="<plot>\1</plot>" dest="2"> + <expression fixchars="1" trim="1"></p>\n?\s+<p\sitemprop="description">([^<]+)</p></expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </ParseIMDBOutlineToPlot> + <GetIMDBCastById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBCast">http://akas.imdb.com/title/$$1/</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBCast">http://akas.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBCastById> <ParseIMDBCast dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="$$1" output="\1" dest="6"> - <expression noclean="1"><table class="cast_list">(.*?)</table></expression> + <expression noclean="1"><table\sclass="cast_list">(.*?)</table></expression> </RegExp> - <RegExp input="$$6" output="<actor><thumb>\2_SX1024_SY1024_\3</thumb><name>\1</name><role>\5</role></actor>" dest="7"> - <expression repeat="yes" clear="yes" trim="3,4" noclean="1,2"><noscript><img \n[^a]*alt="([^"]*)"[^"]*"[^"]*"[^s]*src="(?:([^"]*\.)[^"]*(\.jpg))[^>]*.*?ter">[^>]*>\n\s*(<[^>]*>)?([^<\(]*)?</expression> + <RegExp input="$$6" output="<actor><thumb>\2\3SX1024_SY1024_.jpg</thumb><name>\1</name><role>\5</role></actor>" dest="7"> + <expression repeat="yes" clear="yes" trim="3,4" noclean="1,2"><img[^a]*alt="([^"]*)"[^"]*"[^"]*"[^s]*src="(?:[^"]*\.[^"]*"class="loadlate\shidden\s"\sloadlate="([^"]*)(_V._))[^>]*.*?ter">[^>]*>\n\s*(<[^>]*>)?([^<\(]*)?</expression> </RegExp> <RegExp input="$$6" output="<actor><thumb></thumb><name>\1</name><role>\3</role></actor>" dest="7+"> - <expression repeat="yes" trim="1,2,3" fixchars="3" noclean="1,2"><img \n[^a]*alt="([^"]*)"[^"]*"[^"]*"[^s]*src="(?:[^"]*\.[^"]*\.png)" class="" />*.*?ter">[^>]*>\n\s*(<[^>]*>)?([^<\(]*)?</expression> + <expression repeat="yes" trim="1,2,3" fixchars="3" noclean="1,2"><img[^a]*alt="([^"]*)"[^"]*"[^"]*"[^s]*src="(?:[^"]*\.[^"]*\.png)"\sclass=".*?"\s/>*.*?ter">[^>]*>\n\s*(<[^>]*>)?([^<\(]*)?</expression> </RegExp> <RegExp input="$$7" output="<actor><thumb>\1</thumb>\2</actor>" dest="2+"> <expression repeat="yes" clear="yes" noclean="1,2,3"><actor><thumb>(?:(http.*?)|_SX[0-9]+_SY[0-9]+_)?</thumb>(.*?)</actor></expression> @@ -149,7 +163,7 @@ </ParseIMDBCast> <GetIMDBDirectorsById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBDirectors">http://akas.imdb.com/title/$$1/</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBDirectors">http://akas.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBDirectorsById> @@ -159,14 +173,14 @@ <expression clear="yes" noclean="1">Director(?:s)?:.*?</h4>(.*?)<div class</expression> </RegExp> <RegExp input="$$6" output="<director>\1</director>" dest="2"> - <expression repeat="yes" fixchars="1" clear="yes">href="/name[^>]*>([^<]*)<</expression> + <expression repeat="yes" fixchars="1" clear="yes">href="/name[^>]*>[^<]*<[^>]*>([^<]*)<</expression> </RegExp> <expression noclean="1" /> </RegExp> </ParseIMDBDirectors> <GetIMDBWritersById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBWriters">http://akas.imdb.com/title/$$1/</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBWriters">http://akas.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBWritersById> @@ -176,14 +190,14 @@ <expression clear="yes" noclean="1">Writer(?:s)?:.*?</h4>(.*?)<div class</expression> </RegExp> <RegExp input="$$6" output="<credits>\1</credits>" dest="2"> - <expression repeat="yes" fixchars="1" clear="yes">href="/name[^>]*>([^<]*)<</expression> + <expression repeat="yes" fixchars="1" clear="yes">href="/name[^>]*>[^<]*<[^>]*>([^<]*)<</expression> </RegExp> <expression noclean="1" /> </RegExp> </ParseIMDBWriters> <GetIMDBFullCastById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-combined.html" function="ParseIMDBFullCast">http://akas.imdb.com/title/$$1/combined</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-combined.html" function="ParseIMDBFullCast">http://akas.imdb.com/title/$$1/combined|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBFullCastById> @@ -203,7 +217,7 @@ </ParseIMDBFullCast> <GetIMDBFullDirectorsById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-combined.html" function="ParseIMDBFullDirectors">http://akas.imdb.com/title/$$1/combined</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-combined.html" function="ParseIMDBFullDirectors">http://akas.imdb.com/title/$$1/combined|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBFullDirectorsById> @@ -220,14 +234,14 @@ </ParseIMDBFullDirectors> <GetIMDBFullWritersById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-combined.html" function="ParseIMDBFullWriters">http://akas.imdb.com/title/$$1/combined</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-combined.html" function="ParseIMDBFullWriters">http://akas.imdb.com/title/$$1/combined|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBFullWritersById> <ParseIMDBFullWriters dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="$$1" output="\1" dest="6"> - <expression noclean="1">Writing credits(.*?)name="</expression> + <expression noclean="1">Writing\scredits(.*?)name="</expression> </RegExp> <RegExp input="$$6" output="<credits>\1</credits>" dest="2"> <expression repeat="yes" fixchars="1"><a href="/name/[^>]*>([^<]*)<</expression> @@ -237,14 +251,14 @@ </ParseIMDBFullWriters> <GetIMDBThumbsById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-posters.html" function="ParseIMDBThumbs">http://akas.imdb.com/title/$$1/posters</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-posters.html" function="ParseIMDBThumbs">http://akas.imdb.com/title/$$1/posters|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBThumbsById> <ParseIMDBThumbs dest="5"> <RegExp input="$$6" output="<details>\1</details>" dest="5"> <RegExp input="$$1" output="\1_SX1024_SY1024_\2" dest="4"> - <expression noclean="1,2"><a name="poster".*?src="(.*?)_S.*?(.jpg)".*?</a></expression> + <expression noclean="1,2"><a\sname="poster".*?src="(.*?)_S.*?(.jpg)".*?</a></expression> </RegExp> <RegExp input="$$4" output="<thumb aspect="poster">\1</thumb>" dest="6"> <expression noclean="1">(.*?_SX[0-9]+_SY[0-9]+_.jpg)</expression> @@ -254,18 +268,18 @@ </ParseIMDBThumbs> <GetIMDBUSACert dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBUSACert">http://akas.imdb.com/title/$$1/</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-combined.html" function="ParseIMDBUSACert">http://akas.imdb.com/title/$$1/combined|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBUSACert> <ParseIMDBUSACert dest="5"> <RegExp input="$$1" output="<details><mpaa>$INFO[certprefix]\1</mpaa></details>" dest="5"> - <expression>MPAA</a>\)</h4>\n?<span itemprop="contentRating">Rated\s([^<]*)</expression> + <expression>MPAA</a>:</h5><div\sclass="info-content">Rated\s([^<]*)</expression> </RegExp> </ParseIMDBUSACert> <GetIMDBCountryCert dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-combined.html" function="ParseIMDBCountryCert">http://akas.imdb.com/title/$$1/combined</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-combined.html" function="ParseIMDBCountryCert">http://akas.imdb.com/title/$$1/combined|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBCountryCert> @@ -276,7 +290,7 @@ </ParseIMDBCountryCert> <GetIMDBAKATitlesById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-combined.html" function="ParseIMDBAKATitles">http://akas.imdb.com/title/$$1/combined</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-combined.html" function="ParseIMDBAKATitles">http://akas.imdb.com/title/$$1/combined|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBAKATitlesById> @@ -287,13 +301,13 @@ </RegExp> <RegExp input="$$10" output="\1" dest="4"> <RegExp input="$$1" output="\2" dest="9"> - <expression fixchars="2"><meta name="title" content="(IMDb - )?(?:&#x22;)?([^"]*?)(?:&#x22;)? \([^\(]*?([0-9]{4})\)</expression> + <expression fixchars="2"><meta\sname="title"\scontent="(IMDb\s-\s)?(?:&#x22;)?([^"]*?)(?:&#x22;)? \([^\(]*?([0-9]{4})(?:–\s)?\)</expression> </RegExp> <RegExp input="$$9" output="\1" dest="10"> <expression /> </RegExp> <RegExp input="$$1" output="\1" dest="11"> - <expression fixchars="1" clear="yes">>\s*?"([^<]+)"[^<]+[<em>]?[^"]+Hong Kong [<em>][^"]+English</expression> + <expression fixchars="1" clear="yes">>\s*?"([^<]+)"[^<]+[<em>]?[^"]+Hong Kong\s[<em>][^"]+English</expression> </RegExp> <RegExp input="$$11" output="\1" dest="10"> <expression>(.+)</expression> @@ -311,25 +325,25 @@ <expression>(.+)</expression> </RegExp> <RegExp input="$$1" output="\1" dest="11"> - <expression fixchars="1" clear="yes">>\s*?"([^<]+)"[^"]+International\s(<em>)?\(English title\)(</em>)?(,|<)( |b)</expression> + <expression fixchars="1" clear="yes">>\s*?"([^<]+)"[^"]+International\s(<em>)?\(English\stitle\)(</em>)?(,|<)( |b)</expression> </RegExp> <RegExp input="$$11" output="\1" dest="10"> <expression>(.+)</expression> </RegExp> <RegExp input="$$1" output="\1" dest="11"> - <expression fixchars="1" clear="yes">>\s*?"([^<]+)"[^"]+International\s(<em>)?\(English title\)(</em>)? (<em>)?\(imdb</expression> + <expression fixchars="1" clear="yes">>\s*?"([^<]+)"[^"]+International\s(<em>)?\(English\stitle\)(</em>)? (<em>)?\(imdb</expression> </RegExp> <RegExp input="$$11" output="\1" dest="10"> <expression>(.+)</expression> </RegExp> <RegExp input="$$1" output="\1" dest="12"> - <expression fixchars="1" clear="yes"><a href="/country/[^>]+>(UK</a></div>)</expression> + <expression fixchars="1" clear="yes"><a\shref="/country/[^>]+>(UK</a></div>)</expression> </RegExp> <RegExp input="$$12" output="$$9" dest="10"> <expression>(.+)</expression> </RegExp> <RegExp input="$$1" output="\1" dest="12"> - <expression clear="yes"><a href="/country/[^>]+>(USA</a></div>)</expression> + <expression clear="yes"><a\shref="/country/[^>]+>(USA</a></div>)</expression> </RegExp> <RegExp input="$$12" output="$$9" dest="10"> <expression>(.+)</expression> @@ -347,7 +361,7 @@ <expression>(.+)</expression> </RegExp> <RegExp input="$$1" output="\1" dest="11"> - <expression fixchars="1" clear="yes">>\s*?"([^<]+)"[^<]+[<em>]?[^"]+((USA)\s(<em>)?\((new title))</expression> + <expression fixchars="1" clear="yes">>\s*?"([^<]+)"[^<]+[<em>]?[^"]+((USA)\s(<em>)?\((new\stitle))</expression> </RegExp> <RegExp input="$$11" output="\1" dest="10"> <expression>(.+)</expression> @@ -364,13 +378,13 @@ <expression>(.+)</expression> </RegExp> <RegExp input="$$1" output="\1" dest="4"> - <expression fixchars="1">>\s*?"([^<]+)"[^<]+[<em>]?[^"]+$INFO[imdbakatitles]\s(<em>)?\((imdb display)</expression> + <expression fixchars="1">>\s*?"([^<]+)"[^<]+[<em>]?[^"]+$INFO[imdbakatitles]\s(<em>)?\((imdb\sdisplay)</expression> </RegExp> <RegExp input="$$4" output="\1" dest="2"> <expression>(.+)</expression> </RegExp> <RegExp input="$$1" output="\1" dest="5"> - <expression><a href="/country/[^>]+>($INFO[imdbakatitles])</expression> + <expression><a\shref="/country/[^>]+>($INFO[imdbakatitles])</expression> </RegExp> <RegExp input="$$5" output="$$9" dest="4"> <expression>($INFO[imdbakatitles])</expression> diff --git a/addons/metadata.common.last.fm/addon.xml b/addons/metadata.common.last.fm/addon.xml index 561026f8f1..98c914dbd8 100644 --- a/addons/metadata.common.last.fm/addon.xml +++ b/addons/metadata.common.last.fm/addon.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon id="metadata.common.last.fm" name="Last.FM" - version="1.5.1" + version="1.6.0" provider-name="Team XBMC"> <requires> - <import addon="xbmc.metadata" version="1.0"/> + <import addon="xbmc.metadata" version="2.1.0"/> </requires> <extension point="xbmc.metadata.scraper.library" library="lastfm.xml"/> diff --git a/addons/metadata.common.last.fm/lastfm.xml b/addons/metadata.common.last.fm/lastfm.xml index c47a42e32b..364e70714b 100644 --- a/addons/metadata.common.last.fm/lastfm.xml +++ b/addons/metadata.common.last.fm/lastfm.xml @@ -87,6 +87,9 @@ <RegExp input="$INFO[genresfbsource]" output="<chain function="GetAMGFallbackArtistGenresByAMGID">$$9</chain>" dest="12"> <expression>allmusic.com</expression> </RegExp> + <RegExp input="$INFO[genresfbsource]" output="<chain function="GetTADBFallbackArtistGenresByMBID">$$8</chain>" dest="12"> + <expression>TheAudioDb.com</expression> + </RegExp> <expression><genre></genre></expression> </RegExp> <RegExp input="$$11" output="$$11" dest="4"> diff --git a/addons/metadata.common.musicbrainz.org/addon.xml b/addons/metadata.common.musicbrainz.org/addon.xml index 42a26355a0..df66d41263 100644 --- a/addons/metadata.common.musicbrainz.org/addon.xml +++ b/addons/metadata.common.musicbrainz.org/addon.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon id="metadata.common.musicbrainz.org" name="musicbrainz" - version="1.2.3" + version="1.3.0" provider-name="Team XBMC"> <requires> - <import addon="xbmc.metadata" version="1.0"/> + <import addon="xbmc.metadata" version="2.1.0"/> </requires> <extension point="xbmc.metadata.scraper.library" library="musicbrainz.xml"/> diff --git a/addons/metadata.common.musicbrainz.org/musicbrainz.xml b/addons/metadata.common.musicbrainz.org/musicbrainz.xml index 16e539b23b..a35a9b419f 100644 --- a/addons/metadata.common.musicbrainz.org/musicbrainz.xml +++ b/addons/metadata.common.musicbrainz.org/musicbrainz.xml @@ -17,7 +17,7 @@ </ParseMBDiscography> <GetMBLafeSpanByMBID dest="5" clearbuffers="no"> - <RegExp input="$$1" output="<details><url function="ParseMBLifeSpan" cache="mb-\1-artist.xml">http://www.musicbrainz.org/ws/2/artist/\1?inc=url-rels</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url function="ParseMBLifeSpan" cache="mb-\1-artist.xml">http://musicbrainz.org/ws/2/artist/\1?inc=url-rels</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetMBLafeSpanByMBID> @@ -45,6 +45,9 @@ <RegExp input="$INFO[lifespanfbsource]" output="<chain function="GetAMGFallbackArtistLifeSpanByAMGID">$$9</chain>" dest="12"> <expression>allmusic.com</expression> </RegExp> + <RegExp input="$INFO[lifespanfbsource]" output="<chain function="GetTADBFallbackLifeSpanByMBID">$$8</chain>" dest="12"> + <expression>TheAudioDb.com</expression> + </RegExp> <expression>^$</expression> </RegExp> <RegExp input="$$11" output="$$11" dest="2"> @@ -55,7 +58,7 @@ </ParseMBLifeSpan> <GetMBFallbackLafeSpanByMBID dest="5" clearbuffers="no"> - <RegExp input="$$1" output="<details><url function="ParseFallbackMBLifeSpan" cache="mb-\1-artist.xml">http://www.musicbrainz.org/ws/2/artist/\1?inc=url-rels</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url function="ParseFallbackMBLifeSpan" cache="mb-\1-artist.xml">http://musicbrainz.org/ws/2/artist/\1?inc=url-rels</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetMBFallbackLafeSpanByMBID> @@ -87,13 +90,27 @@ </GetMBAlbumTitleByMBID> <ParseMBAlbumTitle dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> - <RegExp input="$$1" output="<title>\1</title>" dest="2"> - <expression noclean="1"><release id="[^"]*"><title>([^<]*)<</expression> + <RegExp input="$$1" output="<musicBrainzAlbumID>\1</musicBrainzAlbumID><title>\2</title>" dest="2"> + <expression noclean="1"><release id="([^"]*)"><title>([^<]*)<</expression> </RegExp> <expression noclean="1">(.+)</expression> </RegExp> </ParseMBAlbumTitle> + <GetMBAlbumArtistsByMBID dest="5"> + <RegExp input="$$1" output="<details><url function="ParseMBAlbumArtists" cache="mb-\1-album.xml">http://musicbrainz.org/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings</url></details>" dest="5"> + <expression noclean="1" /> + </RegExp> + </GetMBAlbumArtistsByMBID> + <ParseMBAlbumArtists dest="5"> + <RegExp input="$$2" output="<details>\1</details>" dest="5"> + <RegExp input="$$1" output="<albumArtistCredits><joinphrase>\1</joinphrase><musicBrainzArtistID>\2</musicBrainzArtistID><artist>\3</artist></albumArtistCredits>" dest="2"> + <expression repeat="yes" noclean="1">(?:joinphrase="([^"]*)">)?<artist\sid="([^"]*)"><name>([^<]*)<</expression> + </RegExp> + <expression noclean="1">(.+)</expression> + </RegExp> + </ParseMBAlbumArtists> + <GetMBAlbumArtistByMBID dest="5"> <RegExp input="$$1" output="<details><url function="ParseMBAlbumArtist" cache="mb-\1-album.xml">http://musicbrainz.org/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings</url></details>" dest="5"> <expression noclean="1" /> diff --git a/addons/metadata.common.theaudiodb.com/addon.xml b/addons/metadata.common.theaudiodb.com/addon.xml index dbf44f6f8f..432763702a 100644 --- a/addons/metadata.common.theaudiodb.com/addon.xml +++ b/addons/metadata.common.theaudiodb.com/addon.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon id="metadata.common.theaudiodb.com" name="TheAudioDb Common Scraper Functions" - version="1.3.0" + version="1.6.1" provider-name="Team XBMC"> <requires> - <import addon="xbmc.metadata" version="1.0"/> + <import addon="xbmc.metadata" version="2.1.0"/> </requires> <extension point="xbmc.metadata.scraper.library" library="tadb.xml"/> diff --git a/addons/metadata.common.theaudiodb.com/tadb.xml b/addons/metadata.common.theaudiodb.com/tadb.xml index 5cce462cea..7c1a807a05 100644 --- a/addons/metadata.common.theaudiodb.com/tadb.xml +++ b/addons/metadata.common.theaudiodb.com/tadb.xml @@ -64,8 +64,14 @@ <RegExp input="" output="" dest="2"> <expression /> </RegExp> + <RegExp input="" output="" dest="11"> + <expression /> + </RegExp> + <RegExp input="$$1" output="\1" dest="11"> + <expression fixchars="1">strBiographyEN":"(.*?)","</expression> + </RegExp> <RegExp input="$$1" output="\1" dest="11"> - <expression clear="yes" fixchars="1">strBiography":"(.*?)","</expression> + <expression fixchars="1">strBiography$INFO[tadbartistlanguage]":"(.*?)","</expression> </RegExp> <RegExp input="$$11" output="$$12" dest="2"> <RegExp input="$INFO[biogfbsource]" output="<chain function="GetLastFMFallbackBiographyByMBID">$$8</chain>" dest="12"> @@ -94,7 +100,10 @@ <expression /> </RegExp> <RegExp input="$$1" output="<biography>\1</biography>" dest="2"> - <expression clear="yes" fixchars="1">strBiography":"(.*?)","</expression> + <expression fixchars="1">strBiographyen":"(.*?)","</expression> + </RegExp> + <RegExp input="$$1" output="\1" dest="2"> + <expression fixchars="1">strBiography$INFO[tadbartistlanguage]":"(.*?)","</expression> </RegExp> <expression noclean="1"/> </RegExp> @@ -105,6 +114,11 @@ <expression noclean="1" /> </RegExp> </GetTADBDiscographyByID> + <GetTADBDiscographyByMBID dest="5" clearbuffers="no"> + <RegExp input="$$1" output="<details><url function="ParseTADBDiscography">http://www.theaudiodb.com/api/v1/json/58424d43204d6564696120/discography-mb.php?s=\1</url></details>" dest="5"> + <expression noclean="1" /> + </RegExp> + </GetTADBDiscographyByMBID> <ParseTADBDiscography dest="5" clearbuffers="no"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="" output="" dest="2"> @@ -122,6 +136,11 @@ <expression noclean="1" /> </RegExp> </GetTADBLifeSpanByID> + <GetTADBLifeSpanByMBID dest="5" clearbuffers="no"> + <RegExp input="$$1" output="<details><url function="ParseTADBLifeSpan" cache="tadb-\1-artist.json">http://www.theaudiodb.com/api/v1/json/58424d43204d6564696120/artist-mb.php?i=\1</url></details>" dest="5"> + <expression noclean="1"/> + </RegExp> + </GetTADBLifeSpanByMBID> <ParseTADBLifeSpan dest="5" clearbuffers="no"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="" output="" dest="2"> @@ -130,18 +149,27 @@ <RegExp input="" output="" dest="11"> <expression /> </RegExp> - <RegExp input="$$1" output="<formed>\1</formed>" dest="11"> - <expression noclean="1">intFormedYear":"([^"]*)</expression> + <RegExp input="$$1" output="<formed>\2 (\1)</formed>" dest="11"> + <expression fixchars="2" noclean="1">intFormedYear":"([^"]*).*?strCountry":"([^"]*)</expression> </RegExp> <RegExp input="$$1" output="<disbanded>\1</disbanded>" dest="11+"> <expression noclean="1">strDisbanded":"([^"]*)</expression> </RegExp> - <RegExp input="$$1" output="<born>\1</born>" dest="11"> - <expression noclean="1">intBornYear":"([^"]*)</expression> + <RegExp input="$$1" output="<born>\2 (\1)</born>" dest="11"> + <expression fixchars="2" noclean="1">intBornYear":"([^"]*).*?strCountry":"([^"]*)</expression> </RegExp> <RegExp input="$$1" output="<died>\1</died>" dest="11+"> <expression noclean="1">intDiedYear":"([^"]*)</expression> </RegExp> + <RegExp input="$$11" output="$$12" dest="2"> + <RegExp input="$INFO[lifespanfbsource]" output="<chain function="GetMBFallbackLafeSpanByMBID">$$8</chain>" dest="12"> + <expression>MusicBrainz</expression> + </RegExp> + <RegExp input="$INFO[lifespanfbsource]" output="<chain function="GetAMGFallbackArtistLifeSpanByAMGID">$$9</chain>" dest="12"> + <expression>allmusic.com</expression> + </RegExp> + <expression>^$</expression> + </RegExp> <RegExp input="$$11" output="$$11" dest="2"> <expression noclean="1"><(?:born|formed)*>(.+)</(?:born|formed)*></expression> </RegExp> @@ -149,23 +177,92 @@ </RegExp> </ParseTADBLifeSpan> + <GetTADBFallbackLifeSpanByMBID dest="5" clearbuffers="no"> + <RegExp input="$$1" output="<details><url function="ParseTADBFallbackLifeSpan" cache="tadb-\1-artist.json">http://www.theaudiodb.com/api/v1/json/58424d43204d6564696120/artist-mb.php?i=\1</url></details>" dest="5"> + <expression noclean="1"/> + </RegExp> + </GetTADBFallbackLifeSpanByMBID> + <ParseTADBFallbackLifeSpan dest="5" clearbuffers="no"> + <RegExp input="$$2" output="<details>\1</details>" dest="5"> + <RegExp input="" output="" dest="2"> + <expression /> + </RegExp> + <RegExp input="" output="" dest="11"> + <expression /> + </RegExp> + <RegExp input="$$1" output="<formed>\2 (\1)</formed>" dest="11"> + <expression fixchars="2" noclean="1">intFormedYear":"([^"]*).*?strCountry":"([^"]*)</expression> + </RegExp> + <RegExp input="$$1" output="<disbanded>\1</disbanded>" dest="11+"> + <expression noclean="1">strDisbanded":"([^"]*)</expression> + </RegExp> + <RegExp input="$$1" output="<born>\2 (\1)</born>" dest="11"> + <expression fixchars="2" noclean="1">intBornYear":"([^"]*).*?strCountry":"([^"]*)</expression> + </RegExp> + <RegExp input="$$1" output="<died>\1</died>" dest="11+"> + <expression noclean="1">intDiedYear":"([^"]*)</expression> + </RegExp> + <RegExp input="$$11" output="$$11" dest="2"> + <expression noclean="1"><(?:born|formed)*>(.+)</(?:born|formed)*></expression> + </RegExp> + <expression noclean="1"/> + </RegExp> + </ParseTADBFallbackLifeSpan> + <GetTADBArtistGenresByID dest="5" clearbuffers="no"> <RegExp input="$$1" output="<details><url function="ParseTADBArtistGenres" cache="tadb-\1-artist.json">http://www.theaudiodb.com/api/v1/json/58424d43204d6564696120/artist.php?i=\1</url></details>" dest="5"> <expression noclean="1"/> </RegExp> </GetTADBArtistGenresByID> + <GetTADBArtistGenresByMBID dest="5" clearbuffers="no"> + <RegExp input="$$1" output="<details><url function="ParseTADBArtistGenres" cache="tadb-\1-artist.json">http://www.theaudiodb.com/api/v1/json/58424d43204d6564696120/artist-mb.php?i=\1</url></details>" dest="5"> + <expression noclean="1"/> + </RegExp> + </GetTADBArtistGenresByMBID> <ParseTADBArtistGenres dest="5" clearbuffers="no"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="" output="" dest="2"> <expression /> </RegExp> - <RegExp input="$$1" output="<genre>\1</genre>" dest="2"> - <expression noclean="1">strGenre":"([^"]*)</expression> + <RegExp input="" output="" dest="11"> + <expression /> + </RegExp> + <RegExp input="$$1" output="\1" dest="11"> + <expression fixchars="1">strSubGenre":"([^"]*)</expression> + </RegExp> + <RegExp input="$$11" output="$$12" dest="2"> + <RegExp input="$INFO[genresfbsource]" output="<chain function="GetLastFMFallbackArtistGenresByMBID">$$8</chain>" dest="12"> + <expression>last.fm</expression> + </RegExp> + <RegExp input="$INFO[genresfbsource]" output="<chain function="GetAMGFallbackArtistGenresByAMGID">$$9</chain>" dest="12"> + <expression>allmusic.com</expression> + </RegExp> + <expression>^$</expression> + </RegExp> + <RegExp input="$$11" output="<genre>\1</genre>" dest="2"> + <expression>(.+)</expression> </RegExp> <expression noclean="1" /> </RegExp> </ParseTADBArtistGenres> + <GetTADBFallbackArtistGenresByMBID dest="5" clearbuffers="no"> + <RegExp input="$$1" output="<details><url function="ParseTADBArtistGenres" cache="tadb-\1-artist.json">http://www.theaudiodb.com/api/v1/json/58424d43204d6564696120/artist-mb.php?i=\1</url></details>" dest="5"> + <expression noclean="1"/> + </RegExp> + </GetTADBFallbackArtistGenresByMBID> + <ParseTADBFallbackArtistGenres dest="5" clearbuffers="no"> + <RegExp input="$$2" output="<details>\1</details>" dest="5"> + <RegExp input="" output="" dest="2"> + <expression /> + </RegExp> + <RegExp input="$$1" output="<genre>\1</genre>" dest="2"> + <expression noclean="1">strSubGenre":"([^"]*)</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </ParseTADBFallbackArtistGenres> + <GetTADBAlbumReviewByID dest="5"> <RegExp input="$$1" output="<details><url function="ParseTADBAlbumReview" cache="tadb-\1-album.json">http://www.theaudiodb.com/api/v1/json/58424d43204d6564696120/album.php?m=\1</url></details>" dest="5"> @@ -180,7 +277,10 @@ <ParseTADBAlbumReview dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="$$1" output="<review>\1</review>" dest="2"> - <expression fixchars="1">strDescription":"(.*?)","</expression> + <expression fixchars="1">strDescriptionEN":"(.*?)","</expression> + </RegExp> + <RegExp input="$$1" output="<review>\1</review>" dest="2"> + <expression fixchars="1">strDescription$INFO[tadbalbumlanguage]":"(.*?)","</expression> </RegExp> <expression noclean="1" /> </RegExp> @@ -219,6 +319,11 @@ <expression noclean="1"/> </RegExp> </GetTADBAlbumDateByID> + <GetTADBAlbumDateByMBID dest="5"> + <RegExp input="$$1" output="<details><url function="ParseTADBAlbumDate" cache="tadb-\1-album.json">http://www.theaudiodb.com/api/v1/json/58424d43204d6564696120/album-mb.php?i=\1</url></details>" dest="5"> + <expression noclean="1"/> + </RegExp> + </GetTADBAlbumDateByMBID> <ParseTADBAlbumDate dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="$$1" output="<year>\1</year>" dest="2"> @@ -233,10 +338,15 @@ <expression noclean="1"/> </RegExp> </GetTADBAlbumGenresByID> + <GetTADBAlbumGenresByMBID dest="5"> + <RegExp input="$$1" output="<details><url function="ParseTADBAlbumGenres" cache="tadb-\1-album.json">http://www.theaudiodb.com/api/v1/json/58424d43204d6564696120/album-mb.php?i=\1</url></details>" dest="5"> + <expression noclean="1"/> + </RegExp> + </GetTADBAlbumGenresByMBID> <ParseTADBAlbumGenres dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="$$1" output="<genre>\1</genre>" dest="2"> - <expression noclean="1">strGenre":"([^"]*)</expression> + <expression noclean="1">strSubGenre":"([^"]*)</expression> </RegExp> <expression noclean="1" /> </RegExp> diff --git a/addons/metadata.common.themoviedb.org/addon.xml b/addons/metadata.common.themoviedb.org/addon.xml index 1c00e6069d..fc9a87aea6 100644 --- a/addons/metadata.common.themoviedb.org/addon.xml +++ b/addons/metadata.common.themoviedb.org/addon.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon id="metadata.common.themoviedb.org" - name="The MovieDB common scraper functions" - version="2.9.1" + name="The Movie Database Scraper Library" + version="2.9.3" provider-name="Team XBMC"> <requires> - <import addon="xbmc.metadata" version="1.0"/> + <import addon="xbmc.metadata" version="2.1.0"/> </requires> <extension point="xbmc.metadata.scraper.library" library="tmdb.xml"/> diff --git a/addons/metadata.common.themoviedb.org/tmdb.xml b/addons/metadata.common.themoviedb.org/tmdb.xml index ab8b3df1b8..675bf672d6 100644 --- a/addons/metadata.common.themoviedb.org/tmdb.xml +++ b/addons/metadata.common.themoviedb.org/tmdb.xml @@ -132,17 +132,23 @@ </RegExp> </ParseFallbackTMDBTagline> - <GetTMDBSetByIdChain dest="4"> + <GetTMDBSetByIdChain clearbuffers="no" dest="4"> <RegExp input="$$5" output="<details>\1</details>" dest="4"> - <RegExp input="$$1" output="<url function="ParseTMDBSet" cache="tmdb-$INFO[language]-\1.json">http://api.themoviedb.org/3/movie/\1?api_key=57983e31fb435df4df77afb854740ea9&amp;language=$INFO[language]</url>" dest="5"> + <RegExp input="$$1" output="\1" dest="8"> + <expression clear="yes" noclean="1" /> + </RegExp> + <RegExp input="$$8" output="<url function="ParseTMDBSet" cache="tmdb-$INFO[language]-\1.json">http://api.themoviedb.org/3/movie/\1?api_key=57983e31fb435df4df77afb854740ea9&amp;language=$INFO[language]</url>" dest="5"> <expression /> </RegExp> <expression noclean="1" /> </RegExp> </GetTMDBSetByIdChain> - <GetTMDBLangSetByIdChain dest="4"> + <GetTMDBLangSetByIdChain clearbuffers="no" dest="4"> <RegExp input="$$5" output="<details>\1</details>" dest="4"> - <RegExp input="$$1" output="<url function="ParseTMDBSet" cache="tmdb-$INFO[tmdbsetlanguage]-\1.json">http://api.themoviedb.org/3/movie/\1?api_key=57983e31fb435df4df77afb854740ea9&amp;language=$INFO[tmdbsetlanguage]</url>" dest="5"> + <RegExp input="$$1" output="\1" dest="8"> + <expression clear="yes" noclean="1" /> + </RegExp> + <RegExp input="$$8" output="<url function="ParseTMDBSet" cache="tmdb-$INFO[tmdbsetlanguage]-\1.json">http://api.themoviedb.org/3/movie/\1?api_key=57983e31fb435df4df77afb854740ea9&amp;language=$INFO[tmdbsetlanguage]</url>" dest="5"> <expression /> </RegExp> <expression noclean="1" /> diff --git a/addons/metadata.musicvideos.theaudiodb.com/addon.xml b/addons/metadata.musicvideos.theaudiodb.com/addon.xml index 37ab5a46c6..b05009b271 100644 --- a/addons/metadata.musicvideos.theaudiodb.com/addon.xml +++ b/addons/metadata.musicvideos.theaudiodb.com/addon.xml @@ -1,11 +1,12 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon id="metadata.musicvideos.theaudiodb.com" name="TheAudioDb.com for Music Videos" - version="1.0.3" + version="1.2.2" provider-name="Team XBMC"> <requires> - <import addon="xbmc.metadata" version="1.0"/> - <import addon="metadata.common.fanart.tv" version="1.0.1"/> + <import addon="xbmc.metadata" version="2.1.0"/> + <import addon="metadata.common.theaudiodb.com" version="1.6.0"/> + <import addon="metadata.common.fanart.tv" version="2.1.2"/> </requires> <extension point="xbmc.metadata.scraper.musicvideos" language="en" @@ -15,23 +16,27 @@ <summary lang="be">theaudiodb.com Music Video Scraper</summary> <summary lang="bg">Ð¡Ð²Ð°Ð»Ñ Ð¸Ð½Ñ„. за музикални клипове от theaudiodb.com</summary> <summary lang="cs">Zdroj dat o hudebnÃch videÃch theaudiodb.com</summary> + <summary lang="cy">Crafwr Fideo Cerddoriaeth theaudiodb.com</summary> <summary lang="da">theaudiodb.com Musikvideo-scraper</summary> <summary lang="de">theaudiodb.com Musikvideo-Scraper</summary> <summary lang="el">Scraper Μουσικών Βίντεο του theaudiodb.com</summary> <summary lang="en">theaudiodb.com Music Video Scraper</summary> <summary lang="es">Buscador de videoclips de theaudiodb.com</summary> - <summary lang="es_AR">Scraper de Videos de Música de TheAudioDb.com</summary> + <summary lang="es_AR">Scraper de Videos de Música de theaudiodb.com</summary> + <summary lang="et">theaudiodb.com muusikavideo kraabits</summary> <summary lang="fi">theaudiodb.com musiikkivideotietojen lataaja</summary> <summary lang="fr">theaudiodb.com Scraper Clip Vidéo</summary> <summary lang="gl">Scraper de vÃdeo e música de theaudiodb.com</summary> <summary lang="he">theaudiodb.com סקרייפר ויד×ו קליפ</summary> + <summary lang="hr">theaudiodb.com Muzika i Video strugaÄ</summary> <summary lang="hu">theaudiodb.com videóklip leolvasó</summary> <summary lang="it">Lo scraper di video musicali theaudiodb.com</summary> <summary lang="ja">theaudiodb.com 音楽ビデオスクレーパー</summary> - <summary lang="ko">야후! ë®¤ì§ ë¹„ë””ì˜¤ 스í¬ëž˜í¼</summary> + <summary lang="ko">theaudiodb.com ë®¤ì§ ë¹„ë””ì˜¤ ìžë£Œìˆ˜ì§‘기</summary> <summary lang="lt">theaudiodb.com vaizdo klipų Scraper</summary> <summary lang="mk">theaudiodb.com Music Video Scraper</summary> - <summary lang="nl">theaudiodb.com Muziek Video Scraper</summary> + <summary lang="my">theaudiodb.com Music Video Scraper</summary> + <summary lang="nl">theaudiodb.com Muziekvideo-scraper</summary> <summary lang="no">theaudiodb.com Skraper for musikkvideo</summary> <summary lang="pl">Scraper teledysków theaudiodb.com</summary> <summary lang="pt">Scraper de música theaudiodb.com</summary> @@ -42,18 +47,23 @@ <summary lang="sk">Zdroj zÃskavania dát o hudobných videách zo stránky theaudiodb.com</summary> <summary lang="sl">Ponudnik informacij o videospotih theaudiodb.com</summary> <summary lang="sv">theaudiodb.com musikvideoskrapa</summary> + <summary lang="ta_IN">theaudiodb.com இசை நிகழà¯à®ªà®Ÿà®®à¯ சà¯à®°à®£à¯à®Ÿà®¿</summary> <summary lang="th">ตัวดึงข้à¸à¸¡à¸¹à¸¥à¸§à¸´à¸”ีโà¸à¹€à¸žà¸¥à¸‡ theaudiodb.com</summary> + <summary lang="uk">Здирач музичного відео з theaudiodb.com</summary> + <summary lang="vi">Trình lấy dữ liệu Video nhạc từ theaudiodb.com</summary> <summary lang="zh">theaudiodb.com音ä¹ç”µè§†åˆ®å‰Šå™¨</summary> + <summary lang="zh_TW">theaudiodb.com音樂影片æœæ‹¬å™¨</summary> <description lang="af">Laai Musiek Video informasie af</description> <description lang="am">የሙዚቃ ቪዲዮ መረጃ ማá‹áˆ¨áŒƒ</description> <description lang="be">Download Music Video information</description> <description lang="bg">Ð¡Ð²Ð°Ð»Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° музикални клипове</description> <description lang="ca">Baixa informació de videos musicals</description> <description lang="cs">Stáhnout informace o hudebnÃm videu</description> + <description lang="cy">Mae'r crafwr yn llwytho i lawr gwybodaeth am Gerddoriaeth Fideo o TheAudioDB.com. Oherwydd amryw o anawsterau chwilio mae'r crafwr yn disgwyl i'r ffolder/enw ffeil fod wedi ei fformatio fel 'artist - enw track' neu ni fydd yn dychwelyd canlyniadau.</description> <description lang="da">Hent Musikvideo-information</description> <description lang="de">Musik Video Information herunterladen</description> <description lang="el">Λήψη πληÏοφοÏιών Μουσικών Βίντεο</description> - <description lang="en">Download Music Video information</description> + <description lang="en">This scraper is downloading Music Video information from TheAudioDB.com. Due to various search difficulties the scraper currently expects the folder/filename to be formatted as 'artist - trackname' otherwise it will not return results.</description> <description lang="es">Descarga información del videoclip</description> <description lang="es_AR">Descarga información del Video Clip</description> <description lang="es_MX">Descarga Información de VÃdeos de Músca</description> diff --git a/addons/metadata.musicvideos.theaudiodb.com/changelog.txt b/addons/metadata.musicvideos.theaudiodb.com/changelog.txt new file mode 100644 index 0000000000..d3fcfb8d5c --- /dev/null +++ b/addons/metadata.musicvideos.theaudiodb.com/changelog.txt @@ -0,0 +1,19 @@ +[B]1.2.1[/B] +- Fixed: Allow for dashes in artist/title (v12.2+ required) + +[B]1.2.0[/B] +- Added: NfoURL function +- Added: Album thumbs from theaudiodb.com + +[B]1.1.1[/B] +- Fixed Workaround: Scraper won't return 'Unable to Connect to Remote Server' in case of year is available from the folder/file name + +[B]1.1.0[/B] +- Workaround: Scraper won't return 'Unable to Connect to Remote Server' in case of unexpected folder/file naming conventions +- Added: Music Video Director +- Added: Music Video Studio +- Changed: Scrape Music Video screenshot instead of album thumb if available +- Changed: Trust search result ordering from TheAudioDb.com +- Changed: Scrape Album genre instead of track genre for now +- Added: Scrape Album Year +- Added: Scraper description (stating current limitations) diff --git a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Burmese/strings.xml b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Burmese/strings.xml new file mode 100644 index 0000000000..8db0298e4f --- /dev/null +++ b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Burmese/strings.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Burmese language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/my/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">fanart.tv မှ album thumbs များရယူမည်</string> +</strings> diff --git a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Catalan/strings.xml b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Catalan/strings.xml index d38a9ad2b5..bc941dec1a 100644 --- a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Catalan/strings.xml +++ b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Catalan/strings.xml @@ -5,4 +5,5 @@ <strings> <string id="30000">Agafa les miniatures d'à lbums de fanart.tv</string> + <string id="30001">Agafa les miniatures d'à lbums de theaudiodb.com</string> </strings> diff --git a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Chinese (Simple)/strings.xml b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Chinese (Simple)/strings.xml index 1b4badd576..89816a3958 100644 --- a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Chinese (Simple)/strings.xml +++ b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Chinese (Simple)/strings.xml @@ -5,4 +5,5 @@ <strings> <string id="30000">从fanart.tv获å–专辑图片</string> + <string id="30001">从theaudiodb.com获å–专辑图片</string> </strings> diff --git a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Chinese (Traditional)/strings.xml b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Chinese (Traditional)/strings.xml new file mode 100644 index 0000000000..1b15ed9957 --- /dev/null +++ b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Chinese (Traditional)/strings.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Chinese (Traditional) language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/zh_TW/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">從fanart.två–得專輯縮圖</string> + <string id="30001">從 theaudiodb.comå–得專輯縮圖</string> +</strings> diff --git a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Croatian/strings.xml b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Croatian/strings.xml new file mode 100644 index 0000000000..44d7b00a10 --- /dev/null +++ b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Croatian/strings.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Croatian language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/hr/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">Zahvati sliÄice za Albume sa fanart.tv</string> +</strings> diff --git a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Czech/strings.xml b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Czech/strings.xml index 138d80502b..75b442e8f3 100644 --- a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Czech/strings.xml +++ b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Czech/strings.xml @@ -5,4 +5,5 @@ <strings> <string id="30000">ZÃskat náhledy alb z fanart.tv</string> + <string id="30001">ZÃskat náhledy alb z theaudiodb.com</string> </strings> diff --git a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Dutch/strings.xml b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Dutch/strings.xml index 521473130c..b97fbd2d74 100644 --- a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Dutch/strings.xml +++ b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Dutch/strings.xml @@ -4,5 +4,6 @@ <!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> <strings> - <string id="30000">Verkrijg album thumbs van fanart.tv</string> + <string id="30000">Pak albumminiaturen van fanart.tv</string> + <string id="30001">Haal Albumminiaturen van theaudiodb.com</string> </strings> diff --git a/addons/metadata.musicvideos.theaudiodb.com/resources/language/English/strings.xml b/addons/metadata.musicvideos.theaudiodb.com/resources/language/English/strings.xml index 8b5221e453..c581ca412a 100644 --- a/addons/metadata.musicvideos.theaudiodb.com/resources/language/English/strings.xml +++ b/addons/metadata.musicvideos.theaudiodb.com/resources/language/English/strings.xml @@ -5,4 +5,5 @@ <strings> <string id="30000">Grab album thumbs from fanart.tv</string> + <string id="30001">Grab album thumbs from theaudiodb.com</string> </strings> diff --git a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Estonian/strings.xml b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Estonian/strings.xml new file mode 100644 index 0000000000..1d7f626d2b --- /dev/null +++ b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Estonian/strings.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Estonian language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/et/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">Hangi albumi pisipildid fanart.tv-st</string> +</strings> diff --git a/addons/metadata.musicvideos.theaudiodb.com/resources/language/French/strings.xml b/addons/metadata.musicvideos.theaudiodb.com/resources/language/French/strings.xml index bdd7dd3229..c0f8967641 100644 --- a/addons/metadata.musicvideos.theaudiodb.com/resources/language/French/strings.xml +++ b/addons/metadata.musicvideos.theaudiodb.com/resources/language/French/strings.xml @@ -5,4 +5,5 @@ <strings> <string id="30000">Récupérer les vignettes d'albums depuis fanart.tv</string> + <string id="30001">Récupère les vignettes des albums depuis theaudiodb.com</string> </strings> diff --git a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Galician/strings.xml b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Galician/strings.xml index 17b6ffa5f8..7300abd2be 100644 --- a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Galician/strings.xml +++ b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Galician/strings.xml @@ -5,4 +5,5 @@ <strings> <string id="30000">Obter as miniaturas do álbum dende fanart.tv</string> + <string id="30001">Obter as miniaturas do álbum dende theaudiodb.com</string> </strings> diff --git a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Greek/strings.xml b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Greek/strings.xml index a30f60c67e..cc11ca8113 100644 --- a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Greek/strings.xml +++ b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Greek/strings.xml @@ -5,4 +5,5 @@ <strings> <string id="30000">ΜικÏογÏαφίες άλμπουμ από fanart.tv</string> + <string id="30001">ΜικÏογÏαφίες Άλμπουμ από το theaudiodb.com</string> </strings> diff --git a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Hungarian/strings.xml b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Hungarian/strings.xml index 1df352ce4b..717f9bb4c0 100644 --- a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Hungarian/strings.xml +++ b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Hungarian/strings.xml @@ -5,4 +5,5 @@ <strings> <string id="30000">Album miniképek letÅ‘ltésea fanart.tv-rÅ‘l</string> + <string id="30001">Album miniképek a theaudiodb.com-ról</string> </strings> diff --git a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Italian/strings.xml b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Italian/strings.xml index 0c8c8b1219..ba7082dcb1 100644 --- a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Italian/strings.xml +++ b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Italian/strings.xml @@ -5,4 +5,5 @@ <strings> <string id="30000">Scarica le copertine album da fanart.tv</string> + <string id="30001">Prendi miniature album da theaudiodb.com</string> </strings> diff --git a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Korean/strings.xml b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Korean/strings.xml index da27bae11d..1c276a0eeb 100644 --- a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Korean/strings.xml +++ b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Korean/strings.xml @@ -5,4 +5,5 @@ <strings> <string id="30000">fanart.tv ì—ì„œ 앨범 커버 ê°€ì ¸ì˜¤ê¸°</string> + <string id="30001">theaudiodb.com ì—ì„œ 앨범 커버 ê°€ì ¸ì˜¤ê¸°</string> </strings> diff --git a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Polish/strings.xml b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Polish/strings.xml index 157ccb2a27..4802268d61 100644 --- a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Polish/strings.xml +++ b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Polish/strings.xml @@ -5,4 +5,5 @@ <strings> <string id="30000">Pobierz ikony albumu z fanart.tv</string> + <string id="30001">Pobierz miniatury albumu z theaudiodb.com</string> </strings> diff --git a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Portuguese (Brazil)/strings.xml b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Portuguese (Brazil)/strings.xml index 32bff6a511..9419790121 100644 --- a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Portuguese (Brazil)/strings.xml +++ b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Portuguese (Brazil)/strings.xml @@ -5,4 +5,5 @@ <strings> <string id="30000">Obter miniaturas de álbuns de fanart.tv</string> + <string id="30001">Pegar miniaturas de álbum de theaudiodb.com</string> </strings> diff --git a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Portuguese/strings.xml b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Portuguese/strings.xml index d31d2b9d60..2f36fc37da 100644 --- a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Portuguese/strings.xml +++ b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Portuguese/strings.xml @@ -5,4 +5,5 @@ <strings> <string id="30000">Obter miniaturas de álbum em fanart.tv</string> + <string id="30001">Obter miniaturas de álbum em theaudiodb.com</string> </strings> diff --git a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Romanian/strings.xml b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Romanian/strings.xml index 555f442a6b..94321b72ec 100644 --- a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Romanian/strings.xml +++ b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Romanian/strings.xml @@ -5,4 +5,5 @@ <strings> <string id="30000">ObÅ£ine imagini albume de la fanart.tv</string> + <string id="30001">ObÅ£ine imagini albume de la theaudiodb.com</string> </strings> diff --git a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Spanish (Argentina)/strings.xml b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Spanish (Argentina)/strings.xml index 27fb72c87f..e747f649c8 100644 --- a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Spanish (Argentina)/strings.xml +++ b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Spanish (Argentina)/strings.xml @@ -4,5 +4,6 @@ <!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> <strings> - <string id="30000">Obtener miniatura de album de fanart.tv</string> + <string id="30000">Obtener miniaturas de álbum de fanart.tv</string> + <string id="30001">Descargar miniaturas de álbum de theaudiodb.com</string> </strings> diff --git a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Spanish/strings.xml b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Spanish/strings.xml index 54d3c5dabd..1ed1694bab 100644 --- a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Spanish/strings.xml +++ b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Spanish/strings.xml @@ -5,4 +5,5 @@ <strings> <string id="30000">Obtener miniatura de álbum de fanart.tv</string> + <string id="30001">Descargar miniaturas de álbum desde theaudiodb.com</string> </strings> diff --git a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Tamil (India)/strings.xml b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Tamil (India)/strings.xml new file mode 100644 index 0000000000..2206e4558f --- /dev/null +++ b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Tamil (India)/strings.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Tamil (India) language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/ta_IN/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">ஆலà¯à®ªà®®à¯ கà¯à®°à¯à®ªà®Ÿà®™à¯à®•à®³à¯ˆ fanart.tv இரà¯à®¨à¯à®¤à¯ கைபà¯à®ªà®±à¯à®±à¯</string> + <string id="30001">ஆலà¯à®ªà®®à¯ கà¯à®°à¯à®ªà®Ÿà®™à¯à®•à®³à¯ˆ theaudiodb.com இரà¯à®¨à¯à®¤à¯ கைபà¯à®ªà®±à¯à®±à¯</string> +</strings> diff --git a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Turkish/strings.xml b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Turkish/strings.xml new file mode 100644 index 0000000000..683e8d52d8 --- /dev/null +++ b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Turkish/strings.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Turkish language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/tr/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">Albüm kapaklarını fanart.tv'den al</string> +</strings> diff --git a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Ukrainian/strings.xml b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Ukrainian/strings.xml new file mode 100644 index 0000000000..e0a757787f --- /dev/null +++ b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Ukrainian/strings.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Ukrainian language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/uk/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">Отримати малюнки альбому з fanart.tv</string> +</strings> diff --git a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Vietnamese/strings.xml b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Vietnamese/strings.xml new file mode 100644 index 0000000000..43f5a0c618 --- /dev/null +++ b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Vietnamese/strings.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Vietnamese language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/vi/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">Lấy hình đại diện album từ nguồn fanart.tv</string> +</strings> diff --git a/addons/metadata.musicvideos.theaudiodb.com/resources/language/Welsh/strings.xml b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Welsh/strings.xml new file mode 100644 index 0000000000..bcc3a8e13a --- /dev/null +++ b/addons/metadata.musicvideos.theaudiodb.com/resources/language/Welsh/strings.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Welsh language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/cy/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">Estyn lluniau bach album o fanart.tv</string> + <string id="30001">Estynnwch luniau bach albwm o theaudiodb.com</string> +</strings> diff --git a/addons/metadata.musicvideos.theaudiodb.com/resources/settings.xml b/addons/metadata.musicvideos.theaudiodb.com/resources/settings.xml index ea430f171c..fa23fe04ab 100644 --- a/addons/metadata.musicvideos.theaudiodb.com/resources/settings.xml +++ b/addons/metadata.musicvideos.theaudiodb.com/resources/settings.xml @@ -1,4 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> <settings> - <setting label="30000" type="bool" id="fanarttvalbumthumbs" default="true"/> + <setting label="30001" type="bool" id="tadbalbumthumbs" default="true"/> + <setting label="30000" type="bool" id="fanarttvalbumthumbs" default="false"/> </settings> diff --git a/addons/metadata.musicvideos.theaudiodb.com/tadb.xml b/addons/metadata.musicvideos.theaudiodb.com/tadb.xml index 2305e2d09b..100c0bd6fe 100644 --- a/addons/metadata.musicvideos.theaudiodb.com/tadb.xml +++ b/addons/metadata.musicvideos.theaudiodb.com/tadb.xml @@ -1,12 +1,26 @@ <?xml version="1.0" encoding="UTF-8"?> -<scraper framework="1.1" date="2012-06-10"> +<scraper framework="1.1" date="2013-04-03"> + <NfoUrl dest="3"> + <RegExp input="$$1" output="<url>http://www.theaudiodb.com/api/v1/json/58424d43204d6564696120/track.php?h=\1</url>" dest="3"> + <expression>http://www.theaudiodb.com/track/(.+)</expression> + </RegExp> + </NfoUrl> <CreateSearchUrl dest="3"> - <RegExp input="$$1" output="<url>http://www.theaudiodb.com/api/v1/json/58424d43204d6564696120/searchtrack.php?s=\1&t=\2</url>" dest="3"> - <expression trim="1,2">(.+)%20%20%20(.+)</expression> + <RegExp input="$$5" output="\1" dest="3"> + <RegExp input="$$1" output="<url>http://www.theaudiodb.com/api/v1/json/58424d43204d6564696120/searchtrack.php?s=\1&amp;t=\2</url>" dest="6"> + <expression trim="1,2">(.+)%20(?:%20|-)%20(.+)</expression> + </RegExp> + <RegExp input="$$6" output="\1" dest="5"> + <expression noclean="1" /> + </RegExp> + <RegExp input="$$6" output="<url>http://www.theaudiodb.com/api/v1/json/58424d43204d6564696120/searchtrack.php?s=$$1&amp;t=</url>" dest="5"> + <expression>^$</expression> + </RegExp> + <expression noclean="1" /> </RegExp> </CreateSearchUrl> <GetSearchResults dest="3"> - <RegExp input="$$5" output="<results>\1</results>" dest="3"> + <RegExp input="$$5" output="<results sorted="yes">\1</results>" dest="3"> <RegExp input="$$1" output="<entity><title>\5 - \3 [\4]</title><url cache="tadb-\1.json">http://www.theaudiodb.com/api/v1/json/58424d43204d6564696120/track.php?h=\1</url></entity>" dest="5"> <expression repeat="yes" clear="yes" fixchars="1" noclean="1">idTrack":"([^"]*)","idAlbum":"([^"]*).*?"strTrack":"([^"]*)","strAlbum":"([^"]*)","strArtist":"([^"]*)</expression> </RegExp> @@ -25,13 +39,25 @@ <expression fixchars="1" noclean="1">strAlbum":"([^"]*)"</expression> </RegExp> <RegExp input="$$1" output="<plot>\1</plot>" dest="5+"> - <expression fixchars="1" noclean="1">strDescription":"(.*?)","</expression> + <expression fixchars="1" noclean="1">strDescriptionEN":"(.*?)","</expression> + </RegExp> + <RegExp input="$$1" output="<director>\1</director>" dest="5+"> + <expression fixchars="1" noclean="1">strMusicVidDirector":"(.*?)","</expression> </RegExp> - <RegExp input="$$1" output="<genre>\1</genre>" dest="5+"> - <expression fixchars="1" noclean="1">strGenre":"([^"]*)"</expression> + <RegExp input="$$1" output="<studio>\1</studio>" dest="5+"> + <expression fixchars="1" noclean="1">strMusicVidCompany":"(.*?)","</expression> </RegExp> <RegExp input="$$1" output="<thumb>\1</thumb>" dest="5+"> - <expression fixchars="1" noclean="1">strTrackThumb":"([^"]*)"</expression> + <expression repeat="yes">strMusicVidScreen1\d?":"([^"]*)</expression> + </RegExp> + <RegExp input="$$1" output="<chain function="GetTADBAlbumGenresByMBID">\1</chain>" dest="5+"> + <expression fixchars="1" noclean="1">strMusicBrainzAlbumID":"([^"]*)"</expression> + </RegExp> + <RegExp input="$$1" output="<chain function="GetTADBAlbumDateByMBID">\1</chain>" dest="5+"> + <expression fixchars="1" noclean="1">strMusicBrainzAlbumID":"([^"]*)"</expression> + </RegExp> + <RegExp conditional="tadbalbumthumbs" input="$$1" output="<chain function="GetTADBAlbumThumbsByMBID">\1</chain>" dest="5+"> + <expression fixchars="1" noclean="1">strMusicBrainzAlbumID":"([^"]*)"</expression> </RegExp> <RegExp conditional="fanarttvalbumthumbs" input="$$1" output="<chain function="GetFanartTvAlbumThumbsByMBID">\1</chain>" dest="5+"> <expression fixchars="1" noclean="1">strMusicBrainzAlbumID":"([^"]*)"</expression> diff --git a/addons/metadata.themoviedb.org/addon.xml b/addons/metadata.themoviedb.org/addon.xml index 15568ca168..5130cce1b1 100644 --- a/addons/metadata.themoviedb.org/addon.xml +++ b/addons/metadata.themoviedb.org/addon.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon id="metadata.themoviedb.org" name="The Movie Database" - version="3.7.2" + version="3.7.3" provider-name="Team XBMC"> <requires> <import addon="xbmc.metadata" version="1.0"/> @@ -19,6 +19,7 @@ <summary lang="bg">Ð¡Ð²Ð°Ð»Ñ Ð¸Ð½Ñ„. за филми от TMDB</summary> <summary lang="ca">Arreplegador de pel·lÃcules TMDB</summary> <summary lang="cs">Zdroj zisku dat k filmům TMDB</summary> + <summary lang="cy">Crafwr Ffilmiau TMDB</summary> <summary lang="da">TMDB Scraper til Film</summary> <summary lang="de">Film Scraper für TheMovieDB</summary> <summary lang="el">Scraper Ταινιών του TMDb</summary> @@ -31,6 +32,7 @@ <summary lang="fr">Collecteur de Films TMDB</summary> <summary lang="gl">Scraper de Filme de TMDB</summary> <summary lang="he">TMDB סקרייפר סרטי×</summary> + <summary lang="hr">TMDB Oboogatite svoje Filmske Informacije</summary> <summary lang="hu">TMDB filmadat leolvasó</summary> <summary lang="it">Ricercatore per TMDB Movie</summary> <summary lang="ja">TMDBæ˜ ç”»ã®ã‚¹ã‚¯ãƒ¬ãƒ¼ãƒ‘ー</summary> @@ -38,7 +40,9 @@ <summary lang="lt">TMDB Filmų Scraper</summary> <summary lang="mk">TMDB инфо за филмови</summary> <summary lang="ml">മൂവി à´¡à´¿ ബി, വിവരശേഖരം</summary> + <summary lang="my">TMDB Movie Scraper</summary> <summary lang="nl">TMDb-filmscraper</summary> + <summary lang="no">TMDb filminformasjon</summary> <summary lang="pl">Scraper filmowy TMDB</summary> <summary lang="pt">Scraper de filmes TMDb</summary> <summary lang="pt_BR">Scraper de Filmes TMDb</summary> @@ -48,13 +52,17 @@ <summary lang="sk">TheMovieDB filmový sÅ¥ahovaÄ</summary> <summary lang="sl">Ponudnik informacij o filmih TMDB</summary> <summary lang="sv">TMDB Filmskrapa</summary> + <summary lang="ta_IN">LastFM நிகழà¯à®ªà®Ÿà®®à¯ சà¯à®°à®£à¯à®Ÿà®¿</summary> <summary lang="th">ตัวรับข้à¸à¸¡à¸¹à¸¥à¸ าพยนต์ TMDB</summary> + <summary lang="vi">Trình lấy dữ liệu Phim từ TMDB</summary> <summary lang="zh">TMDB电影刮削器</summary> + <summary lang="zh_TW">TMDB 電影æœæ‹¬å™¨</summary> <description lang="af">themoviedb.org is 'n verniet en oop fliek databasis. Dit is totaal gebruiker gedryf deur mense soos jy. TMDB word huidiglik deur miljoene mense elke maand gebruik, en met hulle kragtige API word dit ook deur baie gewilde media sentrums soos XBMC gebruik om Fliek Metadata, Plakkate en Ondersteunerkuns te onttrek om die gebruiker se ondervinding te verryk.</description> <description lang="be">themoviedb.org is a free and open movie database. It's completely user driven by people like you. TMDb is currently used by millions of people every month and with their powerful API, it is also used by many popular media centers like XBMC to retrieve Movie Metadata, Posters and Fanart to enrich the user's experience.</description> <description lang="bg">themoviedb.org е безплатна и отворена база от данни за филми. Задвижва Ñе изцÑло от потребителите Ñи - хора като ваÑ. Милиони хора по Ñвета вÑеки меÑец ползват TMDb, благодарение на многофункционалното API. Едновременно Ñ Ñ‚Ð¾Ð²Ð° е и източник на Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° медийни центрове, като XBMC, които извличат Ð¼ÐµÑ‚Ð°Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° филми, поÑтери и Fanart.</description> <description lang="ca">themoviedb.org és una base de dades oberta i lliure. Es manté completament per usuaris, per gent com tu. TMDb s'utilitza actualment per milions de persones cada mes i amb la seva potent API també és utilitzada per molts centre media populas com l'XBMC per obtenir les meta-dades de pel·lÃcules, pósters i fanart per enriquir l'experiència d'usuari.</description> <description lang="cs">themoviedb.org je otevÅ™ená a svobodná databáze filmů. Je Å™Ãzena uživateli, tedy lidmi jako vy. TMDB je každý mÄ›sÃc použÃvána milióny lidà a se svým výborným API je také použÃvano mnoha populárnÃmi mediálnÃmi centry jako je XBMC, k zÃskávánà metadat, plagátů a fanartu filmů pro obohacenà uživatelského zážitku.</description> + <description lang="cy">Mae themoviedb.org yn gronfa ddata ffilmiau rhydd ac agored. Mae'n cael ei yrru gan ddefnyddwyr fel chi. Mae TMDb yn cael ei ddefnyddio gan filiynau o bobl bob mis a gyda'i API pwerus, mae'n cael ei ddefnyddio gan lawer o'r canolfannau cyfrwng fel XBMC i estyn metadata ffilmiau, posteri a chelf er mwyn cyfoethogi profiad defnyddwyr.</description> <description lang="da">themoviedb.org er en fri og Ã¥ben filmdatabase. Den er helt og aldeles brugerdrevet af folk som dig. TMDb bruges i dag af millioner af mennesker hver mÃ¥ned, og med deres kraftfulde API er den ogsÃ¥ brugt af mange populære mediecentre sÃ¥som XBMC til at hente metadata, plakater og fankunst til film, for at berige brugerens oplevelse.</description> <description lang="de">TheMovieDB.org ist eine freie und offene Filmdatenbank. Sie wird von Benutzern wie Dir betrieben. TheMovieDB wird zur Zeit monatlich von Millionen genutzt. Mit der mächtigen API wird sie auch von vielen Media-Center, wie z.B. XBMC, genutzt um Film Metadaten, Poster und Fanarts zu beziehen, damit der Benutzer sein Media-Center verschönern kann.</description> <description lang="el">Το themoviedb.org είναι μία δωÏεάν και ανοικτή βάση δεδομÎνων ταινιών. ΔιαχειÏίζεται πλήÏως από ανθÏώπους σαν και εσάς. Το TMDb χÏησιμοποιείται από εκατομμÏÏια ανθÏώπους κάθε μήνα, και με το πανίσχυÏο API τους, χÏησιμοποιείται και από πολλά δημοφιλή κÎντÏα πολυμÎσων όπως το XBMC για να λαμβάνουν μετα-δεδομÎνα Ταινιών, Αφίσες και Fanart για εμπλουτισμό της εμπειÏίας του χÏήστη.</description> @@ -67,6 +75,7 @@ <description lang="fr">themoviedb.org est une base de données gratuite et libre d'accès de films. Elle est totalement gérée par les utilisateurs. TMDb est actuellement utilisée par des millions de personnes chaque mois et, grâce à ses puissantes fonctions et routines, elle est également utilisée par de nombreux Media Centers populaires comme XBMC aux fins de récupération des Métadonnées, Posters et Fanarts des films en vue d'améliorer l'expérience de l'utilisateur.</description> <description lang="gl">themoviedb.org é una base de datos sobre filmes libre e aberta, impulsada por xente coma ti. Na actualidade TMDb é usada por millóns de persoas todos os meses, e grazas ó seu potente API, usado por algúns dos centros multimedia máis populares como XBMC para obter a información dos filmes, Posters e Fanart e asà mellorar a experiencia do usuario.</description> <description lang="he">themoviedb.org is a free and open movie database. It's completely user driven by people like you. TMDb is currently used by millions of people every month and with their powerful API, it is also used by many popular media centers like XBMC to retrieve Movie Metadata, Posters and Fanart to enrich the user's experience.</description> + <description lang="hr">themoviedb.org je besplatna i open surce baza podataka za Filmske informacije. TMDb trenutno koriste milijuni ljudi svaki mjesec, on se takoÄ‘er koristi od strane mnogih popularnih medijskih centara poput XBMC.Besplatno dohvatite Filmske metapodatake, plakate i Fanart-ove. Obogatiti si korisniÄko iskustvo.</description> <description lang="hu">A themoviedb.org egy ingyenes és nyÃlt filmadatbázis. Teljes egészében olyan felhasználók töltik fel, mint például Te. A TMDb-t havonta emberek milliói használják és a hatékony API-n keresztül számos népszerű média center is, mint például az XBMC a filmadatok, poszterek, fanartképek letöltésére.</description> <description lang="it">themoviedb.org è un database libero e aperto. E' gestito da utenti e persone come te. Viene usato correntemente da millioni di persone ogni mese e con le sue potenti API, è anche utilizzato da molti popolari media centers come XBMC per ottenere Metadati, Posters e Fanart di film per arricchire la loro esperienza utente.</description> <description lang="ja">themoviedb.org ã¯è‡ªç”±ã§ã‚ªãƒ¼ãƒ—ンãªæ˜ 画データベースã§ã™ã€‚ãã®é‹å–¶ã¯ã€å®Œå…¨ã«ãƒ¦ãƒ¼ã‚¶ä¸»å°Žã§è¡Œã‚ã‚Œã¦ã„ã¾ã™ã€‚TMDb ã¯ç¾åœ¨æ¯Žæœˆä½•ç™¾ä¸‡äººã‚‚ã®äººã«åˆ©ç”¨ã•ã‚Œã¦ã„ã‚‹ã»ã‹ã€XBMC ã®ã‚ˆã†ãªãƒ¡ãƒ‡ã‚£ã‚¢ã‚»ãƒ³ã‚¿ãƒ¼ã‚‚ã€TMDb ã®ãƒ‘ワフル㪠API を介ã—ã¦æ˜ 画メタデータã€ãƒã‚¹ã‚¿ãƒ¼ã€ãƒ•ã‚¡ãƒ³ã‚¢ãƒ¼ãƒˆã‚’å–å¾—ã—ã€ä½¿ã„å‹æ‰‹ã‚’å‘上ã•ã›ã‚‹ãªã©ã—ã¦ä½¿ã£ã¦ã„ã¾ã™ã€‚</description> @@ -75,6 +84,7 @@ <description lang="mk">themoviedb.org is a free and open movie database. It's completely user driven by people like you. TMDb is currently used by millions of people every month and with their powerful API, it is also used by many popular media centers like XBMC to retrieve Movie Metadata, Posters and Fanart to enrich the user's experience.</description> <description lang="ml">മൂവി à´¡à´¿ ബി, à´Žà´²àµà´²à´¾à´µàµ¼à´•àµà´•àµà´‚ കൈവകàµà´•à´¾à´µàµà´¨àµà´¨ ഒരൠസൗജനàµà´¯ വിവരശേഖരമാണàµ. ഇതàµà´®àµ‚ലം ലോകം à´®àµà´´àµà´µà´¨àµà´‚ സിനിമാ പോസàµà´±àµà´±à´±àµà´•àµ¾ à´Žà´²àµà´²à´µà´°àµà´‚ കാണàµà´¨àµà´¨àµ</description> <description lang="nl">Themoviedb.org is een vrije en open filmdatabank. Gebruikers zoals jij vormen de motor van deze site. Op dit moment gebruiken elke maand miljoenen mensen TMDb. De krachtige API van de site laat mediacenters zoals XBMC toe om metadata, posters en fanart op te halen en zo de gebruikerservaring te verrijken.</description> + <description lang="no">themoviedb.org er en gratis og Ã¥pen filmdatabase. Den drives helt og fullt av mennesker som deg. TMDb brukes av millioner av mennesker hver mÃ¥ned og med sitt gode API, brukes den ogsÃ¥ av mange popluære mediasenterløsninger som XBMC for Ã¥ hente metadata for filmer, plakater og fanart for Ã¥ gi en bedre brukeropplevelse.</description> <description lang="pl">themoviedb.org jest wolnÄ… i otwartÄ… filmowÄ… bazÄ… danych. Jest zarzÄ…dzana caÅ‚kowicie przez osoby takie jak Ty. Obecnie odwiedzajÄ… jÄ… miliony osób miesiÄ™cznie, a dziÄ™ki dostÄ™pnoÅ›ci API jest używana w wielu media center, takich jak XBMC, do pobierania informacji o filmach, plakatów i fanartów.</description> <description lang="pt">O themoviedb.org é uma base de dados de filmes livre e aberta. É actualizado inteiramente por pessoas como você e usado por milhões todos os meses. Com o poderoso motor de busca disponÃvel, também se tornou no favorito para muitos programas de centro de média, como o popular XBMC, para obter informação, posters e fanart que enriquecem a experiência do utilizador.</description> <description lang="pt_BR">O themoviedb.org é um banco de dados aberto e gratuito. É completamente operado por pessoas como você. O TMDb é atualmente usado por milhares de pessoas a cada mês e com sua poderosa API, é usado por muitas centrais de mÃdia populares como o XBMC para buscar metadados, cartazes e fanart de filmes para enriquecer a experiência do usuário.</description> @@ -84,8 +94,12 @@ <description lang="sk">themoviedb.org je voľná a otvorená databáza filmov. Je výluÄne vedená užÃvateľmi ako si ty. TMDb je každý mesiac použÃvaná miliónmi ľudÃ, a vÄaka svojmu výkonnému API je veľmi populárna medzi 'media centrami' ako XBMC pre sÅ¥ahovanie filmových metadát, plagátov a fanartov pre obohatenie zážitkov.</description> <description lang="sl">themoviedb.org je brezplaÄna in prosta baza filmov. Je v celoti ustvarjena s strani uporabnikov kot ste vi. TMDB uporablja miljone ljudi in z njihovo moÄno API, jo lahko uporabljate tudi v multimedijskih centrih kot XBMC, s tem prenesete informacije o filmih, plakate in ozadja ter s tem popestrite uporabniÅ¡ko izkuÅ¡njo.</description> <description lang="sv">themoviedb.org är en gratis och öppen filmdatabas. Den drivs helt av människor som du. TMDb används för närvarande av miljoner människor varje mÃ¥nad och med deras kraftfulla API används den även av mÃ¥nga populära mediacenter som t.ex. XBMC för att hämta metadata om filmer, affischer och fanart för att berika användarens upplevelse.</description> + <description lang="ta_IN">themoviedb.org ஒர௠இலவச மறà¯à®±à¯à®®à¯ திறநà¯à®¤ திரைபà¯à®ªà®Ÿ தரவà¯à®¤à¯à®¤à®³à®®à¯ ஆகà¯à®®à¯. இநà¯à®¤ தரவà¯à®¤à¯à®¤à®³à®®à¯ à®®à¯à®±à¯à®±à®¿à®²à¯à®®à¯ பயனர௠மகà¯à®•à®³à®¾à®²à¯ இயகà¯à®•à®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯. TMDb அவரà¯à®•à®³à®¤à¯ சகà¯à®¤à®¿à®µà®¾à®¯à¯à®¨à¯à®¤ API இனால௠தறà¯à®ªà¯‡à®¾à®¤à¯ பல இலடà¯à®šà®•à¯à®•à®£à®•à¯à®•à®¾à®© மகà¯à®•à®³à®¾à®²à¯ ஒவà¯à®µà¯†à®¾à®°à¯ மாதமà¯à®®à¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯, இத௠XBMC போனà¯à®± பல பிரபல ஊடக மையஙà¯à®•à®³à®¿à®²à¯ பயனர௠அனà¯à®ªà®µà®¤à¯à®¤à¯ˆ மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯.</description> <description lang="th">themoviedb.org เป็นà¸à¸²à¸™à¸‚้à¸à¸¡à¸¹à¸¥à¸ าพยนตร์ที่ฟรีà¹à¸¥à¸°à¹€à¸›à¸´à¸”à¸à¸§à¹‰à¸²à¸‡. มันถูà¸à¸‚ับเคลื่à¸à¸™à¸ˆà¸²à¸à¸œà¸¹à¹‰à¹ƒà¸Šà¹‰ โดยคนเช่นคุณ. TMDb ปัจจุบันมีà¸à¸²à¸£à¹ƒà¸Šà¹‰à¹‚ดยคนนับล้านในà¹à¸•à¹ˆà¸¥à¸°à¹€à¸”ืà¸à¸™ à¹à¸¥à¸°à¸¡à¸µà¸›à¸£à¸°à¸ªà¸´à¸—ธิภาพด้วย API ขà¸à¸‡à¸žà¸§à¸à¹€à¸‚า , มันยังถูà¸à¹ƒà¸Šà¹‰à¹‚ดยหลายศูนย์สื่à¸à¸—ี่นิยมเช่น XBMC เพื่à¸à¸”ึง à¸à¸˜à¸´à¸šà¸²à¸¢à¸‚้à¸à¸¡à¸¹à¸¥à¸ าพยนตร์, โปสเตà¸à¸£à¹Œà¹à¸¥à¸° à¹à¸Ÿà¸™à¸à¸²à¸£à¹Œà¸• เพื่à¸à¹€à¸žà¸´à¹ˆà¸¡à¸›à¸£à¸°à¸ªà¸šà¸à¸²à¸£à¸“์ขà¸à¸‡à¸œà¸¹à¹‰à¹ƒà¸Šà¹‰</description> + <description lang="uk">themoviedb.org - це безкоштовна Ñ– відкрита база даних фільмів. Вона повніÑÑ‚ÑŽ підтримуєтьÑÑ Ð·Ð²Ð¸Ñ‡Ð°Ð¹Ð½Ð¸Ð¼Ð¸ людьми. Ð’ даний момент Ñайт TMDb викориÑтовують мільйони людей кожен міÑÑць, Ñ– завдÑки потужному API, його можуть викориÑтовувати різні популÑрні медіацентри, такі Ñк XBMC, щоб отримувати метадані, поÑтери Ñ– фанарт Ð´Ð»Ñ Ñ„Ñ–Ð»ÑŒÐ¼Ñ–Ð² з метою Ð¾Ñ„Ð¾Ñ€Ð¼Ð»ÐµÐ½Ð½Ñ Ñ–Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñу.</description> + <description lang="vi">themoviedb.org là cÆ¡ sở dữ liệu vá» phim ảnh mở và miá»…n phÃ. Nó hoà n toà n được kiểm soát bởi những ngÆ°á»i nhÆ° bạn. TMDb hiện tại Ä‘ang được sá» dụng bởi hà ng triệu ngÆ°á»i dùng hà ng tháng và vá»›i sá»± há»— trợ của bá»™ API mạnh mẽ nó cÅ©ng được sá» dụng bởi những thiết bị giải trà cá nhân nhÆ° XBMC cho việc lấy dữ liệu vá» Phim ảnh, Poster và Fanart để là m tăng trải nghiệm của ngÆ°á»i sá» dụng</description> <description lang="zh">themoviedb.org是一个开放和自由的电影数æ®åº“ã€‚å®ƒå®Œå…¨ç”±è±¡ä½ ä¸€æ ·çš„ç”¨æˆ·æ¥æŽŒæŽ§ã€‚TMDbæ¯æœˆä¸ºä¸Šç™¾ä¸‡ç”¨æˆ·æä¾›æœåŠ¡ï¼Œå¹¶é€šè¿‡å¼ºå¤§çš„APIç•Œé¢ä¸ºè®¸å¤šæµè¡Œçš„媒体ä¸å¿ƒç³»ç»Ÿå¦‚XBMCæ供电影资料ã€å°é¢æµ·æŠ¥å’ŒåŒäººç”»ä»¥ä¸°å¯Œç”¨æˆ·çš„体验。</description> + <description lang="zh_TW">themoviedb.org是一個å…費和開放的電影資料庫。它是完全由與您一樣的廣大使用者來更新資訊。 TMDbç›®å‰æ“有數以百è¬è¨ˆçš„使用人次並且有著強大的API,許多å—æ¡è¿Žçš„媒體ä¸å¿ƒå¹³å°åƒXBMC藉由TMDbç²å–é›»å½±çš„æ•¸æ“šè³‡æ–™åº«ï¼Œæµ·å ±å’Œå½±ç‰‡è³‡è¨Šï¼Œä»¥è±å¯Œä½¿ç”¨è€…體驗。</description> <platform>all</platform> </extension> </addon> diff --git a/addons/metadata.themoviedb.org/changelog.txt b/addons/metadata.themoviedb.org/changelog.txt index c242425df3..63196789f7 100644 --- a/addons/metadata.themoviedb.org/changelog.txt +++ b/addons/metadata.themoviedb.org/changelog.txt @@ -1,3 +1,6 @@ +[B]3.7.3[/B] +- updated language files from Transifex + [B]3.7.2[/B] - updated language files from Transifex diff --git a/addons/metadata.themoviedb.org/resources/language/Albanian/strings.xml b/addons/metadata.themoviedb.org/resources/language/Albanian/strings.xml new file mode 100644 index 0000000000..e960a5db1f --- /dev/null +++ b/addons/metadata.themoviedb.org/resources/language/Albanian/strings.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Albanian language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/sq/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">Aktivo "Fanart'in"</string> +</strings> diff --git a/addons/metadata.themoviedb.org/resources/language/Amharic/strings.xml b/addons/metadata.themoviedb.org/resources/language/Amharic/strings.xml new file mode 100644 index 0000000000..0160016ea5 --- /dev/null +++ b/addons/metadata.themoviedb.org/resources/language/Amharic/strings.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Amharic language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/am/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30002">የተመረጠዠቋንቋ</string> + <string id="30003">ደረጃ á‹«áŒáŠ™ ከ </string> + <string id="30005">ዋናá‹áŠ• አáˆáŠ¥áˆµá‰µ ጠብቅ </string> + <string id="30006">የተመረጠዠየáˆáˆµáŠáˆ ወረቀት አገሠ</string> +</strings> diff --git a/addons/metadata.themoviedb.org/resources/language/Basque/strings.xml b/addons/metadata.themoviedb.org/resources/language/Basque/strings.xml new file mode 100644 index 0000000000..a1048de9d1 --- /dev/null +++ b/addons/metadata.themoviedb.org/resources/language/Basque/strings.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Basque language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/eu/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">Gaitu Fanarta</string> +</strings> diff --git a/addons/metadata.themoviedb.org/resources/language/Burmese/strings.xml b/addons/metadata.themoviedb.org/resources/language/Burmese/strings.xml new file mode 100644 index 0000000000..164c51a429 --- /dev/null +++ b/addons/metadata.themoviedb.org/resources/language/Burmese/strings.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Burmese language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/my/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">Enable Fanart</string> + <string id="30001">HD-Trailers.net မှသင့်လျှော်သော ကြော်ငြာ</string> + <string id="30002">သင့်လျှော်သော ဘာသာစကား</string> + <string id="30004">ကြော်ငြာများရယူမည်(You Tube)</string> + <string id="30005">မူလá€á€±á€«á€„်းစဉ်အá€á€á€¯á€„်းထားမည်</string> +</strings> diff --git a/addons/metadata.themoviedb.org/resources/language/Chinese (Traditional)/strings.xml b/addons/metadata.themoviedb.org/resources/language/Chinese (Traditional)/strings.xml index 84f20c29af..0fa9678c2f 100644 --- a/addons/metadata.themoviedb.org/resources/language/Chinese (Traditional)/strings.xml +++ b/addons/metadata.themoviedb.org/resources/language/Chinese (Traditional)/strings.xml @@ -5,4 +5,10 @@ <strings> <string id="30000">啟用 Fanart</string> + <string id="30001">å好從HD-Trailers.netå–å¾—é 告片</string> + <string id="30002">å好的語言</string> + <string id="30003">從...å–得評價</string> + <string id="30004">啟用é 告片 (YouTube)</string> + <string id="30005">ä¿ç•™åŽŸå§‹æ¨™é¡Œ</string> + <string id="30006">å好的èªè‰åœ‹å®¶</string> </strings> diff --git a/addons/metadata.themoviedb.org/resources/language/Croatian/strings.xml b/addons/metadata.themoviedb.org/resources/language/Croatian/strings.xml new file mode 100644 index 0000000000..0427392b8c --- /dev/null +++ b/addons/metadata.themoviedb.org/resources/language/Croatian/strings.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Croatian language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/hr/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">Omogući "Fanart"</string> + <string id="30001">Preferiraj Najave filmova kroz HD-Trailers.net</string> + <string id="30002">Preferirani Jezik</string> + <string id="30003">Nabavite ocijene od</string> + <string id="30004">Omogući Najave (YouTube)</string> + <string id="30005">Zadržite izvorni naslov</string> + <string id="30006">Preferiraj Cerfikate Država</string> +</strings> diff --git a/addons/metadata.themoviedb.org/resources/language/Finnish/strings.xml b/addons/metadata.themoviedb.org/resources/language/Finnish/strings.xml index ab425a5364..e9fae2fe82 100644 --- a/addons/metadata.themoviedb.org/resources/language/Finnish/strings.xml +++ b/addons/metadata.themoviedb.org/resources/language/Finnish/strings.xml @@ -1,9 +1,8 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Finnish language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/fi/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + <strings> <string id="30000">Fanitaide käytössä</string> - <string id="30004">Trailerit käytössä</string> - <string id="30001">Valitse ensisijaisesti trailerit HD-Trailers.net -sivustolta</string> - <string id="30002">Ensisijainen kieli</string> - <string id="30003">Hae arvosana IMDb:stä</string> - <string id="30005">Näytä alkuperäinen nimi</string> </strings> diff --git a/addons/metadata.themoviedb.org/resources/language/Malay/strings.xml b/addons/metadata.themoviedb.org/resources/language/Malay/strings.xml new file mode 100644 index 0000000000..dffdc26135 --- /dev/null +++ b/addons/metadata.themoviedb.org/resources/language/Malay/strings.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Malay language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/ms/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">Membolehkan Fanart</string> +</strings> diff --git a/addons/metadata.themoviedb.org/resources/language/Norwegian/strings.xml b/addons/metadata.themoviedb.org/resources/language/Norwegian/strings.xml index 82168519e4..65d6c81283 100644 --- a/addons/metadata.themoviedb.org/resources/language/Norwegian/strings.xml +++ b/addons/metadata.themoviedb.org/resources/language/Norwegian/strings.xml @@ -4,9 +4,11 @@ <!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> <strings> + <string id="30000">Hent fanart</string> <string id="30001">Foretrekk trailer fra HD-Trailers.net</string> <string id="30002">Foretrukket sprÃ¥k</string> <string id="30003">Hent rangering fra</string> <string id="30004">Aktive trailer (YouTube)</string> <string id="30005">Bruk originaltittel</string> + <string id="30006">Foretrukket land for aldersgrense</string> </strings> diff --git a/addons/metadata.themoviedb.org/resources/language/Polish/strings.xml b/addons/metadata.themoviedb.org/resources/language/Polish/strings.xml index 8044cf8f90..bdf08701bf 100644 --- a/addons/metadata.themoviedb.org/resources/language/Polish/strings.xml +++ b/addons/metadata.themoviedb.org/resources/language/Polish/strings.xml @@ -10,5 +10,5 @@ <string id="30003">Pobierz ocenÄ™ z</string> <string id="30004">WÅ‚Ä…cz zwiastuny (YouTube)</string> <string id="30005">Zachowaj oryginalny tytuÅ‚</string> - <string id="30006">Prefeowany kraj certyfikacji</string> + <string id="30006">Preferowany kraj certyfikacji</string> </strings> diff --git a/addons/metadata.themoviedb.org/resources/language/Tamil (India)/strings.xml b/addons/metadata.themoviedb.org/resources/language/Tamil (India)/strings.xml new file mode 100644 index 0000000000..bd2db7938f --- /dev/null +++ b/addons/metadata.themoviedb.org/resources/language/Tamil (India)/strings.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Tamil (India) language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/ta_IN/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">விசிறிபடதà¯à®¤à¯ˆ காணà¯à®ªà®¿</string> + <string id="30001">HD-Trailers.net இரà¯à®¨à¯à®¤à¯ வரà¯à®®à¯ டிரெயà¯à®²à®°à¯à®•à®³à¯ˆ விரà¯à®®à¯à®ªà¯</string> + <string id="30002">விரà¯à®®à¯à®ªà®¿à®¯ மொழி</string> + <string id="30003">தரதà¯à®¤à¯ˆ கைபà¯à®ªà®±à¯à®±à¯</string> + <string id="30004">டிரெயà¯à®²à®°à¯ செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤ (YouTube)</string> + <string id="30005">அசல௠தலைபà¯à®ªà¯ˆ வைகà¯à®•</string> + <string id="30006">விரà¯à®ªà¯à®ªà®®à®¾à®© சானà¯à®±à®¿à®¤à®´à¯ நாடà¯</string> +</strings> diff --git a/addons/metadata.themoviedb.org/resources/language/Turkish/strings.xml b/addons/metadata.themoviedb.org/resources/language/Turkish/strings.xml index f30e711c24..85703d1b83 100644 --- a/addons/metadata.themoviedb.org/resources/language/Turkish/strings.xml +++ b/addons/metadata.themoviedb.org/resources/language/Turkish/strings.xml @@ -4,6 +4,7 @@ <!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> <strings> + <string id="30000">Fanart EtkinleÅŸtir</string> <string id="30002">Tercih Edilen Dil</string> <string id="30004">Fragmanı EtkinleÅŸtir (YouTube)</string> <string id="30005">Özgün BaÅŸlığı Koru</string> diff --git a/addons/metadata.themoviedb.org/resources/language/Ukrainian/strings.xml b/addons/metadata.themoviedb.org/resources/language/Ukrainian/strings.xml new file mode 100644 index 0000000000..468a24576e --- /dev/null +++ b/addons/metadata.themoviedb.org/resources/language/Ukrainian/strings.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Ukrainian language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/uk/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">Завантажувати фанарт</string> + <string id="30002">Вибір мови</string> + <string id="30003">Отримати рейтинг з</string> +</strings> diff --git a/addons/metadata.themoviedb.org/resources/language/Uzbek/strings.xml b/addons/metadata.themoviedb.org/resources/language/Uzbek/strings.xml new file mode 100644 index 0000000000..8051b4cac5 --- /dev/null +++ b/addons/metadata.themoviedb.org/resources/language/Uzbek/strings.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Uzbek language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/uz/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30002">Afzal til</string> +</strings> diff --git a/addons/metadata.themoviedb.org/resources/language/Vietnamese/strings.xml b/addons/metadata.themoviedb.org/resources/language/Vietnamese/strings.xml new file mode 100644 index 0000000000..c99544f1ae --- /dev/null +++ b/addons/metadata.themoviedb.org/resources/language/Vietnamese/strings.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Vietnamese language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/vi/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">Sá» dụng Fanart</string> + <string id="30001">Ưu tiên Phim giá»›i thiệu từ HD-Trailers.net</string> + <string id="30002">Ưu tiên ngôn ngữ</string> + <string id="30003">Lấy Äánh giá từ</string> + <string id="30004">Sá» dụng Phim giá»›i thiệu (YouTube)</string> + <string id="30005">Giữ nguyên tên phim gốc</string> + <string id="30006">Ưu tiên chứng chỉ của quốc gia</string> +</strings> diff --git a/addons/metadata.themoviedb.org/resources/language/Welsh/strings.xml b/addons/metadata.themoviedb.org/resources/language/Welsh/strings.xml new file mode 100644 index 0000000000..28d08f8184 --- /dev/null +++ b/addons/metadata.themoviedb.org/resources/language/Welsh/strings.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Welsh language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/cy/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">Galluogi Celf</string> + <string id="30001">Dewis Cyflwyniadau o HD-Trailers.net</string> + <string id="30002">Dewis Iaith</string> + <string id="30003">Graddio gan</string> + <string id="30004">Galluogi Cyflwyniadau (YouTube)</string> + <string id="30005">Cadw'r Teitl Gwreiddiol</string> + <string id="30006">Gwlad Tysytysgrifo Dewisol</string> +</strings> diff --git a/addons/metadata.tvdb.com/addon.xml b/addons/metadata.tvdb.com/addon.xml index 4e0bcb7bdd..80db092cb4 100644 --- a/addons/metadata.tvdb.com/addon.xml +++ b/addons/metadata.tvdb.com/addon.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon id="metadata.tvdb.com" name="The TVDB" - version="1.4.5" + version="1.5.4" provider-name="Team XBMC"> <requires> - <import addon="xbmc.metadata" version="1.0"/> + <import addon="xbmc.metadata" version="2.1.0"/> </requires> <extension point="xbmc.metadata.scraper.tvshows" language="multi" @@ -15,6 +15,7 @@ <summary lang="be">Fetch TV show metadata from TheTVDB.com</summary> <summary lang="bg">Ð˜Ð·Ñ‚ÐµÐ³Ð»Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° ТВ Сериали от TheTVDB.com</summary> <summary lang="cs">ZÃskat metadata televiznÃho poÅ™adu z TheTVDB.com</summary> + <summary lang="cy">Estyn metadata sioeau Teledu o TheTVDB.com</summary> <summary lang="da">Hent metadata til TV-serier fra TheTVDB.com</summary> <summary lang="de">Scraper für Fernsehserien von TheTVDB.com</summary> <summary lang="el">Λήψη μετα-δεδομÎνων σειÏών από το TVDB.com</summary> @@ -22,10 +23,12 @@ <summary lang="es">Recuperar metadatos de series de TV en TheTVDB.com</summary> <summary lang="es_AR">Recuperar metadatos de series de TV en TheTVDB.com</summary> <summary lang="es_MX">Obtener metadata de Series desde TheTVDB.com</summary> + <summary lang="et">Hangi tv seriaalide metainfo TheTVDB.com-ist</summary> <summary lang="fi">Nouda TV-ohjelmien tietoja TheTVDB.com -sivustolta</summary> <summary lang="fr">Collecter les métadonnées des séries TV depuis TheTVDB.com</summary> <summary lang="gl">Obter os metadatos das series de TV dende TheTVDB.com</summary> <summary lang="he">×”×‘× ×ž×™×“×¢ </summary> + <summary lang="hr">Dohvati podatke za TV serije sa TheTVDB.com</summary> <summary lang="hu">TV műsor információk a TheTVDB.com-ról</summary> <summary lang="is">Sækja Sjónvarpsþátta lýsigögn frá TheTVDB.com</summary> <summary lang="it">Scarica informazioni programma TV da TheTVDB.com</summary> @@ -33,7 +36,10 @@ <summary lang="ko">TheTVDB.com ì—ì„œ TV 쇼 ì •ë³´ ê°€ì ¸ì˜¤ê¸°</summary> <summary lang="lt">Parsiųsti TV Å¡ou (serialo) metaduomenis iÅ¡ TheTVDB.com</summary> <summary lang="mk">Превземи ТВ шоу метаподаток од TVDB.com</summary> + <summary lang="ms">Ambil metadata rancangan TV dari TheTVDB.com</summary> + <summary lang="my">TV show နှင့်ပá€á€ºá€žá€€á€ºá€žá€Šá€·á€º အá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸á€€á€á€¯ TheTVDB.com မှ ရယူရန်</summary> <summary lang="nl">Seriemetadata ophalen van TheTVDB.com</summary> + <summary lang="no">Hent TV program data fra TheTVDB.com</summary> <summary lang="pl">Pobieraj dane o serialach TV z TheTVDB.com</summary> <summary lang="pt">Obtenha dados para séries TV de TVDB.com</summary> <summary lang="pt_BR">Obtenha dados dos seriados do TheTVDB.com</summary> @@ -42,15 +48,20 @@ <summary lang="se">Skrapa för TV-seriemetadata frÃ¥n TVDB.com</summary> <summary lang="sk">ZÃskaÅ¥ metadáta o televÃznej relácii zo stránky TheTVDB.com</summary> <summary lang="sl">Prenesite informacije o TV serijah z TheTVDB.com</summary> + <summary lang="sq">Merr "metadata" mbi TV serialet nga TheTVDB.com</summary> <summary lang="sv">Hämta TV-seriemetadata frÃ¥n TVDB.com</summary> + <summary lang="ta_IN">TheTVDB.com இரà¯à®¨à¯à®¤à¯ தொலைகà¯à®•à®¾à®Ÿà¯à®šà®¿ நிகழà¯à®šà¯à®šà®¿ மெடà¯à®Ÿà®¾à®Ÿà¯‡à®Ÿà¯à®Ÿà®¾ எடà¯à®•à¯à®•à®ªà®Ÿà¯à®•à®¿à®©à¯à®±à®¤à¯</summary> <summary lang="th">เรียà¸à¸‚้à¸à¸¡à¸¹à¸¥à¸«à¸¥à¸±à¸à¸‚à¸à¸‡à¸£à¸²à¸¢à¸à¸²à¸£à¸—ีวี จาภTheTVDB.com</summary> + <summary lang="tr">TV programı meta verilerini TheTVDB.com'dan al</summary> <summary lang="uk">ÐžÑ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ð¾Ð¼Ð¾Ñтей про Ñеріали із TheTVDB.com</summary> + <summary lang="vi">Trình lấy TV show từ TheTVDB.com</summary> <summary lang="zh">从TheTVDB.com获å–电视剧集信æ¯</summary> <summary lang="zh_TW">從 TheTVDB.com å–得電視節目資訊</summary> <description lang="af">TheTVDB.com is 'n TV Skraper. Die werf is 'n massiewe oop databasis wat deur enige iemand verander kan word en bevat vol meta data vir baie vertonings in verskillende tale. Alle inhoud en prente op die werf is bygedra deur sy gebruikers vir sy gebruikers en het 'n hoë standaard van kwaliteit. Die databasis skema en webruimte is oopbron onder die GPL.</description> <description lang="be">TheTVDB.com is a TV Scraper. The site is a massive open database that can be modified by anybody and contains full meta data for many shows in different languages. All content and images on the site have been contributed by their users for users and have a high standard or quality. The database schema and website are open source under the GPL.</description> <description lang="bg">TheTVDB.com предоÑÑ‚Ð°Ð²Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° ТВ Сериали. Сайтът предÑтавлÑва една огромна, безплатна и отворена база от данни. Ð’Ñеки може да редактира (наличната информациÑ) или да Ð´Ð¾Ð±Ð°Ð²Ñ Ð½Ð¾Ð²Ð°. Съдържа подробни данни за много Ñериали и на различни езици. ЦÑлото Ñъдържание на Ñайта и публикуваните Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ñа предоÑтавени от потребители за потребителите. Съдържанието на Ñайтът и базата от данни е Ñ Ð¾Ñ‚Ð²Ð¾Ñ€ÐµÐ½ код под лиценза GPL.</description> <description lang="cs">TheTVDB.com je zdroj metadat pro televiznà poÅ™ady. Stránka je masivnà otevÅ™ená databáze, kterou může kdokoliv upravovat a obsahuje veÅ¡kerá metadata v různých jazycÃch k mnoha poÅ™adům. VÅ¡echen obsah a obrázky jsou poskytnuty uživateli pro uživatele a majà vysokou kvalitu. Návrhový vzor databáze a webová stránka jsou svobodný software licencovaný pod GPL.</description> + <description lang="cy">Mae TheTVDB.com yn Grafwr Teledu. Mae'r wefan yn gronfa ddata anferthol agored y mae modd ei addasu gan unrhyw un ac yn cynnwys meta data llaw llawer o sioeau mewn ieithoedd gwahanol. Mae'r holl gynnwys a delweddau ar y wefan wedi ei gyfrannu gan eu defnyddwyr ac i safon uchel . Mae cynllun y gronfa ddata a'r wefan yn god agored o dan y GPL.</description> <description lang="da">TheTVDB.com er en TV-scraper. Siden er en massiv Ã¥ben database, som alle kan modificere, og den indeholder fyldestgørende metadata for mange serier pÃ¥ forskellige sprog. Alt indhold og alle billeder pÃ¥ siden er tilføjet af brugere og har en høj standard eller kvalitet. Databasens model og webside er open source under GPL.</description> <description lang="de">TheTVDB.com ist ein Scraper für TV-Serien. Die Seite hat eine riesige offene Datenbank, welche von jedem geändert werden kann. Sie enthält weitreichende Meta-Daten für viele TV-Serien in verschiedenen Sprachen. Alle Inhalte und Bilder dieser Seite stammen von User für User und haben eine hohe Qualität. Das Datenbankschema und die Webseite sind OpenSource unter dem GPL-Recht</description> <description lang="el">Το TVDB.com είναι Îνα Scraper ΤηλεόÏασης. Η ιστοσελίδα είναι μία τεÏάστια ανοικτή βάση δεδομÎνων η οποία μποÏεί να Ï„Ïοποποιηθεί από τον καθÎνα και πεÏιÎχει πλήÏη μετα-δεδομÎνα για πολλÎÏ‚ σειÏÎÏ‚ σε διάφοÏες γλώσσες. Όλο το πεÏιεχόμενο και οι εικόνες στην ιστοσελίδα Ï€ÏοÎÏχονται από τους χÏήστες του, και Îχουν υψηλά Ï€Ïότυπα ποιότητας. Το σχήμα της βάσης δεδομÎνων και της ιστοσελίδας είναι Î±Î½Î¿Î¹ÎºÏ„Î¿Ï ÎºÏŽÎ´Î¹ÎºÎ± υπό το GPL.</description> @@ -58,6 +69,7 @@ <description lang="es">TheTVDB.com es un scraper de TV. El sitio es una enorme base de datos abierta que puede ser modificada por cualquiera y que contiene metadatos completos de muchas series en diferentes idiomas. Todos los contenidos e imágenes del sitio han sido aportados por sus usuarios y tienen una alta calidad. El esquema de base de datos y sitio web son de código abierto bajo la licencia GPL.</description> <description lang="es_AR">TheTVDB.com es un scraper de TV. El sitio es una enorme base de datos abierta que puede ser modificada por cualquiera y que contiene metadatos completos de muchas series en diferentes idiomas. Todos los contenidos e imágenes del sitio han sido aportados por sus usuarios y tienen una alta calidad. El esquema de base de datos y sitio web son de código abierto bajo la licencia GPL.</description> <description lang="es_MX">TheTVDB.com es un scraper de series de TV. Este sitio es una base de datos masiva y abierta que puede ser modicada por cualquiera y contiene metadata completa para muchas series en diferentes lenguajes. Todo el contenido e imágenes del sitio han sido contribuidos por sus usuarios para usuarios, los cuales tienen un alto estándar de calidad. El esquema de la base de datos y el sitio web son de código abierto bajo GPL.</description> + <description lang="et">TheTVDB.com on seriaalide kraabits. See leht on mahukas avatud andmebaas mida saavad täiendad kõik ja sisaldab palju metaandmeid suure hulga seriaalide kohta. Kõik sisu ja pildid lehel on kasutajate poolt sisestatud ning vastavad kõrgele kvaliteedile. TheTVDB.com andmebaasi struktuur ja kood on avaldatud GPLi all.</description> <description lang="fi">TheTVDB.com on TV-ohjelmatietojen lataaja. Sivusto on massiivinen avoin tietokanta, jonka tietoja kaikki pystyy muokkaamaan ja se sisältää täydet tiedot monista TV-ohjelmista usealla eri kielellä. Kaikki sivuston sisältö ja kuvat on korkealaatuisia ja käyttäjien lahjoittamia. Tietokanta ja sivusto ovat GPL-lisenssin alaisia.</description> <description lang="fr">TheTVDB.com est un collecteur TV. Le site est une immense base de données libre pouvant être modifiée par tout le monde et contenant toutes les informations de nombreuses séries en différentes langues. Les informations et images du site proviennent de contributions d'utilisateurs pour les usagers et sont d'excellentes qualités. Le schéma de la base de données et le site Web sont en open source sous licence GPL.</description> <description lang="gl">TheTVDB.com é un Scraper de TV. O sitio é unha enorme base de datos aberta que calquera pode modificar e contén todos os metadatos de centos de series en diferentes idiomas. Todo o contido e imaxes do sitio foi proporcionado polos seus usuarios e amosa un grande estándar de calidade. O esquema da base de datos e o sitio web son de código aberto baixo licenza GPL.</description> @@ -68,7 +80,10 @@ <description lang="ko">TheTVDB.com ì€ TV ìžë£Œìˆ˜ì§‘기입니다. 위 사ì´íŠ¸ëŠ” ì´ìš©ìžê°€ ì§ì ‘ ìˆ˜ì •í• ìˆ˜ 있으며 다양한 ì–¸ì–´ì˜ ì™„ì „í•œ 메타 ë°ì´í„°ë¥¼ í¬í•¨í•˜ëŠ” 방대한 오픈 ë°ì´í„°ë² ì´ìŠ¤ìž…니다. 사ì´íŠ¸ì˜ ëª¨ë“ ì½˜í…ì¸ ì™€ ì´ë¯¸ì§€ë“¤ì€ 사ì´íŠ¸ ì´ìš©ìžë“¤ì´ 다른 ì´ìš©ìžë“¤ì„ 위해 ì œê³µí•œ 것ì´ë©° ë†’ì€ í’ˆì§ˆì„ ê°€ì§€ê³ ìžˆìŠµë‹ˆë‹¤. 웹사ì´íŠ¸ì™€ ë°ì´í„°ë² ì´ìŠ¤ 스키마는 GLP 오픈소스입니다.</description> <description lang="lt">TheTVDB.com yra TV Scraper. Å i svetainÄ— yra didžiulÄ— atvira duomenų bazÄ—, kuria gali pakeisti bet kas ir kurioje visa meta duomenis bazÄ— daugelo Å¡ou įvairiomis kalbomis. Visas svetainÄ—s turinys atnaujinamas/papyldomasvartotojų ir turi aukÅ¡tÄ… kokybÄ—s standartÄ…. Duomenų bazÄ—s ir svetainÄ—s yra atviro kodo pagal GPL standartÄ….</description> <description lang="mk">TheTVDB.com is a TV Scraper. The site is a massive open database that can be modified by anybody and contains full meta data for many shows in different languages. All content and images on the site have been contributed by their users for users and have a high standard or quality. The database schema and website are open source under the GPL.</description> + <description lang="ms">TheTVDB.com adalah TV Scraper. Laman tersebut merupakan pangkalan data terbuka yang amat besar dan boleh diubahsuai oleh sesiapa pun dan juga mengandungi metadata pelbagai rancangan dalam pelbagai bahasa. Semua kandungan dan imej di laman ini disumbang oleh pengguna mereka untuk pengguna mereka dan mempunyai pemiawaian dan kualiti yang amat tinggi. Skema pangkalan data dan laman adalah sumber terbuka dibawah GPL.</description> + <description lang="my">TheTVDB.com သည် TV Scraper ဖြစ်သည်ዠdatabase ထဲá€á€½á€„် အá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸á€…ွာရှá€á€”ေပြီး မည်သူမဆá€á€¯ မည်သည့် ဘာသာစကားနှင့် မဆá€á€¯ á€á€„်ရောက်ပြုပြင် နá€á€¯á€„်သည်ዠအá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸á€”ှင့် ပုံများသည် áŽá€„်းá€á€á€¯á€·á အသုံးပြုသူများမှ အá€á€¼á€¬á€¸á€¡á€žá€¯á€¶á€¸á€•á€¼á€¯á€žá€°á€™á€»á€¬á€¸á€¡á€á€½á€€á€º ပံ့ပá€á€¯á€¸á€‘ားသော အဆင်မြင့် အရေအသွေးများဖြစ်သည်ዠwebsite နှင့် database သည် open source GPL လá€á€¯á€„်စင် ကá€á€¯ အသုံးပြုထားသည်á‹</description> <description lang="nl">TheTVDB.com is een seriescraper. De site is een gigantische open databank die iedereen kan aanpassen en uitbreiden, en biedt metadata aan voor TV-series in verschillende talen. Alle inhoud en afbeeldingen zijn afkomstig van gebruikers en moeten een grondige kwaliteitscontrole doorstaan. Het databankschema en de websitecode zijn vrijgegeven onder de open source GPL-licentie.</description> + <description lang="no">TheTVDB.com er en Tv Skraper. Siden er en massiv Ã¥pen database som kan endres av alle og inneholder data for mange forskjellige programmer pÃ¥ mange sprÃ¥k. Alt innholdet og bildene pÃ¥ siden er lagt til av brukere for brukere og har høy standard og kvalitet. Database skjemaet og websiden er Ã¥pen kildekode underlagt GPL.</description> <description lang="pl">TheTVDB.com jest scraperem TV. Ten serwis jest ogromnÄ…, wielojÄ™zykowÄ… i otwartÄ… bazÄ… danych o serialach, którÄ… może edytować każdy. Zawartość tego serwisu zostaÅ‚a dostarczona przez użytkowników, dla użytkowników. DostÄ™pne materiaÅ‚y sÄ… najwyższej jakoÅ›ci.</description> <description lang="pt">O TheTVDB.com é um scraper para séries TV. O site é uma gigantesca base de dados livre que pode ser alterada por qualquer pessoa e contém informação em várias lÃnguas. Todos os conteúdos do site foram enviados por utilizadores e têm um elevado padrão de qualidade. A base de dados e o site funcionam sob uma licença GPL de software livre.</description> <description lang="pt_BR">TheTVDB.com é um scraper de seriados. O site é um enorme banco de dados aberto que pode ser modificado por qualquer pessoa e contém metadados completos de muitos seriados em diferentes idiomas. Todos os conteúdos e imagens no site foram contribuições de usuários para usuários e têm um alto padrão de qualidade. O esquema do banco de dados e do site são de código aberto sob a licença GPL.</description> @@ -77,9 +92,14 @@ <description lang="se">TVDB.com är en TV-skrapa. Sajten är en massiv öppen databas som kan ändras av vem som helst och innehÃ¥ller full metadata för mängder av serier pÃ¥ olika sprÃ¥k. Allt innehÃ¥ll och bilder pÃ¥ sajten har bidragits av användare för användare och har en hög standard eller kvalitet. Databasschemat och webbsidan är licensierat som GPL.</description> <description lang="sk">TheTVDB.com je zdroj zÃskavania dát ohľadom TV. Táto stránka je obrovskou otvorenou databázou, ktorú môže upravovaÅ¥ ktokoľvek a obsahuje úplne metadáta pre mnoho relácià v rôznych jazykoch. VÅ¡etok obsah a obrázky na stránke bol dodaný samotnými použÃvateľmi pre použÃvateľov a udržuje si vysoký Å¡tandard a kvalitu. Schéma databázy a webová stránka sú dostupné vo forme open source v súlade s licenciou GPL.</description> <description lang="sl">TheTVDB.com je ponudnik informacij o TV serijah. Stran je masovna odprta baza podatkov, ki jo lahko dopolni kdorkoli, in vsebuje informacije o najrazliÄnejÅ¡ih TV serijah v veÄ jezikih. Vsa vsebina in slike so bile dodane s strani uporabnikov in imajo visok nivo kvalitete. Shema baze in spletna stran sta odprtokodni pod GPL.</description> + <description lang="sq">TheTVDB.com është një "TV Scraper". Kjo faqe është nje bazë e të dhënave e hapur që mund të modifikohet nga si cili dhe përmbanë metadata për shumë seriale në gjuhë të ndryshme. Gjitha të dhënat dhe imazhet në këtë faqe janë kontribuar nga përdoruesit për përdoruesit dhe kanë një standard dhe kualitet të lartë. Skema e bazës së të dhënave dhe sajti i uebit janë open source nën liçensën GPL. </description> <description lang="sv">TVDB.com är en TV-skrapa. Sajten är en massiv öppen databas som kan bli modifierad av vem som helst och innehÃ¥ller all metadata för mÃ¥nga serier pÃ¥ olika sprÃ¥k. Allt innehÃ¥ll och bilder pÃ¥ sidan har bidragits av användare för användare och har hög standard eller kvalitet. Databasschemat och sidan är öppen källkod licensierat under GPL.</description> + <description lang="ta_IN">TheTVDB.com ஒர௠தொலைகà¯à®•à®¾à®Ÿà¯à®šà®¿ சà¯à®°à®£à¯à®Ÿà®¿. இநà¯à®¤ இணையதà¯à®¤à®³à®¤à¯à®¤à®¿à®²à¯ ஒர௠பெரிய தரவà¯à®¤à¯à®¤à®³à®®à¯ உளà¯à®³à®¤à¯. இதில௠எலà¯à®²à®¾ மொழிகளின௠மேடà¯à®Ÿà®¾à®Ÿà¯‡à®Ÿà¯à®Ÿà®¾ உளà¯à®³à®¤à¯. அனைதà¯à®¤à¯ தகவலà¯à®•à®³à¯à®®à¯ படஙà¯à®•à®³à¯à®®à¯ அதன௠பயனரà¯à®•à®³à®¿à®©à¯ சேகரிபà¯à®ªà¯à®†à®•à¯à®®à¯. GPL லைசனà¯à®šà®¿à®²à¯ உளà¯à®³à®¤à¯.</description> <description lang="th">TheTVDB.com เป็นตัวดึงข้à¸à¸¡à¸¹à¸¥à¸—ีวี เว็บไซต์เป็นà¸à¸²à¸™à¸‚้à¸à¸¡à¸¹à¸¥à¹€à¸›à¸´à¸”ขนาดใหà¸à¹ˆà¸—ี่สามารถà¹à¸à¹‰à¹„ขได้โดยทุà¸à¸„นà¹à¸¥à¸°à¸¡à¸µà¸‚้à¸à¸¡à¸¹à¸¥à¸‚ั้นสูงเต็มรูปà¹à¸šà¸š สำหรับหลาย ๆ รายà¸à¸²à¸£ ในà¹à¸•à¹ˆà¸¥à¸°à¸ าษาที่à¹à¸•à¸à¸•à¹ˆà¸²à¸‡à¸à¸±à¸™ เนื้à¸à¸«à¸²à¹à¸¥à¸°à¸£à¸¹à¸›à¸ าพทั้งหมดในเว็บไซต์ ได้รับà¸à¸²à¸£à¸ªà¸™à¸±à¸šà¸ªà¸™à¸¸à¸™à¹‚ดยผู้ใช้เพื่à¸à¸œà¸¹à¹‰à¹ƒà¸Šà¹‰ มีคุณภาพà¹à¸¥à¸°à¸¡à¸²à¸•à¸£à¸à¸²à¸™à¸—ี่สูง schemaขà¸à¸‡à¸à¸²à¸™à¸‚้à¸à¸¡à¸¹à¸¥à¹à¸¥à¸°à¹€à¸§à¹‡à¸šà¹„ซต์ได้เปิดภายใต้ GPL</description> + <description lang="uk">TheTVDB.com Ñ” збирачем TV. Ðа порталі Ñ” маÑивні відкриті бази даних, Ñкі можуть мінÑтиÑÑ ÐºÐ¸Ð¼ завгодно, Ñ– міÑтить повні мета-дані Ð´Ð»Ñ Ð±Ð°Ð³Ð°Ñ‚ÑŒÐ¾Ñ… шоу різними мовами. ВеÑÑŒ вміÑÑ‚ та Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ð° Ñайті були надані кориÑтувачами Ð´Ð»Ñ ÐºÐ¾Ñ€Ð¸Ñтувачів Ñ– мають виÑокий Ñтандарт Ñ– ÑкіÑÑ‚ÑŒ. Бази даних Ñ– веб-Ñайт мають відкритий вихідний код під ліцензією GPL.</description> + <description lang="vi">TheTVDB.com là trình lấy dữ liệu TV show. Site chứa má»™t số lượng khổng lồ cÆ¡ sở dữ liệu mở, có thể được thay đổi bởi má»i ngÆ°á»i và đầy đủ dữ liệu lá»›n các show trên nhiá»u ngôn ngữ. Tất cả ná»™i dung và hình ảnh trên site nà y Ä‘á»u được đóng góp bởi toà n bá»™ ngÆ°á»i dùng của nó và có chất lượng cao. Mô hình cÆ¡ sở dữ liệu và website Ä‘á»u là mã nguồn mở được há»— trợ bởi GPL.</description> <description lang="zh">TheTVDB.com是一个电视刮削器。该网站是一个巨大的开放å¼æ•°æ®åº“,任何人都å¯ä»¥ä¿®æ”¹ï¼ŒåŒ…å«å¤šè¯è¨€çš„许多电视剧集资料。网站设定了高å“è´¨æ ‡å‡†ï¼Œæ‰€æœ‰å›¾ç‰‡å’Œå†…å®¹éƒ½ç”±ç”¨æˆ·æ供。数æ®åº“结构和网站å‡åœ¨GPL许å¯ä¸‹å¼€æºã€‚</description> + <description lang="zh_TW">TheTVDB.com是一個電視節目。該網站是一個é¾å¤§ä¸¦å¯ä»¥ç”±ä»»ä½•äººä¿®æ”¹çš„開放性資料庫,並包å«å¯ä»¥ä»¥å¤šåœ‹èªžè¨€é¡¯ç¤ºçš„完整的數據資料。所有內容和圖片都是經由用戶æ供使用,有一定的標準或質é‡ã€‚數據庫架構和網站是在GPL下的開放性æºç¢¼ã€‚</description> <platform>all</platform> </extension> </addon> diff --git a/addons/metadata.tvdb.com/changelog.txt b/addons/metadata.tvdb.com/changelog.txt index 01a0e682ac..652593d0d2 100644 --- a/addons/metadata.tvdb.com/changelog.txt +++ b/addons/metadata.tvdb.com/changelog.txt @@ -1,3 +1,20 @@ +[B]1.5.4[/B] +- Updated: language files from Transifex + +[B]1.5.3[/B] +- Fixed: Language tag caching - round two (thx and credits to pgit) + +[B]1.5.2[/B] +- Changed: Dropped the www from thetvdb URLs + +[B]1.5.1[/B] +- Updated: Versioning for xbmc.metadata + +[B]1.5.0[/B] +- Added: Language tag to caching (thx and credits to pgit) +- Added: Caching for search results (thx and credits to pgit) +- Removed: Poster preference as this is not needed for Frodo + [B]1.4.5[/B] - Fixed: dvdorder setting won't apply in GetEpisodeDetails (thx and credits to scudlee) diff --git a/addons/metadata.tvdb.com/resources/language/Albanian/strings.xml b/addons/metadata.tvdb.com/resources/language/Albanian/strings.xml new file mode 100644 index 0000000000..dbd922ee5f --- /dev/null +++ b/addons/metadata.tvdb.com/resources/language/Albanian/strings.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Albanian language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/sq/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">Përdor rendin e "DVD'së"</string> + <string id="30001">Përdor renditjen absolute (Sezon i veçantë)</string> + <string id="30002">Aktivo "Fanart'in"</string> + <string id="30003">Prefero Posterë</string> + <string id="30004">Gjuha</string> +</strings> diff --git a/addons/metadata.tvdb.com/resources/language/Basque/strings.xml b/addons/metadata.tvdb.com/resources/language/Basque/strings.xml index 90d1d2ca76..07c046d6c5 100644 --- a/addons/metadata.tvdb.com/resources/language/Basque/strings.xml +++ b/addons/metadata.tvdb.com/resources/language/Basque/strings.xml @@ -4,5 +4,6 @@ <!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> <strings> + <string id="30002">Gaitu Fanarta</string> <string id="30004">Hizkuntza</string> </strings> diff --git a/addons/metadata.tvdb.com/resources/language/Burmese/strings.xml b/addons/metadata.tvdb.com/resources/language/Burmese/strings.xml new file mode 100644 index 0000000000..d27205c50b --- /dev/null +++ b/addons/metadata.tvdb.com/resources/language/Burmese/strings.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Burmese language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/my/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">DVD order ကá€á€¯ အသုံးပြုရန်</string> + <string id="30002">Enable Fanart</string> + <string id="30003">ပá€á€¯á€…á€á€¬ ပုံစံကá€á€¯ သဘောကျသည်</string> + <string id="30004">ဘာသာစကား</string> +</strings> diff --git a/addons/metadata.tvdb.com/resources/language/Catalan/strings.xml b/addons/metadata.tvdb.com/resources/language/Catalan/strings.xml index c796f793b5..26adad4e41 100644 --- a/addons/metadata.tvdb.com/resources/language/Catalan/strings.xml +++ b/addons/metadata.tvdb.com/resources/language/Catalan/strings.xml @@ -4,5 +4,6 @@ <!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> <strings> + <string id="30002">Activar fanart</string> <string id="30004">Idioma</string> </strings> diff --git a/addons/metadata.tvdb.com/resources/language/Croatian/strings.xml b/addons/metadata.tvdb.com/resources/language/Croatian/strings.xml index fa1cc874a5..d3e159c96d 100644 --- a/addons/metadata.tvdb.com/resources/language/Croatian/strings.xml +++ b/addons/metadata.tvdb.com/resources/language/Croatian/strings.xml @@ -4,5 +4,7 @@ <!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> <strings> + <string id="30002">Omogući "Fanart"</string> + <string id="30003">Preferirani poster</string> <string id="30004">Jezik</string> </strings> diff --git a/addons/metadata.tvdb.com/resources/language/Estonian/strings.xml b/addons/metadata.tvdb.com/resources/language/Estonian/strings.xml index ef95aee088..2f4dd47d27 100644 --- a/addons/metadata.tvdb.com/resources/language/Estonian/strings.xml +++ b/addons/metadata.tvdb.com/resources/language/Estonian/strings.xml @@ -4,5 +4,9 @@ <!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> <strings> + <string id="30000">Kasuta DVD järjestust</string> + <string id="30001">Kasuta absoluutset järjestust (Ãœks hooaeg)</string> + <string id="30002">Võimalda fännikunst</string> + <string id="30003">Eelista postreid</string> <string id="30004">Keel</string> </strings> diff --git a/addons/metadata.tvdb.com/resources/language/Faroese/strings.xml b/addons/metadata.tvdb.com/resources/language/Faroese/strings.xml new file mode 100644 index 0000000000..e619bb1510 --- /dev/null +++ b/addons/metadata.tvdb.com/resources/language/Faroese/strings.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Faroese language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/fo/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30004">Mál</string> +</strings> diff --git a/addons/metadata.tvdb.com/resources/language/Latvian/strings.xml b/addons/metadata.tvdb.com/resources/language/Latvian/strings.xml new file mode 100644 index 0000000000..8903bbed54 --- /dev/null +++ b/addons/metadata.tvdb.com/resources/language/Latvian/strings.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Latvian language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/lv/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30004">Valoda</string> +</strings> diff --git a/addons/metadata.tvdb.com/resources/language/Malay/strings.xml b/addons/metadata.tvdb.com/resources/language/Malay/strings.xml new file mode 100644 index 0000000000..f744f97806 --- /dev/null +++ b/addons/metadata.tvdb.com/resources/language/Malay/strings.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Malay language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/ms/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">Gunakan susunan DVD</string> + <string id="30001">Gunakan susunan mutlak (untuk satu musim)</string> + <string id="30002">Membolehkan Fanart</string> + <string id="30003">Poster pilihan</string> + <string id="30004">Bahasa</string> +</strings> diff --git a/addons/metadata.tvdb.com/resources/language/Maltese/strings.xml b/addons/metadata.tvdb.com/resources/language/Maltese/strings.xml new file mode 100644 index 0000000000..0efb3102e5 --- /dev/null +++ b/addons/metadata.tvdb.com/resources/language/Maltese/strings.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Maltese language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/mt/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30004">Lingwa</string> +</strings> diff --git a/addons/metadata.tvdb.com/resources/language/Norwegian/strings.xml b/addons/metadata.tvdb.com/resources/language/Norwegian/strings.xml index 84c859b280..be5fe19520 100644 --- a/addons/metadata.tvdb.com/resources/language/Norwegian/strings.xml +++ b/addons/metadata.tvdb.com/resources/language/Norwegian/strings.xml @@ -4,5 +4,9 @@ <!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> <strings> + <string id="30000">Bruk DVD sortering</string> + <string id="30001">Bruk Absolutt sortering (Enkel Sesong)</string> + <string id="30002">Vis Fanart</string> + <string id="30003">Foretrekke Postere</string> <string id="30004">SprÃ¥k</string> </strings> diff --git a/addons/metadata.tvdb.com/resources/language/Persian (Iran)/strings.xml b/addons/metadata.tvdb.com/resources/language/Persian (Iran)/strings.xml new file mode 100644 index 0000000000..bb073ae860 --- /dev/null +++ b/addons/metadata.tvdb.com/resources/language/Persian (Iran)/strings.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Persian (Iran) language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/fa_IR/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30004">زبان</string> +</strings> diff --git a/addons/metadata.tvdb.com/resources/language/Tamil (India)/strings.xml b/addons/metadata.tvdb.com/resources/language/Tamil (India)/strings.xml new file mode 100644 index 0000000000..ef2285e5ef --- /dev/null +++ b/addons/metadata.tvdb.com/resources/language/Tamil (India)/strings.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Tamil (India) language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/ta_IN/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">டிவிடி வரிசை பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯</string> + <string id="30001">தனி வரிசை (தனி சீசனà¯) பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯</string> + <string id="30002">விசிறிபடதà¯à®¤à¯ˆ காணà¯à®ªà®¿</string> + <string id="30003">சà¯à®µà®°à¯†à®¾à®Ÿà¯à®Ÿà®¿à®•à®³à¯ விரà¯à®ªà¯à®ªà¯</string> + <string id="30004">மொழி</string> +</strings> diff --git a/addons/metadata.tvdb.com/resources/language/Turkish/strings.xml b/addons/metadata.tvdb.com/resources/language/Turkish/strings.xml index c91f88124f..06a7c1a0bf 100644 --- a/addons/metadata.tvdb.com/resources/language/Turkish/strings.xml +++ b/addons/metadata.tvdb.com/resources/language/Turkish/strings.xml @@ -4,6 +4,8 @@ <!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> <strings> + <string id="30000">DVD Sıralama Kullan</string> + <string id="30001">Mutlak Sıralama Kullan (Tek Sezon)</string> <string id="30002">Fanart'ı EtkinleÅŸtir</string> <string id="30003">Posterleri Tercih Et</string> <string id="30004">Dil</string> diff --git a/addons/metadata.tvdb.com/resources/language/Uzbek/strings.xml b/addons/metadata.tvdb.com/resources/language/Uzbek/strings.xml new file mode 100644 index 0000000000..02d02b8b48 --- /dev/null +++ b/addons/metadata.tvdb.com/resources/language/Uzbek/strings.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Uzbek language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/uz/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30004">Til</string> +</strings> diff --git a/addons/metadata.tvdb.com/resources/language/Vietnamese/strings.xml b/addons/metadata.tvdb.com/resources/language/Vietnamese/strings.xml new file mode 100644 index 0000000000..73adc1fd20 --- /dev/null +++ b/addons/metadata.tvdb.com/resources/language/Vietnamese/strings.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Vietnamese language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/vi/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">Sá» dụng DVD Order</string> + <string id="30001">Sá» dụng sắp đặt cố định (Theo Season)</string> + <string id="30002">Sá» dụng Fanart</string> + <string id="30003">Ưu tiên các poster</string> + <string id="30004">Ngôn ngữ</string> +</strings> diff --git a/addons/metadata.tvdb.com/resources/language/Welsh/strings.xml b/addons/metadata.tvdb.com/resources/language/Welsh/strings.xml new file mode 100644 index 0000000000..0dcd86f2b4 --- /dev/null +++ b/addons/metadata.tvdb.com/resources/language/Welsh/strings.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- Translated using Transifex web application. For support, or if you would like to to help out, please visit your language team! --> +<!-- Welsh language-Team URL: http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/cy/ --> +<!-- Report language file syntax bugs at: http://trac.xbmc.org/ --> + +<strings> + <string id="30000">Defnyddio Trefn DVD</string> + <string id="30001">Defnyddio Trefnu Absoliwt (Un Tymor)</string> + <string id="30002">Galluogi Celf Selogion</string> + <string id="30003">Cyfeirio Cofnodwyr</string> + <string id="30004">Iaith</string> +</strings> diff --git a/addons/metadata.tvdb.com/resources/settings.xml b/addons/metadata.tvdb.com/resources/settings.xml index 2396b769b9..14b802a123 100644 --- a/addons/metadata.tvdb.com/resources/settings.xml +++ b/addons/metadata.tvdb.com/resources/settings.xml @@ -4,7 +4,6 @@ <setting label="30001" type="bool" id="absolutenumber" default="false" enable="!eq(-1,true)" /> <setting type="sep" /> <setting label="30002" type="bool" id="fanart" default="true" /> - <setting label="30003" type="bool" id="posters" default="false" /> <setting type="sep" /> <setting label="30004" type="labelenum" id="language" values="da|fi|nl|de|it|es|fr|pl|hu|el|tr|ru|he|ja|pt|zh|cs|sl|hr|ko|en|sv|no" sort="yes" default="en" /> </settings> diff --git a/addons/metadata.tvdb.com/tvdb.xml b/addons/metadata.tvdb.com/tvdb.xml index 844f94501b..4e2cc2fd61 100644 --- a/addons/metadata.tvdb.com/tvdb.xml +++ b/addons/metadata.tvdb.com/tvdb.xml @@ -1,20 +1,20 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- should be self-explanatory --> -<scraper framework="1.1" date="2009-01-27"> +<scraper framework="1.1" date="2013-04-04"> <NfoUrl dest="3"> - <RegExp input="$$1" output="<url cache="\1.xml">http://www.thetvdb.com/api/1D62F2F90030C444/series/\1/all/$INFO[language].zip</url><id>\1</id>" dest="3"> + <RegExp input="$$1" output="<url cache="\1-$INFO[language].xml">http://thetvdb.com/api/1D62F2F90030C444/series/\1/all/$INFO[language].zip</url><id>\1</id>" dest="3"> <expression>http://(?:www\.)?thetvdb.com/(?:index\.php)?\?tab=series&id=([0-9]+)</expression> </RegExp> - <RegExp input="$$1" output="<details><url cache="tt\1.xml" function="GetTVDBId">http://www.thetvdb.com/api/GetSeriesByRemoteID.php?imdbid=tt\1&amp;language=$INFO[language]</url></details>" dest="3+"> + <RegExp input="$$1" output="<details><url cache="tt\1.xml" function="GetTVDBId">http://thetvdb.com/api/GetSeriesByRemoteID.php?imdbid=tt\1&amp;language=$INFO[language]</url></details>" dest="3+"> <expression>imdb....?/title/tt([0-9]*)</expression> </RegExp> - <RegExp input="$$1" output="<details><url cache="tt\1.xml" function="GetTVDBId">http://www.thetvdb.com/api/GetSeriesByRemoteID.php?imdbid=tt\1&amp;language=$INFO[language]</url></details>" dest="3+"> + <RegExp input="$$1" output="<details><url cache="tt\1.xml" function="GetTVDBId">http://thetvdb.com/api/GetSeriesByRemoteID.php?imdbid=tt\1&amp;language=$INFO[language]</url></details>" dest="3+"> <expression>imdb....?/Title\?([0-9]*)</expression> </RegExp> </NfoUrl> <GetTVDBId dest="3"> - <RegExp input="$$1" output="<details><url cache="\1.xml">http://www.thetvdb.com/api/1D62F2F90030C444/series/\1/all/$INFO[language].zip</url><id>\1</id></details>" dest="3"> + <RegExp input="$$1" output="<details><url cache="\1-$INFO[language].xml">http://thetvdb.com/api/1D62F2F90030C444/series/\1/all/$INFO[language].zip</url><id>\1</id></details>" dest="3"> <expression><seriesid>([0-9]*)</seriesid></expression> </RegExp> </GetTVDBId> @@ -31,7 +31,7 @@ <!-- input: $1=query string --> <!-- returns: the url we should use to do the search --> <CreateSearchUrl dest="3"> - <RegExp input="$$1" output="<url>http://www.thetvdb.com/api/GetSeries.php?seriesname=\1$$4&amp;language=$INFO[language]</url>" dest="3"> + <RegExp input="$$1" output="<url cache="cache-\1$$4.xml">http://thetvdb.com/api/GetSeries.php?seriesname=\1$$4&amp;language=$INFO[language]</url>" dest="3"> <RegExp input="$$2" output="%20(\1)" dest="4"> <expression clear="yes">(.+)</expression> </RegExp> @@ -43,7 +43,7 @@ <!-- returns: results in xml format <results><movie><title>*</title><url>*</url>*#urls<extra>*</extra></movie>*</results> --> <GetSearchResults dest="1"> <RegExp input="$$4" output="<?xml version="1.0" encoding="utf-8" standalone="yes"?><results>\1</results>" dest="1"> - <RegExp input="$$1" output="<entity><title>\3</title><language>\2</language><url cache="\1.xml">http://www.thetvdb.com/api/1D62F2F90030C444/series/\1/all/\2.zip</url><id>\1</id></entity>" dest="4"> + <RegExp input="$$1" output="<entity><title>\3</title><language>\2</language><url cache="\1-\2.xml">http://thetvdb.com/api/1D62F2F90030C444/series/\1/all/\2.zip</url><id>\1</id></entity>" dest="4"> <expression repeat="yes"><seriesid>([0-9]*)</seriesid>[^<]*<language>([^<]*)</language>[^<]*<SeriesName>([^<]*)</SeriesName></expression> </RegExp> <expression noclean="1"/> @@ -99,9 +99,6 @@ <RegExp input="$$5" output="<actor><name>\2</name><role>\3</role></actor>" dest="4+"> <expression repeat="yes" noclean="1,2,3"><Actor>.*?<Image>([^<]*)</Image>.*?<Name>([^<]*)</Name>.*?<Role>([^<]*)</expression> </RegExp> - <RegExp conditional="posters" output="<thumb aspect="poster">http://thetvdb.com/banners/\1</thumb>" dest="4+"> - <expression repeat="yes"><BannerPath>([^<]*)</BannerPath>[^<]*<BannerType>poster</BannerType></expression> - </RegExp> <RegExp input="$$5" output="<thumb aspect="banner">http://thetvdb.com/banners/\1</thumb>" dest="4+"> <expression repeat="yes"><BannerPath>([^<]*)</BannerPath>[^<]*<BannerType>series</BannerType>[^<]*<BannerType2>graphical</BannerType2>[^<]*<Language>$INFO[language]</Language></expression> </RegExp> @@ -129,7 +126,7 @@ <RegExp input="$$5" output="<thumb aspect="banner" type="season" season="\3">http://thetvdb.com/banners/\1</thumb>" dest="4+"> <expression repeat="yes"><BannerPath>([^<]*)</BannerPath>[^<]*<BannerType>season</BannerType>[^<]*<BannerType2>seasonwide</BannerType2>[^<]*<Language>((?!$INFO[language])[a-z])*</Language>[^<]*[^S]*Season>([0-9]+)</Season></expression> </RegExp> - <RegExp input="$$5" conditional="!posters" output="<thumb aspect="poster">http://thetvdb.com/banners/\1</thumb>" dest="4+"> + <RegExp input="$$5" output="<thumb aspect="poster">http://thetvdb.com/banners/\1</thumb>" dest="4+"> <expression repeat="yes"><BannerPath>([^<]*)</BannerPath>[^<]*<BannerType>poster</BannerType></expression> </RegExp> <RegExp input="$$5" output="<thumb aspect="poster" type="season" season="-1">http://thetvdb.com/banners/\1</thumb>" dest="4+"> @@ -144,7 +141,10 @@ </RegExp> <expression noclean="1"/> </RegExp> - <RegExp input="$$2" output="<episodeguide><url cache="$$2.xml">http://www.thetvdb.com/api/1D62F2F90030C444/series/\1/all/$INFO[language].zip</url></episodeguide>" dest="4+"> + <RegExp input="$$3" output="\1" dest="6"> + <expression>.*/(.*).zip</expression> + </RegExp> + <RegExp input="$$3" output="<episodeguide><url cache="$$2-$$6.xml">\1</url></episodeguide>" dest="4+"> <expression/> </RegExp> <expression noclean="1"/> @@ -156,8 +156,8 @@ <!-- returns: results in xml format <episodeguide><episode><title>*</title><url>*</url><season>*</season><epnum>*</epnum><thumb>*</thumb><id>*</id><aired>*</aired></episode>*</episodeguide> !--> <GetEpisodeList dest="3"> <RegExp input="$$4" output="<episodeguide>\1</episodeguide>" dest="3"> - <RegExp input="$$2" output="\2" dest="10"> - <expression>http://(?:www\.)thetvdb.com/api/(.+)/series/([0-9]*)/all/(.+).zip</expression> + <RegExp input="$$2" output="\2-\3" dest="10"> + <expression>http://(?:www\.)?thetvdb.com/api/(.+)/series/([0-9]*)/all/(.+).zip</expression> </RegExp> <RegExp conditional="!dvdorder"> <!-- Regular episodes (Absolute order) --> diff --git a/addons/skin.confluence/720p/SettingsCategory.xml b/addons/skin.confluence/720p/SettingsCategory.xml index fda12b3695..ace6202b61 100644 --- a/addons/skin.confluence/720p/SettingsCategory.xml +++ b/addons/skin.confluence/720p/SettingsCategory.xml @@ -70,7 +70,7 @@ <width>260</width> <height>481</height> <itemgap>-1</itemgap> - <onleft>60</onleft> + <onleft>9000</onleft> <onright>5</onright> <onup>3</onup> <ondown>3</ondown> @@ -225,6 +225,44 @@ <label>[COLOR=blue] - [/COLOR]$INFO[Control.GetLabel(2)]</label> </control> </control> + <control type="group"> + <posx>-250</posx> + <include>SideBladeLeft</include> + <control type="grouplist" id="9000"> + <posx>0</posx> + <posy>110</posy> + <width>250</width> + <height>600</height> + <onleft>9000</onleft> + <onright>3</onright> + <onup>9000</onup> + <ondown>9000</ondown> + <onback>3</onback> + <itemgap>0</itemgap> + <control type="label" id="200"> + <width>250</width> + <height>35</height> + <font>font12</font> + <label>31007</label> + <textcolor>blue</textcolor> + <align>center</align> + <aligny>center</aligny> + </control> + <control type="button" id="20"> + <description>Setting level button</description> + <textwidth>235</textwidth> + <include>ButtonCommonValues</include> + <label>10037</label> + <onclick>SettingsLevelChange</onclick> + </control> + <control type="button" id="21"> + <description>Reset button</description> + <include>ButtonCommonValues</include> + <label>10035</label> + <onclick>SettingsReset</onclick> + </control> + </control> + </control> <include>Clock</include> </controls> </window> diff --git a/addons/skin.confluence/720p/SlideShow.xml b/addons/skin.confluence/720p/SlideShow.xml index e131d79a05..7b282343b2 100644 --- a/addons/skin.confluence/720p/SlideShow.xml +++ b/addons/skin.confluence/720p/SlideShow.xml @@ -35,5 +35,17 @@ <include>VisibleFadeEffect</include> <include>SmallMusicInfo</include> </control> + <control type="button"> + <visible>SlideShow.IsVideo + [!SlideShow.IsActive | SlideShow.IsPaused]</visible> + <description>Video Play Button</description> + <posx>540</posx> + <posy>260</posy> + <width>200</width> + <height>200</height> + <font>-</font> + <onclick>play</onclick> + <texturefocus>arrow-big-right.png</texturefocus> + <texturenofocus>arrow-big-right.png</texturenofocus> + </control> </controls> </window>
\ No newline at end of file diff --git a/addons/skin.confluence/language/English/strings.po b/addons/skin.confluence/language/English/strings.po index d6024513d2..445e44a94e 100644 --- a/addons/skin.confluence/language/English/strings.po +++ b/addons/skin.confluence/language/English/strings.po @@ -41,7 +41,9 @@ msgctxt "#31006" msgid "View Options" msgstr "" -#empty string with id 31007 +msgctxt "#31007" +msgid "Settings Options" +msgstr "" msgctxt "#31008" msgid "Fullscreen" diff --git a/addons/xbmc.addon/addon.xml b/addons/xbmc.addon/addon.xml index 8bc67a6411..2694875fe3 100644 --- a/addons/xbmc.addon/addon.xml +++ b/addons/xbmc.addon/addon.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<addon id="xbmc.addon" version="12.9.3" provider-name="Team XBMC"> +<addon id="xbmc.addon" version="12.9.4" provider-name="Team XBMC"> <backwards-compatibility abi="12.0"/> <requires> <import addon="xbmc.core" version="0.1.0"/> diff --git a/addons/xbmc.addon/metadata.xsd b/addons/xbmc.addon/metadata.xsd index 6ae6d6c18d..c4a929bece 100644 --- a/addons/xbmc.addon/metadata.xsd +++ b/addons/xbmc.addon/metadata.xsd @@ -7,9 +7,14 @@ <xs:element name="summary" type="translatedString" minOccurs="1" maxOccurs="unbounded"/> <xs:element name="description" type="translatedString" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="disclaimer" type="translatedString" minOccurs="0"/> - <xs:element name="license" type="xs:string"/> <xs:element name="platform" type="platformList" minOccurs="0"/> <xs:element name="supportedcontent" type="contentList" minOccurs="0"/> + <xs:element name="language" type="xs:string" minOccurs="0"/> + <xs:element name="license" type="xs:string" minOccurs="0"/> + <xs:element name="forum" type="xs:string" minOccurs="0"/> + <xs:element name="website" type="xs:string" minOccurs="0"/> + <xs:element name="source" type="xs:string" minOccurs="0"/> + <xs:element name="email" type="xs:string" minOccurs="0"/> <xs:element name="broken" type="xs:string" minOccurs="0"/> </xs:sequence> <xs:attribute name="point" type="xs:string" use="required"/> diff --git a/addons/xbmc.addon/repository.xsd b/addons/xbmc.addon/repository.xsd index 7ec8141a47..eef49bfb93 100644 --- a/addons/xbmc.addon/repository.xsd +++ b/addons/xbmc.addon/repository.xsd @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE schema PUBLIC "-//W3C//DTD XMLSCHEMA 200102//EN" "http://www.w3.org/2001/XMLSchema.dtd"> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> - <xs:element name="extension"> - <xs:complexType> + <xs:element name="extension"> + <xs:complexType> <xs:element name="info"> <xs:complexType> <xs:attribute name="compressed" type="xs:boolean"/> @@ -14,11 +14,11 @@ <xs:attribute name="zip" type="xs:boolean"/> </xs:complexType> </xs:element> - </xs:complexType> - </xs:element> - <xs:simpleType name="simpleIdentifier"> - <xs:restriction base="xs:string"> - <xs:pattern value="[^.]+"/> - </xs:restriction> - </xs:simpleType> + </xs:complexType> + </xs:element> + <xs:simpleType name="simpleIdentifier"> + <xs:restriction base="xs:string"> + <xs:pattern value="[^.]+"/> + </xs:restriction> + </xs:simpleType> </xs:schema> diff --git a/addons/xbmc.debug/addon.xml b/addons/xbmc.debug/addon.xml new file mode 100644 index 0000000000..a9000d7c35 --- /dev/null +++ b/addons/xbmc.debug/addon.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<addon id="xbmc.debug" version="0.1.0" provider-name="Team XBMC" name="Log"> + <backwards-compatibility abi="0.1"/> + <requires> + <c-pluff version="0.1"/> + </requires> + <extension point="xbmc.python.module"/> + <extension point="xbmc.addon.metadata"> + <platform>all</platform> + </extension> +</addon> diff --git a/addons/metadata.album.universal/resources/language/English/strings.po b/addons/xbmc.debug/resources/language/English/strings.po index 8a0d52e410..8bb4c72d43 100644 --- a/addons/metadata.album.universal/resources/language/English/strings.po +++ b/addons/xbmc.debug/resources/language/English/strings.po @@ -1,8 +1,8 @@ # XBMC Media Center language file -# Addon Name: Universal Album Scraper -# Addon id: metadata.album.universal -# Addon version: 1.6.0 -# Addon Provider: Olympia, Team XBMC +# Addon Name: Debug customizer +# Addon id: xbmc.debug +# Addon version: 0.1.0 +# Addon Provider: Team XBMC msgid "" msgstr "" "Project-Id-Version: XBMC Main Translation Project (Frodo)\n" @@ -18,45 +18,25 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" -msgid "Grab Album Thumbs from fanart.tv" +msgid "Verbose logging for SMB library" msgstr "" msgctxt "#30001" -msgid "Grab Album Thumbs from Last.fm" +msgid "Verbose logging for CURL library (http, dav)" msgstr "" msgctxt "#30002" -msgid "Get Album Review from" +msgid "Verbose logging for CMYTH library" msgstr "" msgctxt "#30003" -msgid " Preferred Language" +msgid "Verbose logging for FFMPEG libraries" msgstr "" msgctxt "#30004" -msgid "Get Album Rating from" +msgid "Verbose logging for RTMP library" msgstr "" msgctxt "#30005" -msgid "Get Album Styles from" -msgstr "" - -msgctxt "#30006" -msgid "Get Album Moods from" -msgstr "" - -msgctxt "#30007" -msgid "Get Album Themes from" -msgstr "" - -msgctxt "#30008" -msgid "Grab Album Thumbs from allmusic.com" -msgstr "" - -msgctxt "#30009" -msgid "Artwork" -msgstr "" - -msgctxt "#30010" -msgid "Grab Album Thumbs from theaudiodb.com" +msgid "Verbose logging for DBUS calls" msgstr "" diff --git a/addons/xbmc.debug/resources/settings.xml b/addons/xbmc.debug/resources/settings.xml new file mode 100644 index 0000000000..2644a96917 --- /dev/null +++ b/addons/xbmc.debug/resources/settings.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<settings> + <setting id="bit1" type="bool" label="30000" default="0"/> + <setting id="bit2" type="bool" label="30001" default="0"/> + <setting id="bit3" type="bool" label="30002" default="0"/> + <setting id="bit4" type="bool" label="30003" default="0"/> + <setting id="bit5" type="bool" label="30004" default="0"/> + <setting id="bit6" type="bool" label="30005" default="0"/> +</settings> diff --git a/addons/xbmc.gui/skin.xsd b/addons/xbmc.gui/skin.xsd index 2dd9863f63..c669367a16 100644 --- a/addons/xbmc.gui/skin.xsd +++ b/addons/xbmc.gui/skin.xsd @@ -1,23 +1,21 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE schema PUBLIC "-//W3C//DTD XMLSCHEMA 200102//EN" "http://www.w3.org/2001/XMLSchema.dtd"> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> - <xs:element name="extension"> - <xs:complexType> - <xs:attribute name="point" type="xs:string" use="required"/> - <xs:attribute name="id" type="simpleIdentifier"/> - <xs:attribute name="name" type="xs:string"/> - - <xs:attribute name="defaultresolution" type="xs:string" use="required"/> - <xs:attribute name="defaultresolutionwide" type="xs:string" use="required"/> - <xs:attribute name="defaultthemename" type="xs:string" use="required"/> - <xs:attribute name="effectslowdown" type="xs:float"/> - <xs:attribute name="debugging" type="xs:boolean"/> - - </xs:complexType> - </xs:element> - <xs:simpleType name="simpleIdentifier"> - <xs:restriction base="xs:string"> - <xs:pattern value="[^.]+"/> - </xs:restriction> - </xs:simpleType> + <xs:element name="extension"> + <xs:complexType> + <xs:attribute name="point" type="xs:string" use="required"/> + <xs:attribute name="id" type="simpleIdentifier"/> + <xs:attribute name="name" type="xs:string"/> + <xs:attribute name="defaultresolution" type="xs:string" use="required"/> + <xs:attribute name="defaultresolutionwide" type="xs:string" use="required"/> + <xs:attribute name="defaultthemename" type="xs:string" use="required"/> + <xs:attribute name="effectslowdown" type="xs:float"/> + <xs:attribute name="debugging" type="xs:boolean"/> + </xs:complexType> + </xs:element> + <xs:simpleType name="simpleIdentifier"> + <xs:restriction base="xs:string"> + <xs:pattern value="[^.]+"/> + </xs:restriction> + </xs:simpleType> </xs:schema> diff --git a/addons/xbmc.metadata/scraper.xsd b/addons/xbmc.metadata/scraper.xsd index 9e031f3370..d993052f46 100644 --- a/addons/xbmc.metadata/scraper.xsd +++ b/addons/xbmc.metadata/scraper.xsd @@ -1,19 +1,19 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE schema PUBLIC "-//W3C//DTD XMLSCHEMA 200102//EN" "http://www.w3.org/2001/XMLSchema.dtd"> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> - <xs:element name="extension"> - <xs:complexType> - <xs:attribute name="point" type="xs:string" use="required"/> - <xs:attribute name="id" type="simpleIdentifier"/> - <xs:attribute name="name" type="xs:string"/> - <xs:attribute name="library" type="xs:string"/> - <xs:attribute name="language" type="xs:string"/> - <xs:attribute name="requiressetting" type="xs:boolean"/> - </xs:complexType> - </xs:element> - <xs:simpleType name="simpleIdentifier"> - <xs:restriction base="xs:string"> - <xs:pattern value="[^.]+"/> - </xs:restriction> - </xs:simpleType> + <xs:element name="extension"> + <xs:complexType> + <xs:attribute name="point" type="xs:string" use="required"/> + <xs:attribute name="id" type="simpleIdentifier"/> + <xs:attribute name="name" type="xs:string"/> + <xs:attribute name="library" type="xs:string"/> + <xs:attribute name="language" type="xs:string"/> + <xs:attribute name="requiressetting" type="xs:boolean"/> + </xs:complexType> + </xs:element> + <xs:simpleType name="simpleIdentifier"> + <xs:restriction base="xs:string"> + <xs:pattern value="[^.]+"/> + </xs:restriction> + </xs:simpleType> </xs:schema> diff --git a/addons/xbmc.python/pluginsource.xsd b/addons/xbmc.python/pluginsource.xsd index 9907324cd4..48891a4481 100644 --- a/addons/xbmc.python/pluginsource.xsd +++ b/addons/xbmc.python/pluginsource.xsd @@ -1,24 +1,25 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE schema PUBLIC "-//W3C//DTD XMLSCHEMA 200102//EN" "http://www.w3.org/2001/XMLSchema.dtd"> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> - <xs:element name="extension"> - <xs:complexType> - <xs:element name="provides" type="providesList"/> - <xs:attribute name="point" type="xs:string" use="required"/> - <xs:attribute name="id" type="simpleIdentifier"/> - <xs:attribute name="name" type="xs:string"/> - </xs:complexType> - </xs:element> - <xs:element name="content"> - <xs:complexType> - <xs:attribute name="type" type="xs:string" use="required"/> - </xs:complexType> - </xs:element> - <xs:simpleType name="simpleIdentifier"> - <xs:restriction base="xs:string"> - <xs:pattern value="[^.]+"/> - </xs:restriction> - </xs:simpleType> + <xs:element name="extension"> + <xs:complexType> + <xs:element name="provides" type="providesList"/> + <xs:attribute name="point" type="xs:string" use="required"/> + <xs:attribute name="id" type="simpleIdentifier"/> + <xs:attribute name="name" type="xs:string"/> + <xs:attribute name="library" type="xs:string" use="required"/> + </xs:complexType> + </xs:element> + <xs:element name="content"> + <xs:complexType> + <xs:attribute name="type" type="xs:string" use="required"/> + </xs:complexType> + </xs:element> + <xs:simpleType name="simpleIdentifier"> + <xs:restriction base="xs:string"> + <xs:pattern value="[^.]+"/> + </xs:restriction> + </xs:simpleType> <xs:simpleType name="providesType"> <xs:restriction base="xs:string"> <xs:enumeration value="audio"/> @@ -30,6 +31,5 @@ <xs:simpleType name="providesList"> <xs:list itemType="providesType"/> </xs:simpleType> - </xs:schema> diff --git a/addons/xbmc.python/script.xsd b/addons/xbmc.python/script.xsd index 76bb96dce5..e409b8d3d2 100644 --- a/addons/xbmc.python/script.xsd +++ b/addons/xbmc.python/script.xsd @@ -1,17 +1,17 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE schema PUBLIC "-//W3C//DTD XMLSCHEMA 200102//EN" "http://www.w3.org/2001/XMLSchema.dtd"> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> - <xs:element name="extension"> - <xs:complexType> - <xs:attribute name="point" type="xs:string" use="required"/> - <xs:attribute name="id" type="simpleIdentifier"/> - <xs:attribute name="name" type="xs:string"/> - <xs:attribute name="library" type="xs:string"/> - </xs:complexType> - </xs:element> - <xs:simpleType name="simpleIdentifier"> - <xs:restriction base="xs:string"> - <xs:pattern value="[^.]+"/> - </xs:restriction> - </xs:simpleType> + <xs:element name="extension"> + <xs:complexType> + <xs:attribute name="point" type="xs:string" use="required"/> + <xs:attribute name="id" type="simpleIdentifier"/> + <xs:attribute name="name" type="xs:string"/> + <xs:attribute name="library" type="xs:string" use="required"/> + </xs:complexType> + </xs:element> + <xs:simpleType name="simpleIdentifier"> + <xs:restriction base="xs:string"> + <xs:pattern value="[^.]+"/> + </xs:restriction> + </xs:simpleType> </xs:schema> diff --git a/configure.in b/configure.in index f0e49051ed..2676dc0b62 100644 --- a/configure.in +++ b/configure.in @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.59) -AC_INIT([xbmc], [12.9.3], [http://trac.xbmc.org]) +AC_INIT([xbmc], [12.9.4], [http://trac.xbmc.org]) AC_CONFIG_HEADERS([xbmc/config.h]) AH_TOP([#pragma once]) m4_include([m4/ax_python_devel.m4]) @@ -30,6 +30,21 @@ AC_DEFUN([XB_ADD_PLAYER], esac ]) +# check for enabling additional codecs +AC_DEFUN([XB_ADD_CODEC], +[ + AC_MSG_CHECKING([for $2]) + case $add_codecs in + *$2*) + AC_SUBST([USE_$1], 1) + AC_DEFINE([HAS_$1], 1, [using $2]) + AC_MSG_RESULT([enabling $2]) + ;; + *) + AC_MSG_RESULT([$2 is not enabled]) + esac +]) + # check for library basenames AC_DEFUN([XB_FIND_SONAME], [ @@ -140,8 +155,8 @@ libnfs_not_found="== Could not find libnfs. NFS client support disabled. ==" libnfs_disabled="== NFS support disabled. ==" libafpclient_not_found="== Could not find libafpclient. AFP client support disabled. ==" libafpclient_disabled="== AFP support disabled. ==" -libshairport_not_found="== Could not find libshairport. AirTunes support disabled. ==" -libshairport_disabled="== AirTunes support disabled. ==" +libshairport_not_found="== Could not find libshairport. ==" +libshairplay_not_found="== Could not find libshairplay. ==" samba_disabled="== SAMBA support disabled. ==" libplist_not_found="== Could not find libplist. AirPlay support disabled. ==" libplist_disabled="== AirPlay support disabled. ==" @@ -513,6 +528,12 @@ AC_ARG_ENABLE([gtest], [configure_gtest=$enableval], [configure_gtest=no]) +AC_ARG_ENABLE([codec], + [AS_HELP_STRING([--enable-codec], + [enable additional codecs from a list of comma separated names, (default is none, choices are amcodec)])], + [add_codecs=$enableval], + [add_codecs=no]) + ### External libraries options AC_ARG_ENABLE([external-libraries], [AS_HELP_STRING([--enable-external-libraries], @@ -850,7 +871,7 @@ AC_CHECK_SIZEOF([size_t]) # Check for intrinsics AC_MSG_CHECKING([for __sync_add_and_fetch(temp, 1)]) -AC_TRY_COMPILE([],[long* temp=0; __sync_add_and_fetch(temp, 1);], +AC_TRY_LINK([],[long* temp=0; long ret=__sync_add_and_fetch(temp, 1);], [have_builtin_sync_add_and_fetch=yes], [have_builtin_sync_add_and_fetch=no]) AC_MSG_RESULT($have_builtin_sync_add_and_fetch) @@ -860,7 +881,7 @@ if test "x$have_builtin_sync_add_and_fetch" = "xyes"; then fi AC_MSG_CHECKING([for __sync_sub_and_fetch(temp, 1)]) -AC_TRY_COMPILE([],[long* temp=0; __sync_sub_and_fetch(temp, 1);], +AC_TRY_LINK([],[long* temp=0; long ret=__sync_sub_and_fetch(temp, 1);], [have_builtin_sync_sub_and_fetch=yes], [have_builtin_sync_sub_and_fetch=no]) AC_MSG_RESULT($have_builtin_sync_sub_and_fetch) @@ -870,7 +891,7 @@ if test "x$have_builtin_sync_sub_and_fetch" = "xyes"; then fi AC_MSG_CHECKING([for __sync_val_compare_and_swap(temp, 1, 1)]) -AC_TRY_COMPILE([],[long *temp = 0; __sync_val_compare_and_swap(temp, 1, 1);], +AC_TRY_LINK([],[long *temp = 0; long ret=__sync_val_compare_and_swap(temp, 1, 1);], [have_builtin_sync_val_compare_and_swap=yes], [have_builtin_sync_val_compare_and_swap=no]) AC_MSG_RESULT($have_builtin_sync_val_compare_and_swap) @@ -1436,24 +1457,45 @@ if test "$use_airplay" != "no"; then fi fi -# libshairport for AirTunes +# libshairplay for AirTunes (prefered lib) USE_AIRTUNES=0 if test "x$use_airtunes" != "xno"; then - AC_CHECK_HEADERS([shairport/shairport.h],, + AC_CHECK_HEADERS([shairplay/raop.h],, [if test "x$use_airtunes" = "xyes"; then - AC_MSG_ERROR($libshairport_not_found) + AC_MSG_ERROR($libshairplay_not_found) elif test "x$use_airtunes" != "xno"; then - AC_MSG_NOTICE($libshairport_not_found) + AC_MSG_NOTICE($libshairplay_not_found) use_airtunes="no" fi ]) if test "x$use_airtunes" != "xno"; then - XB_FIND_SONAME([SHAIRPORT], [shairport], [use_airtunes]) + XB_FIND_SONAME([SHAIRPLAY], [shairplay], [use_airtunes]) USE_AIRTUNES=1 - AC_CHECK_MEMBERS([struct AudioOutput.ao_set_metadata],,, - [[#include <shairport/shairport.h>]]) - AC_DEFINE([HAVE_LIBSHAIRPORT],[1],["Define to 1 if you have libshairport."]) + USE_LIBSHAIRPORT=1 + AC_CHECK_MEMBERS([struct raop_callbacks_s.cls],,, + [[#include <shairplay/raop.h>]]) + AC_DEFINE([HAVE_LIBSHAIRPLAY],[1],["Define to 1 if you have libshairplay."]) + fi + + #libshairport - as a fallback for AirTunes + if test "x$USE_AIRTUNES" == "x0"; then + AC_CHECK_HEADERS([shairport/shairport.h],, + [if test "x$use_airtunes" = "xyes"; then + AC_MSG_ERROR($libshairport_not_found) + elif test "x$use_airtunes" != "xno"; then + AC_MSG_NOTICE($libshairport_not_found) + use_airtunes="no" + fi + ]) + + if test "x$use_airtunes" != "xno"; then + XB_FIND_SONAME([SHAIRPORT], [shairport], [use_airtunes]) + USE_AIRTUNES=1 + AC_CHECK_MEMBERS([struct AudioOutput.ao_set_metadata],,, + [[#include <shairport/shairport.h>]]) + AC_DEFINE([HAVE_LIBSHAIRPORT],[1],["Define to 1 if you have libshairport."]) + fi fi fi @@ -1857,6 +1899,14 @@ case $add_players in ;; esac +# additional internal codecs +case $add_codecs in + *amcodec*) + AC_CHECK_HEADER([amlplayer/codec_error.h],, AC_MSG_ERROR($missing_headers)) + XB_ADD_CODEC([LIBAMCODEC], [amcodec]) + ;; +esac + # platform specific bin utilities if test "$build_vendor" != "apple" ; then AC_CHECK_PROG(HAVE_GAWK,gawk,"yes","no",) @@ -2240,7 +2290,11 @@ else fi if test "x$use_airtunes" != "xno"; then - final_message="$final_message\n AirTunes support:\tYes" + if test "x$USE_LIBSHAIRPORT" == "x1"; then + final_message="$final_message\n AirTunes support (libshairplay):\tYes" + else + final_message="$final_message\n AirTunes support (libshairport):\tYes" + fi else final_message="$final_message\n AirTunes support:\tNo" fi @@ -2401,6 +2455,7 @@ OUTPUT_FILES="Makefile \ xbmc/peripherals/devices/Makefile \ xbmc/android/activity/Makefile \ xbmc/android/loader/Makefile \ + xbmc/utils/Makefile \ xbmc/main/Makefile" if test "$use_skin_touched" = "yes"; then diff --git a/docs/README.android b/docs/README.android index 6ff28ab93c..1b1b496d24 100644 --- a/docs/README.android +++ b/docs/README.android @@ -40,27 +40,19 @@ If you run a 64bit operating system you will also need to get ia32-libs ----------------------------------------------------------------------------- To develop XBMC for Android the Android SDK and NDK are required. -Because the Android NDK is lacking support for wide characters (wchar_t) -which XBMC relies on for Unicode implementation, a third-party NDK -from Crystax is being used. -------------------------------------------------------------------- 3.1. Getting the Android SDK and NDK -------------------------------------------------------------------- To get the Android SDK, go to http://developer.android.com/sdk and -download the latest version for your operating system. The Crystax NDK -can be downloaded from http://www.crystax.net/en/android/ndk - -[NOTICE] Compiling XBMC for Android requires at least Crystax Android NDK - Revision 7b. Crystax Android NDK Revision 7 and earlier do not work - properly for our cause. The corresponding Crystax NDK version - is android-ndk-r7-crystax-5.beta3 Do not use the standard Android NDK. - -[NOTICE] We previously used android-ndk-r7-crystax-5.beta2, but it produced - binaries that would NOT run on Jellybean 4.2. At this time, - android-ndk-r7-crystax-5.beta3 is required. - +download the latest version for your operating system. The NDK +can be downloaded from http://developer.android.com/tools/sdk/ndk/ + +[NOTICE] Compiling XBMC for Android requires at least Android NDK + Revision r8e. Android NDK Revision 7 and earlier do not work + properly for our cause. + After downloading the SDK and NDK extract the files contained in the archives to your harddisk. @@ -93,7 +85,11 @@ specifies where the resulting toolchain should be installed (your choice). # ls platforms # cd build/tools # ./make-standalone-toolchain.sh --ndk-dir=../../ \ - --install-dir=<android-toolchain>/android-14 --platform=android-14 + --install-dir=<android-toolchain>/android-14 --platform=android-14 \ + --toolchain=arm-linux-androideabi-4.7 + +Make sure to pick a toolchain for your desired architecture. Currently only +gcc 4.7 toolchains are supported, anything else will likely fail to build. ATTENTION FOR X86 BUILDS - THIS DOES NOT APPLY TO 99% OF BUILDS: If you want to build for the x86 platform there is a flaw in the mentioned @@ -146,6 +142,7 @@ on with the Android toolchain and creating an Android Application Package # ./configure --help Run configure with the correct settings for you local configuration. + See tools/depends/README for examples. Anyone working on the dependencies themselves will want to set the environment variables specified in ~/.bashrc or similar, to avoid @@ -164,8 +161,9 @@ on with the Android toolchain and creating an Android Application Package -------------------------------------------------------------------- # cd $HOME/xbmc-android - # make -C tools/android/xbmc + # make -C tools/depends/target/xbmc # make + # make apk After the first build (assuming bootstrap and configure are successful), subsequent builds can be run with a simple 'make' and 'make apk'. diff --git a/docs/README.linux b/docs/README.linux index c0d5e78748..d88cc50487 100644 --- a/docs/README.linux +++ b/docs/README.linux @@ -1,4 +1,3 @@ - TOC 1. Introduction 2. Getting the source code @@ -39,26 +38,21 @@ that are used to build XBMC packages on Debian/Ubuntu (with all supported external libraries enabled). Build-Depends: autoconf, automake, autopoint, autotools-dev, cmake, curl, - debhelper (>= 7.0.50~), gawk, gperf, libao-dev, libasound2-dev, - libass-dev (>= 0.9.8), libavahi-client-dev, libavahi-common-dev, - libavcodec-dev, libavfilter-dev, libavformat-dev, libavutil-dev, - libbluetooth-dev, libbluray-dev, libboost-dev, libboost-thread-dev, - libiso9660-dev, libbz2-dev, libcdio-dev, libcec-dev, libcrystalhd-dev, - libcurl4-gnutls-dev | libcurl-dev, libcwiid-dev, libdbus-1-dev, - libenca-dev, libflac-dev, libfontconfig-dev, libfreetype6-dev, - libfribidi-dev, libgl1-mesa-dev | libgl-dev, libglew-dev, - libglu1-mesa-dev | libglu-dev, libhal-dev, libhal-storage-dev, - libjasper-dev, libjpeg-dev, libltdl-dev, liblzo2-dev, libmad0-dev, - libmicrohttpd-dev, libmodplug-dev, libmpcdec-dev, libmpeg2-4-dev, - libmysqlclient-dev, libnfs-dev, libogg-dev, libpcre3-dev, libplist-dev, - libpng12-dev | libpng-dev, libpostproc-dev, libpulse-dev, librtmp-dev, - libsamplerate-dev, libsdl-dev, libsdl-image1.2-dev, libsdl-mixer1.2-dev, - libshairport-dev, libsmbclient-dev, libsqlite3-dev, libssh-dev, libssl-dev, - libswscale-dev, libtinyxml-dev, libtool, libudev-dev, libusb-dev, libva-dev, - libvdpau-dev, libvorbis-dev, libxinerama-dev, libxmu-dev, libxrandr-dev, - libxt-dev, libyajl-dev, lsb-release, nasm [!amd64], python-dev, - python-support, unzip, yasm, zip, zlib1g-dev, libcap-dev, swig, libtag1-dev (>= 1.8), - default-jre, libtiff-dev + debhelper (>= 7.0.50~), default-jre, gawk, gperf, libao-dev, libasound2-dev, + libass-dev (>= 0.9.8), libavahi-client-dev, libavahi-common-dev, libavcodec-dev, + libavfilter-dev, libavformat-dev, libavutil-dev, libbluetooth-dev, libbluray-dev, + libboost-dev, libboost-thread-dev, libbz2-dev, libcap-dev, libcdio-dev, libcec-dev, + libcrystalhd-dev, libcurl4-gnutls-dev | libcurl-dev, libcwiid-dev, libdbus-1-dev, + libenca-dev, libflac-dev, libfontconfig-dev, libfreetype6-dev, libfribidi-dev, + libgl1-mesa-dev | libgl-dev, libglew-dev, libglu1-mesa-dev | libglu-dev, libhal-dev, + libhal-storage-dev, libiso9660-dev, libjasper-dev, libjpeg-dev, libltdl-dev, liblzo2-dev, + libmad0-dev, libmicrohttpd-dev, libmodplug-dev, libmpcdec-dev, libmpeg2-4-dev, libmysqlclient-dev, + libnfs-dev, libogg-dev, libpcre3-dev, libplist-dev, libpng12-dev | libpng-dev, libpostproc-dev, + libpulse-dev, librtmp-dev, libsamplerate-dev, libsdl-dev, libsdl-image1.2-dev, libsdl-mixer1.2-dev, + libshairplay-dev, libsmbclient-dev, libsqlite3-dev, libssh-dev, libssl-dev, libswscale-dev, + libtag1-dev (>= 1.8), libtiff-dev, libtinyxml-dev, libtool, libudev-dev, libusb-dev, libva-dev, + libvdpau-dev, libvorbis-dev, libxinerama-dev, libxmu-dev, libxrandr-dev, libxt-dev, libyajl-dev, + lsb-release, nasm [!amd64], python-dev, python-imaging, python-support, swig, unzip, yasm, zip, zlib1g-dev *** For developers and anyone else who compiles frequently it is recommended to use ccache diff --git a/docs/README.raspberrypi b/docs/README.raspberrypi index 6b6f1b1d74..aadcc418c7 100644 --- a/docs/README.raspberrypi +++ b/docs/README.raspberrypi @@ -6,7 +6,7 @@ TOC 1. Introduction ----------------------------------------------------------------------------- -For developemnt you can use a customized buildroot to produce a small +For development you can use a customized buildroot to produce a small raspberrypi system image which is used to boot the raspberrypi and as crosscompile environment. diff --git a/docs/README.ubuntu b/docs/README.ubuntu index 8bbd176523..9a2b301e30 100644 --- a/docs/README.ubuntu +++ b/docs/README.ubuntu @@ -44,7 +44,7 @@ Two methods exist to install the required Ubuntu packages: For Ubuntu (all versions >= 7.04): - # sudo apt-get install git-core build-essential gawk pmount libtool nasm yasm automake cmake gperf zip unzip bison libsdl-dev libsdl-image1.2-dev libsdl-gfx1.2-dev libsdl-mixer1.2-dev libfribidi-dev liblzo2-dev libfreetype6-dev libsqlite3-dev libogg-dev libasound2-dev python-sqlite libglew-dev libcurl3 libcurl4-gnutls-dev libxrandr-dev libxrender-dev libmad0-dev libogg-dev libvorbisenc2 libsmbclient-dev libmysqlclient-dev libpcre3-dev libdbus-1-dev libhal-dev libhal-storage-dev libjasper-dev libfontconfig-dev libbz2-dev libboost-dev libenca-dev libxt-dev libxmu-dev libpng-dev libjpeg-dev libpulse-dev mesa-utils libcdio-dev libsamplerate-dev libmpeg3-dev libflac-dev libiso9660-dev libass-dev libssl-dev fp-compiler gdc libmpeg2-4-dev libmicrohttpd-dev libmodplug-dev libssh-dev gettext cvs python-dev libyajl-dev libboost-thread-dev libplist-dev libusb-dev libudev-dev libtinyxml-dev libcap-dev curl swig default-jre libtiff-dev + # sudo apt-get install automake bison build-essential cmake curl cvs default-jre fp-compiler gawk gdc gettext git-core gperf libasound2-dev libass-dev libboost-dev libboost-thread-dev libbz2-dev libcap-dev libcdio-dev libcurl3 libcurl4-gnutls-dev libdbus-1-dev libenca-dev libflac-dev libfontconfig-dev libfreetype6-dev libfribidi-dev libglew-dev libhal-dev libhal-storage-dev libiso9660-dev libjasper-dev libjpeg-dev liblzo2-dev libmad0-dev libmicrohttpd-dev libmodplug-dev libmpeg2-4-dev libmpeg3-dev libmysqlclient-dev libogg-dev libogg-dev libpcre3-dev libplist-dev libpng-dev libpulse-dev libsamplerate-dev libsdl-dev libsdl-gfx1.2-dev libsdl-image1.2-dev libsdl-mixer1.2-dev libsmbclient-dev libsqlite3-dev libssh-dev libssl-dev libtiff-dev libtinyxml-dev libtool libudev-dev libusb-dev libvdpau-dev libvorbisenc2 libxmu-dev libxrandr-dev libxrender-dev libxt-dev libyajl-dev mesa-utils nasm pmount python-dev python-imaging python-sqlite swig unzip yasm zip zlib1g-dev For >= 10.10: # sudo apt-get install autopoint libltdl-dev diff --git a/language/English/strings.po b/language/English/strings.po index dfc125cf4c..ca0904ada4 100644 --- a/language/English/strings.po +++ b/language/English/strings.po @@ -15,7 +15,7 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: xbmc/addons/addon.cpp -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#0" msgid "Programs" msgstr "" @@ -31,7 +31,7 @@ msgid "Music" msgstr "" #: Used in Confluence -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#3" msgid "Videos" msgstr "" @@ -491,7 +491,7 @@ msgid "Objects" msgstr "" #: xbmc/addons/guidialogaddonsettings.cpp -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#128" msgid "General" msgstr "" @@ -504,7 +504,7 @@ msgctxt "#130" msgid "System info" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#131" msgid "Display" msgstr "" @@ -665,7 +665,7 @@ msgid "Disc present" msgstr "" #: xbmc/addons/addon.cpp -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#166" msgid "Skin" msgstr "" @@ -678,12 +678,12 @@ msgstr "" #empty string with id 168 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#169" msgid "Resolution" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#170" msgid "Adjust display refresh rate to match video" msgstr "" @@ -694,7 +694,7 @@ msgctxt "#172" msgid "Release date" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#173" msgid "Display 4:3 videos as" msgstr "" @@ -800,7 +800,7 @@ msgid "Loading movie details" msgstr "" #: xbmc/addons/addon.cpp -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#199" msgid "Web interface" msgstr "" @@ -830,7 +830,7 @@ msgid "Plot" msgstr "" #: xbmc/dialogs/GUIDialogPlayEject.cpp -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#208" msgid "Play" msgstr "" @@ -849,7 +849,7 @@ msgctxt "#213" msgid "Calibrate user interface..." msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#214" msgid "Video calibration..." msgstr "" @@ -909,12 +909,12 @@ msgctxt "#225" msgid "Vertical Shift" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#226" msgid "Test patterns..." msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#227" msgid "Lookup audio CD track names from freedb.org" msgstr "" @@ -934,7 +934,7 @@ msgstr "" #: system/peripherals.xml #: xbmc/addons/guiviewstateaddonbrowser.cpp #: xbmc/dialogs/GUIDialogMediaSource.cpp -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#231" msgid "None" msgstr "" @@ -971,7 +971,7 @@ msgctxt "#239" msgid "Clear playlist on finish" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#240" msgid "Display Mode" msgstr "" @@ -984,7 +984,7 @@ msgctxt "#242" msgid "Windowed" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#243" msgid "Refresh Rate" msgstr "" @@ -1003,7 +1003,7 @@ msgctxt "#247" msgid "Scripts" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#248" msgid "Language" msgstr "" @@ -1013,7 +1013,7 @@ msgctxt "#249" msgid "Music" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#250" msgid "Visualization" msgstr "" @@ -1022,7 +1022,7 @@ msgctxt "#251" msgid "Select destination directory" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#252" msgid "Output stereo to all speakers" msgstr "" @@ -1031,7 +1031,7 @@ msgctxt "#253" msgid "Number of channels" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#254" msgid "- DTS capable receiver" msgstr "" @@ -1049,7 +1049,7 @@ msgctxt "#257" msgid "Error" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#258" msgid "Enable tag reading" msgstr "" @@ -1070,7 +1070,7 @@ msgctxt "#262" msgid "Scripts output" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#263" msgid "Allow control of XBMC via HTTP" msgstr "" @@ -1161,17 +1161,17 @@ msgctxt "#284" msgid "No results found" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#285" msgid "Preferred audio language" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#286" msgid "Preferred subtitle language" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#287" msgid "Subtitles" msgstr "" @@ -1180,7 +1180,7 @@ msgctxt "#288" msgid "Font" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#289" msgid "- Size" msgstr "" @@ -1220,7 +1220,7 @@ msgctxt "#298" msgid "Bookmarks" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#299" msgid "- AAC capable receiver" msgstr "" @@ -1247,7 +1247,7 @@ msgstr "" #: system/peripherals.xml #: xbmc/filesystem/AddonsDirectory.cpp -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#305" msgid "Enabled" msgstr "" @@ -1356,7 +1356,7 @@ msgctxt "#333" msgid "Do you want to clean the library?" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#334" msgid "Clean library..." msgstr "" @@ -1369,17 +1369,17 @@ msgctxt "#336" msgid "Framerate conversion" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#337" msgid "Audio output" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#338" msgid "Analog" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#339" msgid "Optical/Coax" msgstr "" @@ -1412,22 +1412,22 @@ msgctxt "#345" msgid "Year" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#346" msgid "Boost volume level on downmix" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#347" msgid "- DTS-HD capable receiver" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#348" msgid "- Multichannel LPCM capable receiver" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#349" msgid "- TrueHD capable receiver" msgstr "" @@ -1437,7 +1437,7 @@ msgctxt "#350" msgid "Programs" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/darwin.xml msgctxt "#351" msgid "Off" msgstr "" @@ -1454,17 +1454,17 @@ msgctxt "#354" msgid "Matrix trails" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#355" msgid "Screensaver time" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#356" msgid "Screensaver mode" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#357" msgid "Shutdown function timer" msgstr "" @@ -1478,7 +1478,7 @@ msgctxt "#359" msgid "Recently added albums" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#360" msgid "Screensaver" msgstr "" @@ -1495,7 +1495,7 @@ msgctxt "#363" msgid "Sort by: File" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#364" msgid "- Dolby Digital (AC3) capable receiver" msgstr "" @@ -1746,7 +1746,7 @@ msgctxt "#417" msgid "View: Big icons" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#418" msgid "Low" msgstr "" @@ -1755,7 +1755,7 @@ msgctxt "#419" msgid "High" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#420" msgid "HDMI" msgstr "" @@ -1832,7 +1832,7 @@ msgctxt "#438" msgid "Opening file" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#439" msgid "Cache" msgstr "" @@ -1871,7 +1871,7 @@ msgstr "" #empty string with id 448 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#449" msgid "Enabled" msgstr "" @@ -1989,7 +1989,7 @@ msgctxt "#479" msgid "Skin & language" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#480" msgid "Appearance" msgstr "" @@ -2020,7 +2020,7 @@ msgctxt "#488" msgid "Repeat folder" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#489" msgid "Play the next song automatically" msgstr "" @@ -2051,7 +2051,7 @@ msgctxt "#496" msgid "Calibration" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#497" msgid "Show file extensions" msgstr "" @@ -2104,7 +2104,7 @@ msgctxt "#511" msgid "Enable video mode switching" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#512" msgid "Startup window" msgstr "" @@ -2239,12 +2239,12 @@ msgctxt "#544" msgid "Media info" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#545" msgid "Audio output device" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#546" msgid "Passthrough output device" msgstr "" @@ -2473,17 +2473,17 @@ msgctxt "#600" msgid "Rip audio CD" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#601" msgid "Medium" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#602" msgid "Standard" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#603" msgid "Extreme" msgstr "" @@ -2528,22 +2528,22 @@ msgstr "" #empty strings from id 614 to 619 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#620" msgid "Audio CDs" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#621" msgid "Encoder" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#622" msgid "Quality" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#623" msgid "Bitrate" msgstr "" @@ -2566,12 +2566,12 @@ msgctxt "#629" msgid "View mode" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#630" msgid "Normal" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#631" msgid "Zoom" msgstr "" @@ -2580,12 +2580,12 @@ msgctxt "#632" msgid "Stretch 4:3" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#633" msgid "Wide Zoom" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#634" msgid "Stretch 16:9" msgstr "" @@ -2602,32 +2602,32 @@ msgctxt "#637" msgid "Replay gain" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#638" msgid "Replaygain volume adjustments" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#639" msgid "Use track levels" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#640" msgid "Use album levels" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#641" msgid "PreAmp Level - Replay gained files" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#642" msgid "PreAmp Level - Non replay gained files" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#643" msgid "Avoid clipping on replay gained files" msgstr "" @@ -2644,12 +2644,12 @@ msgctxt "#646" msgid "Remove from library" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#647" msgid "Export video library" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#648" msgid "Import video library" msgstr "" @@ -2720,12 +2720,17 @@ msgctxt "#664" msgid "Browse for Script" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#665" msgid "Compression level" msgstr "" -#empty strings from id 666 to 699 +#: xbmc/settings/settings.xml +msgctxt "#666" +msgid "Verbose logging..." +msgstr "" + +#empty strings from id 667 to 699 msgctxt "#700" msgid "Cleaning up library" @@ -2745,14 +2750,14 @@ msgctxt "#705" msgid "Network" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#706" msgid "- Server" msgstr "" #empty string with id 707 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#708" msgid "Use an HTTP proxy server to access the internet" msgstr "" @@ -2773,39 +2778,39 @@ msgstr "" #empty string with id 714 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#715" msgid "- Assignment" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#716" msgid "Automatic (DHCP)" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#717" msgid "Manual (Static)" msgstr "" #empty string with id 718 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#719" msgid "- IP address" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#720" msgid "- Netmask" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#721" msgid "- Default gateway" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#722" msgid "- DNS server" msgstr "" @@ -2836,7 +2841,7 @@ msgstr "" #empty string with id 729 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#730" msgid "- Port" msgstr "" @@ -2847,7 +2852,7 @@ msgctxt "#732" msgid "Save & apply" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#733" msgid "- Password" msgstr "" @@ -2856,37 +2861,37 @@ msgctxt "#734" msgid "No pass" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#735" msgid "- Character set" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#736" msgid "- Style" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#737" msgid "- Colour" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#738" msgid "Normal" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#739" msgid "Bold" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#740" msgid "Italics" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#741" msgid "Bold italics" msgstr "" @@ -2999,7 +3004,7 @@ msgstr "" #empty string with id 771 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#772" msgid "Audio output" msgstr "" @@ -3012,47 +3017,47 @@ msgctxt "#774" msgid "Slideshow folder" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#775" msgid "Network interface" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#776" msgid "- Wireless network name (ESSID)" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#777" msgid "- Wireless password" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#778" msgid "- Wireless security" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#779" msgid "Save and apply network interface settings" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#780" msgid "No encryption" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#781" msgid "WEP" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#782" msgid "WPA" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#783" msgid "WPA2" msgstr "" @@ -3069,7 +3074,7 @@ msgctxt "#786" msgid "Network interface did not start successfully." msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#787" msgid "Interface disabled" msgstr "" @@ -3083,37 +3088,37 @@ msgctxt "#789" msgid "Wireless network name (ESSID)" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#790" msgid "Remote control" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#791" msgid "Allow programs on this system to control XBMC" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#792" msgid "Port" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#793" msgid "Port range" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#794" msgid "Allow programs on other systems to control XBMC" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#795" msgid "Initial repeat delay (ms)" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#796" msgid "Continuous repeat delay (ms)" msgstr "" @@ -3122,7 +3127,7 @@ msgctxt "#797" msgid "Maximum number of clients" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#798" msgid "Internet access" msgstr "" @@ -3172,7 +3177,7 @@ msgctxt "#999" msgid "Add Videos..." msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#1000" msgid "- Preview" msgstr "" @@ -3396,7 +3401,7 @@ msgctxt "#1047" msgid "Other..." msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#1048" msgid "- Username" msgstr "" @@ -3416,32 +3421,32 @@ msgstr "" #empty strings from id 1052 to 1179 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#1180" msgid "Proxy type" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#1181" msgid "HTTP" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#1182" msgid "SOCKS4" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#1183" msgid "SOCKS4A" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#1184" msgid "SOCKS5" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#1185" msgid "SOCKS5 with remote dns resolving" msgstr "" @@ -3451,14 +3456,14 @@ msgstr "" #empty strings from id 1190 to 1199 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/win32.xml msgctxt "#1200" msgid "SMB client" msgstr "" #empty string with id 1201 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#1202" msgid "Workgroup" msgstr "" @@ -3473,7 +3478,7 @@ msgstr "" #empty strings from id 1205 to 1206 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#1207" msgid "WINS server" msgstr "" @@ -3585,39 +3590,41 @@ msgstr "" #empty strings from id 1236 to 1258 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#1259" msgid "Zeroconf" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#1260" msgid "Announce these services to other systems via Zeroconf" msgstr "" #empty strings from id 1261 to 1269 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#1270" msgid "Allow XBMC to receive AirPlay content" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#1271" msgid "Device name" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#1272" msgid "- Use password protection" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#1273" msgid "AirPlay" msgstr "" -#empty string with id 1274 +msgctxt "#1274" +msgid "AirTunes" +msgstr "" #. Filter movies/tvshows/music/episodes/artists/musicvideos/albums/songs #: xbmc/dialogs/GUIDialogMediaFilter.cpp @@ -3910,7 +3917,7 @@ msgstr "" #strings through to 1449 reserved for weather translation -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#1450" msgid "Put display to sleep when idle" msgstr "" @@ -4080,14 +4087,48 @@ msgctxt "#10034" msgid "Settings - Profiles" msgstr "" -#empty strings from id 10035 to 10039 +msgctxt "#10035" +msgid "Reset" +msgstr "" + +msgctxt "#10036" +msgid "Level: Basic" +msgstr "" + +msgctxt "#10037" +msgid "Level: Standard" +msgstr "" + +msgctxt "#10038" +msgid "Level: Advanced" +msgstr "" + +msgctxt "#10039" +msgid "Level: Expert" +msgstr "" #: xbmc/guilib/WindowIDs.h msgctxt "#10040" msgid "Addon browser" msgstr "" -#empty strings from id 10041 to 10099 +msgctxt "#10041" +msgid "Reset settings" +msgstr "" + +msgctxt "#10042" +msgid "Are you sure you want to reset the settings in this category?" +msgstr "" + +msgctxt "#10043" +msgid "Help" +msgstr "" + +msgctxt "#10044" +msgid "No help available" +msgstr "" + +#empty strings from id 10045 to 10099 #: xbmc/guilib/WindowIDs.h msgctxt "#10100" @@ -4596,12 +4637,12 @@ msgctxt "#12377" msgid "This will reset any previously saved values" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#12378" msgid "Amount of time to display each image" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#12379" msgid "Use pan and zoom effects" msgstr "" @@ -4676,7 +4717,7 @@ msgstr "" #empty strings from id 12906 to 12999 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13000" msgid "System" msgstr "" @@ -4698,29 +4739,29 @@ msgid "- Minimum file duration" msgstr "" #: system/peripherals.xml -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13005" msgid "Shutdown" msgstr "" #empty strings from id 13006 to 13007 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13008" msgid "Shutdown function" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13009" msgid "Quit" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13010" msgid "Hibernate" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml #: system/peripherals.xml msgctxt "#13011" msgid "Suspend" @@ -4734,7 +4775,7 @@ msgctxt "#13013" msgid "Reboot" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13014" msgid "Minimize" msgstr "" @@ -4793,29 +4834,29 @@ msgctxt "#13100" msgid "Flicker filter" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13101" msgid "Let driver choose (requires restart)" msgstr "" #empty strings from id 13102 to 13104 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13105" msgid "Vertical blank sync" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13106" msgid "Disabled" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13107" msgid "Enabled during video playback" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13108" msgid "Always enabled" msgstr "" @@ -4872,14 +4913,14 @@ msgctxt "#13121" msgid "VDPAU HQ Upscaling level" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13122" msgid "VDPAU Studio level color conversion" msgstr "" #empty strings from id 13123 to 13129 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13130" msgid "Blank other displays" msgstr "" @@ -5157,7 +5198,7 @@ msgctxt "#13302" msgid "Fan speed override" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13303" msgid "- Fonts" msgstr "" @@ -5166,17 +5207,17 @@ msgctxt "#13304" msgid "Enable flipping bi-directional strings" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13305" msgid "Show RSS news feeds" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13306" msgid "Show parent folder items" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13307" msgid "Track naming template" msgstr "" @@ -5205,7 +5246,7 @@ msgctxt "#13313" msgid "Restart" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13314" msgid "Crossfade between songs" msgstr "" @@ -5226,7 +5267,7 @@ msgctxt "#13318" msgid "Recursive slideshow" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13319" msgid "Randomize" msgstr "" @@ -5243,7 +5284,7 @@ msgctxt "#13322" msgid "Right only" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13323" msgid "Enable karaoke support" msgstr "" @@ -5260,7 +5301,7 @@ msgctxt "#13326" msgid "A/V delay" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13327" msgid "Karaoke" msgstr "" @@ -5386,7 +5427,7 @@ msgctxt "#13359" msgid "Set artist thumb" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13360" msgid "Automatically generate thumbnails" msgstr "" @@ -5445,7 +5486,7 @@ msgctxt "#13386" msgid "Use time based seeking" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13387" msgid "Track naming template - right" msgstr "" @@ -5468,7 +5509,7 @@ msgctxt "#13391" msgid "Eject/Load" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13392" msgid "Use visualization if playing audio" msgstr "" @@ -5499,12 +5540,12 @@ msgctxt "#13398" msgid "Shortcuts" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13399" msgid "Ignore articles when sorting (e.g. \"the\")" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13400" msgid "Crossfade between songs on the same album" msgstr "" @@ -5524,7 +5565,7 @@ msgctxt "#13403" msgid "Clear default" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13404" msgid "Resume" msgstr "" @@ -5566,17 +5607,17 @@ msgctxt "#13413" msgid "Downloading" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13414" msgid "Include artists who appear only on compilations" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13415" msgid "Render method" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13416" msgid "Auto detect" msgstr "" @@ -5589,7 +5630,7 @@ msgctxt "#13418" msgid "Advanced shaders (GLSL)" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13419" msgid "Software" msgstr "" @@ -5611,52 +5652,52 @@ msgctxt "#13423" msgid "Remember for this path" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13424" msgid "Use pixel buffer objects" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13425" msgid "Allow hardware acceleration (VDPAU)" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13426" msgid "Allow hardware acceleration (VAAPI)" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13427" msgid "Allow hardware acceleration (DXVA2)" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13428" msgid "Allow hardware acceleration (CrystalHD)" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13429" msgid "Allow hardware acceleration (VDADecoder)" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13430" msgid "Allow hardware acceleration (OpenMax)" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13431" msgid "Pixel Shaders" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13432" msgid "Allow hardware acceleration (VideoToolbox)" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13433" msgid "Play the next video automatically" msgstr "" @@ -5667,59 +5708,59 @@ msgctxt "#13434" msgid "Play only this" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13435" -msgid "Enable HQ Scalers for scalings above %" +msgid "Enable HQ Scalers for scalings above" msgstr "" #empty strings from id 13436 to 13499 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13500" msgid "A/V sync method" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13501" msgid "Audio clock" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13502" msgid "Video clock (Drop/Dupe audio)" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13503" msgid "Video clock (Resample audio)" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13504" msgid "Maximum resample amount (%)" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13505" msgid "Resample quality" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13506" msgid "Low(fast)" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13507" msgid "Medium" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13508" msgid "High" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13509" msgid "Really high(slow!)" msgstr "" @@ -5760,7 +5801,7 @@ msgstr "" #empty strings from id 13517 to 13549 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#13550" msgid "Pause during refresh rate change" msgstr "" @@ -5779,41 +5820,41 @@ msgstr "" #empty strings from id 13554 to 13599 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/darwin.xml msgctxt "#13600" msgid "Apple remote" msgstr "" #empty string with id 13601 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/darwin.xml msgctxt "#13602" msgid "Allow start of XBMC using the remote" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/darwin.xml msgctxt "#13603" msgid "Sequence delay time" msgstr "" #empty strings from id 13604 to 13609 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/darwin.xml msgctxt "#13610" msgid "Disabled" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/darwin.xml msgctxt "#13611" msgid "Standard" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/darwin.xml msgctxt "#13612" msgid "Universal Remote" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/darwin.xml msgctxt "#13613" msgid "Multi Remote (Harmony)" msgstr "" @@ -5914,7 +5955,7 @@ msgctxt "#14021" msgid "Change area code 3" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14022" msgid "Library" msgstr "" @@ -5927,56 +5968,56 @@ msgctxt "#14024" msgid "Enter the nearest large town" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14025" msgid "Video/Audio/DVD cache - Harddisk" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14026" msgid "Video cache - DVD-ROM" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14027" msgid "- Local Network" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14028" msgid "- Internet" msgstr "" #empty string with id 14029 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14030" msgid "Audio cache - DVD-ROM" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14031" msgid "- Local Network" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14032" msgid "- Internet" msgstr "" #empty string with id 14033 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14034" msgid "DVD cache - DVD-ROM" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14035" msgid "- Local Network" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14036" msgid "Services" msgstr "" @@ -5995,7 +6036,7 @@ msgctxt "#14040" msgid "network setup. Would you like to restart now?" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14041" msgid "Internet connection bandwidth limitation" msgstr "" @@ -6006,37 +6047,37 @@ msgctxt "#14043" msgid "- Shutdown while playing" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14044" msgid "%i min" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14045" msgid "%i sec" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/darwin.xml msgctxt "#14046" msgid "%i ms" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14047" msgid "%i %%" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14048" msgid "%i kbps" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14049" msgid "%i kb" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14050" msgid "%i.0 dB" msgstr "" @@ -6071,12 +6112,12 @@ msgctxt "#14058" msgid "Film grain effect" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14059" msgid "Search for thumbnails on remote shares" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14060" msgid "Unknown type cache - Internet" msgstr "" @@ -6121,7 +6162,7 @@ msgctxt "#14070" msgid "Apply changes now" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14071" msgid "Allow file renaming and deletion" msgstr "" @@ -6148,74 +6189,74 @@ msgctxt "#14077" msgid "Remove from favourites" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14078" msgid "- Colours" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14079" msgid "Timezone country" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14080" msgid "Timezone" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14081" msgid "File lists" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14082" msgid "Show EXIF picture information" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14083" msgid "Use a fullscreen window rather than true fullscreen" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14084" msgid "Queue songs on selection" msgstr "" #empty string with id 14085 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14086" msgid "Playback" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14087" msgid "DVDs" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14088" msgid "Play DVDs automatically" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14089" msgid "Font to use for text subtitles" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14090" msgid "International" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14091" msgid "Character set" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14092" msgid "Debugging" msgstr "" @@ -6228,27 +6269,27 @@ msgctxt "#14094" msgid "Input devices" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14095" msgid "Power saving" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14096" msgid "Rip" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14097" msgid "Audio CD Insert Action" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14098" msgid "Play" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#14099" msgid "Eject disc when CD ripping is complete" msgstr "" @@ -6323,7 +6364,7 @@ msgctxt "#15107" msgid "Buffering..." msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#15108" msgid "Navigation sounds" msgstr "" @@ -6334,12 +6375,12 @@ msgstr "" #empty string with id 15110 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#15111" msgid "- Theme" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#15112" msgid "Default theme" msgstr "" @@ -6417,7 +6458,7 @@ msgstr "" #empty strings from id 15312 to 15999 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#16000" msgid "General" msgstr "" @@ -6483,7 +6524,7 @@ msgctxt "#16017" msgid "Enter search string" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#16018" msgid "None" msgstr "" @@ -6763,17 +6804,17 @@ msgstr "" #empty strings from id 17501 to 17996 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#17997" msgid "%i MByte" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#17998" msgid "%i hours" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#17999" msgid "%i days" msgstr "" @@ -6855,7 +6896,7 @@ msgctxt "#19017" msgid "TV recordings" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19018" msgid "Default folder for PVR thumbnails" msgstr "" @@ -6934,7 +6975,7 @@ msgctxt "#19036" msgid "This recording cannot be played. Check the log for details." msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19037" msgid "Show signal quality" msgstr "" @@ -6959,7 +7000,7 @@ msgctxt "#19042" msgid "Are you sure you want to rename this timer?" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19043" msgid "Recording" msgstr "" @@ -7049,7 +7090,7 @@ msgctxt "#19064" msgid "Go to end" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19065" msgid "Default EPG window" msgstr "" @@ -7064,7 +7105,7 @@ msgctxt "#19068" msgid "This recording could not be deleted. Check the log for details." msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19069" msgid "EPG" msgstr "" @@ -7075,12 +7116,12 @@ msgctxt "#19071" msgid "EPG update interval" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19072" msgid "Do not store the EPG in the database" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19073" msgid "Delay channel switch" msgstr "" @@ -7238,7 +7279,7 @@ msgctxt "#19116" msgid "Disksize" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19117" msgid "Search for channels" msgstr "" @@ -7438,7 +7479,7 @@ msgctxt "#19166" msgid "PVR information" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19167" msgid "Scan for missing icons" msgstr "" @@ -7449,79 +7490,79 @@ msgctxt "#19169" msgid "Hide video information box" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19170" msgid "Timeout when starting playback" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19171" msgid "Start playback minimized" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19172" msgid "Instant recording duration" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19173" msgid "Default recording priority" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19174" msgid "Default recording lifetime" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19175" msgid "Margin at the start of a recording" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19176" msgid "Margin at the end of a recording" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19177" msgid "Playback" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19178" msgid "Show channel information when switching channels" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19179" msgid "Automatically hide channel information" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19180" msgid "TV" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19181" msgid "Menu/OSD" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19182" msgid "Days to display in the EPG" msgstr "" #empty string with id 19183 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19184" msgid "Channel information duration" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19185" msgid "Reset the PVR database" msgstr "" @@ -7530,7 +7571,7 @@ msgctxt "#19186" msgid "All data in the PVR database is being erased" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19187" msgid "Reset the EPG database" msgstr "" @@ -7539,7 +7580,7 @@ msgctxt "#19188" msgid "EPG is being reset" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19189" msgid "Continue last channel on startup" msgstr "" @@ -7582,7 +7623,7 @@ msgctxt "#19198" msgid "Recording finished on: %s" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19199" msgid "Channel manager" msgstr "" @@ -7671,7 +7712,7 @@ msgctxt "#19220" msgid "Channels in" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19221" msgid "Synchronise channel groups with backends" msgstr "" @@ -7708,12 +7749,12 @@ msgctxt "#19229" msgid "Close channel OSD after switching channels" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19230" msgid "Prevent EPG updates while playing a TV stream" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19231" msgid "Always use the channel order from the backend(s)" msgstr "" @@ -7722,12 +7763,12 @@ msgctxt "#19232" msgid "Clear search results" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19233" msgid "Display a notification on timer updates" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19234" msgid "Use backend channels numbers (only works with 1 enabled PVR addon)" msgstr "" @@ -7768,27 +7809,27 @@ msgctxt "#19243" msgid "in order to use the PVR functionality." msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19244" msgid "Backend idle time" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19245" msgid "Set wakeup command (cmd [timestamp])" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19246" msgid "Wakeup before recording" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19247" msgid "Daily wakeup" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19248" msgid "Daily wakeup time (HH:MM:SS)" msgstr "" @@ -7834,17 +7875,17 @@ msgctxt "#19258" msgid "Unlock channel" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19259" msgid "Parental control" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19260" msgid "Unlock duration" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19261" msgid "Change PIN" msgstr "" @@ -7874,12 +7915,12 @@ msgctxt "#19267" msgid "Parental locked:" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19268" msgid "Do not show 'no information available' labels" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19269" msgid "Do not show 'connection lost' warnings" msgstr "" @@ -7924,17 +7965,17 @@ msgctxt "#19278" msgid "Recording error" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19279" msgid "Client specific" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19280" msgid "Client specific settings" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#19281" msgid "Confirm channel switches by pressing OK" msgstr "" @@ -8410,7 +8451,7 @@ msgstr "" #empty strings from id 19685 to 19999 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#20000" msgid "Saved music folder" msgstr "" @@ -8427,14 +8468,14 @@ msgctxt "#20003" msgid "Trainers folder" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#20004" msgid "Screenshot folder" msgstr "" #empty string with id 20005 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#20006" msgid "Playlists folder" msgstr "" @@ -8519,7 +8560,7 @@ msgctxt "#20025" msgid "Scan all" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#20026" msgid "Region" msgstr "" @@ -8688,7 +8729,7 @@ msgctxt "#20075" msgid "Enter master lock code" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#20076" msgid "Ask for master lock code on startup" msgstr "" @@ -8785,7 +8826,7 @@ msgctxt "#20099" msgid "Can't rip CD or track while playing from CD" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#20100" msgid "Master lock code and settings" msgstr "" @@ -8823,7 +8864,7 @@ msgctxt "#20108" msgid "Root" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#20109" msgid "- Zoom" msgstr "" @@ -9140,7 +9181,7 @@ msgctxt "#20183" msgid "Reload skin" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#20184" msgid "Rotate pictures using EXIF information" msgstr "" @@ -9153,13 +9194,13 @@ msgctxt "#20186" msgid "Please wait" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#20187" msgid "UPnP" msgstr "" #: xbmc/network/upnp/UPnPServer.cpp -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#20188" msgid "Announce library updates via UPnP" msgstr "" @@ -9172,22 +9213,22 @@ msgctxt "#20190" msgid "Custom" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#20191" msgid "Enable debug logging" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#20192" msgid "Download additional information during updates" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#20193" msgid "Default service for album information" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#20194" msgid "Default service for artist information" msgstr "" @@ -9196,12 +9237,12 @@ msgctxt "#20195" msgid "Change scraper" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#20196" msgid "Export music library" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#20197" msgid "Import music library" msgstr "" @@ -9578,7 +9619,7 @@ msgctxt "#20368" msgid "Prod code" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#20369" msgid "Show plot for unwatched items" msgstr "" @@ -9632,7 +9673,7 @@ msgctxt "#20381" msgid "Specials" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#20382" msgid "Automatically grab season thumbs" msgstr "" @@ -9724,7 +9765,7 @@ msgctxt "#20401" msgid "Play music video" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#20402" msgid "Download actor thumbnails when adding to library" msgstr "" @@ -9766,7 +9807,7 @@ msgctxt "#20411" msgid "Flatten" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#20412" msgid "Flatten TV shows" msgstr "" @@ -9798,22 +9839,22 @@ msgctxt "#20418" msgid "Writers" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#20419" msgid "Replace file names with library titles" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#20420" msgid "Never" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#20421" msgid "If only one season" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#20422" msgid "Always" msgstr "" @@ -9858,7 +9899,7 @@ msgctxt "#20432" msgid "Exclude path from library updates" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#20433" msgid "Extract thumbnails and video information" msgstr "" @@ -9964,7 +10005,7 @@ msgctxt "#20457" msgid "Movie set" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#20458" msgid "Group movies in sets" msgstr "" @@ -10021,7 +10062,7 @@ msgstr "" #empty strings from id 20470 to 21329 #up to 21329 is reserved for the video db !! ! -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#21330" msgid "Show hidden files and directories" msgstr "" @@ -10064,7 +10105,7 @@ msgctxt "#21359" msgid "Add media share..." msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#21360" msgid "Share video and music libraries through UPnP" msgstr "" @@ -10095,7 +10136,7 @@ msgctxt "#21365" msgid "Remove media share" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#21366" msgid "Subtitle folder" msgstr "" @@ -10104,12 +10145,12 @@ msgctxt "#21367" msgid "Movie & alternate subtitle directory" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#21368" msgid "Override ASS/SSA subtitles fonts" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#21369" msgid "Enable mouse and Touch Screen support" msgstr "" @@ -10122,12 +10163,12 @@ msgctxt "#21371" msgid "Thumbnail" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#21372" msgid "Forced DVD player region" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/darwin.xml msgctxt "#21373" msgid "Video output" msgstr "" @@ -10164,7 +10205,7 @@ msgctxt "#21381" msgid "Enter name of new playlist" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#21382" msgid "Show \"Add source\" buttons in file lists" msgstr "" @@ -10289,24 +10330,24 @@ msgctxt "#21412" msgid "Scrapers" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#21413" msgid "Default movie scraper" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#21414" msgid "Default tvshow scraper" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#21415" msgid "Default music video scraper" msgstr "" #empty string with id 21416 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#21417" msgid "- Settings" msgstr "" @@ -10441,12 +10482,12 @@ msgctxt "#21448" msgid "Subtitle language" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#21449" msgid "Remote control sends keyboard presses" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#21450" msgid "- Edit" msgstr "" @@ -10489,32 +10530,32 @@ msgctxt "#21459" msgid "mixed" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#21460" msgid "Subtitle location" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#21461" msgid "Fixed" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#21462" msgid "Bottom of video" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#21463" msgid "Below video" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#21464" msgid "Top of video" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#21465" msgid "Above video" msgstr "" @@ -10773,12 +10814,12 @@ msgctxt "#21880" msgid "Reference service" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#21881" msgid "Allow control of XBMC via UPnP" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#21882" msgid "Attempt to skip introduction before DVD menu" msgstr "" @@ -10862,17 +10903,17 @@ msgstr "" #empty strings from id 21901 to 21999 #strings 21900 thru 21999 reserved for slideshow info -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#22000" msgid "Update library on startup" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#22001" msgid "Hide progress of library updates" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#22002" msgid "- DNS suffix" msgstr "" @@ -10926,7 +10967,7 @@ msgctxt "#22013" msgid "Profile data" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#22014" msgid "Use dim if paused during video playback" msgstr "" @@ -10955,12 +10996,12 @@ msgctxt "#22020" msgid "Guide" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#22021" msgid "Allowed error in aspect ratio to minimize black bars" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#22022" msgid "Show video files in listings" msgstr "" @@ -10978,22 +11019,22 @@ msgstr "" #empty strings from id 22025 to 22029 #strings 22030 thru 22060 reserved for karaoke -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#22030" msgid "Font" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#22031" msgid "- Size" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#22032" msgid "- Colours" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#22033" msgid "- Charset" msgstr "" @@ -11006,17 +11047,17 @@ msgctxt "#22035" msgid "Export karaoke titles as CSV" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#22036" msgid "Import karaoke titles..." msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#22037" msgid "Show song selector automatically" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#22038" msgid "Export karaoke titles..." msgstr "" @@ -11025,7 +11066,7 @@ msgctxt "#22039" msgid "Enter song number" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#22040" msgid "white/green" msgstr "" @@ -11044,17 +11085,17 @@ msgstr "" #empty strings from id 22044 to 22078 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#22079" msgid "Default select action" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#22080" msgid "Choose" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#22081" msgid "Show Information" msgstr "" @@ -11073,7 +11114,7 @@ msgctxt "#23049" msgid "Teletext not available" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#23050" msgid "Activate Teletext" msgstr "" @@ -11094,7 +11135,7 @@ msgctxt "#23054" msgid "Running" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#23055" msgid "Scale Teletext to 4:3" msgstr "" @@ -11239,7 +11280,7 @@ msgctxt "#24028" msgid "Weather.com (standard)" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#24029" msgid "Service for weather information" msgstr "" @@ -11905,7 +11946,7 @@ msgid "Failed to start" msgstr "" #: xbmc/network/network.cpp -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#33101" msgid "Webserver" msgstr "" @@ -12020,25 +12061,25 @@ msgstr "" #empty strings from id 34111 to 34119 #34111-34119 reserved for future use -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#34120" msgid "Play GUI sounds" msgstr "" #. play GUI sounds -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#34121" msgid "Only when playback stopped" msgstr "" #. play GUI sounds -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#34122" msgid "Always" msgstr "" #. play GUI sounds -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#34123" msgid "Never" msgstr "" @@ -12060,7 +12101,7 @@ msgstr "" xbmc\network\windows\ZeroconfWIN.cpp msgctxt "#34300" -msgid "Failed to start zeroconf" +msgid "Failed to start Zeroconf" msgstr "" #: xbmc\network\windows\ZeroconfWIN.cpp @@ -12068,7 +12109,19 @@ msgctxt "#34301" msgid "Is Apple's Bonjour Service installed? See log for more info." msgstr "" -#empty strings from id 34302 to 34399 +msgctxt "#34302" +msgid "AirPlay requires Zeroconf to be enabled." +msgstr "" + +msgctxt "#34303" +msgid "Unable to stop Zeroconf" +msgstr "" + +msgctxt "#34304" +msgid "AirPlay and AirTunes depend on Zeroconf running." +msgstr "" + +#empty strings from id 34305 to 34399 #: xbmc\cores\VideoRenderers\LinuxRendererGL.cpp msgctxt "#34400" @@ -12173,7 +12226,7 @@ msgstr "" #empty strings from id 35010 to 35099 -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#35100" msgid "Enable joystick and gamepad support" msgstr "" @@ -12182,7 +12235,7 @@ msgstr "" #: system/peripherals.xml msgctxt "#35102" -msgid "Disable joystick when device is present" +msgid "Disable joystick when this device is present" msgstr "" #empty strings from id 35103 to 35499 @@ -12380,13 +12433,13 @@ msgstr "" #empty string with id 36034 #. adjust refreshrate -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#36035" msgid "Always" msgstr "" #. adjust refreshrate -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#36036" msgid "On start/stop" msgstr "" @@ -12420,7 +12473,7 @@ msgctxt "#36041" msgid "* Item folder" msgstr "" -#: xbmc/settings/GUISettings.cpp +#: xbmc/settings/settings.xml msgctxt "#36042" msgid "Use limited color range (16-235)" msgstr "" @@ -12459,3 +12512,9 @@ msgstr "" msgctxt "#37014" msgid "Last used profile" msgstr "" + +#: xbmc/Windows/GUIMediaWindow.cpp +msgctxt "#37015" +msgid "Browse Into" +msgstr "" + diff --git a/language/Galician/langinfo.xml b/language/Galician/langinfo.xml index 314540df02..4271cb4d14 100644 --- a/language/Galician/langinfo.xml +++ b/language/Galician/langinfo.xml @@ -11,15 +11,15 @@ </dvd> <regions> <region name="Santiago, Galicia" locale="GL"> - <dateshort>D/M/YYYY</dateshort> - <datelong>DDD, DD' de 'MMMM' de 'YYYY</datelong> + <dateshort>DD/MM/YYYY</dateshort> + <datelong>DDDD, DD' de 'MMMM' de 'YYYY</datelong> <time symbolAM="AM" symbolPM="PM">H:mm:ss</time> <tempunit>C</tempunit> <speedunit>kmh</speedunit> </region> <region name="La Coruna, Galicia" locale="GL"> - <dateshort>D/M/YYYY</dateshort> - <datelong>DDD, DD' de 'MMMM' de 'YYYY</datelong> + <dateshort>DD/MM/YYYY</dateshort> + <datelong>DDDD, DD' de 'MMMM' de 'YYYY</datelong> <time symbolAM="AM" symbolPM="PM">H:mm:ss</time> <tempunit>C</tempunit> <speedunit>kmh</speedunit> diff --git a/language/Spanish (Argentina)/langinfo.xml b/language/Spanish (Argentina)/langinfo.xml index ea186f5f69..3036587b25 100644 --- a/language/Spanish (Argentina)/langinfo.xml +++ b/language/Spanish (Argentina)/langinfo.xml @@ -13,8 +13,8 @@ <regions> <region name="Argentina" locale="AR"> - <dateshort>D/M/YYYY</dateshort> - <datelong>DDD, DD' de 'MMMM' de 'YYYY</datelong> + <dateshort>DD/MM/YYYY</dateshort> + <datelong>DDDD, DD' de 'MMMM' de 'YYYY</datelong> <time symbolAM="" symbolPM="">H:mm:ss</time> <tempunit>C</tempunit> <speedunit>kmh</speedunit> diff --git a/language/Spanish/langinfo.xml b/language/Spanish/langinfo.xml index 3d8bb65801..6a94d8a79e 100644 --- a/language/Spanish/langinfo.xml +++ b/language/Spanish/langinfo.xml @@ -13,32 +13,32 @@ <regions> <region name="España (12 horas)" locale="ES"> - <dateshort>D/M/YYYY</dateshort> - <datelong>DDD, DD' de 'MMMM' de 'YYYY</datelong> + <dateshort>DD/MM/YYYY</dateshort> + <datelong>DDDD, DD' de 'MMMM' de 'YYYY</datelong> <time symbolAM="AM" symbolPM="PM">h:mm:ss xx</time> <tempunit>C</tempunit> <speedunit>kmh</speedunit> <timezone>CEST</timezone> </region> <region name="España (24 horas)" locale="ES"> - <dateshort>D/M/YYYY</dateshort> - <datelong>DDD, DD' de 'MMMM' de 'YYYY</datelong> + <dateshort>DD/MM/YYYY</dateshort> + <datelong>DDDD, DD' de 'MMMM' de 'YYYY</datelong> <time symbolAM="" symbolPM="">H:mm:ss</time> <tempunit>C</tempunit> <speedunit>kmh</speedunit> <timezone>CEST</timezone> </region> <region name="Canarias (12 horas)" locale="ES"> - <dateshort>D/M/YYYY</dateshort> - <datelong>DDD, DD' de 'MMMM' de 'YYYY</datelong> + <dateshort>DD/MM/YYYY</dateshort> + <datelong>DDDD, DD' de 'MMMM' de 'YYYY</datelong> <time symbolAM="AM" symbolPM="PM">h:mm:ss xx</time> <tempunit>C</tempunit> <speedunit>kmh</speedunit> <timezone>GMT</timezone> </region> <region name="Canarias (24 horas)" locale="ES"> - <dateshort>D/M/YYYY</dateshort> - <datelong>DDD, DD' de 'MMMM' de 'YYYY</datelong> + <dateshort>DD/MM/YYYY</dateshort> + <datelong>DDDD, DD' de 'MMMM' de 'YYYY</datelong> <time symbolAM="" symbolPM="">H:mm:ss</time> <tempunit>C</tempunit> <speedunit>kmh</speedunit> diff --git a/lib/DllAvCodec.h b/lib/DllAvCodec.h index 2b4ee22633..96bd68d1d6 100644 --- a/lib/DllAvCodec.h +++ b/lib/DllAvCodec.h @@ -87,6 +87,7 @@ public: virtual int avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt)=0; virtual int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, int *got_sub_ptr, AVPacket *avpkt)=0; virtual int avcodec_encode_audio(AVCodecContext *avctx, uint8_t *buf, int buf_size, const short *samples)=0; + virtual int avcodec_encode_audio2(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr)=0; virtual int avpicture_get_size(PixelFormat pix_fmt, int width, int height)=0; virtual AVCodecContext *avcodec_alloc_context3(AVCodec *codec)=0; virtual void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)=0; @@ -111,6 +112,8 @@ public: virtual AVCodec *av_codec_next(AVCodec *c)=0; virtual int av_dup_packet(AVPacket *pkt)=0; virtual void av_init_packet(AVPacket *pkt)=0; + virtual int avcodec_fill_audio_frame(AVFrame *frame, int nb_channels, enum AVSampleFormat sample_fmt, const uint8_t *buf, int buf_size, int align) = 0; + virtual void avcodec_free_frame(AVFrame **frame)=0; }; #if (defined USE_EXTERNAL_FFMPEG) || (defined TARGET_DARWIN) @@ -148,6 +151,7 @@ public: virtual int avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { return ::avcodec_decode_audio4(avctx, frame, got_frame_ptr, avpkt); } virtual int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, int *got_sub_ptr, AVPacket *avpkt) { return ::avcodec_decode_subtitle2(avctx, sub, got_sub_ptr, avpkt); } virtual int avcodec_encode_audio(AVCodecContext *avctx, uint8_t *buf, int buf_size, const short *samples) { return ::avcodec_encode_audio(avctx, buf, buf_size, samples); } + virtual int avcodec_encode_audio2(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr) { return ::avcodec_encode_audio2(avctx, avpkt, frame, got_packet_ptr); } virtual int avpicture_get_size(PixelFormat pix_fmt, int width, int height) { return ::avpicture_get_size(pix_fmt, width, height); } virtual AVCodecContext *avcodec_alloc_context3(AVCodec *codec) { return ::avcodec_alloc_context3(codec); } virtual void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) { ::avcodec_string(buf, buf_size, enc, encode); } @@ -179,6 +183,8 @@ public: virtual int av_dup_packet(AVPacket *pkt) { return ::av_dup_packet(pkt); } virtual void av_init_packet(AVPacket *pkt) { return ::av_init_packet(pkt); } + virtual int avcodec_fill_audio_frame(AVFrame *frame, int nb_channels, enum AVSampleFormat sample_fmt, const uint8_t *buf, int buf_size, int align) { return ::avcodec_fill_audio_frame(frame, nb_channels, sample_fmt, buf, buf_size, align); } + virtual void avcodec_free_frame(AVFrame **frame) { return ::avcodec_free_frame(frame); }; // DLL faking. virtual bool ResolveExports() { return true; } @@ -200,6 +206,7 @@ class DllAvCodec : public DllDynamic, DllAvCodecInterface DEFINE_FUNC_ALIGNED4(int, __cdecl, avcodec_decode_audio4, AVCodecContext*, AVFrame*, int*, AVPacket*) DEFINE_FUNC_ALIGNED4(int, __cdecl, avcodec_decode_subtitle2, AVCodecContext*, AVSubtitle*, int*, AVPacket*) DEFINE_FUNC_ALIGNED4(int, __cdecl, avcodec_encode_audio, AVCodecContext*, uint8_t*, int, const short*) + DEFINE_FUNC_ALIGNED4(int, __cdecl, avcodec_encode_audio2, AVCodecContext*, AVPacket*, const AVFrame*, int*) DEFINE_FUNC_ALIGNED1(AVCodecContext*, __cdecl, avcodec_alloc_context3, AVCodec *) DEFINE_FUNC_ALIGNED1(AVCodecParserContext*, __cdecl, av_parser_init, int) DEFINE_FUNC_ALIGNED9(int, __cdecl, av_parser_parse2, AVCodecParserContext*,AVCodecContext*, uint8_t**, int*, const uint8_t*, int, int64_t, int64_t, int64_t) @@ -227,6 +234,8 @@ class DllAvCodec : public DllDynamic, DllAvCodecInterface DEFINE_METHOD2(int, avcodec_default_get_buffer, (AVCodecContext *p1, AVFrame *p2)) DEFINE_METHOD2(void, avcodec_default_release_buffer, (AVCodecContext *p1, AVFrame *p2)) DEFINE_METHOD2(enum PixelFormat, avcodec_default_get_format, (struct AVCodecContext *p1, const enum PixelFormat *p2)) + DEFINE_METHOD6(int, avcodec_fill_audio_frame, (AVFrame* p1, int p2, enum AVSampleFormat p3, const uint8_t* p4, int p5, int p6)) + DEFINE_METHOD1(void, avcodec_free_frame, (AVFrame **p1)) DEFINE_METHOD1(AVCodec*, av_codec_next, (AVCodec *p1)) BEGIN_METHOD_RESOLVE() @@ -242,6 +251,7 @@ class DllAvCodec : public DllDynamic, DllAvCodecInterface RESOLVE_METHOD(avcodec_decode_audio4) RESOLVE_METHOD(avcodec_decode_subtitle2) RESOLVE_METHOD(avcodec_encode_audio) + RESOLVE_METHOD(avcodec_encode_audio2) RESOLVE_METHOD(avpicture_get_size) RESOLVE_METHOD(avcodec_alloc_context3) RESOLVE_METHOD(avcodec_string) @@ -261,6 +271,8 @@ class DllAvCodec : public DllDynamic, DllAvCodecInterface RESOLVE_METHOD(av_codec_next) RESOLVE_METHOD(av_dup_packet) RESOLVE_METHOD(av_init_packet) + RESOLVE_METHOD(avcodec_fill_audio_frame) + RESOLVE_METHOD(avcodec_free_frame) END_METHOD_RESOLVE() /* dependencies of libavcodec */ diff --git a/lib/DllAvFormat.h b/lib/DllAvFormat.h index 7fc831e875..b0dcb54d3f 100644 --- a/lib/DllAvFormat.h +++ b/lib/DllAvFormat.h @@ -42,13 +42,14 @@ extern "C" { #else #include <ffmpeg/avformat.h> #endif - /* av_read_frame_flush() is defined for us in lib/xbmc-dll-symbols/DllAvFormat.c */ - // void av_read_frame_flush(AVFormatContext *s); // av_read_frame_flush decrepated - void ff_read_frame_flush(AVFormatContext *s); // internal replacement + /* xbmc_read_frame_flush() is defined for us in lib/xbmc-dll-symbols/DllAvFormat.c */ + void xbmc_read_frame_flush(AVFormatContext *s); #else #include "libavformat/avformat.h" - void ff_read_frame_flush(AVFormatContext *s); // internal replacement - + #if defined(TARGET_DARWIN) + void ff_read_frame_flush(AVFormatContext *s); // internal replacement + #define xbmc_read_frame_flush ff_read_frame_flush + #endif #endif } @@ -118,7 +119,7 @@ public: virtual AVInputFormat *av_find_input_format(const char *short_name) { return ::av_find_input_format(short_name); } virtual void avformat_close_input(AVFormatContext **s) { ::avformat_close_input(s); } virtual int av_read_frame(AVFormatContext *s, AVPacket *pkt) { return ::av_read_frame(s, pkt); } - virtual void av_read_frame_flush(AVFormatContext *s) { ::ff_read_frame_flush(s); } // av_read_frame_flush decrepated + virtual void av_read_frame_flush(AVFormatContext *s) { ::xbmc_read_frame_flush(s); } virtual int av_read_play(AVFormatContext *s) { return ::av_read_play(s); } virtual int av_read_pause(AVFormatContext *s) { return ::av_read_pause(s); } virtual int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) { return ::av_seek_frame(s, stream_index, timestamp, flags); } diff --git a/lib/ffmpeg/libavcodec/mpeg12.c b/lib/ffmpeg/libavcodec/mpeg12.c index 9d2743a6df..0f947726ee 100644 --- a/lib/ffmpeg/libavcodec/mpeg12.c +++ b/lib/ffmpeg/libavcodec/mpeg12.c @@ -1202,6 +1202,7 @@ static const enum AVPixelFormat mpeg1_hwaccel_pixfmt_list_420[] = { #endif #if CONFIG_MPEG1_VDPAU_HWACCEL AV_PIX_FMT_VDPAU_MPEG1, + AV_PIX_FMT_VDPAU, #endif AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE @@ -1214,6 +1215,7 @@ static const enum AVPixelFormat mpeg2_hwaccel_pixfmt_list_420[] = { #endif #if CONFIG_MPEG2_VDPAU_HWACCEL AV_PIX_FMT_VDPAU_MPEG2, + AV_PIX_FMT_VDPAU, #endif #if CONFIG_MPEG2_DXVA2_HWACCEL AV_PIX_FMT_DXVA2_VLD, diff --git a/lib/ffmpeg/libavcodec/vdpau_vc1.c b/lib/ffmpeg/libavcodec/vdpau_vc1.c index f5da9bbe1f..993ef2614a 100644 --- a/lib/ffmpeg/libavcodec/vdpau_vc1.c +++ b/lib/ffmpeg/libavcodec/vdpau_vc1.c @@ -59,7 +59,7 @@ static int vdpau_vc1_start_frame(AVCodecContext *avctx, else info->picture_type = s->pict_type - 1 + s->pict_type / 3; - info->frame_coding_mode = v->fcm; + info->frame_coding_mode = v->fcm ? v->fcm + 1 : 0; info->postprocflag = v->postprocflag; info->pulldown = v->broadcast; info->interlace = v->interlace; diff --git a/lib/ffmpeg/patches/0028-ffmpeg-1.2-fixed-dvd-still-frames-ended-up-in-intern.patch b/lib/ffmpeg/patches/0028-ffmpeg-1.2-fixed-dvd-still-frames-ended-up-in-intern.patch index d294ff174e..17ec941c7f 100644 --- a/lib/ffmpeg/patches/0028-ffmpeg-1.2-fixed-dvd-still-frames-ended-up-in-intern.patch +++ b/lib/ffmpeg/patches/0028-ffmpeg-1.2-fixed-dvd-still-frames-ended-up-in-intern.patch @@ -5,13 +5,13 @@ Subject: [PATCH 4/4] ffmpeg 1.2 - fixed dvd still frames ended up in internal lavf --- - lib/ffmpeg/libavformat/utils.c | 2 +- + libavformat/utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -diff --git a/lib/ffmpeg/libavformat/utils.c b/lib/ffmpeg/libavformat/utils.c +diff --git a/libavformat/utils.c b/libavformat/utils.c index c3bd3d9..72f59d2 100644 ---- a/lib/ffmpeg/libavformat/utils.c -+++ b/lib/ffmpeg/libavformat/utils.c +--- a/libavformat/utils.c ++++ b/libavformat/utils.c @@ -706,7 +706,7 @@ no_packet: if(end || av_log2(pd->buf_size) != av_log2(pd->buf_size - pkt->size)){ diff --git a/lib/ffmpeg/patches/0036-backport-register-vdpau-hwaccel-for-mpeg12-fe1f36547d0be963e352de0cde1a6cba59ea2e78.patch b/lib/ffmpeg/patches/0036-backport-register-vdpau-hwaccel-for-mpeg12-fe1f36547d0be963e352de0cde1a6cba59ea2e78.patch new file mode 100644 index 0000000000..2f3e39650f --- /dev/null +++ b/lib/ffmpeg/patches/0036-backport-register-vdpau-hwaccel-for-mpeg12-fe1f36547d0be963e352de0cde1a6cba59ea2e78.patch @@ -0,0 +1,32 @@ +From bb6ba57092c402b6f2e5edf6d1691beafafa0460 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker <fernetmenta@online.de> +Date: Mon, 6 May 2013 20:58:28 +0200 +Subject: [PATCH] ffmpeg backport: register vdpau hwaccel for mpeg12 + +--- + libavcodec/mpeg12.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/libavcodec/mpeg12.c b/libavcodec/mpeg12.c +index 9d2743a..0f94772 100644 +--- a/libavcodec/mpeg12.c ++++ b/libavcodec/mpeg12.c +@@ -1202,6 +1202,7 @@ static const enum AVPixelFormat mpeg1_hwaccel_pixfmt_list_420[] = { + #endif + #if CONFIG_MPEG1_VDPAU_HWACCEL + AV_PIX_FMT_VDPAU_MPEG1, ++ AV_PIX_FMT_VDPAU, + #endif + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE +@@ -1214,6 +1215,7 @@ static const enum AVPixelFormat mpeg2_hwaccel_pixfmt_list_420[] = { + #endif + #if CONFIG_MPEG2_VDPAU_HWACCEL + AV_PIX_FMT_VDPAU_MPEG2, ++ AV_PIX_FMT_VDPAU, + #endif + #if CONFIG_MPEG2_DXVA2_HWACCEL + AV_PIX_FMT_DXVA2_VLD, +-- +1.7.9.5 + diff --git a/lib/ffmpeg/patches/0037-backport-fix-vdpau-vc1-interlace-modes-b37cc5995b88ec68a68cb8e496a008e1cd467077.patch b/lib/ffmpeg/patches/0037-backport-fix-vdpau-vc1-interlace-modes-b37cc5995b88ec68a68cb8e496a008e1cd467077.patch new file mode 100644 index 0000000000..e27da67fff --- /dev/null +++ b/lib/ffmpeg/patches/0037-backport-fix-vdpau-vc1-interlace-modes-b37cc5995b88ec68a68cb8e496a008e1cd467077.patch @@ -0,0 +1,25 @@ +From b37cc5995b88ec68a68cb8e496a008e1cd467077 Mon Sep 17 00:00:00 2001 +From: Rainer Hochecker <fernetmenta@online.de> +Date: Sun, 5 May 2013 15:12:59 +0200 +Subject: [PATCH] fix vdpau vc1 interlace modes + +--- + libavcodec/vdpau_vc1.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libavcodec/vdpau_vc1.c b/libavcodec/vdpau_vc1.c +index f5da9bb..993ef26 100644 +--- a/libavcodec/vdpau_vc1.c ++++ b/libavcodec/vdpau_vc1.c +@@ -59,7 +59,7 @@ static int vdpau_vc1_start_frame(AVCodecContext *avctx, + else + info->picture_type = s->pict_type - 1 + s->pict_type / 3; + +- info->frame_coding_mode = v->fcm; ++ info->frame_coding_mode = v->fcm ? v->fcm + 1 : 0; + info->postprocflag = v->postprocflag; + info->pulldown = v->broadcast; + info->interlace = v->interlace; +-- +1.7.9.5 + diff --git a/lib/ffmpeg/patches/README-patches b/lib/ffmpeg/patches/README-patches index 5f1db53098..2b0727e4b2 100644 --- a/lib/ffmpeg/patches/README-patches +++ b/lib/ffmpeg/patches/README-patches @@ -1,7 +1,18 @@ -This directory contains XBMC custom patches that are refactored to fit the FFmpeg n1.2 rev e820e3a distribution. +This directory contains XBMC custom patches that are refactored to fit the FFmpeg +n1.2 rev e820e3a distribution. -All patches in the patches folder are already applied to the ffmpeg code base and are only kept here for tracking history. Some of patches are ours and some are backports from ffmpegs upstream. Patches that has become obsolete since ffmpeg n0.10.2 are moved to obsolete-patches, also for tracking reasons. +All patches in the patches folder are already applied to the ffmpeg code base and +are only kept here for tracking history. Some of patches are ours and some are +backports from ffmpegs upstream. Patches that have become obsolete since ffmpeg +n0.10.2 are moved to the directory obsolete-patches, also for tracking reasons. -Normally you can have a look into that patchfile itself to see if its a backport or not (we normally leave the original commit message and the committer in there). You can also use "git log lib/ffmpeg/patches" to show the history where the patch file came from. +Normally you can have a look into that patchfile itself to see if its a backport +or not (we normally leave the original commit message and the committer in there). +You can also use "git log lib/ffmpeg/patches" to show the history where the patch +file came from. -Whenever you need to patch a new ffmpeg versions you apply the patch and then add the git diff to the patches folder in the next commit (if its a backport - adapt the patch so that it clearly states that it is a change from upstream and which commit in ffmpeg repo it is). +Whenever you need to patch a new ffmpeg versions you apply the patch and then add +the git diff to the patches folder in the next commit. If its a backport - adapt +the patch so that it clearly states that it is a change from upstream and which +commit in ffmpeg repo it is. Please pick an uniq patch number that doesn't +conflict with others in both the directories /patches and /patches/obsolete-patches diff --git a/lib/libdvd/libdvdread/src/dvd_reader.c b/lib/libdvd/libdvdread/src/dvd_reader.c index 38a3812f16..d7ff12eb00 100644 --- a/lib/libdvd/libdvdread/src/dvd_reader.c +++ b/lib/libdvd/libdvdread/src/dvd_reader.c @@ -432,7 +432,11 @@ dvd_reader_t *DVDOpen( const char *ppath ) { if( ( cdir = open( ".", O_RDONLY ) ) >= 0 ) { if( chdir( path_copy ) == -1 ) { +#if defined(_XBMC) + fprintf( stderr, "libdvdread: failed to change working directory to \"%s\": %s\n", path_copy, strerror(errno)); /* but ignore error */ +#else goto DVDOpen_error; +#endif // _XBMC } new_path = malloc(PATH_MAX+1); if(!new_path) { diff --git a/lib/libdvd/patches/libdvdread.diff b/lib/libdvd/patches/01-libdvdread.diff index fbf185f0dd..fbf185f0dd 100644 --- a/lib/libdvd/patches/libdvdread.diff +++ b/lib/libdvd/patches/01-libdvdread.diff diff --git a/lib/libdvd/patches/02-libdvdread_dvd_reader.c.diff b/lib/libdvd/patches/02-libdvdread_dvd_reader.c.diff new file mode 100644 index 0000000000..a49c0e741f --- /dev/null +++ b/lib/libdvd/patches/02-libdvdread_dvd_reader.c.diff @@ -0,0 +1,87 @@ +From 3708d886958258fcf18fe827eb8ab32ecda45943 Mon Sep 17 00:00:00 2001 +From: Voyager1 <voyager@xbmc.org> +Date: Wed, 20 Feb 2013 19:47:34 +0100 +Subject: [PATCH 1/3] Fix inability of libdvd 4.2.0 to read DVDs stored as + VIDEO_TS files on non-Windows OSs. Fixes + http://trac.xbmc.org/ticket/14115. + +--- + lib/libdvd/libdvdread/src/dvd_reader.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/lib/libdvd/libdvdread/src/dvd_reader.c b/lib/libdvd/libdvdread/src/dvd_reader.c +index d9544b3..2b3562f 100644 +--- a/lib/libdvd/libdvdread/src/dvd_reader.c ++++ b/lib/libdvd/libdvdread/src/dvd_reader.c +@@ -445,7 +445,11 @@ dvd_reader_t *DVDOpen( const char *ppath ) + close( cdir ); + cdir = -1; + if( retval == -1 ) { ++#if defined(_XBMC) ++ perror("libdvdread: failed to reset working directory to \".\""); /* but ignore error */ ++#else + goto DVDOpen_error; ++#endif // _XBMC + } + path_copy = new_path; + new_path = NULL; +-- +1.7.9.4 + +From cffa18401f642b35a91de7e5b1e184f1dc0bef6d Mon Sep 17 00:00:00 2001 +From: Voyager1 <voyager@xbmc.org> +Date: Thu, 21 Feb 2013 20:07:03 +0100 +Subject: [PATCH 2/3] libdvdread: replace perror by fprintf so that it gets + picked up in xbmc logs + +--- + lib/libdvd/libdvdread/src/dvd_reader.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/libdvd/libdvdread/src/dvd_reader.c b/lib/libdvd/libdvdread/src/dvd_reader.c +index 2b3562f..38a3812 100644 +--- a/lib/libdvd/libdvdread/src/dvd_reader.c ++++ b/lib/libdvd/libdvdread/src/dvd_reader.c +@@ -446,7 +446,7 @@ dvd_reader_t *DVDOpen( const char *ppath ) + cdir = -1; + if( retval == -1 ) { + #if defined(_XBMC) +- perror("libdvdread: failed to reset working directory to \".\""); /* but ignore error */ ++ fprintf( stderr, "libdvdread: failed to reset working directory to \".\": %s\n", strerror(errno)); /* but ignore error */ + #else + goto DVDOpen_error; + #endif // _XBMC +-- +1.7.9.4 + +From cb345a7e3cde07506bf3a2d696fcbb3dff44477d Mon Sep 17 00:00:00 2001 +From: Memphiz <memphis@machzwo.de> +Date: Sat, 20 Apr 2013 01:04:53 +0200 +Subject: [PATCH 3/3] [dvdread] - don't check the return value of chdir in + xbmc - this function is not wrapped and might fail (and + so will the whole dvd open in that case). This is non + fatal for our vfs! + +--- + lib/libdvd/libdvdread/src/dvd_reader.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/lib/libdvd/libdvdread/src/dvd_reader.c b/lib/libdvd/libdvdread/src/dvd_reader.c +index 38a3812..d7ff12e 100644 +--- a/lib/libdvd/libdvdread/src/dvd_reader.c ++++ b/lib/libdvd/libdvdread/src/dvd_reader.c +@@ -432,7 +432,11 @@ dvd_reader_t *DVDOpen( const char *ppath ) + { + if( ( cdir = open( ".", O_RDONLY ) ) >= 0 ) { + if( chdir( path_copy ) == -1 ) { ++#if defined(_XBMC) ++ fprintf( stderr, "libdvdread: failed to change working directory to \"%s\": %s\n", path_copy, strerror(errno)); /* but ignore error */ ++#else + goto DVDOpen_error; ++#endif // _XBMC + } + new_path = malloc(PATH_MAX+1); + if(!new_path) { +-- +1.7.9.4 + diff --git a/lib/xbmc-dll-symbols/DllAvFormat.c b/lib/xbmc-dll-symbols/DllAvFormat.c index 61ffdf4507..4b09663441 100644 --- a/lib/xbmc-dll-symbols/DllAvFormat.c +++ b/lib/xbmc-dll-symbols/DllAvFormat.c @@ -76,8 +76,10 @@ static void flush_packet_queue(AVFormatContext *s) } #endif -/* Taken from libavformat/utils.c */ -void av_read_frame_flush(AVFormatContext *s) +/* Taken from libavformat/utils.c + * Original name is ff_read_frame_flush + * */ +void xbmc_read_frame_flush(AVFormatContext *s) { AVStream *st; int i, j; diff --git a/project/BuildDependencies/scripts/0_package.list b/project/BuildDependencies/scripts/0_package.list index 2b3254399d..69fb977d37 100644 --- a/project/BuildDependencies/scripts/0_package.list +++ b/project/BuildDependencies/scripts/0_package.list @@ -10,7 +10,7 @@ doxygen-1.8.2-win32 lame_enc-3.99.5-win32.7z libbluray-0.2.3-win32 libnfs-1.3.0-win32 +libshairplay-c159ca7-win32 libjpeg-turbo-1.2.0-win32 -libshairplay-d689c6-win32 sqlite-3.7.16.1-win32 taglib-1.8beta-win32 diff --git a/project/BuildDependencies/scripts/libglew_d.bat b/project/BuildDependencies/scripts/libglew_d.bat deleted file mode 100644 index 4942d48f0b..0000000000 --- a/project/BuildDependencies/scripts/libglew_d.bat +++ /dev/null @@ -1,14 +0,0 @@ -@ECHO OFF - -SET LOC_PATH=%CD% -SET FILES=%LOC_PATH%\libglew_d.txt - -CALL dlextract.bat libglew %FILES% - -cd %TMP_PATH% - -xcopy glew\include\* "%CUR_PATH%\include\" /E /Q /I /Y -copy glew\lib\*.lib "%CUR_PATH%\lib\" /Y -copy glew\bin\glew32.dll "%XBMC_PATH%\project\Win32BuildSetup\dependencies\glew32.dll" - -cd %LOC_PATH%
\ No newline at end of file diff --git a/project/BuildDependencies/scripts/libglew_d.txt b/project/BuildDependencies/scripts/libglew_d.txt deleted file mode 100644 index 9fdbb21697..0000000000 --- a/project/BuildDependencies/scripts/libglew_d.txt +++ /dev/null @@ -1,2 +0,0 @@ -; filename mirror source of the file -glew-1.5.0-win32.zip http://mirrors.xbmc.org/build-deps/win32/ http://downloads.sourceforge.net/glew/ diff --git a/project/BuildDependencies/scripts/libshairplay_d.bat b/project/BuildDependencies/scripts/libshairplay_d.bat index 404e772029..c7996de23c 100644 --- a/project/BuildDependencies/scripts/libshairplay_d.bat +++ b/project/BuildDependencies/scripts/libshairplay_d.bat @@ -9,6 +9,6 @@ cd %TMP_PATH% echo readme.txt > shairplay_exclude.txt -xcopy libshairplay-495f02-win32\* "%XBMC_PATH%\" /E /Q /I /Y /EXCLUDE:shairplay_exclude.txt +xcopy libshairplay-c159ca7-win32\* "%XBMC_PATH%\" /E /Q /I /Y /EXCLUDE:shairplay_exclude.txt cd %LOC_PATH% diff --git a/project/BuildDependencies/scripts/libshairplay_d.txt b/project/BuildDependencies/scripts/libshairplay_d.txt index e5186611ed..b3cd0c7016 100644 --- a/project/BuildDependencies/scripts/libshairplay_d.txt +++ b/project/BuildDependencies/scripts/libshairplay_d.txt @@ -1,2 +1,2 @@ ; filename source of the file -libshairplay-495f02-win32.7z http://mirrors.xbmc.org/build-deps/win32/
\ No newline at end of file +libshairplay-c159ca7-win32.7z http://mirrors.xbmc.org/build-deps/win32/
\ No newline at end of file diff --git a/project/VS2010Express/XBMC.vcxproj b/project/VS2010Express/XBMC.vcxproj index 3afa612cc1..d0cad18bf6 100644 --- a/project/VS2010Express/XBMC.vcxproj +++ b/project/VS2010Express/XBMC.vcxproj @@ -397,6 +397,7 @@ <ClCompile Include="..\..\xbmc\cores\dvdplayer\DVDCodecs\Audio\DVDAudioCodecPassthrough.cpp" /> <ClCompile Include="..\..\xbmc\cores\dvdplayer\DVDCodecs\Video\CrystalHD.cpp" /> <ClCompile Include="..\..\xbmc\cores\dvdplayer\DVDDemuxers\DVDDemuxBXA.cpp" /> + <ClCompile Include="..\..\xbmc\cores\dvdplayer\DVDDemuxers\DVDDemuxCDDA.cpp" /> <ClCompile Include="..\..\xbmc\cores\dvdplayer\DVDDemuxers\DVDDemuxPVRClient.cpp" /> <ClCompile Include="..\..\xbmc\cores\dvdplayer\DVDInputStreams\DVDInputStreamBluray.cpp" /> <ClCompile Include="..\..\xbmc\cores\dvdplayer\DVDInputStreams\DVDInputStreamPVRManager.cpp" /> @@ -715,6 +716,7 @@ <ClCompile Include="..\..\xbmc\interfaces\json-rpc\AddonsOperations.cpp" /> <ClCompile Include="..\..\xbmc\interfaces\json-rpc\ApplicationOperations.cpp" /> <ClCompile Include="..\..\xbmc\interfaces\json-rpc\AudioLibrary.cpp" /> + <ClCompile Include="..\..\xbmc\interfaces\json-rpc\FavouritesOperations.cpp" /> <ClCompile Include="..\..\xbmc\interfaces\json-rpc\FileItemHandler.cpp" /> <ClCompile Include="..\..\xbmc\interfaces\json-rpc\FileOperations.cpp" /> <ClCompile Include="..\..\xbmc\interfaces\json-rpc\GUIOperations.cpp" /> @@ -836,6 +838,7 @@ <ClCompile Include="..\..\xbmc\network\httprequesthandler\HTTPWebinterfaceHandler.cpp" /> <ClCompile Include="..\..\xbmc\network\httprequesthandler\IHTTPRequestHandler.cpp" /> <ClCompile Include="..\..\xbmc\network\Network.cpp" /> + <ClCompile Include="..\..\xbmc\network\NetworkServices.cpp" /> <ClCompile Include="..\..\xbmc\network\Socket.cpp" /> <ClCompile Include="..\..\xbmc\network\TCPServer.cpp" /> <ClCompile Include="..\..\xbmc\network\UdpClient.cpp" /> @@ -952,13 +955,24 @@ <ClCompile Include="..\..\xbmc\settings\dialogs\GUIDialogContentSettings.cpp" /> <ClCompile Include="..\..\xbmc\settings\dialogs\GUIDialogSettings.cpp" /> <ClCompile Include="..\..\xbmc\settings\DisplaySettings.cpp" /> - <ClCompile Include="..\..\xbmc\settings\GUISettings.cpp" /> + <ClCompile Include="..\..\xbmc\settings\ISetting.cpp" /> <ClCompile Include="..\..\xbmc\settings\MediaSettings.cpp" /> <ClCompile Include="..\..\xbmc\settings\MediaSourceSettings.cpp" /> + <ClCompile Include="..\..\xbmc\settings\Setting.cpp" /> + <ClCompile Include="..\..\xbmc\settings\SettingAddon.cpp" /> + <ClCompile Include="..\..\xbmc\settings\SettingCategoryAccess.cpp" /> + <ClCompile Include="..\..\xbmc\settings\SettingConditions.cpp" /> + <ClCompile Include="..\..\xbmc\settings\SettingControl.cpp" /> + <ClCompile Include="..\..\xbmc\settings\SettingDependency.cpp" /> + <ClCompile Include="..\..\xbmc\settings\SettingPath.cpp" /> <ClCompile Include="..\..\xbmc\settings\Settings.cpp" /> + <ClCompile Include="..\..\xbmc\settings\SettingSection.cpp" /> + <ClCompile Include="..\..\xbmc\settings\SettingsManager.cpp" /> + <ClCompile Include="..\..\xbmc\settings\SettingUpdate.cpp" /> + <ClCompile Include="..\..\xbmc\settings\SettingVisibility.cpp" /> <ClCompile Include="..\..\xbmc\settings\SkinSettings.cpp" /> <ClCompile Include="..\..\xbmc\settings\VideoSettings.cpp" /> - <ClCompile Include="..\..\xbmc\settings\windows\GUISettingControls.cpp" /> + <ClCompile Include="..\..\xbmc\settings\windows\GUIControlSettings.cpp" /> <ClCompile Include="..\..\xbmc\settings\windows\GUIWindowSettings.cpp" /> <ClCompile Include="..\..\xbmc\settings\windows\GUIWindowSettingsCategory.cpp" /> <ClCompile Include="..\..\xbmc\settings\windows\GUIWindowSettingsScreenCalibration.cpp" /> @@ -1035,6 +1049,7 @@ <ClInclude Include="..\..\xbmc\cores\AudioEngine\Utils\AEWAVLoader.h" /> <ClInclude Include="..\..\xbmc\cores\dvdplayer\DVDCodecs\Audio\DVDAudioCodecPassthrough.h" /> <ClInclude Include="..\..\xbmc\cores\dvdplayer\DVDDemuxers\DVDDemuxBXA.h" /> + <ClInclude Include="..\..\xbmc\cores\dvdplayer\DVDDemuxers\DVDDemuxCDDA.h" /> <ClInclude Include="..\..\xbmc\cores\paplayer\PCMCodec.h" /> <ClInclude Include="..\..\xbmc\dialogs\GUIDialogKeyboardGeneric.h" /> <ClInclude Include="..\..\xbmc\DbUrl.h" /> @@ -1060,6 +1075,7 @@ <ClInclude Include="..\..\xbmc\input\touch\ITouchInputHandling.h" /> <ClInclude Include="..\..\xbmc\input\touch\TouchTypes.h" /> <ClInclude Include="..\..\xbmc\input\windows\WINJoystick.h" /> + <ClInclude Include="..\..\xbmc\interfaces\json-rpc\FavouritesOperations.h" /> <ClInclude Include="..\..\xbmc\interfaces\json-rpc\PVROperations.h" /> <ClInclude Include="..\..\xbmc\interfaces\legacy\Addon.h" /> <ClInclude Include="..\..\xbmc\interfaces\legacy\AddonCallback.h" /> @@ -1103,6 +1119,7 @@ <ClInclude Include="..\..\xbmc\interfaces\python\PyContext.h" /> <ClInclude Include="..\..\xbmc\interfaces\python\pythreadstate.h" /> <ClInclude Include="..\..\xbmc\music\karaoke\karaokevideobackground.h" /> + <ClInclude Include="..\..\xbmc\network\NetworkServices.h" /> <ClInclude Include="..\..\xbmc\peripherals\bus\virtual\PeripheralBusCEC.h" /> <ClInclude Include="..\..\xbmc\network\upnp\UPnPSettings.h" /> <ClInclude Include="..\..\xbmc\profiles\dialogs\GUIDialogLockSettings.h" /> @@ -1113,17 +1130,33 @@ <ClInclude Include="..\..\xbmc\settings\dialogs\GUIDialogContentSettings.h" /> <ClInclude Include="..\..\xbmc\settings\dialogs\GUIDialogSettings.h" /> <ClInclude Include="..\..\xbmc\settings\DisplaySettings.h" /> + <ClInclude Include="..\..\xbmc\settings\ISetting.h" /> + <ClInclude Include="..\..\xbmc\settings\ISettingCallback.h" /> + <ClInclude Include="..\..\xbmc\settings\ISettingCreator.h" /> <ClInclude Include="..\..\xbmc\settings\ISettingsHandler.h" /> <ClInclude Include="..\..\xbmc\settings\ISubSettings.h" /> <ClInclude Include="..\..\xbmc\settings\MediaSettings.h" /> <ClInclude Include="..\..\xbmc\settings\MediaSourceSettings.h" /> + <ClInclude Include="..\..\xbmc\settings\Setting.h" /> + <ClInclude Include="..\..\xbmc\settings\SettingAddon.h" /> + <ClInclude Include="..\..\xbmc\settings\SettingCategoryAccess.h" /> + <ClInclude Include="..\..\xbmc\settings\SettingConditions.h" /> + <ClInclude Include="..\..\xbmc\settings\SettingControl.h" /> + <ClInclude Include="..\..\xbmc\settings\SettingDependency.h" /> + <ClInclude Include="..\..\xbmc\settings\SettingPath.h" /> + <ClInclude Include="..\..\xbmc\settings\SettingSection.h" /> + <ClInclude Include="..\..\xbmc\settings\SettingsManager.h" /> + <ClInclude Include="..\..\xbmc\settings\SettingUpdate.h" /> + <ClInclude Include="..\..\xbmc\settings\SettingVisibility.h" /> <ClInclude Include="..\..\xbmc\settings\SkinSettings.h" /> - <ClInclude Include="..\..\xbmc\settings\windows\GUISettingControls.h" /> + <ClInclude Include="..\..\xbmc\settings\windows\GUIControlSettings.h" /> <ClInclude Include="..\..\xbmc\settings\windows\GUIWindowSettings.h" /> <ClInclude Include="..\..\xbmc\settings\windows\GUIWindowSettingsCategory.h" /> <ClInclude Include="..\..\xbmc\settings\windows\GUIWindowSettingsScreenCalibration.h" /> <ClInclude Include="..\..\xbmc\settings\windows\GUIWindowTestPattern.h" /> + <ClInclude Include="..\..\xbmc\utils\BooleanLogic.h" /> <ClInclude Include="..\..\xbmc\utils\IRssObserver.h" /> + <ClInclude Include="..\..\xbmc\utils\IXmlDeserializable.h" /> <ClInclude Include="..\..\xbmc\utils\RssManager.h" /> <ClInclude Include="..\..\xbmc\utils\Vector.h" /> <ClInclude Include="..\..\xbmc\video\FFmpegVideoDecoder.h" /> @@ -1261,6 +1294,7 @@ </ClInclude> <ClInclude Include="..\..\xbmc\interfaces\json-rpc\AddonsOperations.h" /> <ClCompile Include="..\..\xbmc\ThumbLoader.cpp" /> + <ClCompile Include="..\..\xbmc\utils\BooleanLogic.cpp" /> <ClCompile Include="..\..\xbmc\utils\RssManager.cpp" /> <ClCompile Include="..\..\xbmc\utils\test\TestUrlOptions.cpp"> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug (DirectX)|Win32'">true</ExcludedFromBuild> @@ -1725,7 +1759,6 @@ <ClCompile Include="..\..\xbmc\cores\dvdplayer\DVDPerformanceCounter.cpp" /> <ClCompile Include="..\..\xbmc\cores\dvdplayer\DVDPlayer.cpp" /> <ClCompile Include="..\..\xbmc\cores\dvdplayer\DVDPlayerAudio.cpp" /> - <ClCompile Include="..\..\xbmc\cores\dvdplayer\DVDPlayerAudioResampler.cpp" /> <ClCompile Include="..\..\xbmc\cores\dvdplayer\DVDPlayerSubtitle.cpp" /> <ClCompile Include="..\..\xbmc\cores\dvdplayer\DVDPlayerTeletext.cpp" /> <ClCompile Include="..\..\xbmc\cores\dvdplayer\DVDPlayerVideo.cpp" /> @@ -1788,7 +1821,6 @@ <ClCompile Include="..\..\xbmc\cores\paplayer\ADPCMCodec.cpp" /> <ClCompile Include="..\..\xbmc\cores\paplayer\ASAPCodec.cpp" /> <ClCompile Include="..\..\xbmc\cores\paplayer\AudioDecoder.cpp" /> - <ClCompile Include="..\..\xbmc\cores\paplayer\CDDAcodec.cpp" /> <ClCompile Include="..\..\xbmc\cores\paplayer\CodecFactory.cpp" /> <ClCompile Include="..\..\xbmc\cores\paplayer\DVDPlayerCodec.cpp" /> <ClCompile Include="..\..\xbmc\cores\paplayer\FLACcodec.cpp" /> @@ -2356,7 +2388,6 @@ <ClInclude Include="..\..\xbmc\rendering\RenderSystem.h" /> <ClInclude Include="..\..\xbmc\SectionLoader.h" /> <ClInclude Include="..\..\xbmc\settings\AdvancedSettings.h" /> - <ClInclude Include="..\..\xbmc\settings\GUISettings.h" /> <ClInclude Include="..\..\xbmc\settings\Settings.h" /> <ClInclude Include="..\..\xbmc\settings\VideoSettings.h" /> <ClInclude Include="..\..\xbmc\SortFileItem.h" /> @@ -2536,7 +2567,6 @@ <ClInclude Include="..\..\xbmc\cores\dvdplayer\DVDPerformanceCounter.h" /> <ClInclude Include="..\..\xbmc\cores\dvdplayer\DVDPlayer.h" /> <ClInclude Include="..\..\xbmc\cores\dvdplayer\DVDPlayerAudio.h" /> - <ClInclude Include="..\..\xbmc\cores\dvdplayer\DVDPlayerAudioResampler.h" /> <ClInclude Include="..\..\xbmc\cores\dvdplayer\DVDPlayerSubtitle.h" /> <ClInclude Include="..\..\xbmc\cores\dvdplayer\DVDPlayerTeletext.h" /> <ClInclude Include="..\..\xbmc\cores\dvdplayer\DVDPlayerVideo.h" /> @@ -2623,7 +2653,6 @@ <ClInclude Include="..\..\xbmc\cores\paplayer\ADPCMCodec.h" /> <ClInclude Include="..\..\xbmc\cores\paplayer\ASAPCodec.h" /> <ClInclude Include="..\..\xbmc\cores\paplayer\AudioDecoder.h" /> - <ClInclude Include="..\..\xbmc\cores\paplayer\CDDAcodec.h" /> <ClInclude Include="..\..\xbmc\cores\paplayer\CodecFactory.h" /> <ClInclude Include="..\..\lib\DllAdpcm.h" /> <ClInclude Include="..\..\lib\DllASAP.h" /> diff --git a/project/VS2010Express/XBMC.vcxproj.filters b/project/VS2010Express/XBMC.vcxproj.filters index 4be787ca67..2d42f5507d 100644 --- a/project/VS2010Express/XBMC.vcxproj.filters +++ b/project/VS2010Express/XBMC.vcxproj.filters @@ -363,9 +363,6 @@ <ClCompile Include="..\..\xbmc\cores\dvdplayer\DVDPlayerAudio.cpp"> <Filter>cores\dvdplayer</Filter> </ClCompile> - <ClCompile Include="..\..\xbmc\cores\dvdplayer\DVDPlayerAudioResampler.cpp"> - <Filter>cores\dvdplayer</Filter> - </ClCompile> <ClCompile Include="..\..\xbmc\cores\dvdplayer\DVDPlayerSubtitle.cpp"> <Filter>cores\dvdplayer</Filter> </ClCompile> @@ -528,9 +525,6 @@ <ClCompile Include="..\..\xbmc\cores\paplayer\AudioDecoder.cpp"> <Filter>cores\paplayer</Filter> </ClCompile> - <ClCompile Include="..\..\xbmc\cores\paplayer\CDDAcodec.cpp"> - <Filter>cores\paplayer</Filter> - </ClCompile> <ClCompile Include="..\..\xbmc\cores\paplayer\CodecFactory.cpp"> <Filter>cores\paplayer</Filter> </ClCompile> @@ -1420,9 +1414,6 @@ <ClCompile Include="..\..\xbmc\settings\AdvancedSettings.cpp"> <Filter>settings</Filter> </ClCompile> - <ClCompile Include="..\..\xbmc\settings\GUISettings.cpp"> - <Filter>settings</Filter> - </ClCompile> <ClCompile Include="..\..\xbmc\settings\Settings.cpp"> <Filter>settings</Filter> </ClCompile> @@ -2922,9 +2913,6 @@ <ClCompile Include="..\..\xbmc\settings\dialogs\GUIDialogSettings.cpp"> <Filter>settings\dialogs</Filter> </ClCompile> - <ClCompile Include="..\..\xbmc\settings\windows\GUISettingControls.cpp"> - <Filter>settings\windows</Filter> - </ClCompile> <ClCompile Include="..\..\xbmc\settings\windows\GUIWindowSettings.cpp"> <Filter>settings\windows</Filter> </ClCompile> @@ -2991,6 +2979,57 @@ <ClCompile Include="..\..\xbmc\filesystem\MusicDatabaseDirectory\DirectoryNodeGrouped.cpp"> <Filter>filesystem\MusicDatabaseDirectory</Filter> </ClCompile> + <ClCompile Include="..\..\xbmc\settings\windows\GUIControlSettings.cpp"> + <Filter>settings\windows</Filter> + </ClCompile> + <ClCompile Include="..\..\xbmc\settings\ISetting.cpp"> + <Filter>settings</Filter> + </ClCompile> + <ClCompile Include="..\..\xbmc\settings\Setting.cpp"> + <Filter>settings</Filter> + </ClCompile> + <ClCompile Include="..\..\xbmc\settings\SettingCategoryAccess.cpp"> + <Filter>settings</Filter> + </ClCompile> + <ClCompile Include="..\..\xbmc\settings\SettingConditions.cpp"> + <Filter>settings</Filter> + </ClCompile> + <ClCompile Include="..\..\xbmc\settings\SettingControl.cpp"> + <Filter>settings</Filter> + </ClCompile> + <ClCompile Include="..\..\xbmc\settings\SettingDependency.cpp"> + <Filter>settings</Filter> + </ClCompile> + <ClCompile Include="..\..\xbmc\settings\SettingVisibility.cpp"> + <Filter>settings</Filter> + </ClCompile> + <ClCompile Include="..\..\xbmc\network\NetworkServices.cpp"> + <Filter>network</Filter> + </ClCompile> + <ClCompile Include="..\..\xbmc\utils\BooleanLogic.cpp"> + <Filter>utils</Filter> + </ClCompile> + <ClCompile Include="..\..\xbmc\settings\SettingUpdate.cpp"> + <Filter>settings</Filter> + </ClCompile> + <ClCompile Include="..\..\xbmc\settings\SettingsManager.cpp"> + <Filter>settings</Filter> + </ClCompile> + <ClCompile Include="..\..\xbmc\settings\SettingAddon.cpp"> + <Filter>settings</Filter> + </ClCompile> + <ClCompile Include="..\..\xbmc\settings\SettingPath.cpp"> + <Filter>settings</Filter> + </ClCompile> + <ClCompile Include="..\..\xbmc\settings\SettingSection.cpp"> + <Filter>settings</Filter> + </ClCompile> + <ClCompile Include="..\..\xbmc\interfaces\json-rpc\FavouritesOperations.cpp"> + <Filter>interfaces\json-rpc</Filter> + </ClCompile> + <ClCompile Include="..\..\xbmc\cores\dvdplayer\DVDDemuxers\DVDDemuxCDDA.cpp"> + <Filter>cores\dvdplayer\DVDDemuxers</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="..\..\xbmc\win32\pch.h"> @@ -3056,9 +3095,6 @@ <ClInclude Include="..\..\xbmc\cores\dvdplayer\DVDPlayerAudio.h"> <Filter>cores\dvdplayer</Filter> </ClInclude> - <ClInclude Include="..\..\xbmc\cores\dvdplayer\DVDPlayerAudioResampler.h"> - <Filter>cores\dvdplayer</Filter> - </ClInclude> <ClInclude Include="..\..\xbmc\cores\dvdplayer\DVDPlayerSubtitle.h"> <Filter>cores\dvdplayer</Filter> </ClInclude> @@ -3311,9 +3347,6 @@ <ClInclude Include="..\..\xbmc\cores\paplayer\AudioDecoder.h"> <Filter>cores\paplayer</Filter> </ClInclude> - <ClInclude Include="..\..\xbmc\cores\paplayer\CDDAcodec.h"> - <Filter>cores\paplayer</Filter> - </ClInclude> <ClInclude Include="..\..\xbmc\cores\paplayer\CodecFactory.h"> <Filter>cores\paplayer</Filter> </ClInclude> @@ -4321,9 +4354,6 @@ <ClInclude Include="..\..\xbmc\settings\AdvancedSettings.h"> <Filter>settings</Filter> </ClInclude> - <ClInclude Include="..\..\xbmc\settings\GUISettings.h"> - <Filter>settings</Filter> - </ClInclude> <ClInclude Include="..\..\xbmc\settings\Settings.h"> <Filter>settings</Filter> </ClInclude> @@ -5756,9 +5786,6 @@ <ClInclude Include="..\..\xbmc\settings\dialogs\GUIDialogSettings.h"> <Filter>settings\dialogs</Filter> </ClInclude> - <ClInclude Include="..\..\xbmc\settings\windows\GUISettingControls.h"> - <Filter>settings\windows</Filter> - </ClInclude> <ClInclude Include="..\..\xbmc\settings\windows\GUIWindowSettings.h"> <Filter>settings\windows</Filter> </ClInclude> @@ -5846,6 +5873,66 @@ <ClInclude Include="..\..\xbmc\filesystem\MusicDatabaseDirectory\DirectoryNodeGrouped.h"> <Filter>filesystem\MusicDatabaseDirectory</Filter> </ClInclude> + <ClInclude Include="..\..\xbmc\settings\windows\GUIControlSettings.h"> + <Filter>settings\windows</Filter> + </ClInclude> + <ClInclude Include="..\..\xbmc\settings\ISetting.h"> + <Filter>settings</Filter> + </ClInclude> + <ClInclude Include="..\..\xbmc\settings\ISettingCallback.h"> + <Filter>settings</Filter> + </ClInclude> + <ClInclude Include="..\..\xbmc\settings\Setting.h"> + <Filter>settings</Filter> + </ClInclude> + <ClInclude Include="..\..\xbmc\settings\SettingCategoryAccess.h"> + <Filter>settings</Filter> + </ClInclude> + <ClInclude Include="..\..\xbmc\settings\SettingConditions.h"> + <Filter>settings</Filter> + </ClInclude> + <ClInclude Include="..\..\xbmc\settings\SettingControl.h"> + <Filter>settings</Filter> + </ClInclude> + <ClInclude Include="..\..\xbmc\settings\SettingDependency.h"> + <Filter>settings</Filter> + </ClInclude> + <ClInclude Include="..\..\xbmc\settings\SettingVisibility.h"> + <Filter>settings</Filter> + </ClInclude> + <ClInclude Include="..\..\xbmc\network\NetworkServices.h"> + <Filter>network</Filter> + </ClInclude> + <ClInclude Include="..\..\xbmc\utils\BooleanLogic.h"> + <Filter>utils</Filter> + </ClInclude> + <ClInclude Include="..\..\xbmc\utils\IXmlDeserializable.h"> + <Filter>utils</Filter> + </ClInclude> + <ClInclude Include="..\..\xbmc\settings\SettingUpdate.h"> + <Filter>settings</Filter> + </ClInclude> + <ClInclude Include="..\..\xbmc\settings\SettingsManager.h"> + <Filter>settings</Filter> + </ClInclude> + <ClInclude Include="..\..\xbmc\settings\ISettingCreator.h"> + <Filter>settings</Filter> + </ClInclude> + <ClInclude Include="..\..\xbmc\settings\SettingAddon.h"> + <Filter>settings</Filter> + </ClInclude> + <ClInclude Include="..\..\xbmc\settings\SettingPath.h"> + <Filter>settings</Filter> + </ClInclude> + <ClInclude Include="..\..\xbmc\settings\SettingSection.h"> + <Filter>settings</Filter> + </ClInclude> + <ClInclude Include="..\..\xbmc\interfaces\json-rpc\FavouritesOperations.h"> + <Filter>interfaces\json-rpc</Filter> + </ClInclude> + <ClInclude Include="..\..\xbmc\cores\dvdplayer\DVDDemuxers\DVDDemuxCDDA.h"> + <Filter>cores\dvdplayer\DVDDemuxers</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ResourceCompile Include="..\..\xbmc\win32\XBMC_PC.rc"> diff --git a/system/keymaps/joystick.Microsoft.Xbox.360.Controller.xml b/system/keymaps/joystick.Microsoft.Xbox.360.Controller.xml index e4e3d99feb..51fde9d66a 100644 --- a/system/keymaps/joystick.Microsoft.Xbox.360.Controller.xml +++ b/system/keymaps/joystick.Microsoft.Xbox.360.Controller.xml @@ -81,6 +81,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -172,6 +173,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -203,6 +205,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -234,6 +237,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -269,6 +273,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -349,6 +354,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -394,6 +400,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -433,6 +440,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -468,6 +476,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -529,6 +538,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -562,6 +572,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -593,6 +604,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -624,6 +636,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -687,6 +700,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -722,6 +736,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -757,6 +772,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -788,6 +804,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -825,6 +842,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -858,6 +876,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -891,6 +910,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -926,6 +946,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -957,6 +978,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -998,6 +1020,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -1031,6 +1054,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -1062,6 +1086,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -1093,6 +1118,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -1124,6 +1150,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -1155,6 +1182,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -1186,6 +1214,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -1219,6 +1248,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -1250,6 +1280,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -1281,6 +1312,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -1312,6 +1344,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -1345,6 +1378,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -1376,6 +1410,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> @@ -1409,6 +1444,7 @@ <altname>Controller (Xbox 360 Wireless Receiver for Windows)</altname> <altname>Controller (Xbox wireless receiver for windows)</altname> <altname>Controller (XBOX360 GAMEPAD)</altname> + <altname>Controller (Batarang wired controller (XBOX))</altname> <altname>Wireless Gamepad F710 (Controller)</altname> <altname>XBOX 360 For Windows</altname> <altname>XBOX 360 For Windows (Controller)</altname> diff --git a/system/settings/android.xml b/system/settings/android.xml new file mode 100644 index 0000000000..2982b93678 --- /dev/null +++ b/system/settings/android.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8" ?> +<settings> + <section id="appearance"> + <category id="locale"> + <group id="2"> + <visible>false</visible> + </group> + </category> + </section> +</settings> diff --git a/system/settings/darwin.xml b/system/settings/darwin.xml new file mode 100644 index 0000000000..5d7e9d9898 --- /dev/null +++ b/system/settings/darwin.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="utf-8" ?> +<settings> + <section id="system"> + <category id="videoscreen" label="21373" help=""> + <group id="1"> + <setting id="videoscreen.resolution" label="131" /> + </group> + </category> + <category id="audiooutput"> + <group id="1"> + <setting id="audiooutput.passthroughaac"> + <visible>false</visible> + </setting> + <setting id="audiooutput.truehdpassthrough"> + <visible>false</visible> + </setting> + <setting id="audiooutput.dtshdpassthrough"> + <visible>false</visible> + </setting> + </group> + </category> + <category id="input"> + <group id="1"> + <setting id="input.appleremotemode" type="integer" label="13600" help=""> + <level>1</level> + <default>1</default> <!-- APPLE_REMOTE_STANDARD --> + <constraints> + <options> + <option label="13610">0</option> <!-- APPLE_REMOTE_DISABLED --> + <option label="13611">1</option> <!-- APPLE_REMOTE_STANDARD --> + <option label="13612">2</option> <!-- APPLE_REMOTE_UNIVERSAL --> + <option label="13613">3</option> <!-- APPLE_REMOTE_MULTIREMOTE --> + </options> + </constraints> + <control type="spinner" format="string"/> + </setting> + <setting id="input.appleremotealwayson" type="boolean" label="13602" help=""> + <level>4</level> + <default>false</default> + <control> + <dependencies> + <dependency type="enable" setting="input.appleremotemode" operator="!is">0</dependency> <!-- APPLE_REMOTE_DISABLED --> + </dependencies> + </control> + </setting> + <setting id="input.appleremotesequencetime" type="integer" label="13603" help=""> + <level>1</level> + <default>500</default> + <constraints> + <minimum label="351">50</minimum> + <step>50</step> + <maximum>1000</maximum> + <formatlabel>14046</formatlabel> + <dependencies> + <dependency type="enable" id="input.appleremotemode">2</dependency> <!-- APPLE_REMOTE_UNIVERSAL --> + </dependencies> + </constraints> + <control type="spinner" format="string"/> + </setting> + </group> + </category> + </section> +</settings> diff --git a/system/settings/darwin_ios.xml b/system/settings/darwin_ios.xml new file mode 100644 index 0000000000..e322fd98e6 --- /dev/null +++ b/system/settings/darwin_ios.xml @@ -0,0 +1,82 @@ +<?xml version="1.0" encoding="utf-8" ?> +<settings> + <section id="videos"> + <category id="videoplayer"> + <group id="2"> + <setting id="videoplayer.hqscalers"> + <visible>false</visible> + </setting> + <setting id="videoplayer.adjustrefreshrate"> + <visible>false</visible> + </setting> + <setting id="videoplayer.pauseafterrefreshchange"> + <visible>false</visible> + </setting> + </group> + </category> + </section> + <section id="music"> + <category id="audiocds" label="620" help=""> + <visible>false</visible> + </category> + </section> + <section id="system"> + <category id="videoscreen"> + <group id="1"> + <setting id="videoscreen.fakefullscreen"> + <visible>false</visible> + </setting> + <setting id="videoscreen.blankdisplays"> + <visible>false</visible> + </setting> + </group> + </category> + <category id="audiooutput"> + <group id="1"> + <setting id="audiooutput.ac3passthrough"> + <visible>IsAppleTV2</visible> + </setting> + <setting id="audiooutput.dtspassthrough"> + <visible>IsAppleTV2</visible> + </setting> + <setting id="audiooutput.multichannellpcm"> + <visible>false</visible> + </setting> + <setting id="audiooutput.truehdpassthrough"> + <visible>false</visible> + </setting> + <setting id="audiooutput.dtshdpassthrough"> + <visible>false</visible> + </setting> + </group> + <group id="2"> + <setting id="audiooutput.audiodevice"> + <default>Default</default> + <visible>false</visible> + </setting> + <setting id="audiooutput.passthroughdevice"> + <default>Default</default> + <visible>false</visible> + </setting> + </group> + </category> + <category id="input"> + <group id="1"> + <setting id="input.peripherals"> + <visible>false</visible> + </setting> + <setting id="input.appleremotemode"> + <visible>false</visible> + </setting> + <setting id="input.appleremotesequencetime"> + <visible>false</visible> + </setting> + </group> + <group id="2"> + <setting id="input.enablemouse"> + <visible>false</visible> + </setting> + </group> + </category> + </section> +</settings> diff --git a/system/settings/darwin_ios_atv2.xml b/system/settings/darwin_ios_atv2.xml new file mode 100644 index 0000000000..3ecdcd32ef --- /dev/null +++ b/system/settings/darwin_ios_atv2.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8" ?> +<settings> + <section id="system"> + <category id="videoscreen"> + <group id="1"> + <setting id="videoscreen.screen"> + <visible>false</visible> + </setting> + <setting id="videoscreen.resolution"> + <visible>false</visible> + </setting> + </group> + </category> + </section> +</settings> diff --git a/system/settings/darwin_osx.xml b/system/settings/darwin_osx.xml new file mode 100644 index 0000000000..2d839d6ff1 --- /dev/null +++ b/system/settings/darwin_osx.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" ?> +<settings> + <section id="system"> + <category id="input"> + <group id="1"> + <setting id="input.appleremotealwayson"> + <level>1</level> + </setting> + </group> + </category> + </section> +</settings> diff --git a/system/settings/freebsd.xml b/system/settings/freebsd.xml new file mode 100644 index 0000000000..ccc0c81a0d --- /dev/null +++ b/system/settings/freebsd.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" ?> +<settings> + +</settings> diff --git a/system/settings/linux.xml b/system/settings/linux.xml new file mode 100644 index 0000000000..fd8867ebc3 --- /dev/null +++ b/system/settings/linux.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8" ?> +<settings> + <section id="system"> + <category id="videoscreen"> + <group id="1"> + <setting id="videoscreen.fakefullscreen"> + <visible>false</visible> + </setting> + </group> + </category> + </section> +</settings> diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml new file mode 100644 index 0000000000..daa27f3713 --- /dev/null +++ b/system/settings/rbp.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="utf-8" ?> +<settings><section id="system"> + <category id="videoscreen"> + <group id="1"> + <setting id="videoscreen.screen"> + <visible>false</visible> + </setting> + </group> + </category> + <category id="audiooutput"> + <group id="1"> + <setting id="audiooutput.mode"> + <default>2</default> <!-- AUDIO_HDMI --> + </setting> + <setting id="audiooutput.passthroughaac"> + <visible>false</visible> + </setting> + <setting id="audiooutput.multichannellpcm"> + <visible>false</visible> + </setting> + <setting id="audiooutput.truehdpassthrough"> + <visible>false</visible> + </setting> + <setting id="audiooutput.dtshdpassthrough"> + <visible>false</visible> + </setting> + </group> + <group id="2"> + <visible>false</visible> + </group> + <group id="3"> + <setting id="audiooutput.guisoundmode"> + <visible>false</visible> + </setting> + </group> + </category> + </section> +</settings> diff --git a/system/settings/settings.xml b/system/settings/settings.xml new file mode 100644 index 0000000000..f5284e806b --- /dev/null +++ b/system/settings/settings.xml @@ -0,0 +1,2435 @@ +<?xml version="1.0" encoding="utf-8" ?> +<settings> + <section id="appearance" label="480" help=""> + <category id="lookandfeel" label="166" help=""> + <group id="1"> + <setting id="lookandfeel.skin" type="addon" label="166" help=""> + <level>0</level> + <default>skin.confluence</default> + <addontype>xbmc.gui.skin</addontype> + </setting> + <setting id="lookandfeel.skinsettings" type="action" label="21417" help=""> + <level>0</level> + <control type="button" format="action"> + <dependencies> + <dependency type="enable" on="property" name="AddonHasSettings" setting="lookandfeel.skin" /> + </dependencies> + </control> + </setting> + <setting id="lookandfeel.skintheme" type="string" label="15111" help=""> + <level>1</level> + <default>SKINDEFAULT</default> + <constraints> + <options>skinthemes</options> + </constraints> + <control type="spinner" format="string" delayed="true" /> + </setting> + <setting id="lookandfeel.skincolors" type="string" label="14078" help=""> + <level>1</level> + <default>SKINDEFAULT</default> + <constraints> + <options>skincolors</options> + </constraints> + <control type="spinner" format="string" delayed="true" /> + </setting> + <setting id="lookandfeel.font" type="string" label="13303" help=""> + <level>1</level> + <default>Default</default> + <constraints> + <options>skinfonts</options> + </constraints> + <control type="spinner" format="string" delayed="true" /> + </setting> + <setting id="lookandfeel.skinzoom" type="integer" label="20109" help=""> + <level>2</level> + <default>0</default> + <constraints> + <minimum>-20</minimum> + <step>2</step> + <maximum>20</maximum> + <formatlabel>14047</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="lookandfeel.startupwindow" type="integer" label="512" help=""> + <level>0</level> + <default>10000</default> <!-- WINDOW_HOME --> + <constraints> + <options>startupwindows</options> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="lookandfeel.soundskin" type="string" label="15108" help=""> + <level>0</level> + <default>SKINDEFAULT</default> + <constraints> + <options>skinsounds</options> + </constraints> + <control type="spinner" format="string" /> + </setting> + </group> + <group id="2"> + <setting id="lookandfeel.enablerssfeeds" type="boolean" label="13305" help=""> + <level>1</level> + <default>true</default> + </setting> + <setting id="lookandfeel.rssedit" type="string" label="21450" help=""> + <level>1</level> + <default></default> + <allowempty>true</allowempty> + <control type="button" format="action"> + <dependencies> + <dependency type="enable" setting="lookandfeel.enablerssfeeds">true</dependency> + </dependencies> + </control> + </setting> + </group> + </category> + <category id="locale" label="14090" help=""> + <group id="1"> + <setting id="locale.language" type="string" label="248" help=""> + <level>0</level> + <default>English</default> + <constraints> + <options>languages</options> + </constraints> + <control type="spinner" format="string" delayed="true" /> + </setting> + <setting id="locale.country" type="string" label="20026" help=""> + <level>0</level> + <default>USA (12h)</default> + <constraints> + <options>regions</options> + </constraints> + <control type="spinner" format="string"> + <dependencies> + <dependency type="update" setting="locale.language" /> + </dependencies> + </control> + </setting> + <setting id="locale.charset" type="string" label="14091" help=""> + <level>1</level> + <default>DEFAULT</default> + <constraints> + <options>charsets</options> + </constraints> + <control type="spinner" format="string"> + <dependencies> + <dependency type="update" setting="locale.language" /> + </dependencies> + </control> + </setting> + </group> + <group id="2"> + <setting id="locale.timezonecountry" type="string" label="14079" help=""> + <level>2</level> + <default>default</default> <!-- will be properly set on startup --> + <constraints> + <options>timezonecountries</options> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="locale.timezone" type="string" label="14080" help=""> + <level>2</level> + <default>default</default> <!-- will be properly set on startup --> + <constraints> + <options>timezones</options> + </constraints> + <control type="spinner" format="string"> + <dependencies> + <dependency type="update" setting="locale.timezonecountry" /> + </dependencies> + </control> + </setting> + </group> + <group id="4"> + <setting id="locale.audiolanguage" type="string" label="285" help=""> + <level>1</level> + <default>original</default> + <constraints> + <options>streamlanguages</options> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="locale.subtitlelanguage" type="string" label="286" help=""> + <level>1</level> + <default>original</default> + <constraints> + <options>streamlanguages</options> + </constraints> + <control type="spinner" format="string" /> + </setting> + </group> + </category> + <category id="filelists" label="14081" help=""> + <group id="1"> + <setting id="filelists.showparentdiritems" type="boolean" label="13306" help=""> + <level>1</level> + <default>true</default> + </setting> + <setting id="filelists.showextensions" type="boolean" label="497" help=""> + <level>1</level> + <default>true</default> + </setting> + <setting id="filelists.ignorethewhensorting" type="boolean" label="13399" help=""> + <level>1</level> + <default>true</default> + </setting> + <setting id="filelists.allowfiledeletion" type="boolean" label="14071" help=""> + <level>1</level> + <default>false</default> + <control> + <dependencies> + <dependency type="enable"> + <or> + <condition on="property" operator="!is" name="ProfileHasFilesLocked" /> + <condition on="property" name="IsMasterUser" /> + </or> + </dependency> + </dependencies> + </control> + </setting> + <setting id="filelists.showaddsourcebuttons" type="boolean" label="21382" help=""> + <level>1</level> + <default>true</default> + <control> + <dependencies> + <dependency type="enable"> + <or> + <condition on="property" name="ProfileCanWriteSources" /> + <condition on="property" name="IsMasterUser" /> + </or> + </dependency> + </dependencies> + </control> + </setting> + <setting id="filelists.showhidden" type="boolean" label="21330" help=""> + <level>1</level> + <default>false</default> + </setting> + </group> + </category> + <category id="screensaver" label="360" help="355"> + <group id="1"> + <setting id="screensaver.mode" type="addon" label="356" help=""> + <level>0</level> + <default>screensaver.xbmc.builtin.dim</default> + <addontype>xbmc.ui.screensaver</addontype> + <allowempty>true</allowempty> + <updates> + <update type="change" /> + </updates> + </setting> + <setting id="screensaver.settings" type="action" label="21417" help=""> + <level>0</level> + <control type="button" format="action"> + <dependencies> + <dependency type="enable"> + <and> + <condition on="setting" setting="screensaver.mode" operator="!is"></condition> + <condition on="property" name="AddonHasSettings" setting="screensaver.mode" /> + </and> + </dependency> + </dependencies> + </control> + </setting> + <setting id="screensaver.preview" type="action" label="1000" help=""> + <level>0</level> + <control> + <dependencies> + <dependency type="enable" setting="screensaver.mode" operator="!is"></dependency> + </dependencies> + </control> + </setting> + <setting id="screensaver.time" type="integer" label="355" help=""> + <level>0</level> + <default>3</default> + <constraints> + <minimum>1</minimum> + <step>1</step> + <maximum>60</maximum> + <formatlabel>14044</formatlabel> + </constraints> + <control type="spinner" format="string"> + <dependencies> + <dependency type="enable" setting="screensaver.mode" operator="!is"></dependency> + </dependencies> + </control> + </setting> + </group> + <group id="2"> + <setting id="screensaver.usemusicvisinstead" type="boolean" label="13392" help=""> + <level>1</level> + <default>true</default> + <control> + <dependencies> + <dependency type="enable" setting="screensaver.mode" operator="!is"></dependency> + </dependencies> + </control> + </setting> + <setting id="screensaver.usedimonpause" type="boolean" label="22014" help=""> + <level>1</level> + <default>true</default> + <control> + <dependencies> + <dependency type="enable"> + <and> + <condition setting="screensaver.mode" operator="!is">screensaver.xbmc.builtin.dim</condition> + <condition setting="screensaver.mode" operator="!is"></condition> + </and> + </dependency> + </dependencies> + </control> + </setting> + </group> + </category> + <category id="window" label="0" help=""> + <visible>false</visible> + <group id="1"> + <setting id="window.width" type="integer" label="0" help=""> + <level>4</level> + <default>720</default> + </setting> + <setting id="window.height" type="integer" label="0" help=""> + <level>4</level> + <default>480</default> + </setting> + </group> + </category> + </section> + <section id="videos" label="3" help=""> + <category id="videolibrary" label="14022" help=""> + <group id="1"> + <setting id="videolibrary.enabled" type="boolean" label="24022" help=""> + <level>4</level> + <default>true</default> + </setting> + <setting id="videolibrary.showunwatchedplots" type="boolean" label="20369" help=""> + <level>0</level> + <default>true</default> + </setting> + <setting id="videolibrary.seasonthumbs" type="boolean" label="20382" help=""> + <level>4</level> + <default>true</default> + </setting> + <setting id="videolibrary.actorthumbs" type="boolean" label="20402" help=""> + <level>1</level> + <default>true</default> + </setting> + <setting id="videolibrary.flattentvshows" type="integer" label="20412" help=""> + <level>1</level> + <default>1</default> <!-- if only one season --> + <constraints> + <options> + <option label="20420">0</option> <!-- never --> + <option label="20421">1</option> <!-- if only one season --> + <option label="20422">2</option> <!-- always --> + </options> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="videolibrary.groupmoviesets" type="boolean" label="20458" help=""> + <level>0</level> + <default>false</default> + </setting> + <setting id="videolibrary.updateonstartup" type="boolean" label="22000" help=""> + <level>1</level> + <default>false</default> + </setting> + <setting id="videolibrary.backgroundupdate" type="boolean" label="22001" help=""> + <level>1</level> + <default>false</default> + </setting> + </group> + <group id="2"> + <setting id="videolibrary.cleanup" type="action" label="334" help=""> + <level>2</level> + </setting> + <setting id="videolibrary.export" type="action" label="647" help=""> + <level>2</level> + </setting> + <setting id="videolibrary.import" type="action" label="648" help=""> + <level>2</level> + </setting> + </group> + </category> + <category id="videoplayer" label="14086" help=""> + <group id="1"> + <setting id="videoplayer.autoplaynextitem" type="boolean" label="13433" help=""> + <level>1</level> + <default>false</default> + </setting> + </group> + <group id="2"> + <setting id="videoplayer.rendermethod" type="integer" label="13415" help=""> + <level>2</level> + <default>0</default> <!-- RENDER_METHOD_AUTO --> + <constraints> + <options>rendermethods</options> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="videoplayer.hqscalers" type="integer" label="13435" help=""> + <level>2</level> + <default>0</default> + <constraints> + <minimum>0</minimum> + <step>10</step> + <maximum>100</maximum> + <formatlabel>14047</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="videoplayer.usevdpau" type="boolean" label="13425" help=""> + <visible>HAVE_LIBVDPAU</visible> + <level>2</level> + <default>true</default> + </setting> + <setting id="videoplayer.usevaapi" type="boolean" label="13426" help=""> + <visible>HAVE_LIBVA</visible> + <level>2</level> + <default>true</default> + </setting> + <setting id="videoplayer.usedxva2" type="boolean" label="13427" help=""> + <visible>HasDXVA2</visible> + <level>2</level> + <default>true</default> + </setting> + <setting id="videoplayer.usechd" type="boolean" label="13428" help=""> + <visible>HasCrystalHDDevice</visible> + <level>2</level> + <default>true</default> + </setting> + <setting id="videoplayer.usevda" type="boolean" label="13429" help=""> + <visible>HasVDADecoder</visible> + <level>2</level> + <default>true</default> + </setting> + <setting id="videoplayer.useomx" type="boolean" label="13430" help=""> + <visible>HAVE_LIBOPENMAX</visible> + <level>2</level> + <default>true</default> + </setting> + <setting id="videoplayer.usevideotoolbox" type="boolean" label="13432" help=""> + <visible>HasVideoToolBoxDecoder</visible> + <level>2</level> + <default>true</default> + </setting> + <setting id="videoplayer.usepbo" type="boolean" label="13424" help=""> + <visible>HAS_GL</visible> + <level>4</level> + <default>true</default> + </setting> + <setting id="videoplayer.adjustrefreshrate" type="integer" label="170" help=""> + <level>2</level> + <default>0</default> <!-- ADJUST_REFRESHRATE_OFF --> + <constraints> + <options> + <option label="351">0</option> <!-- ADJUST_REFRESHRATE_OFF --> + <option label="36035">1</option> <!-- ADJUST_REFRESHRATE_ALWAYS --> + <option label="36036">2</option> <!-- ADJUST_REFRESHRATE_ON_STARTSTOP --> + </options> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="videoplayer.pauseafterrefreshchange" type="integer" label="13550" help=""> + <level>2</level> + <default>0</default> + <constraints> + <options>refreshchangedelays</options> + </constraints> + <control type="spinner" format="string"> + <dependencies> + <dependency type="enable" setting="videoplayer.adjustrefreshrate" operator="!is">0</dependency> <!-- ADJUST_REFRESHRATE_OFF --> + </dependencies> + </control> + </setting> + <setting id="videoplayer.usedisplayasclock" type="boolean" label="13510" help=""> + <level>2</level> + <default>false</default> + </setting> + <setting id="videoplayer.synctype" type="integer" label="13500" help=""> + <level>2</level> + <default>2</default> <!-- SYNC_RESAMPLE --> + <constraints> + <options> + <option label="13501">0</option> <!-- SYNC_DISCON --> + <option label="13502">1</option> <!-- SYNC_SKIPDUP --> + <option label="13503">2</option> <!-- SYNC_RESAMPLE --> + </options> + </constraints> + <control type="spinner" format="string"> + <dependencies> + <dependency type="enable" setting="videoplayer.usedisplayasclock" operator="is">true</dependency> + </dependencies> + </control> + </setting> + <setting id="videoplayer.maxspeedadjust" type="number" label="13504" help=""> + <level>4</level> + <default>5.0</default> + <constraints> + <minimum>0.0</minimum> + <step>0.1</step> + <maximum>10.0</maximum> + </constraints> + <control type="spinner" format="number"> + <dependencies> + <dependency type="enable"> + <and> + <condition setting="videoplayer.usedisplayasclock" operator="is">true</condition> + <condition setting="videoplayer.synctype" operator="is">2</condition> <!-- SYNC_RESAMPLE --> + </and> + </dependency> + </dependencies> + </control> + </setting> + <setting id="videoplayer.resamplequality" type="integer" label="13505" help=""> + <level>4</level> + <default>1</default> <!-- RESAMPLE_MID --> + <constraints> + <options> + <option label="13506">0</option> <!-- RESAMPLE_LOW --> + <option label="13507">1</option> <!-- RESAMPLE_MID --> + <option label="13508">2</option> <!-- RESAMPLE_HIGH --> + <option label="13509">3</option> <!-- RESAMPLE_REALLYHIGH --> + </options> + </constraints> + <control type="spinner" format="string"> + <dependencies> + <dependency type="enable"> + <and> + <condition setting="videoplayer.usedisplayasclock" operator="is">true</condition> + <condition setting="videoplayer.synctype" operator="is">2</condition> <!-- SYNC_RESAMPLE --> + </and> + </dependency> + </dependencies> + </control> + </setting> + <setting id="videoplayer.errorinaspect" type="integer" label="22021" help=""> + <level>2</level> + <default>0</default> + <constraints> + <minimum label="231">0</minimum> + <step>1</step> + <maximum>20</maximum> + <formatlabel>14047</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="videoplayer.stretch43" type="integer" label="173" help=""> + <level>1</level> + <default>0</default> <!-- ViewModeNormal --> + <constraints> + <options> + <option label="630">0</option> <!-- ViewModeNormal --> + <option label="633">3</option> <!-- ViewModeWideZoom --> + <option label="634">4</option> <!-- ViewModeStretch16x9 --> + <option label="631">1</option> <!-- ViewModeZoom --> + </options> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="videoplayer.vdpau_allow_xrandr" type="boolean" label="13122" help=""> + <visible>HAVE_LIBVDPAU</visible> + <level>4</level> + <default>false</default> + </setting> + </group> + <group id="3"> + <visible> + <and> + <or> + <condition>HAS_GL</condition> + <condition>HAS_GLESv2</condition> + </or> + <condition>HAVE_LIBVDPAU</condition> + </and> + </visible> + <setting id="videoplayer.vdpauUpscalingLevel" type="boolean" label="13121" help=""> + <level>4</level> + <default>false</default> + </setting> + </group> + <group id="4"> + <setting id="videoplayer.teletextenabled" type="boolean" label="23050" help=""> + <level>1</level> + <default>true</default> + </setting> + <setting id="videoplayer.teletextscale" type="boolean" label="23055" help=""> + <level>1</level> + <default>true</default> + </setting> + </group> + </category> + <category id="myvideos" label="14081" help=""> + <group id="1"> + <setting id="myvideos.selectaction" type="integer" label="22079" help=""> + <level>1</level> + <default>1</default> <!-- SELECT_ACTION_PLAY_OR_RESUME --> + <constraints> + <options> + <option label="22080">0</option> <!-- SELECT_ACTION_CHOOSE --> + <option label="208">1</option> <!-- SELECT_ACTION_PLAY_OR_RESUME --> + <option label="13404">2</option> <!-- SELECT_ACTION_RESUME --> + <option label="22081">3</option> <!-- SELECT_ACTION_INFO --> + </options> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="myvideos.extractflags" type="boolean" label="20433" help=""> + <level>1</level> + <default>true</default> + </setting> + <setting id="myvideos.replacelabels" type="boolean" label="20419" help=""> + <level>1</level> + <default>true</default> + </setting> + <setting id="myvideos.extractthumb" type="boolean" label="20433" help=""> + <level>4</level> + <default>true</default> + </setting> + </group> + <group id="2"> + <setting id="myvideos.startwindow" type="integer" label="0" help=""> + <level>4</level> + <default>100024</default> <!-- WINDOW_VIDEO_FILES --> + </setting> + <setting id="myvideos.stackvideos" type="boolean" label="0" help=""> + <level>4</level> + <default>false</default> + </setting> + <setting id="myvideos.flatten" type="boolean" label="0" help=""> + <level>4</level> + <default>false</default> + </setting> + </group> + </category> + <category id="subtitles" label="287" help=""> + <group id="1"> + <setting id="subtitles.font" type="string" label="14089" help=""> + <level>1</level> + <default>arial.ttf</default> + <constraints> + <options>fonts</options> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="subtitles.height" type="integer" label="289" help=""> + <level>1</level> + <default>28</default> + <constraints> + <minimum>16</minimum> + <step>2</step> + <maximum>74</maximum> + </constraints> + <control type="spinner" format="string"> + <dependencies> + <dependency type="update" setting="subtitles.font" /> + </dependencies> + </control> + </setting> + <setting id="subtitles.style" type="integer" label="736" help=""> + <level>1</level> + <default>1</default> <!-- FONT_STYLE_BOLD --> + <constraints> + <options> + <option label="738">0</option> <!-- FONT_STYLE_NORMAL --> + <option label="739">1</option> <!-- FONT_STYLE_BOLD --> + <option label="740">2</option> <!-- FONT_STYLE_ITALICS --> + <option label="741">3</option> <!-- FONT_STYLE_BOLD | FONT_STYLE_ITALICS --> + </options> + </constraints> + <control type="spinner" format="string"> + <dependencies> + <dependency type="enable" on="property" name="IsUsingTTFSubtitles" setting="subtitles.font" /> + </dependencies> + </control> + </setting> + <setting id="subtitles.color" type="integer" label="737" help=""> + <level>1</level> + <default>1</default> <!-- White --> + <constraints> + <options> + <option label="760">0</option> <!-- Yellow --> + <option label="761">1</option> <!-- White --> + <option label="762">2</option> <!-- Blue --> + <option label="763">3</option> <!-- Bright green --> + <option label="764">4</option> <!-- Yellow green --> + <option label="765">5</option> <!-- Cyan --> + <option label="766">6</option> <!-- Light grey --> + <option label="767">7</option> <!-- Grey --> + </options> + </constraints> + <control type="spinner" format="string"> + <dependencies> + <dependency type="enable" on="property" name="IsUsingTTFSubtitles" setting="subtitles.font" /> + </dependencies> + </control> + </setting> + <setting id="subtitles.charset" type="string" label="735" help=""> + <level>1</level> + <default>DEFAULT</default> + <constraints> + <options>charsets</options> + </constraints> + <control type="spinner" format="string"> + <dependencies> + <dependency type="enable" on="property" name="IsUsingTTFSubtitles" setting="subtitles.font" /> + </dependencies> + </control> + </setting> + <setting id="subtitles.overrideassfonts" type="boolean" label="21368" help=""> + <level>1</level> + <default>false</default> + </setting> + </group> + <group id="2"> + <setting id="subtitles.custompath" type="path" label="21366" help=""> + <level>1</level> + <default></default> + <allowempty>true</allowempty> + <heading>657</heading> + <constraints> + <writable>false</writable> + <sources> + <source>videos</source> + </sources> + </constraints> + <control type="button" format="path" /> + </setting> + <setting id="subtitles.align" type="integer" label="21460" help=""> + <level>1</level> + <default>0</default> <!-- SUBTITLE_ALIGN_MANUAL --> + <constraints> + <options> + <option label="21461">0</option> <!-- SUBTITLE_ALIGN_MANUAL --> + <option label="21462">1</option> <!-- SUBTITLE_ALIGN_BOTTOM_INSIDE --> + <option label="21463">2</option> <!-- SUBTITLE_ALIGN_BOTTOM_OUTSIDE --> + <option label="21464">3</option> <!-- SUBTITLE_ALIGN_TOP_INSIDE --> + <option label="21465">4</option> <!-- SUBTITLE_ALIGN_TOP_OUTSIDE --> + </options> + </constraints> + <control type="spinner" format="string" /> + </setting> + </group> + </category> + <category id="dvds" label="14087" help=""> + <group id="1"> + <setting id="dvds.autorun" type="boolean" label="14088" help=""> + <level>0</level> + <default>false</default> + </setting> + <setting id="dvds.playerregion" type="integer" label="21372" help=""> + <level>2</level> + <default>0</default> + <constraints> + <minimum label="351">0</minimum> + <step>1</step> + <maximum>8</maximum> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="dvds.automenu" type="boolean" label="21882" help=""> + <level>1</level> + <default>false</default> + </setting> + </group> + </category> + <category id="scrapers" label="0" help=""> + <visible>false</visible> + <group id="1"> + <setting id="scrapers.moviesdefault" type="addon" label="21413" help=""> + <level>4</level> + <default>metadata.themoviedb.org</default> + <addontype>xbmc.metadata.scraper.movies</addontype> + </setting> + <setting id="scrapers.tvshowsdefault" type="addon" label="21414" help=""> + <level>4</level> + <default>metadata.tvdb.com</default> + <addontype>xbmc.metadata.scraper.tvshows</addontype> + </setting> + <setting id="scrapers.musicvideosdefault" type="addon" label="21415" help=""> + <level>4</level> + <default>metadata.musicvideos.theaudiodb.com</default> + <addontype>xbmc.metadata.scraper.musicvideos</addontype> + <updates> + <update type="change" /> + </updates> + </setting> + </group> + </category> + </section> + <section id="pvr" label="19180" help=""> + <category id="pvrmanager" label="128" help=""> + <group id="1"> + <setting id="pvrmanager.enabled" type="boolean" label="449" help=""> + <level>1</level> + <default>false</default> + </setting> + </group> + <group id="2"> + <setting id="pvrmanager.syncchannelgroups" type="boolean" label="19221" help=""> + <level>1</level> + <default>true</default> + </setting> + <setting id="pvrmanager.backendchannelorder" type="boolean" label="19231" help=""> + <level>2</level> + <default>true</default> + </setting> + <setting id="pvrmanager.usebackendchannelnumbers" type="boolean" label="19234" help=""> + <level>2</level> + <default>false</default> + </setting> + </group> + <group id="3"> + <setting id="pvrmanager.channelmanager" type="action" label="19199" help=""> + <level>1</level> + <control> + <dependencies> + <dependency type="enable" setting="pvrmanager.enabled">true</dependency> + </dependencies> + </control> + </setting> + <setting id="pvrmanager.channelscan" type="action" label="19117" help=""> + <level>1</level> + <control> + <dependencies> + <dependency type="enable" setting="pvrmanager.enabled">true</dependency> + </dependencies> + </control> + </setting> + <setting id="pvrmanager.resetdb" type="action" label="19185" help=""> + <level>2</level> + </setting> + </group> + <group id="4"> + <setting id="pvrmanager.hideconnectionlostwarning" type="boolean" label="19269" help=""> + <level>1</level> + <default>false</default> + </setting> + </group> + </category> + <category id="pvrmenu" label="19181" help=""> + <group id="1"> + <setting id="pvrmenu.infoswitch" type="boolean" label="19178" help=""> + <level>1</level> + <default>true</default> + </setting> + <setting id="pvrmenu.infotimeout" type="boolean" label="19179" help=""> + <level>1</level> + <default>true</default> + </setting> + <setting id="pvrmenu.closechannelosdonswitch" type="boolean" label="19229" help=""> + <level>1</level> + <default>false</default> + </setting> + <setting id="pvrmenu.infotime" type="integer" label="19184" help=""> + <level>1</level> + <default>5</default> + <constraints> + <minimum>1</minimum> + <step>1</step> + <maximum>10</maximum> + <formatlabel>14045</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + </group> + <group id="2"> + <setting id="pvrmenu.iconpath" type="path" label="19018" help=""> + <level>1</level> + <default></default> + <allowempty>true</allowempty> + <heading>657</heading> + <constraints> + <writable>false</writable> + </constraints> + <control type="button" format="path" /> + </setting> + <setting id="pvrmenu.searchicons" type="action" label="19167" help=""> + <level>1</level> + <control> + <dependencies> + <dependency type="enable" setting="pvrmanager.enabled">true</dependency> + </dependencies> + </control> + </setting> + </group> + </category> + <category id="epg" label="19069" help=""> + <group id="1"> + <setting id="epg.defaultguideview" type="integer" label="19065" help=""> + <level>1</level> + <default>3</default> <!-- GUIDE_VIEW_TIMELINE --> + <constraints> + <minimum>0</minimum> + <step>1</step> + <maximum>3</maximum> + <options>epgguideviews</options> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="epg.daystodisplay" type="integer" label="19182" help=""> + <level>1</level> + <default>3</default> + <constraints> + <minimum>1</minimum> + <step>1</step> + <maximum>14</maximum> + <formatlabel>17999</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + </group> + <group id="2"> + <setting id="epg.epgupdate" type="integer" label="19071" help=""> + <level>1</level> + <default>120</default> + <constraints> + <minimum>15</minimum> + <step>15</step> + <maximum>2880</maximum> + <formatlabel>14044</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="epg.preventupdateswhileplayingtv" type="boolean" label="19230" help=""> + <level>1</level> + <default>false</default> + </setting> + <setting id="epg.ignoredbforclient" type="boolean" label="19072" help=""> + <level>1</level> + <default>false</default> + </setting> + <setting id="epg.hidenoinfoavailable" type="boolean" label="19268" help=""> + <level>1</level> + <default>true</default> + </setting> + <setting id="epg.resetepg" type="action" label="19187" help=""> + <level>1</level> + </setting> + </group> + </category> + <category id="pvrplayback" label="19177" help=""> + <group id="1"> + <setting id="pvrplayback.playminimized" type="boolean" label="19171" help=""> + <level>1</level> + <default>true</default> + </setting> + <setting id="pvrplayback.startlast" type="integer" label="19189" help=""> + <level>1</level> + <default>0</default> <!-- START_LAST_CHANNEL_OFF --> + <constraints> + <minimum>0</minimum> + <step>1</step> + <maximum>2</maximum> + <options>pvrstartlastchannel</options> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="pvrplayback.signalquality" type="boolean" label="19037" help=""> + <level>1</level> + <default>true</default> + </setting> + </group> + <group id="2"> + <setting id="pvrplayback.scantime" type="integer" label="19170" help=""> + <level>1</level> + <default>10</default> + <constraints> + <minimum>1</minimum> + <step>1</step> + <maximum>60</maximum> + <formatlabel>14045</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="pvrplayback.confirmchannelswitch" type="boolean" label="19281" help=""> + <level>1</level> + <default>false</default> + </setting> + <setting id="pvrplayback.channelentrytimeout" type="integer" label="19073" help=""> + <level>1</level> + <default>0</default> + <constraints> + <minimum>0</minimum> + <step>250</step> + <maximum>10000</maximum> + <formatlabel>14046</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + </group> + </category> + <category id="pvrrecord" label="19043" help=""> + <group id="1"> + <setting id="pvrrecord.instantrecordtime" type="integer" label="19172" help=""> + <level>1</level> + <default>120</default> + <constraints> + <minimum>1</minimum> + <step>1</step> + <maximum>720</maximum> + <formatlabel>14044</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="pvrrecord.defaultpriority" type="integer" label="19173" help=""> + <level>1</level> + <default>50</default> + <constraints> + <minimum>1</minimum> + <step>1</step> + <maximum>100</maximum> + </constraints> + <control type="spinner" format="integer" /> + </setting> + <setting id="pvrrecord.defaultlifetime" type="integer" label="19174" help=""> + <level>1</level> + <default>99</default> + <constraints> + <minimum>1</minimum> + <step>1</step> + <maximum>365</maximum> + <formatlabel>17999</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="pvrrecord.marginstart" type="integer" label="19175" help=""> + <level>1</level> + <default>0</default> + <constraints> + <minimum>0</minimum> + <step>1</step> + <maximum>60</maximum> + <formatlabel>14044</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="pvrrecord.marginend" type="integer" label="19176" help=""> + <level>1</level> + <default>0</default> + <constraints> + <minimum>0</minimum> + <step>1</step> + <maximum>60</maximum> + <formatlabel>14044</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + </group> + <group id="2"> + <setting id="pvrrecord.timernotifications" type="boolean" label="19233" help=""> + <level>1</level> + <default>true</default> + </setting> + </group> + </category> + <category id="pvrpowermanagement" label="14095" help=""> + <group id="1"> + <setting id="pvrpowermanagement.enabled" type="boolean" label="305" help=""> + <level>1</level> + <default>false</default> + </setting> + </group> + <group id="2"> + <setting id="pvrpowermanagement.backendidletime" type="integer" label="19244" help=""> + <level>1</level> + <default>15</default> + <constraints> + <minimum label="351">0</minimum> + <step>5</step> + <maximum>360</maximum> + <formatlabel>14044</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="pvrpowermanagement.setwakeupcmd" type="string" label="19245" help=""> + <level>1</level> + <default></default> + <allowempty>true</allowempty> + <control type="edit" format="string" /> + </setting> + <setting id="pvrpowermanagement.prewakeup" type="integer" label="19246" help=""> + <level>1</level> + <default>15</default> + <constraints> + <minimum label="351">0</minimum> + <step>1</step> + <maximum>60</maximum> + <formatlabel>14044</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + </group> + <group id="3"> + <setting id="pvrpowermanagement.dailywakeup" type="boolean" label="19247" help=""> + <level>1</level> + <default>false</default> + </setting> + <setting id="pvrpowermanagement.dailywakeuptime" type="string" label="19248" help=""> + <level>1</level> + <default>00:00:00</default> + <control type="edit" format="string" /> + </setting> + </group> + </category> + <category id="pvrparental" label="19259" help=""> + <access>CheckPVRParentalPin</access> + <group id="1"> + <setting id="pvrparental.enabled" type="boolean" label="449" help=""> + <level>1</level> + <default>false</default> + </setting> + </group> + <group id="2"> + <setting id="pvrparental.pin" type="string" label="19261" help=""> + <level>1</level> + <default></default> + <allowempty>true</allowempty> + <control type="edit" format="integer" attributes="hidden,new" delayed="false"> + <dependencies> + <dependency type="enable" setting="pvrparental.enabled">true</dependency> + </dependencies> + </control> + </setting> + <setting id="pvrparental.duration" type="integer" label="19260" help=""> + <level>1</level> + <default>300</default> + <constraints> + <minimum>5</minimum> + <step>5</step> + <maximum>1200</maximum> + <formatlabel>14045</formatlabel> + </constraints> + <control type="spinner" format="string"> + <dependencies> + <dependency type="enable" setting="pvrparental.enabled">true</dependency> + </dependencies> + </control> + </setting> + </group> + </category> + <category id="pvrclient" label="19279" help=""> + <group id="1"> + <setting id="pvrclient.menuhook" type="action" label="19280" help=""> + <level>1</level> + </setting> + </group> + </category> + </section> + <section id="music" label="2" help=""> + <category id="musiclibrary" label="14022" help=""> + <group id="1"> + <setting id="musiclibrary.enabled" type="boolean" label="24022" help=""> + <level>4</level> + <default>true</default> + </setting> + <setting id="musiclibrary.showcompilationartists" type="boolean" label="13414" help=""> + <level>1</level> + <default>true</default> + </setting> + </group> + <group id="2"> + <setting id="musiclibrary.downloadinfo" type="boolean" label="20192" help=""> + <level>0</level> + <default>false</default> + </setting> + <setting id="musiclibrary.albumsscraper" type="addon" label="20193" help=""> + <level>1</level> + <default>metadata.album.universal</default> + <addontype>xbmc.metadata.scraper.albums</addontype> + </setting> + <setting id="musiclibrary.artistsscraper" type="addon" label="20194" help=""> + <level>1</level> + <default>metadata.artists.universal</default> + <addontype>xbmc.metadata.scraper.artists</addontype> + </setting> + <setting id="musiclibrary.updateonstartup" type="boolean" label="22000" help=""> + <level>1</level> + <default>false</default> + </setting> + <setting id="musiclibrary.backgroundupdate" type="boolean" label="22001" help=""> + <level>1</level> + <default>false</default> + </setting> + </group> + <group id="3"> + <setting id="musiclibrary.cleanup" type="action" label="334" help=""> + <level>2</level> + </setting> + <setting id="musiclibrary.export" type="action" label="20196" help=""> + <level>2</level> + </setting> + <setting id="musiclibrary.import" type="action" label="20197" help=""> + <level>2</level> + </setting> + </group> + </category> + <category id="musicplayer" label="14086" help=""> + <group id="1"> + <setting id="musicplayer.autoplaynextitem" type="boolean" label="489" help=""> + <level>0</level> + <default>true</default> + </setting> + <setting id="musicplayer.queuebydefault" type="boolean" label="14084" help=""> + <level>1</level> + <default>false</default> + </setting> + </group> + <group id="2"> + <setting id="musicplayer.replaygaintype" type="integer" label="638" help=""> + <level>2</level> + <default>1</default> <!-- REPLAY_GAIN_ALBUM --> + <constraints> + <options> + <option label="351">0</option> <!-- REPLAY_GAIN_NONE --> + <option label="639">2</option> <!-- REPLAY_GAIN_TRACK --> + <option label="640">1</option> <!-- REPLAY_GAIN_ALBUM --> + </options> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="musicplayer.replaygainpreamp" type="integer" label="641" help=""> + <level>2</level> + <default>89</default> + <constraints> + <minimum>77</minimum> + <step>1</step> + <maximum>101</maximum> + <formatlabel>14050</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="musicplayer.replaygainnogainpreamp" type="integer" label="642" help=""> + <level>2</level> + <default>89</default> + <constraints> + <minimum>77</minimum> + <step>1</step> + <maximum>101</maximum> + <formatlabel>14050</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="musicplayer.replaygainavoidclipping" type="boolean" label="643" help=""> + <level>2</level> + <default>false</default> + </setting> + </group> + <group id="3"> + <setting id="musicplayer.crossfade" type="integer" label="13314" help=""> + <level>1</level> + <default>0</default> + <constraints> + <minimum label="351">0</minimum> + <step>1</step> + <maximum>15</maximum> + <formatlabel>14045</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="musicplayer.crossfadealbumtracks" type="boolean" label="13400" help=""> + <level>1</level> + <default>true</default> + <control> + <dependencies> + <dependency type="enable"> + <and> + <condition setting="musicplayer.crossfade" operator="!is">0</condition> + </and> + </dependency> + </dependencies> + </control> + </setting> + </group> + <group id="4"> + <setting id="musicplayer.visualisation" type="addon" label="250" help=""> + <level>0</level> + <default>visualization.glspectrum</default> + <addontype>xbmc.player.musicviz</addontype> + <allowempty>true</allowempty> + </setting> + </group> + </category> + <category id="musicfiles" label="14081" help=""> + <group id="1"> + <setting id="musicfiles.usetags" type="boolean" label="258" help=""> + <level>0</level> + <default>true</default> + </setting> + <setting id="musicfiles.trackformat" type="string" label="13307" help=""> + <level>2</level> + <default>[%N. ]%A - %T</default> + <heading>16016</heading> + <control type="edit" format="string" /> + </setting> + <setting id="musicfiles.trackformatright" type="string" label="13387" help=""> + <level>2</level> + <default>%D</default> + <heading>16016</heading> + <control type="edit" format="string" /> + </setting> + <setting id="musicfiles.nowplayingtrackformat" type="string" label="13307" help=""> + <level>4</level> + <default></default> + <allowempty>true</allowempty> + <heading>16016</heading> + <control type="edit" format="string" /> + </setting> + <setting id="musicfiles.nowplayingtrackformatright" type="string" label="13387" help=""> + <level>4</level> + <default></default> + <allowempty>true</allowempty> + <heading>16016</heading> + <control type="edit" format="string" /> + </setting> + <setting id="musicfiles.librarytrackformat" type="string" label="13307" help=""> + <level>4</level> + <default></default> + <allowempty>true</allowempty> + <heading>16016</heading> + <control type="edit" format="string" /> + </setting> + <setting id="musicfiles.librarytrackformatright" type="string" label="13387" help=""> + <level>4</level> + <default></default> + <allowempty>true</allowempty> + <heading>16016</heading> + <control type="edit" format="string" /> + </setting> + <setting id="musicfiles.findremotethumbs" type="boolean" label="14059" help=""> + <level>0</level> + <default>true</default> + </setting> + </group> + </category> + <category id="audiocds" label="620" help=""> + <group id="1"> + <setting id="audiocds.autoaction" type="integer" label="14097" help=""> + <level>1</level> + <default>0</default> <!-- AUTOCD_NONE --> + <constraints> + <options>audiocdactions</options> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="audiocds.usecddb" type="boolean" label="227" help=""> + <level>1</level> + <default>true</default> + </setting> + </group> + <group id="2"> + <setting id="audiocds.recordingpath" type="path" label="20000" help=""> + <level>1</level> + <default></default> + <allowempty>true</allowempty> + <heading>657</heading> + <control type="button" format="path" /> + </setting> + <setting id="audiocds.trackpathformat" type="string" label="13307" help=""> + <level>2</level> + <default>%A - %B/[%N. ][%A - ]%T</default> + <heading>16016</heading> + <control type="edit" format="string" /> + </setting> + <setting id="audiocds.encoder" type="integer" label="621" help=""> + <level>2</level> + <default>3</default> <!-- CDDARIP_ENCODER_FLAC --> + <constraints> + <options>audiocdencoders</options> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="audiocds.quality" type="integer" label="622" help=""> + <level>2</level> + <default>0</default> <!-- CDDARIP_QUALITY_CBR --> + <constraints> + <options> + <option label="604">0</option> <!-- CDDARIP_QUALITY_CBR --> + <option label="601">1</option> <!-- CDDARIP_QUALITY_MEDIUM --> + <option label="602">2</option> <!-- CDDARIP_QUALITY_STANDARD --> + <option label="603">3</option> <!-- CDDARIP_QUALITY_EXTREME --> + </options> + </constraints> + <control type="spinner" format="string"> + <dependencies> + <dependency type="enable"> + <and> + <condition setting="audiocds.encoder" operator="!is">2</condition> <!-- CDDARIP_ENCODER_WAV --> + <condition setting="audiocds.encoder" operator="!is">3</condition> <!-- CDDARIP_ENCODER_FLAC --> + </and> + </dependency> + </dependencies> + </control> + </setting> + <setting id="audiocds.bitrate" type="integer" label="623" help=""> + <level>2</level> + <default>192</default> + <constraints> + <minimum>128</minimum> + <step>32</step> + <maximum>320</maximum> + <formatlabel>14048</formatlabel> + </constraints> + <control type="spinner" format="string"> + <dependencies> + <dependency type="enable"> + <and> + <condition setting="audiocds.encoder" operator="!is">2</condition> <!-- CDDARIP_ENCODER_WAV --> + <condition setting="audiocds.encoder" operator="!is">3</condition> <!-- CDDARIP_ENCODER_FLAC --> + <condition setting="audiocds.quality" operator="is">0</condition> <!-- CDDARIP_QUALITY_CBR --> + </and> + </dependency> + </dependencies> + </control> + </setting> + <setting id="audiocds.compressionlevel" type="integer" label="665" help=""> + <level>2</level> + <default>5</default> + <constraints> + <minimum>0</minimum> + <step>1</step> + <maximum>8</maximum> + </constraints> + <control type="spinner" format="integer"> + <dependencies> + <dependency type="enable" setting="audiocds.encoder">3</dependency> <!-- CDDARIP_ENCODER_FLAC --> + </dependencies> + </control> + </setting> + <setting id="audiocds.ejectonrip" type="boolean" label="14099" help=""> + <level>1</level> + <default>true</default> + </setting> + </group> + </category> + <category id="karaoke" label="13327" help=""> + <visible>HAS_KARAOKE</visible> + <group id="1"> + <setting id="karaoke.enabled" type="boolean" label="13323" help=""> + <level>2</level> + <default>false</default> + </setting> + <setting id="karaoke.autopopupselector" type="boolean" label="22037" help=""> + <level>2</level> + <default>false</default> + <control> + <dependencies> + <dependency type="enable" setting="karaoke.enabled">true</dependency> + </dependencies> + </control> + </setting> + </group> + <group id="2"> + <setting id="karaoke.font" type="string" label="22030" help=""> + <level>2</level> + <default>arial.ttf</default> + <constraints> + <options>fonts</options> + </constraints> + <control type="spinner" format="string"> + <dependencies> + <dependency type="enable" setting="karaoke.enabled">true</dependency> + </dependencies> + </control> + </setting> + <setting id="karaoke.fontheight" type="integer" label="22031" help=""> + <level>2</level> + <default>36</default> + <constraints> + <minimum>16</minimum> + <step>2</step> + <maximum>74</maximum> + </constraints> + <control type="spinner" format="string"> + <dependencies> + <dependency type="enable" setting="karaoke.enabled">true</dependency> + <dependency type="update" setting="karaoke.font" /> + </dependencies> + </control> + </setting> + <setting id="karaoke.fontcolors" type="integer" label="22032" help=""> + <level>2</level> + <default>0</default> <!-- white/green --> + <constraints> + <options> + <option label="22040">0</option> <!-- white/green --> + <option label="22041">1</option> <!-- white/red --> + <option label="22042">2</option> <!-- white/blue --> + <option label="22043">3</option> <!-- black/white --> + </options> + </constraints> + <control type="spinner" format="string"> + <dependencies> + <dependency type="enable" setting="karaoke.enabled">true</dependency> + </dependencies> + </control> + </setting> + <setting id="karaoke.charset" type="string" label="22033" help=""> + <level>2</level> + <default>DEFAULT</default> + <constraints> + <options>charsets</options> + </constraints> + <control type="spinner" format="string"> + <dependencies> + <dependency type="enable" setting="karaoke.enabled">true</dependency> + </dependencies> + </control> + </setting> + </group> + <group id="3"> + <setting id="karaoke.export" type="action" label="22038" help=""> + <level>2</level> + <control> + <dependencies> + <dependency type="enable" setting="karaoke.enabled">true</dependency> + </dependencies> + </control> + </setting> + <setting id="karaoke.importcsv" type="action" label="22036" help=""> + <level>2</level> + <control> + <dependencies> + <dependency type="enable" setting="karaoke.enabled">true</dependency> + </dependencies> + </control> + </setting> + </group> + </category> + <category id="mymusic" label="0" help="0"> + <group id="1"> + <setting id="mymusic.startwindow" type="integer" label="0" help=""> + <level>4</level> + <default>10501</default> <!-- WINDOW_MUSIC_FILES --> + </setting> + <setting id="mymusic.songthumbinvis" type="boolean" label="0" help=""> + <level>4</level> + <default>false</default> + </setting> + <setting id="mymusic.defaultlibview" type="string" label="0" help=""> + <level>4</level> + <default></default> + <allowempty>true</allowempty> + </setting> + </group> + </category> + </section> + <section id="pictures" label="1" help=""> + <category id="pictures" label="14081" help=""> + <group id="1"> + <setting id="pictures.usetags" type="boolean" label="14082" help=""> + <level>0</level> + <default>true</default> + </setting> + <setting id="pictures.generatethumbs" type="boolean" label="13360" help=""> + <level>1</level> + <default>true</default> + </setting> + <setting id="pictures.useexifrotation" type="boolean" label="20184" help=""> + <level>1</level> + <default>true</default> + </setting> + <setting id="pictures.showvideos" type="boolean" label="22022" help=""> + <level>1</level> + <default>true</default> + </setting> + <setting id="pictures.displayresolution" type="integer" label="169" help=""> + <visible>false</visible> <!-- not properly respected --> + <level>1</level> + <default>14</default> <!-- RES_AUTORES --> + <constraints> + <options>resolutions</options> + </constraints> + <control type="spinner" format="string" /> + </setting> + </group> + </category> + <category id="slideshow" label="108" help=""> + <group id="1"> + <setting id="slideshow.staytime" type="integer" label="12378" help=""> + <level>0</level> + <default>5</default> + <constraints> + <minimum>1</minimum> + <step>1</step> + <maximum>100</maximum> + <formatlabel>14045</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="slideshow.displayeffects" type="boolean" label="12379" help=""> + <level>0</level> + <default>true</default> + </setting> + <setting id="slideshow.shuffle" type="boolean" label="13319" help=""> + <level>2</level> + <default>false</default> + </setting> + </group> + </category> + </section> + <section id="weather" label="8" help=""> + <category id="weather" label="16000" help=""> + <group id="1"> + <setting id="weather.currentlocation" type="integer" label="0" help=""> + <level>4</level> + <default>0</default> + <constraints> + <minimum>0</minimum> + <step>1</step> + <maximum>2</maximum> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="weather.addon" type="addon" label="24029" help=""> + <level>0</level> + <default>weather.wunderground</default> + <addontype>xbmc.python.weather</addontype> + <allowempty>true</allowempty> + </setting> + <setting id="weather.addonsettings" type="action" label="21417" help=""> + <level>0</level> + <control type="button" format="action"> + <dependencies> + <dependency type="enable" on="property" name="AddonHasSettings" setting="weather.addon" /> + </dependencies> + </control> + </setting> + </group> + </category> + </section> + <section id="services" label="14036" help=""> + <category id="general" label="16000" help=""> + <group id="1"> + <setting id="services.devicename" type="string" label="1271" help=""> + <level>0</level> + <default>XBMC</default> + <control type="edit" format="string" /> + </setting> + </group> + </category> + <category id="upnp" label="20187" help=""> + <group id="1"> + <setting id="services.upnpserver" type="boolean" label="21360" help=""> + <level>0</level> + <default>false</default> + </setting> + <setting id="services.upnpannounce" type="boolean" label="20188" help=""> + <level>2</level> + <default>true</default> + <control> + <dependencies> + <dependency type="enable" setting="services.upnpserver">true</dependency> + </dependencies> + </control> + </setting> + <setting id="services.upnprenderer" type="boolean" label="21881" help=""> + <level>1</level> + <default>false</default> + </setting> + <setting id="services.upnpcontroller" type="boolean" label="21361" help=""> + <level>1</level> + <default>false</default> + </setting> + </group> + </category> + <category id="webserver" label="33101" help=""> + <visible>HAS_WEB_SERVER</visible> + <group id="1"> + <setting id="services.webserver" type="boolean" label="263" help=""> + <level>1</level> + <default>false</default> + </setting> + <setting id="services.webserverport" type="integer" label="730" help=""> + <level>2</level> + <default>8080</default> + <heading>730</heading> + <constraints> + <minimum>1</minimum> + <step>1</step> + <maximum>65535</maximum> + </constraints> + <control type="edit" format="integer"> + <dependencies> + <dependency type="enable" setting="services.webserver">true</dependency> + </dependencies> + </control> + </setting> + <setting id="services.webserverusername" type="string" label="1048" help=""> + <level>2</level> + <default>xbmc</default> + <allowempty>true</allowempty> + <control type="edit" format="string"> + <dependencies> + <dependency type="enable" setting="services.webserver">true</dependency> + </dependencies> + </control> + </setting> + <setting id="services.webserverpassword" type="string" label="733" help=""> + <level>2</level> + <default></default> + <allowempty>true</allowempty> + <heading>730</heading> + <control type="edit" format="string" attributes="hidden"> + <dependencies> + <dependency type="enable" setting="services.webserver">true</dependency> + </dependencies> + </control> + </setting> + <setting id="services.webskin" type="addon" label="199" help=""> + <level>1</level> + <default>webinterface.default</default> + <addontype>xbmc.gui.webinterface</addontype> + </setting> + </group> + </category> + <category id="remotecontrol" label="790" help=""> + <visible> + <or> + <condition>HAS_EVENT_SERVER</condition> + <condition>HAS_JSONRPC</condition> + </or> + </visible> + <group id="1"> + <setting id="services.esenabled" type="boolean" label="791" help=""> + <level>1</level> + <default>true</default> + </setting> + <setting id="services.esport" type="integer" label="792" help=""> + <visible>HAS_EVENT_SERVER</visible> + <level>4</level> + <default>9777</default> + <constraints> + <minimum>1</minimum> + <step>1</step> + <maximum>65535</maximum> + </constraints> + <control type="edit" format="integer"> + <dependencies> + <dependency type="enable" setting="services.esenabled">true</dependency> + </dependencies> + </control> + </setting> + <setting id="services.esportrange" type="integer" label="793" help=""> + <visible>HAS_EVENT_SERVER</visible> + <level>4</level> + <default>10</default> + <constraints> + <minimum>1</minimum> + <step>1</step> + <maximum>100</maximum> + </constraints> + <control type="spinner" format="integer"> + <dependencies> + <dependency type="enable" setting="services.esenabled">true</dependency> + </dependencies> + </control> + </setting> + <setting id="services.esmaxclients" type="integer" label="797" help=""> + <visible>HAS_EVENT_SERVER</visible> + <level>4</level> + <default>20</default> + <constraints> + <minimum>1</minimum> + <step>1</step> + <maximum>100</maximum> + </constraints> + <control type="spinner" format="integer"> + <dependencies> + <dependency type="enable" setting="services.esenabled">true</dependency> + </dependencies> + </control> + </setting> + <setting id="services.esallinterfaces" type="boolean" label="794" help=""> + <level>1</level> + <default>false</default> + <control> + <dependencies> + <dependency type="enable" setting="services.esenabled">true</dependency> + </dependencies> + </control> + </setting> + <setting id="services.esinitialdelay" type="integer" label="795" help=""> + <visible>HAS_EVENT_SERVER</visible> + <level>4</level> + <default>750</default> + <constraints> + <minimum>5</minimum> + <step>5</step> + <maximum>10000</maximum> + </constraints> + <control type="spinner" format="integer"> + <dependencies> + <dependency type="enable" setting="services.esenabled">true</dependency> + </dependencies> + </control> + </setting> + <setting id="services.escontinuousdelay" type="integer" label="796" help=""> + <visible>HAS_EVENT_SERVER</visible> + <level>4</level> + <default>25</default> + <constraints> + <minimum>5</minimum> + <step>5</step> + <maximum>10000</maximum> + </constraints> + <control type="spinner" format="integer"> + <dependencies> + <dependency type="enable" setting="services.esenabled">true</dependency> + </dependencies> + </control> + </setting> + </group> + </category> + <category id="zeroconf" label="1259" help=""> + <visible>HAS_ZEROCONF</visible> + <group id="1"> + <setting id="services.zeroconf" type="boolean" label="1260" help=""> + <level>2</level> + <default>true</default> + </setting> + </group> + </category> + <category id="airplay" label="1273" help=""> + <visible>HAS_AIRPLAY</visible> + <group id="1"> + <setting id="services.airplay" type="boolean" label="1270" help=""> + <level>1</level> + <default>false</default> + </setting> + <setting id="services.useairplaypassword" type="boolean" label="1272" help=""> + <level>1</level> + <default>false</default> + <control> + <dependencies> + <dependency type="enable" setting="services.airplay">true</dependency> + </dependencies> + </control> + </setting> + <setting id="services.airplaypassword" type="string" label="733" help=""> + <level>1</level> + <default></default> + <allowempty>true</allowempty> + <heading>733</heading> + <control type="edit" format="string" attributes="hidden"> + <dependencies> + <dependency type="enable" setting="services.useairplaypassword">true</dependency> + </dependencies> + </control> + </setting> + </group> + </category> + <category id="smb" label="1200" help=""> + <group id="1"> + <setting id="smb.winsserver" type="string" label="1207" help=""> + <level>2</level> + <default>0.0.0.0</default> + <control type="edit" format="ip" /> + </setting> + <setting id="smb.workgroup" type="string" label="1202" help=""> + <level>2</level> + <default>WORKGROUP</default> + <heading>1202</heading> + <control type="edit" format="string" /> + </setting> + </group> + </category> + </section> + <section id="system" label="13000" help=""> + <category id="videoscreen" label="21373" help=""> + <group id="1"> + <setting id="videoscreen.screen" type="integer" label="240" help=""> + <level>0</level> + <default>0</default> + <constraints> + <options>screens</options> + </constraints> + <control type="spinner" format="string" delayed="true" /> + </setting> + <setting id="videoscreen.resolution" type="integer" label="169" help=""> + <level>0</level> + <default>16</default> <!-- RES_DESKTOP --> + <constraints> + <options>resolutions</options> + </constraints> + <control type="spinner" format="string" delayed="true"> + <dependencies> + <dependency type="enable" setting="videoscreen.screen" operator="!is">-1</dependency> <!-- DM_WINDOWED --> + <dependency type="update" setting="videoscreen.screen" /> + </dependencies> + </control> + </setting> + <setting id="videoscreen.screenmode" type="string" label="243" help=""> + <visible>IsStandAlone</visible> + <level>0</level> + <default>DESKTOP</default> + <constraints> + <options>refreshrates</options> + </constraints> + <updates> + <update type="change" /> + </updates> + <control type="spinner" format="string" delayed="true"> + <dependencies> + <dependency type="enable" setting="videoscreen.screen" operator="!is">-1</dependency> <!-- DM_WINDOWED --> + <dependency type="update" setting="videoscreen.screen" /> + <dependency type="update" setting="videoscreen.resolution" /> + </dependencies> + </control> + </setting> + <setting id="videoscreen.fakefullscreen" type="boolean" label="14083" help=""> + <level>2</level> + <default>true</default> + <control> + <dependencies> + <dependency type="enable" setting="videoscreen.screen" operator="!is">-1</dependency> <!-- DM_WINDOWED --> + </dependencies> + </control> + </setting> + <setting id="videoscreen.blankdisplays" type="boolean" label="13130" help=""> + <level>1</level> + <default>false</default> + <control> + <dependencies> + <dependency type="enable" on="property" name="IsFullscreen" /> + </dependencies> + </control> + </setting> + </group> + <group id="2"> + <setting id="videoscreen.vsync" type="integer" label="13105" help=""> + <level>2</level> + <default>3</default> <!-- VSYNC_DRIVER --> + <constraints> + <options>verticalsyncs</options> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="videoscreen.guicalibration" type="action" label="214" help=""> + <level>1</level> + </setting> + <setting id="videoscreen.testpattern" type="action" label="226" help=""> + <visible>HAS_GL</visible> + <level>1</level> + </setting> + <setting id="videoscreen.limitedrange" type="boolean" label="36042" help=""> + <visible> + <or> + <condition>HAS_GL</condition> + <condition>HAS_DX</condition> + </or> + </visible> + <level>3</level> + <default>false</default> + <updates> + <update type="rename">videoplayer.vdpaustudiolevel</update> + </updates> + </setting> + </group> + </category> + <category id="audiooutput" label="772" help=""> + <group id="1"> + <setting id="audiooutput.mode" type="integer" label="337" help=""> + <level>1</level> + <default>0</default> <!-- AUDIO_ANALOG --> + <constraints> + <options>audiooutputmodes</options> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="audiooutput.channels" type="integer" label="34100" help=""> + <level>0</level> + <default>1</default> <!-- AE_CH_LAYOUT_2_0 --> + <constraints> + <options> + <option label="34101">1</option> <!-- AE_CH_LAYOUT_2_0 --> + <option label="34102">2</option> <!-- AE_CH_LAYOUT_2_1 --> + <option label="34103">3</option> <!-- AE_CH_LAYOUT_3_0 --> + <option label="34104">4</option> <!-- AE_CH_LAYOUT_3_1 --> + <option label="34105">5</option> <!-- AE_CH_LAYOUT_4_0 --> + <option label="34106">6</option> <!-- AE_CH_LAYOUT_4_1 --> + <option label="34107">7</option> <!-- AE_CH_LAYOUT_5_0 --> + <option label="34108">8</option> <!-- AE_CH_LAYOUT_5_1 --> + <option label="34109">9</option> <!-- AE_CH_LAYOUT_7_0 --> + <option label="34110">10</option> <!-- AE_CH_LAYOUT_7_1 --> + </options> + </constraints> + <updates> + <update type="rename">audiooutput.channellayout</update> + </updates> + <control type="spinner" format="string" /> + </setting> + <setting id="audiooutput.normalizelevels" type="boolean" label="346" help=""> + <level>2</level> + <default>true</default> + </setting> + <setting id="audiooutput.stereoupmix" type="boolean" label="252" help=""> + <level>2</level> + <default>false</default> + </setting> + <setting id="audiooutput.ac3passthrough" type="boolean" label="364" help=""> + <level>2</level> + <default>true</default> + <control> + <dependencies> + <dependency type="enable"> + <or> + <condition setting="audiooutput.mode">1</condition> <!-- AUDIO_IEC958 --> + <condition setting="audiooutput.mode">2</condition> <!-- AUDIO_HDMI --> + </or> + </dependency> + </dependencies> + </control> + </setting> + <setting id="audiooutput.dtspassthrough" type="boolean" label="254" help=""> + <level>2</level> + <default>true</default> + <control> + <dependencies> + <dependency type="enable"> + <or> + <condition setting="audiooutput.mode">1</condition> <!-- AUDIO_IEC958 --> + <condition setting="audiooutput.mode">2</condition> <!-- AUDIO_HDMI --> + </or> + </dependency> + </dependencies> + </control> + </setting> + <setting id="audiooutput.passthroughaac" type="boolean" label="299" help=""> + <level>2</level> + <default>false</default> + <control> + <dependencies> + <dependency type="enable"> + <or> + <condition setting="audiooutput.mode">1</condition> <!-- AUDIO_IEC958 --> + <condition setting="audiooutput.mode">2</condition> <!-- AUDIO_HDMI --> + </or> + </dependency> + </dependencies> + </control> + </setting> + <setting id="audiooutput.multichannellpcm" type="boolean" label="348" help=""> + <level>2</level> + <default>true</default> + <control> + <dependencies> + <dependency type="enable" setting="audiooutput.mode">2</dependency> <!-- AUDIO_HDMI --> + </dependencies> + </control> + </setting> + <setting id="audiooutput.truehdpassthrough" type="boolean" label="349" help=""> + <level>2</level> + <default>true</default> + <control> + <dependencies> + <dependency type="enable" setting="audiooutput.mode">2</dependency> <!-- AUDIO_HDMI --> + </dependencies> + </control> + </setting> + <setting id="audiooutput.dtshdpassthrough" type="boolean" label="347" help=""> + <level>2</level> + <default>true</default> + <control> + <dependencies> + <dependency type="enable"> + <and> + <condition setting="audiooutput.dtspassthrough">true</condition> + <condition setting="audiooutput.mode">2</condition> <!-- AUDIO_HDMI --> + </and> + </dependency> + </dependencies> + </control> + </setting> + </group> + <group id="2"> + <setting id="audiooutput.audiodevice" type="string" label="545" help=""> + <level>2</level> + <default>Default</default> <!-- will be properly set on startup --> + <constraints> + <options>audiodevices</options> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="audiooutput.passthroughdevice" type="string" label="546" help=""> + <level>2</level> + <default>Default</default> <!-- will be properly set on startup --> + <constraints> + <options>audiodevicespassthrough</options> + </constraints> + <control type="spinner" format="string"> + <dependencies> + <dependency type="enable"> + <or> + <condition setting="audiooutput.mode">1</condition> <!-- AUDIO_IEC958 --> + <condition setting="audiooutput.mode">2</condition> <!-- AUDIO_HDMI --> + </or> + </dependency> + </dependencies> + </control> + </setting> + </group> + <group id="3"> + <setting id="audiooutput.guisoundmode" type="integer" label="34120" help=""> + <level>0</level> + <default>1</default> <!-- AE_SOUND_IDLE --> + <constraints> + <options> + <option label="34121">1</option> <!-- AE_SOUND_IDLE --> + <option label="34122">2</option> <!-- AE_SOUND_ALWAYS --> + <option label="34123">0</option> <!-- AE_SOUND_OFF --> + </options> + </constraints> + <control type="spinner" format="string" /> + </setting> + </group> + </category> + <category id="input" label="14094" help=""> + <group id="1"> + <setting id="input.peripherals" type="action" label="35000" help=""> + <level>2</level> + <control> + <dependencies> + <dependency type="enable" on="property" name="HasPeripherals" /> + </dependencies> + </control> + </setting> + </group> + <group id="2"> + <setting id="input.remoteaskeyboard" type="boolean" label="21449" help=""> + <level>2</level> + <default>false</default> + </setting> + <setting id="input.enablemouse" type="boolean" label="21369" help=""> + <level>0</level> + <default>true</default> + </setting> + <setting id="input.enablejoystick" type="boolean" label="35100" help=""> + <visible>HAS_SDL_JOYSTICK</visible> + <level>0</level> + <default>true</default> + </setting> + </group> + </category> + <category id="network" label="798" help=""> + <group id="1"> + <setting id="network.usehttpproxy" type="boolean" label="708" help=""> + <level>1</level> + <default>false</default> + </setting> + <setting id="network.httpproxytype" type="integer" label="1180" help=""> + <level>1</level> + <default>0</default> + <constraints> + <options> + <option label="1181">0</option> <!-- PROXY_HTTP --> + <option label="1182">1</option> <!-- PROXY_SOCKS4 --> + <option label="1183">2</option> <!-- PROXY_SOCKS4A --> + <option label="1184">3</option> <!-- PROXY_SOCKS5 --> + <option label="1185">4</option> <!-- PROXY_SOCKS5_REMOTE --> + </options> + </constraints> + <control type="spinner" format="string"> + <dependencies> + <dependency type="enable" setting="network.usehttpproxy">true</dependency> + </dependencies> + </control> + </setting> + <setting id="network.httpproxyserver" type="string" label="706" help=""> + <level>1</level> + <default></default> + <allowempty>true</allowempty> + <control type="edit" format="string"> + <dependencies> + <dependency type="enable" setting="network.usehttpproxy">true</dependency> + </dependencies> + </control> + </setting> + <setting id="network.httpproxyport" type="integer" label="730" help=""> + <level>1</level> + <default>8080</default> + <heading>707</heading> + <constraints> + <minimum>1</minimum> + <step>1</step> + <maximum>65535</maximum> + </constraints> + <control type="edit" format="integer"> + <dependencies> + <dependency type="enable" setting="network.usehttpproxy">true</dependency> + </dependencies> + </control> + </setting> + <setting id="network.httpproxyusername" type="string" label="1048" help=""> + <level>1</level> + <default></default> + <allowempty>true</allowempty> + <control type="edit" format="string"> + <dependencies> + <dependency type="enable" setting="network.usehttpproxy">true</dependency> + </dependencies> + </control> + </setting> + <setting id="network.httpproxypassword" type="string" label="733" help=""> + <level>1</level> + <default></default> + <allowempty>true</allowempty> + <control type="edit" format="string" attributes="hidden"> + <dependencies> + <dependency type="enable" setting="network.usehttpproxy">true</dependency> + </dependencies> + </control> + </setting> + </group> + <group id="2"> + <setting id="network.bandwidth" type="integer" label="14041" help=""> + <level>2</level> + <default>0</default> + <constraints> + <minimum label="351">0</minimum> + <step>512</step> + <maximum>102400</maximum> + <formatlabel>14048</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + </group> + </category> + <category id="powermanagement" label="14095" help=""> + <group id="1"> + <setting id="powermanagement.displaysoff" type="integer" label="1450" help=""> + <level>0</level> + <default>0</default> + <constraints> + <minimum label="351">0</minimum> + <step>5</step> + <maximum>120</maximum> + <formatlabel>14044</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="powermanagement.shutdowntime" type="integer" label="357" help=""> + <level>2</level> + <default>0</default> + <constraints> + <minimum label="351">0</minimum> + <step>5</step> + <maximum>120</maximum> + <formatlabel>14044</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="powermanagement.shutdownstate" type="integer" label="13008" help=""> + <level>2</level> + <default>0</default> <!-- POWERSTATE_QUIT --> + <constraints> + <options>shutdownstates</options> + </constraints> + <control type="spinner" format="string" /> + </setting> + </group> + </category> + <category id="debug" label="14092" help=""> + <group id="1"> + <setting id="debug.showloginfo" type="boolean" label="20191" help=""> + <level>1</level> + <default>false</default> + </setting> + <setting id="debug.screenshotpath" type="path" label="20004" help=""> + <level>1</level> + <default></default> + <allowempty>true</allowempty> + <heading>657</heading> + <control type="button" format="path" /> + </setting> + <setting id="debug.setextraloglevel" type="action" label="666" help=""> + <level>1</level> + <control type="button" format="action"> + <dependencies> + <dependency type="enable" setting="debug.showloginfo">true</dependency> + </dependencies> + </control> + </setting> + </group> + </category> + <category id="masterlock" label="12360" help=""> + <access>CheckMasterLock</access> + <group id="1"> + <setting id="masterlock.lockcode" type="string" label="20100" help=""> + <level>2</level> + <default>-</default> + <control type="button" format="action" /> + </setting> + <setting id="masterlock.startuplock" type="boolean" label="20076" help=""> + <level>2</level> + <default>false</default> + <control> + <dependencies> + <dependency type="enable" on="property" name="ProfileLockMode" operator="!is">0</dependency> + </dependencies> + </control> + </setting> + <setting id="masterlock.maxretries" type="integer" label="12364" help=""> + <level>4</level> + <default>3</default> + <constraints> + <minimum>3</minimum> + <step>1</step> + <maximum>100</maximum> + </constraints> + <control type="spinner" format="integer" /> + </setting> + </group> + </category> + <category id="cache" label="439" help=""> + <visible>false</visible> + <group id="1"> + <setting id="cache.harddisk" type="integer" label="14025" help=""> + <level>4</level> + <default>256</default> + <constraints> + <minimum label="351">0</minimum> + <step>256</step> + <maximum>4096</maximum> + <formatlabel>14049</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + </group> + <group id="2"> + <setting id="cachevideo.dvdrom" type="integer" label="14026" help=""> + <level>4</level> + <default>2048</default> + <constraints> + <minimum label="351">0</minimum> + <step>256</step> + <maximum>16384</maximum> + <formatlabel>14049</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="cachevideo.lan" type="integer" label="14027" help=""> + <level>4</level> + <default>2048</default> + <constraints> + <minimum label="351">0</minimum> + <step>256</step> + <maximum>16384</maximum> + <formatlabel>14049</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="cachevideo.internet" type="integer" label="14028" help=""> + <level>4</level> + <default>4096</default> + <constraints> + <minimum label="351">0</minimum> + <step>256</step> + <maximum>16384</maximum> + <formatlabel>14049</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + </group> + <group id="3"> + <setting id="cacheaudio.dvdrom" type="integer" label="14030" help=""> + <level>4</level> + <default>256</default> + <constraints> + <minimum label="351">0</minimum> + <step>256</step> + <maximum>4096</maximum> + <formatlabel>14049</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="cacheaudio.lan" type="integer" label="14031" help=""> + <level>4</level> + <default>256</default> + <constraints> + <minimum label="351">0</minimum> + <step>256</step> + <maximum>4096</maximum> + <formatlabel>14049</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="cacheaudio.internet" type="integer" label="14032" help=""> + <level>4</level> + <default>256</default> + <constraints> + <minimum label="351">0</minimum> + <step>256</step> + <maximum>4096</maximum> + <formatlabel>14049</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + </group> + <group id="4"> + <setting id="cachedvd.dvdrom" type="integer" label="14034" help=""> + <level>4</level> + <default>2048</default> + <constraints> + <minimum label="351">0</minimum> + <step>256</step> + <maximum>16384</maximum> + <formatlabel>14049</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + <setting id="cachedvd.lan" type="integer" label="14060" help=""> + <level>4</level> + <default>2048</default> + <constraints> + <minimum label="351">0</minimum> + <step>256</step> + <maximum>16384</maximum> + <formatlabel>14049</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + </group> + <group id="5"> + <setting id="cacheunknown.internet" type="integer" label="4096" help=""> + <level>4</level> + <default>4096</default> + <constraints> + <minimum label="351">0</minimum> + <step>256</step> + <maximum>16384</maximum> + <formatlabel>14049</formatlabel> + </constraints> + <control type="spinner" format="string" /> + </setting> + </group> + </category> + <category id="paths" label="" help=""> + <group id="1"> + <setting id="system.playlistspath" type="path" label="20006" help=""> + <level>4</level> + <default></default> + <allowempty>true</allowempty> + </setting> + </group> + </category> + <category id="general" label="" help=""> + <group id="1"> + <setting id="general.addonautoupdate" type="boolean" label="0" help=""> + <level>4</level> + <default>true</default> + </setting> + <setting id="general.addonnotifications" type="boolean" label="0" help=""> + <level>4</level> + <default>true</default> + </setting> + <setting id="general.addonforeignfilter" type="boolean" label="0" help=""> + <level>4</level> + <default>false</default> + </setting> + </group> + </category> + </section> +</settings> diff --git a/system/settings/win32.xml b/system/settings/win32.xml new file mode 100644 index 0000000000..0daee415ef --- /dev/null +++ b/system/settings/win32.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="utf-8" ?> +<settings> + <section id="appearance"> + <category id="locale"> + <group id="2"> + <visible>false</visible> + </group> + </category> + </section> + <section id="videos"> + <category id="videoplayer"> + <group id="2"> + <setting id="videoplayer.usedisplayasclock"> + <visible negated="true">HAS_GL</visible> + </setting> + <setting id="videoplayer.synctype"> + <visible negated="true">HAS_GL</visible> + </setting> + </group> + </category> + </section> + <section id="services"> + <category id="zeroconf"> + <group id="1"> + <setting id="services.zeroconf"> + <default>false</default> + </setting> + </group> + </category> + <category id="smb" label="1200" help=""> + <visible>false</visible> + </category> + </section> + <section id="system"> + <category id="videoscreen"> + <group id="1"> + <setting id="videoscreen.fakefullscreen"> + <visible negated="true">HAS_GL</visible> + </setting> + </group> + </category> + </section> +</settings> diff --git a/tools/android/packaging/Makefile b/tools/android/packaging/Makefile index 2174415d7b..9c20f2b94f 100644 --- a/tools/android/packaging/Makefile +++ b/tools/android/packaging/Makefile @@ -3,7 +3,7 @@ include ../../depends/Makefile.include OBJS = libcurl.so \ librtmp.so libmad.so \ libafpclient.so \ - libshairport.so libplist.so \ + libplist.so \ libxbogg.so libxbvorbis.so libxbvorbisfile.so libxbFLAC.so libxbmpeg2.so \ libxbmpeg2convert.so libnfs.so libass.so diff --git a/tools/android/packaging/xbmc/AndroidManifest.xml b/tools/android/packaging/xbmc/AndroidManifest.xml index 31573a988a..9aa52a5c40 100644 --- a/tools/android/packaging/xbmc/AndroidManifest.xml +++ b/tools/android/packaging/xbmc/AndroidManifest.xml @@ -2,8 +2,8 @@ <!-- BEGIN_INCLUDE(manifest) --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.xbmc.xbmc" - android:versionCode="9" - android:versionName="13.0-ALPHA3" > + android:versionCode="10" + android:versionName="13.0-ALPHA4" > <!-- This is the platform API where NativeActivity was introduced. --> <uses-sdk android:minSdkVersion="14" /> diff --git a/tools/buildsteps/android/configure-depends b/tools/buildsteps/android/configure-depends index 13ab6cdd53..73f9be569f 100644 --- a/tools/buildsteps/android/configure-depends +++ b/tools/buildsteps/android/configure-depends @@ -5,11 +5,11 @@ XBMC_PLATFORM_DIR=android if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ] then cd $WORKSPACE/tools/depends;./configure \ - --with-tarballs=/opt/xbmc-tarballs \ + --with-tarballs=$TARBALLS \ --host=arm-linux-androideabi \ --with-sdk-path=$SDK_PATH \ --with-ndk=$NDK_PATH \ - --with-sdk=android-$SDK_VERSION \ + $(if [ "$SDK_VERSION" != "Default" ]; then echo --with-sdk=android-$SDK_VERSION;fi) \ --with-toolchain=$TOOLCHAIN \ --prefix=$XBMC_DEPENDS_ROOT fi diff --git a/tools/buildsteps/atv2/make-xbmc b/tools/buildsteps/atv2/make-xbmc index 743db59d11..5a68e3d206 100755 --- a/tools/buildsteps/atv2/make-xbmc +++ b/tools/buildsteps/atv2/make-xbmc @@ -4,5 +4,5 @@ XBMC_PLATFORM_DIR=atv2 cd $WORKSPACE;make -j$BUILDTHREADS xcode_depends cd $WORKSPACE;xcodebuild -project XBMC-ATV2.xcodeproj -target XBMC -configuration $Configuration build \ - ONLY_ACTIVE_ARCH=YES ARCHS=armv7 VALID_ARCHS=armv7 IPHONEOS_DEPLOYMENT_TARGET=4.1 \ + ONLY_ACTIVE_ARCH=YES ARCHS=armv7 VALID_ARCHS=armv7 IPHONEOS_DEPLOYMENT_TARGET=4.2 \ SDKROOT=iphoneos$SDK_VERSION XBMC_DEPENDS_ROOT=$XBMC_DEPENDS_ROOT diff --git a/tools/buildsteps/defaultenv b/tools/buildsteps/defaultenv index 9547e835c0..bbdcb29c90 100644 --- a/tools/buildsteps/defaultenv +++ b/tools/buildsteps/defaultenv @@ -3,6 +3,8 @@ SDK_VERSION=${SDK_VERSION:-"Default"} Configuration=${Configuration:-"Default"} XBMC_DEPENDS_ROOT=${XBMC_DEPENDS_ROOT:-"Default"} PATH_CHANGE_REV_FILENAME=".last_success_revision" +#TARBALLS ENV-VAR is only used by android scripts atm +TARBALLS=${TARBALLS:-"/opt/xbmc-tarballs"} #set platform defaults #$XBMC_PLATFORM_DIR matches the platform subdirs! @@ -30,29 +32,35 @@ case $XBMC_PLATFORM_DIR in DEFAULT_XBMC_DEPENDS_ROOT=$WORKSPACE/tools/depends/xbmc-depends DEFAULT_CONFIGURATION="Debug" ;; + android) - DEFAULT_SDK_VERSION=10 + DEFAULT_SDK_VERSION="Default" + DEFAULT_XBMC_DEPENDS_ROOT=$WORKSPACE/tools/depends/xbmc-depends + DEFAULT_CONFIGURATION="Debug" + ;; + + linux*) DEFAULT_XBMC_DEPENDS_ROOT=$WORKSPACE/tools/depends/xbmc-depends DEFAULT_CONFIGURATION="Debug" esac -if [ $SDK_VERSION == "Default" ] +if [ "$SDK_VERSION" == "Default" ] then SDK_VERSION=$DEFAULT_SDK_VERSION fi -if [ $XBMC_DEPENDS_ROOT == "Default" ] +if [ "$XBMC_DEPENDS_ROOT" == "Default" ] then XBMC_DEPENDS_ROOT=$DEFAULT_XBMC_DEPENDS_ROOT fi -if [ $Configuration == "Default" ] +if [ "$Configuration" == "Default" ] then Configuration=$DEFAULT_CONFIGURATION fi #clamp release builds to 1 thread only -if [ $Configuration == "Release" ] +if [ "$Configuration" == "Release" ] then BUILDTHREADS=1 fi @@ -76,7 +84,7 @@ function pathChanged () local checkPath ret="0" #no optims in release builds! - if [ $Configuration == "Release" ] + if [ "$Configuration" == "Release" ] then echo "1" return diff --git a/tools/buildsteps/ios/make-xbmc b/tools/buildsteps/ios/make-xbmc index 7693d21472..407c19f02a 100755 --- a/tools/buildsteps/ios/make-xbmc +++ b/tools/buildsteps/ios/make-xbmc @@ -4,6 +4,6 @@ XBMC_PLATFORM_DIR=ios cd $WORKSPACE;make -j$BUILDTHREADS xcode_depends cd $WORKSPACE;xcodebuild -project XBMC-IOS.xcodeproj -target XBMC -configuration $Configuration build \ - ONLY_ACTIVE_ARCH=YES ARCHS=armv7 VALID_ARCHS=armv7 IPHONEOS_DEPLOYMENT_TARGET=4.1 \ + ONLY_ACTIVE_ARCH=YES ARCHS=armv7 VALID_ARCHS=armv7 IPHONEOS_DEPLOYMENT_TARGET=4.2 \ SDKROOT=iphoneos$SDK_VERSION XBMC_DEPENDS_ROOT=$XBMC_DEPENDS_ROOT diff --git a/tools/buildsteps/linux32/configure-depends b/tools/buildsteps/linux32/configure-depends new file mode 100755 index 0000000000..4f34c32e7b --- /dev/null +++ b/tools/buildsteps/linux32/configure-depends @@ -0,0 +1,9 @@ +WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )} +XBMC_PLATFORM_DIR=linux32 +. $WORKSPACE/tools/buildsteps/defaultenv + +if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ] +then + cd $WORKSPACE/tools/depends;./configure \ + --with-toolchain=/usr --prefix=$XBMC_DEPENDS_ROOT --host=i686-linux-gnu +fi diff --git a/tools/buildsteps/linux32/configure-xbmc b/tools/buildsteps/linux32/configure-xbmc new file mode 100755 index 0000000000..5e532760bf --- /dev/null +++ b/tools/buildsteps/linux32/configure-xbmc @@ -0,0 +1,5 @@ +WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )} +XBMC_PLATFORM_DIR=linux32 +. $WORKSPACE/tools/buildsteps/defaultenv + +cd $WORKSPACE/;./configure diff --git a/tools/buildsteps/linux32/make-depends b/tools/buildsteps/linux32/make-depends new file mode 100755 index 0000000000..73e21a6ada --- /dev/null +++ b/tools/buildsteps/linux32/make-depends @@ -0,0 +1,9 @@ +WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )} +XBMC_PLATFORM_DIR=linux32 +. $WORKSPACE/tools/buildsteps/defaultenv + +if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ] +then + cd $WORKSPACE/tools/depends;make -j $BUILDTHREADS && tagSuccessFulBuild . +fi + diff --git a/tools/buildsteps/linux32/make-xbmc b/tools/buildsteps/linux32/make-xbmc new file mode 100755 index 0000000000..a2bc0a7afc --- /dev/null +++ b/tools/buildsteps/linux32/make-xbmc @@ -0,0 +1,5 @@ +WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )} +XBMC_PLATFORM_DIR=linux32 +. $WORKSPACE/tools/buildsteps/defaultenv + +cd $WORKSPACE;make -j$BUILDTHREADS diff --git a/tools/buildsteps/linux32/package b/tools/buildsteps/linux32/package new file mode 100755 index 0000000000..45dc4c34cf --- /dev/null +++ b/tools/buildsteps/linux32/package @@ -0,0 +1,10 @@ +WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )} +XBMC_PLATFORM_DIR=linux32 +. $WORKSPACE/tools/buildsteps/defaultenv + +#nothing for linux atm + +#rename for upload +#e.x. xbmc-20130314-8c2fb31-Frodo-armeabi-v7a.apk +UPLOAD_FILENAME="xbmc-$(getBuildRevDateStr)-armeabi-v7a.apk" +#mv xbmcapp-armeabi-*.apk $UPLOAD_FILENAME diff --git a/tools/buildsteps/linux32/prepare-depends b/tools/buildsteps/linux32/prepare-depends new file mode 100755 index 0000000000..51878d9f1a --- /dev/null +++ b/tools/buildsteps/linux32/prepare-depends @@ -0,0 +1,13 @@ +WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )} +XBMC_PLATFORM_DIR=linux32 +. $WORKSPACE/tools/buildsteps/defaultenv + +#clean without depends for skipping depends build if possible +cd $WORKSPACE;git clean -xfd -e "tools/depends" + +if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ] +then + #clean up the rest too + cd $WORKSPACE;git clean -xfd + cd $WORKSPACE/tools/depends/;./bootstrap +fi diff --git a/tools/buildsteps/linux32/prepare-xbmc b/tools/buildsteps/linux32/prepare-xbmc new file mode 100755 index 0000000000..ca3a3d2774 --- /dev/null +++ b/tools/buildsteps/linux32/prepare-xbmc @@ -0,0 +1,5 @@ +WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )} +XBMC_PLATFORM_DIR=linux32 +. $WORKSPACE/tools/buildsteps/defaultenv + +#nothing on linux diff --git a/tools/buildsteps/linux64/configure-depends b/tools/buildsteps/linux64/configure-depends new file mode 100755 index 0000000000..1460e3c630 --- /dev/null +++ b/tools/buildsteps/linux64/configure-depends @@ -0,0 +1,9 @@ +WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )} +XBMC_PLATFORM_DIR=linux64 +. $WORKSPACE/tools/buildsteps/defaultenv + +if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ] +then + cd $WORKSPACE/tools/depends;./configure \ + --with-toolchain=/usr --prefix=$XBMC_DEPENDS_ROOT --host=x86_64-linux-gnu +fi diff --git a/tools/buildsteps/linux64/configure-xbmc b/tools/buildsteps/linux64/configure-xbmc new file mode 100755 index 0000000000..38a5e2d862 --- /dev/null +++ b/tools/buildsteps/linux64/configure-xbmc @@ -0,0 +1,5 @@ +WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )} +XBMC_PLATFORM_DIR=linux64 +. $WORKSPACE/tools/buildsteps/defaultenv + +cd $WORKSPACE/;./configure diff --git a/tools/buildsteps/linux64/make-depends b/tools/buildsteps/linux64/make-depends new file mode 100755 index 0000000000..c9c98aa09a --- /dev/null +++ b/tools/buildsteps/linux64/make-depends @@ -0,0 +1,9 @@ +WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )} +XBMC_PLATFORM_DIR=linux64 +. $WORKSPACE/tools/buildsteps/defaultenv + +if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ] +then + cd $WORKSPACE/tools/depends;make -j $BUILDTHREADS && tagSuccessFulBuild . +fi + diff --git a/tools/buildsteps/linux64/make-xbmc b/tools/buildsteps/linux64/make-xbmc new file mode 100755 index 0000000000..10200c8529 --- /dev/null +++ b/tools/buildsteps/linux64/make-xbmc @@ -0,0 +1,5 @@ +WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )} +XBMC_PLATFORM_DIR=linux64 +. $WORKSPACE/tools/buildsteps/defaultenv + +cd $WORKSPACE;make -j$BUILDTHREADS diff --git a/tools/buildsteps/linux64/package b/tools/buildsteps/linux64/package new file mode 100755 index 0000000000..243f5097ff --- /dev/null +++ b/tools/buildsteps/linux64/package @@ -0,0 +1,10 @@ +WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )} +XBMC_PLATFORM_DIR=linux64 +. $WORKSPACE/tools/buildsteps/defaultenv + +#nothing for linux atm + +#rename for upload +#e.x. xbmc-20130314-8c2fb31-Frodo-armeabi-v7a.apk +UPLOAD_FILENAME="xbmc-$(getBuildRevDateStr)-armeabi-v7a.apk" +#mv xbmcapp-armeabi-*.apk $UPLOAD_FILENAME diff --git a/tools/buildsteps/linux64/prepare-depends b/tools/buildsteps/linux64/prepare-depends new file mode 100755 index 0000000000..710ad5b8ff --- /dev/null +++ b/tools/buildsteps/linux64/prepare-depends @@ -0,0 +1,13 @@ +WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )} +XBMC_PLATFORM_DIR=linux64 +. $WORKSPACE/tools/buildsteps/defaultenv + +#clean without depends for skipping depends build if possible +cd $WORKSPACE;git clean -xfd -e "tools/depends" + +if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ] +then + #clean up the rest too + cd $WORKSPACE;git clean -xfd + cd $WORKSPACE/tools/depends/;./bootstrap +fi diff --git a/tools/buildsteps/linux64/prepare-xbmc b/tools/buildsteps/linux64/prepare-xbmc new file mode 100755 index 0000000000..f71fcf6fef --- /dev/null +++ b/tools/buildsteps/linux64/prepare-xbmc @@ -0,0 +1,5 @@ +WORKSPACE=${WORKSPACE:-$( cd $(dirname $0)/../../.. ; pwd -P )} +XBMC_PLATFORM_DIR=linux64 +. $WORKSPACE/tools/buildsteps/defaultenv + +#nothing on linux diff --git a/tools/darwin/packaging/xbmc-atv2/mkdeb-xbmc-atv2.sh b/tools/darwin/packaging/xbmc-atv2/mkdeb-xbmc-atv2.sh index bfce090088..4883031909 100755 --- a/tools/darwin/packaging/xbmc-atv2/mkdeb-xbmc-atv2.sh +++ b/tools/darwin/packaging/xbmc-atv2/mkdeb-xbmc-atv2.sh @@ -45,7 +45,7 @@ fi PACKAGE=org.xbmc.xbmc-atv2 VERSION=13.0 -REVISION=0~alpha3 +REVISION=0~alpha4 ARCHIVE=${PACKAGE}_${VERSION}-${REVISION}_iphoneos-arm.deb echo Creating $PACKAGE package version $VERSION revision $REVISION diff --git a/tools/darwin/packaging/xbmc-ios/mkdeb-xbmc-ios.sh b/tools/darwin/packaging/xbmc-ios/mkdeb-xbmc-ios.sh index 57bbcb7f99..dfa446d7bf 100755 --- a/tools/darwin/packaging/xbmc-ios/mkdeb-xbmc-ios.sh +++ b/tools/darwin/packaging/xbmc-ios/mkdeb-xbmc-ios.sh @@ -46,7 +46,7 @@ fi PACKAGE=org.xbmc.xbmc-ios VERSION=13.0 -REVISION=0~alpha3 +REVISION=0~alpha4 ARCHIVE=${PACKAGE}_${VERSION}-${REVISION}_iphoneos-arm.deb echo Creating $PACKAGE package version $VERSION revision $REVISION diff --git a/tools/depends/native/zlib-native/Makefile b/tools/depends/native/zlib-native/Makefile index 31154eec93..125258fdb6 100644 --- a/tools/depends/native/zlib-native/Makefile +++ b/tools/depends/native/zlib-native/Makefile @@ -8,7 +8,6 @@ LIBNAME=zlib VERSION=1.2.7 SOURCE=$(LIBNAME)-$(VERSION) ARCHIVE=$(SOURCE).tar.gz -BASE_URL=http://zlib.net/ # configuration settings CONFIGURE= CC="$(CC_FOR_BUILD)" CFLAGS="$(BUILD_CFLAGS)" ./configure --prefix=$(PREFIX) diff --git a/tools/depends/target/Makefile b/tools/depends/target/Makefile index 17298f1d2b..dcf01b945a 100644 --- a/tools/depends/target/Makefile +++ b/tools/depends/target/Makefile @@ -12,7 +12,7 @@ DEPENDS = \ libogg libvorbis libflac libmad fribidi libmpeg2 \ libass libsamplerate \ libmodplug librtmp libxml2 yajl libmicrohttpd mysql libffi \ - python26 afpfs-ng libshairport \ + python26 afpfs-ng libshairplay \ libplist libcec libbluray boost tinyxml dummy-libxbmc \ libamplayer libssh taglib xbmc-pvr-addons libusb libnfs libmp3lame \ pythonmodule-pil @@ -33,6 +33,10 @@ ifeq ($(OS),osx) EXCLUDED_DEPENDS = libusb endif +ifeq ($(OS),android) + EXCLUDED_DEPENDS = libshairplay +endif + DEPENDS := $(filter-out $(EXCLUDED_DEPENDS),$(DEPENDS)) ZLIB= @@ -73,7 +77,6 @@ libmicrohttpd: openssl libgpg-error libgcrypt python26: expat gettext libxml2 sqlite3 openssl libffi libcdio: $(ICONV) afpfs-ng: libgcrypt $(ICONV) -libshairport: openssl libplist: libxml2 $(ZLIB) libbluray: $(ICONV) libxml2 libssh: openssl diff --git a/tools/depends/target/libamplayer/libamplayer/include/amports/vformat.h b/tools/depends/target/libamplayer/libamplayer/include/amports/vformat.h index 6ded0d47d2..ed0021963f 100644 --- a/tools/depends/target/libamplayer/libamplayer/include/amports/vformat.h +++ b/tools/depends/target/libamplayer/libamplayer/include/amports/vformat.h @@ -48,6 +48,7 @@ typedef enum { VIDEO_DEC_FORMAT_WMV3, VIDEO_DEC_FORMAT_WVC1, VIDEO_DEC_FORMAT_SW, + VIDEO_DEC_FORMAT_AVS, VIDEO_DEC_FORMAT_MAX } vdec_type_t; diff --git a/tools/depends/target/libamplayer/libamplayer/include/codec.h b/tools/depends/target/libamplayer/libamplayer/include/codec.h new file mode 100644 index 0000000000..187d4d5c82 --- /dev/null +++ b/tools/depends/target/libamplayer/libamplayer/include/codec.h @@ -0,0 +1,93 @@ +/** +* @file codec.h +* @brief Function prototypes of codec lib +* @author Zhang Chen <chen.zhang@amlogic.com> +* @version 1.0.0 +* @date 2011-02-24 +*/ +/* Copyright (C) 2007-2011, Amlogic Inc. +* All right reserved +* +*/ +#ifndef CODEC_CTRL_H_ +#define CODEC_CTRL_H_ + +#include <codec_type.h> +#include <codec_error.h> + + +int codec_init(codec_para_t *); +int codec_close(codec_para_t *); +void codec_audio_basic_init(void); +void codec_close_audio(codec_para_t *); +void codec_resume_audio(codec_para_t *, unsigned int); +int codec_reset(codec_para_t *); +int codec_init_sub(codec_para_t *); +int codec_open_sub_read(void); +int codec_close_sub(codec_para_t *); +int codec_close_sub_fd(CODEC_HANDLE); +int codec_reset_subtile(codec_para_t *pcodec); +int codec_poll_sub(codec_para_t *); +int codec_poll_sub_fd(CODEC_HANDLE, int); +int codec_get_sub_size(codec_para_t *); +int codec_get_sub_size_fd(CODEC_HANDLE); +int codec_read_sub_data(codec_para_t *, char *, unsigned int); +int codec_read_sub_data_fd(CODEC_HANDLE, char *, unsigned int); +int codec_write_sub_data(codec_para_t *, char *, unsigned int); +int codec_init_cntl(codec_para_t *); +int codec_close_cntl(codec_para_t *); +int codec_poll_cntl(codec_para_t *); +int codec_get_cntl_state(codec_para_t *); +int codec_set_cntl_mode(codec_para_t *, unsigned int); +int codec_set_cntl_avthresh(codec_para_t *, unsigned int); +int codec_set_cntl_syncthresh(codec_para_t *pcodec, unsigned int syncthresh); +int codec_reset_audio(codec_para_t *pcodec); +int codec_set_audio_pid(codec_para_t *pcodec); +int codec_set_sub_id(codec_para_t *pcodec); +int codec_set_sub_type(codec_para_t *pcodec); +int codec_audio_reinit(codec_para_t *pcodec); +int codec_set_dec_reset(codec_para_t *pcodec); + +int codec_write(codec_para_t *pcodec, void *buffer, int len); +int codec_checkin_pts(codec_para_t *pcodec, unsigned long pts); +int codec_get_vbuf_state(codec_para_t *, struct buf_status *); +int codec_get_abuf_state(codec_para_t *, struct buf_status *); +int codec_get_vdec_state(codec_para_t *, struct vdec_status *); +int codec_get_adec_state(codec_para_t *, struct adec_status *); + +int codec_pause(codec_para_t *); +int codec_resume(codec_para_t *); +int codec_audio_search(codec_para_t *p); +int codec_set_mute(codec_para_t *p, int mute); +int codec_get_volume_range(codec_para_t *, int *min, int *max); +int codec_set_volume(codec_para_t *, float val); +int codec_get_volume(codec_para_t *, float *val); +int codec_set_lrvolume(codec_para_t *, float lvol,float rvol); +int codec_get_lrvolume(codec_para_t *, float *lvol,float* rvol); +int codec_get_mutesta(codec_para_t *); +int codec_set_volume_balance(codec_para_t *, int); /*left£¨0-100)right*/ +int codec_swap_left_right(codec_para_t *); +int codec_left_mono(codec_para_t *p); +int codec_right_mono(codec_para_t *p); +int codec_stereo(codec_para_t *p); +int codec_get_soundtrack(codec_para_t *p,int* strack); +int codec_audio_automute(void *priv, int auto_mute); +int codec_audio_spectrum_switch(codec_para_t *p, int isStart, int interval); +int codec_audio_isready(codec_para_t *p); +int codec_audio_get_nb_frames(codec_para_t *p); +int codec_audio_set_audioinfo(codec_para_t *p); + +int codec_get_apts(codec_para_t *pcodec); +int codec_get_vpts(codec_para_t *pcodec); +int codec_get_pcrscr(codec_para_t *pcodec); +int codec_set_pcrscr(codec_para_t *pcodec, int val); +int codec_set_syncenable(codec_para_t *pcodec, int enable); +int codec_set_sync_audio_discont(codec_para_t *pcodec, int discontinue); +int codec_get_sync_audio_discont(codec_para_t *pcodec); +int codec_set_sync_video_discont(codec_para_t *pcodec, int discontinue); +int codec_get_sync_video_discont(codec_para_t *pcodec); + +int codec_get_sub_num(codec_para_t *pcodec); +int codec_get_sub_info(codec_para_t *pcodec, subtitle_info_t *sub_info); + +#endif diff --git a/tools/depends/target/libamplayer/libamplayer/include/codec_error.h b/tools/depends/target/libamplayer/libamplayer/include/codec_error.h new file mode 100644 index 0000000000..0d6df8fdf4 --- /dev/null +++ b/tools/depends/target/libamplayer/libamplayer/include/codec_error.h @@ -0,0 +1,37 @@ +/** +* @file codec_error.h +* @brief Codec error type definitions +* @author Zhang Chen <chen.zhang@amlogic.com> +* @version 1.0.0 +* @date 2011-02-24 +*/ +/* Copyright (C) 2007-2011, Amlogic Inc. +* All right reserved +* +*/ + +#ifndef CODEC_ERROR_H_ +#define CODEC_ERROR_H_ + +#define C_PAE (0x01000000) + +#define CODEC_ERROR_NONE ( 0) +#define CODEC_ERROR_INVAL (C_PAE | 1) +#define CODEC_ERROR_NOMEM (C_PAE | 2) +#define CODEC_ERROR_BUSY (C_PAE | 3) +#define CODEC_ERROR_IO (C_PAE | 4) +#define CODEC_ERROR_PARAMETER (C_PAE | 5) +#define CODEC_ERROR_AUDIO_TYPE_UNKNOW (C_PAE | 6) +#define CODEC_ERROR_VIDEO_TYPE_UNKNOW (C_PAE | 7) +#define CODEC_ERROR_STREAM_TYPE_UNKNOW (C_PAE | 8) +#define CODEC_ERROR_VDEC_TYPE_UNKNOW (C_PAE | 9) + +#define CODEC_ERROR_INIT_FAILED (C_PAE | 10) +#define CODEC_ERROR_SET_BUFSIZE_FAILED (C_PAE | 11) +#define CODEC_OPEN_HANDLE_FAILED (C_PAE | 12) + + + + +#endif + diff --git a/tools/depends/target/libamplayer/libamplayer/include/codec_msg.h b/tools/depends/target/libamplayer/libamplayer/include/codec_msg.h new file mode 100644 index 0000000000..f898af3756 --- /dev/null +++ b/tools/depends/target/libamplayer/libamplayer/include/codec_msg.h @@ -0,0 +1,19 @@ +/** +* @file codec_msg.h +* @brief Function prototype of codec error +* @author Zhang Chen <chen.zhang@amlogic.com> +* @version 1.0.0 +* @date 2011-02-24 +*/ +/* Copyright (C) 2007-2011, Amlogic Inc. +* All right reserved +* +*/ +#ifndef CODEC_MSG_H +#define CODEC_MSG_H + +const char * codec_error_msg(int error); +int system_error_to_codec_error(int error); +void print_error_msg(int error, int syserr, char *func, int line); + +#endif diff --git a/tools/depends/target/libamplayer/libamplayer/include/codec_type.h b/tools/depends/target/libamplayer/libamplayer/include/codec_type.h new file mode 100644 index 0000000000..5d61ca8722 --- /dev/null +++ b/tools/depends/target/libamplayer/libamplayer/include/codec_type.h @@ -0,0 +1,108 @@ +/** +* @file codec_type.h +* @brief Definitions of codec type and structures +* @author Zhang Chen <chen.zhang@amlogic.com> +* @version 1.0.0 +* @date 2011-02-24 +*/ +/* Copyright (C) 2007-2011, Amlogic Inc. +* All right reserved +* +*/ +#ifndef CODEC_TYPE_H_ +#define CODEC_TYPE_H_ + +#include "amports/amstream.h" +#include "amports/vformat.h" +#include "amports/aformat.h" + +typedef int CODEC_HANDLE; + +typedef enum { + STREAM_TYPE_UNKNOW, + STREAM_TYPE_ES_VIDEO, + STREAM_TYPE_ES_AUDIO, + STREAM_TYPE_ES_SUB, + STREAM_TYPE_PS, + STREAM_TYPE_TS, + STREAM_TYPE_RM, +} stream_type_t; + +typedef struct { + unsigned int format; ///< video format, such as H264, MPEG2... + unsigned int width; ///< video source width + unsigned int height; ///< video source height + unsigned int rate; ///< video source frame duration + unsigned int extra; ///< extra data information of video stream + unsigned int status; ///< status of video stream + unsigned int ratio; ///< aspect ratio of video source + void * param; ///< other parameters for video decoder + unsigned long long ratio64; ///< aspect ratio of video source +} dec_sysinfo_t; + +typedef struct { + int valid; ///< audio extradata valid(1) or invalid(0), set by dsp + int sample_rate; ///< audio stream sample rate + int channels; ///< audio stream channels + int bitrate; ///< audio stream bit rate + int codec_id; ///< codec format id + int block_align; ///< audio block align from ffmpeg + int extradata_size; ///< extra data size + char extradata[AUDIO_EXTRA_DATA_SIZE]; ///< extra data information for decoder +} audio_info_t; + +typedef struct { + CODEC_HANDLE handle; ///< codec device handler + CODEC_HANDLE cntl_handle; ///< video control device handler + CODEC_HANDLE sub_handle; ///< subtile device handler + stream_type_t stream_type; ///< stream type(es, ps, rm, ts) + unsigned int has_video:1; ///< stream has video(1) or not(0) + unsigned int has_audio:1; ///< stream has audio(1) or not(0) + unsigned int has_sub:1; ///< stream has subtitle(1) or not(0) + unsigned int noblock:1; ///< codec device is NONBLOCK(1) or not(0) + int video_type; ///< stream video type(H264, VC1...) + int audio_type; ///< stream audio type(PCM, WMA...) + int sub_type; ///< stream subtitle type(TXT, SSA...) + int video_pid; ///< stream video pid + int audio_pid; ///< stream audio pid + int sub_pid; ///< stream subtitle pid + int audio_channels; ///< stream audio channel number + int audio_samplerate; ///< steram audio sample rate + int vbuf_size; ///< video buffer size of codec device + int abuf_size; ///< audio buffer size of codec device + dec_sysinfo_t am_sysinfo; ///< system information for video + audio_info_t audio_info; ///< audio information pass to audiodsp + int packet_size; ///< data size per packet + int avsync_threshold; ///<for adec in ms> + void * adec_priv; ///<for adec> +} codec_para_t; + +typedef struct +{ + signed char id; + unsigned char width; + unsigned char height; + unsigned char type; +} subtitle_info_t; +#define MAX_SUB_NUM (32) + +#define IS_VALID_PID(t) (t>=0 && t<=0x1fff) +#define IS_VALID_STREAM(t) (t>0 && t<=0x1fff) +#define IS_VALID_ATYPE(t) (t>=0 && t<AFORMAT_MAX) +#define IS_VALID_VTYPE(t) (t>=0 && t<VFORMAT_MAX) + +//pass to arm audio decoder +typedef struct { + int sample_rate; ///< audio stream sample rate + int channels; ///< audio stream channels + int format; ///< codec format id + int handle; ///< codec device handler + int extradata_size; ///< extra data size + char extradata[AUDIO_EXTRA_DATA_SIZE]; +} arm_audio_info; + +//audio decoder type, default arc +#define AUDIO_ARC_DECODER 0 +#define AUDIO_ARM_DECODER 1 +#define AUDIO_FFMPEG_DECODER 2 +#endif diff --git a/tools/depends/target/libamplayer/libamplayer/include/player_type.h b/tools/depends/target/libamplayer/libamplayer/include/player_type.h index 2abd1940f3..37ad847573 100644 --- a/tools/depends/target/libamplayer/libamplayer/include/player_type.h +++ b/tools/depends/target/libamplayer/libamplayer/include/player_type.h @@ -5,7 +5,14 @@ #include <stream_format.h> #define MSG_SIZE 64 +#if defined(HAS_AMLPLAYER_CHAPTERS) +#define MAX_CHAPTERS 64 +#endif +#if defined(HAS_AMLPLAYER_VIDEO_STREAMS10) +#define MAX_VIDEO_STREAMS 10 +#else #define MAX_VIDEO_STREAMS 8 +#endif #define MAX_AUDIO_STREAMS 8 #define MAX_SUB_INTERNAL 8 #define MAX_SUB_EXTERNAL 24 @@ -64,8 +71,6 @@ typedef enum PLAYER_DIVX_AUTHORERR = 0x40001, PLAYER_DIVX_RENTAL_EXPIRED = 0x40002, PLAYER_DIVX_RENTAL_VIEW = 0x40003, - - }player_status; @@ -107,6 +112,7 @@ typedef struct typedef struct { + int index; int id; int channel; int sample_rate; @@ -114,10 +120,14 @@ typedef struct aformat_t aformat; int duration; audio_tag_info *audio_tag; +#if defined(HAS_AMLPLAYER_AUDIO_LANG) + char audio_language[4]; +#endif }maudio_info_t; typedef struct { + int index; char id; char internal_external; //0:internal_sub 1:external_sub unsigned short width; @@ -147,14 +157,33 @@ typedef struct int cur_sub_index; int seekable; int drm_check; +#if defined(HAS_AMLPLAYER_VIDEO_STREAMS10) + int t1; + int t2; +#endif +#if defined(HAS_AMLPLAYER_CHAPTERS) + int has_chapter; + int total_chapter_num; +#endif }mstream_info_t; +#if defined(HAS_AMLPLAYER_CHAPTERS) +typedef struct +{ + char *name; + int64_t seekto_ms; +} mchapter_info_t; +#endif + typedef struct { mstream_info_t stream_info; mvideo_info_t *video_info[MAX_VIDEO_STREAMS]; maudio_info_t *audio_info[MAX_AUDIO_STREAMS]; msub_info_t *sub_info[MAX_SUB_STREAMS]; +#if defined(HAS_AMLPLAYER_CHAPTERS) + mchapter_info_t *chapter_info[MAX_CHAPTERS]; +#endif }media_info_t; typedef struct player_info @@ -213,10 +242,25 @@ typedef enum PLAYER_EVENTS_ERROR, ///<ext1=error_code,ext2=message char * PLAYER_EVENTS_BUFFERING, ///<ext1=buffered=d,d={0-100},ext2=0, PLAYER_EVENTS_FILE_TYPE, ///<ext1=player_file_type_t*,ext2=0 + PLAYER_EVENTS_HTTP_WV, ///<(need use DRMExtractor),ext1=0, ext2=0 + PLAYER_EVENTS_HWBUF_DATA_SIZE_CHANGED, ///<(need use DRMExtractor),ext1=0, ext2=0 }player_events; typedef struct { + int vbufused; + int vbufsize; + int vdatasize; + int abufused; + int abufsize; + int adatasize; + int sbufused; + int sbufsize; + int sdatasize; +}hwbufstats_t; + +typedef struct +{ update_state_fun_t update_statue_callback; int update_interval; long callback_old_time; @@ -231,7 +275,7 @@ typedef struct int video_index; //video track, no assigned, please set to -1 int audio_index; //audio track, no assigned, please set to -1 int sub_index; //subtitle track, no assigned, please set to -1 - int t_pos; //start postion, use second as unit + float t_pos; //start postion, use second as unit int read_max_cnt; //read retry maxium counts, if exceed it, return error int avsync_threshold; //for adec av sync threshold in ms union @@ -265,7 +309,9 @@ typedef struct int is_type_parser; //is try to get file type int buffing_starttime_s; //for rest buffing_middle,buffering seconds data to start. int buffing_force_delay_s; + int lowbuffermode_flag; int reserved [56]; //reserved for furthur used,some one add more ,can del reserved num + int SessionID; }play_control_t; #endif diff --git a/tools/depends/target/libgcrypt/01-inline-gcc.patch b/tools/depends/target/libgcrypt/01-inline-gcc.patch new file mode 100644 index 0000000000..3a0fe015ac --- /dev/null +++ b/tools/depends/target/libgcrypt/01-inline-gcc.patch @@ -0,0 +1,42 @@ +From 5abc06114e91beca0177331e1c79815f5fb6d7be Mon Sep 17 00:00:00 2001 +From: Werner Koch <wk@gnupg.org> +Date: Thu, 8 Nov 2012 15:38:44 +0100 +Subject: [PATCH] Fix extern inline use for gcc > 4.3 in c99 mode + +* mpi/mpi-inline.h [!G10_MPI_INLINE_DECL]: Take care of changed extern +inline semantics in gcc. +-- + +I am not use how this will work out with non-gcc. However, we had no +problems in the past and thus this change is the least invasive for +non-gcc compilers. + +GnuPG-bug-id: 1406, 1435 +--- + mpi/mpi-inline.h | 9 ++++++++- + 1 files changed, 8 insertions(+), 1 deletions(-) + +diff --git a/mpi/mpi-inline.h b/mpi/mpi-inline.h +index 88d9f56..94e2aec 100644 +--- a/mpi/mpi-inline.h ++++ b/mpi/mpi-inline.h +@@ -28,8 +28,15 @@ + #ifndef G10_MPI_INLINE_H + #define G10_MPI_INLINE_H + ++/* Starting with gcc 4.3 "extern inline" conforms in c99 mode to the ++ c99 semantics. To keep the useful old semantics we use an ++ attribute. */ + #ifndef G10_MPI_INLINE_DECL +-#define G10_MPI_INLINE_DECL extern __inline__ ++# ifdef __GNUC_STDC_INLINE__ ++# define G10_MPI_INLINE_DECL extern inline __attribute__ ((__gnu_inline__)) ++# else ++# define G10_MPI_INLINE_DECL extern __inline__ ++# endif + #endif + + G10_MPI_INLINE_DECL mpi_limb_t +-- +1.7.2.5 + diff --git a/tools/depends/target/libgcrypt/01-static-mpi_mpi-internal.patch b/tools/depends/target/libgcrypt/01-static-mpi_mpi-internal.patch deleted file mode 100644 index 5a1f60f8d6..0000000000 --- a/tools/depends/target/libgcrypt/01-static-mpi_mpi-internal.patch +++ /dev/null @@ -1,53 +0,0 @@ -*** mpi/mpi-internal.h Sun May 6 17:39:56 2012 ---- mpi/mpi-internal_new.h Sun May 6 17:45:59 2012 -*************** void _gcry_mpi_lshift_limbs( gcry_mpi_t -*** 183,206 **** - - - /*-- mpih-add.c --*/ -! mpi_limb_t _gcry_mpih_add_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, -! mpi_size_t s1_size, mpi_limb_t s2_limb ); - mpi_limb_t _gcry_mpih_add_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, -! mpi_ptr_t s2_ptr, mpi_size_t size); -! mpi_limb_t _gcry_mpih_add(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, -! mpi_ptr_t s2_ptr, mpi_size_t s2_size); -! - /*-- mpih-sub.c --*/ -! mpi_limb_t _gcry_mpih_sub_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, -! mpi_size_t s1_size, mpi_limb_t s2_limb ); - mpi_limb_t _gcry_mpih_sub_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, -! mpi_ptr_t s2_ptr, mpi_size_t size); -! mpi_limb_t _gcry_mpih_sub(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, -! mpi_ptr_t s2_ptr, mpi_size_t s2_size); -! - /*-- mpih-cmp.c --*/ -! int _gcry_mpih_cmp( mpi_ptr_t op1_ptr, mpi_ptr_t op2_ptr, mpi_size_t size ); -! - /*-- mpih-mul.c --*/ - - struct karatsuba_ctx { ---- 183,206 ---- - - - /*-- mpih-add.c --*/ -! static mpi_limb_t _gcry_mpih_add_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, -! mpi_size_t s1_size, mpi_limb_t s2_limb ); - mpi_limb_t _gcry_mpih_add_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, -! mpi_ptr_t s2_ptr, mpi_size_t size); -! static mpi_limb_t _gcry_mpih_add(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, -! mpi_ptr_t s2_ptr, mpi_size_t s2_size); -! - /*-- mpih-sub.c --*/ -! static mpi_limb_t _gcry_mpih_sub_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, -! mpi_size_t s1_size, mpi_limb_t s2_limb ); - mpi_limb_t _gcry_mpih_sub_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, -! mpi_ptr_t s2_ptr, mpi_size_t size); -! static mpi_limb_t _gcry_mpih_sub(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, -! mpi_ptr_t s2_ptr, mpi_size_t s2_size); -! - /*-- mpih-cmp.c --*/ -! static int _gcry_mpih_cmp( mpi_ptr_t op1_ptr, mpi_ptr_t op2_ptr, mpi_size_t size ); -! - /*-- mpih-mul.c --*/ - - struct karatsuba_ctx { diff --git a/tools/depends/target/libgcrypt/Makefile b/tools/depends/target/libgcrypt/Makefile index e4e121fb60..3e21bd5f7d 100644 --- a/tools/depends/target/libgcrypt/Makefile +++ b/tools/depends/target/libgcrypt/Makefile @@ -27,7 +27,7 @@ $(TARBALLS_LOCATION)/$(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-static-mpi_mpi-internal.patch + cd $(PLATFORM); patch -p1 < ../01-inline-gcc.patch cd $(PLATFORM); patch -p0 < ../02-armasm.patch cd $(PLATFORM); patch -p0 < ../03-gcrypt-android-select.patch cd $(PLATFORM); patch -p0 < ../04-oflagmunging.patch diff --git a/tools/depends/target/libshairplay/Makefile b/tools/depends/target/libshairplay/Makefile new file mode 100644 index 0000000000..7665015564 --- /dev/null +++ b/tools/depends/target/libshairplay/Makefile @@ -0,0 +1,39 @@ +include ../../Makefile.include +DEPS= ../../Makefile.include + +# lib name, version +LIBNAME=shairplay +VERSION=139d5ef +SOURCE=$(LIBNAME)-$(VERSION) +ARCHIVE=$(SOURCE).tar.bz2 + +# configuration settings +CONFIGURE=./configure --prefix=$(PREFIX) + + +LIBDYLIB=$(PLATFORM)/src/lib/.libs/libshairplay.so.0.0.0 + +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); $(AUTORECONF) -vif + cd $(PLATFORM); $(CONFIGURE) + +$(LIBDYLIB): $(PLATFORM) + $(MAKE) -j 1 -C $(PLATFORM) + +.installed-$(PLATFORM): $(LIBDYLIB) + $(MAKE) -C $(PLATFORM) install + touch $@ + +clean: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + +distclean:: + rm -rf $(PLATFORM) .installed-$(PLATFORM) + diff --git a/tools/depends/target/libshairport/001_add_ao.patch b/tools/depends/target/libshairport/001_add_ao.patch deleted file mode 100644 index 995f7b78ee..0000000000 --- a/tools/depends/target/libshairport/001_add_ao.patch +++ /dev/null @@ -1,270 +0,0 @@ -diff -uP libshairport-1.2.0.20310_lib/src/ao.h ../../../../../libshairport-1.2.0.20310_lib/src/ao.h ---- src/ao.h 1970-01-01 01:00:00.000000000 +0100 -+++ src/ao.h 2011-09-25 20:36:36.000000000 +0200 -@@ -0,0 +1,156 @@ -+/* -+ * -+ * ao.h -+ * -+ * Original Copyright (C) Aaron Holtzman - May 1999 -+ * Modifications Copyright (C) Stan Seibert - July 2000, July 2001 -+ * More Modifications Copyright (C) Jack Moffitt - October 2000 -+ * -+ * This file is part of libao, a cross-platform audio outputlibrary. See -+ * README for a history of this source code. -+ * -+ * libao 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. -+ * -+ * libao 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 GNU Make; see the file COPYING. If not, write to -+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. -+ * -+ */ -+#ifndef __AO_H__ -+#define __AO_H__ -+ -+#ifdef __cplusplus -+extern "C" -+{ -+#endif /* __cplusplus */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <stdint.h> -+#include <errno.h> -+ -+/* --- Constants ---*/ -+ -+#define AO_TYPE_LIVE 1 -+#define AO_TYPE_FILE 2 -+ -+ -+#define AO_ENODRIVER 1 -+#define AO_ENOTFILE 2 -+#define AO_ENOTLIVE 3 -+#define AO_EBADOPTION 4 -+#define AO_EOPENDEVICE 5 -+#define AO_EOPENFILE 6 -+#define AO_EFILEEXISTS 7 -+#define AO_EBADFORMAT 8 -+ -+#define AO_EFAIL 100 -+ -+ -+#define AO_FMT_LITTLE 1 -+#define AO_FMT_BIG 2 -+#define AO_FMT_NATIVE 4 -+ -+/* --- Structures --- */ -+ -+typedef struct ao_info { -+ int type; /* live output or file output? */ -+ char *name; /* full name of driver */ -+ char *short_name; /* short name of driver */ -+ char *author; /* driver author */ -+ char *comment; /* driver comment */ -+ int preferred_byte_format; -+ int priority; -+ char **options; -+ int option_count; -+} ao_info; -+ -+typedef struct ao_functions ao_functions; -+typedef struct ao_device ao_device; -+ -+typedef struct ao_sample_format { -+ int bits; /* bits per sample */ -+ int rate; /* samples per second (in a single channel) */ -+ int channels; /* number of audio channels */ -+ int byte_format; /* Byte ordering in sample, see constants below */ -+ char *matrix; /* input channel location/ordering */ -+} ao_sample_format; -+ -+typedef struct ao_option { -+ char *key; -+ char *value; -+ struct ao_option *next; -+} ao_option; -+ -+#if defined(AO_BUILDING_LIBAO) -+#include "ao_private.h" -+#endif -+ -+/* --- Functions --- */ -+ -+/* library setup/teardown */ -+void ao_initialize(void); -+void ao_shutdown(void); -+ -+/* device setup/playback/teardown */ -+int ao_append_global_option(const char *key, -+ const char *value); -+int ao_append_option(ao_option **options, -+ const char *key, -+ const char *value); -+void ao_free_options(ao_option *options); -+ -+char* ao_get_option(ao_option *options, const char* key); -+ -+ao_device* ao_open_live(int driver_id, -+ ao_sample_format *format, -+ ao_option *option); -+ao_device* ao_open_file(int driver_id, -+ const char *filename, -+ int overwrite, -+ ao_sample_format *format, -+ ao_option *option); -+ -+int ao_play(ao_device *device, -+ char *output_samples, -+ uint32_t num_bytes); -+int ao_close(ao_device *device); -+ -+/* driver information */ -+int ao_driver_id(const char *short_name); -+int ao_default_driver_id(void); -+ao_info *ao_driver_info(int driver_id); -+ao_info **ao_driver_info_list(int *driver_count); -+char *ao_file_extension(int driver_id); -+ -+/* miscellaneous */ -+int ao_is_big_endian(void); -+ -+ -+#ifdef __cplusplus -+} -+#endif /* __cplusplus */ -+ -+#endif /* __AO_H__ */ -+ -+extern struct AudioOutput g_ao; -+struct AudioOutput -+ { -+ void (*ao_initialize)(void); -+ int (*ao_play)(ao_device *, char *, uint32_t); -+ int (*ao_default_driver_id)(void); -+ ao_device* (*ao_open_live)( int, ao_sample_format *, ao_option *); -+ int (*ao_close)(ao_device *); -+ /* -- Device Setup/Playback/Teardown -- */ -+ int (*ao_append_option)(ao_option **, const char *, const char *); -+ void (*ao_free_options)(ao_option *); -+ char* (*ao_get_option)(ao_option *, const char* ); -+ }; -diff -uP libshairport-1.2.0.20310_lib/src/hairtunes.c ../../../../../libshairport-1.2.0.20310_lib/src/hairtunes.c ---- src/hairtunes.c 2011-09-23 21:55:48.000000000 +0200 -+++ src/hairtunes.c 2011-09-25 20:37:49.000000000 +0200 -@@ -25,7 +25,7 @@ - */ - - #define XBMC --//#defined HAS_AO -+#define HAS_AO - - #include <stdio.h> - #include <stdlib.h> -@@ -45,7 +45,7 @@ - #include <sys/signal.h> - #include <fcntl.h> - #ifdef HAS_AO --#include <ao/ao.h> -+#include "ao.h" - #endif - - #ifdef FANCY_RESAMPLING -@@ -881,7 +881,7 @@ - } - #ifdef HAS_AO - } else { -- ao_play(dev, (char *)outbuf, play_samples*4); -+ g_ao.ao_play(dev, (char *)outbuf, play_samples*4); - #endif - } - } -@@ -906,7 +906,7 @@ - ao_device *dev; - - void* init_ao() { -- ao_initialize(); -+ g_ao.ao_initialize(); - - int driver; - #ifndef XBMC -@@ -921,7 +921,7 @@ - #endif - { - // otherwise choose the default -- driver = ao_default_driver_id(); -+ driver = g_ao.ao_default_driver_id(); - } - - ao_sample_format fmt; -@@ -944,9 +944,9 @@ - } - #endif - -- ao_append_option(&ao_opts, "name", "Streaming..."); -+ g_ao.ao_append_option(&ao_opts, "name", "Streaming..."); - -- dev = ao_open_live(driver, &fmt, ao_opts); -+ dev = g_ao.ao_open_live(driver, &fmt, ao_opts); - if (dev == NULL) { - die("Could not open ao device"); - } -@@ -985,7 +985,7 @@ - audio_running = 0; - pthread_join(audio_thread, NULL); - #ifdef HAS_AO -- ao_close(dev); -+ g_ao.ao_close(dev); - #endif - } - -diff -uP libshairport-1.2.0.20310_lib/src/shairport.c ../../../../../libshairport-1.2.0.20310_lib/src/shairport.c ---- src/shairport.c 2011-08-21 01:57:56.000000000 +0200 -+++ src/shairport.c 2011-09-25 20:44:40.000000000 +0200 -@@ -92,6 +92,14 @@ - static char tPassword[56] = ""; - static char tHWID[HWID_SIZE] = {0,51,52,53,54,55}; - -+#ifdef XBMC -+struct AudioOutput g_ao; -+void shairport_set_ao(struct AudioOutput *ao) -+{ -+ g_ao=*ao; -+} -+#endif -+ - #ifndef XBMC - int main(int argc, char **argv) - #else -diff -uP libshairport-1.2.0.20310_lib/src/shairport.h ../../../../../libshairport-1.2.0.20310_lib/src/shairport.h ---- src/shairport.h 2011-08-21 01:58:11.000000000 +0200 -+++ src/shairport.h 2011-09-25 20:36:43.000000000 +0200 -@@ -11,6 +11,7 @@ - #include <regex.h> - #include <sys/types.h> - #include <regex.h> -+#include "ao.h" - - - #define HWID_SIZE 6 -@@ -62,9 +63,11 @@ - void shairport_exit(void); - int shairport_loop(void); - int shairport_is_running(void); -+void shairport_set_ao(struct AudioOutput *ao); - - #ifdef __cplusplus - } - #endif /* __cplusplus */ - - #endif -+ diff --git a/tools/depends/target/libshairport/002_fix_install_header.patch b/tools/depends/target/libshairport/002_fix_install_header.patch deleted file mode 100644 index 495b97346c..0000000000 --- a/tools/depends/target/libshairport/002_fix_install_header.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- src/Makefile.am.old 2011-09-23 23:14:39.000000000 +0200 -+++ src/Makefile.am 2011-09-25 21:38:08.000000000 +0200 -@@ -1,7 +1,7 @@ - lib_LTLIBRARIES=libshairport.la - --library_includedir=$(includedir) --library_include_HEADERS = shairport.h -+library_includedir=$(includedir)/shairport -+library_include_HEADERS = shairport.h ao.h socketlib.h - - libshairport_la_SOURCES=shairport.c hairtunes.c socketlib.c alac.c - libshairport_la_LDFLAGS=-dynamiclib diff --git a/tools/depends/target/libshairport/003_fix_deadlock.patch b/tools/depends/target/libshairport/003_fix_deadlock.patch deleted file mode 100644 index c05970e138..0000000000 --- a/tools/depends/target/libshairport/003_fix_deadlock.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- src/hairtunes.c.orig 2011-09-25 21:58:08.000000000 +0200 -+++ src/hairtunes.c 2011-09-25 21:58:12.000000000 +0200 -@@ -991,6 +991,7 @@ - - void hairtunes_cleanup(void) - { -+ pthread_cond_signal(&ab_buffer_ready); - clean_output(); - clean_rtp(); - clean_buffer(); diff --git a/tools/depends/target/libshairport/004_fix_bad_access.patch b/tools/depends/target/libshairport/004_fix_bad_access.patch deleted file mode 100644 index 1976904c4d..0000000000 --- a/tools/depends/target/libshairport/004_fix_bad_access.patch +++ /dev/null @@ -1,22 +0,0 @@ ---- src/hairtunes.c.orig 2011-09-25 23:26:56.000000000 +0200 -+++ src/hairtunes.c 2011-09-25 23:29:27.000000000 +0200 -@@ -89,7 +89,6 @@ - // maximal resampling shift - conservative - #define OUTFRAME_BYTES (4*(frame_size+3)) - -- - alac_file *decoder_info; - - #ifdef FANCY_RESAMPLING -@@ -849,6 +848,11 @@ - inbuf = buffer_get_frame(); - } while (!inbuf && audio_running); - -+ if(!audio_running) -+ { -+ return 0; //don't access inbuf if audio stopped -+ } -+ - #ifdef FANCY_RESAMPLING - if (fancy_resampling) { - int i; diff --git a/tools/depends/target/libshairport/005_fix_shutdown.patch b/tools/depends/target/libshairport/005_fix_shutdown.patch deleted file mode 100644 index 32bd282719..0000000000 --- a/tools/depends/target/libshairport/005_fix_shutdown.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- src/shairport.c 2011-09-25 23:58:06.000000000 +0200 -+++ src/shairport.c.new 2011-09-25 23:57:54.000000000 +0200 -@@ -368,6 +368,7 @@ - void shairport_exit(void) - { - m_running = 0; -+ close(tServerSock); - } - - int shairport_is_running(void) diff --git a/tools/depends/target/libshairport/006_no_printf.patch b/tools/depends/target/libshairport/006_no_printf.patch deleted file mode 100644 index eb69d42b74..0000000000 --- a/tools/depends/target/libshairport/006_no_printf.patch +++ /dev/null @@ -1,843 +0,0 @@ ---- src/alac.c 2011-08-21 00:06:21.000000000 +0200 -+++ src/alac.c 2011-10-01 04:12:09.000000000 +0200 -@@ -804,7 +804,7 @@ - } - else - { -- fprintf(stderr, "FIXME: unhandled predicition type: %i\n", prediction_type); -+ xprintf("FIXME: unhandled predicition type: %i\n", prediction_type); - /* i think the only other prediction type (or perhaps this is just a - * boolean?) runs adaptive fir twice.. like: - * predictor_decompress_fir_adapt(predictor_error, tempout, ...) -@@ -885,7 +885,7 @@ - } - case 20: - case 32: -- fprintf(stderr, "FIXME: unimplemented sample size %i\n", alac->setinfo_sample_size); -+ xprintf("FIXME: unimplemented sample size %i\n", alac->setinfo_sample_size); - break; - default: - break; -@@ -1004,7 +1004,7 @@ - } - else - { /* see mono case */ -- fprintf(stderr, "FIXME: unhandled predicition type: %i\n", prediction_type_a); -+ xprintf("FIXME: unhandled predicition type: %i\n", prediction_type_a); - } - - /* channel 2 */ -@@ -1029,7 +1029,7 @@ - } - else - { -- fprintf(stderr, "FIXME: unhandled predicition type: %i\n", prediction_type_b); -+ xprintf("FIXME: unhandled predicition type: %i\n", prediction_type_b); - } - } - else -@@ -1106,7 +1106,7 @@ - } - case 20: - case 32: -- fprintf(stderr, "FIXME: unimplemented sample size %i\n", alac->setinfo_sample_size); -+ xprintf("FIXME: unimplemented sample size %i\n", alac->setinfo_sample_size); - break; - default: - break; ---- src/hairtunes.c 2011-10-01 17:45:08.000000000 +0200 -+++ src/hairtunes.c 2011-10-01 17:42:07.000000000 +0200 -@@ -121,8 +121,8 @@ - pthread_cond_t ab_buffer_ready; - - static void die(char *why) { -- fprintf(stderr, "FATAL: %s\n", why); -- exit(1); -+ xprintf("FATAL: %s\n", why); -+ //exit(1); - } - - static int hex2bin(unsigned char *buf, char *hex) { -@@ -245,13 +245,13 @@ - continue; - } - if (!strcmp(line, "exit\n")) { -- exit(0); -+ ;//exit(0); - } - if (!strcmp(line, "flush\n")) { - hairtunes_flush(); - } - } -- fprintf(stderr, "bye!\n"); -+ xprintf("bye!\n"); - fflush(stderr); - #endif - -@@ -262,7 +262,7 @@ - { - assert(f<=0); - if (debug) -- fprintf(stderr, "VOL: %lf\n", f); -+ xprintf("VOL: %lf\n", f); - volume = pow(10.0,0.05*f); - fix_volume = 65536.0 * volume; - } -@@ -273,7 +273,7 @@ - ab_resync(); - pthread_mutex_unlock(&ab_mutex); - if (debug) -- fprintf(stderr, "FLUSH\n"); -+ xprintf("FLUSH\n"); - } - - #ifdef HAIRTUNES_STANDALONE -@@ -423,7 +423,7 @@ - } else if (seq_order(ab_read, seqno)) { // late but not yet played - abuf = audio_buffer + BUFIDX(seqno); - } else { // too late. -- fprintf(stderr, "\nlate packet %04X (%04X:%04X)\n", seqno, ab_read, ab_write); -+ xprintf("\nlate packet %04X (%04X:%04X)\n", seqno, ab_read, ab_write); - } - buf_fill = ab_write - ab_read; - pthread_mutex_unlock(&ab_mutex); -@@ -520,7 +520,7 @@ - if (seq_order(last, first)) - return; - -- fprintf(stderr, "requesting resend on %d packets (port %d)\n", last-first+1, controlport); -+ xprintf("requesting resend on %d packets (port %d)\n", last-first+1, controlport); - - char req[8]; // *not* a standard RTCP NACK - req[0] = 0x80; -@@ -604,8 +604,8 @@ - port += 3; - } - -- printf("port: %d\n", port); // let our handler know where we end up listening -- printf("cport: %d\n", port+1); -+ xprintf("port: %d\n", port); // let our handler know where we end up listening -+ xprintf("cport: %d\n", port+1); - - rtp_sockets[0] = sock; - rtp_sockets[1] = csock; -@@ -708,7 +708,7 @@ - bf_est_drift = biquad_filt(&bf_drift_lpf, CONTROL_B*(bf_est_err*CONTROL_A + err_deriv) + bf_est_drift); - - if (debug) -- fprintf(stderr, "bf %d err %f drift %f desiring %f ed %f estd %f\r", fill, bf_est_err, bf_est_drift, desired_fill, err_deriv, err_deriv + CONTROL_A*bf_est_err); -+ xprintf("bf %d err %f drift %f desiring %f ed %f estd %f\r", fill, bf_est_err, bf_est_drift, desired_fill, err_deriv, err_deriv + CONTROL_A*bf_est_err); - bf_playback_rate = 1.0 + CONTROL_A*bf_est_err + bf_est_drift; - - bf_last_err = bf_est_err; -@@ -724,7 +724,7 @@ - buf_fill = ab_write - ab_read; - if (buf_fill < 1 || !ab_synced || ab_buffering) { // init or underrun. stop and wait - if (ab_synced) -- fprintf(stderr, "\nunderrun\n"); -+ xprintf("\nunderrun\n"); - - ab_buffering = 1; - pthread_cond_wait(&ab_buffer_ready, &ab_mutex); -@@ -736,7 +736,7 @@ - return 0; - } - if (buf_fill >= BUFFER_FRAMES) { // overrunning! uh-oh. restart at a sane distance -- fprintf(stderr, "\noverrun.\n"); -+ xprintf("\noverrun.\n"); - ab_read = ab_write - START_FILL; - } - read = ab_read; -@@ -748,7 +748,7 @@ - - volatile abuf_t *curframe = audio_buffer + BUFIDX(read); - if (!curframe->ready) { -- fprintf(stderr, "\nmissing frame.\n"); -+ xprintf("\nmissing frame.\n"); - memset(curframe->data, 0, FRAME_BYTES); - } - curframe->ready = 0; -@@ -775,13 +775,13 @@ - if (stuff) { - if (stuff==1) { - if (debug) -- fprintf(stderr, "+++++++++\n"); -+ xprintf("+++++++++\n"); - // interpolate one sample - *outptr++ = dithered_vol(((long)inptr[-2] + (long)inptr[0]) >> 1); - *outptr++ = dithered_vol(((long)inptr[-1] + (long)inptr[1]) >> 1); - } else if (stuff==-1) { - if (debug) -- fprintf(stderr, "---------\n"); -+ xprintf("---------\n"); - inptr++; - inptr++; - } ---- src/shairport.c 2011-10-01 17:45:08.000000000 +0200 -+++ src/shairport.c 2011-10-01 17:41:04.000000000 +0200 -@@ -31,6 +31,27 @@ - #include "shairport.h" - #include "hairtunes.h" - -+static struct printfPtr g_printf={NULL}; -+ -+int xprintf(const char *format, ...) -+{ -+ char dbg[2048]; -+ va_list args; -+ va_start(args, format); -+ vsnprintf(dbg, sizeof(dbg), format, args); -+ va_end(args); -+ if(g_printf.extprintf) -+ { -+ g_printf.extprintf(dbg, sizeof(dbg)); -+ } -+ else -+ { -+ printf(dbg); -+ } -+ -+ return 1; -+} -+ - #ifndef TRUE - #define TRUE (-1) - #endif -@@ -98,6 +119,11 @@ - { - g_ao=*ao; - } -+ -+void shairport_set_printf(struct printfPtr *funcPtr) -+{ -+ g_printf = *funcPtr; -+} - #endif - - #ifndef XBMC -@@ -106,7 +132,7 @@ - int shairport_main(int argc, char **argv) - #endif - { -- printf("initializing shairport\n"); -+ xprintf("initializing shairport\n",NULL); - char tHWID_Hex[HWID_SIZE * 2 + 1]; - char tKnownHwid[32]; - -@@ -185,22 +211,22 @@ - } - else if(!strcmp(arg, "-h") || !strcmp(arg, "--help")) - { -- slog(LOG_INFO, "ShairPort version 0.05 C port - Airport Express emulator\n"); -- slog(LOG_INFO, "Usage:\nshairport [OPTION...]\n\nOptions:\n"); -- slog(LOG_INFO, " -a, --apname=AirPort Sets Airport name\n"); -- slog(LOG_INFO, " -p, --password=secret Sets Password (not working)\n"); -- slog(LOG_INFO, " -o, --server_port=5000 Sets Port for Avahi/dns-sd\n"); -- slog(LOG_INFO, " -b, --buffer=282 Sets Number of frames to buffer before beginning playback\n"); -- slog(LOG_INFO, " -d Daemon mode\n"); -- slog(LOG_INFO, " -q, --quiet Supresses all output.\n"); -- slog(LOG_INFO, " -v,-v2,-v3,-vv Various debugging levels\n"); -- slog(LOG_INFO, "\n"); -+ xprintf("ShairPort version 0.05 C port - Airport Express emulator\n"); -+ xprintf("Usage:\nshairport [OPTION...]\n\nOptions:\n"); -+ xprintf(" -a, --apname=AirPort Sets Airport name\n"); -+ xprintf(" -p, --password=secret Sets Password (not working)\n"); -+ xprintf(" -o, --server_port=5000 Sets Port for Avahi/dns-sd\n"); -+ xprintf(" -b, --buffer=282 Sets Number of frames to buffer before beginning playback\n"); -+ xprintf(" -d Daemon mode\n"); -+ xprintf(" -q, --quiet Supresses all output.\n"); -+ xprintf(" -v,-v2,-v3,-vv Various debugging levels\n"); -+ xprintf("\n"); - return 0; - } - } - - if ( buffer_start_fill < 30 || buffer_start_fill > BUFFER_FRAMES ) { -- fprintf(stderr, "buffer value must be > 30 and < %d\n", BUFFER_FRAMES); -+ xprintf("buffer value must be > 30 and < %d\n", BUFFER_FRAMES); - return(0); - } - -@@ -209,11 +235,11 @@ - int tPid = fork(); - if(tPid < 0) - { -- exit(1); // Error on fork -+ //exit(1); // Error on fork - } - else if(tPid > 0) - { -- exit(0); -+ //exit(0); - } - else - { -@@ -254,10 +280,10 @@ - sscanf(tHWID_Hex, "%02X%02X%02X%02X%02X%02X", &tHWID[0], &tHWID[1], &tHWID[2], &tHWID[3], &tHWID[4], &tHWID[5]); - } - -- slog(LOG_INFO, "LogLevel: %d\n", kCurrentLogLevel); -- slog(LOG_INFO, "AirName: %s\n", tServerName); -- slog(LOG_INFO, "HWID: %.*s\n", HWID_SIZE, tHWID+1); -- slog(LOG_INFO, "HWID_Hex(%d): %s\n", strlen(tHWID_Hex), tHWID_Hex); -+ xprintf("LogLevel: %d\n", kCurrentLogLevel); -+ xprintf("AirName: %s\n", tServerName); -+ xprintf("HWID: %.*s\n", HWID_SIZE, tHWID+1); -+ xprintf("HWID_Hex(%d): %s\n", strlen(tHWID_Hex), tHWID_Hex); - - if(tSimLevel >= 1) - { -@@ -271,12 +297,12 @@ - #ifndef XBMC - startAvahi(tHWID_Hex, tServerName, tPort); - #endif -- slog(LOG_DEBUG_V, "Starting connection server: specified server port: %d\n", tPort); -+ xprintf("Starting connection server: specified server port: %d\n", tPort); - tServerSock = setupListenServer(&tAddrInfo, tPort); - if(tServerSock < 0) - { - freeaddrinfo(tAddrInfo); -- slog(LOG_INFO, "Error setting up server socket on port %d, try specifying a different port\n", tPort); -+ xprintf("Error setting up server socket on port %d, try specifying a different port\n", tPort); - return 0; - } - -@@ -303,7 +329,7 @@ - - int readsock; - -- slog(LOG_DEBUG_V, "Waiting for clients to connect\n"); -+ xprintf("Waiting for clients to connect\n"); - - while(m_running) - { -@@ -335,7 +361,7 @@ - { - freeaddrinfo(tAddrInfo); - tAddrInfo = NULL; -- slog(LOG_DEBUG, "...Accepted Client Connection..\n"); -+ xprintf("...Accepted Client Connection..\n"); - close(tServerSock); - handleClient(tClientSock, tPassword, tHWID); - //close(tClientSock); -@@ -343,11 +369,11 @@ - } - else - { -- slog(LOG_DEBUG_VV, "Child now busy handling new client\n"); -+ xprintf("Child now busy handling new client\n"); - close(tClientSock); - } - #else -- slog(LOG_DEBUG, "...Accepted Client Connection..\n"); -+ xprintf("...Accepted Client Connection..\n"); - handleClient(tClientSock, tPassword, tHWID); - #endif - } -@@ -357,7 +383,7 @@ - } - } - -- slog(LOG_DEBUG_VV, "Finished\n"); -+ xprintf("Finished\n"); - if(tAddrInfo != NULL) - { - freeaddrinfo(tAddrInfo); -@@ -416,7 +442,7 @@ - - void handleClient(int pSock, char *pPassword, char *pHWADDR) - { -- slog(LOG_DEBUG_VV, "In Handle Client\n"); -+ xprintf("In Handle Client\n"); - fflush(stdout); - - socklen_t len; -@@ -435,7 +461,7 @@ - - // deal with both IPv4 and IPv6: - if (addr.ss_family == AF_INET) { -- slog(LOG_DEBUG_V, "Constructing ipv4 address\n"); -+ xprintf("Constructing ipv4 address\n"); - struct sockaddr_in *s = (struct sockaddr_in *)&addr; - port = ntohs(s->sin_port); - inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof ipstr); -@@ -455,20 +481,20 @@ - if(memcmp(&addr.bin[0], "\x00\x00\x00\x00" "\x00\x00\x00\x00" "\x00\x00\xff\xff", 12) == 0) - { - // its ipv4... -- slog(LOG_DEBUG_V, "Constructing ipv4 from ipv6 address\n"); -+ xprintf("Constructing ipv4 from ipv6 address\n"); - memcpy(ipbin, &addr.bin[12], 4); - ipbinlen = 4; - } - else - { -- slog(LOG_DEBUG_V, "Constructing ipv6 address\n"); -+ xprintf("Constructing ipv6 address\n"); - memcpy(ipbin, &s->sin6_addr, 16); - ipbinlen = 16; - } - } - -- slog(LOG_DEBUG_V, "Peer IP address: %s\n", ipstr); -- slog(LOG_DEBUG_V, "Peer port : %d\n", port); -+ xprintf("Peer IP address: %s\n", ipstr); -+ xprintf("Peer port : %d\n", port); - - int tMoreDataNeeded = 1; - struct keyring tKeys; -@@ -489,16 +515,16 @@ - tError = readDataFromClient(pSock, &(tConn.recv)); - if(!tError && strlen(tConn.recv.data) > 0) - { -- slog(LOG_DEBUG_VV, "Finished Reading some data from client\n"); -+ xprintf("Finished Reading some data from client\n"); - // parse client request - tMoreDataNeeded = parseMessage(&tConn, ipbin, ipbinlen, pHWADDR); - if(1 == tMoreDataNeeded) - { -- slog(LOG_DEBUG_VV, "\n\nNeed to read more data\n"); -+ xprintf("\n\nNeed to read more data\n"); - } - else if(-1 == tMoreDataNeeded) // Forked process down below ended. - { -- slog(LOG_DEBUG_V, "Forked Process ended...cleaning up\n"); -+ xprintf("Forked Process ended...cleaning up\n"); - cleanup(&tConn); - // pSock was already closed - return; -@@ -507,13 +533,13 @@ - } - else - { -- slog(LOG_DEBUG, "Error reading from socket, closing client\n"); -+ xprintf("Error reading from socket, closing client\n"); - // Error reading data....quit. - cleanup(&tConn); - return; - } - } -- slog(LOG_DEBUG_VV, "Writing: %d chars to socket\n", tConn.resp.current); -+ xprintf("Writing: %d chars to socket\n", tConn.resp.current); - //tConn->resp.data[tConn->resp.current-1] = '\0'; - writeDataToClient(pSock, &(tConn.resp)); - // Finished reading one message... -@@ -526,9 +552,9 @@ - - void writeDataToClient(int pSock, struct shairbuffer *pResponse) - { -- slog(LOG_DEBUG_VV, "\n----Beg Send Response Header----\n%.*s\n", pResponse->current, pResponse->data); -+ xprintf("\n----Beg Send Response Header----\n%.*s\n", pResponse->current, pResponse->data); - send(pSock, pResponse->data, pResponse->current,0); -- slog(LOG_DEBUG_VV, "----Send Response Header----\n"); -+ xprintf("----Send Response Header----\n"); - } - - int readDataFromClient(int pSock, struct shairbuffer *pClientBuffer) -@@ -541,7 +567,7 @@ - while(tRetval > 0 && tEnd < 0) - { - // Read from socket until \n\n, \r\n\r\n, or \r\r is found -- slog(LOG_DEBUG_V, "Waiting To Read...\n"); -+ xprintf("Waiting To Read...\n"); - fflush(stdout); - tRetval = read(pSock, tReadBuf, MAX_SIZE); - // if new buffer contains the end of request string, only copy partial buffer? -@@ -552,40 +578,40 @@ - { - pClientBuffer->marker = tEnd+1; // Marks start of content - } -- slog(SOCKET_LOG_LEVEL, "Found end of http request at: %d\n", tEnd); -+ xprintf("Found end of http request at: %d\n", tEnd); - fflush(stdout); - } - else - { - tEnd = MAX_SIZE; -- slog(SOCKET_LOG_LEVEL, "Read %d of data so far\n%s\n", tRetval, tReadBuf); -+ xprintf("Read %d of data so far\n%s\n", tRetval, tReadBuf); - fflush(stdout); - } - if(tRetval > 0) - { - // Copy read data into tReceive; -- slog(SOCKET_LOG_LEVEL, "Read %d data, using %d of it\n", tRetval, tEnd); -+ xprintf("Read %d data, using %d of it\n", tRetval, tEnd); - addNToShairBuffer(pClientBuffer, tReadBuf, tRetval); -- slog(LOG_DEBUG_VV, "Finished copying data\n"); -+ xprintf("Finished copying data\n"); - } - else - { -- slog(LOG_DEBUG, "Error reading data from socket, got: %d bytes", tRetval); -+ xprintf("Error reading data from socket, got: %d bytes", tRetval); - return tRetval; - } - } - if(tEnd + 1 != tRetval) - { -- slog(SOCKET_LOG_LEVEL, "Read more data after end of http request. %d instead of %d\n", tRetval, tEnd+1); -+ xprintf("Read more data after end of http request. %d instead of %d\n", tRetval, tEnd+1); - } -- slog(SOCKET_LOG_LEVEL, "Finished Reading Data:\n%s\nEndOfData\n", pClientBuffer->data); -+ xprintf("Finished Reading Data:\n%s\nEndOfData\n", pClientBuffer->data); - fflush(stdout); - return 0; - } - - char *getFromBuffer(char *pBufferPtr, const char *pField, int pLenAfterField, int *pReturnSize, char *pDelims) - { -- slog(LOG_DEBUG_V, "GettingFromBuffer: %s\n", pField); -+ xprintf("GettingFromBuffer: %s\n", pField); - char* tFound = strstr(pBufferPtr, pField); - int tSize = 0; - if(tFound != NULL) -@@ -606,7 +632,7 @@ - } - - tSize = (int) (tShortest - tFound); -- slog(LOG_DEBUG_VV, "Found %.*s length: %d\n", tSize, tFound, tSize); -+ xprintf("Found %.*s length: %d\n", tSize, tFound, tSize); - if(pReturnSize != NULL) - { - *pReturnSize = tSize; -@@ -614,7 +640,7 @@ - } - else - { -- slog(LOG_DEBUG_V, "Not Found\n"); -+ xprintf("Not Found\n"); - } - return tFound; - } -@@ -648,10 +674,10 @@ - { - char tTrim[tFoundSize + 2]; - getTrimmed(tFound, tFoundSize, TRUE, TRUE, tTrim); -- slog(LOG_DEBUG_VV, "HeaderChallenge: [%s] len: %d sizeFound: %d\n", tTrim, strlen(tTrim), tFoundSize); -+ xprintf("HeaderChallenge: [%s] len: %d sizeFound: %d\n", tTrim, strlen(tTrim), tFoundSize); - int tChallengeDecodeSize = 16; - char *tChallenge = decode_base64((unsigned char *)tTrim, tFoundSize, &tChallengeDecodeSize); -- slog(LOG_DEBUG_VV, "Challenge Decode size: %d expected 16\n", tChallengeDecodeSize); -+ xprintf("Challenge Decode size: %d expected 16\n", tChallengeDecodeSize); - - int tCurSize = 0; - unsigned char tChalResp[38]; -@@ -673,7 +699,7 @@ - } - - char *tTmp = encode_base64((unsigned char *)tChalResp, tCurSize); -- slog(LOG_DEBUG_VV, "Full sig: %s\n", tTmp); -+ xprintf("Full sig: %s\n", tTmp); - free(tTmp); - - // RSA Encrypt -@@ -722,10 +748,10 @@ - { - if(isLogEnabledFor(HEADER_LOG_LEVEL)) - { -- slog(HEADER_LOG_LEVEL, "Content-Length: %s value -> %d\n", tContent, tContentSize); -+ xprintf("Content-Length: %s value -> %d\n", tContent, tContentSize); - if(pConn->recv.marker != 0) - { -- slog(HEADER_LOG_LEVEL, "ContentPtr has %d, but needs %d\n", -+ xprintf("ContentPtr has %d, but needs %d\n", - strlen(pConn->recv.data+pConn->recv.marker), tContentSize); - } - } -@@ -735,7 +761,7 @@ - } - else - { -- slog(LOG_DEBUG_VV, "No content, header only\n"); -+ xprintf("No content, header only\n"); - } - - // "Creates" a new Response Header for our response message -@@ -748,7 +774,7 @@ - { - tLen = 20; - } -- slog(LOG_INFO, "********** RECV %.*s **********\n", tLen, pConn->recv.data); -+ xprintf("********** RECV %.*s **********\n", tLen, pConn->recv.data); - } - - if(pConn->password != NULL) -@@ -758,7 +784,7 @@ - - if(buildAppleResponse(pConn, pIpBin, pIpBinLen, pHWID)) // need to free sig - { -- slog(LOG_DEBUG_V, "Added AppleResponse to Apple-Challenge request\n"); -+ xprintf("Added AppleResponse to Apple-Challenge request\n"); - } - - // Find option, then based on option, do different actions. -@@ -778,14 +804,14 @@ - int tKeySize = 0; - char tEncodedAesIV[tSize + 2]; - getTrimmed(tHeaderVal, tSize, TRUE, TRUE, tEncodedAesIV); -- slog(LOG_DEBUG_VV, "AESIV: [%.*s] Size: %d Strlen: %d\n", tSize, tEncodedAesIV, tSize, strlen(tEncodedAesIV)); -+ xprintf("AESIV: [%.*s] Size: %d Strlen: %d\n", tSize, tEncodedAesIV, tSize, strlen(tEncodedAesIV)); - char *tDecodedIV = decode_base64((unsigned char*) tEncodedAesIV, tSize, &tSize); - - // grab the key, copy it out of the receive buffer - tHeaderVal = getFromContent(tContent, "a=rsaaeskey", &tKeySize); - char tEncodedAesKey[tKeySize + 2]; // +1 for nl, +1 for \0 - getTrimmed(tHeaderVal, tKeySize, TRUE, TRUE, tEncodedAesKey); -- slog(LOG_DEBUG_VV, "AES KEY: [%s] Size: %d Strlen: %d\n", tEncodedAesKey, tKeySize, strlen(tEncodedAesKey)); -+ xprintf("AES KEY: [%s] Size: %d Strlen: %d\n", tEncodedAesKey, tKeySize, strlen(tEncodedAesKey)); - // remove base64 coding from key - char *tDecodedAesKey = decode_base64((unsigned char*) tEncodedAesKey, - tKeySize, &tKeySize); // Need to free DecodedAesKey -@@ -794,7 +820,7 @@ - int tFmtpSize = 0; - char *tFmtp = getFromContent(tContent, "a=fmtp", &tFmtpSize); // Don't need to free - tFmtp = getTrimmedMalloc(tFmtp, tFmtpSize, TRUE, FALSE); // will need to free -- slog(LOG_DEBUG_VV, "Format: %s\n", tFmtp); -+ xprintf("Format: %s\n", tFmtp); - - RSA *rsa = loadKey(); - // Decrypt the binary aes key -@@ -803,11 +829,11 @@ - if(RSA_private_decrypt(tKeySize, (unsigned char *)tDecodedAesKey, - (unsigned char*) tDecryptedKey, rsa, RSA_PKCS1_OAEP_PADDING) >= 0) - { -- slog(LOG_DEBUG, "Decrypted AES key from RSA Successfully\n"); -+ xprintf("Decrypted AES key from RSA Successfully\n"); - } - else - { -- slog(LOG_INFO, "Error Decrypting AES key from RSA\n"); -+ xprintf("Error Decrypting AES key from RSA\n"); - } - free(tDecodedAesKey); - RSA_free(rsa); -@@ -823,13 +849,13 @@ - // struct comms *tComms = pConn->hairtunes; - // if (! (pipe(tComms->in) == 0 && pipe(tComms->out) == 0)) - // { --// slog(LOG_INFO, "Error setting up hairtunes communications...some things probably wont work very well.\n"); -+// xprintf("Error setting up hairtunes communications...some things probably wont work very well.\n"); - // } - - // Setup fork - char tPort[8] = "6000"; // get this from dup()'d stdout of child pid - -- printf("******** SETUP!!!!!\n"); -+ xprintf("******** SETUP!!!!!\n",NULL); - #ifndef XBMC - int tPid = fork(); - if(tPid == 0) -@@ -845,11 +871,11 @@ - tFound = getFromSetup(pConn->recv.data, "timing_port", &tSize); - getTrimmed(tFound, tSize, 1, 0, tTPortStr); - -- slog(LOG_DEBUG_VV, "converting %s and %s from str->int\n", tCPortStr, tTPortStr); -+ xprintf("converting %s and %s from str->int\n", tCPortStr, tTPortStr); - int tControlport = atoi(tCPortStr); - int tTimingport = atoi(tTPortStr); - -- slog(LOG_DEBUG_V, "Got %d for CPort and %d for TPort\n", tControlport, tTimingport); -+ xprintf("Got %d for CPort and %d for TPort\n", tControlport, tTimingport); - char *tRtp = NULL; - char *tPipe = NULL; - char *tAoDriver = NULL; -@@ -884,7 +910,7 @@ - tDataport, tRtp, tPipe, tAoDriver, tAoDeviceName, tAoDeviceId); - #ifndef XBMC - // Quit when finished. -- slog(LOG_DEBUG, "Returned from hairtunes init....returning -1, should close out this whole side of the fork\n"); -+ xprintf("Returned from hairtunes init....returning -1, should close out this whole side of the fork\n"); - return -1; - } - else if(tPid >0) -@@ -897,7 +923,7 @@ - int tRead = read(tComms->out[0], tFromHairtunes, 80); - if(tRead <= 0) - { -- slog(LOG_INFO, "Error reading port from hairtunes function, assuming default port: %d\n", tPort); -+ xprintf("Error reading port from hairtunes function, assuming default port: %d\n", tPort); - } - else - { -@@ -909,7 +935,7 @@ - } - else - { -- slog(LOG_INFO, "Read %d bytes, Error translating %s into a port\n", tRead, tFromHairtunes); -+ xprintf("Read %d bytes, Error translating %s into a port\n", tRead, tFromHairtunes); - } - } - -@@ -930,7 +956,7 @@ - } - else - { -- slog(LOG_INFO, "Error forking process....dere' be errors round here.\n"); -+ xprintf("Error forking process....dere' be errors round here.\n"); - return -1; - } - #endif -@@ -942,7 +968,7 @@ - propogateCSeq(pConn); - #ifndef XBMC - close(pConn->hairtunes->in[1]); -- slog(LOG_DEBUG, "Tearing down connection, closing pipes\n"); -+ xprintf("Tearing down connection, closing pipes\n"); - #else - hairtunes_cleanup(); - #endif -@@ -964,7 +990,7 @@ - propogateCSeq(pConn); - int tSize = 0; - char *tVol = getFromHeader(pConn->recv.data, "volume", &tSize); -- slog(LOG_DEBUG_VV, "About to write [vol: %.*s] data to hairtunes\n", tSize, tVol); -+ xprintf("About to write [vol: %.*s] data to hairtunes\n", tSize, tVol); - // TBD VOLUME - #ifndef XBMC - write(pConn->hairtunes->in[1], "vol: ", 5); -@@ -973,11 +999,11 @@ - #else - hairtunes_setvolume(atof(tVol)); - #endif -- slog(LOG_DEBUG_VV, "Finished writing data write data to hairtunes\n"); -+ xprintf("Finished writing data write data to hairtunes\n"); - } - else - { -- slog(LOG_DEBUG, "\n\nUn-Handled recv: %s\n", pConn->recv.data); -+ xprintf("\n\nUn-Handled recv: %s\n", pConn->recv.data); - propogateCSeq(pConn); - } - addToShairBuffer(&(pConn->resp), "\r\n"); -@@ -1056,7 +1082,7 @@ - char tName[100 + HWID_SIZE + 3]; - if(strlen(pServerName) > tMaxServerName) - { -- slog(LOG_INFO,"Hey dog, we see you like long server names, " -+ xprintf("Hey dog, we see you like long server names, " - "so we put a strncat in our command so we don't buffer overflow, while you listen to your flow.\n" - "We just used the first %d characters. Pick something shorter if you want\n", tMaxServerName); - } -@@ -1067,7 +1093,7 @@ - strcat(tName, pHWStr); - strcat(tName, "@"); - strncat(tName, pServerName, tMaxServerName); -- slog(AVAHI_LOG_LEVEL, "Avahi/DNS-SD Name: %s\n", tName); -+ xprintf("Avahi/DNS-SD Name: %s\n", tName); - - execlp("avahi-publish-service", "avahi-publish-service", tName, - "_raop._tcp", tPort, "tp=UDP","sm=false","sv=false","ek=1","et=0,1", -@@ -1079,12 +1105,12 @@ - perror("error"); - } - -- slog(LOG_INFO, "Bad error... couldn't find or failed to run: avahi-publish-service OR dns-sd\n"); -- exit(1); -+ xprintf("Bad error... couldn't find or failed to run: avahi-publish-service OR dns-sd\n"); -+ //exit(1); - } - else - { -- slog(LOG_DEBUG_VV, "Avahi/DNS-SD started on PID: %d\n", tPid); -+ xprintf("Avahi/DNS-SD started on PID: %d\n", tPid); - } - return tPid; - } -@@ -1092,7 +1118,7 @@ - - void printBufferInfo(struct shairbuffer *pBuf, int pLevel) - { -- slog(pLevel, "Buffer: [%s] size: %d maxchars:%d\n", pBuf->data, pBuf->current, pBuf->maxsize/sizeof(char)); -+ xprintf("Buffer: [%s] size: %d maxchars:%d\n", pBuf->data, pBuf->current, pBuf->maxsize/sizeof(char)); - } - - int getAvailChars(struct shairbuffer *pBuf) -@@ -1173,7 +1199,8 @@ - { - va_list argp; - va_start(argp, pFormat); -- vprintf(pFormat, argp); -+ xprintf(pFormat, argp); -+ //vprintf(pFormat, argp); - va_end(argp); - } - //#endif -@@ -1227,9 +1254,9 @@ - { - if(pBuf->data != NULL) - { -- slog(LOG_DEBUG_VV, "Hrm, buffer wasn't cleaned up....trying to free\n"); -+ xprintf("Hrm, buffer wasn't cleaned up....trying to free\n"); - free(pBuf->data); -- slog(LOG_DEBUG_VV, "Free didn't seem to seg fault....huzzah\n"); -+ xprintf("Free didn't seem to seg fault....huzzah\n"); - } - pBuf->current = 0; - pBuf->marker = 0; -@@ -1287,6 +1314,6 @@ - BIO *tBio = BIO_new_mem_buf(AIRPORT_PRIVATE_KEY, -1); - RSA *rsa = PEM_read_bio_RSAPrivateKey(tBio, NULL, NULL, NULL); //NULL, NULL, NULL); - BIO_free(tBio); -- slog(RSA_LOG_LEVEL, "RSA Key: %d\n", RSA_check_key(rsa)); -+ xprintf("RSA Key: %d\n", RSA_check_key(rsa)); - return rsa; - } ---- src/shairport.h 2011-10-01 17:45:08.000000000 +0200 -+++ src/shairport.h 2011-10-01 17:19:43.000000000 +0200 -@@ -59,11 +59,17 @@ - { - #endif /* __cplusplus */ - -+struct printfPtr -+{ -+ int (*extprintf)(const char* msg, size_t msgSize); -+}; -+ - int shairport_main(int argc, char **argv); - void shairport_exit(void); - int shairport_loop(void); - int shairport_is_running(void); - void shairport_set_ao(struct AudioOutput *ao); -+void shairport_set_printf(struct printfPtr *funcPtr); - - #ifdef __cplusplus - } ---- src/socketlib.c 2011-09-23 22:00:48.000000000 +0200 -+++ src/socketlib.c 2011-10-01 17:42:39.000000000 +0200 -@@ -82,7 +82,7 @@ - delay(RETRY_DELAY, &tRes); - } - } -- printf("%d Retry attempts exceeded\n", RETRY_COUNT); -+ xprintf("%d Retry attempts exceeded\n", RETRY_COUNT); - return ERROR; - } - -@@ -102,7 +102,7 @@ - tError = getaddrinfo(pHostname, pService, &hints, pAddrInfo); - if(tError != 0) - { -- printf("Error getting address info\n"); -+ xprintf("Error getting address info\n"); - } - return tError; - } -@@ -200,7 +200,7 @@ - else - { - // Invalid encoded data, no other cases are possible. -- printf("Unrecoverable error....base64 values are incorrectly encoded\n"); -+ xprintf("Unrecoverable error....base64 values are incorrectly encoded\n"); - return pSize; - } - } -@@ -226,7 +226,7 @@ - memset(input, 0, length); - memcpy(input, pInput, pLength); - memset(input+pLength, '=', length-pLength); -- printf("Fixed value: [%.*s]\n", length, input); -+ xprintf("Fixed value: [%.*s]\n", length, input); - } - char *buffer = (char *)malloc(length); - memset(buffer, 0, length); diff --git a/tools/depends/target/libshairport/007_fix_syslog_defines.patch b/tools/depends/target/libshairport/007_fix_syslog_defines.patch deleted file mode 100644 index 4d9b834f9c..0000000000 --- a/tools/depends/target/libshairport/007_fix_syslog_defines.patch +++ /dev/null @@ -1,24 +0,0 @@ ---- src/shairport.h 2011-10-01 04:09:16.000000000 +0200 -+++ src/shairport.h 2011-11-07 18:05:05.000000000 +0100 -@@ -16,10 +16,17 @@ - - #define HWID_SIZE 6 - #define SHAIRPORT_LOG 1 --#define LOG_INFO 1 --#define LOG_DEBUG 5 --#define LOG_DEBUG_V 6 --#define LOG_DEBUG_VV 7 -+ -+#ifndef LOG_INFO -+#define LOG_INFO 5 -+#endif -+ -+#ifndef LOG_DEBUG -+#define LOG_DEBUG 6 -+#endif -+ -+#define LOG_DEBUG_V 7 -+#define LOG_DEBUG_VV 8 - - struct shairbuffer - { diff --git a/tools/depends/target/libshairport/008-add-missing-libs.patch b/tools/depends/target/libshairport/008-add-missing-libs.patch deleted file mode 100644 index 6efd30222a..0000000000 --- a/tools/depends/target/libshairport/008-add-missing-libs.patch +++ /dev/null @@ -1,21 +0,0 @@ ---- configure.in-org 2011-11-08 11:53:42.802419355 -0500 -+++ configure.in 2011-11-08 11:55:38.082419413 -0500 -@@ -11,8 +11,9 @@ AC_PROG_LIBTOOL - - # Checks for libraries. - #AC_CHECK_LIB([c], [main]) --#AC_CHECK_LIB([m], [main]) -+AC_CHECK_LIB([m], [main]) - AC_CHECK_LIB([ssl], [main],, AC_MSG_ERROR($missing_library)) -+AC_CHECK_LIB([crypto], [main],, AC_MSG_ERROR($missing_library)) - AC_CHECK_LIB([pthread], [main],, AC_MSG_ERROR($missing_library)) - - OUTPUT_FILES="Makefile" -@@ -21,4 +22,4 @@ LIBDIR=$PREFIX - - AC_CONFIG_FILES([${OUTPUT_FILES}]) - AC_OUTPUT(Makefile src/Makefile) --AC_OUTPUT -\ No newline at end of file -+AC_OUTPUT - diff --git a/tools/depends/target/libshairport/009_fix_ipv6.patch b/tools/depends/target/libshairport/009_fix_ipv6.patch deleted file mode 100644 index 01ff026d07..0000000000 --- a/tools/depends/target/libshairport/009_fix_ipv6.patch +++ /dev/null @@ -1,22 +0,0 @@ ---- src/socketlib.c 2012-01-04 20:41:05.000000000 +0100 -+++ src/socketlib.c 2012-01-04 20:35:53.000000000 +0100 -@@ -48,7 +48,7 @@ - if((tSock==-1) && (pAddrInfo->ai_family == AF_INET6) && (errno == EAFNOSUPPORT)) - { - //Fallback to ipv4 -- perror("Failed to create ipv6 socket. Trying ipv4"); -+ xprintf("Failed to create ipv6 socket. Trying ipv4"); - pAddrInfo->ai_family = AF_INET; - tSock = socket(pAddrInfo->ai_family, pAddrInfo->ai_socktype, 0); - } -@@ -158,8 +158,8 @@ - sprintf(tService, "%d", pPort); // copies port to string - int tFamily = AF_INET; - #ifdef AF_INET6 -- //printf("Listening on IPv6 Socket\n"); -- //tFamily = AF_INET6; -+ xprintf("Listening on IPv6 Socket\n"); -+ tFamily = AF_INET6; - #else - //printf("Listening on IPv4 Socket"); - #endif diff --git a/tools/depends/target/libshairport/010_handle_metadata.patch b/tools/depends/target/libshairport/010_handle_metadata.patch deleted file mode 100644 index a48782ed08..0000000000 --- a/tools/depends/target/libshairport/010_handle_metadata.patch +++ /dev/null @@ -1,154 +0,0 @@ -diff -ruP src/ao.h libshairport.new/src/ao.h ---- src/ao.h 2012-05-07 22:26:53.000000000 +0200 -+++ src/ao.h 2012-05-08 18:46:42.000000000 +0200 -@@ -152,5 +152,7 @@ - /* -- Device Setup/Playback/Teardown -- */ - int (*ao_append_option)(ao_option **, const char *, const char *); - void (*ao_free_options)(ao_option *); -- char* (*ao_get_option)(ao_option *, const char* ); -+ char* (*ao_get_option)(ao_option *, const char* ); -+ void (*ao_set_metadata)(const char *buffer, unsigned int size); -+ void (*ao_set_metadata_coverart)(const char *buffer, unsigned int size); - }; -diff -ruP src/hairtunes.c src/hairtunes.c ---- src/hairtunes.c 2012-05-07 22:26:53.000000000 +0200 -+++ src/hairtunes.c 2012-05-08 18:45:51.000000000 +0200 -@@ -267,6 +267,16 @@ - fix_volume = 65536.0 * volume; - } - -+void hairtunes_set_metadata(const char *buffer, unsigned int size) -+{ -+ g_ao.ao_set_metadata(buffer, size); -+} -+ -+void hairtunes_set_metadata_coverart(const char *buffer, unsigned int size) -+{ -+ g_ao.ao_set_metadata_coverart(buffer, size); -+} -+ - void hairtunes_flush(void) - { - pthread_mutex_lock(&ab_mutex); -diff -ruP src/hairtunes.h src/hairtunes.h ---- src/hairtunes.h 2011-08-21 00:06:21.000000000 +0200 -+++ src/hairtunes.h 2012-05-08 18:46:00.000000000 +0200 -@@ -4,6 +4,8 @@ - int hairtunes_init(char *pAeskey, char *pAesiv, char *pFmtpstr, int pCtrlPort, int pTimingPort, - int pDataPort, char *pRtpHost, char*pPipeName, char *pLibaoDriver, char *pLibaoDeviceName, char *pLibaoDeviceId); - void hairtunes_setvolume(float vol); -+void hairtunes_set_metadata(const char *buffer, unsigned int size); -+void hairtunes_set_metadata_coverart(const char *buffer, unsigned int size); - void hairtunes_flush(void); - void hairtunes_cleanup(void); - -diff -ruP src/shairport.c src/shairport.c ---- src/shairport.c 2012-05-07 22:26:53.000000000 +0200 -+++ src/shairport.c 2012-05-08 18:45:30.000000000 +0200 -@@ -513,7 +513,8 @@ - while(1 == tMoreDataNeeded) - { - tError = readDataFromClient(pSock, &(tConn.recv)); -- if(!tError && strlen(tConn.recv.data) > 0) -+ //if(!tError && strlen(tConn.recv.data) > 0) -+ if(!tError && tConn.recv.current > 0) - { - xprintf("Finished Reading some data from client\n"); - // parse client request -@@ -632,7 +633,7 @@ - } - - tSize = (int) (tShortest - tFound); -- xprintf("Found %.*s length: %d\n", tSize, tFound, tSize); -+ xprintf("Found %s length: %d\n",tFound, tSize); - if(pReturnSize != NULL) - { - *pReturnSize = tSize; -@@ -744,7 +745,7 @@ - if(tContent != NULL) - { - int tContentSize = atoi(tContent); -- if(pConn->recv.marker == 0 || strlen(pConn->recv.data+pConn->recv.marker) != tContentSize) -+ if(pConn->recv.marker == 0 || pConn->recv.current-pConn->recv.marker != tContentSize) - { - if(isLogEnabledFor(HEADER_LOG_LEVEL)) - { -@@ -752,7 +753,7 @@ - if(pConn->recv.marker != 0) - { - xprintf("ContentPtr has %d, but needs %d\n", -- strlen(pConn->recv.data+pConn->recv.marker), tContentSize); -+ (pConn->recv.current-pConn->recv.marker), tContentSize); - } - } - // check if value in tContent > 2nd read from client. -@@ -989,15 +990,67 @@ - { - propogateCSeq(pConn); - int tSize = 0; -+ char *buffer = NULL; -+ char *contentType = getFromHeader(pConn->recv.data, "Content-Type", &tSize); -+ char *tContent = getFromHeader(pConn->recv.data, "Content-Length", NULL); -+ int iContentSize = 0; -+ int isJpg = 0; -+ -+ if(tContent != NULL) -+ { -+ iContentSize = atoi(tContent); -+ } -+ -+ if( tSize > 1 && -+ (strncmp(contentType, "application/x-dmap-tagged", tSize) == 0) || -+ (strncmp(contentType, "image/jpeg", tSize) == 0) ) -+ { -+ if( (pConn->recv.current - pConn->recv.marker) == iContentSize && pConn->recv.marker != 0) -+ { -+ if(strncmp(contentType, "image/jpeg", tSize) == 0) -+ { -+ isJpg = 1; -+ } -+ buffer = (char *)malloc(iContentSize * sizeof(char)); -+ memcpy(buffer, pConn->recv.data + pConn->recv.marker, iContentSize); -+ } -+ else -+ { -+ iContentSize = 0; -+ } -+ } -+ else -+ { -+ iContentSize = 0; -+ } - char *tVol = getFromHeader(pConn->recv.data, "volume", &tSize); -- xprintf("About to write [vol: %.*s] data to hairtunes\n", tSize, tVol); -+ if( tVol) -+ { -+ xprintf("About to write [vol: %.*s] data to hairtunes\n", tSize, tVol); -+ } - // TBD VOLUME - #ifndef XBMC - write(pConn->hairtunes->in[1], "vol: ", 5); - write(pConn->hairtunes->in[1], tVol, tSize); - write(pConn->hairtunes->in[1], "\n", 1); - #else -- hairtunes_setvolume(atof(tVol)); -+ if(tVol) -+ { -+ hairtunes_setvolume(atof(tVol)); -+ } -+ -+ if(iContentSize) -+ { -+ if(isJpg) -+ { -+ hairtunes_set_metadata_coverart(buffer, iContentSize); -+ } -+ else -+ { -+ hairtunes_set_metadata(buffer, iContentSize); -+ } -+ free(buffer); -+ } - #endif - xprintf("Finished writing data write data to hairtunes\n"); - } diff --git a/tools/depends/target/libshairport/011_fix_ipv4_fallback.patch b/tools/depends/target/libshairport/011_fix_ipv4_fallback.patch deleted file mode 100644 index 2c813f224e..0000000000 --- a/tools/depends/target/libshairport/011_fix_ipv4_fallback.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- src/socketlib.c 2012-07-14 22:49:30.000000000 +0200 -+++ src/socketlib.c 2012-10-08 21:55:51.000000000 +0200 -@@ -118,6 +118,7 @@ - - int tEnable = 1; - setsockopt(tSock, SOL_SOCKET, SO_REUSEADDR, &tEnable, sizeof (tEnable)); -+ server_addr->ai_addr->sa_family = server_addr->ai_family; // ensure that server_addr has same famliy than the socket - if (bind(tSock, server_addr->ai_addr, server_addr->ai_addrlen) < 0) - { - close(tSock); diff --git a/tools/depends/target/libshairport/012_add_volume_control.patch b/tools/depends/target/libshairport/012_add_volume_control.patch deleted file mode 100644 index c036b94c6e..0000000000 --- a/tools/depends/target/libshairport/012_add_volume_control.patch +++ /dev/null @@ -1,28 +0,0 @@ ---- src/ao.h 2013-03-14 19:07:04.000000000 +0100 -+++ src/ao.h 2013-03-14 20:45:15.000000000 +0100 -@@ -141,6 +141,7 @@ - - #endif /* __AO_H__ */ - -+#define SHAIRPORT_AUDIOOUTPUT_VERSION 2 - extern struct AudioOutput g_ao; - struct AudioOutput - { -@@ -155,4 +156,5 @@ - char* (*ao_get_option)(ao_option *, const char* ); - void (*ao_set_metadata)(const char *buffer, unsigned int size); - void (*ao_set_metadata_coverart)(const char *buffer, unsigned int size); -+ void (*ao_set_volume)(float volume); - }; -diff -uPr orig/src/hairtunes.c macosx10.6_i386-target/src/hairtunes.c ---- src/hairtunes.c 2013-03-14 19:07:04.000000000 +0100 -+++ src/hairtunes.c 2013-03-14 20:46:33.000000000 +0100 -@@ -265,6 +265,8 @@ - assert(f<=0); - if (debug) - xprintf("VOL: %lf\n", f); -+ if (g_ao.ao_set_volume) -+ g_ao.ao_set_volume(f); - volume = pow(10.0,0.05*f); - fix_volume = 65536.0 * volume; - } diff --git a/tools/depends/target/libshairport/Makefile b/tools/depends/target/libshairport/Makefile deleted file mode 100644 index 03016ca5da..0000000000 --- a/tools/depends/target/libshairport/Makefile +++ /dev/null @@ -1,61 +0,0 @@ -include ../../Makefile.include -DEPS= ../../Makefile.include 001_add_ao.patch 002_fix_install_header.patch 003_fix_deadlock.patch \ - 004_fix_bad_access.patch 005_fix_shutdown.patch 006_no_printf.patch \ - 007_fix_syslog_defines.patch 008-add-missing-libs.patch \ - 009_fix_ipv6.patch 010_handle_metadata.patch android.patch Makefile - -# lib name, version -LIBNAME=libshairport -VERSION=1.2.0.20310_lib -SOURCE=$(LIBNAME)-$(VERSION) -ARCHIVE=$(SOURCE).tar.gz - -# configuration settings -CONFIGURE=./configure --prefix=$(PREFIX) - - -LIBDYLIB=$(PLATFORM)/src/.libs/libshairport.so.0.0.0 - -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 < ../001_add_ao.patch - cd $(PLATFORM); patch -p0 < ../002_fix_install_header.patch - cd $(PLATFORM); patch -p0 < ../003_fix_deadlock.patch - cd $(PLATFORM); patch -p0 < ../004_fix_bad_access.patch - cd $(PLATFORM); patch -p0 < ../005_fix_shutdown.patch - cd $(PLATFORM); patch -p0 < ../006_no_printf.patch - cd $(PLATFORM); patch -p0 < ../007_fix_syslog_defines.patch - cd $(PLATFORM); patch -p0 < ../008-add-missing-libs.patch - cd $(PLATFORM); patch -p0 < ../009_fix_ipv6.patch - cd $(PLATFORM); patch -p0 < ../010_handle_metadata.patch - cd $(PLATFORM); patch -p0 < ../011_fix_ipv4_fallback.patch - cd $(PLATFORM); patch -p0 < ../android.patch - cd $(PLATFORM); patch -p0 < ../012_add_volume_control.patch - cd $(PLATFORM); $(AUTORECONF) -vif - cd $(PLATFORM); $(CONFIGURE) - -$(LIBDYLIB): $(PLATFORM) - $(MAKE) -j 1 -C $(PLATFORM) - -.installed-$(PLATFORM): $(LIBDYLIB) - $(MAKE) -C $(PLATFORM) install -ifeq ($(OS),android) - rm -f $(PREFIX)/lib/libshairport.la $(PREFIX)/lib/libshairport.so $(PREFIX)/lib/libshairport.so.0 - mv -f $(PREFIX)/lib/libshairport.so.0.0.0 $(PREFIX)/lib/libshairport.so - $(RPL) -e "libshairport.so.0" "libshairport.so\x00\x00" $(PREFIX)/lib/libshairport.so - -$(READELF) --dynamic $(PREFIX)/lib/libshairport.so | grep ibrary -endif - touch $@ - -clean: - rm -rf $(PLATFORM) .installed-$(PLATFORM) - -distclean:: - rm -rf $(PLATFORM) .installed-$(PLATFORM) - diff --git a/tools/depends/target/libshairport/android.patch b/tools/depends/target/libshairport/android.patch deleted file mode 100644 index b27c82b944..0000000000 --- a/tools/depends/target/libshairport/android.patch +++ /dev/null @@ -1,23 +0,0 @@ ---- configure.in 2012-06-03 23:09:30.024347827 -0400 -+++ configure.in 2012-06-03 23:11:37.494347747 -0400 -@@ -14,7 +14,7 @@ - AC_CHECK_LIB([m], [main]) - AC_CHECK_LIB([ssl], [main],, AC_MSG_ERROR($missing_library)) - AC_CHECK_LIB([crypto], [main],, AC_MSG_ERROR($missing_library)) --AC_CHECK_LIB([pthread], [main],, AC_MSG_ERROR($missing_library)) -+AC_SEARCH_LIBS([pthread_create], [pthread],, AC_MSG_ERROR($missing_library)) - - OUTPUT_FILES="Makefile" - ---- src/hairtunes.c 2012-06-03 23:15:47.944347589 -0400 -+++ src/hairtunes.c 2012-06-03 23:16:23.044347567 -0400 -@@ -42,7 +42,9 @@ - #include <sys/stat.h> - - #include "hairtunes.h" -+#ifndef ANDROID - #include <sys/signal.h> -+#endif - #include <fcntl.h> - #ifdef HAS_AO - #include "ao.h" diff --git a/tools/depends/target/zlib/Makefile b/tools/depends/target/zlib/Makefile index e40f21582d..551301ca57 100644 --- a/tools/depends/target/zlib/Makefile +++ b/tools/depends/target/zlib/Makefile @@ -6,7 +6,6 @@ LIBNAME=zlib VERSION=1.2.7 SOURCE=$(LIBNAME)-$(VERSION) ARCHIVE=$(SOURCE).tar.gz -BASE_URL=http://zlib.net/ # configuration settings CONFIGURE= CC="$(CC)" CFLAGS="$(CFLAGS)" ./configure --prefix=$(PREFIX) --static diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp index d99703a731..02b7b7595f 100644 --- a/xbmc/Application.cpp +++ b/xbmc/Application.cpp @@ -37,18 +37,7 @@ #include "PlayListPlayer.h" #include "Autorun.h" #include "video/Bookmark.h" -#ifdef HAS_WEB_SERVER -#include "network/WebServer.h" -#include "network/httprequesthandler/HTTPImageHandler.h" -#include "network/httprequesthandler/HTTPVfsHandler.h" -#ifdef HAS_JSONRPC -#include "network/httprequesthandler/HTTPJsonRpcHandler.h" -#endif -#ifdef HAS_WEB_INTERFACE -#include "network/httprequesthandler/HTTPWebinterfaceHandler.h" -#include "network/httprequesthandler/HTTPWebinterfaceAddonsHandler.h" -#endif -#endif +#include "network/NetworkServices.h" #include "guilib/GUIControlProfiler.h" #include "utils/LangCodeExpander.h" #include "GUIInfoManager.h" @@ -94,12 +83,14 @@ #include "windowing/WindowingFactory.h" #include "powermanagement/PowerManager.h" #include "powermanagement/DPMSSupport.h" +#include "settings/SettingAddon.h" #include "settings/Settings.h" #include "settings/AdvancedSettings.h" #include "settings/DisplaySettings.h" #include "settings/MediaSettings.h" #include "settings/MediaSourceSettings.h" #include "settings/SkinSettings.h" +#include "settings/Settings.h" #include "guilib/LocalizeStrings.h" #include "utils/CPUInfo.h" #include "utils/RssManager.h" @@ -319,10 +310,16 @@ #include "utils/JobManager.h" #include "utils/SaveFileStateJob.h" #include "utils/AlarmClock.h" +#include "utils/RssReader.h" #include "utils/StringUtils.h" #include "utils/Weather.h" #include "DatabaseManager.h" +#include "settings/DisplaySettings.h" +#include "settings/MediaSettings.h" +#include "settings/SkinSettings.h" +#include "view/ViewStateSettings.h" + #ifdef _LINUX #include "XHandle.h" #endif @@ -344,6 +341,10 @@ #include "android/activity/XBMCApp.h" #endif +#ifdef TARGET_LINUX +#include "linux/LinuxTimezone.h" +#endif + using namespace std; using namespace ADDON; using namespace XFILE; @@ -374,19 +375,7 @@ using namespace XbmcThreads; //extern IDirectSoundRenderer* m_pAudioDecoder; CApplication::CApplication(void) - : m_pPlayer(NULL) -#ifdef HAS_WEB_SERVER - , m_WebServer(*new CWebServer) - , m_httpImageHandler(*new CHTTPImageHandler) - , m_httpVfsHandler(*new CHTTPVfsHandler) -#ifdef HAS_JSONRPC - , m_httpJsonRpcHandler(*new CHTTPJsonRpcHandler) -#endif -#ifdef HAS_WEB_INTERFACE - , m_httpWebinterfaceHandler(*new CHTTPWebinterfaceHandler) - , m_httpWebinterfaceAddonsHandler(*new CHTTPWebinterfaceAddonsHandler) -#endif -#endif + : m_pPlayer() , m_itemCurrentFile(new CFileItem) , m_stackFileItemToUpdate(new CFileItem) , m_progressTrackingVideoResumeBookmark(*new CBookmark) @@ -409,7 +398,9 @@ CApplication::CApplication(void) m_eForcedNextPlayer = EPC_NONE; m_strPlayListFile = ""; m_nextPlaylistItem = -1; + m_iPlayerOPSeq = 0; m_bPlaybackStarting = false; + m_ePlayState = PLAY_STATE_NONE; m_skinReloading = false; #ifdef HAS_GLX @@ -453,18 +444,6 @@ CApplication::CApplication(void) CApplication::~CApplication(void) { -#ifdef HAS_WEB_SERVER - delete &m_WebServer; - delete &m_httpImageHandler; - delete &m_httpVfsHandler; -#ifdef HAS_JSONRPC - delete &m_httpJsonRpcHandler; -#endif -#ifdef HAS_WEB_INTERFACE - delete &m_httpWebinterfaceHandler; - delete &m_httpWebinterfaceAddonsHandler; -#endif -#endif delete m_musicInfoScanner; delete m_videoInfoScanner; delete &m_progressTrackingVideoResumeBookmark; @@ -510,9 +489,9 @@ bool CApplication::OnEvent(XBMC_Event& newEvent) { g_Windowing.SetWindowResolution(newEvent.resize.w, newEvent.resize.h); g_graphicsContext.SetVideoResolution(RES_WINDOW, true); - g_guiSettings.SetInt("window.width", newEvent.resize.w); - g_guiSettings.SetInt("window.height", newEvent.resize.h); - g_settings.Save(); + CSettings::Get().SetInt("window.width", newEvent.resize.w); + CSettings::Get().SetInt("window.height", newEvent.resize.h); + CSettings::Get().Save(); } break; case XBMC_VIDEOMOVE: @@ -665,6 +644,7 @@ bool CApplication::Create() init_emu_environ(); CProfilesManager::Get().Load(); + CSpecialProtocol::SetProfilePath(CProfilesManager::Get().GetProfileUserDataFolder()); CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------"); #if defined(TARGET_DARWIN_OSX) @@ -735,36 +715,25 @@ bool CApplication::Create() return false; } + // Initialize default Settings - don't move CLog::Log(LOGNOTICE, "load settings..."); - g_settings.RegisterSettingsHandler(this); - g_settings.RegisterSettingsHandler(&CProfilesManager::Get()); - g_settings.RegisterSettingsHandler(&g_advancedSettings); - g_settings.RegisterSettingsHandler(&CMediaSourceSettings::Get()); - g_settings.RegisterSettingsHandler(&CPlayerCoreFactory::Get()); - g_settings.RegisterSettingsHandler(&CRssManager::Get()); -#ifdef HAS_UPNP - g_settings.RegisterSettingsHandler(&CUPnPSettings::Get()); -#endif - - g_settings.RegisterSubSettings(this); - g_settings.RegisterSubSettings(&CDisplaySettings::Get()); - g_settings.RegisterSubSettings(&CMediaSettings::Get()); - g_settings.RegisterSubSettings(&CSkinSettings::Get()); - g_settings.RegisterSubSettings(&g_sysinfo); - g_settings.RegisterSubSettings(&CViewStateSettings::Get()); - - g_guiSettings.Initialize(); // Initialize default Settings - don't move + if (!CSettings::Get().Initialize()) + return false; + g_powerManager.SetDefaults(); - if (!g_settings.Load()) + + // load the actual values + if (!CSettings::Get().Load()) { - CLog::Log(LOGFATAL, "%s: Failed to reset settings", __FUNCTION__); + CLog::Log(LOGFATAL, "unable to load settings"); return false; } + CSettings::Get().SetLoaded(); CLog::Log(LOGINFO, "creating subdirectories"); CLog::Log(LOGINFO, "userdata folder: %s", CProfilesManager::Get().GetProfileUserDataFolder().c_str()); - CLog::Log(LOGINFO, "recording folder: %s", g_guiSettings.GetString("audiocds.recordingpath",false).c_str()); - CLog::Log(LOGINFO, "screenshots folder: %s", g_guiSettings.GetString("debug.screenshotpath",false).c_str()); + CLog::Log(LOGINFO, "recording folder: %s", CSettings::Get().GetString("audiocds.recordingpath").c_str()); + CLog::Log(LOGINFO, "screenshots folder: %s", CSettings::Get().GetString("debug.screenshotpath").c_str()); CDirectory::Create(CProfilesManager::Get().GetUserDataFolder()); CDirectory::Create(CProfilesManager::Get().GetProfileUserDataFolder()); CProfilesManager::Get().CreateProfileFolders(); @@ -775,7 +744,7 @@ bool CApplication::Create() g_charsetConverter.reset(); // Load the langinfo to have user charset <-> utf-8 conversion - CStdString strLanguage = g_guiSettings.GetString("locale.language"); + CStdString strLanguage = CSettings::Get().GetString("locale.language"); strLanguage[0] = toupper(strLanguage[0]); CStdString strLangInfoPath; @@ -803,7 +772,7 @@ bool CApplication::Create() // restore AE's previous volume state SetHardwareVolume(m_volumeLevel); CAEFactory::SetMute (m_muted); - CAEFactory::SetSoundMode(g_guiSettings.GetInt("audiooutput.guisoundmode")); + CAEFactory::SetSoundMode(CSettings::Get().GetInt("audiooutput.guisoundmode")); // initialize the addon database (must be before the addon manager is init'd) CDatabaseManager::Get().Initialize(true); @@ -816,12 +785,18 @@ bool CApplication::Create() return false; } + // set logging from debug add-on + AddonPtr addon; + CAddonMgr::Get().GetAddon("xbmc.debug", addon); + if (addon) + g_advancedSettings.SetExtraLogsFromAddon(addon.get()); + g_peripherals.Initialise(); // Create the Mouse, Keyboard, Remote, and Joystick devices // Initialize after loading settings to get joystick deadzone setting g_Mouse.Initialize(); - g_Mouse.SetEnabled(g_guiSettings.GetBool("input.enablemouse")); + g_Mouse.SetEnabled(CSettings::Get().GetBool("input.enablemouse")); g_Keyboard.Initialize(); #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE) @@ -911,7 +886,7 @@ bool CApplication::CreateGUI() } // update the window resolution - g_Windowing.SetWindowResolution(g_guiSettings.GetInt("window.width"), g_guiSettings.GetInt("window.height")); + g_Windowing.SetWindowResolution(CSettings::Get().GetInt("window.width"), CSettings::Get().GetInt("window.height")); if (g_advancedSettings.m_startFullScreen && CDisplaySettings::Get().GetCurrentResolution() == RES_WINDOW) CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP); @@ -1263,25 +1238,13 @@ bool CApplication::Initialize() // initialize (and update as needed) our databases CDatabaseManager::Get().Initialize(); -#ifdef HAS_WEB_SERVER - CWebServer::RegisterRequestHandler(&m_httpImageHandler); - CWebServer::RegisterRequestHandler(&m_httpVfsHandler); -#ifdef HAS_JSONRPC - CWebServer::RegisterRequestHandler(&m_httpJsonRpcHandler); -#endif -#ifdef HAS_WEB_INTERFACE - CWebServer::RegisterRequestHandler(&m_httpWebinterfaceAddonsHandler); - CWebServer::RegisterRequestHandler(&m_httpWebinterfaceHandler); -#endif -#endif - StartServices(); // Init DPMS, before creating the corresponding setting control. m_dpms = new DPMSSupport(); if (g_windowManager.Initialized()) { - g_guiSettings.GetSetting("powermanagement.displaysoff")->SetVisible(m_dpms->IsSupported()); + CSettings::Get().GetSetting("powermanagement.displaysoff")->SetVisible(m_dpms->IsSupported()); g_windowManager.Add(new CGUIWindowHome); g_windowManager.Add(new CGUIWindowPrograms); @@ -1399,16 +1362,17 @@ bool CApplication::Initialize() /* window id's 3000 - 3100 are reserved for python */ // Make sure we have at least the default skin - if (!LoadSkin(g_guiSettings.GetString("lookandfeel.skin")) && !LoadSkin(DEFAULT_SKIN)) + string defaultSkin = ((const CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault(); + if (!LoadSkin(CSettings::Get().GetString("lookandfeel.skin")) && !LoadSkin(defaultSkin)) { - CLog::Log(LOGERROR, "Default skin '%s' not found! Terminating..", DEFAULT_SKIN); - return false; + CLog::Log(LOGERROR, "Default skin '%s' not found! Terminating..", defaultSkin.c_str()); + return false; } if (g_advancedSettings.m_splashImage) SAFE_DELETE(m_splash); - if (g_guiSettings.GetBool("masterlock.startuplock") && + if (CSettings::Get().GetBool("masterlock.startuplock") && CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE && !CProfilesManager::Get().GetMasterProfile().getLockCode().IsEmpty()) { @@ -1474,7 +1438,7 @@ bool CApplication::Initialize() ResetScreenSaver(); #ifdef HAS_SDL_JOYSTICK - g_Joystick.SetEnabled(g_guiSettings.GetBool("input.enablejoystick") && + g_Joystick.SetEnabled(CSettings::Get().GetBool("input.enablejoystick") && CPeripheralImon::GetCountOfImonsConflictWithDInput() == 0 ); #endif @@ -1483,458 +1447,217 @@ bool CApplication::Initialize() bool CApplication::StartServer(enum ESERVERS eServer, bool bStart, bool bWait/* = false*/) { - bool ret = true; - bool oldSetting = false; - + bool ret = false; switch(eServer) { case ES_WEBSERVER: - oldSetting = g_guiSettings.GetBool("services.webserver"); - g_guiSettings.SetBool("services.webserver", bStart); - - if (bStart) - ret = StartWebServer(); - else - StopWebServer(); - - if (!ret) - { - g_guiSettings.SetBool("services.webserver", oldSetting); - } + // the callback will take care of starting/stopping webserver + ret = CSettings::Get().SetBool("services.webserver", bStart); break; - case ES_AIRPLAYSERVER: - oldSetting = g_guiSettings.GetBool("services.airplay"); - g_guiSettings.SetBool("services.airplay", bStart); - if (bStart) - ret = StartAirplayServer(); - else - StopAirplayServer(bWait); - - if (!ret) - { - g_guiSettings.SetBool("services.airplay", oldSetting); - } + case ES_AIRPLAYSERVER: + // the callback will take care of starting/stopping airplay + ret = CSettings::Get().SetBool("services.airplay", bStart); break; - case ES_JSONRPCSERVER: - oldSetting = g_guiSettings.GetBool("services.esenabled"); - g_guiSettings.SetBool("services.esenabled", bStart); - if (bStart) - ret = StartJSONRPCServer(); - else - StopJSONRPCServer(bWait); - - if (!ret) - { - g_guiSettings.SetBool("services.esenabled", oldSetting); - } + case ES_JSONRPCSERVER: + // the callback will take care of starting/stopping jsonrpc server + ret = CSettings::Get().SetBool("services.esenabled", bStart); break; + case ES_UPNPSERVER: - g_guiSettings.SetBool("services.upnpserver", bStart); - if (bStart) - StartUPnPServer(); - else - StopUPnPServer(); + // the callback will take care of starting/stopping upnp server + ret = CSettings::Get().SetBool("services.upnpserver", bStart); break; + case ES_UPNPRENDERER: - g_guiSettings.SetBool("services.upnprenderer", bStart); - if (bStart) - StartUPnPRenderer(); - else - StopUPnPRenderer(); + // the callback will take care of starting/stopping upnp renderer + ret = CSettings::Get().SetBool("services.upnprenderer", bStart); break; - case ES_EVENTSERVER: - oldSetting = g_guiSettings.GetBool("services.esenabled"); - g_guiSettings.SetBool("services.esenabled", bStart); - - if (bStart) - ret = StartEventServer(); - else - StopEventServer(bWait, false); - - if (!ret) - { - g_guiSettings.SetBool("services.esenabled", oldSetting); - } + case ES_EVENTSERVER: + // the callback will take care of starting/stopping event server + ret = CSettings::Get().SetBool("services.esenabled", bStart); break; + case ES_ZEROCONF: - g_guiSettings.SetBool("services.zeroconf", bStart); - if (bStart) - StartZeroconf(); - else - StopZeroconf(); + // the callback will take care of starting/stopping zeroconf + ret = CSettings::Get().SetBool("services.zeroconf", bStart); break; + default: ret = false; break; } - g_settings.Save(); + CSettings::Get().Save(); return ret; } -bool CApplication::StartWebServer() -{ -#ifdef HAS_WEB_SERVER - if (g_guiSettings.GetBool("services.webserver") && m_network->IsAvailable()) - { - int webPort = atoi(g_guiSettings.GetString("services.webserverport")); - CLog::Log(LOGNOTICE, "Webserver: Starting..."); -#ifdef _LINUX - if (webPort < 1024 && !CUtil::CanBindPrivileged()) - { - CLog::Log(LOGERROR, "Cannot start Web Server on port %i, no permission to bind to ports below 1024", webPort); - return false; - } -#endif - - bool started = false; - if (m_WebServer.Start(webPort, g_guiSettings.GetString("services.webserverusername"), g_guiSettings.GetString("services.webserverpassword"))) - { - std::vector<std::pair<std::string, std::string> > txt; - started = true; - // publish web frontend and API services -#ifdef HAS_WEB_INTERFACE - CZeroconf::GetInstance()->PublishService("servers.webserver", "_http._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), webPort, txt); -#endif -#ifdef HAS_JSONRPC - CZeroconf::GetInstance()->PublishService("servers.jsonrpc-http", "_xbmc-jsonrpc-h._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), webPort, txt); -#endif - } - - return started; - } -#endif - - return true; -} - -void CApplication::StopWebServer() -{ -#ifdef HAS_WEB_SERVER - if (m_WebServer.IsStarted()) - { - CLog::Log(LOGNOTICE, "Webserver: Stopping..."); - m_WebServer.Stop(); - if(! m_WebServer.IsStarted() ) - { - CLog::Log(LOGNOTICE, "Webserver: Stopped..."); - CZeroconf::GetInstance()->RemoveService("servers.webserver"); - CZeroconf::GetInstance()->RemoveService("servers.jsonrpc-http"); - } else - CLog::Log(LOGWARNING, "Webserver: Failed to stop."); - } -#endif -} - -bool CApplication::StartAirplayServer() +void CApplication::StartPVRManager(bool bOpenPVRWindow /* = false */) { - bool ret = false; -#ifdef HAS_AIRPLAY - if (g_guiSettings.GetBool("services.airplay") && m_network->IsAvailable()) - { - int listenPort = g_advancedSettings.m_airPlayPort; - CStdString password = g_guiSettings.GetString("services.airplaypassword"); - bool usePassword = g_guiSettings.GetBool("services.useairplaypassword"); - - if (CAirPlayServer::StartServer(listenPort, true)) - { - CAirPlayServer::SetCredentials(usePassword, password); - std::vector<std::pair<std::string, std::string> > txt; - CNetworkInterface* iface = g_application.getNetwork().GetFirstConnectedInterface(); - if (iface) - { - txt.push_back(std::make_pair("deviceid", iface->GetMacAddress())); - } - else - { - txt.push_back(std::make_pair("deviceid", "FF:FF:FF:FF:FF:F2")); - } - txt.push_back(std::make_pair("features", "0x77")); - txt.push_back(std::make_pair("model", "Xbmc,1")); - txt.push_back(std::make_pair("srcvers", AIRPLAY_SERVER_VERSION_STR)); - CZeroconf::GetInstance()->PublishService("servers.airplay", "_airplay._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), listenPort, txt); - ret = true; - } - } - if (ret) -#endif - { -#ifdef HAS_AIRTUNES - if (g_guiSettings.GetBool("services.airplay") && m_network->IsAvailable()) - { - int listenPort = g_advancedSettings.m_airTunesPort; - CStdString password = g_guiSettings.GetString("services.airplaypassword"); - bool usePassword = g_guiSettings.GetBool("services.useairplaypassword"); - - if (!CAirTunesServer::StartServer(listenPort, true, usePassword, password)) - { - CLog::Log(LOGERROR, "Failed to start AirTunes Server"); - } - ret = true; - } -#endif - } - return ret; + if (CSettings::Get().GetBool("pvrmanager.enabled")) + g_PVRManager.Start(true, bOpenPVRWindow); } -void CApplication::StopAirplayServer(bool bWait) +void CApplication::StopPVRManager() { -#ifdef HAS_AIRPLAY - CAirPlayServer::StopServer(bWait); - CZeroconf::GetInstance()->RemoveService("servers.airplay"); -#endif -#ifdef HAS_AIRTUNES - CAirTunesServer::StopServer(bWait); -#endif + CLog::Log(LOGINFO, "stopping PVRManager"); + if (g_PVRManager.IsPlaying()) + StopPlaying(); + g_PVRManager.Stop(); + g_EpgContainer.Stop(); } -bool CApplication::StartJSONRPCServer() +void CApplication::StartServices() { -#ifdef HAS_JSONRPC - if (g_guiSettings.GetBool("services.esenabled")) - { - if (CTCPServer::StartServer(g_advancedSettings.m_jsonTcpPort, g_guiSettings.GetBool("services.esallinterfaces"))) - { - std::vector<std::pair<std::string, std::string> > txt; - CZeroconf::GetInstance()->PublishService("servers.jsonrpc-tcp", "_xbmc-jsonrpc._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), g_advancedSettings.m_jsonTcpPort, txt); - return true; - } - else - return false; - } +#if !defined(_WIN32) && defined(HAS_DVD_DRIVE) + // Start Thread for DVD Mediatype detection + CLog::Log(LOGNOTICE, "start dvd mediatype detection"); + m_DetectDVDType.Create(false, THREAD_MINSTACKSIZE); #endif - return true; -} - -void CApplication::StopJSONRPCServer(bool bWait) -{ -#ifdef HAS_JSONRPC - CTCPServer::StopServer(bWait); - CZeroconf::GetInstance()->RemoveService("servers.jsonrpc-tcp"); -#endif + CLog::Log(LOGNOTICE, "initializing playlistplayer"); + g_playlistPlayer.SetRepeat(PLAYLIST_MUSIC, CMediaSettings::Get().DoesMusicPlaylistRepeat() ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE); + g_playlistPlayer.SetShuffle(PLAYLIST_MUSIC, CMediaSettings::Get().IsMusicPlaylistShuffled()); + g_playlistPlayer.SetRepeat(PLAYLIST_VIDEO, CMediaSettings::Get().DoesVideoPlaylistRepeat() ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE); + g_playlistPlayer.SetShuffle(PLAYLIST_VIDEO, CMediaSettings::Get().IsVideoPlaylistShuffled()); + CLog::Log(LOGNOTICE, "DONE initializing playlistplayer"); } -void CApplication::StartUPnP() +void CApplication::StopServices() { -#ifdef HAS_UPNP - StartUPnPClient(); - StartUPnPServer(); - StartUPnPRenderer(); -#endif -} + m_network->NetworkMessage(CNetwork::SERVICES_DOWN, 0); -void CApplication::StopUPnP(bool bWait) -{ -#ifdef HAS_UPNP - if (UPNP::CUPnP::IsInstantiated()) - { - CLog::Log(LOGNOTICE, "stopping upnp"); - UPNP::CUPnP::ReleaseInstance(bWait); - } +#if !defined(_WIN32) && defined(HAS_DVD_DRIVE) + CLog::Log(LOGNOTICE, "stop dvd detect media"); + m_DetectDVDType.StopThread(); #endif -} -bool CApplication::StartEventServer() -{ -#ifdef HAS_EVENT_SERVER - CEventServer* server = CEventServer::GetInstance(); - if (!server) - { - CLog::Log(LOGERROR, "ES: Out of memory"); - return false; - } - if (g_guiSettings.GetBool("services.esenabled")) - { - CLog::Log(LOGNOTICE, "ES: Starting event server"); - server->StartServer(); - return true; - } -#endif - return true; + g_peripherals.Clear(); } -bool CApplication::StopEventServer(bool bWait, bool promptuser) +void CApplication::OnSettingChanged(const CSetting *setting) { -#ifdef HAS_EVENT_SERVER - CEventServer* server = CEventServer::GetInstance(); - if (!server) - { - CLog::Log(LOGERROR, "ES: Out of memory"); - return false; - } - if (promptuser) - { - if (server->GetNumberOfClients() > 0) - { - bool cancelled = false; - if (!CGUIDialogYesNo::ShowAndGetInput(13140, 13141, 13142, 20022, - -1, -1, cancelled, 10000) - || cancelled) - { - CLog::Log(LOGNOTICE, "ES: Not stopping event server"); - return false; - } - } - CLog::Log(LOGNOTICE, "ES: Stopping event server with confirmation"); + if (setting == NULL) + return; - CEventServer::GetInstance()->StopServer(true); + const std::string &settingId = setting->GetId(); + if (settingId == "lookandfeel.skin" || + settingId == "lookandfeel.font" || + settingId == "lookandfeel.skincolors") + ReloadSkin(); + else if (settingId == "lookandfeel.skintheme") + { + // also set the default color theme + string colorTheme = URIUtils::ReplaceExtension(((CSettingString*)setting)->GetValue(), ".xml"); + if (StringUtils::EqualsNoCase(colorTheme, "Textures.xml")) + colorTheme = "defaults.xml"; + + // check if we have to change the skin color + // if yes, it will trigger a call to ReloadSkin() in + // it's OnSettingChanged() callback + // if no we have to call ReloadSkin() ourselves + if (!StringUtils::EqualsNoCase(colorTheme, CSettings::Get().GetString("lookandfeel.skincolors"))) + CSettings::Get().SetString("lookandfeel.skincolors", colorTheme); + else + ReloadSkin(); } - else + else if (settingId == "lookandfeel.skinzoom") + g_windowManager.SendMessage(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_WINDOW_RESIZE); + else if (StringUtils::StartsWith(settingId, "audiooutput.")) { - if (!bWait) - CLog::Log(LOGNOTICE, "ES: Stopping event server"); + if (settingId == "audiooutput.guisoundmode") + CAEFactory::SetSoundMode(((CSettingInt*)setting)->GetValue()); - CEventServer::GetInstance()->StopServer(bWait); + CAEFactory::OnSettingsChange(settingId); } - - return true; -#endif -} - -void CApplication::RefreshEventServer() -{ -#ifdef HAS_EVENT_SERVER - if (g_guiSettings.GetBool("services.esenabled")) - { - CEventServer::GetInstance()->RefreshSettings(); - } -#endif + else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygaintype")) + m_replayGainSettings.iType = ((CSettingInt*)setting)->GetValue(); + else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainpreamp")) + m_replayGainSettings.iPreAmp = ((CSettingInt*)setting)->GetValue(); + else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainnogainpreamp")) + m_replayGainSettings.iNoGainPreAmp = ((CSettingInt*)setting)->GetValue(); + else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainavoidclipping")) + m_replayGainSettings.bAvoidClipping = ((CSettingBool*)setting)->GetValue(); } -void CApplication::StartUPnPClient() +void CApplication::OnSettingAction(const CSetting *setting) { -#ifdef HAS_UPNP - if (g_guiSettings.GetBool("services.upnpcontroller")) - { - CLog::Log(LOGNOTICE, "starting upnp client"); - UPNP::CUPnP::GetInstance()->StartClient(); - } -#endif -} + if (setting == NULL) + return; -void CApplication::StopUPnPClient() -{ -#ifdef HAS_UPNP - if (UPNP::CUPnP::IsInstantiated()) + const std::string &settingId = setting->GetId(); + if (settingId == "lookandfeel.skinsettings") + g_windowManager.ActivateWindow(WINDOW_SKIN_SETTINGS); + else if (settingId == "screensaver.preview") + ActivateScreenSaver(true); + else if (settingId == "screensaver.settings") { - CLog::Log(LOGNOTICE, "stopping upnp client"); - UPNP::CUPnP::GetInstance()->StopClient(); + AddonPtr addon; + if (CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), addon, ADDON_SCREENSAVER)) + CGUIDialogAddonSettings::ShowAndGetInput(addon); } -#endif + else if (settingId == "videoscreen.guicalibration") + g_windowManager.ActivateWindow(WINDOW_SCREEN_CALIBRATION); + else if (settingId == "videoscreen.testpattern") + g_windowManager.ActivateWindow(WINDOW_TEST_PATTERN); } -void CApplication::StartUPnPRenderer() +bool CApplication::OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode) { -#ifdef HAS_UPNP - if (g_guiSettings.GetBool("services.upnprenderer")) - { - CLog::Log(LOGNOTICE, "starting upnp renderer"); - UPNP::CUPnP::GetInstance()->StartRenderer(); - } -#endif -} + if (setting == NULL) + return false; -void CApplication::StopUPnPRenderer() -{ -#ifdef HAS_UPNP - if (UPNP::CUPnP::IsInstantiated()) + const std::string &settingId = setting->GetId(); + if (settingId == "audiooutput.channels") { - CLog::Log(LOGNOTICE, "stopping upnp renderer"); - UPNP::CUPnP::GetInstance()->StopRenderer(); - } -#endif -} + // check if this is an update from Eden + if (oldSettingId != NULL && oldSettingNode != NULL && + StringUtils::EqualsNoCase(oldSettingId, "audiooutput.channellayout")) + { + bool ret = false; + CSettingInt* channels = (CSettingInt*)setting; + if (channels->FromString(oldSettingNode->FirstChild()->ValueStr()) && channels->GetValue() < AE_CH_LAYOUT_MAX - 1) + ret = channels->SetValue(channels->GetValue() + 1); -void CApplication::StartUPnPServer() -{ -#ifdef HAS_UPNP - if (g_guiSettings.GetBool("services.upnpserver")) - { - CLog::Log(LOGNOTICE, "starting upnp server"); - UPNP::CUPnP::GetInstance()->StartServer(); - } -#endif -} + // let's just reset the audiodevice settings as well + std::string audiodevice = CSettings::Get().GetString("audiooutput.audiodevice"); + CAEFactory::VerifyOutputDevice(audiodevice, false); + ret |= CSettings::Get().SetString("audiooutput.audiodevice", audiodevice.c_str()); -void CApplication::StopUPnPServer() -{ -#ifdef HAS_UPNP - if (UPNP::CUPnP::IsInstantiated()) - { - CLog::Log(LOGNOTICE, "stopping upnp server"); - UPNP::CUPnP::GetInstance()->StopServer(); + return ret; + } } -#endif -} - -void CApplication::StartZeroconf() -{ -#ifdef HAS_ZEROCONF - //entry in guisetting only present if HAS_ZEROCONF is set - if(g_guiSettings.GetBool("services.zeroconf")) + else if (settingId == "screensaver.mode") { - CLog::Log(LOGNOTICE, "starting zeroconf publishing"); - CZeroconf::GetInstance()->Start(); + CSettingString *screensaverMode = (CSettingString*)setting; + // we no longer ship the built-in slideshow screensaver, replace it if it's still in use + if (StringUtils::EqualsNoCase(screensaverMode->GetValue(), "screensaver.xbmc.builtin.slideshow")) + return screensaverMode->SetValue("screensaver.xbmc.builtin.dim"); } -#endif -} - -void CApplication::StopZeroconf() -{ -#ifdef HAS_ZEROCONF - if(CZeroconf::IsInstantiated()) + else if (settingId == "scrapers.musicvideosdefault") { - CLog::Log(LOGNOTICE, "stopping zeroconf publishing"); - CZeroconf::GetInstance()->Stop(); + CSettingAddon *musicvideoScraper = (CSettingAddon*)setting; + if (StringUtils::EqualsNoCase(musicvideoScraper->GetValue(), "metadata.musicvideos.last.fm")) + { + musicvideoScraper->Reset(); + return true; + } } -#endif -} - -void CApplication::StartPVRManager(bool bOpenPVRWindow /* = false */) -{ - if (g_guiSettings.GetBool("pvrmanager.enabled")) - g_PVRManager.Start(true, bOpenPVRWindow); -} -void CApplication::StopPVRManager() -{ - CLog::Log(LOGINFO, "stopping PVRManager"); - if (g_PVRManager.IsPlaying()) - StopPlaying(); - g_PVRManager.Stop(); - g_EpgContainer.Stop(); -} - -void CApplication::StartServices() -{ -#if !defined(_WIN32) && defined(HAS_DVD_DRIVE) - // Start Thread for DVD Mediatype detection - CLog::Log(LOGNOTICE, "start dvd mediatype detection"); - m_DetectDVDType.Create(false, THREAD_MINSTACKSIZE); -#endif - - CLog::Log(LOGNOTICE, "initializing playlistplayer"); - g_playlistPlayer.SetRepeat(PLAYLIST_MUSIC, CMediaSettings::Get().DoesMusicPlaylistRepeat() ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE); - g_playlistPlayer.SetShuffle(PLAYLIST_MUSIC, CMediaSettings::Get().IsMusicPlaylistShuffled()); - g_playlistPlayer.SetRepeat(PLAYLIST_VIDEO, CMediaSettings::Get().DoesVideoPlaylistRepeat() ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE); - g_playlistPlayer.SetShuffle(PLAYLIST_VIDEO, CMediaSettings::Get().IsVideoPlaylistShuffled()); - CLog::Log(LOGNOTICE, "DONE initializing playlistplayer"); + return false; } -void CApplication::StopServices() +bool CApplication::OnSettingsSaving() const { - m_network->NetworkMessage(CNetwork::SERVICES_DOWN, 0); - -#if !defined(_WIN32) && defined(HAS_DVD_DRIVE) - CLog::Log(LOGNOTICE, "stop dvd detect media"); - m_DetectDVDType.StopThread(); -#endif + // don't save settings when we're busy stopping the application + // a lot of screens try to save settings on deinit and deinit is + // called for every screen when the application is stopping + if (m_bStop) + return false; - g_peripherals.Clear(); + return true; } void CApplication::ReloadSkin() @@ -1950,7 +1673,7 @@ void CApplication::ReloadSkin() if (pWindow) iCtrlID = pWindow->GetFocusedControlID(); - g_application.LoadSkin(g_guiSettings.GetString("lookandfeel.skin")); + g_application.LoadSkin(CSettings::Get().GetString("lookandfeel.skin")); if (iCtrlID != -1) { @@ -1963,14 +1686,6 @@ void CApplication::ReloadSkin() } } -bool CApplication::OnSettingsSaving() const -{ - // Don't save settings when we're busy stopping the application. - // A lot of screens try to save settings on deinit and deinit is called - // for every screen when the application is stopping. - return !m_bStop; -} - bool CApplication::Load(const TiXmlNode *settings) { if (settings == NULL) @@ -2019,11 +1734,11 @@ bool CApplication::LoadSkin(const CStdString& skinID) void CApplication::LoadSkin(const SkinPtr& skin) { + string defaultSkin = ((const CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault(); if (!skin) { - CLog::Log(LOGERROR, "failed to load requested skin, fallback to \"%s\" skin", DEFAULT_SKIN); - g_guiSettings.SetString("lookandfeel.skin", DEFAULT_SKIN); - LoadSkin(DEFAULT_SKIN); + CLog::Log(LOGERROR, "failed to load requested skin, fallback to \"%s\" skin", defaultSkin.c_str()); + CSettings::Get().SetString("lookandfeel.skin", defaultSkin); return ; } @@ -2032,11 +1747,11 @@ void CApplication::LoadSkin(const SkinPtr& skin) { // failed to find home.xml // fallback to default skin - if (strcmpi(skin->ID().c_str(), DEFAULT_SKIN) != 0) + if (strcmpi(skin->ID().c_str(), defaultSkin.c_str()) != 0) { - CLog::Log(LOGERROR, "home.xml doesn't exist in skin: %s, fallback to \"%s\" skin", skin->ID().c_str(), DEFAULT_SKIN); - g_guiSettings.SetString("lookandfeel.skin", DEFAULT_SKIN); - LoadSkin(DEFAULT_SKIN); + CLog::Log(LOGERROR, "home.xml doesn't exist in skin: %s, fallback to \"%s\" skin", skin->ID().c_str(), defaultSkin.c_str()); + CSettings::Get().SetString("lookandfeel.skin", defaultSkin); + LoadSkin(defaultSkin); CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(24102), g_localizeStrings.Get(24103)); return ; } @@ -2077,29 +1792,28 @@ void CApplication::LoadSkin(const SkinPtr& skin) CLog::Log(LOGINFO, " load fonts for skin..."); g_graphicsContext.SetMediaDir(skin->Path()); g_directoryCache.ClearSubPaths(skin->Path()); - if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode(g_guiSettings.GetString("lookandfeel.font"))) + if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode(CSettings::Get().GetString("lookandfeel.font"))) { CLog::Log(LOGINFO, " language needs a ttf font, loading first ttf font available"); CStdString strFontSet; if (g_fontManager.GetFirstFontSetUnicode(strFontSet)) { CLog::Log(LOGINFO, " new font is '%s'", strFontSet.c_str()); - g_guiSettings.SetString("lookandfeel.font", strFontSet); - g_settings.Save(); + CSettings::Get().SetString("lookandfeel.font", strFontSet); + CSettings::Get().Save(); } else - CLog::Log(LOGERROR, " no ttf font found, but needed for the language %s.", g_guiSettings.GetString("locale.language").c_str()); + CLog::Log(LOGERROR, " no ttf font found, but needed for the language %s.", CSettings::Get().GetString("locale.language").c_str()); } - g_colorManager.Load(g_guiSettings.GetString("lookandfeel.skincolors")); + g_colorManager.Load(CSettings::Get().GetString("lookandfeel.skincolors")); - g_fontManager.LoadFonts(g_guiSettings.GetString("lookandfeel.font")); + g_fontManager.LoadFonts(CSettings::Get().GetString("lookandfeel.font")); // load in the skin strings - CStdString langPath; - URIUtils::AddFileToFolder(skin->Path(), "language", langPath); + CStdString langPath = URIUtils::AddFileToFolder(skin->Path(), "language"); URIUtils::AddSlashAtEnd(langPath); - g_localizeStrings.LoadSkinStrings(langPath, g_guiSettings.GetString("locale.language")); + g_localizeStrings.LoadSkinStrings(langPath, CSettings::Get().GetString("locale.language")); g_SkinInfo->LoadIncludes(); @@ -2360,7 +2074,7 @@ void CApplication::Render() MEASURE_FUNCTION; - int vsync_mode = g_guiSettings.GetInt("videoscreen.vsync"); + int vsync_mode = CSettings::Get().GetInt("videoscreen.vsync"); bool decrement = false; bool hasRendered = false; @@ -2374,7 +2088,7 @@ void CApplication::Render() bool extPlayerActive = m_eCurrentPlayer == EPC_EXTPLAYER && IsPlaying() && !m_AppFocused; m_bPresentFrame = false; - if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !IsPaused()) + if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !IsPaused() && g_renderManager.RendererHandlesPresent()) { CSingleLock lock(m_frameMutex); @@ -2584,7 +2298,7 @@ bool CApplication::OnKey(const CKey& key) if (useKeyboard) { action = CAction(0); // reset our action - if (g_guiSettings.GetBool("input.remoteaskeyboard")) + if (CSettings::Get().GetBool("input.remoteaskeyboard")) { // users remote is executing keyboard commands, so use the virtualkeyboard section of keymap.xml // and send those rather than actual keyboard presses. Only for navigation-type commands though @@ -2978,13 +2692,13 @@ bool CApplication::OnAction(const CAction &action) if (action.GetID() == ACTION_TOGGLE_DIGITAL_ANALOG) { // we are only allowed to SetInt to a value supported in GUISettings, so we keep trying until it sticks - int mode = g_guiSettings.GetInt("audiooutput.mode"); - for (int i = 0; i < AUDIO_COUNT; i++) + int mode = CSettings::Get().GetInt("audiooutput.mode"); + for (int i = 0; i < 3; i++) { - if (++mode == AUDIO_COUNT) + if (++mode == 3) mode = 0; - g_guiSettings.SetInt("audiooutput.mode", mode); - if (g_guiSettings.GetInt("audiooutput.mode") == mode) + CSettings::Get().SetInt("audiooutput.mode", mode); + if (CSettings::Get().GetInt("audiooutput.mode") == mode) break; } @@ -3586,26 +3300,8 @@ bool CApplication::Cleanup() #endif DllLoaderContainer::Clear(); g_playlistPlayer.Clear(); - g_settings.Clear(); - g_guiSettings.Clear(); + CSettings::Get().Uninitialize(); g_advancedSettings.Clear(); - - g_settings.UnregisterSubSettings(this); - g_settings.UnregisterSubSettings(&CDisplaySettings::Get()); - g_settings.UnregisterSubSettings(&CMediaSettings::Get()); - g_settings.UnregisterSubSettings(&CSkinSettings::Get()); - g_settings.UnregisterSubSettings(&g_sysinfo); - g_settings.UnregisterSubSettings(&CViewStateSettings::Get()); - - g_settings.UnregisterSettingsHandler(&g_advancedSettings); - g_settings.UnregisterSettingsHandler(&CMediaSourceSettings::Get()); - g_settings.UnregisterSettingsHandler(&CPlayerCoreFactory::Get()); - g_settings.UnregisterSettingsHandler(&CRssManager::Get()); -#ifdef HAS_UPNP - g_settings.UnregisterSettingsHandler(&CUPnPSettings::Get()); -#endif - g_settings.UnregisterSettingsHandler(&CProfilesManager::Get()); - g_settings.UnregisterSettingsHandler(this); #ifdef _LINUX CXHandle::DumpObjectTracker(); @@ -3659,7 +3355,7 @@ void CApplication::Stop(int exitCode) if (CFile::Exists(CProfilesManager::Get().GetSettingsFile())) { CLog::Log(LOGNOTICE, "Saving settings"); - g_settings.Save(); + CSettings::Get().Save(); } else CLog::Log(LOGNOTICE, "Not saving settings (settings.xml is not present)"); @@ -3682,24 +3378,12 @@ void CApplication::Stop(int exitCode) StopServices(); //Sleep(5000); -#ifdef HAS_WEB_SERVER - CWebServer::UnregisterRequestHandler(&m_httpImageHandler); - CWebServer::UnregisterRequestHandler(&m_httpVfsHandler); -#ifdef HAS_JSONRPC - CWebServer::UnregisterRequestHandler(&m_httpJsonRpcHandler); - CJSONRPC::Cleanup(); -#endif -#ifdef HAS_WEB_INTERFACE - CWebServer::UnregisterRequestHandler(&m_httpWebinterfaceAddonsHandler); - CWebServer::UnregisterRequestHandler(&m_httpWebinterfaceHandler); -#endif -#endif - if (m_pPlayer) { CLog::Log(LOGNOTICE, "stop player"); - delete m_pPlayer; - m_pPlayer = NULL; + ++m_iPlayerOPSeq; + m_pPlayer->CloseFile(); + m_pPlayer.reset(); } #if HAS_FILESYTEM_DAAP @@ -3827,13 +3511,13 @@ bool CApplication::PlayMedia(const CFileItem& item, int iPlaylist) { CLog::Log(LOGWARNING, "CApplication::PlayMedia called to play a playlist %s but no idea which playlist to use, playing first item", item.GetPath().c_str()); if(pPlayList->size()) - return PlayFile(*(*pPlayList)[0], false); + return PlayFile(*(*pPlayList)[0], false) == PLAYBACK_OK; } } } //nothing special just play - return PlayFile(item, false); + return PlayFile(item, false) == PLAYBACK_OK; } // PlayStack() @@ -3842,10 +3526,11 @@ bool CApplication::PlayMedia(const CFileItem& item, int iPlaylist) // of each video, so we open + close each one in turn. // A faster calculation of video time would improve this // substantially. -bool CApplication::PlayStack(const CFileItem& item, bool bRestart) +// return value: same with PlayFile() +PlayBackRet CApplication::PlayStack(const CFileItem& item, bool bRestart) { if (!item.IsStack()) - return false; + return PLAYBACK_FAIL; CVideoDatabase dbs; @@ -3929,7 +3614,7 @@ bool CApplication::PlayStack(const CFileItem& item, bool bRestart) if (!CDVDFileInfo::GetFileDuration((*m_currentStack)[i]->GetPath(), duration)) { m_currentStack->Clear(); - return false; + return PLAYBACK_FAIL; } totalTime += duration / 1000; (*m_currentStack)[i]->m_lEndOffset = totalTime; @@ -3981,10 +3666,10 @@ bool CApplication::PlayStack(const CFileItem& item, bool bRestart) return PlayFile(*(*m_currentStack)[0], true); } - return false; + return PLAYBACK_FAIL; } -bool CApplication::PlayFile(const CFileItem& item, bool bRestart) +PlayBackRet CApplication::PlayFile(const CFileItem& item, bool bRestart) { if (!bRestart) { @@ -4016,24 +3701,24 @@ bool CApplication::PlayFile(const CFileItem& item, bool bRestart) if (CGUIDialogPlayEject::ShowAndGetInput(item)) // PlayDiscAskResume takes path to disc. No parameter means default DVD drive. // Can't do better as CGUIDialogPlayEject calls CMediaManager::IsDiscInDrive, which assumes default DVD drive anyway - return MEDIA_DETECT::CAutorun::PlayDiscAskResume(); + return MEDIA_DETECT::CAutorun::PlayDiscAskResume() ? PLAYBACK_OK : PLAYBACK_FAIL; } else #endif CGUIDialogOK::ShowAndGetInput(435, 0, 436, 0); - return true; + return PLAYBACK_OK; } if (item.IsPlayList()) - return false; + return PLAYBACK_FAIL; if (item.IsPlugin()) { // we modify the item so that it becomes a real URL CFileItem item_new(item); if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new)) return PlayFile(item_new, false); - return false; + return PLAYBACK_FAIL; } #ifdef HAS_UPNP @@ -4042,7 +3727,7 @@ bool CApplication::PlayFile(const CFileItem& item, bool bRestart) CFileItem item_new(item); if (XFILE::CUPnPDirectory::GetResource(item.GetPath(), item_new)) return PlayFile(item_new, false); - return false; + return PLAYBACK_FAIL; } #endif @@ -4060,6 +3745,7 @@ bool CApplication::PlayFile(const CFileItem& item, bool bRestart) if(g_tuxboxService.IsRunning()) g_tuxboxService.Stop(); + PlayBackRet ret = PLAYBACK_FAIL; CFileItem item_new; if(g_tuxbox.CreateNewItem(item, item_new)) { @@ -4070,14 +3756,14 @@ bool CApplication::PlayFile(const CFileItem& item, bool bRestart) // keep the tuxbox:// url as playing url // and give the new url to the player - if(PlayFile(item_new, true)) + ret = PlayFile(item_new, true); + if(ret == PLAYBACK_OK) { if(!g_tuxboxService.IsRunning()) g_tuxboxService.Start(); - return true; } } - return false; + return ret; } CPlayerOptions options; @@ -4192,8 +3878,30 @@ bool CApplication::PlayFile(const CFileItem& item, bool bRestart) m_pKaraokeMgr->Stop(); #endif - // tell system we are starting a file - m_bPlaybackStarting = true; + { + CSingleLock lock(m_playStateMutex); + // tell system we are starting a file + m_bPlaybackStarting = true; + + // for playing a new item, previous playing item's callback may already + // pushed some delay message into the threadmessage list, they are not + // expected be processed after or during the new item playback starting. + // so we clean up previous playing item's playback callback delay messages here. + int previousMsgsIgnoredByNewPlaying[] = { + GUI_MSG_PLAYBACK_STARTED, + GUI_MSG_PLAYBACK_ENDED, + GUI_MSG_PLAYBACK_STOPPED, + GUI_MSG_PLAYLIST_CHANGED, + GUI_MSG_PLAYLISTPLAYER_STOPPED, + GUI_MSG_PLAYLISTPLAYER_STARTED, + GUI_MSG_PLAYLISTPLAYER_CHANGED, + GUI_MSG_QUEUE_NEXT_ITEM, + 0 + }; + int dMsgCount = g_windowManager.RemoveThreadMessageByMessageIds(&previousMsgsIgnoredByNewPlaying[0]); + if (dMsgCount > 0) + CLog::Log(LOGDEBUG,"%s : Ignored %d playback thread messages", __FUNCTION__, dMsgCount); + } // We should restart the player, unless the previous and next tracks are using // one of the players that allows gapless playback (paplayer, dvdplayer) @@ -4205,18 +3913,33 @@ bool CApplication::PlayFile(const CFileItem& item, bool bRestart) #endif )) ) { - delete m_pPlayer; - m_pPlayer = NULL; + ++m_iPlayerOPSeq; + m_pPlayer->CloseFile(); + m_pPlayer.reset(); + } + else + { + // XXX: we had to stop the previous playing item, it was done in dvdplayer::OpenFile. + // but in paplayer::OpenFile, it sometimes just fade in without call CloseFile. + // but if we do not stop it, we can not distingush callbacks from previous + // item and current item, it will confused us then we can not make correct delay + // callback after the starting state. + ++m_iPlayerOPSeq; + m_pPlayer->CloseFile(); } } + // now reset play state to starting, since we already stopped the previous playing item if there is. + // and from now there should be no playback callback from previous playing item be called. + m_ePlayState = PLAY_STATE_STARTING; + if (!m_pPlayer) { m_eCurrentPlayer = eNewCore; - m_pPlayer = CPlayerCoreFactory::Get().CreatePlayer(eNewCore, *this); + m_pPlayer.reset(CPlayerCoreFactory::Get().CreatePlayer(eNewCore, *this)); } - bool bResult; + PlayBackRet iResult; if (m_pPlayer) { /* When playing video pause any low priority jobs, they will be unpaused when playback stops. @@ -4231,15 +3954,25 @@ bool CApplication::PlayFile(const CFileItem& item, bool bRestart) // don't hold graphicscontext here since player // may wait on another thread, that requires gfx CSingleExit ex(g_graphicsContext); - bResult = m_pPlayer->OpenFile(item, options); + // In busy dialog of OpenFile there's a chance to call another place delete the player + // e.g. another PlayFile call switch player. + // Here we use a holdPlace to keep the player not be deleted during OpenFile call + boost::shared_ptr<IPlayer> holdPlace(m_pPlayer); + // op seq for detect cancel (CloseFile be called or OpenFile be called again) during OpenFile. + unsigned int startingSeq = ++m_iPlayerOPSeq; + + iResult = m_pPlayer->OpenFile(item, options) ? PLAYBACK_OK : PLAYBACK_FAIL; + // check whether the OpenFile was canceled by either CloseFile or another OpenFile. + if (m_iPlayerOPSeq != startingSeq) + iResult = PLAYBACK_CANCELED; } else { CLog::Log(LOGERROR, "Error creating player for item %s (File doesn't exist?)", item.GetPath().c_str()); - bResult = false; + iResult = PLAYBACK_FAIL; } - if(bResult) + if(iResult == PLAYBACK_OK) { if (m_iPlaySpeed != 1) { @@ -4288,17 +4021,41 @@ bool CApplication::PlayFile(const CFileItem& item, bool bRestart) if (item.HasPVRChannelInfoTag()) g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_NONE); } + + CSingleLock lock(m_playStateMutex); m_bPlaybackStarting = false; - if (bResult) + if (iResult == PLAYBACK_OK) { - // we must have started, otherwise player might send this later - if(IsPlaying()) - OnPlayBackStarted(); - else - OnPlayBackEnded(); + // play state: none, starting; playing; stopped; ended. + // last 3 states are set by playback callback, they are all ignored during starting, + // but we recorded the state, here we can make up the callback for the state. + CLog::Log(LOGDEBUG,"%s : OpenFile succeed, play state %d", __FUNCTION__, m_ePlayState); + switch (m_ePlayState) + { + case PLAY_STATE_PLAYING: + OnPlayBackStarted(); + break; + // FIXME: it seems no meaning to callback started here if there was an started callback + // before this stopped/ended callback we recorded. if we callback started here + // first, it will delay send OnPlay announce, but then we callback stopped/ended + // which will send OnStop announce at once, so currently, just call stopped/ended. + case PLAY_STATE_ENDED: + OnPlayBackEnded(); + break; + case PLAY_STATE_STOPPED: + OnPlayBackStopped(); + break; + case PLAY_STATE_STARTING: + // neither started nor stopped/ended callback be called, that means the item still + // not started, we need not make up any callback, just leave this and + // let the player callback do its work. + break; + default: + break; + } } - else + else if (iResult == PLAYBACK_FAIL) { // we send this if it isn't playlistplayer that is doing this int next = g_playlistPlayer.GetNextSong(); @@ -4306,13 +4063,17 @@ bool CApplication::PlayFile(const CFileItem& item, bool bRestart) if(next < 0 || next >= size) OnPlayBackStopped(); + m_ePlayState = PLAY_STATE_NONE; } - return bResult; + return iResult; } void CApplication::OnPlayBackEnded() { + CSingleLock lock(m_playStateMutex); + CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting); + m_ePlayState = PLAY_STATE_ENDED; if(m_bPlaybackStarting) return; @@ -4332,6 +4093,9 @@ void CApplication::OnPlayBackEnded() void CApplication::OnPlayBackStarted() { + CSingleLock lock(m_playStateMutex); + CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting); + m_ePlayState = PLAY_STATE_PLAYING; if(m_bPlaybackStarting) return; @@ -4347,6 +4111,10 @@ void CApplication::OnPlayBackStarted() void CApplication::OnQueueNextItem() { + CSingleLock lock(m_playStateMutex); + CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting); + if(m_bPlaybackStarting) + return; // informs python script currently running that we are requesting the next track // (does nothing if python is not loaded) #ifdef HAS_PYTHON @@ -4359,6 +4127,9 @@ void CApplication::OnQueueNextItem() void CApplication::OnPlayBackStopped() { + CSingleLock lock(m_playStateMutex); + CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting); + m_ePlayState = PLAY_STATE_STOPPED; if(m_bPlaybackStarting) return; @@ -4546,7 +4317,8 @@ void CApplication::UpdateFileState() // Check whether we're *really* playing video else we may race when getting eg. stream details if (IsPlayingVideo()) { - // Special case for DVDs: Only extract streamdetails if title length > 15m. Should yield more correct info + /* Always update streamdetails, except for DVDs where we only update + streamdetails if title length > 15m (Should yield more correct info) */ if (!(m_progressTrackingItem->IsDVDImage() || m_progressTrackingItem->IsDVDFile()) || m_pPlayer->GetTotalTime() > 15*60*1000) { CStreamDetails details; @@ -4597,7 +4369,10 @@ void CApplication::StopPlaying() g_PVRManager.SaveCurrentChannelSettings(); if (m_pPlayer) + { + ++m_iPlayerOPSeq; m_pPlayer->CloseFile(); + } // turn off visualisation window when stopping if ((iWin == WINDOW_VISUALISATION @@ -4697,7 +4472,7 @@ bool CApplication::WakeUpScreenSaver(bool bPowerOffKeyPressed /* = false */) { if (m_iScreenSaveLock == 0) if (CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE && - (CProfilesManager::Get().UsingLoginScreen() || g_guiSettings.GetBool("masterlock.startuplock")) && + (CProfilesManager::Get().UsingLoginScreen() || CSettings::Get().GetBool("masterlock.startuplock")) && CProfilesManager::Get().GetCurrentProfile().getLockMode() != LOCK_MODE_EVERYONE && m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" && m_screenSaver->ID() != "screensaver.xbmc.builtin.black" && !m_screenSaver->ID().empty() && m_screenSaver->ID() != "visualization") { @@ -4748,10 +4523,10 @@ void CApplication::CheckScreenSaverAndDPMS() bool maybeScreensaver = !m_dpmsIsActive && !m_bScreenSave - && !g_guiSettings.GetString("screensaver.mode").IsEmpty(); + && !CSettings::Get().GetString("screensaver.mode").empty(); bool maybeDPMS = !m_dpmsIsActive && m_dpms->IsSupported() - && g_guiSettings.GetInt("powermanagement.displaysoff") > 0; + && CSettings::Get().GetInt("powermanagement.displaysoff") > 0; // Has the screen saver window become active? if (maybeScreensaver && g_windowManager.IsWindowActive(WINDOW_SCREENSAVER)) @@ -4773,7 +4548,7 @@ void CApplication::CheckScreenSaverAndDPMS() if ((IsPlayingVideo() && !m_pPlayer->IsPaused()) // * Are we playing some music in fullscreen vis? || (IsPlayingAudio() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION - && !g_guiSettings.GetString("musicplayer.visualisation").IsEmpty())) + && !CSettings::Get().GetString("musicplayer.visualisation").empty())) { ResetScreenSaverTimer(); return; @@ -4783,13 +4558,13 @@ void CApplication::CheckScreenSaverAndDPMS() // DPMS has priority (it makes the screensaver not needed) if (maybeDPMS - && elapsed > g_guiSettings.GetInt("powermanagement.displaysoff") * 60) + && elapsed > CSettings::Get().GetInt("powermanagement.displaysoff") * 60) { ToggleDPMS(false); WakeUpScreenSaver(); } else if (maybeScreensaver - && elapsed > g_guiSettings.GetInt("screensaver.time") * 60) + && elapsed > CSettings::Get().GetInt("screensaver.time") * 60) { ActivateScreenSaver(); } @@ -4804,7 +4579,7 @@ void CApplication::ActivateScreenSaver(bool forceType /*= false */) // Get Screensaver Mode m_screenSaver.reset(); - if (!CAddonMgr::Get().GetAddon(g_guiSettings.GetString("screensaver.mode"), m_screenSaver)) + if (!CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), m_screenSaver)) m_screenSaver.reset(new CScreenSaver("")); CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverActivated"); @@ -4814,13 +4589,13 @@ void CApplication::ActivateScreenSaver(bool forceType /*= false */) if (!forceType) { // set to Dim in the case of a dialog on screen or playing video - if (g_windowManager.HasModalDialog() || (IsPlayingVideo() && g_guiSettings.GetBool("screensaver.usedimonpause")) || g_PVRManager.IsRunningChannelScan()) + if (g_windowManager.HasModalDialog() || (IsPlayingVideo() && CSettings::Get().GetBool("screensaver.usedimonpause")) || g_PVRManager.IsRunningChannelScan()) { if (!CAddonMgr::Get().GetAddon("screensaver.xbmc.builtin.dim", m_screenSaver)) m_screenSaver.reset(new CScreenSaver("")); } // Check if we are Playing Audio and Vis instead Screensaver! - else if (IsPlayingAudio() && g_guiSettings.GetBool("screensaver.usemusicvisinstead") && !g_guiSettings.GetString("musicplayer.visualisation").IsEmpty()) + else if (IsPlayingAudio() && CSettings::Get().GetBool("screensaver.usemusicvisinstead") && !CSettings::Get().GetString("musicplayer.visualisation").empty()) { // activate the visualisation m_screenSaver.reset(new CScreenSaver("visualization")); g_windowManager.ActivateWindow(WINDOW_VISUALISATION); @@ -4861,7 +4636,7 @@ void CApplication::CheckShutdown() if (g_windowManager.IsWindowActive(WINDOW_DIALOG_PROGRESS)) // progress dialog is onscreen resetTimer = true; - if (g_guiSettings.GetBool("pvrmanager.enabled") && !g_PVRManager.IsIdle()) + if (CSettings::Get().GetBool("pvrmanager.enabled") && !g_PVRManager.IsIdle()) resetTimer = true; if (resetTimer) @@ -4870,7 +4645,7 @@ void CApplication::CheckShutdown() return; } - if ( m_shutdownTimer.GetElapsedSeconds() > g_guiSettings.GetInt("powermanagement.shutdowntime") * 60 ) + if ( m_shutdownTimer.GetElapsedSeconds() > CSettings::Get().GetInt("powermanagement.shutdowntime") * 60 ) { // Since it is a sleep instead of a shutdown, let's set everything to reset when we wake up. m_shutdownTimer.Stop(); @@ -4951,7 +4726,7 @@ bool CApplication::OnMessage(CGUIMessage& message) { // Start our cdg parser as appropriate #ifdef HAS_KARAOKE - if (m_pKaraokeMgr && g_guiSettings.GetBool("karaoke.enabled") && !m_itemCurrentFile->IsInternetStream()) + if (m_pKaraokeMgr && CSettings::Get().GetBool("karaoke.enabled") && !m_itemCurrentFile->IsInternetStream()) { m_pKaraokeMgr->Stop(); if (m_itemCurrentFile->IsMusicDb()) @@ -5001,11 +4776,22 @@ bool CApplication::OnMessage(CGUIMessage& message) } #endif - // ok - send the file to the player if it wants it - if (m_pPlayer && m_pPlayer->QueueNextFile(file)) - { // player wants the next file - m_nextPlaylistItem = iNext; + // ok - send the file to the player, if it accepts it + if (m_pPlayer) + { + if (m_pPlayer->QueueNextFile(file)) + { + // player accepted the next file + m_nextPlaylistItem = iNext; + } + else + { + /* Player didn't accept next file: *ALWAYS* advance playlist in this case so the player can + queue the next (if it wants to) and it doesn't keep looping on this song */ + g_playlistPlayer.SetCurrentSong(iNext); + } } + return true; } break; @@ -5053,8 +4839,12 @@ bool CApplication::OnMessage(CGUIMessage& message) // reset any forced player m_eForcedNextPlayer = EPC_NONE; - delete m_pPlayer; - m_pPlayer = 0; + if (m_pPlayer) + { + ++m_iPlayerOPSeq; + m_pPlayer->CloseFile(); + m_pPlayer.reset(); + } // Reset playspeed m_iPlaySpeed = 1; @@ -5081,7 +4871,7 @@ bool CApplication::OnMessage(CGUIMessage& message) if (!IsPlayingAudio() && g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_NONE && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION) { - g_settings.Save(); // save vis settings + CSettings::Get().Save(); // save vis settings WakeUpScreenSaverAndDPMS(); g_windowManager.PreviousWindow(); } @@ -5090,7 +4880,7 @@ bool CApplication::OnMessage(CGUIMessage& message) if (!IsPlayingAudio() && (m_itemCurrentFile->IsCDDA() || m_itemCurrentFile->IsOnDVD()) && !g_mediaManager.IsDiscInDrive() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION) { // yes, disable vis - g_settings.Save(); // save vis settings + CSettings::Get().Save(); // save vis settings WakeUpScreenSaverAndDPMS(); g_windowManager.PreviousWindow(); } @@ -5226,9 +5016,9 @@ void CApplication::ProcessSlow() // Check if we need to shutdown (if enabled). #if defined(TARGET_DARWIN) - if (g_guiSettings.GetInt("powermanagement.shutdowntime") && g_advancedSettings.m_fullScreen) + if (CSettings::Get().GetInt("powermanagement.shutdowntime") && g_advancedSettings.m_fullScreen) #else - if (g_guiSettings.GetInt("powermanagement.shutdowntime")) + if (CSettings::Get().GetInt("powermanagement.shutdowntime")) #endif { CheckShutdown(); @@ -5373,7 +5163,7 @@ void CApplication::Restart(bool bSamePosition) m_itemCurrentFile->m_lStartOffset = (long)(time * 75.0); // reopen the file - if ( PlayFile(*m_itemCurrentFile, true) && m_pPlayer ) + if ( PlayFile(*m_itemCurrentFile, true) == PLAYBACK_OK && m_pPlayer ) m_pPlayer->SetPlayerState(state); } @@ -5749,13 +5539,13 @@ PLAYERCOREID CApplication::GetCurrentPlayer() void CApplication::UpdateLibraries() { - if (g_guiSettings.GetBool("videolibrary.updateonstartup")) + if (CSettings::Get().GetBool("videolibrary.updateonstartup")) { CLog::Log(LOGNOTICE, "%s - Starting video library startup scan", __FUNCTION__); StartVideoScan(""); } - if (g_guiSettings.GetBool("musiclibrary.updateonstartup")) + if (CSettings::Get().GetBool("musiclibrary.updateonstartup")) { CLog::Log(LOGNOTICE, "%s - Starting music library startup scan", __FUNCTION__); StartMusicScan(""); @@ -5809,9 +5599,9 @@ void CApplication::StartMusicScan(const CStdString &strDirectory, int flags) if (!flags) { // setup default flags - if (g_guiSettings.GetBool("musiclibrary.downloadinfo")) + if (CSettings::Get().GetBool("musiclibrary.downloadinfo")) flags |= CMusicInfoScanner::SCAN_ONLINE; - if (g_guiSettings.GetBool("musiclibrary.backgroundupdate")) + if (CSettings::Get().GetBool("musiclibrary.backgroundupdate")) flags |= CMusicInfoScanner::SCAN_BACKGROUND; } @@ -5982,7 +5772,7 @@ CPerformanceStats &CApplication::GetPerformanceStats() bool CApplication::SetLanguage(const CStdString &strLanguage) { - CStdString strPreviousLanguage = g_guiSettings.GetString("locale.language"); + CStdString strPreviousLanguage = CSettings::Get().GetString("locale.language"); CStdString strNewLanguage = strLanguage; if (strNewLanguage != strPreviousLanguage) { @@ -6000,7 +5790,7 @@ bool CApplication::SetLanguage(const CStdString &strLanguage) else CLog::Log(LOGERROR, "No ttf font found but needed: %s", strFontSet.c_str()); } - g_guiSettings.SetString("locale.language", strNewLanguage); + CSettings::Get().SetString("locale.language", strNewLanguage); g_charsetConverter.reset(); diff --git a/xbmc/Application.h b/xbmc/Application.h index 4e02f67a60..471199e238 100644 --- a/xbmc/Application.h +++ b/xbmc/Application.h @@ -50,6 +50,7 @@ class CPlayerController; #include "cores/playercorefactory/PlayerCoreFactory.h" #include "PlayListPlayer.h" #include "settings/ISettingsHandler.h" +#include "settings/ISettingCallback.h" #include "settings/ISubSettings.h" #if !defined(_WIN32) && defined(HAS_DVD_DRIVE) #include "storage/DetectDVDType.h" @@ -70,21 +71,6 @@ class CInertialScrollingHandler; class DPMSSupport; class CSplash; class CBookmark; -class CWebServer; -class IPlayer; -#ifdef HAS_WEB_SERVER -class CWebServer; -class CHTTPImageHandler; -class CHTTPVfsHandler; -#ifdef HAS_JSONRPC -class CHTTPJsonRpcHandler; -#endif -#ifdef HAS_WEB_INTERFACE -class CHTTPWebinterfaceHandler; -class CHTTPWebinterfaceAddonsHandler; -#endif -#endif - class CNetwork; namespace VIDEO @@ -102,6 +88,16 @@ namespace MUSIC_INFO #define VOLUME_DYNAMIC_RANGE 90.0f // 60dB #define VOLUME_CONTROL_STEPS 90 // 90 steps +// replay gain settings struct for quick access by the player multiple +// times per second (saves doing settings lookup) +struct ReplayGainSettings +{ + int iPreAmp; + int iNoGainPreAmp; + int iType; + bool bAvoidClipping; +}; + class CBackgroundPlayer : public CThread { public: @@ -113,8 +109,15 @@ protected: int m_iPlayList; }; +typedef enum +{ + PLAYBACK_CANCELED = -1, + PLAYBACK_FAIL = 0, + PLAYBACK_OK = 1, +} PlayBackRet; + class CApplication : public CXBApplicationEx, public IPlayerCallback, public IMsgTargetCallback, - public ISettingsHandler, public ISubSettings + public ISettingCallback, public ISettingsHandler, public ISubSettings { public: @@ -147,27 +150,8 @@ public: bool StartServer(enum ESERVERS eServer, bool bStart, bool bWait = false); - bool StartWebServer(); - void StopWebServer(); - bool StartAirplayServer(); - void StopAirplayServer(bool bWait); - bool StartJSONRPCServer(); - void StopJSONRPCServer(bool bWait); - void StartUPnP(); - void StopUPnP(bool bWait); - void StartUPnPClient(); - void StopUPnPClient(); - void StartUPnPRenderer(); - void StopUPnPRenderer(); - void StartUPnPServer(); - void StopUPnPServer(); void StartPVRManager(bool bOpenPVRWindow = false); void StopPVRManager(); - bool StartEventServer(); - bool StopEventServer(bool bWait, bool promptuser); - void RefreshEventServer(); - void StartZeroconf(); - void StopZeroconf(); bool IsCurrentThread() const; void Stop(int exitCode); void RestartApp(); @@ -190,7 +174,7 @@ public: bool PlayMedia(const CFileItem& item, int iPlaylist = PLAYLIST_MUSIC); bool PlayMediaSync(const CFileItem& item, int iPlaylist = PLAYLIST_MUSIC); bool ProcessAndStartPlaylist(const CStdString& strPlayList, PLAYLIST::CPlayList& playlist, int iPlaylist, int track=0); - bool PlayFile(const CFileItem& item, bool bRestart = false); + PlayBackRet PlayFile(const CFileItem& item, bool bRestart = false); void SaveFileState(bool bForeground = false); void UpdateFileState(); void StopPlaying(); @@ -289,25 +273,23 @@ public: MEDIA_DETECT::CDetectDVDMedia m_DetectDVDType; #endif - IPlayer* m_pPlayer; - -#ifdef HAS_WEB_SERVER - CWebServer& m_WebServer; - CHTTPImageHandler& m_httpImageHandler; - CHTTPVfsHandler& m_httpVfsHandler; -#ifdef HAS_JSONRPC - CHTTPJsonRpcHandler& m_httpJsonRpcHandler; -#endif -#ifdef HAS_WEB_INTERFACE - CHTTPWebinterfaceHandler& m_httpWebinterfaceHandler; - CHTTPWebinterfaceAddonsHandler& m_httpWebinterfaceAddonsHandler; -#endif -#endif + boost::shared_ptr<IPlayer> m_pPlayer; inline bool IsInScreenSaver() { return m_bScreenSave; }; int m_iScreenSaveLock; // spiff: are we checking for a lock? if so, ignore the screensaver state, if -1 we have failed to input locks + unsigned int m_iPlayerOPSeq; // used to detect whether an OpenFile request on player is canceled by us. bool m_bPlaybackStarting; + typedef enum + { + PLAY_STATE_NONE = 0, + PLAY_STATE_STARTING, + PLAY_STATE_PLAYING, + PLAY_STATE_STOPPED, + PLAY_STATE_ENDED, + } PlayState; + PlayState m_ePlayState; + CCriticalSection m_playStateMutex; bool m_bInBackground; inline bool IsInBackground() { return m_bInBackground; }; @@ -379,12 +361,18 @@ public: bool GetRenderGUI() const { return m_renderGUI; }; bool SetLanguage(const CStdString &strLanguage); + + ReplayGainSettings& GetReplayGainSettings() { return m_replayGainSettings; } protected: virtual bool OnSettingsSaving() const; virtual bool Load(const TiXmlNode *settings); virtual bool Save(TiXmlNode *settings) const; + virtual void OnSettingChanged(const CSetting *setting); + virtual void OnSettingAction(const CSetting *setting); + virtual bool OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode); + bool LoadSkin(const CStdString& skinID); void LoadSkin(const boost::shared_ptr<ADDON::CSkinInfo>& skin); @@ -462,7 +450,7 @@ protected: void VolumeChanged() const; - bool PlayStack(const CFileItem& item, bool bRestart); + PlayBackRet PlayStack(const CFileItem& item, bool bRestart); bool ProcessMouse(); bool ProcessRemote(float frameTime); bool ProcessGamepad(float frameTime); @@ -494,6 +482,7 @@ protected: std::map<std::string, std::map<int, float> > m_lastAxisMap; #endif + ReplayGainSettings m_replayGainSettings; }; XBMC_GLOBAL_REF(CApplication,g_application); diff --git a/xbmc/ApplicationMessenger.cpp b/xbmc/ApplicationMessenger.cpp index 9be09ab1c1..5ab05fde95 100644 --- a/xbmc/ApplicationMessenger.cpp +++ b/xbmc/ApplicationMessenger.cpp @@ -22,6 +22,7 @@ #include "ApplicationMessenger.h" #include "Application.h" +#include "LangInfo.h" #include "PlayListPlayer.h" #include "Util.h" #ifdef HAS_PYTHON @@ -34,11 +35,11 @@ #include "utils/URIUtils.h" #include "utils/Variant.h" #include "guilib/GUIWindowManager.h" -#include "guilib/Key.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "FileItem.h" #include "guilib/GUIDialog.h" +#include "guilib/Key.h" #include "GUIInfoManager.h" #include "utils/Splash.h" #include "cores/IPlayer.h" @@ -227,7 +228,7 @@ void CApplicationMessenger::ProcessMessage(ThreadMessage *pMsg) { case TMSG_SHUTDOWN: { - switch (g_guiSettings.GetInt("powermanagement.shutdownstate")) + switch (CSettings::Get().GetInt("powermanagement.shutdownstate")) { case POWERSTATE_SHUTDOWN: Powerdown(); @@ -456,7 +457,7 @@ void CApplicationMessenger::ProcessMessage(ThreadMessage *pMsg) { if(items.Size() == 0) { - g_guiSettings.SetString("screensaver.mode", "screensaver.xbmc.builtin.dim"); + CSettings::Get().SetString("screensaver.mode", "screensaver.xbmc.builtin.dim"); g_application.ActivateScreenSaver(); } else diff --git a/xbmc/AutoSwitch.cpp b/xbmc/AutoSwitch.cpp index 13b9541ed5..6d51d7f317 100644 --- a/xbmc/AutoSwitch.cpp +++ b/xbmc/AutoSwitch.cpp @@ -19,10 +19,10 @@ */ #include "AutoSwitch.h" -#include "settings/GUISettings.h" -#include "guilib/GUIWindowManager.h" #include "FileItem.h" +#include "guilib/GUIWindowManager.h" #include "guilib/WindowIDs.h" +#include "settings/Settings.h" #include "view/ViewState.h" #define METHOD_BYFOLDERS 0 @@ -44,7 +44,7 @@ int CAutoSwitch::GetView(const CFileItemList &vecItems) int iSortMethod = -1; int iPercent = 0; int iCurrentWindow = g_windowManager.GetActiveWindow(); - bool bHideParentFolderItems = !g_guiSettings.GetBool("filelists.showparentdiritems"); + bool bHideParentFolderItems = !CSettings::Get().GetBool("filelists.showparentdiritems"); switch (iCurrentWindow) { diff --git a/xbmc/Autorun.cpp b/xbmc/Autorun.cpp index 47f5dbc7e2..9411b7e04f 100644 --- a/xbmc/Autorun.cpp +++ b/xbmc/Autorun.cpp @@ -32,9 +32,10 @@ #include "filesystem/DirectoryFactory.h" #include "filesystem/File.h" #include "profiles/ProfilesManager.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "playlists/PlayList.h" #include "guilib/GUIWindowManager.h" +#include "guilib/LocalizeStrings.h" #include "storage/MediaManager.h" #include "video/VideoDatabase.h" #include "dialogs/GUIDialogYesNo.h" @@ -70,7 +71,7 @@ void CAutorun::ExecuteAutorun(const CStdString& path, bool bypassSettings, bool g_application.ResetScreenSaver(); g_application.WakeUpScreenSaverAndDPMS(); // turn off the screensaver if it's active #ifdef HAS_CDDA_RIPPER - if (g_guiSettings.GetInt("audiocds.autoaction") == AUTOCD_RIP && + if (CSettings::Get().GetInt("audiocds.autoaction") == AUTOCD_RIP && pInfo->IsAudio(1) && !CProfilesManager::Get().GetCurrentProfile().musicLocked()) { CCDDARipper::GetInstance().RipCD(); @@ -82,7 +83,7 @@ void CAutorun::ExecuteAutorun(const CStdString& path, bool bypassSettings, bool bool CAutorun::PlayDisc(const CStdString& path, bool bypassSettings, bool startFromBeginning) { - if ( !bypassSettings && !g_guiSettings.GetInt("audiocds.autoaction") == AUTOCD_PLAY && !g_guiSettings.GetBool("dvds.autorun")) + if ( !bypassSettings && !CSettings::Get().GetInt("audiocds.autoaction") == AUTOCD_PLAY && !CSettings::Get().GetBool("dvds.autorun")) return false; int nSize = g_playlistPlayer.GetPlaylist( PLAYLIST_MUSIC ).size(); @@ -169,7 +170,7 @@ bool CAutorun::RunDisc(IDirectory* pDir, const CStdString& strDrive, int& nAdded // Check if the current foldername indicates a DVD structure (name is "VIDEO_TS") if (name.Equals("VIDEO_TS") && bAllowVideo - && (bypassSettings || g_guiSettings.GetBool("dvds.autorun"))) + && (bypassSettings || CSettings::Get().GetBool("dvds.autorun"))) { CStdString path = URIUtils::AddFileToFolder(pItem->GetPath(), "VIDEO_TS.IFO"); if(!CFile::Exists(path)) @@ -190,7 +191,7 @@ bool CAutorun::RunDisc(IDirectory* pDir, const CStdString& strDrive, int& nAdded // A BR should also include an "AACS" folder for encryption, Sony-BRs can also include update folders for PS3 (PS3_UPDATE / PS3_VPRM). // ToDo: for the time beeing, the DVD autorun settings are used to determine if the BR should be started automatically. if (name.Equals("BDMV") && bAllowVideo - && (bypassSettings || g_guiSettings.GetBool("dvds.autorun"))) + && (bypassSettings || CSettings::Get().GetBool("dvds.autorun"))) { CFileItem item(URIUtils::AddFileToFolder(pItem->GetPath(), "index.bdmv"), false); item.SetLabel(g_mediaManager.GetDiskLabel(strDrive)); @@ -228,7 +229,7 @@ bool CAutorun::RunDisc(IDirectory* pDir, const CStdString& strDrive, int& nAdded // Standard Content HD DVD (few discs?) if (name.Equals("HVDVD_TS") && bAllowVideo - && (bypassSettings || g_guiSettings.GetBool("dvds.autorun"))) + && (bypassSettings || CSettings::Get().GetBool("dvds.autorun"))) { if (hddvdname == "") { @@ -322,7 +323,7 @@ bool CAutorun::RunDisc(IDirectory* pDir, const CStdString& strDrive, int& nAdded // If a file format was extracted we are sure this is a VCD. Autoplay if settings indicate we should. if (!strExt.IsEmpty() && bAllowVideo - && (bypassSettings || g_guiSettings.GetBool("dvds.autorun"))) + && (bypassSettings || CSettings::Get().GetBool("dvds.autorun"))) { CFileItemList items; CDirectory::GetDirectory(pItem->GetPath(), items, strExt); @@ -353,12 +354,12 @@ bool CAutorun::RunDisc(IDirectory* pDir, const CStdString& strDrive, int& nAdded } // check video first - if (!nAddedToPlaylist && !bPlaying && (bypassSettings || g_guiSettings.GetBool("dvds.autorun"))) + if (!nAddedToPlaylist && !bPlaying && (bypassSettings || CSettings::Get().GetBool("dvds.autorun"))) { // stack video files CFileItemList tempItems; tempItems.Append(vecItems); - if (g_guiSettings.GetBool("myvideos.stackvideos")) + if (CSettings::Get().GetBool("myvideos.stackvideos")) tempItems.Stack(); CFileItemList itemlist; @@ -398,7 +399,7 @@ bool CAutorun::RunDisc(IDirectory* pDir, const CStdString& strDrive, int& nAdded } } // then music - if (!bPlaying && (bypassSettings || g_guiSettings.GetInt("audiocds.autoaction") == AUTOCD_PLAY) && bAllowMusic) + if (!bPlaying && (bypassSettings || CSettings::Get().GetInt("audiocds.autoaction") == AUTOCD_PLAY) && bAllowMusic) { for (int i = 0; i < vecItems.Size(); i++) { @@ -503,4 +504,25 @@ bool CAutorun::CanResumePlayDVD(const CStdString& path) return false; } +void CAutorun::SettingOptionAudioCdActionsFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t) +{ + list.push_back(make_pair(g_localizeStrings.Get(16018), AUTOCD_NONE)); + list.push_back(make_pair(g_localizeStrings.Get(14098), AUTOCD_PLAY)); +#ifdef HAS_CDDA_RIPPER + list.push_back(make_pair(g_localizeStrings.Get(14096), AUTOCD_RIP)); +#endif +} + +void CAutorun::SettingOptionAudioCdEncodersFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t) +{ +#ifdef HAVE_LIBMP3LAME + list.push_back(make_pair(g_localizeStrings.Get(34000), CDDARIP_ENCODER_LAME)); +#endif +#ifdef HAVE_LIBVORBISENC + list.push_back(make_pair(g_localizeStrings.Get(34001), CDDARIP_ENCODER_VORBIS)); +#endif + list.push_back(make_pair(g_localizeStrings.Get(34002), CDDARIP_ENCODER_WAV)); + list.push_back(make_pair(g_localizeStrings.Get(34005), CDDARIP_ENCODER_FLAC)); +} + #endif diff --git a/xbmc/Autorun.h b/xbmc/Autorun.h index e078c5ae72..1faed11246 100644 --- a/xbmc/Autorun.h +++ b/xbmc/Autorun.h @@ -39,6 +39,15 @@ namespace XFILE class IDirectory; } +class CSetting; + +enum AutoCDAction +{ + AUTOCD_NONE = 0, + AUTOCD_PLAY, + AUTOCD_RIP +}; + namespace MEDIA_DETECT { class CAutorun @@ -54,6 +63,10 @@ public: void Disable(); void HandleAutorun(); static void ExecuteAutorun(const CStdString& path = "", bool bypassSettings = false, bool ignoreplaying = false, bool startFromBeginning = false); + + static void SettingOptionAudioCdActionsFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t); + static void SettingOptionAudioCdEncodersFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t); + protected: static bool RunDisc(XFILE::IDirectory* pDir, const CStdString& strDrive, int& nAddedToPlaylist, bool bRoot, bool bypassSettings, bool startFromBeginning); bool m_bEnable; diff --git a/xbmc/CueDocument.cpp b/xbmc/CueDocument.cpp index e579fdbc6f..cfe41d6748 100644 --- a/xbmc/CueDocument.cpp +++ b/xbmc/CueDocument.cpp @@ -362,7 +362,7 @@ bool CCueDocument::ResolvePath(CStdString &strPath, const CStdString &strBase) CStdString strFilename = URIUtils::GetFileName(strPath); - URIUtils::AddFileToFolder(strDirectory, strFilename, strPath); + strPath = URIUtils::AddFileToFolder(strDirectory, strFilename); // i *hate* windows if (!CFile::Exists(strPath)) diff --git a/xbmc/DllPaths_generated.h.in b/xbmc/DllPaths_generated.h.in index 53fdacb892..09e54913a8 100644 --- a/xbmc/DllPaths_generated.h.in +++ b/xbmc/DllPaths_generated.h.in @@ -37,6 +37,7 @@ #define DLL_PATH_LIBAFP "@AFPCLIENT_SONAME@" #define DLL_PATH_LIBPLIST "@PLIST_SONAME@" #define DLL_PATH_LIBSHAIRPORT "@SHAIRPORT_SONAME@" +#define DLL_PATH_LIBSHAIRPLAY "@SHAIRPLAY_SONAME@" #define DLL_PATH_LIBCEC "@LIBCEC_SONAME@" #ifndef DLL_PATH_LIBCURL diff --git a/xbmc/DllPaths_generated_android.h.in b/xbmc/DllPaths_generated_android.h.in index 570c36f98d..cca9ed2a99 100644 --- a/xbmc/DllPaths_generated_android.h.in +++ b/xbmc/DllPaths_generated_android.h.in @@ -39,6 +39,7 @@ #define DLL_PATH_LIBAFP "@AFPCLIENT_SONAME@" #define DLL_PATH_LIBPLIST "@PLIST_SONAME@" #define DLL_PATH_LIBSHAIRPORT "@SHAIRPORT_SONAME@" +#define DLL_PATH_LIBSHAIRPLAY "@SHAIRPLAY_SONAME@" #define DLL_PATH_LIBCEC "@LIBCEC_SONAME@" #ifndef DLL_PATH_LIBCURL diff --git a/xbmc/DllPaths_win32.h b/xbmc/DllPaths_win32.h index 1f9ff3cb3d..63155a1071 100644 --- a/xbmc/DllPaths_win32.h +++ b/xbmc/DllPaths_win32.h @@ -25,7 +25,6 @@ #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_LIBID3TAG "special://xbmcbin/system/libid3tag.dll" #define DLL_PATH_LIBCMYTH "special://xbmcbin/system/libcmyth.dll" #define DLL_PATH_LIBHDHOMERUN "special://xbmcbin/system/hdhomerun.dll" #define DLL_PATH_LIBCURL "special://xbmcbin/system/libcurl.dll" diff --git a/xbmc/Favourites.cpp b/xbmc/Favourites.cpp index a6925456c4..26535d429f 100644 --- a/xbmc/Favourites.cpp +++ b/xbmc/Favourites.cpp @@ -40,7 +40,7 @@ bool CFavourites::Load(CFileItemList &items) CFavourites::LoadFavourites(favourites, items); else CLog::Log(LOGDEBUG, "CFavourites::Load - no system favourites found, skipping"); - URIUtils::AddFileToFolder(CProfilesManager::Get().GetProfileUserDataFolder(), "favourites.xml", favourites); + favourites = URIUtils::AddFileToFolder(CProfilesManager::Get().GetProfileUserDataFolder(), "favourites.xml"); if(XFILE::CFile::Exists(favourites)) CFavourites::LoadFavourites(favourites, items); else @@ -108,7 +108,7 @@ bool CFavourites::Save(const CFileItemList &items) rootNode->InsertEndChild(favNode); } - URIUtils::AddFileToFolder(CProfilesManager::Get().GetProfileUserDataFolder(), "favourites.xml", favourites); + favourites = URIUtils::AddFileToFolder(CProfilesManager::Get().GetProfileUserDataFolder(), "favourites.xml"); return doc.SaveFile(favourites); } diff --git a/xbmc/FileItem.cpp b/xbmc/FileItem.cpp index d63bfa93c9..1b9b9af867 100644 --- a/xbmc/FileItem.cpp +++ b/xbmc/FileItem.cpp @@ -49,8 +49,8 @@ #include "music/Album.h" #include "music/Song.h" #include "URL.h" -#include "settings/GUISettings.h" #include "settings/AdvancedSettings.h" +#include "settings/Settings.h" #include "utils/RegExp.h" #include "utils/log.h" #include "utils/Variant.h" @@ -167,7 +167,7 @@ CFileItem::CFileItem(const CPVRChannel& channel) *GetPVRChannelInfoTag() = channel; SetLabel(channel.ChannelName()); m_strLabel2 = bHasEpgNow ? epgNow.Title() : - g_guiSettings.GetBool("epg.hidenoinfoavailable") ? + CSettings::Get().GetBool("epg.hidenoinfoavailable") ? StringUtils::EmptyString : g_localizeStrings.Get(19055); // no information available @@ -900,20 +900,47 @@ bool CFileItem::IsInternetStream(const bool bStrictCheck /* = false */) const return URIUtils::IsInternetStream(m_strPath, bStrictCheck); } -bool CFileItem::IsFileFolder() const +bool CFileItem::IsFileFolder(EFileFolderType types) const { - return ( - IsSmartPlayList() || - (IsPlayList() && g_advancedSettings.m_playlistAsFolders) || - IsAPK() || - IsZIP() || - IsRAR() || - IsRSS() || - IsType(".ogg") || - IsType(".nsf") || - IsType(".sid") || - IsType(".sap") - ); + EFileFolderType always_type = EFILEFOLDER_TYPE_ALWAYS; + + /* internet streams are not directly expanded */ + if(IsInternetStream()) + always_type = EFILEFOLDER_TYPE_ONCLICK; + + + if(types & always_type) + { + if( IsSmartPlayList() + || (IsPlayList() && g_advancedSettings.m_playlistAsFolders) + || IsAPK() + || IsZIP() + || IsRAR() + || IsRSS() + || IsType(".ogg") + || IsType(".oga") + || IsType(".nsf") + || IsType(".sid") + || IsType(".sap") + || IsType(".xsp") +#if defined(TARGET_ANDROID) + || IsType(".apk") +#endif +#ifdef HAS_ASAP_CODEC + || ASAPCodec::IsSupportedFormat(URIUtils::GetExtension(m_strPath)) +#endif + ) + return true; + } + + if(types & EFILEFOLDER_TYPE_ONBROWSE) + { + if((IsPlayList() && !g_advancedSettings.m_playlistAsFolders) + || IsDVDImage()) + return true; + } + + return false; } @@ -2321,13 +2348,13 @@ void CFileItemList::StackFolders() { CStdString path; CStdString dvdPath; - URIUtils::AddFileToFolder(item->GetPath(), "VIDEO_TS.IFO", path); + path = URIUtils::AddFileToFolder(item->GetPath(), "VIDEO_TS.IFO"); if (CFile::Exists(path)) dvdPath = path; else { - URIUtils::AddFileToFolder(item->GetPath(), "VIDEO_TS", dvdPath); - URIUtils::AddFileToFolder(dvdPath, "VIDEO_TS.IFO", path); + dvdPath = URIUtils::AddFileToFolder(item->GetPath(), "VIDEO_TS"); + path = URIUtils::AddFileToFolder(dvdPath, "VIDEO_TS.IFO"); dvdPath.Empty(); if (CFile::Exists(path)) dvdPath = path; @@ -2335,13 +2362,13 @@ void CFileItemList::StackFolders() #ifdef HAVE_LIBBLURAY if (dvdPath.IsEmpty()) { - URIUtils::AddFileToFolder(item->GetPath(), "index.bdmv", path); + path = URIUtils::AddFileToFolder(item->GetPath(), "index.bdmv"); if (CFile::Exists(path)) dvdPath = path; else { - URIUtils::AddFileToFolder(item->GetPath(), "BDMV", dvdPath); - URIUtils::AddFileToFolder(dvdPath, "index.bdmv", path); + dvdPath = URIUtils::AddFileToFolder(item->GetPath(), "BDMV"); + path = URIUtils::AddFileToFolder(dvdPath, "index.bdmv"); dvdPath.Empty(); if (CFile::Exists(path)) dvdPath = path; @@ -2529,7 +2556,7 @@ void CFileItemList::StackFiles() // item->m_bIsFolder = true; // don't treat stacked files as folders // the label may be in a different char set from the filename (eg over smb // the label is converted from utf8, but the filename is not) - if (!g_guiSettings.GetBool("filelists.showextensions")) + if (!CSettings::Get().GetBool("filelists.showextensions")) URIUtils::RemoveExtension(stackName); item1->SetLabel(stackName); @@ -2654,7 +2681,7 @@ CStdString CFileItem::GetUserMusicThumb(bool alwaysCheckRemote /* = false */, bo } // if a folder, check for folder.jpg - if (m_bIsFolder && !IsFileFolder() && (!IsRemote() || alwaysCheckRemote || g_guiSettings.GetBool("musicfiles.findremotethumbs"))) + if (m_bIsFolder && !IsFileFolder() && (!IsRemote() || alwaysCheckRemote || CSettings::Get().GetBool("musicfiles.findremotethumbs"))) { CStdStringArray thumbs; StringUtils::SplitString(g_advancedSettings.m_musicThumbs, "|", thumbs); @@ -2685,11 +2712,11 @@ CStdString CFileItem::GetTBNFile() const URIUtils::GetParentPath(m_strPath,strPath); CFileItem item(CStackDirectory::GetFirstStackedFile(strFile),false); CStdString strTBNFile = item.GetTBNFile(); - URIUtils::AddFileToFolder(strPath,URIUtils::GetFileName(strTBNFile),strReturn); + strReturn = URIUtils::AddFileToFolder(strPath, URIUtils::GetFileName(strTBNFile)); if (CFile::Exists(strReturn)) return strReturn; - URIUtils::AddFileToFolder(strPath,URIUtils::GetFileName(CStackDirectory::GetStackedTitlePath(strFile)),strFile); + strFile = URIUtils::AddFileToFolder(strPath,URIUtils::GetFileName(CStackDirectory::GetStackedTitlePath(strFile))); } if (URIUtils::IsInRAR(strFile) || URIUtils::IsInZIP(strFile)) @@ -2697,7 +2724,7 @@ CStdString CFileItem::GetTBNFile() const CStdString strPath, strParent; URIUtils::GetDirectory(strFile,strPath); URIUtils::GetParentPath(strPath,strParent); - URIUtils::AddFileToFolder(strParent,URIUtils::GetFileName(m_strPath),strFile); + strFile = URIUtils::AddFileToFolder(strParent, URIUtils::GetFileName(m_strPath)); } CURL url(strFile); @@ -2766,7 +2793,7 @@ CStdString CFileItem::GetLocalArt(const std::string &artFile, bool useFolder) co */ CStdString strPath; URIUtils::GetParentPath(m_strPath,strPath); - URIUtils::AddFileToFolder(strPath,URIUtils::GetFileName(CStackDirectory::GetStackedTitlePath(strFile)),strFile); + strFile = URIUtils::AddFileToFolder(strPath, URIUtils::GetFileName(CStackDirectory::GetStackedTitlePath(strFile))); } if (URIUtils::IsInRAR(strFile) || URIUtils::IsInZIP(strFile)) @@ -2774,7 +2801,7 @@ CStdString CFileItem::GetLocalArt(const std::string &artFile, bool useFolder) co CStdString strPath, strParent; URIUtils::GetDirectory(strFile,strPath); URIUtils::GetParentPath(strPath,strParent); - URIUtils::AddFileToFolder(strParent,URIUtils::GetFileName(strFile),strFile); + strFile = URIUtils::AddFileToFolder(strParent, URIUtils::GetFileName(strFile)); } if (IsMultiPath()) @@ -2808,7 +2835,6 @@ CStdString CFileItem::GetLocalArt(const std::string &artFile, bool useFolder) co CStdString CFileItem::GetFolderThumb(const CStdString &folderJPG /* = "folder.jpg" */) const { - CStdString folderThumb; CStdString strFolder = m_strPath; if (IsStack() || @@ -2821,8 +2847,7 @@ CStdString CFileItem::GetFolderThumb(const CStdString &folderJPG /* = "folder.jp if (IsMultiPath()) strFolder = CMultiPathDirectory::GetFirstPath(m_strPath); - URIUtils::AddFileToFolder(strFolder, folderJPG, folderThumb); - return folderThumb; + return URIUtils::AddFileToFolder(strFolder, folderJPG); } CStdString CFileItem::GetMovieName(bool bUseFolderNames /* = false */) const @@ -2895,17 +2920,17 @@ CStdString CFileItem::GetLocalFanart() const CStackDirectory dir; CStdString strPath2; strPath2 = dir.GetStackedTitlePath(strFile); - URIUtils::AddFileToFolder(strPath,URIUtils::GetFileName(strPath2),strFile); + strFile = URIUtils::AddFileToFolder(strPath, URIUtils::GetFileName(strPath2)); CFileItem item(dir.GetFirstStackedFile(m_strPath),false); CStdString strTBNFile(URIUtils::ReplaceExtension(item.GetTBNFile(), "-fanart")); - URIUtils::AddFileToFolder(strPath,URIUtils::GetFileName(strTBNFile),strFile2); + strFile2 = URIUtils::AddFileToFolder(strPath, URIUtils::GetFileName(strTBNFile)); } if (URIUtils::IsInRAR(strFile) || URIUtils::IsInZIP(strFile)) { CStdString strPath, strParent; URIUtils::GetDirectory(strFile,strPath); URIUtils::GetParentPath(strPath,strParent); - URIUtils::AddFileToFolder(strParent,URIUtils::GetFileName(m_strPath),strFile); + strFile = URIUtils::AddFileToFolder(strParent, URIUtils::GetFileName(m_strPath)); } // no local fanart available for these @@ -3151,17 +3176,17 @@ CStdString CFileItem::FindTrailer() const CStackDirectory dir; CStdString strPath2; strPath2 = dir.GetStackedTitlePath(strFile); - URIUtils::AddFileToFolder(strPath,URIUtils::GetFileName(strPath2),strFile); + strFile = URIUtils::AddFileToFolder(strPath,URIUtils::GetFileName(strPath2)); CFileItem item(dir.GetFirstStackedFile(m_strPath),false); CStdString strTBNFile(URIUtils::ReplaceExtension(item.GetTBNFile(), "-trailer")); - URIUtils::AddFileToFolder(strPath,URIUtils::GetFileName(strTBNFile),strFile2); + strFile2 = URIUtils::AddFileToFolder(strPath,URIUtils::GetFileName(strTBNFile)); } if (URIUtils::IsInRAR(strFile) || URIUtils::IsInZIP(strFile)) { CStdString strPath, strParent; URIUtils::GetDirectory(strFile,strPath); URIUtils::GetParentPath(strPath,strParent); - URIUtils::AddFileToFolder(strParent,URIUtils::GetFileName(m_strPath),strFile); + strFile = URIUtils::AddFileToFolder(strParent,URIUtils::GetFileName(m_strPath)); } // no local trailer available for these diff --git a/xbmc/FileItem.h b/xbmc/FileItem.h index 8e5926b867..7f8501b1b1 100644 --- a/xbmc/FileItem.h +++ b/xbmc/FileItem.h @@ -66,6 +66,19 @@ class CURL; class CMediaSource; +enum EFileFolderType { + EFILEFOLDER_TYPE_ALWAYS = 1<<0, + EFILEFOLDER_TYPE_ONCLICK = 1<<1, + EFILEFOLDER_TYPE_ONBROWSE = 1<<2, + + EFILEFOLDER_MASK_ALL = 0xff, + EFILEFOLDER_MASK_ONCLICK = EFILEFOLDER_TYPE_ALWAYS + | EFILEFOLDER_TYPE_ONCLICK, + EFILEFOLDER_MASK_ONBROWSE = EFILEFOLDER_TYPE_ALWAYS + | EFILEFOLDER_TYPE_ONCLICK + | EFILEFOLDER_TYPE_ONBROWSE, +}; + /*! \brief Represents a file on a share \sa CFileItemList @@ -175,7 +188,7 @@ public: bool CanQueue() const; void SetCanQueue(bool bYesNo); bool IsParentFolder() const; - bool IsFileFolder() const; + bool IsFileFolder(EFileFolderType types = EFILEFOLDER_MASK_ALL) const; bool IsRemovable() const; bool IsTuxBox() const; bool IsMythTV() const; diff --git a/xbmc/GUIInfoManager.cpp b/xbmc/GUIInfoManager.cpp index f5320ddbdc..0540df8953 100644 --- a/xbmc/GUIInfoManager.cpp +++ b/xbmc/GUIInfoManager.cpp @@ -81,6 +81,7 @@ #include "video/VideoDatabase.h" #include "cores/IPlayer.h" #include "cores/AudioEngine/Utils/AEUtil.h" +#include "cores/VideoRenderers/BaseRenderer.h" #define SYSHEATUPDATEINTERVAL 60000 @@ -199,6 +200,7 @@ const infomap player_labels[] = {{ "hasmedia", PLAYER_HAS_MEDIA }, { "starrating", PLAYER_STAR_RATING }, { "folderpath", PLAYER_PATH }, { "filenameandpath", PLAYER_FILEPATH }, + { "isinternetstream", PLAYER_ISINTERNETSTREAM }, { "pauseenabled", PLAYER_CAN_PAUSE }, { "seekenabled", PLAYER_CAN_SEEK }}; @@ -1339,7 +1341,7 @@ CStdString CGUIInfoManager::GetLabel(int info, int contextWindow, CStdString *fa URIUtils::RemoveExtension(strLabel); break; case WEATHER_PLUGIN: - strLabel = g_guiSettings.GetString("weather.addon"); + strLabel = CSettings::Get().GetString("weather.addon"); break; case SYSTEM_DATE: strLabel = GetDate(); @@ -1412,7 +1414,7 @@ CStdString CGUIInfoManager::GetLabel(int info, int contextWindow, CStdString *fa CEpgInfoTag tag; return m_currentFile->GetPVRChannelInfoTag()->GetEPGNow(tag) ? tag.Title() : - g_guiSettings.GetBool("epg.hidenoinfoavailable") ? + CSettings::Get().GetBool("epg.hidenoinfoavailable") ? StringUtils::EmptyString : g_localizeStrings.Get(19055); // no information available } @@ -1716,7 +1718,7 @@ CStdString CGUIInfoManager::GetLabel(int info, int contextWindow, CStdString *fa return g_localizeStrings.Get(g_windowManager.GetFocusedWindow()); break; case SYSTEM_STARTUP_WINDOW: - strLabel.Format("%i", g_guiSettings.GetInt("lookandfeel.startupwindow")); + strLabel.Format("%i", CSettings::Get().GetInt("lookandfeel.startupwindow")); break; case SYSTEM_CURRENT_CONTROL: { @@ -1760,7 +1762,7 @@ CStdString CGUIInfoManager::GetLabel(int info, int contextWindow, CStdString *fa } break; case SYSTEM_LANGUAGE: - strLabel = g_guiSettings.GetString("locale.language"); + strLabel = CSettings::Get().GetString("locale.language"); break; case SYSTEM_TEMPERATURE_UNITS: strLabel = g_langInfo.GetTempUnitString(); @@ -1774,7 +1776,7 @@ CStdString CGUIInfoManager::GetLabel(int info, int contextWindow, CStdString *fa break; case SYSTEM_FRIENDLY_NAME: { - CStdString friendlyName = g_guiSettings.GetString("services.devicename"); + CStdString friendlyName = CSettings::Get().GetString("services.devicename"); if (friendlyName.Equals("XBMC")) strLabel.Format("%s (%s)", friendlyName.c_str(), g_application.getNetwork().GetHostName().c_str()); else @@ -1783,10 +1785,10 @@ CStdString CGUIInfoManager::GetLabel(int info, int contextWindow, CStdString *fa break; case SKIN_THEME: - strLabel = g_guiSettings.GetString("lookandfeel.skintheme"); + strLabel = CSettings::Get().GetString("lookandfeel.skintheme"); break; case SKIN_COLOUR_THEME: - strLabel = g_guiSettings.GetString("lookandfeel.skincolors"); + strLabel = CSettings::Get().GetString("lookandfeel.skincolors"); break; case SKIN_ASPECT_RATIO: if (g_SkinInfo) @@ -1865,7 +1867,7 @@ CStdString CGUIInfoManager::GetLabel(int info, int contextWindow, CStdString *fa case VISUALISATION_NAME: { AddonPtr addon; - strLabel = g_guiSettings.GetString("musicplayer.visualisation"); + strLabel = CSettings::Get().GetString("musicplayer.visualisation"); if (CAddonMgr::Get().GetAddon(strLabel,addon) && addon) strLabel = addon->Name(); } @@ -2191,7 +2193,7 @@ bool CGUIInfoManager::GetBool(int condition1, int contextWindow, const CGUIListI else if (condition == SYSTEM_ISINHIBIT) bReturn = g_application.IsIdleShutdownInhibited(); else if (condition == SYSTEM_HAS_SHUTDOWN) - bReturn = (g_guiSettings.GetInt("powermanagement.shutdowntime") > 0); + bReturn = (CSettings::Get().GetInt("powermanagement.shutdowntime") > 0); else if (condition == SYSTEM_LOGGEDON) bReturn = !(g_windowManager.GetActiveWindow() == WINDOW_LOGIN_SCREEN); else if (condition == SYSTEM_SHOW_EXIT_BUTTON) @@ -2406,6 +2408,9 @@ bool CGUIInfoManager::GetBool(int condition1, int contextWindow, const CGUIListI case PLAYER_PASSTHROUGH: bReturn = g_application.m_pPlayer && g_application.m_pPlayer->IsPassthrough(); break; + case PLAYER_ISINTERNETSTREAM: + bReturn = m_currentFile && URIUtils::IsInternetStream(m_currentFile->GetPath()); + break; case MUSICPM_ENABLED: bReturn = g_partyModeManager.IsEnabled(); break; @@ -2433,7 +2438,7 @@ bool CGUIInfoManager::GetBool(int condition1, int contextWindow, const CGUIListI } break; case VIDEOPLAYER_USING_OVERLAYS: - bReturn = (g_guiSettings.GetInt("videoplayer.rendermethod") == RENDER_OVERLAYS); + bReturn = (CSettings::Get().GetInt("videoplayer.rendermethod") == RENDER_OVERLAYS); break; case VIDEOPLAYER_ISFULLSCREEN: bReturn = g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO; @@ -2475,7 +2480,7 @@ bool CGUIInfoManager::GetBool(int condition1, int contextWindow, const CGUIListI } break; case VISUALISATION_ENABLED: - bReturn = !g_guiSettings.GetString("musicplayer.visualisation").IsEmpty(); + bReturn = !CSettings::Get().GetString("musicplayer.visualisation").empty(); break; case VIDEOPLAYER_HAS_EPG: if (m_currentFile->HasPVRChannelInfoTag()) @@ -2547,7 +2552,7 @@ bool CGUIInfoManager::GetMultiInfoBool(const GUIInfo &info, int contextWindow, c break; case SKIN_HAS_THEME: { - CStdString theme = g_guiSettings.GetString("lookandfeel.skintheme"); + CStdString theme = CSettings::Get().GetString("lookandfeel.skintheme"); theme.ToLower(); URIUtils::RemoveExtension(theme); bReturn = theme.Equals(m_stringParameters[info.GetData1()]); @@ -2717,7 +2722,7 @@ bool CGUIInfoManager::GetMultiInfoBool(const GUIInfo &info, int contextWindow, c bReturn = g_alarmClock.HasAlarm(m_stringParameters[info.GetData1()]); break; case SYSTEM_GET_BOOL: - bReturn = g_guiSettings.GetBool(m_stringParameters[info.GetData1()]); + bReturn = CSettings::Get().GetBool(m_stringParameters[info.GetData1()]); break; case SYSTEM_HAS_CORE_ID: bReturn = g_cpuInfo.HasCoreId(info.GetData1()); @@ -3583,7 +3588,7 @@ CStdString CGUIInfoManager::GetVideoLabel(int item) case VIDEOPLAYER_ORIGINALTITLE: return tag->GetEPGNow(epgTag) ? epgTag.Title() : - g_guiSettings.GetBool("epg.hidenoinfoavailable") ? + CSettings::Get().GetBool("epg.hidenoinfoavailable") ? StringUtils::EmptyString : g_localizeStrings.Get(19055); // no information available case VIDEOPLAYER_GENRE: @@ -3601,7 +3606,7 @@ CStdString CGUIInfoManager::GetVideoLabel(int item) case VIDEOPLAYER_NEXT_TITLE: return tag->GetEPGNext(epgTag) ? epgTag.Title() : - g_guiSettings.GetBool("epg.hidenoinfoavailable") ? + CSettings::Get().GetBool("epg.hidenoinfoavailable") ? StringUtils::EmptyString : g_localizeStrings.Get(19055); // no information available case VIDEOPLAYER_NEXT_GENRE: @@ -4214,7 +4219,7 @@ CStdString CGUIInfoManager::GetItemLabel(const CFileItem *item, int info, CStdSt CEpgInfoTag epgTag; return item->GetPVRChannelInfoTag()->GetEPGNow(epgTag) ? epgTag.Title() : - g_guiSettings.GetBool("epg.hidenoinfoavailable") ? + CSettings::Get().GetBool("epg.hidenoinfoavailable") ? StringUtils::EmptyString : g_localizeStrings.Get(19055); // no information available } @@ -4450,7 +4455,7 @@ CStdString CGUIInfoManager::GetItemLabel(const CFileItem *item, int info, CStdSt if (item->HasVideoInfoTag()) { if (!(!item->GetVideoInfoTag()->m_strShowTitle.IsEmpty() && item->GetVideoInfoTag()->m_iSeason == -1)) // dont apply to tvshows - if (item->GetVideoInfoTag()->m_playCount == 0 && !g_guiSettings.GetBool("videolibrary.showunwatchedplots")) + if (item->GetVideoInfoTag()->m_playCount == 0 && !CSettings::Get().GetBool("videolibrary.showunwatchedplots")) return g_localizeStrings.Get(20370); return item->GetVideoInfoTag()->m_strPlot; diff --git a/xbmc/GUIInfoManager.h b/xbmc/GUIInfoManager.h index 42b0aef46d..e281c84f69 100644 --- a/xbmc/GUIInfoManager.h +++ b/xbmc/GUIInfoManager.h @@ -109,6 +109,7 @@ namespace INFO #define PLAYER_CAN_SEEK 51 #define PLAYER_START_TIME 52 #define PLAYER_TITLE 53 +#define PLAYER_ISINTERNETSTREAM 54 #define WEATHER_CONDITIONS 100 #define WEATHER_TEMPERATURE 101 @@ -486,7 +487,7 @@ namespace INFO #define VERSION_MAJOR 13 #define VERSION_MINOR 0 -#define VERSION_TAG "-ALPHA3" +#define VERSION_TAG "-ALPHA4" #define LISTITEM_START 35000 #define LISTITEM_THUMB (LISTITEM_START) diff --git a/xbmc/GUILargeTextureManager.cpp b/xbmc/GUILargeTextureManager.cpp index dca794f524..bc66088c5b 100644 --- a/xbmc/GUILargeTextureManager.cpp +++ b/xbmc/GUILargeTextureManager.cpp @@ -20,7 +20,7 @@ #include "threads/SystemClock.h" #include "GUILargeTextureManager.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "guilib/Texture.h" #include "threads/SingleLock.h" #include "utils/TimeUtils.h" @@ -61,7 +61,7 @@ bool CImageLoader::DoWork() { // direct route - load the image unsigned int start = XbmcThreads::SystemClockMillis(); - m_texture = CBaseTexture::LoadFromFile(loadPath, g_graphicsContext.GetWidth(), g_graphicsContext.GetHeight(), g_guiSettings.GetBool("pictures.useexifrotation")); + m_texture = CBaseTexture::LoadFromFile(loadPath, g_graphicsContext.GetWidth(), g_graphicsContext.GetHeight(), CSettings::Get().GetBool("pictures.useexifrotation")); if (!m_texture) return false; if (XbmcThreads::SystemClockMillis() - start > 100) diff --git a/xbmc/GUIPassword.cpp b/xbmc/GUIPassword.cpp index 161edffcd9..778f362b79 100644 --- a/xbmc/GUIPassword.cpp +++ b/xbmc/GUIPassword.cpp @@ -29,8 +29,8 @@ #include "profiles/dialogs/GUIDialogLockSettings.h" #include "profiles/dialogs/GUIDialogProfileSettings.h" #include "Util.h" -#include "settings/GUISettings.h" #include "settings/MediaSourceSettings.h" +#include "settings/Settings.h" #include "guilib/GUIWindowManager.h" #include "FileItem.h" #include "guilib/LocalizeStrings.h" @@ -65,7 +65,7 @@ bool CGUIPassword::IsItemUnlocked(CFileItem* pItem, const CStdString &strType) } else { - if (0 != g_guiSettings.GetInt("masterlock.maxretries") && pItem->m_iBadPwdCount >= g_guiSettings.GetInt("masterlock.maxretries")) + if (0 != CSettings::Get().GetInt("masterlock.maxretries") && pItem->m_iBadPwdCount >= CSettings::Get().GetInt("masterlock.maxretries")) { // user previously exhausted all retries, show access denied error CGUIDialogOK::ShowAndGetInput(12345, 12346, 0, 0); return false; @@ -100,7 +100,7 @@ bool CGUIPassword::IsItemUnlocked(CFileItem* pItem, const CStdString &strType) case 1: { // password entry failed - if (0 != g_guiSettings.GetInt("masterlock.maxretries")) + if (0 != CSettings::Get().GetInt("masterlock.maxretries")) pItem->m_iBadPwdCount++; sprintf(buffer,"%i",pItem->m_iBadPwdCount); CMediaSourceSettings::Get().UpdateSource(strType, strLabel, "badpwdcount", buffer); @@ -124,7 +124,7 @@ bool CGUIPassword::CheckStartUpLock() int iVerifyPasswordResult = -1; CStdString strHeader = g_localizeStrings.Get(20075); if (iMasterLockRetriesLeft == -1) - iMasterLockRetriesLeft = g_guiSettings.GetInt("masterlock.maxretries"); + iMasterLockRetriesLeft = CSettings::Get().GetInt("masterlock.maxretries"); if (g_passwordManager.iMasterLockRetriesLeft == 0) g_passwordManager.iMasterLockRetriesLeft = 1; CStdString strPassword = CProfilesManager::Get().GetMasterProfile().getLockCode(); if (CProfilesManager::Get().GetMasterProfile().getLockMode() == 0) @@ -151,7 +151,7 @@ bool CGUIPassword::CheckStartUpLock() if (iVerifyPasswordResult == 0) { - g_passwordManager.iMasterLockRetriesLeft = g_guiSettings.GetInt("masterlock.maxretries"); + g_passwordManager.iMasterLockRetriesLeft = CSettings::Get().GetInt("masterlock.maxretries"); return true; // OK The MasterCode Accepted! XBMC Can Run! } else @@ -227,7 +227,7 @@ bool CGUIPassword::IsMasterLockUnlocked(bool bPromptUser, bool& bCanceled) { bCanceled = false; if (iMasterLockRetriesLeft == -1) - iMasterLockRetriesLeft = g_guiSettings.GetInt("masterlock.maxretries"); + iMasterLockRetriesLeft = CSettings::Get().GetInt("masterlock.maxretries"); if ((LOCK_MODE_EVERYONE < CProfilesManager::Get().GetMasterProfile().getLockMode() && !bMasterUser) && !bPromptUser) // not unlocked, but calling code doesn't want to prompt user return false; @@ -267,7 +267,7 @@ void CGUIPassword::UpdateMasterLockRetryCount(bool bResetCount) if (!bResetCount) { // Bad mastercode entered - if (0 < g_guiSettings.GetInt("masterlock.maxretries")) + if (0 < CSettings::Get().GetInt("masterlock.maxretries")) { // We're keeping track of how many bad passwords are entered if (1 < g_passwordManager.iMasterLockRetriesLeft) @@ -290,7 +290,7 @@ void CGUIPassword::UpdateMasterLockRetryCount(bool bResetCount) CGUIDialogOK::ShowAndGetInput(20075, 12345, dlgLine1, 0); } else - g_passwordManager.iMasterLockRetriesLeft = g_guiSettings.GetInt("masterlock.maxretries"); // user entered correct mastercode, reset retries to max allowed + g_passwordManager.iMasterLockRetriesLeft = CSettings::Get().GetInt("masterlock.maxretries"); // user entered correct mastercode, reset retries to max allowed } bool CGUIPassword::CheckLock(LockType btnType, const CStdString& strPassword, int iHeading) @@ -454,6 +454,16 @@ bool CGUIPassword::IsDatabasePathUnlocked(const CStdString& strPath, VECSOURCES& return false; } +void CGUIPassword::OnSettingAction(const CSetting *setting) +{ + if (setting == NULL) + return; + + const std::string &settingId = setting->GetId(); + if (settingId == "masterlock.lockcode") + SetMasterLockMode(); +} + int CGUIPassword::VerifyPassword(LockType btnType, const CStdString& strPassword, const CStdString& strHeading) { int iVerifyPasswordResult; diff --git a/xbmc/GUIPassword.h b/xbmc/GUIPassword.h index 09a4144c1f..7719dd9992 100644 --- a/xbmc/GUIPassword.h +++ b/xbmc/GUIPassword.h @@ -20,14 +20,15 @@ * */ +#include <map> +#include <vector> + +#include "settings/ISettingCallback.h" #include "utils/StdString.h" class CFileItem; class CMediaSource; -#include <vector> -#include <map> - typedef std::vector<CMediaSource> VECSOURCES; typedef enum @@ -41,7 +42,7 @@ typedef enum LOCK_MODE_EEPROM_PARENTAL = 5 } LockType; -class CGUIPassword +class CGUIPassword : public ISettingCallback { public: CGUIPassword(void); @@ -64,6 +65,8 @@ public: void RemoveSourceLocks(); bool IsDatabasePathUnlocked(const CStdString& strPath, VECSOURCES& vecSources); + virtual void OnSettingAction(const CSetting *setting); + bool bMasterUser; int iMasterLockRetriesLeft; diff --git a/xbmc/GUIUserMessages.h b/xbmc/GUIUserMessages.h index ad267cc903..e097fedb0a 100644 --- a/xbmc/GUIUserMessages.h +++ b/xbmc/GUIUserMessages.h @@ -129,3 +129,6 @@ // Sent to the AddonSetting dialogs from addons if they updated a setting #define GUI_MSG_SETTING_UPDATED GUI_MSG_USER + 35 + +// Message sent to CGUIWindowSlideshow to show picture +#define GUI_MSG_SHOW_PICTURE GUI_MSG_USER + 36 diff --git a/xbmc/LangInfo.cpp b/xbmc/LangInfo.cpp index d60314ef2e..2b1373199d 100644 --- a/xbmc/LangInfo.cpp +++ b/xbmc/LangInfo.cpp @@ -19,14 +19,24 @@ */ #include "LangInfo.h" -#include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" +#include "Application.h" +#include "FileItem.h" +#include "Util.h" +#include "filesystem/Directory.h" +#include "guilib/GUIFontManager.h" #include "guilib/LocalizeStrings.h" +#include "pvr/PVRManager.h" +#include "settings/AdvancedSettings.h" +#include "settings/Settings.h" +#include "utils/CharsetConverter.h" #include "utils/log.h" -#include "utils/XBMCTinyXML.h" #include "utils/LangCodeExpander.h" +#include "utils/StringUtils.h" +#include "utils/Weather.h" +#include "utils/XBMCTinyXML.h" using namespace std; +using namespace PVR; #define TEMP_UNIT_STRINGS 20027 @@ -195,6 +205,28 @@ CLangInfo::~CLangInfo() { } +void CLangInfo::OnSettingChanged(const CSetting *setting) +{ + if (setting == NULL) + return; + + const std::string &settingId = setting->GetId(); + if (settingId == "locale.audiolanguage") + SetAudioLanguage(((CSettingString*)setting)->GetValue()); + else if (settingId == "locale.subtitlelanguage") + SetSubtitleLanguage(((CSettingString*)setting)->GetValue()); + else if (settingId == "locale.language") + { + if (!SetLanguage(((CSettingString*)setting)->GetValue())) + ((CSettingString*)CSettings::Get().GetSetting("locale.language"))->Reset(); + } + else if (settingId == "locale.country") + { + g_langInfo.SetCurrentRegion(((CSettingString*)setting)->GetValue()); + g_weatherManager.Refresh(); // need to reset our weather, as temperatures need re-translating. + } +} + bool CLangInfo::Load(const CStdString& strFileName) { SetDefaults(); @@ -328,7 +360,7 @@ bool CLangInfo::Load(const CStdString& strFileName) pRegion=pRegion->NextSiblingElement("region"); } - const CStdString& strName=g_guiSettings.GetString("locale.country"); + const CStdString& strName=CSettings::Get().GetString("locale.country"); SetCurrentRegion(strName); } @@ -376,7 +408,7 @@ void CLangInfo::SetDefaults() CStdString CLangInfo::GetGuiCharSet() const { CStdString strCharSet; - strCharSet=g_guiSettings.GetString("locale.charset"); + strCharSet=CSettings::Get().GetString("locale.charset"); if (strCharSet=="DEFAULT") strCharSet=m_currentRegion->m_strGuiCharSet; @@ -385,13 +417,40 @@ CStdString CLangInfo::GetGuiCharSet() const CStdString CLangInfo::GetSubtitleCharSet() const { - CStdString strCharSet=g_guiSettings.GetString("subtitles.charset"); + CStdString strCharSet=CSettings::Get().GetString("subtitles.charset"); if (strCharSet=="DEFAULT") strCharSet=m_currentRegion->m_strSubtitleCharSet; return strCharSet; } +bool CLangInfo::SetLanguage(const std::string &strLanguage) +{ + string strLangInfoPath = StringUtils::Format("special://xbmc/language/%s/langinfo.xml", strLanguage.c_str()); + if (!g_langInfo.Load(strLangInfoPath)) + return false; + + if (ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode()) + { + CLog::Log(LOGINFO, "Language needs a ttf font, loading first ttf font available"); + CStdString strFontSet; + if (!g_fontManager.GetFirstFontSetUnicode(strFontSet)) + CLog::Log(LOGERROR, "No ttf font found but needed: %s", strFontSet.c_str()); + } + + g_charsetConverter.reset(); + + if (!g_localizeStrings.Load("special://xbmc/language/", strLanguage)) + return false; + + // also tell our weather and skin to reload as these are localized + g_weatherManager.Refresh(); + g_PVRManager.LocalizationChanged(); + g_application.ReloadSkin(); + + return true; +} + // three char language code (not win32 specific) const CStdString& CLangInfo::GetAudioLanguage() const { @@ -530,3 +589,64 @@ const CStdString& CLangInfo::GetSpeedUnitString() const { return g_localizeStrings.Get(SPEED_UNIT_STRINGS+m_currentRegion->m_speedUnit); } + +void CLangInfo::SettingOptionsLanguagesFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t) +{ + SettingOptionsLanguagesFillerGeneral(setting, list, current); +} + +void CLangInfo::SettingOptionsStreamLanguagesFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t) +{ + vector<string> languages; + languages.push_back(g_localizeStrings.Get(308)); + languages.push_back(g_localizeStrings.Get(309)); + vector<string> languageKeys; + languageKeys.push_back("original"); + languageKeys.push_back("default"); + SettingOptionsLanguagesFillerGeneral(setting, list, current, languages, languageKeys); +} + +void CLangInfo::SettingOptionsRegionsFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t) +{ + CStdStringArray regions; + g_langInfo.GetRegionNames(regions); + sort(regions.begin(), regions.end(), sortstringbyname()); + + for (unsigned int i = 0; i < regions.size(); ++i) + list.push_back(make_pair(regions[i], regions[i])); +} + +void CLangInfo::SettingOptionsLanguagesFillerGeneral(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t, + const std::vector<std::string> &languages /* = std::vector<std::string>() */, + const std::vector<std::string> &languageKeys /* = std::vector<std::string>() */) +{ + //find languages... + CFileItemList items; + XFILE::CDirectory::GetDirectory("special://xbmc/language/", items); + + vector<string> vecLanguage; + for (int i = 0; i < items.Size(); ++i) + { + CFileItemPtr pItem = items[i]; + if (pItem->m_bIsFolder) + { + if (StringUtils::EqualsNoCase(pItem->GetLabel(), ".svn") || + StringUtils::EqualsNoCase(pItem->GetLabel(), "fonts") || + StringUtils::EqualsNoCase(pItem->GetLabel(), "media")) + continue; + + vecLanguage.push_back(pItem->GetLabel()); + } + } + + sort(vecLanguage.begin(), vecLanguage.end(), sortstringbyname()); + // Add language options passed by parameter at the beginning + if (languages.size() > 0) + { + for (unsigned int i = 0; i < languages.size(); ++i) + list.push_back(make_pair(languages[i], languageKeys[i])); + } + + for (unsigned int i = 0; i < vecLanguage.size(); ++i) + list.push_back(make_pair(vecLanguage[i], vecLanguage[i])); +} diff --git a/xbmc/LangInfo.h b/xbmc/LangInfo.h index 61e7160f47..1281c1ed86 100644 --- a/xbmc/LangInfo.h +++ b/xbmc/LangInfo.h @@ -19,18 +19,21 @@ * */ +#include "settings/ISettingCallback.h" #include "utils/StdString.h" #include <map> class TiXmlNode; -class CLangInfo +class CLangInfo : public ISettingCallback { public: CLangInfo(); virtual ~CLangInfo(); + virtual void OnSettingChanged(const CSetting *setting); + bool Load(const CStdString& strFileName); CStdString GetGuiCharSet() const; @@ -39,6 +42,8 @@ public: // three char language code (not win32 specific) const CStdString& GetLanguageCode() const { return m_languageCodeGeneral; } + bool SetLanguage(const std::string &strLanguage); + const CStdString& GetAudioLanguage() const; // language can either be a two char language code as defined in ISO639 // or a three char language code @@ -114,11 +119,20 @@ public: const CStdString& GetCurrentRegion() const; static void LoadTokens(const TiXmlNode* pTokens, std::vector<CStdString>& vecTokens); + + static void SettingOptionsLanguagesFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t); + static void SettingOptionsStreamLanguagesFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t); + static void SettingOptionsRegionsFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t); + protected: void SetDefaults(); protected: + static void SettingOptionsLanguagesFillerGeneral(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t, + const std::vector<std::string> &languages = std::vector<std::string>(), + const std::vector<std::string> &languageKeys = std::vector<std::string>()); + class CRegion { public: diff --git a/xbmc/Makefile.in b/xbmc/Makefile.in index 1a995f779a..5a9bd6b178 100644 --- a/xbmc/Makefile.in +++ b/xbmc/Makefile.in @@ -10,10 +10,10 @@ SRCS=Application.cpp \ DynamicDll.cpp \ Favourites.cpp \ FileItem.cpp \ - LangInfo.cpp \ GUIInfoManager.cpp \ GUILargeTextureManager.cpp \ GUIPassword.cpp \ + LangInfo.cpp \ MediaSource.cpp \ NfoFile.cpp \ PasswordManager.cpp \ diff --git a/xbmc/NfoFile.cpp b/xbmc/NfoFile.cpp index f91367e064..791c92e49b 100644 --- a/xbmc/NfoFile.cpp +++ b/xbmc/NfoFile.cpp @@ -25,11 +25,10 @@ #include "video/VideoInfoDownloader.h" #include "addons/AddonManager.h" #include "filesystem/File.h" -#include "settings/GUISettings.h" #include "FileItem.h" #include "music/Album.h" #include "music/Artist.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "utils/log.h" #include <vector> @@ -72,6 +71,7 @@ CNfoFile::NFOResult CNfoFile::Create(const CStdString& strPath, const ScraperPtr { int infos=0; m_headofdoc = strstr(m_headofdoc,"<episodedetails"); + bNfo = GetDetails(details); while (m_headofdoc && details.m_iEpisode != episode) { m_headofdoc = strstr(m_headofdoc+1,"<episodedetails"); diff --git a/xbmc/PlayListPlayer.cpp b/xbmc/PlayListPlayer.cpp index b6adb28f63..baa20b5361 100644 --- a/xbmc/PlayListPlayer.cpp +++ b/xbmc/PlayListPlayer.cpp @@ -258,7 +258,10 @@ bool CPlayListPlayer::Play(int iSong, bool bAutoPlay /* = false */, bool bPlayPr m_bPlaybackStarted = false; unsigned int playAttempt = XbmcThreads::SystemClockMillis(); - if (!g_application.PlayFile(*item, bAutoPlay)) + PlayBackRet ret = g_application.PlayFile(*item, bAutoPlay); + if (ret == PLAYBACK_CANCELED) + return false; + if (ret == PLAYBACK_FAIL) { CLog::Log(LOGERROR,"Playlist Player: skipping unplayable item: %i, path [%s]", m_iCurrentSong, item->GetPath().c_str()); playlist.SetUnPlayable(m_iCurrentSong); diff --git a/xbmc/SystemGlobals.cpp b/xbmc/SystemGlobals.cpp index 758e763a39..987b7b7657 100644 --- a/xbmc/SystemGlobals.cpp +++ b/xbmc/SystemGlobals.cpp @@ -23,8 +23,6 @@ #include "Application.h" #include "GUILargeTextureManager.h" #include "guilib/TextureManager.h" -#include "settings/GUISettings.h" -#include "settings/Settings.h" #include "utils/AlarmClock.h" #include "utils/DownloadQueueManager.h" #include "GUIInfoManager.h" @@ -55,8 +53,6 @@ #include "linux/RBP.h" #endif - CSettings g_settings; - CXBMCRenderManager g_renderManager; CLangInfo g_langInfo; CLangCodeExpander g_LangCodeExpander; diff --git a/xbmc/TextureCacheJob.cpp b/xbmc/TextureCacheJob.cpp index 6f062c1a4a..cffc70d8be 100644 --- a/xbmc/TextureCacheJob.cpp +++ b/xbmc/TextureCacheJob.cpp @@ -23,7 +23,7 @@ #include "guilib/Texture.h" #include "guilib/DDSImage.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "utils/log.h" #include "filesystem/File.h" #include "pictures/Picture.h" @@ -177,7 +177,7 @@ CBaseTexture *CTextureCacheJob::LoadImage(const CStdString &image, unsigned int && !file.GetMimeType().Left(6).Equals("image/") && !file.GetMimeType().Equals("application/octet-stream")) // ignore non-pictures return NULL; - CBaseTexture *texture = CBaseTexture::LoadFromFile(image, width, height, g_guiSettings.GetBool("pictures.useexifrotation")); + CBaseTexture *texture = CBaseTexture::LoadFromFile(image, width, height, CSettings::Get().GetBool("pictures.useexifrotation")); if (!texture) return NULL; diff --git a/xbmc/Util.cpp b/xbmc/Util.cpp index 3b670c877b..7bb8d3c6eb 100644 --- a/xbmc/Util.cpp +++ b/xbmc/Util.cpp @@ -59,7 +59,6 @@ #endif #include "profiles/ProfilesManager.h" #include "utils/RegExp.h" -#include "settings/GUISettings.h" #include "guilib/GraphicContext.h" #include "guilib/TextureManager.h" #include "utils/fstrcmp.h" @@ -74,6 +73,7 @@ #endif #include "GUIUserMessages.h" #include "filesystem/File.h" +#include "settings/MediaSettings.h" #include "settings/Settings.h" #include "utils/StringUtils.h" #include "settings/AdvancedSettings.h" @@ -220,7 +220,7 @@ CStdString CUtil::GetTitleFromPath(const CStdString& strFileNameAndPath, bool bI strFilename = URIUtils::GetFileName(url.GetHostName()); // now remove the extension if needed - if (!g_guiSettings.GetBool("filelists.showextensions") && !bIsFolder) + if (!CSettings::Get().GetBool("filelists.showextensions") && !bIsFolder) { URIUtils::RemoveExtension(strFilename); return strFilename; @@ -1029,7 +1029,7 @@ CStdString CUtil::ValidatePath(const CStdString &path, bool bFixDoubleSlashes /* bool CUtil::IsUsingTTFSubtitles() { - return URIUtils::GetExtension(g_guiSettings.GetString("subtitles.font")).Equals(".ttf"); + return URIUtils::GetExtension(CSettings::Get().GetString("subtitles.font")).Equals(".ttf"); } #ifdef UNIT_TESTING @@ -1318,56 +1318,49 @@ int CUtil::GetMatchingSource(const CStdString& strPath1, VECSOURCES& VECSOURCES, CStdString CUtil::TranslateSpecialSource(const CStdString &strSpecial) { - CStdString strReturn=strSpecial; if (!strSpecial.IsEmpty() && strSpecial[0] == '$') { if (strSpecial.Left(5).Equals("$HOME")) - URIUtils::AddFileToFolder("special://home/", strSpecial.Mid(5), strReturn); + return URIUtils::AddFileToFolder("special://home/", strSpecial.Mid(5)); else if (strSpecial.Left(10).Equals("$SUBTITLES")) - URIUtils::AddFileToFolder("special://subtitles/", strSpecial.Mid(10), strReturn); + return URIUtils::AddFileToFolder("special://subtitles/", strSpecial.Mid(10)); else if (strSpecial.Left(9).Equals("$USERDATA")) - URIUtils::AddFileToFolder("special://userdata/", strSpecial.Mid(9), strReturn); + return URIUtils::AddFileToFolder("special://userdata/", strSpecial.Mid(9)); else if (strSpecial.Left(9).Equals("$DATABASE")) - URIUtils::AddFileToFolder("special://database/", strSpecial.Mid(9), strReturn); + return URIUtils::AddFileToFolder("special://database/", strSpecial.Mid(9)); else if (strSpecial.Left(11).Equals("$THUMBNAILS")) - URIUtils::AddFileToFolder("special://thumbnails/", strSpecial.Mid(11), strReturn); + return URIUtils::AddFileToFolder("special://thumbnails/", strSpecial.Mid(11)); else if (strSpecial.Left(11).Equals("$RECORDINGS")) - URIUtils::AddFileToFolder("special://recordings/", strSpecial.Mid(11), strReturn); + return URIUtils::AddFileToFolder("special://recordings/", strSpecial.Mid(11)); else if (strSpecial.Left(12).Equals("$SCREENSHOTS")) - URIUtils::AddFileToFolder("special://screenshots/", strSpecial.Mid(12), strReturn); + return URIUtils::AddFileToFolder("special://screenshots/", strSpecial.Mid(12)); else if (strSpecial.Left(15).Equals("$MUSICPLAYLISTS")) - URIUtils::AddFileToFolder("special://musicplaylists/", strSpecial.Mid(15), strReturn); + return URIUtils::AddFileToFolder("special://musicplaylists/", strSpecial.Mid(15)); else if (strSpecial.Left(15).Equals("$VIDEOPLAYLISTS")) - URIUtils::AddFileToFolder("special://videoplaylists/", strSpecial.Mid(15), strReturn); + return URIUtils::AddFileToFolder("special://videoplaylists/", strSpecial.Mid(15)); else if (strSpecial.Left(7).Equals("$CDRIPS")) - URIUtils::AddFileToFolder("special://cdrips/", strSpecial.Mid(7), strReturn); + return URIUtils::AddFileToFolder("special://cdrips/", strSpecial.Mid(7)); // this one will be removed post 2.0 else if (strSpecial.Left(10).Equals("$PLAYLISTS")) - URIUtils::AddFileToFolder(g_guiSettings.GetString("system.playlistspath",false), strSpecial.Mid(10), strReturn); + return URIUtils::AddFileToFolder(CSettings::Get().GetString("system.playlistspath"), strSpecial.Mid(10)); } - return strReturn; + return strSpecial; } CStdString CUtil::MusicPlaylistsLocation() { vector<CStdString> vec; - CStdString strReturn; - URIUtils::AddFileToFolder(g_guiSettings.GetString("system.playlistspath"), "music", strReturn); - vec.push_back(strReturn); - URIUtils::AddFileToFolder(g_guiSettings.GetString("system.playlistspath"), "mixed", strReturn); - vec.push_back(strReturn); - return XFILE::CMultiPathDirectory::ConstructMultiPath(vec);; + vec.push_back(URIUtils::AddFileToFolder(CSettings::Get().GetString("system.playlistspath"), "music")); + vec.push_back(URIUtils::AddFileToFolder(CSettings::Get().GetString("system.playlistspath"), "mixed")); + return XFILE::CMultiPathDirectory::ConstructMultiPath(vec); } CStdString CUtil::VideoPlaylistsLocation() { vector<CStdString> vec; - CStdString strReturn; - URIUtils::AddFileToFolder(g_guiSettings.GetString("system.playlistspath"), "video", strReturn); - vec.push_back(strReturn); - URIUtils::AddFileToFolder(g_guiSettings.GetString("system.playlistspath"), "mixed", strReturn); - vec.push_back(strReturn); - return XFILE::CMultiPathDirectory::ConstructMultiPath(vec);; + vec.push_back(URIUtils::AddFileToFolder(CSettings::Get().GetString("system.playlistspath"), "video")); + vec.push_back(URIUtils::AddFileToFolder(CSettings::Get().GetString("system.playlistspath"), "mixed")); + return XFILE::CMultiPathDirectory::ConstructMultiPath(vec); } void CUtil::DeleteMusicDatabaseDirectoryCache() @@ -1568,8 +1561,7 @@ CStdString CUtil::GetDefaultFolderThumb(const CStdString &folderThumb) void CUtil::GetSkinThemes(vector<CStdString>& vecTheme) { - CStdString strPath; - URIUtils::AddFileToFolder(g_graphicsContext.GetMediaDir(),"media",strPath); + CStdString strPath = URIUtils::AddFileToFolder(g_graphicsContext.GetMediaDir(), "media"); CFileItemList items; CDirectory::GetDirectory(strPath, items); // Search for Themes in the Current skin! @@ -1912,14 +1904,14 @@ void CUtil::ScanForExternalSubtitles(const CStdString& strMovie, std::vector<CSt CStdString strMovieFileNameNoExt(URIUtils::ReplaceExtension(strMovieFileName, "")); strLookInPaths.push_back(strPath); - if (!CMediaSettings::Get().GetAdditionalSubtitleDirectoryChecked() && !g_guiSettings.GetString("subtitles.custompath").IsEmpty()) // to avoid checking non-existent directories (network) every time.. + if (!CMediaSettings::Get().GetAdditionalSubtitleDirectoryChecked() && !CSettings::Get().GetString("subtitles.custompath").empty()) // to avoid checking non-existent directories (network) every time.. { - if (!g_application.getNetwork().IsAvailable() && !URIUtils::IsHD(g_guiSettings.GetString("subtitles.custompath"))) + if (!g_application.getNetwork().IsAvailable() && !URIUtils::IsHD(CSettings::Get().GetString("subtitles.custompath"))) { CLog::Log(LOGINFO,"CUtil::CacheSubtitles: disabling alternate subtitle directory for this session, it's nonaccessible"); CMediaSettings::Get().SetAdditionalSubtitleDirectoryChecked(-1); // disabled } - else if (!CDirectory::Exists(g_guiSettings.GetString("subtitles.custompath"))) + else if (!CDirectory::Exists(CSettings::Get().GetString("subtitles.custompath"))) { CLog::Log(LOGINFO,"CUtil::CacheSubtitles: disabling alternate subtitle directory for this session, it's nonexistant"); CMediaSettings::Get().SetAdditionalSubtitleDirectoryChecked(-1); // disabled @@ -1993,7 +1985,7 @@ void CUtil::ScanForExternalSubtitles(const CStdString& strMovie, std::vector<CSt // this is last because we dont want to check any common subdirs or cd-dirs in the alternate <subtitles> dir. if (CMediaSettings::Get().GetAdditionalSubtitleDirectoryChecked() == 1) { - strPath = g_guiSettings.GetString("subtitles.custompath"); + strPath = CSettings::Get().GetString("subtitles.custompath"); URIUtils::AddSlashAtEnd(strPath); strLookInPaths.push_back(strPath); } @@ -2241,6 +2233,20 @@ bool CUtil::CanBindPrivileged() #endif //_LINUX } +bool CUtil::ValidatePort(int port) +{ + // check that it's a valid port +#ifdef _LINUX + if (!CUtil::CanBindPrivileged() && (port < 1024 || port > 65535)) + return false; + else +#endif + if (port <= 0 || port > 65535) + return false; + + return true; +} + int CUtil::GetRandomNumber() { #ifdef TARGET_WINDOWS diff --git a/xbmc/Util.h b/xbmc/Util.h index e9f1715d5f..6a902cab37 100644 --- a/xbmc/Util.h +++ b/xbmc/Util.h @@ -197,6 +197,7 @@ public: static CStdString GetFrameworksPath(bool forPython = false); static bool CanBindPrivileged(); + static bool ValidatePort(int port); /*! * \brief Thread-safe random number generation diff --git a/xbmc/addons/Addon.cpp b/xbmc/addons/Addon.cpp index 1fbc27463b..cb1290062c 100644 --- a/xbmc/addons/Addon.cpp +++ b/xbmc/addons/Addon.cpp @@ -20,7 +20,7 @@ #include "Addon.h" #include "AddonManager.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "filesystem/Directory.h" #include "filesystem/File.h" #include "interfaces/python/XBPython.h" @@ -252,7 +252,7 @@ CAddon::CAddon(const cp_extension_t *ext) { BuildLibName(ext); BuildProfilePath(); - URIUtils::AddFileToFolder(Profile(), "settings.xml", m_userSettingsPath); + m_userSettingsPath = URIUtils::AddFileToFolder(Profile(), "settings.xml"); m_enabled = true; m_hasSettings = true; m_hasStrings = false; @@ -280,7 +280,7 @@ CAddon::CAddon(const AddonProps &props) if (props.libname.IsEmpty()) BuildLibName(); else m_strLibName = props.libname; BuildProfilePath(); - URIUtils::AddFileToFolder(Profile(), "settings.xml", m_userSettingsPath); + m_userSettingsPath = URIUtils::AddFileToFolder(Profile(), "settings.xml"); m_enabled = true; m_hasSettings = true; m_hasStrings = false; @@ -299,7 +299,7 @@ CAddon::CAddon(const CAddon &rhs, const AddonPtr &parent) m_userSettingsLoaded = rhs.m_userSettingsLoaded; m_hasSettings = rhs.m_hasSettings; BuildProfilePath(); - URIUtils::AddFileToFolder(Profile(), "settings.xml", m_userSettingsPath); + m_userSettingsPath = URIUtils::AddFileToFolder(Profile(), "settings.xml"); m_strLibName = rhs.m_strLibName; m_enabled = rhs.Enabled(); m_hasStrings = false; @@ -411,7 +411,7 @@ bool CAddon::LoadStrings() // Path where the language strings reside CStdString chosenPath = URIUtils::AddFileToFolder(m_props.path, "resources/language/"); - m_hasStrings = m_strings.Load(chosenPath, g_guiSettings.GetString("locale.language")); + m_hasStrings = m_strings.Load(chosenPath, CSettings::Get().GetString("locale.language")); return m_checkedStrings = true; } diff --git a/xbmc/addons/Addon.h b/xbmc/addons/Addon.h index dac880ef94..e3ba9af0e2 100644 --- a/xbmc/addons/Addon.h +++ b/xbmc/addons/Addon.h @@ -107,7 +107,7 @@ public: \return true if the addon has settings, false otherwise \sa LoadSettings, LoadUserSettings, SaveSettings, HasUserSettings, GetSetting, UpdateSetting */ - bool HasSettings(); + virtual bool HasSettings(); /*! \brief Check whether the user has configured this addon or not \return true if previously saved settings are found, false otherwise diff --git a/xbmc/addons/AddonCallbacksGUI.cpp b/xbmc/addons/AddonCallbacksGUI.cpp index ddbf3f6205..3d14a2441c 100644 --- a/xbmc/addons/AddonCallbacksGUI.cpp +++ b/xbmc/addons/AddonCallbacksGUI.cpp @@ -31,7 +31,6 @@ #include "guilib/GUIWindowManager.h" #include "guilib/Key.h" #include "guilib/TextureManager.h" -#include "settings/GUISettings.h" #include "guilib/GUISpinControlEx.h" #include "guilib/GUIRadioButtonControl.h" #include "guilib/GUISettingsSliderControl.h" @@ -188,10 +187,9 @@ GUIHANDLE CAddonCallbacksGUI::Window_New(void *addonData, const char *xmlFilenam if (!XFILE::CFile::Exists(strSkinPath)) { /* Check for the matching folder for the skin in the fallback skins folder */ - CStdString basePath; - URIUtils::AddFileToFolder(guiHelper->m_addon->Path(), "resources", basePath); - URIUtils::AddFileToFolder(basePath, "skins", basePath); - URIUtils::AddFileToFolder(basePath, URIUtils::GetFileName(g_SkinInfo->Path()), basePath); + CStdString basePath = URIUtils::AddFileToFolder(guiHelper->m_addon->Path(), "resources"); + basePath = URIUtils::AddFileToFolder(basePath, "skins"); + basePath = URIUtils::AddFileToFolder(basePath, URIUtils::GetFileName(g_SkinInfo->Path())); strSkinPath = g_SkinInfo->GetSkinPath(xmlFilename, &res, basePath); if (!XFILE::CFile::Exists(strSkinPath)) { @@ -207,10 +205,9 @@ GUIHANDLE CAddonCallbacksGUI::Window_New(void *addonData, const char *xmlFilenam //FIXME make this static method of current skin? CStdString str("none"); AddonProps props(str, ADDON_SKIN, str, str); - CStdString basePath; - URIUtils::AddFileToFolder(guiHelper->m_addon->Path(), "resources", basePath); - URIUtils::AddFileToFolder(basePath, "skins", basePath); - URIUtils::AddFileToFolder(basePath, defaultSkin, basePath); + CStdString basePath = URIUtils::AddFileToFolder(guiHelper->m_addon->Path(), "resources"); + basePath = URIUtils::AddFileToFolder(basePath, "skins"); + basePath = URIUtils::AddFileToFolder(basePath, defaultSkin); props.path = basePath; CSkinInfo skinInfo(props); diff --git a/xbmc/addons/AddonInstaller.cpp b/xbmc/addons/AddonInstaller.cpp index 7c42632051..2338b1d5ac 100644 --- a/xbmc/addons/AddonInstaller.cpp +++ b/xbmc/addons/AddonInstaller.cpp @@ -27,7 +27,7 @@ #include "guilib/LocalizeStrings.h" #include "filesystem/Directory.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "ApplicationMessenger.h" #include "Favourites.h" #include "utils/JobManager.h" @@ -553,7 +553,7 @@ bool CAddonInstallJob::DownloadPackage(const CStdString &path, const CStdString bool CAddonInstallJob::OnPreInstall() { // check whether this is an active skin - we need to unload it if so - if (g_guiSettings.GetString("lookandfeel.skin") == m_addon->ID()) + if (CSettings::Get().GetString("lookandfeel.skin") == m_addon->ID()) { CApplicationMessenger::Get().ExecBuiltIn("UnloadSkin", true); return true; @@ -654,7 +654,7 @@ bool CAddonInstallJob::Install(const CStdString &installFrom) void CAddonInstallJob::OnPostInstall(bool reloadAddon) { - if (m_addon->Type() < ADDON_VIZ_LIBRARY && g_guiSettings.GetBool("general.addonnotifications")) + if (m_addon->Type() < ADDON_VIZ_LIBRARY && CSettings::Get().GetBool("general.addonnotifications")) { CGUIDialogKaiToast::QueueNotification(m_addon->Icon(), m_addon->Name(), @@ -667,7 +667,7 @@ void CAddonInstallJob::OnPostInstall(bool reloadAddon) if (reloadAddon || (!m_update && CGUIDialogYesNo::ShowAndGetInput(m_addon->Name(), g_localizeStrings.Get(24099),"",""))) { - g_guiSettings.SetString("lookandfeel.skin",m_addon->ID().c_str()); + CSettings::Get().SetString("lookandfeel.skin",m_addon->ID().c_str()); CGUIDialogKaiToast *toast = (CGUIDialogKaiToast *)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST); if (toast) { @@ -805,7 +805,7 @@ void CAddonUnInstallJob::OnPostUnInstall() if (m_addon->Type() == ADDON_PVRDLL) { - if (g_guiSettings.GetBool("pvrmanager.enabled")) + if (CSettings::Get().GetBool("pvrmanager.enabled")) PVR::CPVRManager::Get().Start(true); } } diff --git a/xbmc/addons/AddonManager.cpp b/xbmc/addons/AddonManager.cpp index 38c304b7c6..e40fe877fe 100644 --- a/xbmc/addons/AddonManager.cpp +++ b/xbmc/addons/AddonManager.cpp @@ -25,8 +25,8 @@ #include "threads/SingleLock.h" #include "FileItem.h" #include "LangInfo.h" -#include "settings/GUISettings.h" #include "settings/AdvancedSettings.h" +#include "settings/Settings.h" #include "utils/log.h" #include "utils/XBMCTinyXML.h" #ifdef HAS_VISUALISATION @@ -473,28 +473,28 @@ bool CAddonMgr::GetDefault(const TYPE &type, AddonPtr &addon) switch (type) { case ADDON_VIZ: - setting = g_guiSettings.GetString("musicplayer.visualisation"); + setting = CSettings::Get().GetString("musicplayer.visualisation"); break; case ADDON_SCREENSAVER: - setting = g_guiSettings.GetString("screensaver.mode"); + setting = CSettings::Get().GetString("screensaver.mode"); break; case ADDON_SCRAPER_ALBUMS: - setting = g_guiSettings.GetString("musiclibrary.albumsscraper"); + setting = CSettings::Get().GetString("musiclibrary.albumsscraper"); break; case ADDON_SCRAPER_ARTISTS: - setting = g_guiSettings.GetString("musiclibrary.artistsscraper"); + setting = CSettings::Get().GetString("musiclibrary.artistsscraper"); break; case ADDON_SCRAPER_MOVIES: - setting = g_guiSettings.GetString("scrapers.moviesdefault"); + setting = CSettings::Get().GetString("scrapers.moviesdefault"); break; case ADDON_SCRAPER_MUSICVIDEOS: - setting = g_guiSettings.GetString("scrapers.musicvideosdefault"); + setting = CSettings::Get().GetString("scrapers.musicvideosdefault"); break; case ADDON_SCRAPER_TVSHOWS: - setting = g_guiSettings.GetString("scrapers.tvshowsdefault"); + setting = CSettings::Get().GetString("scrapers.tvshowsdefault"); break; case ADDON_WEB_INTERFACE: - setting = g_guiSettings.GetString("services.webskin"); + setting = CSettings::Get().GetString("services.webskin"); break; default: return false; @@ -507,25 +507,25 @@ bool CAddonMgr::SetDefault(const TYPE &type, const CStdString &addonID) switch (type) { case ADDON_VIZ: - g_guiSettings.SetString("musicplayer.visualisation",addonID); + CSettings::Get().SetString("musicplayer.visualisation",addonID); break; case ADDON_SCREENSAVER: - g_guiSettings.SetString("screensaver.mode",addonID); + CSettings::Get().SetString("screensaver.mode",addonID); break; case ADDON_SCRAPER_ALBUMS: - g_guiSettings.SetString("musiclibrary.albumsscraper",addonID); + CSettings::Get().SetString("musiclibrary.albumsscraper",addonID); break; case ADDON_SCRAPER_ARTISTS: - g_guiSettings.SetString("musiclibrary.artistsscraper",addonID); + CSettings::Get().SetString("musiclibrary.artistsscraper",addonID); break; case ADDON_SCRAPER_MOVIES: - g_guiSettings.SetString("scrapers.moviesdefault",addonID); + CSettings::Get().SetString("scrapers.moviesdefault",addonID); break; case ADDON_SCRAPER_MUSICVIDEOS: - g_guiSettings.SetString("scrapers.musicvideosdefault",addonID); + CSettings::Get().SetString("scrapers.musicvideosdefault",addonID); break; case ADDON_SCRAPER_TVSHOWS: - g_guiSettings.SetString("scrapers.tvshowsdefault",addonID); + CSettings::Get().SetString("scrapers.tvshowsdefault",addonID); break; default: return false; diff --git a/xbmc/addons/AddonStatusHandler.cpp b/xbmc/addons/AddonStatusHandler.cpp index 6d4d1f6111..874461be97 100644 --- a/xbmc/addons/AddonStatusHandler.cpp +++ b/xbmc/addons/AddonStatusHandler.cpp @@ -26,7 +26,7 @@ #include "dialogs/GUIDialogYesNo.h" #include "dialogs/GUIDialogOK.h" #include "dialogs/GUIDialogKaiToast.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "utils/log.h" namespace ADDON @@ -89,7 +89,7 @@ void CAddonStatusHandler::Process() { if (m_addon->Type() == ADDON_PVRDLL) { - if (!g_guiSettings.GetBool("pvrmanager.hideconnectionlostwarning")) + if (!CSettings::Get().GetBool("pvrmanager.hideconnectionlostwarning")) CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, m_addon->Name().c_str(), g_localizeStrings.Get(36030)); // connection lost // TODO handle disconnects after the add-on's been initialised } diff --git a/xbmc/addons/GUIWindowAddonBrowser.cpp b/xbmc/addons/GUIWindowAddonBrowser.cpp index 8fbd83dbe2..e6303e2a75 100644 --- a/xbmc/addons/GUIWindowAddonBrowser.cpp +++ b/xbmc/addons/GUIWindowAddonBrowser.cpp @@ -39,12 +39,12 @@ #include "utils/log.h" #include "threads/SingleLock.h" #include "settings/Settings.h" +#include "settings/MediaSourceSettings.h" #include "utils/StringUtils.h" #include "AddonDatabase.h" #include "settings/AdvancedSettings.h" #include "settings/MediaSourceSettings.h" #include "storage/MediaManager.h" -#include "settings/GUISettings.h" #include "LangInfo.h" #include "guilib/Key.h" @@ -90,20 +90,19 @@ bool CGUIWindowAddonBrowser::OnMessage(CGUIMessage& message) int iControl = message.GetSenderId(); if (iControl == CONTROL_AUTOUPDATE) { - g_guiSettings.ToggleBool("general.addonautoupdate"); - g_settings.Save(); + CSettings::Get().ToggleBool("general.addonautoupdate"); return true; } else if (iControl == CONTROL_SHUTUP) { - g_guiSettings.ToggleBool("general.addonnotifications"); - g_settings.Save(); + CSettings::Get().ToggleBool("general.addonnotifications"); + CSettings::Get().Save(); return true; } else if (iControl == CONTROL_FOREIGNFILTER) { - g_guiSettings.ToggleBool("general.addonforeignfilter"); - g_settings.Save(); + CSettings::Get().ToggleBool("general.addonforeignfilter"); + CSettings::Get().Save(); Refresh(); return true; } @@ -251,9 +250,9 @@ bool CGUIWindowAddonBrowser::OnClick(int iItem) void CGUIWindowAddonBrowser::UpdateButtons() { - SET_CONTROL_SELECTED(GetID(),CONTROL_AUTOUPDATE,g_guiSettings.GetBool("general.addonautoupdate")); - SET_CONTROL_SELECTED(GetID(),CONTROL_SHUTUP,g_guiSettings.GetBool("general.addonnotifications")); - SET_CONTROL_SELECTED(GetID(),CONTROL_FOREIGNFILTER,g_guiSettings.GetBool("general.addonforeignfilter")); + SET_CONTROL_SELECTED(GetID(),CONTROL_AUTOUPDATE, CSettings::Get().GetBool("general.addonautoupdate")); + SET_CONTROL_SELECTED(GetID(),CONTROL_SHUTUP, CSettings::Get().GetBool("general.addonnotifications")); + SET_CONTROL_SELECTED(GetID(),CONTROL_FOREIGNFILTER, CSettings::Get().GetBool("general.addonforeignfilter")); CGUIMediaWindow::UpdateButtons(); } @@ -298,14 +297,14 @@ bool CGUIWindowAddonBrowser::GetDirectory(const CStdString& strDirectory, else { result = CGUIMediaWindow::GetDirectory(strDirectory,items); - if (g_guiSettings.GetBool("general.addonforeignfilter")) + if (CSettings::Get().GetBool("general.addonforeignfilter")) { int i=0; while (i < items.Size()) { - if (!FilterVar(g_guiSettings.GetBool("general.addonforeignfilter"), + if (!FilterVar(CSettings::Get().GetBool("general.addonforeignfilter"), items[i]->GetProperty("Addon.Language"), "en") || - !FilterVar(g_guiSettings.GetBool("general.addonforeignfilter"), + !FilterVar(CSettings::Get().GetBool("general.addonforeignfilter"), items[i]->GetProperty("Addon.Language"), g_langInfo.GetLanguageLocale())) { diff --git a/xbmc/addons/Repository.cpp b/xbmc/addons/Repository.cpp index e58024d180..580fa91de1 100644 --- a/xbmc/addons/Repository.cpp +++ b/xbmc/addons/Repository.cpp @@ -22,7 +22,7 @@ #include "utils/XBMCTinyXML.h" #include "filesystem/File.h" #include "AddonDatabase.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "FileItem.h" #include "utils/JobManager.h" #include "addons/AddonInstaller.h" @@ -222,7 +222,7 @@ bool CRepositoryUpdateJob::DoWork() if (addon && addons[i]->Version() > addon->Version() && !database.IsAddonBlacklisted(addons[i]->ID(),addons[i]->Version().c_str())) { - if (g_guiSettings.GetBool("general.addonautoupdate") || addon->Type() >= ADDON_VIZ_LIBRARY) + if (CSettings::Get().GetBool("general.addonautoupdate") || addon->Type() >= ADDON_VIZ_LIBRARY) { CStdString referer; if (URIUtils::IsInternetStream(addons[i]->Path())) @@ -234,7 +234,7 @@ bool CRepositoryUpdateJob::DoWork() else CAddonInstaller::Get().Install(addon->ID(), true, referer); } - else if (g_guiSettings.GetBool("general.addonnotifications")) + else if (CSettings::Get().GetBool("general.addonnotifications")) { CGUIDialogKaiToast::QueueNotification(addon->Icon(), g_localizeStrings.Get(24061), diff --git a/xbmc/addons/Scraper.cpp b/xbmc/addons/Scraper.cpp index 75d185a79f..8e7c5f1c37 100644 --- a/xbmc/addons/Scraper.cpp +++ b/xbmc/addons/Scraper.cpp @@ -248,7 +248,7 @@ vector<CStdString> CScraper::Run(const CStdString& function, CStdString strXML = InternalRun(function,scrURL,http,extras); if (strXML.IsEmpty()) { - if (function != "NfoUrl") + if (function != "NfoUrl" && function != "ResolveIDToUrl") CLog::Log(LOGERROR, "%s: Unable to parse web site",__FUNCTION__); throw CScraperError(); } @@ -487,6 +487,68 @@ CScraperUrl CScraper::NfoUrl(const CStdString &sNfoContent) return scurlRet; } +CScraperUrl CScraper::ResolveIDToUrl(const CStdString& externalID) +{ + CScraperUrl scurlRet; + + // scraper function takes an external ID, returns XML (see below) + vector<CStdString> vcsIn; + vcsIn.push_back(externalID); + CScraperUrl scurl; + CCurlFile fcurl; + vector<CStdString> vcsOut = Run("ResolveIDToUrl", scurl, fcurl, &vcsIn); + if (vcsOut.empty() || vcsOut[0].empty()) + return scurlRet; + if (vcsOut.size() > 1) + CLog::Log(LOGWARNING, "%s: scraper returned multiple results; using first", __FUNCTION__); + + // parse returned XML: either <error> element on error, blank on failure, + // or <url>...</url> or <url>...</url><id>...</id> on success + for (unsigned int i=0; i < vcsOut.size(); ++i) + { + CXBMCTinyXML doc; + doc.Parse(vcsOut[i], 0, TIXML_ENCODING_UTF8); + CheckScraperError(doc.RootElement()); + + if (doc.RootElement()) + { + /* + NOTE: Scrapers might return invalid xml with some loose + elements (eg. '<url>http://some.url</url><id>123</id>'). + Since XMLUtils::GetString() is assuming well formed xml + with start and end-tags we're not able to use it. + Check for the desired Elements instead. + */ + TiXmlElement* pxeUrl=NULL; + TiXmlElement* pId=NULL; + if (!strcmp(doc.RootElement()->Value(),"details")) + { + pxeUrl = doc.RootElement()->FirstChildElement("url"); + pId = doc.RootElement()->FirstChildElement("id"); + } + else + { + pId = doc.FirstChildElement("id"); + pxeUrl = doc.FirstChildElement("url"); + } + if (pId && pId->FirstChild()) + scurlRet.strId = pId->FirstChild()->Value(); + + if (pxeUrl && pxeUrl->Attribute("function")) + continue; + + if (pxeUrl) + scurlRet.ParseElement(pxeUrl); + else if (!strcmp(doc.RootElement()->Value(), "url")) + scurlRet.ParseElement(doc.RootElement()); + else + continue; + break; + } + } + return scurlRet; +} + static bool RelevanceSortFunction(const CScraperUrl &left, const CScraperUrl &right) { return left.relevance > right.relevance; @@ -510,7 +572,7 @@ std::vector<CScraperUrl> CScraper::FindMovie(XFILE::CCurlFile &fcurl, const CStd if (IsNoop()) return vcscurl; - if (!fFirst || Content() == CONTENT_MUSICVIDEOS) + if (!fFirst) sTitle.Replace("-"," "); sTitle.ToLower(); diff --git a/xbmc/addons/Scraper.h b/xbmc/addons/Scraper.h index 0d542870b4..e9c0b42419 100644 --- a/xbmc/addons/Scraper.h +++ b/xbmc/addons/Scraper.h @@ -121,6 +121,17 @@ public: // scraper media functions CScraperUrl NfoUrl(const CStdString &sNfoContent); + /*! \brief Resolve an external ID (e.g. MusicBrainz IDs) to a URL using scrapers + If we have an ID in hand, e.g. MusicBrainz IDs or TheTVDB Season IDs + we can get directly to a URL instead of searching by name and choosing from + the search results. The correct scraper type should be used to get the right + URL for a given ID, so we can differentiate albums, artists, TV Seasons, etc. + \param externalID the external ID - e.g. MusicBrainzArtist/AlbumID + \return a populated URL pointing to the details page for the given ID or + an empty URL if we couldn't resolve the ID. + */ + CScraperUrl ResolveIDToUrl(const CStdString &externalID); + std::vector<CScraperUrl> FindMovie(XFILE::CCurlFile &fcurl, const CStdString &sMovie, bool fFirst); std::vector<MUSIC_GRABBER::CMusicAlbumInfo> FindAlbum(XFILE::CCurlFile &fcurl, diff --git a/xbmc/addons/Skin.cpp b/xbmc/addons/Skin.cpp index a6beb4a143..7ae1736f94 100644 --- a/xbmc/addons/Skin.cpp +++ b/xbmc/addons/Skin.cpp @@ -20,13 +20,15 @@ #include "Skin.h" #include "AddonManager.h" +#include "LangInfo.h" +#include "Util.h" #include "filesystem/File.h" #include "filesystem/SpecialProtocol.h" #include "guilib/WindowIDs.h" +#include "settings/Settings.h" #include "utils/URIUtils.h" #include "utils/log.h" #include "utils/StringUtils.h" -#include "settings/GUISettings.h" // fallback for new skin resolution code #include "filesystem/Directory.h" @@ -99,6 +101,11 @@ CSkinInfo::~CSkinInfo() { } +bool CSkinInfo::HasSettings() +{ + return HasSkinFile("SkinSettings.xml"); +} + struct closestRes { closestRes(const RESOLUTION_INFO &target) : m_target(target) { }; @@ -197,7 +204,7 @@ void CSkinInfo::ResolveIncludes(TiXmlElement *node, std::map<int, bool>* xmlIncl int CSkinInfo::GetStartWindow() const { - int windowID = g_guiSettings.GetInt("lookandfeel.startupwindow"); + int windowID = CSettings::Get().GetInt("lookandfeel.startupwindow"); assert(m_startupWindows.size()); for (vector<CStartupWindow>::const_iterator it = m_startupWindows.begin(); it != m_startupWindows.end(); it++) { @@ -263,7 +270,7 @@ int CSkinInfo::GetFirstWindow() const bool CSkinInfo::IsInUse() const { // Could extend this to prompt for reverting to the standard skin perhaps - return g_guiSettings.GetString("lookandfeel.skin") == ID(); + return CSettings::Get().GetString("lookandfeel.skin") == ID(); } const INFO::CSkinVariableString* CSkinInfo::CreateSkinVariable(const CStdString& name, int context) @@ -271,4 +278,167 @@ const INFO::CSkinVariableString* CSkinInfo::CreateSkinVariable(const CStdString& return m_includes.CreateSkinVariable(name, context); } +void CSkinInfo::SettingOptionsSkinColorsFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t) +{ + // There is a default theme (just defaults.xml) + // any other *.xml files are additional color themes on top of this one. + + // add the default label + list.push_back(make_pair(g_localizeStrings.Get(15109), "SKINDEFAULT")); // the standard defaults.xml will be used! + + // Search for colors in the Current skin! + vector<string> vecColors; + string strPath = URIUtils::AddFileToFolder(g_SkinInfo->Path(), "colors"); + + CFileItemList items; + CDirectory::GetDirectory(CSpecialProtocol::TranslatePathConvertCase(strPath), items, ".xml"); + // Search for Themes in the Current skin! + for (int i = 0; i < items.Size(); ++i) + { + CFileItemPtr pItem = items[i]; + if (!pItem->m_bIsFolder && !StringUtils::EqualsNoCase(pItem->GetLabel(), "defaults.xml")) + { // not the default one + vecColors.push_back(pItem->GetLabel().Mid(0, pItem->GetLabel().size() - 4)); + } + } + sort(vecColors.begin(), vecColors.end(), sortstringbyname()); + + for (int i = 0; i < (int) vecColors.size(); ++i) + list.push_back(make_pair(vecColors[i], vecColors[i])); + + CStdString settingValue = ((const CSettingString*)setting)->GetValue(); + // Remove the .xml extension from the Themes + if (URIUtils::GetExtension(settingValue) == ".xml") + URIUtils::RemoveExtension(settingValue); + + // Set the choosen theme + current = settingValue; +} + +void CSkinInfo::SettingOptionsSkinFontsFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t) +{ + std::string strPath = g_SkinInfo->GetSkinPath("Font.xml"); + + CXBMCTinyXML xmlDoc; + if (!xmlDoc.LoadFile(strPath)) + { + CLog::Log(LOGERROR, "FillInSkinFonts: Couldn't load %s", strPath.c_str()); + return; + } + + TiXmlElement* pRootElement = xmlDoc.RootElement(); + + std::string strValue = pRootElement->ValueStr(); + if (strValue != "fonts") + { + CLog::Log(LOGERROR, "FillInSkinFonts: file %s doesn't start with <fonts>", strPath.c_str()); + return; + } + + const TiXmlNode *pChild = pRootElement->FirstChild(); + strValue = pChild->ValueStr(); + if (strValue == "fontset") + { + while (pChild) + { + strValue = pChild->ValueStr(); + if (strValue == "fontset") + { + const char* idAttr = ((TiXmlElement*) pChild)->Attribute("id"); + const char* idLocAttr = ((TiXmlElement*) pChild)->Attribute("idloc"); + const char* unicodeAttr = ((TiXmlElement*) pChild)->Attribute("unicode"); + + bool isUnicode = (unicodeAttr && stricmp(unicodeAttr, "true") == 0); + + bool isAllowed = true; + if (g_langInfo.ForceUnicodeFont() && !isUnicode) + isAllowed = false; + + if (idAttr != NULL && isAllowed) + { + if (idLocAttr) + list.push_back(make_pair(g_localizeStrings.Get(atoi(idLocAttr)), idAttr)); + else + list.push_back(make_pair(idAttr, idAttr)); + } + } + + pChild = pChild->NextSibling(); + } + } + else + { + // Since no fontset is defined, there is no selection of a fontset, so disable the component + list.push_back(make_pair(g_localizeStrings.Get(13278), "")); + } +} + +void CSkinInfo::SettingOptionsSkinSoundFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t) +{ + //find skins... + CFileItemList items; + CDirectory::GetDirectory("special://xbmc/sounds/", items); + CDirectory::GetDirectory("special://home/sounds/", items); + + vector<string> vecSoundSkins; + for (int i = 0; i < items.Size(); i++) + { + CFileItemPtr pItem = items[i]; + if (pItem->m_bIsFolder) + { + if (StringUtils::EqualsNoCase(pItem->GetLabel(), ".svn") || + StringUtils::EqualsNoCase(pItem->GetLabel(), "fonts") || + StringUtils::EqualsNoCase(pItem->GetLabel(), "media")) + continue; + + vecSoundSkins.push_back(pItem->GetLabel()); + } + } + + list.push_back(make_pair(g_localizeStrings.Get(474), "OFF")); + list.push_back(make_pair(g_localizeStrings.Get(15109), "SKINDEFAULT")); + + sort(vecSoundSkins.begin(), vecSoundSkins.end(), sortstringbyname()); + for (unsigned int i = 0; i < vecSoundSkins.size(); i++) + list.push_back(make_pair(vecSoundSkins[i], vecSoundSkins[i])); +} + +void CSkinInfo::SettingOptionsSkinThemesFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t) +{ + // there is a default theme (just Textures.xpr/xbt) + // any other *.xpr|*.xbt files are additional themes on top of this one. + const CSettingString *pSettingString = (const CSettingString *)setting; + + // add the default Label + list.push_back(make_pair(g_localizeStrings.Get(15109), "SKINDEFAULT")); // the standard Textures.xpr/xbt will be used + + // search for themes in the current skin! + vector<CStdString> vecTheme; + CUtil::GetSkinThemes(vecTheme); + + // sort the themes for GUI and list them + for (int i = 0; i < (int) vecTheme.size(); ++i) + list.push_back(make_pair(vecTheme[i], vecTheme[i])); + + // set the choosen theme and remove the extension from the current theme (backward compat) + CStdString settingValue = pSettingString->GetValue(); + URIUtils::RemoveExtension(settingValue); + current = settingValue; +} + +void CSkinInfo::SettingOptionsStartupWindowsFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t) +{ + const vector<CStartupWindow> &startupWindows = g_SkinInfo->GetStartupWindows(); + + for (vector<CStartupWindow>::const_iterator it = startupWindows.begin(); it != startupWindows.end(); it++) + { + string windowName = it->m_name; + if (StringUtils::IsNaturalNumber(windowName)) + windowName = g_localizeStrings.Get(atoi(windowName.c_str())); + int windowID = it->m_id; + + list.push_back(make_pair(windowName, windowID)); + } +} + } /*namespace ADDON*/ diff --git a/xbmc/addons/Skin.h b/xbmc/addons/Skin.h index 6666346d76..c569dcb2b9 100644 --- a/xbmc/addons/Skin.h +++ b/xbmc/addons/Skin.h @@ -20,12 +20,15 @@ * */ +#include <vector> + #include "Addon.h" #include "guilib/GraphicContext.h" // needed for the RESOLUTION members #include "guilib/GUIIncludes.h" // needed for the GUIInclude member #define CREDIT_LINE_LENGTH 50 class TiXmlNode; +class CSetting; namespace ADDON { @@ -49,6 +52,8 @@ public: CSkinInfo(const cp_extension_t *ext); virtual ~CSkinInfo(); + virtual bool HasSettings(); + /*! \brief Load resultion information from directories in Path(). */ void Start(); @@ -110,6 +115,13 @@ public: static double GetMinVersion(); void LoadIncludes(); const INFO::CSkinVariableString* CreateSkinVariable(const CStdString& name, int context); + + static void SettingOptionsSkinColorsFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t); + static void SettingOptionsSkinFontsFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t); + static void SettingOptionsSkinSoundFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t); + static void SettingOptionsSkinThemesFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t); + static void SettingOptionsStartupWindowsFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t); + protected: /*! \brief Given a resolution, retrieve the corresponding directory name \param res RESOLUTION to translate diff --git a/xbmc/addons/Visualisation.cpp b/xbmc/addons/Visualisation.cpp index e4dccbe399..ee672a90a4 100644 --- a/xbmc/addons/Visualisation.cpp +++ b/xbmc/addons/Visualisation.cpp @@ -26,6 +26,7 @@ #include "settings/DisplaySettings.h" #include "settings/Settings.h" #include "settings/AdvancedSettings.h" +#include "settings/DisplaySettings.h" #include "windowing/WindowingFactory.h" #include "utils/URIUtils.h" #include "utils/StringUtils.h" diff --git a/xbmc/cdrip/CDDARipJob.cpp b/xbmc/cdrip/CDDARipJob.cpp index 258f6100ce..9b8f9c168f 100644 --- a/xbmc/cdrip/CDDARipJob.cpp +++ b/xbmc/cdrip/CDDARipJob.cpp @@ -38,7 +38,6 @@ #include "guilib/LocalizeStrings.h" #include "settings/AdvancedSettings.h" #include "utils/StringUtils.h" -#include "settings/GUISettings.h" #include "storage/MediaManager.h" using namespace MUSIC_INFO; diff --git a/xbmc/cdrip/CDDARipJob.h b/xbmc/cdrip/CDDARipJob.h index 04392106a5..adb2c08631 100644 --- a/xbmc/cdrip/CDDARipJob.h +++ b/xbmc/cdrip/CDDARipJob.h @@ -37,7 +37,7 @@ public: //! \param input The input file url //! \param output The output file url //! \param tag The music tag to attach to track - //! \param encoder The encoder to use. See GUISettings.h + //! \param encoder The encoder to use. See Encoder.h //! \param eject Should we eject tray on finish? //! \param rate The sample rate of the input //! \param channels Number of audio channels in input diff --git a/xbmc/cdrip/CDDARipper.cpp b/xbmc/cdrip/CDDARipper.cpp index 25507ea192..0d5bb3b675 100644 --- a/xbmc/cdrip/CDDARipper.cpp +++ b/xbmc/cdrip/CDDARipper.cpp @@ -33,8 +33,10 @@ #include "music/tags/MusicInfoTag.h" #include "guilib/GUIWindowManager.h" #include "dialogs/GUIDialogOK.h" -#include "settings/GUISettings.h" #include "settings/AdvancedSettings.h" +#include "settings/SettingPath.h" +#include "settings/Settings.h" +#include "settings/windows/GUIControlSettings.h" #include "FileItem.h" #include "filesystem/SpecialProtocol.h" #include "storage/MediaManager.h" @@ -84,7 +86,7 @@ bool CCDDARipper::RipTrack(CFileItem* pItem) AddJob(new CCDDARipJob(pItem->GetPath(),strFile, *pItem->GetMusicInfoTag(), - g_guiSettings.GetInt("audiocds.encoder"))); + CSettings::Get().GetInt("audiocds.encoder"))); return true; } @@ -136,11 +138,11 @@ bool CCDDARipper::RipCD() if (item->GetPath().Find(".cdda") < 0) continue; - bool eject = g_guiSettings.GetBool("audiocds.ejectonrip") && + bool eject = CSettings::Get().GetBool("audiocds.ejectonrip") && i == vecItems.Size()-1; AddJob(new CCDDARipJob(item->GetPath(),strFile, *item->GetMusicInfoTag(), - g_guiSettings.GetInt("audiocds.encoder"), eject)); + CSettings::Get().GetInt("audiocds.encoder"), eject)); } return true; @@ -156,7 +158,16 @@ const char* CCDDARipper::GetExtension(int iEncoder) bool CCDDARipper::CreateAlbumDir(const MUSIC_INFO::CMusicInfoTag& infoTag, CStdString& strDirectory, int& legalType) { - strDirectory = g_guiSettings.GetString("audiocds.recordingpath"); + CSettingPath *recordingpathSetting = (CSettingPath*)CSettings::Get().GetSetting("audiocds.recordingpath"); + if (recordingpathSetting != NULL) + { + strDirectory = recordingpathSetting->GetValue(); + if (strDirectory.empty()) + { + if (CGUIControlButtonSetting::GetPath(recordingpathSetting)) + strDirectory = recordingpathSetting->GetValue(); + } + } URIUtils::AddSlashAtEnd(strDirectory); if (strDirectory.size() < 3) @@ -182,7 +193,7 @@ bool CCDDARipper::CreateAlbumDir(const MUSIC_INFO::CMusicInfoTag& infoTag, CStdS if (!strAlbumDir.IsEmpty()) { - URIUtils::AddFileToFolder(strDirectory, strAlbumDir, strDirectory); + strDirectory = URIUtils::AddFileToFolder(strDirectory, strAlbumDir); URIUtils::AddSlashAtEnd(strDirectory); } @@ -205,7 +216,7 @@ CStdString CCDDARipper::GetAlbumDirName(const MUSIC_INFO::CMusicInfoTag& infoTag // use audiocds.trackpathformat setting to format // directory name where CD tracks will be stored, // use only format part ending at the last '/' - strAlbumDir = g_guiSettings.GetString("audiocds.trackpathformat"); + strAlbumDir = CSettings::Get().GetString("audiocds.trackpathformat"); int pos = max(strAlbumDir.ReverseFind('/'), strAlbumDir.ReverseFind('\\')); if (pos < 0) return ""; // no directory @@ -272,7 +283,7 @@ CStdString CCDDARipper::GetTrackName(CFileItem *item) // get track file name format from audiocds.trackpathformat setting, // use only format part starting from the last '/' - CStdString strFormat = g_guiSettings.GetString("audiocds.trackpathformat"); + CStdString strFormat = CSettings::Get().GetString("audiocds.trackpathformat"); int pos = max(strFormat.ReverseFind('/'), strFormat.ReverseFind('\\')); if (pos != -1) { @@ -286,7 +297,7 @@ CStdString CCDDARipper::GetTrackName(CFileItem *item) CStdString track = destItem.GetLabel(); if (track.IsEmpty()) track.Format("%s%02i", "Track-", trackNumber); - track += GetExtension(g_guiSettings.GetInt("audiocds.encoder")); + track += GetExtension(CSettings::Get().GetInt("audiocds.encoder")); return track; } diff --git a/xbmc/cdrip/Encoder.h b/xbmc/cdrip/Encoder.h index 54f9d1bbe3..a4e920fe85 100644 --- a/xbmc/cdrip/Encoder.h +++ b/xbmc/cdrip/Encoder.h @@ -33,6 +33,22 @@ #define WRITEBUFFER_SIZE 131072 // 128k buffer +enum CDDARipEncoder +{ + CDDARIP_ENCODER_LAME = 0, + CDDARIP_ENCODER_VORBIS, + CDDARIP_ENCODER_WAV, + CDDARIP_ENCODER_FLAC +}; + +enum CDDARipQuality +{ + CDDARIP_QUALITY_CBR = 0, + CDDARIP_QUALITY_MEDIUM, + CDDARIP_QUALITY_STANDARD, + CDDARIP_QUALITY_EXTREME +}; + namespace XFILE { class CFile; } class CEncoder diff --git a/xbmc/cdrip/EncoderFFmpeg.cpp b/xbmc/cdrip/EncoderFFmpeg.cpp index bd314024d8..30c9be3151 100644 --- a/xbmc/cdrip/EncoderFFmpeg.cpp +++ b/xbmc/cdrip/EncoderFFmpeg.cpp @@ -33,7 +33,7 @@ #include "EncoderFFmpeg.h" #include "filesystem/File.h" #include "utils/log.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "utils/URIUtils.h" /* AV_PKT_FLAG_KEY was named PKT_FLAG_KEY in older versions of libavcodec */ @@ -86,7 +86,7 @@ bool CEncoderFFmpeg::Init(const char* strFile, int iInChannels, int iInRate, int } m_Format->oformat = fmt; - m_Format->bit_rate = g_guiSettings.GetInt("audiocds.bitrate") * 1000; + m_Format->bit_rate = CSettings::Get().GetInt("audiocds.bitrate") * 1000; /* add a stream to it */ m_Stream = m_dllAvFormat.avformat_new_stream(m_Format, codec); diff --git a/xbmc/cdrip/EncoderFlac.cpp b/xbmc/cdrip/EncoderFlac.cpp index 49a11cc215..bab4532ad3 100644 --- a/xbmc/cdrip/EncoderFlac.cpp +++ b/xbmc/cdrip/EncoderFlac.cpp @@ -21,7 +21,7 @@ #include "EncoderFlac.h" #include "utils/log.h" #include "filesystem/File.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" CEncoderFlac::CEncoderFlac() : m_encoder(0), m_samplesBuf(new FLAC__int32[SAMPLES_BUF_SIZE]) { @@ -63,7 +63,7 @@ bool CEncoderFlac::Init(const char* strFile, int iInChannels, int iInRate, int i ok &= m_dll.FLAC__stream_encoder_set_bits_per_sample(m_encoder, 16); ok &= m_dll.FLAC__stream_encoder_set_sample_rate(m_encoder, 44100); ok &= m_dll.FLAC__stream_encoder_set_total_samples_estimate(m_encoder, m_iTrackLength / 4); - ok &= m_dll.FLAC__stream_encoder_set_compression_level(m_encoder, g_guiSettings.GetInt("audiocds.compressionlevel")); + ok &= m_dll.FLAC__stream_encoder_set_compression_level(m_encoder, CSettings::Get().GetInt("audiocds.compressionlevel")); // now add some metadata FLAC__StreamMetadata_VorbisComment_Entry entry; diff --git a/xbmc/cdrip/EncoderLame.cpp b/xbmc/cdrip/EncoderLame.cpp index 3a03f7b166..a1b359b731 100644 --- a/xbmc/cdrip/EncoderLame.cpp +++ b/xbmc/cdrip/EncoderLame.cpp @@ -19,7 +19,7 @@ */ #include "EncoderLame.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "utils/log.h" #ifdef _WIN32 @@ -54,9 +54,9 @@ bool CEncoderLame::Init(const char* strFile, int iInChannels, int iInRate, int i } // setup parmaters, see lame.h for possibilities - if (g_guiSettings.GetInt("audiocds.quality") == CDDARIP_QUALITY_CBR) + if (CSettings::Get().GetInt("audiocds.quality") == CDDARIP_QUALITY_CBR) { - int bitrate = g_guiSettings.GetInt("audiocds.bitrate"); + int bitrate = CSettings::Get().GetInt("audiocds.bitrate"); // use cbr and specified bitrate from settings CLog::Log(LOGDEBUG, "Lame setting CBR bitrate %d", bitrate); m_dll.lame_set_brate(m_pGlobalFlags, bitrate); @@ -65,7 +65,7 @@ bool CEncoderLame::Init(const char* strFile, int iInChannels, int iInRate, int i { // use presets (VBR) int preset; - switch (g_guiSettings.GetInt("audiocds.quality")) + switch (CSettings::Get().GetInt("audiocds.quality")) { case CDDARIP_QUALITY_MEDIUM: preset = MEDIUM; diff --git a/xbmc/cdrip/EncoderVorbis.cpp b/xbmc/cdrip/EncoderVorbis.cpp index cb23269542..f1b81a17e0 100644 --- a/xbmc/cdrip/EncoderVorbis.cpp +++ b/xbmc/cdrip/EncoderVorbis.cpp @@ -19,7 +19,7 @@ */ #include "EncoderVorbis.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "utils/log.h" CEncoderVorbis::CEncoderVorbis() @@ -36,9 +36,9 @@ bool CEncoderVorbis::Init(const char* strFile, int iInChannels, int iInRate, int if (!CEncoder::Init(strFile, iInChannels, iInRate, iInBits)) return false; float fQuality = 0.5f; - if (g_guiSettings.GetInt("audiocds.quality") == CDDARIP_QUALITY_MEDIUM) fQuality = 0.4f; - if (g_guiSettings.GetInt("audiocds.quality") == CDDARIP_QUALITY_STANDARD) fQuality = 0.5f; - if (g_guiSettings.GetInt("audiocds.quality") == CDDARIP_QUALITY_EXTREME) fQuality = 0.7f; + if (CSettings::Get().GetInt("audiocds.quality") == CDDARIP_QUALITY_MEDIUM) fQuality = 0.4f; + if (CSettings::Get().GetInt("audiocds.quality") == CDDARIP_QUALITY_STANDARD) fQuality = 0.5f; + if (CSettings::Get().GetInt("audiocds.quality") == CDDARIP_QUALITY_EXTREME) fQuality = 0.7f; if (!m_VorbisEncDll.Load() || !m_OggDll.Load() || !m_VorbisDll.Load()) { @@ -48,10 +48,10 @@ bool CEncoderVorbis::Init(const char* strFile, int iInChannels, int iInRate, int } m_VorbisDll.vorbis_info_init(&m_sVorbisInfo); - if (g_guiSettings.GetInt("audiocds.quality") == CDDARIP_QUALITY_CBR) + if (CSettings::Get().GetInt("audiocds.quality") == CDDARIP_QUALITY_CBR) { // not realy cbr, but abr in this case - int iBitRate = g_guiSettings.GetInt("audiocds.bitrate") * 1000; + int iBitRate = CSettings::Get().GetInt("audiocds.bitrate") * 1000; m_VorbisEncDll.vorbis_encode_init(&m_sVorbisInfo, m_iInChannels, m_iInSampleRate, -1, iBitRate, -1); } else diff --git a/xbmc/commons/ilog.h b/xbmc/commons/ilog.h index 395fc46f82..012d3f681f 100644 --- a/xbmc/commons/ilog.h +++ b/xbmc/commons/ilog.h @@ -26,8 +26,7 @@ #define LOG_LEVEL_NORMAL 0 // shows notice, error, severe and fatal #define LOG_LEVEL_DEBUG 1 // shows all #define LOG_LEVEL_DEBUG_FREEMEM 2 // shows all + shows freemem on screen -#define LOG_LEVEL_DEBUG_SAMBA 3 // shows all + freemem on screen + samba debugging -#define LOG_LEVEL_MAX LOG_LEVEL_DEBUG_SAMBA +#define LOG_LEVEL_MAX LOG_LEVEL_DEBUG_FREEMEM // ones we use in the code #define LOGDEBUG 0 @@ -39,6 +38,17 @@ #define LOGFATAL 6 #define LOGNONE 7 +// extra masks - from bit 5 +#define LOGMASKBIT 5 +#define LOGMASK ((1 << LOGMASKBIT)-1) + +#define LOGSAMBA (1 << (LOGMASKBIT+0)) +#define LOGCURL (1 << (LOGMASKBIT+1)) +#define LOGCMYTH (1 << (LOGMASKBIT+2)) +#define LOGFFMPEG (1 << (LOGMASKBIT+3)) +#define LOGRTMP (1 << (LOGMASKBIT+4)) +#define LOGDBUS (1 << (LOGMASKBIT+5)) + #ifdef __GNUC__ #define ATTRIB_LOG_FORMAT __attribute__((format(printf,3,4))) #else diff --git a/xbmc/cores/AudioEngine/AEFactory.cpp b/xbmc/cores/AudioEngine/AEFactory.cpp index 8c0cbb6e09..ad2fe27f00 100644 --- a/xbmc/cores/AudioEngine/AEFactory.cpp +++ b/xbmc/cores/AudioEngine/AEFactory.cpp @@ -20,9 +20,11 @@ #include "system.h" #include "AEFactory.h" +#include "Utils/AEUtil.h" #if defined(TARGET_DARWIN) #include "Engines/CoreAudio/CoreAudioAE.h" + #include "settings/SettingsManager.h" #else #include "Engines/SoftAE/SoftAE.h" #endif @@ -31,6 +33,10 @@ #include "Engines/PulseAE/PulseAE.h" #endif +#include "guilib/LocalizeStrings.h" +#include "settings/Setting.h" +#include "utils/StringUtils.h" + IAE* CAEFactory::AE = NULL; static float g_fVolume = 1.0f; static bool g_bMute = false; @@ -297,3 +303,58 @@ void CAEFactory::GarbageCollect() if(AE) AE->GarbageCollect(); } + +void CAEFactory::SettingOptionsAudioDevicesFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t) +{ + SettingOptionsAudioDevicesFillerGeneral(setting, list, current, false); +} + +void CAEFactory::SettingOptionsAudioDevicesPassthroughFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t) +{ + SettingOptionsAudioDevicesFillerGeneral(setting, list, current, true); +} + +void CAEFactory::SettingOptionsAudioOutputModesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t) +{ + list.push_back(std::make_pair(g_localizeStrings.Get(338), AUDIO_ANALOG)); +#if !defined(TARGET_RASPBERRY_PI) + list.push_back(std::make_pair(g_localizeStrings.Get(339), AUDIO_IEC958)); +#endif + list.push_back(std::make_pair(g_localizeStrings.Get(420), AUDIO_HDMI)); +} + +void CAEFactory::SettingOptionsAudioDevicesFillerGeneral(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t, bool passthrough) +{ + current = ((const CSettingString*)setting)->GetValue(); + std::string firstDevice; + + bool foundValue = false; + AEDeviceList sinkList; + EnumerateOutputDevices(sinkList, passthrough); +#if !defined(TARGET_DARWIN) + if (sinkList.size() == 0) + list.push_back(std::make_pair("Error - no devices found", "error")); + else + { +#endif + for (AEDeviceList::const_iterator sink = sinkList.begin(); sink != sinkList.end(); sink++) + { + if (sink == sinkList.begin()) + firstDevice = sink->second; + +#if defined(TARGET_DARWIN) + list.push_back(StringSettingOption(sink->first, sink->first)); +#else + list.push_back(std::make_pair(sink->first, sink->second)); +#endif + + if (StringUtils::EqualsNoCase(current, sink->second)) + foundValue = true; + } +#if !defined(TARGET_DARWIN) + } +#endif + + if (!foundValue) + current = firstDevice; +} diff --git a/xbmc/cores/AudioEngine/AEFactory.h b/xbmc/cores/AudioEngine/AEFactory.h index 99cdebd10c..56a1e273f3 100644 --- a/xbmc/cores/AudioEngine/AEFactory.h +++ b/xbmc/cores/AudioEngine/AEFactory.h @@ -19,9 +19,13 @@ * */ +#include <vector> + #include "Interfaces/AE.h" #include "threads/Thread.h" +class CSetting; + enum AEEngine { AE_ENGINE_NULL, @@ -58,8 +62,15 @@ public: unsigned int encodedSampleRate, CAEChannelInfo channelLayout, unsigned int options = 0); static IAEStream *FreeStream(IAEStream *stream); static void GarbageCollect(); + + static void SettingOptionsAudioDevicesFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t); + static void SettingOptionsAudioDevicesPassthroughFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t); + static void SettingOptionsAudioOutputModesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t); + private: static bool LoadEngine(enum AEEngine engine); static IAE *AE; + + static void SettingOptionsAudioDevicesFillerGeneral(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t, bool passthrough); }; diff --git a/xbmc/cores/AudioEngine/Encoders/AEEncoderFFmpeg.cpp b/xbmc/cores/AudioEngine/Encoders/AEEncoderFFmpeg.cpp index 34ddda64eb..8f432a5360 100644 --- a/xbmc/cores/AudioEngine/Encoders/AEEncoderFFmpeg.cpp +++ b/xbmc/cores/AudioEngine/Encoders/AEEncoderFFmpeg.cpp @@ -25,17 +25,21 @@ #include "cores/AudioEngine/Utils/AEUtil.h" #include "utils/log.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include <string.h> CAEEncoderFFmpeg::CAEEncoderFFmpeg(): m_BitRate (0 ), m_CodecCtx (NULL ), + m_SwrCtx (NULL ), m_BufferSize (0 ), m_OutputSize (0 ), m_OutputRatio (0.0 ), m_SampleRateMul (0.0 ), - m_NeededFrames (0 ) + m_NeededFrames (0 ), + m_NeedConversion(false), + m_ResampBuffer (NULL ), + m_ResampBufferSize(0 ) { } @@ -43,6 +47,9 @@ CAEEncoderFFmpeg::~CAEEncoderFFmpeg() { Reset(); m_dllAvUtil.av_freep(&m_CodecCtx); + m_dllAvUtil.av_freep(&m_ResampBuffer); + if (m_SwrCtx) + m_dllSwResample.swr_free(&m_SwrCtx); } bool CAEEncoderFFmpeg::IsCompatible(AEAudioFormat format) @@ -95,17 +102,17 @@ bool CAEEncoderFFmpeg::Initialize(AEAudioFormat &format) { Reset(); - if (!m_dllAvUtil.Load() || !m_dllAvCodec.Load()) + if (!m_dllAvUtil.Load() || !m_dllAvCodec.Load() || !m_dllSwResample.Load()) return false; m_dllAvCodec.avcodec_register_all(); - bool ac3 = g_guiSettings.GetBool("audiooutput.ac3passthrough"); + bool ac3 = CSettings::Get().GetBool("audiooutput.ac3passthrough"); AVCodec *codec = NULL; #if 0 /* the DCA encoder is currently useless for transcode, it creates a 196 kHz DTS-HD like mongrel which is useless for SPDIF */ - bool dts = g_guiSettings.GetBool("audiooutput.dtspassthrough"); + bool dts = CSettings::Get().GetBool("audiooutput.dtspassthrough"); if (dts && (!ac3 || g_advancedSettings.m_audioTranscodeTo.Equals("dts"))) { m_CodecName = "DTS"; @@ -143,6 +150,7 @@ bool CAEEncoderFFmpeg::Initialize(AEAudioFormat &format) bool hasS32 = false; bool hasS16 = false; bool hasU8 = false; + bool hasUnknownFormat = false; for(int i = 0; codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; ++i) { @@ -153,9 +161,8 @@ bool CAEEncoderFFmpeg::Initialize(AEAudioFormat &format) case AV_SAMPLE_FMT_S32: hasS32 = true; break; case AV_SAMPLE_FMT_S16: hasS16 = true; break; case AV_SAMPLE_FMT_U8 : hasU8 = true; break; - - default: - return false; + case AV_SAMPLE_FMT_NONE: return false; + default: hasUnknownFormat = true; break; } } @@ -184,6 +191,13 @@ bool CAEEncoderFFmpeg::Initialize(AEAudioFormat &format) m_CodecCtx->sample_fmt = AV_SAMPLE_FMT_U8; format.m_dataFormat = AE_FMT_U8; } + else if (hasUnknownFormat) + { + m_CodecCtx->sample_fmt = codec->sample_fmts[0]; + format.m_dataFormat = AE_FMT_FLOAT; + m_NeedConversion = true; + CLog::Log(LOGNOTICE, "CAEEncoderFFmpeg::Initialize - Unknown audio format, it will be resampled."); + } else { CLog::Log(LOGERROR, "CAEEncoderFFmpeg::Initialize - Unable to find a suitable data format for the codec (%s)", m_CodecName.c_str()); @@ -212,6 +226,18 @@ bool CAEEncoderFFmpeg::Initialize(AEAudioFormat &format) m_OutputRatio = (double)m_NeededFrames / m_OutputSize; m_SampleRateMul = 1.0 / (double)m_CodecCtx->sample_rate; + if (m_NeedConversion) + { + m_SwrCtx = m_dllSwResample.swr_alloc_set_opts(NULL, + m_CodecCtx->channel_layout, m_CodecCtx->sample_fmt, m_CodecCtx->sample_rate, + m_CodecCtx->channel_layout, AV_SAMPLE_FMT_FLT, m_CodecCtx->sample_rate, + 0, NULL); + if (!m_SwrCtx || m_dllSwResample.swr_init(m_SwrCtx) < 0) + { + CLog::Log(LOGERROR, "CAEEncoderFFmpeg::Initialize - Failed to initialise resampler."); + return false; + } + } CLog::Log(LOGNOTICE, "CAEEncoderFFmpeg::Initialize - %s encoder ready", m_CodecName.c_str()); return true; } @@ -238,20 +264,89 @@ unsigned int CAEEncoderFFmpeg::GetFrames() int CAEEncoderFFmpeg::Encode(float *data, unsigned int frames) { + int got_output; + AVFrame *frame; + const uint8_t *input = (const uint8_t*) data; + if (!m_CodecCtx || frames < m_NeededFrames) return 0; + /* size of the buffer sent to the encoder: either from the input data or after + * conversion, in all cases it is in the m_CodecCtx->sample_fmt format */ + int buf_size = m_dllAvUtil.av_samples_get_buffer_size(NULL, m_CodecCtx->channels, frames, m_CodecCtx->sample_fmt, 0); + assert(buf_size>0); + + /* allocate the input frame + * sadly, we have to alloc/dealloc it everytime since we have no guarantee the + * data argument will be constant over iterated calls and the frame needs to + * setup pointers inside data */ + frame = m_dllAvCodec.avcodec_alloc_frame(); + if (!frame) + return 0; + + frame->nb_samples = m_CodecCtx->frame_size; + frame->format = m_CodecCtx->sample_fmt; + frame->channel_layout = m_CodecCtx->channel_layout; + + if (m_NeedConversion) + { + if (!m_ResampBuffer || buf_size > m_ResampBufferSize) + { + m_ResampBuffer = (uint8_t*)m_dllAvUtil.av_realloc(m_ResampBuffer, buf_size); + if (!m_ResampBuffer) + { + CLog::Log(LOGERROR, "CAEEncoderFFmpeg::Encode - Failed to allocate %i bytes buffer for resampling", buf_size); + m_dllAvCodec.avcodec_free_frame(&frame); + return 0; + } + m_ResampBufferSize = buf_size; + } + + m_dllAvCodec.avcodec_fill_audio_frame(frame, m_CodecCtx->channels, m_CodecCtx->sample_fmt, m_ResampBuffer, buf_size, 0); + + /* important note: the '&input' here works because we convert from a packed + * format (ie, interleaved). If it were to be used to convert from planar + * formats (ie, non-interleaved, which is not currently supported by AE), + * we would need to adapt it or it would segfault. */ + if (m_dllSwResample.swr_convert(m_SwrCtx, frame->extended_data, frames, &input, frames) < 0) + { + CLog::Log(LOGERROR, "CAEEncoderFFmpeg::Encode - Resampling failed"); + m_dllAvCodec.avcodec_free_frame(&frame); + return 0; + } + } + else + m_dllAvCodec.avcodec_fill_audio_frame(frame, m_CodecCtx->channels, m_CodecCtx->sample_fmt, + input, buf_size, 0); + + /* initialize the output packet */ + m_dllAvCodec.av_init_packet(&m_Pkt); + m_Pkt.size = sizeof(m_Buffer) - IEC61937_DATA_OFFSET; + m_Pkt.data = m_Buffer + IEC61937_DATA_OFFSET; + /* encode it */ - int size = m_dllAvCodec.avcodec_encode_audio(m_CodecCtx, m_Buffer + IEC61937_DATA_OFFSET, FF_MIN_BUFFER_SIZE, (short*)data); + int ret = m_dllAvCodec.avcodec_encode_audio2(m_CodecCtx, &m_Pkt, frame, &got_output); + + /* free temporary data */ + m_dllAvCodec.avcodec_free_frame(&frame); + + if (ret < 0 || !got_output) + { + CLog::Log(LOGERROR, "CAEEncoderFFmpeg::Encode - Encoding failed"); + return 0; + } /* pack it into an IEC958 frame */ - m_BufferSize = m_PackFunc(NULL, size, m_Buffer); + m_BufferSize = m_PackFunc(NULL, m_Pkt.size, m_Buffer); if (m_BufferSize != m_OutputSize) { m_OutputSize = m_BufferSize; m_OutputRatio = (double)m_NeededFrames / m_OutputSize; } + /* free the packet */ + m_dllAvCodec.av_free_packet(&m_Pkt); + /* return the number of frames used */ return m_NeededFrames; } diff --git a/xbmc/cores/AudioEngine/Encoders/AEEncoderFFmpeg.h b/xbmc/cores/AudioEngine/Encoders/AEEncoderFFmpeg.h index 0cedf3fa8c..48667d3aa9 100644 --- a/xbmc/cores/AudioEngine/Encoders/AEEncoderFFmpeg.h +++ b/xbmc/cores/AudioEngine/Encoders/AEEncoderFFmpeg.h @@ -27,6 +27,7 @@ #undef restrict #include "DllAvCodec.h" #include "DllAvFormat.h" +#include "DllSwResample.h" class CAEEncoderFFmpeg: public IAEEncoder { @@ -49,6 +50,7 @@ private: DllAvCodec m_dllAvCodec; DllAvFormat m_dllAvFormat; DllAvUtil m_dllAvUtil; + DllSwResample m_dllSwResample; std::string m_CodecName; CodecID m_CodecID; @@ -57,7 +59,9 @@ private: AEAudioFormat m_CurrentFormat; AVCodecContext *m_CodecCtx; + SwrContext *m_SwrCtx; CAEChannelInfo m_Layout; + AVPacket m_Pkt; uint8_t m_Buffer[IEC61937_DATA_OFFSET + FF_MIN_BUFFER_SIZE]; int m_BufferSize; int m_OutputSize; @@ -67,5 +71,9 @@ private: unsigned int m_NeededFrames; unsigned int BuildChannelLayout(const int64_t ffmap, CAEChannelInfo& layout); + + bool m_NeedConversion; + uint8_t *m_ResampBuffer; + int m_ResampBufferSize; }; diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAE.cpp b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAE.cpp index ce3b0c4158..3aadf3b14e 100644 --- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAE.cpp +++ b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAE.cpp @@ -26,8 +26,8 @@ #include "CoreAudioAESound.h" #include "Application.h" #include "cores/AudioEngine/Utils/AEUtil.h" -#include "settings/GUISettings.h" #include "settings/AdvancedSettings.h" +#include "settings/Settings.h" #include "threads/SingleLock.h" #include "utils/EndianSwap.h" #include "utils/log.h" @@ -105,8 +105,8 @@ CCoreAudioAE::CCoreAudioAE() : CCoreAudioAE::~CCoreAudioAE() { - Shutdown(); RegisterDeviceChangedCB(false, this); + Shutdown(); } void CCoreAudioAE::Shutdown() @@ -150,6 +150,10 @@ void CCoreAudioAE::AudioDevicesChanged() // again (yeah that really is the case - duh) Sleep(500); CSingleLock engineLock(m_engineLock); + + // re-check initialized since it can have changed when we waited and grabbed the lock + if (!m_Initialized) + return; OpenCoreAudio(m_lastSampleRate, COREAUDIO_IS_RAW(m_lastStreamFormat), m_lastStreamFormat); } @@ -173,7 +177,7 @@ bool CCoreAudioAE::Initialize() bool CCoreAudioAE::OpenCoreAudio(unsigned int sampleRate, bool forceRaw, enum AEDataFormat rawDataFormat) { - + unsigned int maxChannelCountInStreams = 0; // remove any deleted streams CSingleLock streamLock(m_streamLock); for (StreamList::iterator itt = m_streams.begin(); itt != m_streams.end();) @@ -190,6 +194,10 @@ bool CCoreAudioAE::OpenCoreAudio(unsigned int sampleRate, bool forceRaw, // close all converter stream->CloseConverter(); } + + if (stream->GetChannelCount() > maxChannelCountInStreams) + maxChannelCountInStreams = stream->GetChannelCount(); + ++itt; } @@ -206,12 +214,12 @@ bool CCoreAudioAE::OpenCoreAudio(unsigned int sampleRate, bool forceRaw, if (m_rawPassthrough) CLog::Log(LOGINFO, "CCoreAudioAE::OpenCoreAudio - RAW passthrough enabled"); - std::string m_outputDevice = g_guiSettings.GetString("audiooutput.audiodevice"); + std::string m_outputDevice = CSettings::Get().GetString("audiooutput.audiodevice"); // on iOS devices we set fixed to two channels. m_stdChLayout = AE_CH_LAYOUT_2_0; #if defined(TARGET_DARWIN_OSX) - switch (g_guiSettings.GetInt("audiooutput.channels")) + switch (CSettings::Get().GetInt("audiooutput.channels")) { default: case 0: m_stdChLayout = AE_CH_LAYOUT_2_0; break; /* do not allow 1_0 output */ @@ -228,7 +236,7 @@ bool CCoreAudioAE::OpenCoreAudio(unsigned int sampleRate, bool forceRaw, } #endif // force optical/coax to 2.0 output channels - if (!m_rawPassthrough && g_guiSettings.GetInt("audiooutput.mode") == AUDIO_IEC958) + if (!m_rawPassthrough && CSettings::Get().GetInt("audiooutput.mode") == AUDIO_IEC958) m_stdChLayout = AE_CH_LAYOUT_2_0; // setup the desired format @@ -263,7 +271,16 @@ bool CCoreAudioAE::OpenCoreAudio(unsigned int sampleRate, bool forceRaw, m_format.m_dataFormat = AE_FMT_S16NE; break; case AE_FMT_LPCM: - m_format.m_channelLayout = CAEChannelInfo(AE_CH_LAYOUT_7_1); + // audio midi setup can be setup to 2.0 or 7.1 + // if we have the number of max channels from streams we use that for + // selecting either 2.0 or 7.1 setup depending on that. + // This allows DPII modes on amps for enhancing stereo sound + // (when switching to 7.1 - all 8 channels will be pushed out preventing most amps + // to switch to DPII mode) + if (maxChannelCountInStreams == 1 || maxChannelCountInStreams == 2) + m_format.m_channelLayout = CAEChannelInfo(AE_CH_LAYOUT_2_0); + else + m_format.m_channelLayout = CAEChannelInfo(AE_CH_LAYOUT_7_1); m_format.m_sampleRate = sampleRate; m_format.m_dataFormat = AE_FMT_FLOAT; break; diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALOSX.cpp b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALOSX.cpp index b43732f43e..52b2272a2d 100644 --- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALOSX.cpp +++ b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALOSX.cpp @@ -34,8 +34,8 @@ #include "CoreAudioChannelLayout.h" #include "cores/AudioEngine/Utils/AEUtil.h" -#include "settings/GUISettings.h" #include "utils/log.h" +#include "settings/Settings.h" CCoreAudioAEHALOSX::CCoreAudioAEHALOSX() : m_audioGraph (NULL ), @@ -93,9 +93,9 @@ bool CCoreAudioAEHALOSX::InitializePCM(ICoreAudioSource *pSource, AEAudioFormat if (!m_audioGraph) return false; - AudioChannelLayoutTag layout = g_LayoutMap[ g_guiSettings.GetInt("audiooutput.channels") ]; + AudioChannelLayoutTag layout = g_LayoutMap[ CSettings::Get().GetInt("audiooutput.channels") ]; // force optical/coax to 2.0 output channels - if (!m_Passthrough && g_guiSettings.GetInt("audiooutput.mode") == AUDIO_IEC958) + if (!m_Passthrough && CSettings::Get().GetInt("audiooutput.mode") == AUDIO_IEC958) layout = g_LayoutMap[1]; if (!m_audioGraph->Open(pSource, format, outputDevice, allowMixing, layout, m_initVolume )) diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEStream.cpp b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEStream.cpp index afd82852f9..a9422f779d 100644 --- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEStream.cpp +++ b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEStream.cpp @@ -26,7 +26,6 @@ #include "xbmc/cores/AudioEngine/Interfaces/AE.h" #include "xbmc/cores/AudioEngine/AEFactory.h" #include "xbmc/cores/AudioEngine/Utils/AEUtil.h" -#include "settings/GUISettings.h" #include "settings/Settings.h" #include "threads/SingleLock.h" #include "settings/AdvancedSettings.h" diff --git a/xbmc/cores/AudioEngine/Engines/PulseAE/PulseAE.cpp b/xbmc/cores/AudioEngine/Engines/PulseAE/PulseAE.cpp index dabe89160b..f5f699cb9d 100644 --- a/xbmc/cores/AudioEngine/Engines/PulseAE/PulseAE.cpp +++ b/xbmc/cores/AudioEngine/Engines/PulseAE/PulseAE.cpp @@ -27,6 +27,7 @@ #include "Application.h" #include "threads/SingleLock.h" #include "utils/log.h" +#include "settings/Settings.h" #include <pulse/pulseaudio.h> #include <pulse/simple.h> #include "guilib/LocalizeStrings.h" diff --git a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp index 9222944b36..26a87a42a4 100644 --- a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp +++ b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp @@ -28,9 +28,8 @@ #include "utils/MathUtils.h" #include "utils/EndianSwap.h" #include "threads/SingleLock.h" -#include "settings/GUISettings.h" -#include "settings/Settings.h" #include "settings/AdvancedSettings.h" +#include "settings/Settings.h" #include "SoftAE.h" #include "SoftAESound.h" @@ -529,8 +528,7 @@ void CSoftAE::OnSettingsChange(const std::string& setting) setting == "audiooutput.passthroughaac" || setting == "audiooutput.truehdpassthrough" || setting == "audiooutput.dtshdpassthrough" || - setting == "audiooutput.channels" || - setting == "audiooutput.useexclusivemode" || + setting == "audiooutput.channels" || setting == "audiooutput.multichannellpcm" || setting == "audiooutput.stereoupmix") { @@ -552,13 +550,13 @@ void CSoftAE::LoadSettings() if (m_audiophile) CLog::Log(LOGINFO, "CSoftAE::LoadSettings - Audiophile switch enabled"); - m_stereoUpmix = g_guiSettings.GetBool("audiooutput.stereoupmix"); + m_stereoUpmix = CSettings::Get().GetBool("audiooutput.stereoupmix"); if (m_stereoUpmix) CLog::Log(LOGINFO, "CSoftAE::LoadSettings - Stereo upmix is enabled"); /* load the configuration */ m_stdChLayout = AE_CH_LAYOUT_2_0; - switch (g_guiSettings.GetInt("audiooutput.channels")) + switch (CSettings::Get().GetInt("audiooutput.channels")) { default: case 0: m_stdChLayout = AE_CH_LAYOUT_2_0; break; /* dont alow 1_0 output */ @@ -575,21 +573,21 @@ void CSoftAE::LoadSettings() } // force optical/coax to 2.0 output channels - if (!m_rawPassthrough && g_guiSettings.GetInt("audiooutput.mode") == AUDIO_IEC958) + if (!m_rawPassthrough && CSettings::Get().GetInt("audiooutput.mode") == AUDIO_IEC958) m_stdChLayout = AE_CH_LAYOUT_2_0; /* get the output devices and ensure they exist */ - m_device = g_guiSettings.GetString("audiooutput.audiodevice"); - m_passthroughDevice = g_guiSettings.GetString("audiooutput.passthroughdevice"); + m_device = CSettings::Get().GetString("audiooutput.audiodevice"); + m_passthroughDevice = CSettings::Get().GetString("audiooutput.passthroughdevice"); VerifySoundDevice(m_device , false); VerifySoundDevice(m_passthroughDevice, true ); m_transcode = ( - g_guiSettings.GetBool("audiooutput.ac3passthrough") /*|| - g_guiSettings.GetBool("audiooutput.dtspassthrough") */ + CSettings::Get().GetBool("audiooutput.ac3passthrough") /*|| + CSettings::Get().GetBool("audiooutput.dtspassthrough") */ ) && ( - (g_guiSettings.GetInt("audiooutput.mode") == AUDIO_IEC958) || - (g_guiSettings.GetInt("audiooutput.mode") == AUDIO_HDMI && !g_guiSettings.GetBool("audiooutput.multichannellpcm")) + (CSettings::Get().GetInt("audiooutput.mode") == AUDIO_IEC958) || + (CSettings::Get().GetInt("audiooutput.mode") == AUDIO_HDMI && !CSettings::Get().GetBool("audiooutput.multichannellpcm")) ); } @@ -1295,6 +1293,8 @@ int CSoftAE::RunRawOutputStage(bool hasAudio) int CSoftAE::RunTranscodeStage(bool hasAudio) { + if (!m_encoder) return 0; + /* if we dont have enough samples to encode yet, return */ unsigned int block = m_encoderFormat.m_frames * m_encoderFormat.m_frameSize; unsigned int sinkBlock = m_sinkFormat.m_frames * m_sinkFormat.m_frameSize; diff --git a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAEStream.cpp b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAEStream.cpp index a64beb1aa2..ee7a3c432d 100644 --- a/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAEStream.cpp +++ b/xbmc/cores/AudioEngine/Engines/SoftAE/SoftAEStream.cpp @@ -29,6 +29,10 @@ #include "SoftAE.h" #include "SoftAEStream.h" +#ifdef TARGET_WINDOWS +#pragma comment(lib, "libsamplerate-0.lib") +#endif + /* typecast AE to CSoftAE */ #define AE (*((CSoftAE*)CAEFactory::GetEngine())) diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp index 2629c72cec..93ee569f72 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp @@ -32,7 +32,6 @@ #include "utils/log.h" #include "utils/MathUtils.h" #include "threads/SingleLock.h" -#include "settings/GUISettings.h" #if defined(HAS_AMLPLAYER) #include "cores/amlplayer/AMLUtils.h" #endif @@ -147,7 +146,7 @@ bool CAESinkALSA::Initialize(AEAudioFormat &format, std::string &device) m_channelLayout = GetChannelLayout(format); m_passthrough = false; } -#if defined(HAS_AMLPLAYER) +#if defined(HAS_AMLPLAYER) || defined(HAS_LIBAMCODEC) if (aml_present()) { aml_set_audio_passthrough(m_passthrough); diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp index 34f6e979b1..ffb5f30f73 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp @@ -23,8 +23,8 @@ #include "Utils/AERingBuffer.h" #include "android/activity/XBMCApp.h" #include "utils/log.h" -#if defined(HAS_AMLPLAYER) -#include "cores/amlplayer/AMLUtils.h" +#if defined(HAS_AMLPLAYER) || defined(HAS_LIBAMCODEC) +#include "utils/AMLUtils.h" #endif #include <jni.h> @@ -83,14 +83,14 @@ CAESinkAUDIOTRACK::CAESinkAUDIOTRACK() m_audiotrackbuffer_sec = 0.0; m_audiotrack_empty_sec = 0.0; m_volume = 0.0; -#if defined(HAS_AMLPLAYER) +#if defined(HAS_AMLPLAYER) || defined(HAS_LIBAMCODEC) aml_cpufreq_limit(true); #endif } CAESinkAUDIOTRACK::~CAESinkAUDIOTRACK() { -#if defined(HAS_AMLPLAYER) +#if defined(HAS_AMLPLAYER) || defined(HAS_LIBAMCODEC) aml_cpufreq_limit(false); #endif } @@ -99,6 +99,16 @@ bool CAESinkAUDIOTRACK::Initialize(AEAudioFormat &format, std::string &device) { m_format = format; + if (AE_IS_RAW(m_format.m_dataFormat)) + m_passthrough = true; + else + m_passthrough = false; + +#if defined(HAS_LIBAMCODEC) + if (aml_present()) + aml_set_audio_passthrough(m_passthrough); +#endif + // default to 44100, all android devices support it. // then check if we can support the requested rate. unsigned int sampleRate = 44100; @@ -173,7 +183,12 @@ double CAESinkAUDIOTRACK::GetDelay() // AudioMixer (if any) and audio hardware driver. double sinkbuffer_seconds_to_empty = m_sinkbuffer_sec_per_byte * (double)m_sinkbuffer->GetReadSize(); - return sinkbuffer_seconds_to_empty + m_audiotrack_empty_sec; + sinkbuffer_seconds_to_empty += m_audiotrack_empty_sec; +#if defined(HAS_LIBAMCODEC) + if (sinkbuffer_seconds_to_empty > 0.0) + sinkbuffer_seconds_to_empty += 0.250; +#endif + return sinkbuffer_seconds_to_empty; } double CAESinkAUDIOTRACK::GetCacheTime() @@ -182,7 +197,12 @@ double CAESinkAUDIOTRACK::GetCacheTime() // to underrun the buffer if no sample is added. double sinkbuffer_seconds_to_empty = m_sinkbuffer_sec_per_byte * (double)m_sinkbuffer->GetReadSize(); - return sinkbuffer_seconds_to_empty + m_audiotrack_empty_sec; + sinkbuffer_seconds_to_empty += m_audiotrack_empty_sec; +#if defined(HAS_LIBAMCODEC) + if (sinkbuffer_seconds_to_empty > 0.0) + sinkbuffer_seconds_to_empty += 0.250; +#endif + return sinkbuffer_seconds_to_empty; } double CAESinkAUDIOTRACK::GetCacheTotal() @@ -244,7 +264,8 @@ void CAESinkAUDIOTRACK::SetVolume(float scale) // Android uses fixed steps, reverse scale back to percent float gain = CAEUtil::ScaleToGain(scale); m_volume = CAEUtil::GainToPercent(gain); - m_volume_changed = true; + if (!m_passthrough) + m_volume_changed = true; } void CAESinkAUDIOTRACK::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) @@ -313,6 +334,12 @@ void CAESinkAUDIOTRACK::Process() min_buffer_size, GetStaticIntField(jenv, "AudioTrack", "MODE_STREAM")); + // Set the initial volume + float volume = 1.0; + if (!m_passthrough) + volume = m_volume; + CXBMCApp::SetSystemVolume(jenv, volume); + // The AudioTrack object has been created and waiting to play, m_inited.Set(); // yield to give other threads a chance to do some work. @@ -329,7 +356,7 @@ void CAESinkAUDIOTRACK::Process() while (!m_bStop) { - if (m_volume_changed) + if (m_volume_changed && !m_passthrough) { // check of volume changes and make them, // do it here to keep jni calls local to this thread. diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h index 4ba78ce25f..d07ab8d81c 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h +++ b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h @@ -62,6 +62,8 @@ private: CEvent m_wake; CEvent m_inited; volatile bool m_draining; + bool m_passthrough; + double m_audiotrackbuffer_sec; double m_audiotrack_empty_sec; }; diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkProfiler.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkProfiler.cpp index 3ccb83b3ee..7c01573c95 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkProfiler.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkProfiler.cpp @@ -28,7 +28,6 @@ #include "utils/StdString.h" #include "utils/log.h" #include "utils/TimeUtils.h" -#include "settings/GUISettings.h" CAESinkProfiler::CAESinkProfiler() { diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp index 8f82cec31b..ab197a7a2c 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp @@ -26,7 +26,6 @@ #include <stdint.h> #include "../Utils/AEUtil.h" -#include "settings/GUISettings.h" #include "settings/AdvancedSettings.h" #include "utils/StdString.h" #include "utils/log.h" diff --git a/xbmc/cores/AudioEngine/Utils/AERemap.cpp b/xbmc/cores/AudioEngine/Utils/AERemap.cpp index 0ec257b17d..f99d52eeac 100644 --- a/xbmc/cores/AudioEngine/Utils/AERemap.cpp +++ b/xbmc/cores/AudioEngine/Utils/AERemap.cpp @@ -24,7 +24,7 @@ #include "cores/AudioEngine/AEFactory.h" #include "cores/AudioEngine/Utils/AEUtil.h" #include "utils/log.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" using namespace std; @@ -197,7 +197,7 @@ bool CAERemap::Initialize(CAEChannelInfo input, CAEChannelInfo output, bool fina #undef RM - if (g_guiSettings.GetBool("audiooutput.stereoupmix")) + if (CSettings::Get().GetBool("audiooutput.stereoupmix")) BuildUpmixMatrix(input, output); /* normalize the values */ @@ -207,7 +207,7 @@ bool CAERemap::Initialize(CAEChannelInfo input, CAEChannelInfo output, bool fina else { //FIXME: guisetting is reversed, change the setting name after frodo - normalize = !g_guiSettings.GetBool("audiooutput.normalizelevels"); + normalize = !CSettings::Get().GetBool("audiooutput.normalizelevels"); CLog::Log(LOGDEBUG, "AERemap: Downmix normalization is %s", (normalize ? "enabled" : "disabled")); } diff --git a/xbmc/cores/AudioEngine/Utils/AEUtil.h b/xbmc/cores/AudioEngine/Utils/AEUtil.h index 458dc00e39..48cbc3b4a7 100644 --- a/xbmc/cores/AudioEngine/Utils/AEUtil.h +++ b/xbmc/cores/AudioEngine/Utils/AEUtil.h @@ -42,6 +42,23 @@ #define MEMALIGN(b, x) __declspec(align(b)) x #endif +#define AUDIO_IS_BITSTREAM(x) ((x) == AUDIO_IEC958 || (x) == AUDIO_HDMI) + +enum AudioOutputs +{ + AUDIO_ANALOG = 0, + AUDIO_IEC958, + AUDIO_HDMI +}; + +// AV sync options +enum AVSync +{ + SYNC_DISCON = 0, + SYNC_SKIPDUP, + SYNC_RESAMPLE +}; + class CAEUtil { private: diff --git a/xbmc/cores/DllLoader/exports/emu_msvcrt.cpp b/xbmc/cores/DllLoader/exports/emu_msvcrt.cpp index 2f15c971d4..d58ba7857a 100644 --- a/xbmc/cores/DllLoader/exports/emu_msvcrt.cpp +++ b/xbmc/cores/DllLoader/exports/emu_msvcrt.cpp @@ -56,7 +56,7 @@ #include "filesystem/SpecialProtocol.h" #include "URL.h" #include "filesystem/File.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "FileItem.h" #include "filesystem/Directory.h" @@ -200,21 +200,21 @@ extern "C" void __stdcall init_emu_environ() extern "C" void __stdcall update_emu_environ() { // Use a proxy, if the GUI was configured as such - if (g_guiSettings.GetBool("network.usehttpproxy") - && !g_guiSettings.GetString("network.httpproxyserver").empty() - && !g_guiSettings.GetString("network.httpproxyport").empty() - && g_guiSettings.GetInt("network.httpproxytype") == 0) + if (CSettings::Get().GetBool("network.usehttpproxy") + && !CSettings::Get().GetString("network.httpproxyserver").empty() + && !CSettings::Get().GetString("network.httpproxyport").empty() + && CSettings::Get().GetInt("network.httpproxytype") == 0) { CStdString strProxy; - if (g_guiSettings.GetString("network.httpproxyusername") && - g_guiSettings.GetString("network.httpproxypassword")) + if (!CSettings::Get().GetString("network.httpproxyusername").empty() && + !CSettings::Get().GetString("network.httpproxypassword").empty()) { - strProxy.Format("%s:%s@", g_guiSettings.GetString("network.httpproxyusername").c_str(), - g_guiSettings.GetString("network.httpproxypassword").c_str()); + strProxy.Format("%s:%s@", CSettings::Get().GetString("network.httpproxyusername").c_str(), + CSettings::Get().GetString("network.httpproxypassword").c_str()); } - strProxy += g_guiSettings.GetString("network.httpproxyserver"); - strProxy += ":" + g_guiSettings.GetString("network.httpproxyport"); + strProxy += CSettings::Get().GetString("network.httpproxyserver"); + strProxy += ":" + CSettings::Get().GetString("network.httpproxyport"); #ifdef _WIN32 pgwin32_putenv(("HTTP_PROXY=http://" +strProxy).c_str()); diff --git a/xbmc/cores/VideoRenderers/BaseRenderer.cpp b/xbmc/cores/VideoRenderers/BaseRenderer.cpp index 513cf4818c..899cab2964 100644 --- a/xbmc/cores/VideoRenderers/BaseRenderer.cpp +++ b/xbmc/cores/VideoRenderers/BaseRenderer.cpp @@ -23,13 +23,14 @@ #include <algorithm> #include "BaseRenderer.h" #include "settings/DisplaySettings.h" -#include "settings/Settings.h" -#include "settings/GUISettings.h" #include "settings/MediaSettings.h" +#include "settings/Settings.h" #include "guilib/GraphicContext.h" #include "guilib/GUIWindowManager.h" +#include "guilib/LocalizeStrings.h" #include "utils/log.h" #include "utils/MathUtils.h" +#include "utils/SystemInfo.h" #include "settings/AdvancedSettings.h" #include "cores/VideoRenderers/RenderFlags.h" @@ -68,13 +69,19 @@ void CBaseRenderer::RegisterRenderUpdateCallBack(const void *ctx, RenderUpdateCa m_RenderUpdateCallBackCtx = ctx; } +void CBaseRenderer::RegisterRenderFeaturesCallBack(const void *ctx, RenderFeaturesCallBackFn fn) +{ + m_RenderFeaturesCallBackFn = fn; + m_RenderFeaturesCallBackCtx = ctx; +} + void CBaseRenderer::ChooseBestResolution(float fps) { if (fps == 0.0) return; // Adjust refreshrate to match source fps #if !defined(TARGET_DARWIN_IOS) - if (g_guiSettings.GetInt("videoplayer.adjustrefreshrate") != ADJUST_REFRESHRATE_OFF) + if (CSettings::Get().GetInt("videoplayer.adjustrefreshrate") != ADJUST_REFRESHRATE_OFF) { float weight; if (!FindResolutionFromOverride(fps, weight, false)) //find a refreshrate from overrides @@ -427,7 +434,7 @@ void CBaseRenderer::CalcNormalDisplayRect(float offsetX, float offsetY, float sc // allow a certain error to maximize screen size float fCorrection = screenWidth / screenHeight / outputFrameRatio - 1.0f; - float fAllowed = g_guiSettings.GetInt("videoplayer.errorinaspect") * 0.01f; + float fAllowed = CSettings::Get().GetInt("videoplayer.errorinaspect") * 0.01f; if(fCorrection > fAllowed) fCorrection = fAllowed; if(fCorrection < - fAllowed) fCorrection = - fAllowed; @@ -611,7 +618,7 @@ void CBaseRenderer::SetViewMode(int viewMode) CDisplaySettings::Get().SetNonLinearStretched(false); if ( CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode == ViewModeZoom || - (is43 && g_guiSettings.GetInt("videoplayer.stretch43") == ViewModeZoom)) + (is43 && CSettings::Get().GetInt("videoplayer.stretch43") == ViewModeZoom)) { // zoom image so no black bars CDisplaySettings::Get().SetPixelRatio(1.0); // calculate the desired output ratio @@ -643,7 +650,7 @@ void CBaseRenderer::SetViewMode(int viewMode) } } else if ( CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode == ViewModeWideZoom || - (is43 && g_guiSettings.GetInt("videoplayer.stretch43") == ViewModeWideZoom)) + (is43 && CSettings::Get().GetInt("videoplayer.stretch43") == ViewModeWideZoom)) { // super zoom float stretchAmount = (screenWidth / screenHeight) * CDisplaySettings::Get().GetResolutionInfo(res).fPixelRatio / sourceFrameRatio; CDisplaySettings::Get().SetPixelRatio(pow(stretchAmount, float(2.0/3.0))); @@ -651,7 +658,7 @@ void CBaseRenderer::SetViewMode(int viewMode) CDisplaySettings::Get().SetNonLinearStretched(true); } else if ( CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode == ViewModeStretch16x9 || - (is43 && g_guiSettings.GetInt("videoplayer.stretch43") == ViewModeStretch16x9)) + (is43 && CSettings::Get().GetInt("videoplayer.stretch43") == ViewModeStretch16x9)) { // stretch image to 16:9 ratio CDisplaySettings::Get().SetZoomAmount(1.0); if (res == RES_PAL_4x3 || res == RES_PAL60_4x3 || res == RES_NTSC_4x3 || res == RES_HDTV_480p_4x3) @@ -704,3 +711,20 @@ void CBaseRenderer::MarkDirty() g_windowManager.MarkDirty(m_destRect); } +void CBaseRenderer::SettingOptionsRenderMethodsFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t) +{ + list.push_back(make_pair(g_localizeStrings.Get(13416), RENDER_METHOD_AUTO)); + +#ifdef HAS_DX + if (g_sysinfo.IsVistaOrHigher()) + list.push_back(make_pair(g_localizeStrings.Get(16319), RENDER_METHOD_DXVA)); + list.push_back(make_pair(g_localizeStrings.Get(13431), RENDER_METHOD_D3D_PS)); + list.push_back(make_pair(g_localizeStrings.Get(13419), RENDER_METHOD_SOFTWARE)); +#endif + +#ifdef HAS_GL + list.push_back(make_pair(g_localizeStrings.Get(13417), RENDER_METHOD_ARB)); + list.push_back(make_pair(g_localizeStrings.Get(13418), RENDER_METHOD_GLSL)); + list.push_back(make_pair(g_localizeStrings.Get(13419), RENDER_METHOD_SOFTWARE)); +#endif +} diff --git a/xbmc/cores/VideoRenderers/BaseRenderer.h b/xbmc/cores/VideoRenderers/BaseRenderer.h index 3e1944d2e9..ac1a0c8934 100644 --- a/xbmc/cores/VideoRenderers/BaseRenderer.h +++ b/xbmc/cores/VideoRenderers/BaseRenderer.h @@ -20,13 +20,18 @@ * */ +#include <vector> + #include "guilib/Resolution.h" #include "guilib/Geometry.h" #include "RenderFormats.h" +#include "RenderFeatures.h" #define MAX_PLANES 3 #define MAX_FIELDS 3 +class CSetting; + typedef struct YV12Image { BYTE * plane[MAX_PLANES]; @@ -48,24 +53,20 @@ enum EFIELDSYNC FS_BOT }; -enum ERENDERFEATURE +// Render Methods +enum RenderMethods { - RENDERFEATURE_GAMMA, - RENDERFEATURE_BRIGHTNESS, - RENDERFEATURE_CONTRAST, - RENDERFEATURE_NOISE, - RENDERFEATURE_SHARPNESS, - RENDERFEATURE_NONLINSTRETCH, - RENDERFEATURE_ROTATION, - RENDERFEATURE_STRETCH, - RENDERFEATURE_CROP, - RENDERFEATURE_ZOOM, - RENDERFEATURE_VERTICAL_SHIFT, - RENDERFEATURE_PIXEL_RATIO, - RENDERFEATURE_POSTPROCESS + RENDER_METHOD_AUTO = 0, + RENDER_METHOD_ARB, + RENDER_METHOD_GLSL, + RENDER_METHOD_SOFTWARE, + RENDER_METHOD_D3D_PS, + RENDER_METHOD_DXVA, + RENDER_OVERLAYS = 99 // to retain compatibility }; typedef void (*RenderUpdateCallBackFn)(const void *ctx, const CRect &SrcRect, const CRect &DestRect); +typedef void (*RenderFeaturesCallBackFn)(const void *ctx, Features &renderFeatures); struct DVDVideoPicture; @@ -91,6 +92,9 @@ public: std::vector<ERenderFormat> SupportedFormats() { return std::vector<ERenderFormat>(); } virtual void RegisterRenderUpdateCallBack(const void *ctx, RenderUpdateCallBackFn fn); + virtual void RegisterRenderFeaturesCallBack(const void *ctx, RenderFeaturesCallBackFn fn); + + static void SettingOptionsRenderMethodsFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t); protected: void ChooseBestResolution(float fps); @@ -131,4 +135,7 @@ protected: const void* m_RenderUpdateCallBackCtx; RenderUpdateCallBackFn m_RenderUpdateCallBackFn; + + const void* m_RenderFeaturesCallBackCtx; + RenderFeaturesCallBackFn m_RenderFeaturesCallBackFn; }; diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp index 7d53d862b0..267dd40fc2 100644 --- a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp +++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp @@ -30,11 +30,10 @@ #include "LinuxRendererGL.h" #include "Application.h" -#include "settings/Settings.h" #include "settings/AdvancedSettings.h" #include "settings/DisplaySettings.h" -#include "settings/GUISettings.h" #include "settings/MediaSettings.h" +#include "settings/Settings.h" #include "VideoShaders/YUV2RGBShader.h" #include "VideoShaders/VideoFilterShader.h" #include "windowing/WindowingFactory.h" @@ -327,7 +326,7 @@ bool CLinuxRendererGL::Configure(unsigned int width, unsigned int height, unsign m_nonLinStretchGui = false; m_pixelRatio = 1.0; - m_pboSupported = glewIsSupported("GL_ARB_pixel_buffer_object") && g_guiSettings.GetBool("videoplayer.usepbo"); + m_pboSupported = glewIsSupported("GL_ARB_pixel_buffer_object") && CSettings::Get().GetBool("videoplayer.usepbo"); return true; } @@ -984,7 +983,7 @@ void CLinuxRendererGL::LoadShaders(int field) } else { - int requestedMethod = g_guiSettings.GetInt("videoplayer.rendermethod"); + int requestedMethod = CSettings::Get().GetInt("videoplayer.rendermethod"); CLog::Log(LOGDEBUG, "GL: Requested render method: %d", requestedMethod); if (m_pYUVShader) @@ -3204,7 +3203,7 @@ bool CLinuxRendererGL::Supports(ERENDERFEATURE feature) { if(feature == RENDERFEATURE_BRIGHTNESS) { - if ((m_renderMethod & RENDER_VDPAU) && !g_guiSettings.GetBool("videoscreen.limitedrange")) + if ((m_renderMethod & RENDER_VDPAU) && !CSettings::Get().GetBool("videoscreen.limitedrange")) return true; if (m_renderMethod & RENDER_VAAPI) @@ -3217,7 +3216,7 @@ bool CLinuxRendererGL::Supports(ERENDERFEATURE feature) if(feature == RENDERFEATURE_CONTRAST) { - if ((m_renderMethod & RENDER_VDPAU) && !g_guiSettings.GetBool("videoscreen.limitedrange")) + if ((m_renderMethod & RENDER_VDPAU) && !CSettings::Get().GetBool("videoscreen.limitedrange")) return true; if (m_renderMethod & RENDER_VAAPI) @@ -3361,7 +3360,7 @@ bool CLinuxRendererGL::Supports(ESCALINGMETHOD method) // if scaling is below level, avoid hq scaling float scaleX = fabs(((float)m_sourceWidth - m_destRect.Width())/m_sourceWidth)*100; float scaleY = fabs(((float)m_sourceHeight - m_destRect.Height())/m_sourceHeight)*100; - int minScale = g_guiSettings.GetInt("videoplayer.hqscalers"); + int minScale = CSettings::Get().GetInt("videoplayer.hqscalers"); if (scaleX < minScale && scaleY < minScale) return false; diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.h b/xbmc/cores/VideoRenderers/LinuxRendererGL.h index 40e31c58d0..44e69ac930 100644 --- a/xbmc/cores/VideoRenderers/LinuxRendererGL.h +++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.h @@ -30,6 +30,7 @@ #include "guilib/Shader.h" #include "settings/VideoSettings.h" #include "RenderFlags.h" +#include "RenderFormats.h" #include "guilib/GraphicContext.h" #include "BaseRenderer.h" #include "RenderFormats.h" diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp index cca55c78b2..a6dd363fe6 100644 --- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp +++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp @@ -32,11 +32,10 @@ #include "utils/fastmemcpy.h" #include "utils/MathUtils.h" #include "utils/GLUtils.h" -#include "settings/Settings.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" -#include "settings/MediaSettings.h" #include "settings/DisplaySettings.h" +#include "settings/MediaSettings.h" +#include "settings/Settings.h" #include "guilib/FrameBufferObject.h" #include "VideoShaders/YUV2RGBShader.h" #include "VideoShaders/VideoFilterShader.h" @@ -203,6 +202,18 @@ bool CLinuxRendererGLES::Configure(unsigned int width, unsigned int height, unsi m_RenderUpdateCallBackCtx = NULL; if ((m_format == RENDER_FMT_BYPASS) && g_application.GetCurrentPlayer()) { + m_renderFeatures.clear(); + m_scalingMethods.clear(); + m_deinterlaceModes.clear(); + m_deinterlaceMethods.clear(); + + if (m_RenderFeaturesCallBackFn) + { + (*m_RenderFeaturesCallBackFn)(m_RenderFeaturesCallBackCtx, m_renderFeatures); + // after setting up m_renderFeatures, we are done with the callback + m_RenderFeaturesCallBackFn = NULL; + m_RenderFeaturesCallBackCtx = NULL; + } g_application.m_pPlayer->GetRenderFeatures(m_renderFeatures); g_application.m_pPlayer->GetDeinterlaceMethods(m_deinterlaceMethods); g_application.m_pPlayer->GetDeinterlaceModes(m_deinterlaceModes); @@ -621,7 +632,7 @@ void CLinuxRendererGLES::LoadShaders(int field) #ifdef TARGET_DARWIN_IOS float ios_version = GetIOSVersion(); #endif - int requestedMethod = g_guiSettings.GetInt("videoplayer.rendermethod"); + int requestedMethod = CSettings::Get().GetInt("videoplayer.rendermethod"); CLog::Log(LOGDEBUG, "GL: Requested render method: %d", requestedMethod); if (m_pYUVShader) @@ -759,6 +770,8 @@ void CLinuxRendererGLES::UnInit() m_bConfigured = false; m_RenderUpdateCallBackFn = NULL; m_RenderUpdateCallBackCtx = NULL; + m_RenderFeaturesCallBackFn = NULL; + m_RenderFeaturesCallBackCtx = NULL; } inline void CLinuxRendererGLES::ReorderDrawPoints() diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h index cf814d7d8d..ce93e3d87e 100644 --- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h +++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h @@ -29,6 +29,7 @@ #include "xbmc/guilib/Shader.h" #include "settings/VideoSettings.h" #include "RenderFlags.h" +#include "RenderFormats.h" #include "guilib/GraphicContext.h" #include "BaseRenderer.h" #include "xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h" diff --git a/xbmc/cores/VideoRenderers/OverlayRenderer.cpp b/xbmc/cores/VideoRenderers/OverlayRenderer.cpp index 30267a2e5c..59a4732923 100644 --- a/xbmc/cores/VideoRenderers/OverlayRenderer.cpp +++ b/xbmc/cores/VideoRenderers/OverlayRenderer.cpp @@ -26,11 +26,13 @@ #include "cores/dvdplayer/DVDCodecs/Overlay/DVDOverlaySpu.h" #include "cores/dvdplayer/DVDCodecs/Overlay/DVDOverlaySSA.h" #include "cores/VideoRenderers/RenderManager.h" +#include "guilib/GraphicContext.h" #include "Application.h" #include "guilib/GraphicContext.h" #include "windowing/WindowingFactory.h" #include "settings/DisplaySettings.h" #include "settings/Settings.h" +#include "settings/DisplaySettings.h" #include "threads/SingleLock.h" #include "utils/MathUtils.h" #if defined(HAS_GL) || defined(HAS_GLES) diff --git a/xbmc/cores/VideoRenderers/RenderCapture.cpp b/xbmc/cores/VideoRenderers/RenderCapture.cpp index 8b6b0b6bf2..252dea995a 100644 --- a/xbmc/cores/VideoRenderers/RenderCapture.cpp +++ b/xbmc/cores/VideoRenderers/RenderCapture.cpp @@ -22,8 +22,8 @@ #include "utils/log.h" #include "windowing/WindowingFactory.h" #include "utils/fastmemcpy.h" -#include "settings/GUISettings.h" #include "settings/AdvancedSettings.h" +#include "settings/Settings.h" CRenderCaptureBase::CRenderCaptureBase() { @@ -94,7 +94,7 @@ void CRenderCaptureGL::BeginRender() if (!m_asyncChecked) { #ifndef HAS_GLES - bool usePbo = g_guiSettings.GetBool("videoplayer.usepbo"); + bool usePbo = CSettings::Get().GetBool("videoplayer.usepbo"); m_asyncSupported = g_Windowing.IsExtSupported("GL_ARB_pixel_buffer_object") && usePbo; m_occlusionQuerySupported = g_Windowing.IsExtSupported("GL_ARB_occlusion_query"); diff --git a/xbmc/cores/VideoRenderers/RenderFeatures.h b/xbmc/cores/VideoRenderers/RenderFeatures.h new file mode 100644 index 0000000000..6124f52032 --- /dev/null +++ b/xbmc/cores/VideoRenderers/RenderFeatures.h @@ -0,0 +1,41 @@ +#pragma once +/* + * Copyright (C) 2005-2012 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 <vector> + +enum ERENDERFEATURE +{ + RENDERFEATURE_GAMMA, + RENDERFEATURE_BRIGHTNESS, + RENDERFEATURE_CONTRAST, + RENDERFEATURE_NOISE, + RENDERFEATURE_SHARPNESS, + RENDERFEATURE_NONLINSTRETCH, + RENDERFEATURE_ROTATION, + RENDERFEATURE_STRETCH, + RENDERFEATURE_CROP, + RENDERFEATURE_ZOOM, + RENDERFEATURE_VERTICAL_SHIFT, + RENDERFEATURE_PIXEL_RATIO, + RENDERFEATURE_POSTPROCESS +}; + +typedef std::vector<int> Features; diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp index 14c30843e8..b415c2cbbe 100644 --- a/xbmc/cores/VideoRenderers/RenderManager.cpp +++ b/xbmc/cores/VideoRenderers/RenderManager.cpp @@ -31,10 +31,9 @@ #include "Application.h" #include "ApplicationMessenger.h" -#include "settings/Settings.h" -#include "settings/GUISettings.h" #include "settings/AdvancedSettings.h" #include "settings/MediaSettings.h" +#include "settings/Settings.h" #if defined(HAS_GL) #include "LinuxRendererGL.h" @@ -262,6 +261,9 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi CApplicationMessenger::Get().SwitchToFullscreen(); lock.Enter(); } + if( format & RENDER_FMT_BYPASS ) + m_presentmethod = PRESENT_METHOD_BYPASS; + m_pRenderer->Update(false); m_bIsStarted = true; m_bReconfigured = true; @@ -272,7 +274,12 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi return result; } -bool CXBMCRenderManager::IsConfigured() +bool CXBMCRenderManager::RendererHandlesPresent() const +{ + return IsConfigured() && m_presentmethod != PRESENT_METHOD_BYPASS; +} + +bool CXBMCRenderManager::IsConfigured() const { if (!m_pRenderer) return false; @@ -641,7 +648,7 @@ float CXBMCRenderManager::GetMaximumFPS() { float fps; - if (g_guiSettings.GetInt("videoscreen.vsync") != VSYNC_DISABLED) + if (CSettings::Get().GetInt("videoscreen.vsync") != VSYNC_DISABLED) { fps = (float)g_VideoReferenceClock.GetRefreshRate(); if (fps <= 0) fps = g_graphicsContext.GetFPS(); @@ -658,6 +665,12 @@ void CXBMCRenderManager::RegisterRenderUpdateCallBack(const void *ctx, RenderUpd m_pRenderer->RegisterRenderUpdateCallBack(ctx, fn); } +void CXBMCRenderManager::RegisterRenderFeaturesCallBack(const void *ctx, RenderFeaturesCallBackFn fn) +{ + if (m_pRenderer) + m_pRenderer->RegisterRenderFeaturesCallBack(ctx, fn); +} + void CXBMCRenderManager::Render(bool clear, DWORD flags, DWORD alpha) { CSharedLock lock(m_sharedSection); diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h index e79a12ba88..b67629a935 100644 --- a/xbmc/cores/VideoRenderers/RenderManager.h +++ b/xbmc/cores/VideoRenderers/RenderManager.h @@ -66,7 +66,7 @@ public: // Functions called from mplayer bool Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format, unsigned int orientation); - bool IsConfigured(); + bool IsConfigured() const; int AddVideoPicture(DVDVideoPicture& picture); @@ -110,6 +110,8 @@ public: void UpdateResolution(); + bool RendererHandlesPresent() const; + #ifdef HAS_GL CLinuxRendererGL *m_pRenderer; #elif HAS_GLES == 2 @@ -131,6 +133,7 @@ public: CSharedSection& GetSection() { return m_sharedSection; }; void RegisterRenderUpdateCallBack(const void *ctx, RenderUpdateCallBackFn fn); + void RegisterRenderFeaturesCallBack(const void *ctx, RenderFeaturesCallBackFn fn); protected: void Render(bool clear, DWORD flags, DWORD alpha); @@ -164,6 +167,7 @@ protected: PRESENT_METHOD_BLEND, PRESENT_METHOD_WEAVE, PRESENT_METHOD_BOB, + PRESENT_METHOD_BYPASS, }; double m_displayLatency; diff --git a/xbmc/cores/VideoRenderers/WinRenderer.cpp b/xbmc/cores/VideoRenderers/WinRenderer.cpp index 6ed53dcc4c..0f38c9b476 100644 --- a/xbmc/cores/VideoRenderers/WinRenderer.cpp +++ b/xbmc/cores/VideoRenderers/WinRenderer.cpp @@ -23,9 +23,8 @@ #include "WinRenderer.h" #include "Util.h" #include "settings/DisplaySettings.h" -#include "settings/Settings.h" -#include "settings/GUISettings.h" #include "settings/MediaSettings.h" +#include "settings/Settings.h" #include "guilib/Texture.h" #include "windowing/WindowingFactory.h" #include "settings/AdvancedSettings.h" @@ -382,7 +381,7 @@ unsigned int CWinRenderer::PreInit() g_Windowing.Get3DDevice()->GetDeviceCaps(&m_deviceCaps); - m_iRequestedMethod = g_guiSettings.GetInt("videoplayer.rendermethod"); + m_iRequestedMethod = CSettings::Get().GetInt("videoplayer.rendermethod"); if ((g_advancedSettings.m_DXVAForceProcessorRenderer || m_iRequestedMethod == RENDER_METHOD_DXVA) && !m_processor.PreInit()) CLog::Log(LOGNOTICE, "CWinRenderer::Preinit - could not init DXVA2 processor - skipping"); @@ -1085,7 +1084,7 @@ bool CWinRenderer::Supports(ESCALINGMETHOD method) // if scaling is below level, avoid hq scaling float scaleX = fabs(((float)m_sourceWidth - m_destRect.Width())/m_sourceWidth)*100; float scaleY = fabs(((float)m_sourceHeight - m_destRect.Height())/m_sourceHeight)*100; - int minScale = g_guiSettings.GetInt("videoplayer.hqscalers"); + int minScale = CSettings::Get().GetInt("videoplayer.hqscalers"); if (scaleX < minScale && scaleY < minScale) return false; return true; diff --git a/xbmc/cores/VideoRenderers/WinRenderer.h b/xbmc/cores/VideoRenderers/WinRenderer.h index 251aa31c19..3887343cc4 100644 --- a/xbmc/cores/VideoRenderers/WinRenderer.h +++ b/xbmc/cores/VideoRenderers/WinRenderer.h @@ -24,6 +24,7 @@ #include "guilib/GraphicContext.h" #include "RenderFlags.h" +#include "RenderFormats.h" #include "BaseRenderer.h" #include "guilib/D3DResource.h" #include "RenderCapture.h" diff --git a/xbmc/cores/VideoRenderers/legacy/ComboRenderer.cpp b/xbmc/cores/VideoRenderers/legacy/ComboRenderer.cpp index eb6078be89..6cc8842b2e 100644 --- a/xbmc/cores/VideoRenderers/legacy/ComboRenderer.cpp +++ b/xbmc/cores/VideoRenderers/legacy/ComboRenderer.cpp @@ -21,7 +21,7 @@ #include "stdafx.h" #include "ComboRenderer.h" #include "Application.h" -#include "Settings.h" +#include "settings/Settings.h" #include "settings/DisplaySettings.h" CComboRenderer::CComboRenderer(LPDIRECT3DDEVICE8 pDevice) @@ -384,7 +384,7 @@ void CComboRenderer::CheckScreenSaver() if (g_application.IsInScreenSaver() && !m_bHasDimView) { D3DLOCKED_RECT lr; - float fAmount = (float)g_guiSettings.GetInt("screensaver.dimlevel") / 100.0f; + float fAmount = (float)CSettings::Get().GetInt("screensaver.dimlevel") / 100.0f; if ( D3D_OK == m_YUY2Texture[m_iYUY2RenderBuffer]->LockRect(0, &lr, NULL, 0 )) { // Drop brightness of current surface to 20% diff --git a/xbmc/cores/amlplayer/AMLPlayer.cpp b/xbmc/cores/amlplayer/AMLPlayer.cpp index 59917ab299..47e41e8d32 100644 --- a/xbmc/cores/amlplayer/AMLPlayer.cpp +++ b/xbmc/cores/amlplayer/AMLPlayer.cpp @@ -27,6 +27,7 @@ #include "GUIInfoManager.h" #include "video/VideoThumbLoader.h" #include "Util.h" +#include "cores/AudioEngine/AEFactory.h" #include "cores/AudioEngine/Utils/AEUtil.h" #include "cores/VideoRenderers/RenderFlags.h" #include "cores/VideoRenderers/RenderFormats.h" @@ -37,9 +38,9 @@ #include "guilib/GUIWindowManager.h" #include "guilib/LocalizeStrings.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" -#include "settings/Settings.h" #include "settings/VideoSettings.h" +#include "settings/MediaSettings.h" +#include "settings/Settings.h" #include "threads/SingleLock.h" #include "utils/log.h" #include "utils/TimeUtils.h" @@ -55,9 +56,23 @@ #include "settings/VideoSettings.h" // amlogic libplayer -#include "AMLUtils.h" +#include "utils/AMLUtils.h" #include "DllLibamplayer.h" +static float VolumePercentToScale(float volume) +{ + float audio_volume = 0.0; + if (volume > VOLUME_MINIMUM) + { + float dB = CAEUtil::PercentToGain(volume); + audio_volume = CAEUtil::GainToScale(dB); + } + if (audio_volume >= 0.99f) + audio_volume = 1.0f; + + return audio_volume; +} + struct AMLChapterInfo { std::string name; @@ -313,6 +328,12 @@ CAMLSubTitleThread::~CAMLSubTitleThread() StopThread(); } +void CAMLSubTitleThread::Flush() +{ + CSingleLock lock(m_subtitle_csection); + m_subtitle_strings.clear(); +} + void CAMLSubTitleThread::UpdateSubtitle(CStdString &subtitle, int64_t elapsed_ms) { CSingleLock lock(m_subtitle_csection); @@ -380,9 +401,10 @@ void CAMLSubTitleThread::Process(void) CSingleLock lock(m_subtitle_csection); AMLSubtitle *subtitle = new AMLSubtitle; - int sub_type = (sub_buffer[5] << 16) | (sub_buffer[6] << 8) | sub_buffer[7]; + + int sub_type = (sub_buffer[5] << 16) | (sub_buffer[6] << 8) | sub_buffer[7]; // sub_pts are in ffmpeg timebase, not ms timebase, convert it. - int sub_pts = (sub_buffer[12] << 24) | (sub_buffer[13] << 16) | (sub_buffer[14] << 8) | sub_buffer[15]; + int sub_pts = (sub_buffer[12] << 24) | (sub_buffer[13] << 16) | (sub_buffer[14] << 8) | sub_buffer[15]; /* TODO: handle other subtitle codec types // subtitle codecs @@ -482,12 +504,14 @@ void CAMLSubTitleThread::Process(void) } else { - usleep(100 * 1000); + if (!m_bStop) + usleep(100 * 1000); } } else { - usleep(250 * 1000); + if (!m_bStop) + usleep(250 * 1000); } } m_subtitle_strings.clear(); @@ -524,7 +548,6 @@ CAMLPlayer::CAMLPlayer(IPlayerCallback &callback) m_subtitle_show (false ), m_subtitle_delay (0 ), m_subtitle_thread (NULL ), - m_chapter_index (0 ), m_chapter_count (0 ), m_show_mainvideo (0 ), m_view_mode (0 ), @@ -544,6 +567,13 @@ CAMLPlayer::CAMLPlayer(IPlayerCallback &callback) // for external subtitles m_dvdOverlayContainer = new CDVDOverlayContainer; m_dvdPlayerSubtitle = new CDVDPlayerSubtitle(m_dvdOverlayContainer); + + // Suspend AE temporarily so exclusive or hog-mode sinks + // don't block external player's access to audio device + if (!CAEFactory::Suspend()) + { + CLog::Log(LOGNOTICE,"%s: Failed to suspend AudioEngine before launching external player", __FUNCTION__); + } } CAMLPlayer::~CAMLPlayer() @@ -553,6 +583,12 @@ CAMLPlayer::~CAMLPlayer() delete m_dvdPlayerSubtitle; delete m_dvdOverlayContainer; delete m_dll, m_dll = NULL; + + // Resume AE processing of XBMC native audio + if (!CAEFactory::Resume()) + { + CLog::Log(LOGFATAL, "%s: Failed to restart AudioEngine after return from external player",__FUNCTION__); + } } bool CAMLPlayer::OpenFile(const CFileItem &file, const CPlayerOptions &options) @@ -570,13 +606,16 @@ bool CAMLPlayer::OpenFile(const CFileItem &file, const CPlayerOptions &options) m_item = file; m_options = options; + m_pid = -1; m_elapsed_ms = 0; m_duration_ms = 0; m_audio_info = "none"; m_audio_delay = 0; - m_audio_passthrough_ac3 = g_guiSettings.GetBool("audiooutput.ac3passthrough"); - m_audio_passthrough_dts = g_guiSettings.GetBool("audiooutput.dtspassthrough"); + m_audio_mute = CAEFactory::IsMuted(); + m_audio_volume = VolumePercentToScale(CAEFactory::GetVolume()); + m_audio_passthrough_ac3 = CSettings::Get().GetBool("audiooutput.ac3passthrough"); + m_audio_passthrough_dts = CSettings::Get().GetBool("audiooutput.dtspassthrough"); m_video_info = "none"; m_video_width = 0; @@ -587,7 +626,6 @@ bool CAMLPlayer::OpenFile(const CFileItem &file, const CPlayerOptions &options) m_subtitle_delay = 0; m_subtitle_thread = NULL; - m_chapter_index = 0; m_chapter_count = 0; m_show_mainvideo = -1; @@ -598,6 +636,9 @@ bool CAMLPlayer::OpenFile(const CFileItem &file, const CPlayerOptions &options) ClearStreamInfos(); + if (m_item.IsDVDFile() || m_item.IsDVD()) + return false; + // setup to spin the busy dialog until we are playing m_ready.Reset(); @@ -805,7 +846,8 @@ float CAMLPlayer::GetPercentage() void CAMLPlayer::SetMute(bool bOnOff) { m_audio_mute = bOnOff; -#if !defined(TARGET_ANDROID) + +#if defined(HAS_AMLPLAYER_AUDIO_SETVOLUME) CSingleLock lock(m_aml_csection); if (m_dll->check_pid_valid(m_pid)) { @@ -819,16 +861,10 @@ void CAMLPlayer::SetMute(bool bOnOff) void CAMLPlayer::SetVolume(float volume) { - m_audio_volume = 0.0f; - if (volume > VOLUME_MINIMUM) - { - float dB = CAEUtil::PercentToGain(volume); - m_audio_volume = CAEUtil::GainToScale(dB); - } - if (m_audio_volume >= 0.99f) - m_audio_volume = 1.0f; + // volume is a float percent from 0.0 to 1.0 + m_audio_volume = VolumePercentToScale(volume); -#if !defined(TARGET_ANDROID) +#if defined(HAS_AMLPLAYER_AUDIO_SETVOLUME) CSingleLock lock(m_aml_csection); if (!m_audio_mute && m_dll->check_pid_valid(m_pid)) m_dll->audio_set_volume(m_pid, m_audio_volume); @@ -892,11 +928,13 @@ void CAMLPlayer::SetAVDelay(float fValue) CLog::Log(LOGDEBUG, "CAMLPlayer::SetAVDelay (%f)", fValue); m_audio_delay = fValue * 1000.0; +#if defined(HAS_AMLPLAYER_AUDIO_SETDELAY) if (m_audio_streams.size() && m_dll->check_pid_valid(m_pid)) { CSingleLock lock(m_aml_csection); m_dll->audio_set_delay(m_pid, m_audio_delay); } +#endif } float CAMLPlayer::GetAVDelay() @@ -961,7 +999,12 @@ void CAMLPlayer::SetSubtitle(int iStream) return; if (m_dll->check_pid_valid(m_pid) && m_subtitle_streams[m_subtitle_index]->source == STREAM_SOURCE_NONE) + { m_dll->player_sid(m_pid, m_subtitle_streams[m_subtitle_index]->id); + aml_set_sysfs_int("/sys/class/subtitle/curr", m_subtitle_index); + if (m_subtitle_thread) + m_subtitle_thread->Flush(); + } else { m_dvdPlayerSubtitle->CloseStream(true); @@ -981,12 +1024,19 @@ void CAMLPlayer::SetSubtitleVisible(bool bVisible) if (m_subtitle_show && m_subtitle_count) { + if (CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleStream < m_subtitle_count) + m_subtitle_index = CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleStream; // on startup, if asked to show subs and SetSubtitle has not // been called, we are expected to switch/show the 1st subtitle if (m_subtitle_index < 0) m_subtitle_index = 0; if (m_dll->check_pid_valid(m_pid) && m_subtitle_streams[m_subtitle_index]->source == STREAM_SOURCE_NONE) + { m_dll->player_sid(m_pid, m_subtitle_streams[m_subtitle_index]->id); + aml_set_sysfs_int("/sys/class/subtitle/curr", m_subtitle_index); + if (m_subtitle_thread) + m_subtitle_thread->Flush(); + } else OpenSubtitleStream(m_subtitle_index); } @@ -1004,6 +1054,16 @@ void CAMLPlayer::Update(bool bPauseDrawing) g_renderManager.Update(bPauseDrawing); } +void CAMLPlayer::GetVideoRect(CRect& SrcRect, CRect& DestRect) +{ + g_renderManager.GetVideoRect(SrcRect, DestRect); +} + +void CAMLPlayer::GetVideoAspectRatio(float &fAR) +{ + fAR = g_renderManager.GetAspectRatio(); +} + int CAMLPlayer::GetChapterCount() { return m_chapter_count; @@ -1011,14 +1071,16 @@ int CAMLPlayer::GetChapterCount() int CAMLPlayer::GetChapter() { + // returns a one based value or zero if no chapters GetStatus(); - for (int i = 0; i < m_chapter_count - 1; i++) + int chapter_index = -1; + for (int i = 0; i < m_chapter_count; i++) { - if (m_elapsed_ms >= m_chapters[i]->seekto_ms && m_elapsed_ms < m_chapters[i + 1]->seekto_ms) - return i + 1; + if (m_elapsed_ms >= m_chapters[i]->seekto_ms) + chapter_index = i; } - return 0; + return chapter_index + 1; } void CAMLPlayer::GetChapterName(CStdString& strChapterName) @@ -1071,7 +1133,7 @@ float CAMLPlayer::GetActualFPS() return video_fps; } -void CAMLPlayer::SeekTime(__int64 seek_ms) +void CAMLPlayer::SeekTime(int64_t seek_ms) { CSingleLock lock(m_aml_csection); @@ -1091,17 +1153,15 @@ void CAMLPlayer::SeekTime(__int64 seek_ms) m_dll->player_timesearch(m_pid, (float)seek_ms/1000.0); WaitForSearchOK(5000); WaitForPlaying(5000); - // restore system volume setting. - SetVolume(m_audio_volume); } } -__int64 CAMLPlayer::GetTime() +int64_t CAMLPlayer::GetTime() { return m_elapsed_ms; } -__int64 CAMLPlayer::GetTotalTime() +int64_t CAMLPlayer::GetTotalTime() { return m_duration_ms; } @@ -1268,7 +1328,6 @@ void CAMLPlayer::OnStartup() void CAMLPlayer::OnExit() { //CLog::Log(LOGNOTICE, "CAMLPlayer::OnExit()"); - Sleep(1000); m_bStop = true; // if we didn't stop playing, advance to the next item in xbmc's playlist @@ -1289,15 +1348,6 @@ void CAMLPlayer::Process() CLog::Log(LOGNOTICE, "CAMLPlayer::Process"); try { - if (CJobManager::GetInstance().IsProcessing(CJob::PRIORITY_LOW)) - { - if (!WaitForPausedThumbJobs(20000)) - { - CJobManager::GetInstance().UnPause(kJobTypeMediaFlags); - throw "CAMLPlayer::Process:thumbgen jobs still running !!!"; - } - } - static AML_URLProtocol vfs_protocol = { "vfs", CFileURLProtocol::Open, @@ -1368,6 +1418,33 @@ void CAMLPlayer::Process() vfs_protocol.name = http_name; url = "xb-" + url; } + else if (url.Left(strlen("sftp://")).Equals("sftp://")) + { + // the name string needs to persist + static const char *http_name = "xb-sftp"; + vfs_protocol.name = http_name; + url = "xb-" + url; + } + else if (url.Left(strlen("udp://")).Equals("udp://")) + { + std::string udp_params; + // bump up the default udp params for ffmpeg. + // ffmpeg will strip out 'dummy=10', we only add it + // to make the logic below with prpending '&' work right. + // to watch for udp errors, 'cat /proc/net/udp' + if (url.find("?") == std::string::npos) + udp_params.append("?dummy=10"); + if (url.find("pkt_size=") == std::string::npos) + udp_params.append("&pkt_size=5264"); + if (url.find("buffer_size=") == std::string::npos) + udp_params.append("&buffer_size=5390336"); + // newer ffmpeg uses fifo_size instead of buf_size + if (url.find("buf_size=") == std::string::npos) + udp_params.append("&buf_size=5390336"); + + if (udp_params.size() > 0) + url.append(udp_params); + } CLog::Log(LOGDEBUG, "CAMLPlayer::Process: URL=%s", url.c_str()); if (m_dll->player_init() != PLAYER_SUCCESS) @@ -1376,7 +1453,7 @@ void CAMLPlayer::Process() throw "CAMLPlayer::Process:player init failed"; } CLog::Log(LOGDEBUG, "player init......"); - usleep(250 * 1000); + usleep(50 * 1000); // must be after player_init m_dll->av_register_protocol2(&vfs_protocol, sizeof(vfs_protocol)); @@ -1400,13 +1477,20 @@ void CAMLPlayer::Process() play_control.need_start = 1; // if 0,you can omit player_start_play API. // just play video/audio immediately. // if 1,then need call "player_start_play" API; - //play_control.auto_buffing_enable = 1; - //play_control.buffing_min = 0.2; - //play_control.buffing_middle = 0.5; - //play_control.buffing_max = 0.8; - //play_control.byteiobufsize =; // maps to av_open_input_file buffer size - //play_control.loopbufsize =; - //play_control.enable_rw_on_pause =; + play_control.displast_frame = 0; // 0:black out when player exit 1:keep last frame when player exit + + // tweak player playback buffers for udp + if (url.Left(strlen("udp://")).Equals("udp://")) + { + play_control.auto_buffing_enable = 1; + play_control.buffing_min = 0.01; // default = 0.01 + play_control.buffing_middle = 0.02; // default = 0.02 + play_control.buffing_max = 0.20; // default = 0.80 + play_control.byteiobufsize = 1024 * 128; // maps to av_open_input_file buffer size (1024 * 32) + //play_control.loopbufsize =; + //play_control.enable_rw_on_pause =; + } + m_aml_state.clear(); m_aml_state.push_back(0); m_pid = m_dll->player_start(&play_control, 0); @@ -1445,13 +1529,7 @@ void CAMLPlayer::Process() // get our initial status. GetStatus(); - // restore mute setting. - SetMute(g_application.IsMuted()); - - // restore system volume setting. - SetVolume(g_application.GetVolume(false)); - - // the default staturation is to high, drop it + // the default staturation is too high, drop it SetVideoSaturation(110); // drop CGUIDialogBusy dialog and release the hold in OpenFile. @@ -1557,13 +1635,14 @@ void CAMLPlayer::Process() case PLAYER_EXIT: if (m_log_level > 5) { - CLog::Log(LOGDEBUG, "CAMLPlayer::Process PLAYER_STOPED"); + CLog::Log(LOGDEBUG, "CAMLPlayer::Process PLAYER_STOPPED"); CLog::Log(LOGDEBUG, "CAMLPlayer::Process: %s", m_dll->player_status2str(pstatus)); } stopPlaying = true; break; } - usleep(250 * 1000); + if (!stopPlaying) + usleep(250 * 1000); } } } @@ -1599,48 +1678,45 @@ void CAMLPlayer::Process() if (m_log_level > 5) CLog::Log(LOGDEBUG, "CAMLPlayer::Process exit"); } -/* -void CAMLPlayer::GetRenderFeatures(Features* renderFeatures) + +void CAMLPlayer::GetRenderFeatures(std::vector<int> &renderFeatures) { - renderFeatures->push_back(RENDERFEATURE_ZOOM); - renderFeatures->push_back(RENDERFEATURE_CONTRAST); - renderFeatures->push_back(RENDERFEATURE_BRIGHTNESS); - renderFeatures->push_back(RENDERFEATURE_STRETCH); - return; + renderFeatures.push_back(RENDERFEATURE_ZOOM); + renderFeatures.push_back(RENDERFEATURE_CONTRAST); + renderFeatures.push_back(RENDERFEATURE_BRIGHTNESS); + renderFeatures.push_back(RENDERFEATURE_STRETCH); } -void CAMLPlayer::GetDeinterlaceMethods(Features* deinterlaceMethods) +void CAMLPlayer::GetDeinterlaceMethods(std::vector<int> &deinterlaceMethods) { - deinterlaceMethods->push_back(VS_INTERLACEMETHOD_DEINTERLACE); - return; + deinterlaceMethods.push_back(VS_INTERLACEMETHOD_DEINTERLACE); } -void CAMLPlayer::GetDeinterlaceModes(Features* deinterlaceModes) +void CAMLPlayer::GetDeinterlaceModes(std::vector<int> &deinterlaceModes) { - deinterlaceModes->push_back(VS_DEINTERLACEMODE_AUTO); - return; + deinterlaceModes.push_back(VS_DEINTERLACEMODE_AUTO); } -void CAMLPlayer::GetScalingMethods(Features* scalingMethods) +void CAMLPlayer::GetScalingMethods(std::vector<int> &scalingMethods) { - return; } -void CAMLPlayer::GetAudioCapabilities(Features* audioCaps) +void CAMLPlayer::GetAudioCapabilities(std::vector<int> &audioCaps) { - audioCaps->push_back(IPC_AUD_OFFSET); - audioCaps->push_back(IPC_AUD_SELECT_STREAM); - return; + audioCaps.push_back(IPC_AUD_SELECT_STREAM); + audioCaps.push_back(IPC_AUD_SELECT_OUTPUT); +#if defined(HAS_AMLPLAYER_AUDIO_SETDELAY) + audioCaps.push_back(IPC_AUD_OFFSET); +#endif } -void CAMLPlayer::GetSubtitleCapabilities(Features* subCaps) +void CAMLPlayer::GetSubtitleCapabilities(std::vector<int> &subCaps) { - subCaps->push_back(IPC_SUBS_EXTERNAL); - subCaps->push_back(IPC_SUBS_OFFSET); - subCaps->push_back(IPC_SUBS_SELECT); - return; + subCaps.push_back(IPC_SUBS_EXTERNAL); + subCaps.push_back(IPC_SUBS_SELECT); + subCaps.push_back(IPC_SUBS_OFFSET); } -*/ + //////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////// @@ -1695,23 +1771,6 @@ void CAMLPlayer::SetAudioPassThrough(int format) (m_audio_passthrough_dts && format == AFORMAT_DTS)); } -bool CAMLPlayer::WaitForPausedThumbJobs(int timeout_ms) -{ - // use m_bStop and Sleep so we can get canceled. - while (!m_bStop && (timeout_ms > 0)) - { - if (CJobManager::GetInstance().IsProcessing(CJob::PRIORITY_LOW)) - { - Sleep(100); - timeout_ms -= 100; - } - else - return true; - } - - return false; -} - int CAMLPlayer::GetPlayerSerializedState(void) { CSingleLock lock(m_aml_state_csection); @@ -1774,8 +1833,8 @@ bool CAMLPlayer::WaitForStopped(int timeout_ms) switch(pstatus) { default: - usleep(100 * 1000); - timeout_ms -= 100; + usleep(20 * 1000); + timeout_ms -= 20; break; case PLAYER_PLAYEND: case PLAYER_STOPED: @@ -1800,8 +1859,8 @@ bool CAMLPlayer::WaitForSearchOK(int timeout_ms) switch(pstatus) { default: - usleep(100 * 1000); - timeout_ms -= 100; + usleep(20 * 1000); + timeout_ms -= 20; break; case PLAYER_STOPED: return false; @@ -1821,23 +1880,22 @@ bool CAMLPlayer::WaitForSearchOK(int timeout_ms) bool CAMLPlayer::WaitForPlaying(int timeout_ms) { - // force the volume off in case we are starting muted - m_audio_mute = true; while (!m_bAbortRequest && (timeout_ms > 0)) { -#if !defined(TARGET_ANDROID) - // anoying that we have to hammer audio_set_volume - // but have to catch it before any audio comes out. - m_dll->audio_set_volume(m_pid, 0.0); -#endif + // anoying that we have to hammer setting audio volume via mute + // but we have to catch it before any audio comes out. + // we cannot do this for m1 (playback will bork) so trap it out. + if (aml_get_cputype() != 1) + SetMute(m_audio_mute); + player_status pstatus = (player_status)GetPlayerSerializedState(); if (m_log_level > 5) CLog::Log(LOGDEBUG, "CAMLPlayer::WaitForPlaying: %s", m_dll->player_status2str(pstatus)); switch(pstatus) { default: - usleep(100 * 1000); - timeout_ms -= 100; + usleep(20 * 1000); + timeout_ms -= 20; break; case PLAYER_ERROR: case PLAYER_EXIT: @@ -1845,6 +1903,8 @@ bool CAMLPlayer::WaitForPlaying(int timeout_ms) return false; break; case PLAYER_RUNNING: + // restore mute/volume settings + SetMute(m_audio_mute); return true; break; } @@ -1863,8 +1923,8 @@ bool CAMLPlayer::WaitForFormatValid(int timeout_ms) switch(pstatus) { default: - usleep(100 * 1000); - timeout_ms -= 100; + usleep(20 * 1000); + timeout_ms -= 20; break; case PLAYER_ERROR: case PLAYER_EXIT: @@ -1875,35 +1935,50 @@ bool CAMLPlayer::WaitForFormatValid(int timeout_ms) ClearStreamInfos(); - media_info_t media_info; + media_info_t media_info = {{0}}; +#if defined(TARGET_ANDROID) + // media_info_t might be different so check its size. + // player_get_media_info will memset to zero the passed + // structure so alloc more space and preset to a know value + // so we can compare the size we use to the size the lib uses. + int msize = sizeof(media_info_t) + 10240; + media_info_t *test_media_info = (media_info_t*)calloc(msize, 1); + memset(test_media_info, 0xEF, msize); + + int res = m_dll->player_get_media_info(m_pid, test_media_info); + + uint8_t *t1 = (uint8_t*)test_media_info; + for (size_t i = msize-1; i >= 0; i--) + { + if (t1[i] != 0xEF) + { + if (sizeof(media_info_t) != i+1) + { + CLog::Log(LOGERROR, "CAMLPlayer::media_info_t(%d) size changed to %d", + sizeof(media_info_t), i+1); + // size is different, we cannot trust it + free(test_media_info); + return false; + } + break; + } + } + media_info = *test_media_info; + free(test_media_info); +#else int res = m_dll->player_get_media_info(m_pid, &media_info); +#endif if (res != PLAYER_SUCCESS) return false; if (m_log_level > 5) - { media_info_dump(&media_info); - // m_video_index, m_audio_index, m_subtitle_index might be -1 eventhough - // total_video_xxx is > 0, not sure why, they should be set to zero or - // some other sensible value. - CLog::Log(LOGDEBUG, "CAMLPlayer::WaitForFormatValid: " - "m_video_index(%d), m_audio_index(%d), m_subtitle_index(%d), m_chapter_count(%d)", - media_info.stream_info.cur_video_index, - media_info.stream_info.cur_audio_index, -#if !defined(TARGET_ANDROID) - media_info.stream_info.cur_sub_index, - media_info.stream_info.total_chapter_num); -#else - media_info.stream_info.cur_sub_index, - 0); -#endif - } - // video info if (media_info.stream_info.has_video && media_info.stream_info.total_video_num > 0) { - for (int i = 0; i < media_info.stream_info.total_video_num; i++) + for (int i = 0; i < media_info.stream_info.total_video_num && + media_info.stream_info.total_video_num < MAX_VIDEO_STREAMS; i++) { AMLPlayerStreamInfo *info = new AMLPlayerStreamInfo; info->Clear(); @@ -1940,7 +2015,8 @@ bool CAMLPlayer::WaitForFormatValid(int timeout_ms) // audio info if (media_info.stream_info.has_audio && media_info.stream_info.total_audio_num > 0) { - for (int i = 0; i < media_info.stream_info.total_audio_num; i++) + for (int i = 0; i < media_info.stream_info.total_audio_num && + media_info.stream_info.total_audio_num < MAX_AUDIO_STREAMS; i++) { AMLPlayerStreamInfo *info = new AMLPlayerStreamInfo; info->Clear(); @@ -1952,19 +2028,11 @@ bool CAMLPlayer::WaitForFormatValid(int timeout_ms) info->bit_rate = media_info.audio_info[i]->bit_rate; info->duration = media_info.audio_info[i]->duration; info->format = media_info.audio_info[i]->aformat; -#if !defined(TARGET_ANDROID) +#if defined(HAS_AMLPLAYER_AUDIO_LANG) if (media_info.audio_info[i]->audio_language[0] != 0) - { info->language = std::string(media_info.audio_info[i]->audio_language, 3); - - if (info->language.length() == 2) - { - CStdString lang; - g_LangCodeExpander.ConvertToThreeCharCode(lang, info->language); - info->language = lang; - } - } #endif + m_audio_streams.push_back(info); } @@ -1979,7 +2047,7 @@ bool CAMLPlayer::WaitForFormatValid(int timeout_ms) // subtitle info if (media_info.stream_info.has_sub && media_info.stream_info.total_sub_num > 0) { - for (int i = 0; i < media_info.stream_info.total_sub_num; i++) + for (int i = 0; i < media_info.stream_info.total_sub_num && i < MAX_SUB_STREAMS; i++) { AMLPlayerStreamInfo *info = new AMLPlayerStreamInfo; info->Clear(); @@ -1987,16 +2055,7 @@ bool CAMLPlayer::WaitForFormatValid(int timeout_ms) info->id = media_info.sub_info[i]->id; info->type = STREAM_SUBTITLE; if (media_info.sub_info[i]->sub_language && media_info.sub_info[i]->sub_language[0] != 0) - { info->language = std::string(media_info.sub_info[i]->sub_language, 3); - - if (info->language.length() == 2) - { - CStdString lang; - g_LangCodeExpander.ConvertToThreeCharCode(lang, info->language); - info->language = lang; - } - } m_subtitle_streams.push_back(info); } m_subtitle_index = media_info.stream_info.cur_sub_index; @@ -2008,12 +2067,12 @@ bool CAMLPlayer::WaitForFormatValid(int timeout_ms) if (m_subtitle_count && m_subtitle_index != 0) m_subtitle_index = 0; -#if !defined(TARGET_ANDROID) +#if defined(HAS_AMLPLAYER_CHAPTERS) // chapter info if (media_info.stream_info.total_chapter_num > 0) { m_chapter_count = media_info.stream_info.total_chapter_num; - for (int i = 0; i < m_chapter_count; i++) + for (int i = 0; i < m_chapter_count && m_chapter_count < MAX_CHAPTERS; i++) { if (media_info.chapter_info[i] != NULL) { @@ -2026,6 +2085,7 @@ bool CAMLPlayer::WaitForFormatValid(int timeout_ms) } } #endif + return true; break; } @@ -2127,11 +2187,11 @@ void CAMLPlayer::FindSubtitleFiles() int CAMLPlayer::AddSubtitleFile(const std::string &filename, const std::string &subfilename) { std::string ext = URIUtils::GetExtension(filename); + std::string vobsubfile = subfilename; if(ext == ".idx") { /* TODO: we do not handle idx/sub binary subs yet. - std::string vobsubfile = subfilename; if (vobsubfile.empty()) vobsubfile = URIUtils::ReplaceExtension(filename, ".sub"); @@ -2303,6 +2363,8 @@ void CAMLPlayer::SetVideoRect(const CRect &SrcRect, const CRect &DestRect) char video_axis[256] = {0}; sprintf(video_axis, "%d %d %d %d", (int)dst_rect.x1, (int)dst_rect.y1, (int)dst_rect.x2, (int)dst_rect.y2); aml_set_sysfs_str("/sys/class/video/axis", video_axis); + // make sure we are in 'full stretch' so we can stretch + aml_set_sysfs_int("/sys/class/video/screen_mode", 1); /* CStdString rectangle; rectangle.Format("%i,%i,%i,%i", @@ -2321,41 +2383,3 @@ void CAMLPlayer::RenderUpdateCallBack(const void *ctx, const CRect &SrcRect, con player->SetVideoRect(SrcRect, DestRect); } -void CAMLPlayer::GetRenderFeatures(std::vector<int> &renderFeatures) -{ - renderFeatures.push_back(RENDERFEATURE_ZOOM); - renderFeatures.push_back(RENDERFEATURE_CONTRAST); - renderFeatures.push_back(RENDERFEATURE_BRIGHTNESS); - renderFeatures.push_back(RENDERFEATURE_STRETCH); -} - -void CAMLPlayer::GetDeinterlaceMethods(std::vector<int> &deinterlaceMethods) -{ - deinterlaceMethods.push_back(VS_INTERLACEMETHOD_DEINTERLACE); -} - -void CAMLPlayer::GetDeinterlaceModes(std::vector<int> &deinterlaceModes) -{ - deinterlaceModes.push_back(VS_DEINTERLACEMODE_AUTO); -} - -void CAMLPlayer::GetScalingMethods(std::vector<int> &scalingMethods) -{ -} - -void CAMLPlayer::GetAudioCapabilities(std::vector<int> &audioCaps) -{ - audioCaps.push_back(IPC_AUD_SELECT_STREAM); - audioCaps.push_back(IPC_AUD_SELECT_OUTPUT); -#if !defined(TARGET_ANDROID) - audioCaps.push_back(IPC_AUD_OFFSET); -#endif -} - -void CAMLPlayer::GetSubtitleCapabilities(std::vector<int> &subCaps) -{ - subCaps.push_back(IPC_SUBS_EXTERNAL); - subCaps.push_back(IPC_SUBS_SELECT); - subCaps.push_back(IPC_SUBS_OFFSET); -} - diff --git a/xbmc/cores/amlplayer/AMLPlayer.h b/xbmc/cores/amlplayer/AMLPlayer.h index 56557a8565..6eb7e50541 100644 --- a/xbmc/cores/amlplayer/AMLPlayer.h +++ b/xbmc/cores/amlplayer/AMLPlayer.h @@ -43,6 +43,7 @@ public: CAMLSubTitleThread(DllLibAmplayer* dll); virtual ~CAMLSubTitleThread(); + void Flush(); void UpdateSubtitle(CStdString &subtitle, int64_t elapsed_ms); protected: virtual void Process(void); @@ -81,13 +82,15 @@ public: virtual void SeekPercentage(float fPercent = 0.0f); virtual float GetPercentage(); virtual void SetMute(bool bOnOff); - virtual void SetVolume(float volume); virtual bool ControlsVolume() {return true;} + virtual void SetVolume(float volume); virtual void SetDynamicRangeCompression(long drc) {} virtual void GetAudioInfo(CStdString &strAudioInfo); virtual void GetVideoInfo(CStdString &strVideoInfo); virtual void GetGeneralInfo(CStdString &strVideoInfo) {}; virtual void Update(bool bPauseDrawing); + virtual void GetVideoRect(CRect& SrcRect, CRect& DestRect); + virtual void GetVideoAspectRatio(float &fAR); virtual bool CanRecord() {return false;}; virtual bool IsRecording() {return false;}; virtual bool Record(bool bOnOff) {return false;}; @@ -118,9 +121,9 @@ public: virtual int SeekChapter(int iChapter); virtual float GetActualFPS(); - virtual void SeekTime(__int64 iTime = 0); - virtual __int64 GetTime(); - virtual __int64 GetTotalTime(); + virtual void SeekTime(int64_t iTime = 0); + virtual int64_t GetTime(); + virtual int64_t GetTotalTime(); virtual void GetAudioStreamInfo(int index, SPlayerAudioStreamInfo &info); virtual void GetVideoStreamInfo(SPlayerVideoStreamInfo &info); virtual int GetSourceBitrate(); @@ -150,14 +153,6 @@ public: virtual bool SetPlayerState(CStdString state) {return false;}; virtual CStdString GetPlayingTitle() {return "";}; -/* - virtual void GetRenderFeatures(Features* renderFeatures); - virtual void GetDeinterlaceMethods(Features* deinterlaceMethods); - virtual void GetDeinterlaceModes(Features* deinterlaceModes); - virtual void GetScalingMethods(Features* scalingMethods); - virtual void GetAudioCapabilities(Features* audioCaps); - virtual void GetSubtitleCapabilities(Features* subCaps); -*/ virtual void GetRenderFeatures(std::vector<int> &renderFeatures); virtual void GetDeinterlaceMethods(std::vector<int> &deinterlaceMethods); @@ -236,7 +231,6 @@ private: CDVDPlayerSubtitle *m_dvdPlayerSubtitle; CDVDOverlayContainer *m_dvdOverlayContainer; - int m_chapter_index; int m_chapter_count; int m_show_mainvideo; diff --git a/xbmc/cores/amlplayer/AMLUtils.cpp b/xbmc/cores/amlplayer/AMLUtils.cpp deleted file mode 100644 index f22e96db9b..0000000000 --- a/xbmc/cores/amlplayer/AMLUtils.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (C) 2011-2013 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 <unistd.h> -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include <fcntl.h> -#include <string> - -int aml_set_sysfs_str(const char *path, const char *val) -{ - int fd = open(path, O_CREAT | O_RDWR | O_TRUNC, 0644); - if (fd >= 0) - { - write(fd, val, strlen(val)); - close(fd); - return 0; - } - return -1; -} - -int aml_get_sysfs_str(const char *path, char *valstr, const int size) -{ - int fd = open(path, O_RDONLY); - if (fd >= 0) - { - read(fd, valstr, size - 1); - valstr[strlen(valstr)] = '\0'; - close(fd); - return 0; - } - - sprintf(valstr, "%s", "fail"); - return -1; -} - -int aml_set_sysfs_int(const char *path, const int val) -{ - int fd = open(path, O_CREAT | O_RDWR | O_TRUNC, 0644); - if (fd >= 0) - { - char bcmd[16]; - sprintf(bcmd, "%d", val); - write(fd, bcmd, strlen(bcmd)); - close(fd); - return 0; - } - return -1; -} - -int aml_get_sysfs_int(const char *path) -{ - int val = 0; - int fd = open(path, O_RDONLY); - if (fd >= 0) - { - char bcmd[16]; - read(fd, bcmd, sizeof(bcmd)); - val = strtol(bcmd, NULL, 16); - close(fd); - } - return val; -} - -bool aml_present() -{ - static int has_aml = -1; - if (has_aml == -1) - { - if (aml_get_sysfs_int("/sys/class/amhdmitx/amhdmitx0/disp_cap") != -1) - has_aml = 1; - else - has_aml = 0; - } - return has_aml; -} - -void aml_cpufreq_limit(bool limit) -{ - static int audiotrack_cputype = -1; - if (audiotrack_cputype == -1) - { - // defualt to m1 SoC - audiotrack_cputype = 1; - - FILE *cpuinfo_fd = fopen("/proc/cpuinfo", "r"); - if (cpuinfo_fd) - { - char buffer[512]; - while (fgets(buffer, sizeof(buffer), cpuinfo_fd)) - { - std::string stdbuffer(buffer); - if (stdbuffer.find("MESON-M3") != std::string::npos) - { - audiotrack_cputype = 3; - break; - } - } - fclose(cpuinfo_fd); - } - } - // On M1 SoCs, when playing hw decoded audio, we cannot drop below 600MHz - // or risk hw audio dropouts. AML code does a 2X scaling based off - // /sys/class/audiodsp/codec_mips but tests show that this is - // seems risky so we just clamp to 600Mhz to be safe. - if (audiotrack_cputype == 3) - return; - - int cpufreq = 300000; - if (limit) - cpufreq = 600000; - - aml_set_sysfs_int("/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq", cpufreq); -} - -void aml_set_audio_passthrough(bool passthrough) -{ - if (aml_present()) - aml_set_sysfs_int("/sys/class/audiodsp/digital_raw", passthrough ? 1:0); -} diff --git a/xbmc/cores/amlplayer/DllLibamplayer.h b/xbmc/cores/amlplayer/DllLibamplayer.h index ac69d3bda5..2d4da44066 100644 --- a/xbmc/cores/amlplayer/DllLibamplayer.h +++ b/xbmc/cores/amlplayer/DllLibamplayer.h @@ -25,6 +25,17 @@ extern "C" { +// beware, these will alter the structs +// in player_type.h. +#if 1 + #define HAS_AMLPLAYER_CHAPTERS + #define HAS_AMLPLAYER_AUDIO_LANG + #define HAS_AMLPLAYER_AUDIO_SETDELAY + #define HAS_AMLPLAYER_AUDIO_SETVOLUME +#else + #define HAS_AMLPLAYER_VIDEO_STREAMS10 +#endif + #include <player_type.h> #include <player_error.h> } @@ -62,9 +73,13 @@ public: virtual int player_register_update_callback(callback_t *cb,update_state_fun_t up_fn,int interval_s)=0; virtual char* player_status2str(player_status status)=0; - virtual int audio_set_volume(int pid,float val)=0; +#if defined(HAS_AMLPLAYER_AUDIO_SETDELAY) virtual int audio_set_delay(int pid, int delay)=0; - +#endif +#if defined(HAS_AMLPLAYER_AUDIO_SETVOLUME) + virtual int audio_set_volume(int pid,float val)=0; +#endif + virtual int codec_open_sub_read(void)=0; virtual int codec_close_sub_fd(int sub_fd)=0; virtual int codec_get_sub_size_fd(int sub_fd)=0; @@ -103,8 +118,12 @@ class DllLibAmplayer : public DllDynamic, DllLibAmplayerInterface DEFINE_METHOD3(int, player_register_update_callback, (callback_t *p1, update_state_fun_t p2, int p3)) DEFINE_METHOD1(char*, player_status2str, (player_status p1)) - DEFINE_METHOD2(int, audio_set_volume, (int p1, float p2)) +#if defined(HAS_AMLPLAYER_AUDIO_SETDELAY) DEFINE_METHOD2(int, audio_set_delay, (int p1, int p2)) +#endif +#if defined(HAS_AMLPLAYER_AUDIO_SETVOLUME) + DEFINE_METHOD2(int, audio_set_volume, (int p1, float p2)) +#endif DEFINE_METHOD0(int, codec_open_sub_read) DEFINE_METHOD1(int, codec_close_sub_fd, (int p1)) @@ -140,8 +159,12 @@ class DllLibAmplayer : public DllDynamic, DllLibAmplayerInterface RESOLVE_METHOD(player_register_update_callback) RESOLVE_METHOD(player_status2str) - RESOLVE_METHOD(audio_set_volume) +#if defined(HAS_AMLPLAYER_AUDIO_SETDELAY) RESOLVE_METHOD(audio_set_delay) +#endif +#if defined(HAS_AMLPLAYER_AUDIO_SETVOLUME) + RESOLVE_METHOD(audio_set_volume) +#endif RESOLVE_METHOD(codec_open_sub_read) RESOLVE_METHOD(codec_close_sub_fd) diff --git a/xbmc/cores/amlplayer/FileURLProtocol.cpp b/xbmc/cores/amlplayer/FileURLProtocol.cpp index cbef19b803..2b8547ac4e 100644 --- a/xbmc/cores/amlplayer/FileURLProtocol.cpp +++ b/xbmc/cores/amlplayer/FileURLProtocol.cpp @@ -56,6 +56,10 @@ int CFileURLProtocol::Open(AML_URLContext *h, const char *filename, int flags) { url = url.Right(url.size() - strlen("xb-")); } + else if (url.Left(strlen("xb-sftp://")).Equals("xb-sftp://")) + { + url = url.Right(url.size() - strlen("xb-")); + } else if (url.Left(strlen("xb-hdhomerun://")).Equals("xb-hdhomerun://")) { url = url.Right(url.size() - strlen("xb-")); diff --git a/xbmc/cores/amlplayer/Makefile.in b/xbmc/cores/amlplayer/Makefile.in index 3d16c3daeb..1645cf26c2 100644 --- a/xbmc/cores/amlplayer/Makefile.in +++ b/xbmc/cores/amlplayer/Makefile.in @@ -3,14 +3,14 @@ INCLUDES += -I$(prefix)/include/amlplayer SRCS = AMLPlayer.cpp -SRCS+= AMLUtils.cpp SRCS+= FileURLProtocol.cpp LIB = amlplayer.a +ifneq (@USE_LIBAMCODEC@,1) @abs_top_srcdir@/system/advancedsettings.xml: $(LIB) cp -f amlplayer_advancedsettings.xml $@ +endif include @abs_top_srcdir@/Makefile.include -include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS))) - diff --git a/xbmc/cores/amlplayer/amlplayer_advancedsettings.xml b/xbmc/cores/amlplayer/amlplayer_advancedsettings.xml index 7199cd47b6..310ff95891 100644 --- a/xbmc/cores/amlplayer/amlplayer_advancedsettings.xml +++ b/xbmc/cores/amlplayer/amlplayer_advancedsettings.xml @@ -1,6 +1,5 @@ <advancedsettings> <video> <defaultplayer>amlplayer</defaultplayer> - <defaultdvdplayer>amlplayer</defaultdvdplayer> </video> </advancedsettings> diff --git a/xbmc/cores/dvdplayer/DVDAudio.cpp b/xbmc/cores/dvdplayer/DVDAudio.cpp index 1b31ad161f..dd8eab3e3f 100644 --- a/xbmc/cores/dvdplayer/DVDAudio.cpp +++ b/xbmc/cores/dvdplayer/DVDAudio.cpp @@ -26,7 +26,6 @@ #include "DVDPlayerAudio.h" #include "cores/AudioEngine/AEFactory.h" #include "cores/AudioEngine/Interfaces/AEStream.h" -#include "settings/Settings.h" #include "settings/MediaSettings.h" using namespace std; diff --git a/xbmc/cores/dvdplayer/DVDClock.cpp b/xbmc/cores/dvdplayer/DVDClock.cpp index 7284bb4434..f38eab5ad7 100644 --- a/xbmc/cores/dvdplayer/DVDClock.cpp +++ b/xbmc/cores/dvdplayer/DVDClock.cpp @@ -28,8 +28,8 @@ int64_t CDVDClock::m_systemOffset; int64_t CDVDClock::m_systemFrequency; CCriticalSection CDVDClock::m_systemsection; - bool CDVDClock::m_ismasterclock; +CDVDClock *CDVDClock::m_playerclock = NULL;; CDVDClock::CDVDClock() { @@ -45,10 +45,15 @@ CDVDClock::CDVDClock() m_ismasterclock = true; m_startClock = 0; + + m_playerclock = this; } CDVDClock::~CDVDClock() -{} +{ + CSingleLock lock(m_systemsection); + m_playerclock = NULL; +} // Returns the current absolute clock in units of DVD_TIME_BASE (usually microseconds). double CDVDClock::GetAbsoluteClock(bool interpolated /*= true*/) @@ -90,6 +95,12 @@ double CDVDClock::WaitAbsoluteClock(double target) return (double)systemtarget / freq * DVD_TIME_BASE; } +CDVDClock* CDVDClock::GetMasterClock() +{ + CSingleLock lock(m_systemsection); + return m_playerclock; +} + double CDVDClock::GetClock(bool interpolated /*= true*/) { CSharedLock lock(m_critSection); diff --git a/xbmc/cores/dvdplayer/DVDClock.h b/xbmc/cores/dvdplayer/DVDClock.h index 99723de33d..2ee505ff7f 100644 --- a/xbmc/cores/dvdplayer/DVDClock.h +++ b/xbmc/cores/dvdplayer/DVDClock.h @@ -66,7 +66,7 @@ public: //the rendermanager needs to know about that because it can synchronize the videoreferenceclock to the video timestamps static void SetMasterClock(bool ismasterclock) { m_ismasterclock = ismasterclock; } static bool IsMasterClock() { return m_ismasterclock; } - + static CDVDClock* GetMasterClock(); protected: static void CheckSystemClock(); static double SystemToAbsolute(int64_t system); @@ -87,4 +87,5 @@ protected: bool m_speedadjust; CCriticalSection m_speedsection; static bool m_ismasterclock; + static CDVDClock *m_playerclock; }; diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp index 80930a0ef7..efae6eb375 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp @@ -24,7 +24,11 @@ #endif #include "../../DVDStreamInfo.h" #include "utils/log.h" -#include "settings/GUISettings.h" + +#if defined(TARGET_DARWIN) +#include "settings/Settings.h" +#include "cores/AudioEngine/Utils/AEUtil.h" +#endif CDVDAudioCodecFFmpeg::CDVDAudioCodecFFmpeg() : CDVDAudioCodec() { @@ -72,9 +76,9 @@ bool CDVDAudioCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options } #if defined(TARGET_DARWIN) - int audioMode = g_guiSettings.GetInt("audiooutput.mode"); + int audioMode = CSettings::Get().GetInt("audiooutput.mode"); if (audioMode == AUDIO_HDMI) - m_bLpcmMode = g_guiSettings.GetBool("audiooutput.multichannellpcm"); + m_bLpcmMode = CSettings::Get().GetBool("audiooutput.multichannellpcm"); #endif m_pCodecContext = m_dllAvCodec.avcodec_alloc_context3(pCodec); @@ -97,9 +101,12 @@ bool CDVDAudioCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options if( hints.extradata && hints.extrasize > 0 ) { - m_pCodecContext->extradata_size = hints.extrasize; m_pCodecContext->extradata = (uint8_t*)m_dllAvUtil.av_mallocz(hints.extrasize + FF_INPUT_BUFFER_PADDING_SIZE); - memcpy(m_pCodecContext->extradata, hints.extradata, hints.extrasize); + if(m_pCodecContext->extradata) + { + m_pCodecContext->extradata_size = hints.extrasize; + memcpy(m_pCodecContext->extradata, hints.extradata, hints.extrasize); + } } if (m_dllAvCodec.avcodec_open2(m_pCodecContext, pCodec, NULL) < 0) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthrough.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthrough.cpp index e6deb6cac7..9d7030f36b 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthrough.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthrough.cpp @@ -21,7 +21,7 @@ #include "DVDAudioCodecPassthrough.h" #include "DVDCodecs/DVDCodecs.h" #include "DVDStreamInfo.h" -#include "settings/GUISettings.h" +#include "cores/AudioEngine/Utils/AEUtil.h" #include "settings/Settings.h" #include "utils/log.h" @@ -49,17 +49,17 @@ bool CDVDAudioCodecPassthrough::Open(CDVDStreamInfo &hints, CDVDCodecOptions &op bool bSupportsTrueHDOut = false; bool bSupportsDTSHDOut = false; - int audioMode = g_guiSettings.GetInt("audiooutput.mode"); + int audioMode = CSettings::Get().GetInt("audiooutput.mode"); if (AUDIO_IS_BITSTREAM(audioMode)) { - bSupportsAC3Out = g_guiSettings.GetBool("audiooutput.ac3passthrough"); - bSupportsDTSOut = g_guiSettings.GetBool("audiooutput.dtspassthrough"); + bSupportsAC3Out = CSettings::Get().GetBool("audiooutput.ac3passthrough"); + bSupportsDTSOut = CSettings::Get().GetBool("audiooutput.dtspassthrough"); } if (audioMode == AUDIO_HDMI) { - bSupportsTrueHDOut = g_guiSettings.GetBool("audiooutput.truehdpassthrough"); - bSupportsDTSHDOut = g_guiSettings.GetBool("audiooutput.dtshdpassthrough" ) && bSupportsDTSOut; + bSupportsTrueHDOut = CSettings::Get().GetBool("audiooutput.truehdpassthrough"); + bSupportsDTSHDOut = CSettings::Get().GetBool("audiooutput.dtshdpassthrough" ) && bSupportsDTSOut; } /* only get the dts core from the parser if we don't support dtsHD */ diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.cpp index e9a820e63c..4f607b5baf 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.cpp @@ -21,7 +21,7 @@ #include "DVDAudioCodecPassthroughFFmpeg.h" #include "DVDCodecs/DVDCodecs.h" #include "DVDStreamInfo.h" -#include "settings/GUISettings.h" +#include "cores/AudioEngine/Utils/AEUtil.h" #include "settings/MediaSettings.h" #include "settings/Settings.h" #include "utils/log.h" @@ -293,14 +293,14 @@ bool CDVDAudioCodecPassthroughFFmpeg::SupportsFormat(CDVDStreamInfo &hints) bool CDVDAudioCodecPassthroughFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) { - int audioMode = g_guiSettings.GetInt("audiooutput.mode"); + int audioMode = CSettings::Get().GetInt("audiooutput.mode"); // TODO - move this stuff somewhere else if (AUDIO_IS_BITSTREAM(audioMode)) { - m_bSupportsAC3Out = g_guiSettings.GetBool("audiooutput.ac3passthrough"); - m_bSupportsDTSOut = g_guiSettings.GetBool("audiooutput.dtspassthrough"); - m_bSupportsAACOut = g_guiSettings.GetBool("audiooutput.passthroughaac"); + m_bSupportsAC3Out = CSettings::Get().GetBool("audiooutput.ac3passthrough"); + m_bSupportsDTSOut = CSettings::Get().GetBool("audiooutput.dtspassthrough"); + m_bSupportsAACOut = CSettings::Get().GetBool("audiooutput.passthroughaac"); } else return false; diff --git a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp index 4ea66172f5..100cb22bd4 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp @@ -38,6 +38,9 @@ #if defined(HAVE_LIBCRYSTALHD) #include "Video/DVDVideoCodecCrystalHD.h" #endif +#if defined(HAS_LIBAMCODEC) +#include "Video/DVDVideoCodecAmlogic.h" +#endif #include "Audio/DVDAudioCodecFFmpeg.h" #include "Audio/DVDAudioCodecLibMad.h" #include "Audio/DVDAudioCodecPcm.h" @@ -53,7 +56,7 @@ #include "DVDStreamInfo.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "utils/SystemInfo.h" CDVDVideoCodec* CDVDFactoryCodec::OpenCodec(CDVDVideoCodec* pCodec, CDVDStreamInfo &hints, CDVDCodecOptions &options ) @@ -151,6 +154,11 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, unsigne #else hwSupport += "CrystalHD:no "; #endif +#if defined(HAS_LIBAMCODEC) + hwSupport += "AMCodec:yes "; +#else + hwSupport += "AMCodec:no "; +#endif #if defined(HAVE_LIBOPENMAX) && defined(_LINUX) hwSupport += "OpenMax:yes "; #elif defined(_LINUX) @@ -173,14 +181,16 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, unsigne #endif CLog::Log(LOGDEBUG, "CDVDFactoryCodec: compiled in hardware support: %s", hwSupport.c_str()); - +#if !defined(HAS_LIBAMCODEC) // dvd's have weird still-frames in it, which is not fully supported in ffmpeg if(hint.stills && (hint.codec == CODEC_ID_MPEG2VIDEO || hint.codec == CODEC_ID_MPEG1VIDEO)) { if( (pCodec = OpenCodec(new CDVDVideoCodecLibMpeg2(), hint, options)) ) return pCodec; } +#endif + #if defined(HAVE_LIBVDADECODER) - if (!hint.software && g_guiSettings.GetBool("videoplayer.usevda")) + if (!hint.software && CSettings::Get().GetBool("videoplayer.usevda")) { if (g_sysinfo.HasVDADecoder()) { @@ -193,7 +203,7 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, unsigne #endif #if defined(HAVE_VIDEOTOOLBOXDECODER) - if (!hint.software && g_guiSettings.GetBool("videoplayer.usevideotoolbox")) + if (!hint.software && CSettings::Get().GetBool("videoplayer.usevideotoolbox")) { if (g_sysinfo.HasVideoToolBoxDecoder()) { @@ -212,7 +222,7 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, unsigne #endif #if defined(HAVE_LIBCRYSTALHD) - if (!hint.software && g_guiSettings.GetBool("videoplayer.usechd")) + if (!hint.software && CSettings::Get().GetBool("videoplayer.usechd")) { if (CCrystalHD::GetInstance()->DevicePresent()) { @@ -235,8 +245,16 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, unsigne } #endif +#if defined(HAS_LIBAMCODEC) + if (!hint.software) + { + CLog::Log(LOGINFO, "Amlogic Video Decoder..."); + if ( (pCodec = OpenCodec(new CDVDVideoCodecAmlogic(), hint, options)) ) return pCodec; + } +#endif + #if defined(HAVE_LIBOPENMAX) - if (g_guiSettings.GetBool("videoplayer.useomx") && !hint.software ) + if (CSettings::Get().GetBool("videoplayer.useomx") && !hint.software ) { if (hint.codec == CODEC_ID_H264 || hint.codec == CODEC_ID_MPEG2VIDEO || hint.codec == CODEC_ID_VC1) { diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayCodecFFmpeg.cpp index 7f7b304fdd..0eb1fcfa01 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayCodecFFmpeg.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayCodecFFmpeg.cpp @@ -186,7 +186,8 @@ int CDVDOverlayCodecFFmpeg::Decode(DemuxPacket *pPacket) // for pgs subtitles the packet pts of the end_segments are wrong // instead use the subtitle pts to calc the offset here // see http://git.videolan.org/?p=ffmpeg.git;a=commit;h=2939e258f9d1fff89b3b68536beb931b54611585 - if (m_Subtitle.pts != DVD_NOPTS_VALUE) + + if (m_Subtitle.pts != AV_NOPTS_VALUE && pPacket->pts != DVD_NOPTS_VALUE) { pts_offset = m_Subtitle.pts - pPacket->pts ; } diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayCodecTX3G.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayCodecTX3G.cpp index c269bf7e21..477c74633c 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayCodecTX3G.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayCodecTX3G.cpp @@ -24,7 +24,7 @@ #include "DVDOverlayText.h" #include "DVDStreamInfo.h" #include "DVDCodecs/DVDCodecs.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "utils/log.h" // 3GPP/TX3G (aka MPEG-4 Timed Text) Subtitle support @@ -64,7 +64,7 @@ CDVDOverlayCodecTX3G::CDVDOverlayCodecTX3G() : CDVDOverlayCodec("TX3G Subtitle D m_pOverlay = NULL; // stupid, this comes from a static global in GUIWindowFullScreen.cpp uint32_t colormap[8] = { 0xFFFFFF00, 0xFFFFFFFF, 0xFF0099FF, 0xFF00FF00, 0xFFCCFF00, 0xFF00FFFF, 0xFFE5E5E5, 0xFFC0C0C0 }; - m_textColor = colormap[g_guiSettings.GetInt("subtitles.color")]; + m_textColor = colormap[CSettings::Get().GetInt("subtitles.color")]; } CDVDOverlayCodecTX3G::~CDVDOverlayCodecTX3G() diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp new file mode 100644 index 0000000000..46b172665c --- /dev/null +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.cpp @@ -0,0 +1,2175 @@ +/* + * Copyright (C) 2005-2011 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 "system.h" + +#include "AMLCodec.h" +#include "DynamicDll.h" + +#include "cores/dvdplayer/DVDClock.h" +#include "cores/VideoRenderers/RenderManager.h" +#include "guilib/GraphicContext.h" +#include "settings/MediaSettings.h" +#include "settings/Settings.h" +#include "utils/AMLUtils.h" +#include "utils/log.h" +#include "utils/TimeUtils.h" + +#include <unistd.h> +#include <queue> +#include <vector> +#include <signal.h> +#include <semaphore.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/ioctl.h> + +// amcodec include +extern "C" { +#include <codec.h> +} // extern "C" + +class DllLibamCodecInterface +{ +public: + virtual ~DllLibamCodecInterface() {}; + + virtual int codec_init(codec_para_t *pcodec)=0; + virtual int codec_close(codec_para_t *pcodec)=0; + virtual int codec_reset(codec_para_t *pcodec)=0; + virtual int codec_pause(codec_para_t *pcodec)=0; + virtual int codec_resume(codec_para_t *pcodec)=0; + virtual int codec_write(codec_para_t *pcodec, void *buffer, int len)=0; + virtual int codec_checkin_pts(codec_para_t *pcodec, unsigned long pts)=0; + virtual int codec_get_vbuf_state(codec_para_t *pcodec, struct buf_status *buf)=0; + virtual int codec_get_vdec_state(codec_para_t *pcodec, struct vdec_status *vdec)=0; + + virtual int codec_init_cntl(codec_para_t *pcodec)=0; + virtual int codec_poll_cntl(codec_para_t *pcodec)=0; + virtual int codec_set_cntl_mode(codec_para_t *pcodec, unsigned int mode)=0; + virtual int codec_set_cntl_avthresh(codec_para_t *pcodec, unsigned int avthresh)=0; + virtual int codec_set_cntl_syncthresh(codec_para_t *pcodec, unsigned int syncthresh)=0; + + // grab these from libamplayer + virtual int h263vld(unsigned char *inbuf, unsigned char *outbuf, int inbuf_len, int s263)=0; + virtual int decodeble_h263(unsigned char *buf)=0; + + // grab this from amffmpeg so we do not have to load DllAvUtil + virtual AVRational av_d2q(double d, int max)=0; +}; + +class DllLibAmCodec : public DllDynamic, DllLibamCodecInterface +{ + // libamcodec is static linked into libamplayer.so + DECLARE_DLL_WRAPPER(DllLibAmCodec, "libamplayer.so") + + DEFINE_METHOD1(int, codec_init, (codec_para_t *p1)) + DEFINE_METHOD1(int, codec_close, (codec_para_t *p1)) + DEFINE_METHOD1(int, codec_reset, (codec_para_t *p1)) + DEFINE_METHOD1(int, codec_pause, (codec_para_t *p1)) + DEFINE_METHOD1(int, codec_resume, (codec_para_t *p1)) + DEFINE_METHOD3(int, codec_write, (codec_para_t *p1, void *p2, int p3)) + DEFINE_METHOD2(int, codec_checkin_pts, (codec_para_t *p1, unsigned long p2)) + DEFINE_METHOD2(int, codec_get_vbuf_state, (codec_para_t *p1, struct buf_status * p2)) + DEFINE_METHOD2(int, codec_get_vdec_state, (codec_para_t *p1, struct vdec_status * p2)) + + DEFINE_METHOD1(int, codec_init_cntl, (codec_para_t *p1)) + DEFINE_METHOD1(int, codec_poll_cntl, (codec_para_t *p1)) + DEFINE_METHOD2(int, codec_set_cntl_mode, (codec_para_t *p1, unsigned int p2)) + DEFINE_METHOD2(int, codec_set_cntl_avthresh, (codec_para_t *p1, unsigned int p2)) + DEFINE_METHOD2(int, codec_set_cntl_syncthresh,(codec_para_t *p1, unsigned int p2)) + + DEFINE_METHOD4(int, h263vld, (unsigned char *p1, unsigned char *p2, int p3, int p4)) + DEFINE_METHOD1(int, decodeble_h263, (unsigned char *p1)) + + DEFINE_METHOD2(AVRational, av_d2q, (double p1, int p2)) + + BEGIN_METHOD_RESOLVE() + RESOLVE_METHOD(codec_init) + RESOLVE_METHOD(codec_close) + RESOLVE_METHOD(codec_reset) + RESOLVE_METHOD(codec_pause) + RESOLVE_METHOD(codec_resume) + RESOLVE_METHOD(codec_write) + RESOLVE_METHOD(codec_checkin_pts) + RESOLVE_METHOD(codec_get_vbuf_state) + RESOLVE_METHOD(codec_get_vdec_state) + + RESOLVE_METHOD(codec_init_cntl) + RESOLVE_METHOD(codec_poll_cntl) + RESOLVE_METHOD(codec_set_cntl_mode) + RESOLVE_METHOD(codec_set_cntl_avthresh) + RESOLVE_METHOD(codec_set_cntl_syncthresh) + + RESOLVE_METHOD(h263vld) + RESOLVE_METHOD(decodeble_h263) + + RESOLVE_METHOD(av_d2q) + END_METHOD_RESOLVE() +}; + +//----------------------------------------------------------------------------------- +//----------------------------------------------------------------------------------- +// AppContext - Application state +#define PTS_FREQ 90000 +#define UNIT_FREQ 96000 +#define AV_SYNC_THRESH PTS_FREQ*30 + +#define TRICKMODE_NONE 0x00 +#define TRICKMODE_I 0x01 +#define TRICKMODE_FFFB 0x02 + +// same as AV_NOPTS_VALUE +#define INT64_0 INT64_C(0x8000000000000000) + +#define EXTERNAL_PTS (1) +#define SYNC_OUTSIDE (2) + +// missing tags +#define CODEC_TAG_VC_1 (0x312D4356) +#define CODEC_TAG_RV30 (0x30335652) +#define CODEC_TAG_RV40 (0x30345652) +#define CODEC_TAG_MJPEG (0x47504a4d) +#define CODEC_TAG_mjpeg (0x47504a4c) +#define CODEC_TAG_jpeg (0x6765706a) +#define CODEC_TAG_mjpa (0x61706a6d) + +#define RW_WAIT_TIME (20 * 1000) // 20ms + +#define P_PRE (0x02000000) +#define F_PRE (0x03000000) +#define PLAYER_SUCCESS (0) +#define PLAYER_FAILED (-(P_PRE|0x01)) +#define PLAYER_NOMEM (-(P_PRE|0x02)) +#define PLAYER_EMPTY_P (-(P_PRE|0x03)) + +#define PLAYER_WR_FAILED (-(P_PRE|0x21)) +#define PLAYER_WR_EMPTYP (-(P_PRE|0x22)) +#define PLAYER_WR_FINISH (P_PRE|0x1) + +#define PLAYER_PTS_ERROR (-(P_PRE|0x31)) +#define PLAYER_UNSUPPORT (-(P_PRE|0x35)) +#define PLAYER_CHECK_CODEC_ERROR (-(P_PRE|0x39)) + +#define HDR_BUF_SIZE 1024 +typedef struct hdr_buf { + char *data; + int size; +} hdr_buf_t; + +typedef struct am_packet { + AVPacket avpkt; + int64_t avpts; + int64_t avdts; + int avduration; + int isvalid; + int newflag; + int64_t lastpts; + unsigned char *data; + unsigned char *buf; + int data_size; + int buf_size; + hdr_buf_t *hdr; + codec_para_t *codec; +} am_packet_t; + +typedef enum { + AM_STREAM_UNKNOWN = 0, + AM_STREAM_TS, + AM_STREAM_PS, + AM_STREAM_ES, + AM_STREAM_RM, + AM_STREAM_AUDIO, + AM_STREAM_VIDEO, +} pstream_type; + +typedef union { + int64_t total_bytes; + unsigned int vpkt_num; + unsigned int spkt_num; +} read_write_size; + +typedef struct { + unsigned int read_end_flag: 1; + unsigned int end_flag: 1; + unsigned int reset_flag: 1; + int check_lowlevel_eagain_cnt; +} p_ctrl_info_t; + +typedef struct am_private_t +{ + am_packet_t am_pkt; + codec_para_t vcodec; + + pstream_type stream_type; + p_ctrl_info_t playctrl_info; + + read_write_size read_size; + read_write_size write_size; + int check_first_pts; + + vformat_t video_format; + int video_pid; + unsigned int video_codec_id; + unsigned int video_codec_tag; + vdec_type_t video_codec_type; + unsigned int video_width; + unsigned int video_height; + unsigned int video_ratio; + unsigned int video_ratio64; + unsigned int video_rate; + unsigned int video_rotation_degree; + int flv_flag; + int h263_decodable; + int extrasize; + uint8_t *extradata; + DllLibAmCodec *m_dll; +} am_private_t; + +/*************************************************************************/ +static int64_t get_pts_video() +{ + int fd = open("/sys/class/tsync/pts_video", O_RDONLY); + if (fd >= 0) + { + char pts_str[16]; + int size = read(fd, pts_str, sizeof(pts_str)); + close(fd); + if (size > 0) + { + unsigned long pts = strtoul(pts_str, NULL, 16); + return pts; + } + } + + CLog::Log(LOGERROR, "get_pts_video: open /tsync/event error"); + return -1; +} + +static int set_pts_pcrscr(int64_t value) +{ + int fd = open("/sys/class/tsync/pts_pcrscr", O_WRONLY); + if (fd >= 0) + { + char pts_str[64]; + unsigned long pts = (unsigned long)value; + sprintf(pts_str, "0x%lx", pts); + write(fd, pts_str, strlen(pts_str)); + close(fd); + return 0; + } + + CLog::Log(LOGERROR, "set_pts_pcrscr: open pts_pcrscr error"); + return -1; +} + +static vformat_t codecid_to_vformat(enum CodecID id) +{ + vformat_t format; + switch (id) + { + case CODEC_ID_MPEG1VIDEO: + case CODEC_ID_MPEG2VIDEO: + case CODEC_ID_MPEG2VIDEO_XVMC: + format = VFORMAT_MPEG12; + break; + case CODEC_ID_H263: + case CODEC_ID_MPEG4: + case CODEC_ID_H263P: + case CODEC_ID_H263I: + case CODEC_ID_MSMPEG4V2: + case CODEC_ID_MSMPEG4V3: + case CODEC_ID_FLV1: + format = VFORMAT_MPEG4; + break; + case CODEC_ID_RV10: + case CODEC_ID_RV20: + case CODEC_ID_RV30: + case CODEC_ID_RV40: + format = VFORMAT_REAL; + break; + case CODEC_ID_H264: + format = VFORMAT_H264; + break; + /* + case CODEC_ID_H264MVC: + // H264 Multiview Video Coding (3d blurays) + format = VFORMAT_H264MVC; + break; + */ + case CODEC_ID_MJPEG: + format = VFORMAT_MJPEG; + break; + case CODEC_ID_VC1: + case CODEC_ID_WMV3: + format = VFORMAT_VC1; + break; + case CODEC_ID_AVS: + case CODEC_ID_CAVS: + format = VFORMAT_AVS; + break; + + default: + format = VFORMAT_UNSUPPORT; + break; + } + + CLog::Log(LOGDEBUG, "codecid_to_vformat, id(%d) -> vformat(%d)", (int)id, format); + return format; +} + +static vdec_type_t codec_tag_to_vdec_type(unsigned int codec_tag) +{ + vdec_type_t dec_type; + switch (codec_tag) + { + case CODEC_TAG_MJPEG: + case CODEC_TAG_mjpeg: + case CODEC_TAG_jpeg: + case CODEC_TAG_mjpa: + // mjpeg + dec_type = VIDEO_DEC_FORMAT_MJPEG; + break; + case CODEC_TAG_XVID: + case CODEC_TAG_xvid: + case CODEC_TAG_XVIX: + // xvid + dec_type = VIDEO_DEC_FORMAT_MPEG4_5; + break; + case CODEC_TAG_COL1: + case CODEC_TAG_DIV3: + case CODEC_TAG_MP43: + // divx3.11 + dec_type = VIDEO_DEC_FORMAT_MPEG4_3; + break; + case CODEC_TAG_DIV4: + case CODEC_TAG_DIVX: + // divx4 + dec_type = VIDEO_DEC_FORMAT_MPEG4_4; + break; + case CODEC_TAG_DIV5: + case CODEC_TAG_DX50: + case CODEC_TAG_M4S2: + case CODEC_TAG_FMP4: + // divx5 + dec_type = VIDEO_DEC_FORMAT_MPEG4_5; + break; + case CODEC_TAG_DIV6: + // divx6 + dec_type = VIDEO_DEC_FORMAT_MPEG4_5; + break; + case CODEC_TAG_MP4V: + case CODEC_TAG_RMP4: + case CODEC_TAG_MPG4: + case CODEC_TAG_mp4v: + case CODEC_ID_MPEG4: + // mp4 + dec_type = VIDEO_DEC_FORMAT_MPEG4_5; + break; + case CODEC_ID_H263: + case CODEC_TAG_H263: + case CODEC_TAG_h263: + case CODEC_TAG_s263: + case CODEC_TAG_F263: + // h263 + dec_type = VIDEO_DEC_FORMAT_H263; + break; + case CODEC_TAG_AVC1: + case CODEC_TAG_avc1: + case CODEC_TAG_H264: + case CODEC_TAG_h264: + case CODEC_ID_H264: + // h264 + dec_type = VIDEO_DEC_FORMAT_H264; + break; + /* + case CODEC_ID_H264MVC: + dec_type = VIDEO_DEC_FORMAT_H264; + break; + */ + case CODEC_ID_RV30: + case CODEC_TAG_RV30: + // realmedia 3 + dec_type = VIDEO_DEC_FORMAT_REAL_8; + break; + case CODEC_ID_RV40: + case CODEC_TAG_RV40: + // realmedia 4 + dec_type = VIDEO_DEC_FORMAT_REAL_9; + break; + case CODEC_TAG_WMV3: + // wmv3 + dec_type = VIDEO_DEC_FORMAT_WMV3; + break; + case CODEC_ID_VC1: + case CODEC_TAG_VC_1: + case CODEC_TAG_WVC1: + case CODEC_TAG_WMVA: + // vc1 + dec_type = VIDEO_DEC_FORMAT_WVC1; + break; + case CODEC_ID_VP6F: + // vp6 + dec_type = VIDEO_DEC_FORMAT_SW; + break; + case CODEC_ID_CAVS: + case CODEC_ID_AVS: + // avs + dec_type = VIDEO_DEC_FORMAT_AVS; + break; + default: + dec_type = VIDEO_DEC_FORMAT_UNKNOW; + break; + } + + CLog::Log(LOGDEBUG, "codec_tag_to_vdec_type, codec_tag(%d) -> vdec_type(%d)", codec_tag, dec_type); + return dec_type; +} + +static void am_packet_init(am_packet_t *pkt) +{ + memset(&pkt->avpkt, 0, sizeof(AVPacket)); + pkt->avpts = 0; + pkt->avdts = 0; + pkt->avduration = 0; + pkt->isvalid = 0; + pkt->newflag = 0; + pkt->lastpts = 0; + pkt->data = NULL; + pkt->buf = NULL; + pkt->data_size = 0; + pkt->buf_size = 0; + pkt->hdr = NULL; + pkt->codec = NULL; +} + +void am_packet_release(am_packet_t *pkt) +{ + if (pkt->buf != NULL) + { + free(pkt->buf); + pkt->buf= NULL; + } + if (pkt->hdr != NULL) + { + free(pkt->hdr->data); + pkt->hdr->data = NULL; + free(pkt->hdr); + pkt->hdr = NULL; + } + pkt->codec = NULL; +} + +int check_in_pts(am_private_t *para, am_packet_t *pkt) +{ + int last_duration = 0; + static int last_v_duration = 0; + int64_t pts = 0; + + last_duration = last_v_duration; + + if (para->stream_type == AM_STREAM_ES) { + if ((int64_t)INT64_0 != pkt->avpts) { + pts = pkt->avpts; + + if (para->m_dll->codec_checkin_pts(pkt->codec, pts) != 0) { + CLog::Log(LOGDEBUG, "ERROR check in pts error!"); + return PLAYER_PTS_ERROR; + } + + } else if ((int64_t)INT64_0 != pkt->avdts) { + pts = pkt->avdts * last_duration; + + if (para->m_dll->codec_checkin_pts(pkt->codec, pts) != 0) { + CLog::Log(LOGDEBUG, "ERROR check in dts error!"); + return PLAYER_PTS_ERROR; + } + + last_v_duration = pkt->avduration ? pkt->avduration : 1; + } else { + if (!para->check_first_pts) { + if (para->m_dll->codec_checkin_pts(pkt->codec, 0) != 0) { + CLog::Log(LOGDEBUG, "ERROR check in 0 to video pts error!"); + return PLAYER_PTS_ERROR; + } + } + } + if (!para->check_first_pts) { + para->check_first_pts = 1; + } + } + if (pts > 0) + pkt->lastpts = pts; + + return PLAYER_SUCCESS; +} + +static int check_write_finish(am_private_t *para, am_packet_t *pkt) +{ + if (para->playctrl_info.read_end_flag) { + if ((para->write_size.vpkt_num == para->read_size.vpkt_num)) { + return PLAYER_WR_FINISH; + } + } + return PLAYER_WR_FAILED; +} + +static int write_header(am_private_t *para, am_packet_t *pkt) +{ + int write_bytes = 0, len = 0; + + if (pkt->hdr && pkt->hdr->size > 0) { + if ((NULL == pkt->codec) || (NULL == pkt->hdr->data)) { + CLog::Log(LOGDEBUG, "[write_header]codec null!"); + return PLAYER_EMPTY_P; + } + //some wvc1 es data not need to add header + if (para->video_format == VFORMAT_VC1 && para->video_codec_type == VIDEO_DEC_FORMAT_WVC1) { + if ((pkt->data) && (pkt->data_size >= 4) + && (pkt->data[0] == 0) && (pkt->data[1] == 0) + && (pkt->data[2] == 1) && (pkt->data[3] == 0xd || pkt->data[3] == 0xf)) { + return PLAYER_SUCCESS; + } + } + while (1) { + write_bytes = para->m_dll->codec_write(pkt->codec, pkt->hdr->data + len, pkt->hdr->size - len); + if (write_bytes < 0 || write_bytes > (pkt->hdr->size - len)) { + if (-errno != AVERROR(EAGAIN)) { + CLog::Log(LOGDEBUG, "ERROR:write header failed!"); + return PLAYER_WR_FAILED; + } else { + continue; + } + } else { + len += write_bytes; + if (len == pkt->hdr->size) { + break; + } + } + } + } + return PLAYER_SUCCESS; +} + +int check_avbuffer_enough(am_private_t *para, am_packet_t *pkt) +{ + return 1; +} + +int write_av_packet(am_private_t *para, am_packet_t *pkt) +{ + //CLog::Log(LOGDEBUG, "write_av_packet, pkt->isvalid(%d), pkt->data(%p), pkt->data_size(%d)", + // pkt->isvalid, pkt->data, pkt->data_size); + + int write_bytes = 0, len = 0, ret; + unsigned char *buf; + int size; + + if (pkt->newflag) { + if (pkt->isvalid) { + ret = check_in_pts(para, pkt); + if (ret != PLAYER_SUCCESS) { + CLog::Log(LOGDEBUG, "check in pts failed"); + return PLAYER_WR_FAILED; + } + } + if (write_header(para, pkt) == PLAYER_WR_FAILED) { + CLog::Log(LOGDEBUG, "[%s]write header failed!", __FUNCTION__); + return PLAYER_WR_FAILED; + } + pkt->newflag = 0; + } + + buf = pkt->data; + size = pkt->data_size ; + if (size == 0 && pkt->isvalid) { + para->write_size.vpkt_num++; + pkt->isvalid = 0; + } + while (size > 0 && pkt->isvalid) { + write_bytes = para->m_dll->codec_write(pkt->codec, (char *)buf, size); + if (write_bytes < 0 || write_bytes > size) { + if (-errno != AVERROR(EAGAIN)) { + para->playctrl_info.check_lowlevel_eagain_cnt = 0; + CLog::Log(LOGDEBUG, "write codec data failed!"); + return PLAYER_WR_FAILED; + } else { + // EAGAIN to see if buffer full or write time out too much + if (check_avbuffer_enough(para, pkt)) { + para->playctrl_info.check_lowlevel_eagain_cnt++; + } else { + para->playctrl_info.check_lowlevel_eagain_cnt = 0; + } + + if (para->playctrl_info.check_lowlevel_eagain_cnt > 50) { + // reset decoder + para->playctrl_info.check_lowlevel_eagain_cnt = 0; + para->playctrl_info.reset_flag = 1; + para->playctrl_info.end_flag = 1; + CLog::Log(LOGDEBUG, "$$$$$$ write blocked, need reset decoder!$$$$$$"); + } + //pkt->data += len; + //pkt->data_size -= len; + usleep(RW_WAIT_TIME); + CLog::Log(LOGDEBUG, "usleep(RW_WAIT_TIME), len(%d)", len); + return PLAYER_SUCCESS; + } + } else { + para->playctrl_info.check_lowlevel_eagain_cnt = 0; + len += write_bytes; + if (len == pkt->data_size) { + para->write_size.vpkt_num++; + pkt->isvalid = 0; + pkt->data_size = 0; + break; + } else if (len < pkt->data_size) { + buf += write_bytes; + size -= write_bytes; + } else { + return PLAYER_WR_FAILED; + } + } + } + if (check_write_finish(para, pkt) == PLAYER_WR_FINISH) { + return PLAYER_WR_FINISH; + } + return PLAYER_SUCCESS; +} + +static int check_size_in_buffer(unsigned char *p, int len) +{ + unsigned int size; + unsigned char *q = p; + while ((q + 4) < (p + len)) { + size = (*q << 24) | (*(q + 1) << 16) | (*(q + 2) << 8) | (*(q + 3)); + if (size & 0xff000000) { + return 0; + } + + if (q + size + 4 == p + len) { + return 1; + } + + q += size + 4; + } + return 0; +} + +static int check_size_in_buffer3(unsigned char *p, int len) +{ + unsigned int size; + unsigned char *q = p; + while ((q + 3) < (p + len)) { + size = (*q << 16) | (*(q + 1) << 8) | (*(q + 2)); + + if (q + size + 3 == p + len) { + return 1; + } + + q += size + 3; + } + return 0; +} + +static int check_size_in_buffer2(unsigned char *p, int len) +{ + unsigned int size; + unsigned char *q = p; + while ((q + 2) < (p + len)) { + size = (*q << 8) | (*(q + 1)); + + if (q + size + 2 == p + len) { + return 1; + } + + q += size + 2; + } + return 0; +} + +/*************************************************************************/ +static int m4s2_dx50_mp4v_add_header(unsigned char *buf, int size, am_packet_t *pkt) +{ + if (size > pkt->hdr->size) { + free(pkt->hdr->data), pkt->hdr->data = NULL; + pkt->hdr->size = 0; + + pkt->hdr->data = (char*)malloc(size); + if (!pkt->hdr->data) { + CLog::Log(LOGDEBUG, "[m4s2_dx50_add_header] NOMEM!"); + return PLAYER_FAILED; + } + } + + pkt->hdr->size = size; + memcpy(pkt->hdr->data, buf, size); + + return PLAYER_SUCCESS; +} + +static int m4s2_dx50_mp4v_write_header(am_private_t *para, am_packet_t *pkt) +{ + CLog::Log(LOGDEBUG, "m4s2_dx50_mp4v_write_header"); + int ret = m4s2_dx50_mp4v_add_header(para->extradata, para->extrasize, pkt); + if (ret == PLAYER_SUCCESS) { + if (1) { + pkt->codec = ¶->vcodec; + } else { + CLog::Log(LOGDEBUG, "[m4s2_dx50_mp4v_add_header]invalid video codec!"); + return PLAYER_EMPTY_P; + } + pkt->newflag = 1; + ret = write_av_packet(para, pkt); + } + return ret; +} + +static int mjpeg_data_prefeeding(am_packet_t *pkt) +{ + const unsigned char mjpeg_addon_data[] = { + 0xff, 0xd8, 0xff, 0xc4, 0x01, 0xa2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, + 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x01, 0x00, 0x03, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x10, + 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, + 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, + 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, + 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, + 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, + 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, + 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, + 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, + 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, + 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, + 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, + 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x11, 0x00, 0x02, 0x01, + 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, + 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, + 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, + 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, + 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, + 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, + 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, + 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, + 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, + 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, + 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa + }; + + if (pkt->hdr->data) { + memcpy(pkt->hdr->data, &mjpeg_addon_data, sizeof(mjpeg_addon_data)); + pkt->hdr->size = sizeof(mjpeg_addon_data); + } else { + CLog::Log(LOGDEBUG, "[mjpeg_data_prefeeding]No enough memory!"); + return PLAYER_FAILED; + } + return PLAYER_SUCCESS; +} + +static int mjpeg_write_header(am_private_t *para, am_packet_t *pkt) +{ + mjpeg_data_prefeeding(pkt); + if (1) { + pkt->codec = ¶->vcodec; + } else { + CLog::Log(LOGDEBUG, "[mjpeg_write_header]invalid codec!"); + return PLAYER_EMPTY_P; + } + pkt->newflag = 1; + write_av_packet(para, pkt); + return PLAYER_SUCCESS; +} + +static int divx3_data_prefeeding(am_packet_t *pkt, unsigned w, unsigned h) +{ + unsigned i = (w << 12) | (h & 0xfff); + unsigned char divx311_add[10] = { + 0x00, 0x00, 0x00, 0x01, + 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00 + }; + divx311_add[5] = (i >> 16) & 0xff; + divx311_add[6] = (i >> 8) & 0xff; + divx311_add[7] = i & 0xff; + + if (pkt->hdr->data) { + memcpy(pkt->hdr->data, divx311_add, sizeof(divx311_add)); + pkt->hdr->size = sizeof(divx311_add); + } else { + CLog::Log(LOGDEBUG, "[divx3_data_prefeeding]No enough memory!"); + return PLAYER_FAILED; + } + return PLAYER_SUCCESS; +} + +static int divx3_write_header(am_private_t *para, am_packet_t *pkt) +{ + CLog::Log(LOGDEBUG, "divx3_write_header"); + divx3_data_prefeeding(pkt, para->video_width, para->video_height); + if (1) { + pkt->codec = ¶->vcodec; + } else { + CLog::Log(LOGDEBUG, "[divx3_write_header]invalid codec!"); + return PLAYER_EMPTY_P; + } + pkt->newflag = 1; + write_av_packet(para, pkt); + return PLAYER_SUCCESS; +} + +static int h264_add_header(unsigned char *buf, int size, am_packet_t *pkt) +{ + char nal_start_code[] = {0x0, 0x0, 0x0, 0x1}; + int nalsize; + unsigned char* p; + int tmpi; + unsigned char* extradata = buf; + int header_len = 0; + char* buffer = pkt->hdr->data; + + p = extradata; + + // h264 annex-b + if ((p[0]==0 && p[1]==0 && p[2]==0 && p[3]==1) && size < HDR_BUF_SIZE) { + CLog::Log(LOGDEBUG, "add four byte NAL 264 header in stream before header len=%d",size); + memcpy(buffer, buf, size); + pkt->hdr->size = size; + return PLAYER_SUCCESS; + } + + if ((p[0]==0 && p[1]==0 && p[2]==1) && size < HDR_BUF_SIZE) { + CLog::Log(LOGDEBUG, "add three byte NAL 264 header in stream before header len=%d",size); + memcpy(buffer, buf, size); + pkt->hdr->size = size; + return PLAYER_SUCCESS; + } + + if (size < 4) { + return PLAYER_FAILED; + } + + if (size < 10) { + CLog::Log(LOGDEBUG, "avcC too short"); + return PLAYER_FAILED; + } + + // h264 avcC + if (*p != 1) { + CLog::Log(LOGDEBUG, "Unknown avcC version %d", *p); + return PLAYER_FAILED; + } + + int cnt = *(p + 5) & 0x1f; //number of sps + // CLog::Log(LOGDEBUG, "number of sps :%d", cnt); + p += 6; + for (tmpi = 0; tmpi < cnt; tmpi++) { + nalsize = (*p << 8) | (*(p + 1)); + memcpy(&(buffer[header_len]), nal_start_code, 4); + header_len += 4; + memcpy(&(buffer[header_len]), p + 2, nalsize); + header_len += nalsize; + p += (nalsize + 2); + } + + cnt = *(p++); //Number of pps + // CLog::Log(LOGDEBUG, "number of pps :%d", cnt); + for (tmpi = 0; tmpi < cnt; tmpi++) { + nalsize = (*p << 8) | (*(p + 1)); + memcpy(&(buffer[header_len]), nal_start_code, 4); + header_len += 4; + memcpy(&(buffer[header_len]), p + 2, nalsize); + header_len += nalsize; + p += (nalsize + 2); + } + if (header_len >= HDR_BUF_SIZE) { + CLog::Log(LOGDEBUG, "header_len %d is larger than max length", header_len); + return 0; + } + pkt->hdr->size = header_len; + + return PLAYER_SUCCESS; +} +static int h264_write_header(am_private_t *para, am_packet_t *pkt) +{ + // CLog::Log(LOGDEBUG, "h264_write_header"); + int ret = -1; + + ret = h264_add_header(para->extradata, para->extrasize, pkt); + if (ret == PLAYER_SUCCESS) { + //if (ctx->vcodec) { + if (1) { + pkt->codec = ¶->vcodec; + } else { + //CLog::Log(LOGDEBUG, "[pre_header_feeding]invalid video codec!"); + return PLAYER_EMPTY_P; + } + + pkt->newflag = 1; + ret = write_av_packet(para, pkt); + } + return ret; +} + +static int wmv3_write_header(am_private_t *para, am_packet_t *pkt) +{ + CLog::Log(LOGDEBUG, "wmv3_write_header"); + unsigned i, check_sum = 0; + unsigned data_len = para->extrasize + 4; + + pkt->hdr->data[0] = 0; + pkt->hdr->data[1] = 0; + pkt->hdr->data[2] = 1; + pkt->hdr->data[3] = 0x10; + + pkt->hdr->data[4] = 0; + pkt->hdr->data[5] = (data_len >> 16) & 0xff; + pkt->hdr->data[6] = 0x88; + pkt->hdr->data[7] = (data_len >> 8) & 0xff; + pkt->hdr->data[8] = data_len & 0xff; + pkt->hdr->data[9] = 0x88; + + pkt->hdr->data[10] = 0xff; + pkt->hdr->data[11] = 0xff; + pkt->hdr->data[12] = 0x88; + pkt->hdr->data[13] = 0xff; + pkt->hdr->data[14] = 0xff; + pkt->hdr->data[15] = 0x88; + + for (i = 4 ; i < 16 ; i++) { + check_sum += pkt->hdr->data[i]; + } + + pkt->hdr->data[16] = (check_sum >> 8) & 0xff; + pkt->hdr->data[17] = check_sum & 0xff; + pkt->hdr->data[18] = 0x88; + pkt->hdr->data[19] = (check_sum >> 8) & 0xff; + pkt->hdr->data[20] = check_sum & 0xff; + pkt->hdr->data[21] = 0x88; + + pkt->hdr->data[22] = (para->video_width >> 8) & 0xff; + pkt->hdr->data[23] = para->video_width & 0xff; + pkt->hdr->data[24] = (para->video_height >> 8) & 0xff; + pkt->hdr->data[25] = para->video_height & 0xff; + + memcpy(pkt->hdr->data + 26, para->extradata, para->extrasize); + pkt->hdr->size = para->extrasize + 26; + if (1) { + pkt->codec = ¶->vcodec; + } else { + CLog::Log(LOGDEBUG, "[wmv3_write_header]invalid codec!"); + return PLAYER_EMPTY_P; + } + pkt->newflag = 1; + return write_av_packet(para, pkt); +} + +static int wvc1_write_header(am_private_t *para, am_packet_t *pkt) +{ + CLog::Log(LOGDEBUG, "wvc1_write_header"); + memcpy(pkt->hdr->data, para->extradata + 1, para->extrasize - 1); + pkt->hdr->size = para->extrasize - 1; + if (1) { + pkt->codec = ¶->vcodec; + } else { + CLog::Log(LOGDEBUG, "[wvc1_write_header]invalid codec!"); + return PLAYER_EMPTY_P; + } + pkt->newflag = 1; + return write_av_packet(para, pkt); +} + +static int mpeg_add_header(am_private_t *para, am_packet_t *pkt) +{ + CLog::Log(LOGDEBUG, "mpeg_add_header"); +#define STUFF_BYTES_LENGTH (256) + int size; + unsigned char packet_wrapper[] = { + 0x00, 0x00, 0x01, 0xe0, + 0x00, 0x00, /* pes packet length */ + 0x81, 0xc0, 0x0d, + 0x20, 0x00, 0x00, 0x00, 0x00, /* PTS */ + 0x1f, 0xff, 0xff, 0xff, 0xff, /* DTS */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + + size = para->extrasize + sizeof(packet_wrapper); + packet_wrapper[4] = size >> 8 ; + packet_wrapper[5] = size & 0xff ; + memcpy(pkt->hdr->data, packet_wrapper, sizeof(packet_wrapper)); + size = sizeof(packet_wrapper); + //CLog::Log(LOGDEBUG, "[mpeg_add_header:%d]wrapper size=%d\n",__LINE__,size); + memcpy(pkt->hdr->data + size, para->extradata, para->extrasize); + size += para->extrasize; + //CLog::Log(LOGDEBUG, "[mpeg_add_header:%d]wrapper+seq size=%d\n",__LINE__,size); + memset(pkt->hdr->data + size, 0xff, STUFF_BYTES_LENGTH); + size += STUFF_BYTES_LENGTH; + pkt->hdr->size = size; + //CLog::Log(LOGDEBUG, "[mpeg_add_header:%d]hdr_size=%d\n",__LINE__,size); + if (1) { + pkt->codec = ¶->vcodec; + } else { + CLog::Log(LOGDEBUG, "[mpeg_add_header]invalid codec!"); + return PLAYER_EMPTY_P; + } + + pkt->newflag = 1; + return write_av_packet(para, pkt); +} + +int pre_header_feeding(am_private_t *para, am_packet_t *pkt) +{ + int ret; + if (para->stream_type == AM_STREAM_ES) { + if (pkt->hdr == NULL) { + pkt->hdr = (hdr_buf_t*)malloc(sizeof(hdr_buf_t)); + pkt->hdr->data = (char *)malloc(HDR_BUF_SIZE); + if (!pkt->hdr->data) { + //CLog::Log(LOGDEBUG, "[pre_header_feeding] NOMEM!"); + return PLAYER_NOMEM; + } + } + + if (VFORMAT_H264 == para->video_format /*|| VFORMAT_H264MVC == para->video_format*/) { + ret = h264_write_header(para, pkt); + if (ret != PLAYER_SUCCESS) { + return ret; + } + } else if ((VFORMAT_MPEG4 == para->video_format) && (VIDEO_DEC_FORMAT_MPEG4_3 == para->video_codec_type)) { + ret = divx3_write_header(para, pkt); + if (ret != PLAYER_SUCCESS) { + return ret; + } + } else if ((CODEC_TAG_M4S2 == para->video_codec_tag) + || (CODEC_TAG_DX50 == para->video_codec_tag) + || (CODEC_TAG_mp4v == para->video_codec_tag)) { + ret = m4s2_dx50_mp4v_write_header(para, pkt); + if (ret != PLAYER_SUCCESS) { + return ret; + } + /* + } else if ((AVI_FILE == para->file_type) + && (VIDEO_DEC_FORMAT_MPEG4_3 != para->vstream_info.video_codec_type) + && (VFORMAT_H264 != para->vstream_info.video_format) + && (VFORMAT_VC1 != para->vstream_info.video_format)) { + ret = avi_write_header(para); + if (ret != PLAYER_SUCCESS) { + return ret; + } + */ + } else if (CODEC_TAG_WMV3 == para->video_codec_tag) { + CLog::Log(LOGDEBUG, "CODEC_TAG_WMV3 == para->video_codec_tag"); + ret = wmv3_write_header(para, pkt); + if (ret != PLAYER_SUCCESS) { + return ret; + } + } else if ((CODEC_TAG_WVC1 == para->video_codec_tag) + || (CODEC_TAG_VC_1 == para->video_codec_tag) + || (CODEC_TAG_WMVA == para->video_codec_tag)) { + CLog::Log(LOGDEBUG, "CODEC_TAG_WVC1 == para->video_codec_tag"); + ret = wvc1_write_header(para, pkt); + if (ret != PLAYER_SUCCESS) { + return ret; + } + /* + } else if ((MKV_FILE == para->file_type) && + ((VFORMAT_MPEG4 == para->vstream_info.video_format) + || (VFORMAT_MPEG12 == para->vstream_info.video_format))) { + ret = mkv_write_header(para, pkt); + if (ret != PLAYER_SUCCESS) { + return ret; + } + */ + } else if (VFORMAT_MJPEG == para->video_format) { + ret = mjpeg_write_header(para, pkt); + if (ret != PLAYER_SUCCESS) { + return ret; + } + } + + if (pkt->hdr) { + if (pkt->hdr->data) { + free(pkt->hdr->data); + pkt->hdr->data = NULL; + } + free(pkt->hdr); + pkt->hdr = NULL; + } + } + else if (para->stream_type == AM_STREAM_PS) { + if (pkt->hdr == NULL) { + pkt->hdr = (hdr_buf_t*)malloc(sizeof(hdr_buf_t)); + pkt->hdr->data = (char*)malloc(HDR_BUF_SIZE); + if (!pkt->hdr->data) { + CLog::Log(LOGDEBUG, "[pre_header_feeding] NOMEM!"); + return PLAYER_NOMEM; + } + } + if (( CODEC_ID_MPEG1VIDEO == para->video_codec_id) + || (CODEC_ID_MPEG2VIDEO == para->video_codec_id) + || (CODEC_ID_MPEG2VIDEO_XVMC == para->video_codec_id)) { + ret = mpeg_add_header(para, pkt); + if (ret != PLAYER_SUCCESS) { + return ret; + } + } + if (pkt->hdr) { + if (pkt->hdr->data) { + free(pkt->hdr->data); + pkt->hdr->data = NULL; + } + free(pkt->hdr); + pkt->hdr = NULL; + } + } + return PLAYER_SUCCESS; +} + +/*************************************************************************/ +int h264_update_frame_header(am_packet_t *pkt) +{ + int nalsize, size = pkt->data_size; + unsigned char *data = pkt->data; + unsigned char *p = data; + if (p != NULL) { + if (check_size_in_buffer(p, size)) { + while ((p + 4) < (data + size)) { + nalsize = (*p << 24) | (*(p + 1) << 16) | (*(p + 2) << 8) | (*(p + 3)); + *p = 0; + *(p + 1) = 0; + *(p + 2) = 0; + *(p + 3) = 1; + p += (nalsize + 4); + } + return PLAYER_SUCCESS; + } else if (check_size_in_buffer3(p, size)) { + while ((p + 3) < (data + size)) { + nalsize = (*p << 16) | (*(p + 1) << 8) | (*(p + 2)); + *p = 0; + *(p + 1) = 0; + *(p + 2) = 1; + p += (nalsize + 3); + } + return PLAYER_SUCCESS; + } else if (check_size_in_buffer2(p, size)) { + unsigned char *new_data; + int new_len = 0; + + new_data = (unsigned char *)malloc(size + 2 * 1024); + if (!new_data) { + return PLAYER_NOMEM; + } + + while ((p + 2) < (data + size)) { + nalsize = (*p << 8) | (*(p + 1)); + *(new_data + new_len) = 0; + *(new_data + new_len + 1) = 0; + *(new_data + new_len + 2) = 0; + *(new_data + new_len + 3) = 1; + memcpy(new_data + new_len + 4, p + 2, nalsize); + p += (nalsize + 2); + new_len += nalsize + 4; + } + + free(pkt->buf); + + pkt->buf = new_data; + pkt->buf_size = size + 2 * 1024; + pkt->data = pkt->buf; + pkt->data_size = new_len; + } + } else { + CLog::Log(LOGDEBUG, "[%s]invalid pointer!", __FUNCTION__); + return PLAYER_FAILED; + } + return PLAYER_SUCCESS; +} + +int divx3_prefix(am_packet_t *pkt) +{ +#define DIVX311_CHUNK_HEAD_SIZE 13 + const unsigned char divx311_chunk_prefix[DIVX311_CHUNK_HEAD_SIZE] = { + 0x00, 0x00, 0x00, 0x01, 0xb6, 'D', 'I', 'V', 'X', '3', '.', '1', '1' + }; + if ((pkt->hdr != NULL) && (pkt->hdr->data != NULL)) { + free(pkt->hdr->data); + pkt->hdr->data = NULL; + } + + if (pkt->hdr == NULL) { + pkt->hdr = (hdr_buf_t*)malloc(sizeof(hdr_buf_t)); + if (!pkt->hdr) { + CLog::Log(LOGDEBUG, "[divx3_prefix] NOMEM!"); + return PLAYER_FAILED; + } + + pkt->hdr->data = NULL; + pkt->hdr->size = 0; + } + + pkt->hdr->data = (char*)malloc(DIVX311_CHUNK_HEAD_SIZE + 4); + if (pkt->hdr->data == NULL) { + CLog::Log(LOGDEBUG, "[divx3_prefix] NOMEM!"); + return PLAYER_FAILED; + } + + memcpy(pkt->hdr->data, divx311_chunk_prefix, DIVX311_CHUNK_HEAD_SIZE); + + pkt->hdr->data[DIVX311_CHUNK_HEAD_SIZE + 0] = (pkt->data_size >> 24) & 0xff; + pkt->hdr->data[DIVX311_CHUNK_HEAD_SIZE + 1] = (pkt->data_size >> 16) & 0xff; + pkt->hdr->data[DIVX311_CHUNK_HEAD_SIZE + 2] = (pkt->data_size >> 8) & 0xff; + pkt->hdr->data[DIVX311_CHUNK_HEAD_SIZE + 3] = pkt->data_size & 0xff; + + pkt->hdr->size = DIVX311_CHUNK_HEAD_SIZE + 4; + pkt->newflag = 1; + + return PLAYER_SUCCESS; +} + +int set_header_info(am_private_t *para) +{ + am_packet_t *pkt = ¶->am_pkt; + + //if (pkt->newflag) + { + //if (pkt->hdr) + // pkt->hdr->size = 0; + + if ((para->video_format == VFORMAT_H264) /*|| (am_private->video_format == VFORMAT_H264MVC)*/) + { + return h264_update_frame_header(pkt); + } + else if (para->video_format == VFORMAT_MPEG4) + { + if (para->video_codec_type == VIDEO_DEC_FORMAT_MPEG4_3) + { + return divx3_prefix(pkt); + } + else if (para->video_codec_type == VIDEO_DEC_FORMAT_H263) + { + return PLAYER_UNSUPPORT; + unsigned char *vld_buf; + int vld_len, vld_buf_size = para->video_width * para->video_height * 2; + + if (!pkt->data_size) { + return PLAYER_SUCCESS; + } + + if ((pkt->data[0] == 0) && (pkt->data[1] == 0) && (pkt->data[2] == 1) && (pkt->data[3] == 0xb6)) { + return PLAYER_SUCCESS; + } + + vld_buf = (unsigned char*)malloc(vld_buf_size); + if (!vld_buf) { + return PLAYER_NOMEM; + } + + if (para->flv_flag) { + vld_len = para->m_dll->h263vld(pkt->data, vld_buf, pkt->data_size, 1); + } else { + if (0 == para->h263_decodable) { + para->h263_decodable = para->m_dll->decodeble_h263(pkt->data); + if (0 == para->h263_decodable) { + CLog::Log(LOGDEBUG, "[%s]h263 unsupport video and audio, exit", __FUNCTION__); + return PLAYER_UNSUPPORT; + } + } + vld_len = para->m_dll->h263vld(pkt->data, vld_buf, pkt->data_size, 0); + } + + if (vld_len > 0) { + if (pkt->buf) { + free(pkt->buf); + } + pkt->buf = vld_buf; + pkt->buf_size = vld_buf_size; + pkt->data = pkt->buf; + pkt->data_size = vld_len; + } else { + free(vld_buf); + pkt->data_size = 0; + } + } + } else if (para->video_format == VFORMAT_VC1) { + if (para->video_codec_type == VIDEO_DEC_FORMAT_WMV3) { + unsigned i, check_sum = 0, data_len = 0; + + if ((pkt->hdr != NULL) && (pkt->hdr->data != NULL)) { + free(pkt->hdr->data); + pkt->hdr->data = NULL; + } + + if (pkt->hdr == NULL) { + pkt->hdr = (hdr_buf_t*)malloc(sizeof(hdr_buf_t)); + if (!pkt->hdr) { + return PLAYER_FAILED; + } + + pkt->hdr->data = NULL; + pkt->hdr->size = 0; + } + + if (pkt->avpkt.flags) { + pkt->hdr->data = (char*)malloc(para->extrasize + 26 + 22); + if (pkt->hdr->data == NULL) { + return PLAYER_FAILED; + } + + pkt->hdr->data[0] = 0; + pkt->hdr->data[1] = 0; + pkt->hdr->data[2] = 1; + pkt->hdr->data[3] = 0x10; + + data_len = para->extrasize + 4; + pkt->hdr->data[4] = 0; + pkt->hdr->data[5] = (data_len >> 16) & 0xff; + pkt->hdr->data[6] = 0x88; + pkt->hdr->data[7] = (data_len >> 8) & 0xff; + pkt->hdr->data[8] = data_len & 0xff; + pkt->hdr->data[9] = 0x88; + + pkt->hdr->data[10] = 0xff; + pkt->hdr->data[11] = 0xff; + pkt->hdr->data[12] = 0x88; + pkt->hdr->data[13] = 0xff; + pkt->hdr->data[14] = 0xff; + pkt->hdr->data[15] = 0x88; + + for (i = 4 ; i < 16 ; i++) { + check_sum += pkt->hdr->data[i]; + } + + pkt->hdr->data[16] = (check_sum >> 8) & 0xff; + pkt->hdr->data[17] = check_sum & 0xff; + pkt->hdr->data[18] = 0x88; + pkt->hdr->data[19] = (check_sum >> 8) & 0xff; + pkt->hdr->data[20] = check_sum & 0xff; + pkt->hdr->data[21] = 0x88; + + pkt->hdr->data[22] = (para->video_width >> 8) & 0xff; + pkt->hdr->data[23] = para->video_width & 0xff; + pkt->hdr->data[24] = (para->video_height >> 8) & 0xff; + pkt->hdr->data[25] = para->video_height & 0xff; + + memcpy(pkt->hdr->data + 26, para->extradata, para->extrasize); + + check_sum = 0; + data_len = para->extrasize + 26; + } else { + pkt->hdr->data = (char*)malloc(22); + if (pkt->hdr->data == NULL) { + return PLAYER_FAILED; + } + } + + pkt->hdr->data[data_len + 0] = 0; + pkt->hdr->data[data_len + 1] = 0; + pkt->hdr->data[data_len + 2] = 1; + pkt->hdr->data[data_len + 3] = 0xd; + + pkt->hdr->data[data_len + 4] = 0; + pkt->hdr->data[data_len + 5] = (pkt->data_size >> 16) & 0xff; + pkt->hdr->data[data_len + 6] = 0x88; + pkt->hdr->data[data_len + 7] = (pkt->data_size >> 8) & 0xff; + pkt->hdr->data[data_len + 8] = pkt->data_size & 0xff; + pkt->hdr->data[data_len + 9] = 0x88; + + pkt->hdr->data[data_len + 10] = 0xff; + pkt->hdr->data[data_len + 11] = 0xff; + pkt->hdr->data[data_len + 12] = 0x88; + pkt->hdr->data[data_len + 13] = 0xff; + pkt->hdr->data[data_len + 14] = 0xff; + pkt->hdr->data[data_len + 15] = 0x88; + + for (i = data_len + 4 ; i < data_len + 16 ; i++) { + check_sum += pkt->hdr->data[i]; + } + + pkt->hdr->data[data_len + 16] = (check_sum >> 8) & 0xff; + pkt->hdr->data[data_len + 17] = check_sum & 0xff; + pkt->hdr->data[data_len + 18] = 0x88; + pkt->hdr->data[data_len + 19] = (check_sum >> 8) & 0xff; + pkt->hdr->data[data_len + 20] = check_sum & 0xff; + pkt->hdr->data[data_len + 21] = 0x88; + + pkt->hdr->size = data_len + 22; + pkt->newflag = 1; + } else if (para->video_codec_type == VIDEO_DEC_FORMAT_WVC1) { + if ((pkt->hdr != NULL) && (pkt->hdr->data != NULL)) { + free(pkt->hdr->data); + pkt->hdr->data = NULL; + } + + if (pkt->hdr == NULL) { + pkt->hdr = (hdr_buf_t*)malloc(sizeof(hdr_buf_t)); + if (!pkt->hdr) { + CLog::Log(LOGDEBUG, "[wvc1_prefix] NOMEM!"); + return PLAYER_FAILED; + } + + pkt->hdr->data = NULL; + pkt->hdr->size = 0; + } + + pkt->hdr->data = (char*)malloc(4); + if (pkt->hdr->data == NULL) { + CLog::Log(LOGDEBUG, "[wvc1_prefix] NOMEM!"); + return PLAYER_FAILED; + } + + pkt->hdr->data[0] = 0; + pkt->hdr->data[1] = 0; + pkt->hdr->data[2] = 1; + pkt->hdr->data[3] = 0xd; + pkt->hdr->size = 4; + pkt->newflag = 1; + } + } + } + return PLAYER_SUCCESS; +} + +/*************************************************************************/ +CAMLCodec::CAMLCodec() : CThread("CAMLCodec") +{ + m_opened = false; + am_private = new am_private_t; + memset(am_private, 0, sizeof(am_private_t)); + m_dll = new DllLibAmCodec; + m_dll->Load(); + am_private->m_dll = m_dll; +} + + +CAMLCodec::~CAMLCodec() +{ + StopThread(); + delete am_private; + am_private = NULL; + delete m_dll, m_dll = NULL; +} + +bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) +{ + CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder"); + m_speed = DVD_PLAYSPEED_NORMAL; + m_1st_pts = 0; + m_cur_pts = 0; + m_cur_pictcnt = 0; + m_old_pictcnt = 0; + m_dst_rect.SetRect(0, 0, 0, 0); + m_zoom = -1; + m_contrast = -1; + m_brightness = -1; + m_vbufsize = 500000 * 2; + m_start_dts = 0; + m_start_pts = 0; + m_hints = hints; + + ShowMainVideo(false); + + am_packet_init(&am_private->am_pkt); + // default stream type + am_private->stream_type = AM_STREAM_ES; + // handle hints. + am_private->video_width = hints.width; + am_private->video_height = hints.height; + am_private->video_codec_id = hints.codec; + am_private->video_codec_tag = hints.codec_tag; + am_private->video_pid = hints.pid; + + // handle video ratio + AVRational video_ratio = m_dll->av_d2q(1, SHRT_MAX); + //if (!hints.forced_aspect) + // video_ratio = m_dll->av_d2q(hints.aspect, SHRT_MAX); + am_private->video_ratio = ((int32_t)video_ratio.num << 16) | video_ratio.den; + am_private->video_ratio64 = ((int64_t)video_ratio.num << 32) | video_ratio.den; + + // handle video rate + if (hints.rfpsrate > 0 && hints.rfpsscale != 0) + { + // check ffmpeg r_frame_rate 1st + am_private->video_rate = 0.5 + (float)UNIT_FREQ * hints.rfpsscale / hints.rfpsrate; + } + else if (hints.fpsrate > 0 && hints.fpsscale != 0) + { + // then ffmpeg avg_frame_rate next + am_private->video_rate = 0.5 + (float)UNIT_FREQ * hints.fpsscale / hints.fpsrate; + } + + // check for 1920x1080, interlaced, 25 fps + // incorrectly reported as 50 fps (yes, video_rate == 1920) + if (hints.width == 1920 && am_private->video_rate == 1920) + { + CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder video_rate exception"); + am_private->video_rate = 0.5 + (float)UNIT_FREQ * 1001 / 25000; + } + + // check for SD h264 content incorrectly reported as 60 fsp + // mp4/avi containers :( + if (hints.codec == CODEC_ID_H264 && hints.width <= 720 && am_private->video_rate == 1602) + { + CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder video_rate exception"); + am_private->video_rate = 0.5 + (float)UNIT_FREQ * 1001 / 24000; + } + + // check for SD h264 content incorrectly reported as some form of 30 fsp + // mp4/avi containers :( + if (hints.codec == CODEC_ID_H264 && hints.width <= 720) + { + if (am_private->video_rate >= 3200 && am_private->video_rate <= 3210) + { + CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder video_rate exception"); + am_private->video_rate = 0.5 + (float)UNIT_FREQ * 1001 / 24000; + } + } + + // handle orientation + am_private->video_rotation_degree = 0; + if (hints.orientation == 90) + am_private->video_rotation_degree = 1; + else if (hints.orientation == 180) + am_private->video_rotation_degree = 2; + else if (hints.orientation == 270) + am_private->video_rotation_degree = 3; + // handle extradata + am_private->video_format = codecid_to_vformat(hints.codec); + switch (am_private->video_format) + { + default: + am_private->extrasize = hints.extrasize; + am_private->extradata = (uint8_t*)malloc(hints.extrasize); + memcpy(am_private->extradata, hints.extradata, hints.extrasize); + break; + case VFORMAT_REAL: + case VFORMAT_MPEG12: + break; + } + + if (am_private->stream_type == AM_STREAM_ES && am_private->video_codec_tag != 0) + am_private->video_codec_type = codec_tag_to_vdec_type(am_private->video_codec_tag); + else + am_private->video_codec_type = codec_tag_to_vdec_type(am_private->video_codec_id); + + am_private->flv_flag = 0; + if (am_private->video_codec_id == CODEC_ID_FLV1) + { + am_private->video_codec_tag = CODEC_TAG_F263; + am_private->flv_flag = 1; + } + + CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder hints.fpsrate(%d), hints.fpsscale(%d), hints.rfpsrate(%d), hints.rfpsscale(%d), video_rate(%d)", + hints.fpsrate, hints.fpsscale, hints.rfpsrate, hints.rfpsscale, am_private->video_rate); + CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder hints.aspect(%f), video_ratio.num(%d), video_ratio.den(%d)", + hints.aspect, video_ratio.num, video_ratio.den); + CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder hints.orientation(%d), hints.forced_aspect(%d), hints.extrasize(%d)", + hints.orientation, hints.forced_aspect, hints.extrasize); + + // default video codec params + am_private->vcodec.has_video = 1; + am_private->vcodec.noblock = 0; + am_private->vcodec.video_pid = am_private->video_pid; + am_private->vcodec.video_type = am_private->video_format; + am_private->vcodec.stream_type = STREAM_TYPE_ES_VIDEO; + am_private->vcodec.am_sysinfo.format = am_private->video_codec_type; + am_private->vcodec.am_sysinfo.width = am_private->video_width; + am_private->vcodec.am_sysinfo.height = am_private->video_height; + am_private->vcodec.am_sysinfo.rate = am_private->video_rate; + am_private->vcodec.am_sysinfo.ratio = am_private->video_ratio; + am_private->vcodec.am_sysinfo.ratio64 = am_private->video_ratio64; + am_private->vcodec.am_sysinfo.param = NULL; + + switch(am_private->video_format) + { + default: + break; + case VFORMAT_MPEG4: + am_private->vcodec.am_sysinfo.param = (void*)EXTERNAL_PTS; + break; + case VFORMAT_H264: + case VFORMAT_H264MVC: + am_private->vcodec.am_sysinfo.format = VIDEO_DEC_FORMAT_H264; + am_private->vcodec.am_sysinfo.param = (void*)EXTERNAL_PTS; + // h264 in an avi file + if (m_hints.ptsinvalid) + am_private->vcodec.am_sysinfo.param = (void*)(EXTERNAL_PTS | SYNC_OUTSIDE); + break; + case VFORMAT_REAL: + am_private->stream_type = AM_STREAM_RM; + am_private->vcodec.stream_type = STREAM_TYPE_RM; + am_private->vcodec.am_sysinfo.ratio = 0x100; + am_private->vcodec.am_sysinfo.ratio64 = 0; + { + static unsigned short tbl[9] = {0}; + if (VIDEO_DEC_FORMAT_REAL_8 == am_private->video_codec_type) + { + am_private->vcodec.am_sysinfo.extra = am_private->extradata[1] & 7; + tbl[0] = (((am_private->vcodec.am_sysinfo.width >> 2) - 1) << 8) + | (((am_private->vcodec.am_sysinfo.height >> 2) - 1) & 0xff); + unsigned int j; + for (unsigned int i = 1; i <= am_private->vcodec.am_sysinfo.extra; i++) + { + j = 2 * (i - 1); + tbl[i] = ((am_private->extradata[8 + j] - 1) << 8) | ((am_private->extradata[8 + j + 1] - 1) & 0xff); + } + } + am_private->vcodec.am_sysinfo.param = &tbl; + } + break; + case VFORMAT_VC1: + // vc1 in an avi file + if (m_hints.ptsinvalid) + am_private->vcodec.am_sysinfo.param = (void*)EXTERNAL_PTS; + break; + } + am_private->vcodec.am_sysinfo.param = (void *)((unsigned int)am_private->vcodec.am_sysinfo.param | (am_private->video_rotation_degree << 16)); + + int ret = m_dll->codec_init(&am_private->vcodec); + if (ret != CODEC_ERROR_NONE) + { + CLog::Log(LOGDEBUG, "CAMLCodec::OpenDecoder codec init failed, ret=0x%x", -ret); + return false; + } + // make sure we are not stuck in pause (amcodec bug) + m_dll->codec_resume(&am_private->vcodec); + m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE); + + m_dll->codec_set_cntl_avthresh(&am_private->vcodec, AV_SYNC_THRESH); + m_dll->codec_set_cntl_syncthresh(&am_private->vcodec, 0); + // disable tsync, we are playing video disconnected from audio. + aml_set_sysfs_int("/sys/class/tsync/enable", 0); + + am_private->am_pkt.codec = &am_private->vcodec; + pre_header_feeding(am_private, &am_private->am_pkt); + + Create(); + + g_renderManager.RegisterRenderUpdateCallBack((const void*)this, RenderUpdateCallBack); + g_renderManager.RegisterRenderFeaturesCallBack((const void*)this, RenderFeaturesCallBack); + +/* + // if display is set to 1080xxx, then disable deinterlacer for HD content + // else bandwidth usage is too heavy and it will slow down video decoder. + char display_mode[256] = {0}; + aml_get_sysfs_str("/sys/class/display/mode", display_mode, 255); + if (strstr(display_mode,"1080")) + aml_set_sysfs_int("/sys/module/di/parameters/bypass_all", 1); + else + aml_set_sysfs_int("/sys/module/di/parameters/bypass_all", 0); +*/ + + m_opened = true; + // vcodec is open, update speed if it was + // changed before dvdplayer called OpenDecoder. + SetSpeed(m_speed); + + return true; +} + +void CAMLCodec::CloseDecoder() +{ + CLog::Log(LOGDEBUG, "CAMLCodec::CloseDecoder"); + StopThread(); + + g_renderManager.RegisterRenderUpdateCallBack((const void*)NULL, NULL); + g_renderManager.RegisterRenderFeaturesCallBack((const void*)NULL, NULL); + + // never leave vcodec paused and closed. + SetSpeed(DVD_PLAYSPEED_NORMAL); + m_dll->codec_close(&am_private->vcodec); + m_opened = false; + + am_packet_release(&am_private->am_pkt); + free(am_private->extradata); + am_private->extradata = NULL; + // return tsync to default so external apps work + aml_set_sysfs_int("/sys/class/tsync/enable", 1); + + ShowMainVideo(false); + +} + +void CAMLCodec::Reset() +{ + CLog::Log(LOGDEBUG, "CAMLCodec::Reset"); + + if (!m_opened) + return; + + // set the system blackout_policy to leave the last frame showing + int blackout_policy = aml_get_sysfs_int("/sys/class/video/blackout_policy"); + aml_set_sysfs_int("/sys/class/video/blackout_policy", 0); + + // restore the speed (some amcodec versions require this) + if (m_speed != DVD_PLAYSPEED_NORMAL) + { + m_dll->codec_resume(&am_private->vcodec); + m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE); + } + // reset the decoder + m_dll->codec_reset(&am_private->vcodec); + + // re-init our am_pkt + am_packet_release(&am_private->am_pkt); + am_packet_init(&am_private->am_pkt); + am_private->am_pkt.codec = &am_private->vcodec; + pre_header_feeding(am_private, &am_private->am_pkt); + + // restore the saved system blackout_policy value + aml_set_sysfs_int("/sys/class/video/blackout_policy", blackout_policy); + + // reset some interal vars + m_1st_pts = 0; + m_cur_pts = 0; + m_cur_pictcnt = 0; + m_old_pictcnt = 0; + SetSpeed(m_speed); +} + +int CAMLCodec::Decode(unsigned char *pData, size_t size, double dts, double pts) +{ + if (!m_opened) + return VC_BUFFER; + + // grr, m_RenderUpdateCallBackFn in g_renderManager is NULL'ed during + // g_renderManager.Configure call by player, which happens after the codec + // OpenDecoder call. So we need to restore it but it does not seem to stick :) + g_renderManager.RegisterRenderUpdateCallBack((const void*)this, RenderUpdateCallBack); + + if (pData) + { + am_private->am_pkt.data = pData; + am_private->am_pkt.data_size = size; + + am_private->am_pkt.newflag = 1; + am_private->am_pkt.isvalid = 1; + am_private->am_pkt.avduration = 0; + + // handle pts, including 31bit wrap, aml can only handle 31 + // bit pts as it uses an int in kernel. + if (m_hints.ptsinvalid || pts == DVD_NOPTS_VALUE) + am_private->am_pkt.avpts = AV_NOPTS_VALUE; + else + { + am_private->am_pkt.avpts = 0.5 + (pts * PTS_FREQ) / DVD_TIME_BASE;\ + if (!m_start_pts && am_private->am_pkt.avpts >= 0x7fffffff) + m_start_pts = am_private->am_pkt.avpts & ~0x0000ffff; + } + if (am_private->am_pkt.avpts != (int64_t)AV_NOPTS_VALUE) + am_private->am_pkt.avpts -= m_start_pts; + + + // handle dts, including 31bit wrap, aml can only handle 31 + // bit dts as it uses an int in kernel. + if (dts == DVD_NOPTS_VALUE) + am_private->am_pkt.avdts = AV_NOPTS_VALUE; + else + { + am_private->am_pkt.avdts = 0.5 + (dts * PTS_FREQ) / DVD_TIME_BASE; + if (!m_start_dts && am_private->am_pkt.avdts >= 0x7fffffff) + m_start_dts = am_private->am_pkt.avdts & ~0x0000ffff; + } + if (am_private->am_pkt.avdts != (int64_t)AV_NOPTS_VALUE) + am_private->am_pkt.avdts -= m_start_dts; + + //CLog::Log(LOGDEBUG, "CAMLCodec::Decode: siz(%d), dts(%f), pts(%f), avdts(%llx), avpts(%llx)", + // size, dts, pts, am_private->am_pkt.avdts, am_private->am_pkt.avpts); + + set_header_info(am_private); + write_av_packet(am_private, &am_private->am_pkt); + + // if we seek, then GetTimeSize is wrong as + // reports lastpts - cur_pts and hw decoder has + // not started outputing new pts values yet. + // so we grab the 1st pts sent into driver and + // use that to calc GetTimeSize. + if (m_1st_pts == 0) + m_1st_pts = am_private->am_pkt.lastpts; + } + + // if we have still frames, demux size will be small + // and we need to pre-buffer more. + double target_timesize = 1.0; + if (size < 20) + target_timesize = 2.0; + + // keep hw buffered demux above 1 second + if (GetTimeSize() < target_timesize && m_speed == DVD_PLAYSPEED_NORMAL) + return VC_BUFFER; + + // wait until we get a new frame or 100ms, + if (m_old_pictcnt == m_cur_pictcnt) + m_ready_event.WaitMSec(100); + + // we must return VC_BUFFER or VC_PICTURE, + // default to VC_BUFFER. + int rtn = VC_BUFFER; + if (m_old_pictcnt != m_cur_pictcnt) + { + m_old_pictcnt = m_cur_pictcnt; + rtn = VC_PICTURE; + // we got a new pict, try and keep hw buffered demux above 2 seconds. + // this, combined with the above 1 second check, keeps hw buffered demux between 1 and 2 seconds. + // we also check to make sure we keep from filling hw buffer. + if (GetTimeSize() < 2.0 && GetDataSize() < m_vbufsize/3) + rtn |= VC_BUFFER; + } +/* + CLog::Log(LOGDEBUG, "CAMLCodec::Decode: " + "rtn(%d), m_cur_pictcnt(%lld), m_cur_pts(%f), lastpts(%f), GetTimeSize(%f), GetDataSize(%d)", + rtn, m_cur_pictcnt, (float)m_cur_pts/PTS_FREQ, (float)am_private->am_pkt.lastpts/PTS_FREQ, GetTimeSize(), GetDataSize()); +*/ + return rtn; +} + +bool CAMLCodec::GetPicture(DVDVideoPicture *pDvdVideoPicture) +{ + if (!m_opened) + return false; + + pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED; + pDvdVideoPicture->format = RENDER_FMT_BYPASS; + pDvdVideoPicture->iDuration = (double)(am_private->video_rate * DVD_TIME_BASE) / UNIT_FREQ; + + pDvdVideoPicture->dts = DVD_NOPTS_VALUE; + pDvdVideoPicture->pts = GetPlayerPtsSeconds() * (double)DVD_TIME_BASE; + // video pts cannot be late or dvdplayer goes nuts, + // so run it one frame ahead + pDvdVideoPicture->pts += 1 * pDvdVideoPicture->iDuration; + + return true; +} + +void CAMLCodec::SetSpeed(int speed) +{ + CLog::Log(LOGDEBUG, "CAMLCodec::SetSpeed, speed(%d)", speed); + + // update internal vars regardless + // of if we are open or not. + m_speed = speed; + + if (!m_opened) + return; + + switch(speed) + { + case DVD_PLAYSPEED_PAUSE: + m_dll->codec_pause(&am_private->vcodec); + m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE); + break; + case DVD_PLAYSPEED_NORMAL: + m_dll->codec_resume(&am_private->vcodec); + m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE); + break; + default: + m_dll->codec_resume(&am_private->vcodec); + if (am_private->video_format == VFORMAT_H264) + m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_FFFB); + else + m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_I); + break; + } +} + +int CAMLCodec::GetDataSize() +{ + if (!m_opened) + return 0; + + struct buf_status vbuf ={0}; + if (m_dll->codec_get_vbuf_state(&am_private->vcodec, &vbuf) >= 0) + m_vbufsize = vbuf.size; + + return vbuf.data_len; +} + +double CAMLCodec::GetTimeSize() +{ + if (!m_opened) + return 0; + + // if m_cur_pts is zero, hw decoder was not started yet + // so we use the pts of the 1st demux packet that was send + // to hw decoder to calc timesize. + if (m_cur_pts == 0) + m_timesize = (double)(am_private->am_pkt.lastpts - m_1st_pts) / PTS_FREQ; + else + m_timesize = (double)(am_private->am_pkt.lastpts - m_cur_pts) / PTS_FREQ; + + // lie to DVDPlayer, it is hardcoded to a max of 8 seconds, + // if you buffer more than 8 seconds, it goes nuts. + double timesize = m_timesize; + if (timesize < 0.0) + timesize = 0.0; + else if (timesize > 7.0) + timesize = 7.0; + + return timesize; +} + +void CAMLCodec::Process() +{ + CLog::Log(LOGDEBUG, "CAMLCodec::Process Started"); + + // bump our priority to be level with SoftAE + SetPriority(THREAD_PRIORITY_ABOVE_NORMAL); + while (!m_bStop) + { + int64_t pts_video = 0; + if (am_private->am_pkt.lastpts > 0) + { + // this is a blocking poll that returns every vsync. + // since we are running at a higher priority, make sure + // we sleep if the call fails or does a timeout. + if (m_dll->codec_poll_cntl(&am_private->vcodec) < 0) + { + CLog::Log(LOGDEBUG, "CAMLCodec::Process: codec_poll_cntl failed"); + Sleep(10); + } + + pts_video = get_pts_video(); + if (m_cur_pts != pts_video) + { + //CLog::Log(LOGDEBUG, "CAMLCodec::Process: pts_video(%lld), pts_video/PTS_FREQ(%f), duration(%f)", + // pts_video, (double)pts_video/PTS_FREQ, 1.0/((double)(pts_video - m_cur_pts)/PTS_FREQ)); + // other threads look at these, do them first + m_cur_pts = pts_video; + m_cur_pictcnt++; + m_ready_event.Set(); + + // correct video pts by starting pts. + if (m_start_pts != 0) + pts_video += m_start_pts; + else if (m_start_dts != 0) + pts_video += m_start_dts; + + double app_pts = GetPlayerPtsSeconds(); + // add in audio delay/display latency contribution + double offset = g_renderManager.GetDisplayLatency() - CMediaSettings::Get().GetCurrentVideoSettings().m_AudioDelay; + // correct video pts by user set delay and rendering delay + app_pts += offset; + + //CLog::Log(LOGDEBUG, "CAMLCodec::Process: app_pts(%f), pts_video/PTS_FREQ(%f)", + // app_pts, (double)pts_video/PTS_FREQ); + + double error = app_pts - (double)pts_video/PTS_FREQ; + double abs_error = fabs(error); + if (abs_error > 0.150) + { + //CLog::Log(LOGDEBUG, "CAMLCodec::Process pts diff = %f", error); + if (abs_error > 0.125) + { + // big error so try to reset pts_pcrscr + SetVideoPtsSeconds(app_pts); + } + else + { + // small error so try to avoid a frame jump + SetVideoPtsSeconds((double)pts_video/PTS_FREQ + error/4); + } + } + } + } + else + { + Sleep(10); + } + } + SetPriority(THREAD_PRIORITY_NORMAL); + CLog::Log(LOGDEBUG, "CAMLCodec::Process Stopped"); +} + +double CAMLCodec::GetPlayerPtsSeconds() +{ + double clock_pts = 0.0; + CDVDClock *playerclock = CDVDClock::GetMasterClock(); + if (playerclock) + clock_pts = playerclock->GetClock() / DVD_TIME_BASE; + + return clock_pts; +} + +void CAMLCodec::SetVideoPtsSeconds(const double pts) +{ + //CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoPtsSeconds: pts(%f)", pts); + if (pts >= 0.0) + { + int64_t pts_video = (int64_t)(pts * PTS_FREQ); + if (m_start_pts != 0) + pts_video -= m_start_pts; + else if (m_start_dts != 0) + pts_video -= m_start_dts; + + set_pts_pcrscr(pts_video); + } +} + +void CAMLCodec::ShowMainVideo(const bool show) +{ + static int saved_disable_video = -1; + + int disable_video = show ? 0:1; + if (saved_disable_video == disable_video) + return; + + aml_set_sysfs_int("/sys/class/video/disable_video", disable_video); + saved_disable_video = disable_video; +} + +void CAMLCodec::SetVideoZoom(const float zoom) +{ + // input zoom range is 0.5 to 2.0 with a default of 1.0. + // output zoom range is 2 to 300 with default of 100. + // we limit that to a range of 50 to 200 with default of 100. + aml_set_sysfs_int("/sys/class/video/zoom", (int)(100 * zoom)); +} + +void CAMLCodec::SetVideoContrast(const int contrast) +{ + // input contrast range is 0 to 100 with default of 50. + // output contrast range is -255 to 255 with default of 0. + int aml_contrast = (255 * (contrast - 50)) / 50; + aml_set_sysfs_int("/sys/class/video/contrast", aml_contrast); +} +void CAMLCodec::SetVideoBrightness(const int brightness) +{ + // input brightness range is 0 to 100 with default of 50. + // output brightness range is -127 to 127 with default of 0. + int aml_brightness = (127 * (brightness - 50)) / 50; + aml_set_sysfs_int("/sys/class/video/brightness", aml_brightness); +} +void CAMLCodec::SetVideoSaturation(const int saturation) +{ + // output saturation range is -127 to 127 with default of 127. + aml_set_sysfs_int("/sys/class/video/saturation", saturation); +} + +void CAMLCodec::GetRenderFeatures(Features &renderFeatures) +{ + renderFeatures.push_back(RENDERFEATURE_ZOOM); + renderFeatures.push_back(RENDERFEATURE_CONTRAST); + renderFeatures.push_back(RENDERFEATURE_BRIGHTNESS); + renderFeatures.push_back(RENDERFEATURE_STRETCH); + renderFeatures.push_back(RENDERFEATURE_PIXEL_RATIO); + return; +} + +void CAMLCodec::RenderFeaturesCallBack(const void *ctx, Features &renderFeatures) +{ + CAMLCodec *codec = (CAMLCodec*)ctx; + if (codec) + codec->GetRenderFeatures(renderFeatures); +} + +void CAMLCodec::SetVideoRect(const CRect &SrcRect, const CRect &DestRect) +{ + // this routine gets called every video frame + // and is in the context of the renderer thread so + // do not do anything stupid here. + + // video zoom adjustment. + float zoom = CMediaSettings::Get().GetCurrentVideoSettings().m_CustomZoomAmount; + if ((int)(zoom * 1000) != (int)(m_zoom * 1000)) + { + m_zoom = zoom; + } + // video contrast adjustment. + int contrast = CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast; + if (contrast != m_contrast) + { + SetVideoContrast(contrast); + m_contrast = contrast; + } + // video brightness adjustment. + int brightness = CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness; + if (brightness != m_brightness) + { + SetVideoBrightness(brightness); + m_brightness = brightness; + } + + // check if destination rect or video view mode has changed + if ((m_dst_rect != DestRect) || (m_view_mode != CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode)) + { + m_dst_rect = DestRect; + m_view_mode = CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode; + } + else + { + // mainvideo 'should' be showing already if we get here, make sure. + ShowMainVideo(true); + return; + } + + CRect gui, display, dst_rect; + gui = g_graphicsContext.GetViewWindow(); + // when display is at 1080p, we have freescale enabled + // and that scales all layers into 1080p display including video, + // so we have to setup video axis for 720p instead of 1080p... Boooo. + display = g_graphicsContext.GetViewWindow(); + dst_rect = m_dst_rect; + if (gui != display) + { + float xscale = display.Width() / gui.Width(); + float yscale = display.Height() / gui.Height(); + dst_rect.x1 *= xscale; + dst_rect.x2 *= xscale; + dst_rect.y1 *= yscale; + dst_rect.y2 *= yscale; + } + + ShowMainVideo(false); + + // goofy 0/1 based difference in aml axis coordinates. + // fix them. + dst_rect.x2--; + dst_rect.y2--; + + char video_axis[256] = {0}; + sprintf(video_axis, "%d %d %d %d", (int)dst_rect.x1, (int)dst_rect.y1, (int)dst_rect.x2, (int)dst_rect.y2); + aml_set_sysfs_str("/sys/class/video/axis", video_axis); + // make sure we are in 'full stretch' so we can stretch + aml_set_sysfs_int("/sys/class/video/screen_mode", 1); + +/* + CStdString rectangle; + rectangle.Format("%i,%i,%i,%i", + (int)dst_rect.x1, (int)dst_rect.y1, + (int)dst_rect.Width(), (int)dst_rect.Height()); + CLog::Log(LOGDEBUG, "CAMLCodec::SetVideoRect:dst_rect(%s)", rectangle.c_str()); +*/ + + // we only get called once gui has changed to something + // that would show video playback, so show it. + ShowMainVideo(true); +} + +void CAMLCodec::RenderUpdateCallBack(const void *ctx, const CRect &SrcRect, const CRect &DestRect) +{ + CAMLCodec *codec = (CAMLCodec*)ctx; + codec->SetVideoRect(SrcRect, DestRect); +} diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.h new file mode 100644 index 0000000000..346f92b0c1 --- /dev/null +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/AMLCodec.h @@ -0,0 +1,86 @@ +#pragma once +/* + * Copyright (C) 2005-2011 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 "DVDVideoCodec.h" +#include "cores/dvdplayer/DVDStreamInfo.h" +#include "cores/VideoRenderers/RenderFeatures.h" +#include "guilib/Geometry.h" +#include "threads/Thread.h" + +typedef struct am_private_t am_private_t; + +class DllLibAmCodec; + +class CAMLCodec : public CThread +{ +public: + CAMLCodec(); + virtual ~CAMLCodec(); + + bool OpenDecoder(CDVDStreamInfo &hints); + void CloseDecoder(); + void Reset(); + + int Decode(unsigned char *pData, size_t size, double dts, double pts); + + bool GetPicture(DVDVideoPicture* pDvdVideoPicture); + void SetSpeed(int speed); + int GetDataSize(); + double GetTimeSize(); + +protected: + virtual void Process(); + +private: + double GetPlayerPtsSeconds(); + void SetVideoPtsSeconds(double pts); + void ShowMainVideo(const bool show); + void SetVideoZoom(const float zoom); + void SetVideoContrast(const int contrast); + void SetVideoBrightness(const int brightness); + void SetVideoSaturation(const int saturation); + void GetRenderFeatures(Features &renderFeatures); + static void RenderFeaturesCallBack(const void *ctx, Features &renderFeatures); + void SetVideoRect(const CRect &SrcRect, const CRect &DestRect); + static void RenderUpdateCallBack(const void *ctx, const CRect &SrcRect, const CRect &DestRect); + + DllLibAmCodec *m_dll; + bool m_opened; + am_private_t *am_private; + CDVDStreamInfo m_hints; + volatile int m_speed; + volatile int64_t m_1st_pts; + volatile int64_t m_cur_pts; + volatile int64_t m_cur_pictcnt; + volatile int64_t m_old_pictcnt; + volatile double m_timesize; + volatile int64_t m_vbufsize; + int64_t m_start_dts; + int64_t m_start_pts; + CEvent m_ready_event; + + CRect m_dst_rect; + int m_view_mode; + float m_zoom; + int m_contrast; + int m_brightness; +}; diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp new file mode 100644 index 0000000000..252ab6cfad --- /dev/null +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp @@ -0,0 +1,467 @@ +/* + * Copyright (C) 2005-2011 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 <math.h> + +#include "DVDVideoCodecAmlogic.h" +#include "DVDClock.h" +#include "DVDStreamInfo.h" +#include "AMLCodec.h" +#include "video/VideoThumbLoader.h" +#include "utils/BitstreamConverter.h" +#include "utils/log.h" + +#define __MODULE_NAME__ "DVDVideoCodecAmlogic" + +typedef struct frame_queue { + double dts; + double pts; + double sort_time; + struct frame_queue *nextframe; +} frame_queue; + +CDVDVideoCodecAmlogic::CDVDVideoCodecAmlogic() : + m_Codec(NULL), + m_pFormatName("amcodec"), + m_last_pts(0.0), + m_frame_queue(NULL), + m_queue_depth(0), + m_framerate(0.0), + m_video_rate(0), + m_mpeg2_sequence(NULL) +{ + pthread_mutex_init(&m_queue_mutex, NULL); +} + +CDVDVideoCodecAmlogic::~CDVDVideoCodecAmlogic() +{ + Dispose(); + pthread_mutex_destroy(&m_queue_mutex); +} + +bool CDVDVideoCodecAmlogic::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) +{ + switch(hints.codec) + { + case CODEC_ID_MJPEG: + m_pFormatName = "am-mjpeg"; + break; + case CODEC_ID_MPEG1VIDEO: + case CODEC_ID_MPEG2VIDEO: + case CODEC_ID_MPEG2VIDEO_XVMC: + m_mpeg2_sequence_pts = 0; + m_mpeg2_sequence = new mpeg2_sequence; + m_mpeg2_sequence->width = hints.width; + m_mpeg2_sequence->height = hints.height; + m_mpeg2_sequence->ratio = hints.aspect; + if (hints.rfpsrate > 0 && hints.rfpsscale != 0) + m_mpeg2_sequence->rate = (float)hints.rfpsrate / hints.rfpsscale; + else if (hints.fpsrate > 0 && hints.fpsscale != 0) + m_mpeg2_sequence->rate = (float)hints.fpsrate / hints.fpsscale; + else + m_mpeg2_sequence->rate = 1.0; + m_pFormatName = "am-mpeg2"; + break; + case CODEC_ID_H264: + m_pFormatName = "am-h264"; + break; + case CODEC_ID_MPEG4: + case CODEC_ID_MSMPEG4V2: + case CODEC_ID_MSMPEG4V3: + m_pFormatName = "am-mpeg4"; + break; + case CODEC_ID_H263: + case CODEC_ID_H263P: + case CODEC_ID_H263I: + m_pFormatName = "am-h263"; + break; + case CODEC_ID_FLV1: + m_pFormatName = "am-flv1"; + break; + case CODEC_ID_RV10: + case CODEC_ID_RV20: + case CODEC_ID_RV30: + case CODEC_ID_RV40: + m_pFormatName = "am-rv"; + break; + case CODEC_ID_VC1: + m_pFormatName = "am-vc1"; + break; + case CODEC_ID_WMV3: + m_pFormatName = "am-wmv3"; + break; + case CODEC_ID_AVS: + case CODEC_ID_CAVS: + m_pFormatName = "am-avs"; + break; + default: + CLog::Log(LOGDEBUG, "%s: Unknown hints.codec(%d", __MODULE_NAME__, hints.codec); + return false; + break; + } + + m_hints = hints; + m_aspect_ratio = hints.aspect; + m_Codec = new CAMLCodec(); + if (!m_Codec) + { + CLog::Log(LOGERROR, "%s: Failed to create Amlogic Codec", __MODULE_NAME__); + return false; + } + m_opened = false; + + // allocate a dummy DVDVideoPicture buffer. + // first make sure all properties are reset. + memset(&m_videobuffer, 0, sizeof(DVDVideoPicture)); + + m_videobuffer.dts = DVD_NOPTS_VALUE; + m_videobuffer.pts = DVD_NOPTS_VALUE; + m_videobuffer.format = RENDER_FMT_BYPASS; + m_videobuffer.color_range = 0; + m_videobuffer.color_matrix = 4; + m_videobuffer.iFlags = DVP_FLAG_ALLOCATED; + m_videobuffer.iWidth = hints.width; + m_videobuffer.iHeight = hints.height; + + m_videobuffer.iDisplayWidth = m_videobuffer.iWidth; + m_videobuffer.iDisplayHeight = m_videobuffer.iHeight; + if (hints.aspect > 0.0 && !hints.forced_aspect) + { + m_videobuffer.iDisplayWidth = ((int)lrint(m_videobuffer.iHeight * hints.aspect)) & -3; + if (m_videobuffer.iDisplayWidth > m_videobuffer.iWidth) + { + m_videobuffer.iDisplayWidth = m_videobuffer.iWidth; + m_videobuffer.iDisplayHeight = ((int)lrint(m_videobuffer.iWidth / hints.aspect)) & -3; + } + } + + CLog::Log(LOGINFO, "%s: Opened Amlogic Codec", __MODULE_NAME__); + return true; +} + +void CDVDVideoCodecAmlogic::Dispose(void) +{ + if (m_Codec) + m_Codec->CloseDecoder(), m_Codec = NULL; + if (m_videobuffer.iFlags) + m_videobuffer.iFlags = 0; + if (m_mpeg2_sequence) + delete m_mpeg2_sequence, m_mpeg2_sequence = NULL; + + while (m_queue_depth) + FrameQueuePop(); +} + +int CDVDVideoCodecAmlogic::Decode(BYTE *pData, int iSize, double dts, double pts) +{ + // Handle Input, add demuxer packet to input queue, we must accept it or + // it will be discarded as DVDPlayerVideo has no concept of "try again". + + if (pData) + FrameRateTracking( pData, iSize, dts, pts); + + if (!m_opened) + { + if (m_Codec && !m_Codec->OpenDecoder(m_hints)) + CLog::Log(LOGERROR, "%s: Failed to open Amlogic Codec", __MODULE_NAME__); + m_opened = true; + } + + if (m_hints.ptsinvalid) + pts = DVD_NOPTS_VALUE; + + return m_Codec->Decode(pData, iSize, dts, pts); +} + +void CDVDVideoCodecAmlogic::Reset(void) +{ + while (m_queue_depth) + FrameQueuePop(); + + m_Codec->Reset(); + m_mpeg2_sequence_pts = 0; +} + +bool CDVDVideoCodecAmlogic::GetPicture(DVDVideoPicture* pDvdVideoPicture) +{ + if (m_Codec) + m_Codec->GetPicture(&m_videobuffer); + *pDvdVideoPicture = m_videobuffer; + + // check for mpeg2 aspect ratio changes + if (m_mpeg2_sequence && pDvdVideoPicture->pts >= m_mpeg2_sequence_pts) + m_aspect_ratio = m_mpeg2_sequence->ratio; + + pDvdVideoPicture->iDisplayWidth = pDvdVideoPicture->iWidth; + pDvdVideoPicture->iDisplayHeight = pDvdVideoPicture->iHeight; + if (m_aspect_ratio > 1.0 && !m_hints.forced_aspect) + { + pDvdVideoPicture->iDisplayWidth = ((int)lrint(pDvdVideoPicture->iHeight * m_aspect_ratio)) & -3; + if (pDvdVideoPicture->iDisplayWidth > pDvdVideoPicture->iWidth) + { + pDvdVideoPicture->iDisplayWidth = pDvdVideoPicture->iWidth; + pDvdVideoPicture->iDisplayHeight = ((int)lrint(pDvdVideoPicture->iWidth / m_aspect_ratio)) & -3; + } + } + + return true; +} + +void CDVDVideoCodecAmlogic::SetDropState(bool bDrop) +{ +} + +void CDVDVideoCodecAmlogic::SetSpeed(int iSpeed) +{ + if (m_Codec) + m_Codec->SetSpeed(iSpeed); +} + +int CDVDVideoCodecAmlogic::GetDataSize(void) +{ + if (m_Codec) + return m_Codec->GetDataSize(); + + return 0; +} + +double CDVDVideoCodecAmlogic::GetTimeSize(void) +{ + if (m_Codec) + return m_Codec->GetTimeSize(); + + return 0.0; +} + +void CDVDVideoCodecAmlogic::FrameQueuePop(void) +{ + if (!m_frame_queue || m_queue_depth == 0) + return; + + pthread_mutex_lock(&m_queue_mutex); + // pop the top frame off the queue + frame_queue *top = m_frame_queue; + m_frame_queue = top->nextframe; + m_queue_depth--; + pthread_mutex_unlock(&m_queue_mutex); + + // and release it + free(top); +} + +void CDVDVideoCodecAmlogic::FrameQueuePush(double dts, double pts) +{ + frame_queue *newframe = (frame_queue*)calloc(sizeof(frame_queue), 1); + newframe->dts = dts; + newframe->pts = pts; + // if both dts or pts are good we use those, else use decoder insert time for frame sort + if ((newframe->pts != DVD_NOPTS_VALUE) || (newframe->dts != DVD_NOPTS_VALUE)) + { + // if pts is borked (stupid avi's), use dts for frame sort + if (newframe->pts == DVD_NOPTS_VALUE) + newframe->sort_time = newframe->dts; + else + newframe->sort_time = newframe->pts; + } + + pthread_mutex_lock(&m_queue_mutex); + frame_queue *queueWalker = m_frame_queue; + if (!queueWalker || (newframe->sort_time < queueWalker->sort_time)) + { + // we have an empty queue, or this frame earlier than the current queue head. + newframe->nextframe = queueWalker; + m_frame_queue = newframe; + } + else + { + // walk the queue and insert this frame where it belongs in display order. + bool ptrInserted = false; + frame_queue *nextframe = NULL; + // + while (!ptrInserted) + { + nextframe = queueWalker->nextframe; + if (!nextframe || (newframe->sort_time < nextframe->sort_time)) + { + // if the next frame is the tail of the queue, or our new frame is earlier. + newframe->nextframe = nextframe; + queueWalker->nextframe = newframe; + ptrInserted = true; + } + queueWalker = nextframe; + } + } + m_queue_depth++; + pthread_mutex_unlock(&m_queue_mutex); +} + +void CDVDVideoCodecAmlogic::FrameRateTracking(BYTE *pData, int iSize, double dts, double pts) +{ + // mpeg2 handling + if (m_mpeg2_sequence) + { + // probe demux for sequence_header_code NAL and + // decode aspect ratio and frame rate. + if (CBitstreamConverter::mpeg2_sequence_header(pData, iSize, m_mpeg2_sequence)) + { + m_mpeg2_sequence_pts = pts; + if (m_mpeg2_sequence_pts == DVD_NOPTS_VALUE) + m_mpeg2_sequence_pts = dts; + + m_framerate = m_mpeg2_sequence->rate; + m_video_rate = (int)(0.5 + (96000.0 / m_framerate)); + + CLog::Log(LOGDEBUG, "%s: detected mpeg2 aspect ratio(%f), framerate(%f), video_rate(%d)", + __MODULE_NAME__, m_mpeg2_sequence->ratio, m_framerate, m_video_rate); + + // update hints for 1st frame fixup. + switch(m_mpeg2_sequence->rate_info) + { + default: + case 0x01: + m_hints.rfpsrate = 24000.0; + m_hints.rfpsscale = 1001.0; + break; + case 0x02: + m_hints.rfpsrate = 24000.0; + m_hints.rfpsscale = 1000.0; + break; + case 0x03: + m_hints.rfpsrate = 25000.0; + m_hints.rfpsscale = 1000.0; + break; + case 0x04: + m_hints.rfpsrate = 30000.0; + m_hints.rfpsscale = 1001.0; + break; + case 0x05: + m_hints.rfpsrate = 30000.0; + m_hints.rfpsscale = 1000.0; + break; + case 0x06: + m_hints.rfpsrate = 50000.0; + m_hints.rfpsscale = 1000.0; + break; + case 0x07: + m_hints.rfpsrate = 60000.0; + m_hints.rfpsscale = 1001.0; + break; + case 0x08: + m_hints.rfpsrate = 60000.0; + m_hints.rfpsscale = 1000.0; + break; + } + m_hints.width = m_mpeg2_sequence->width; + m_hints.height = m_mpeg2_sequence->height; + m_hints.aspect = m_mpeg2_sequence->ratio; + m_hints.fpsrate = m_hints.rfpsrate; + m_hints.fpsscale = m_hints.rfpsscale; + } + return; + } + + // everything else + FrameQueuePush(dts, pts); + + // we might have out-of-order pts, + // so make sure we wait for at least 8 values in sorted queue. + if (m_queue_depth > 16) + { + pthread_mutex_lock(&m_queue_mutex); + + float cur_pts = m_frame_queue->pts; + if (cur_pts == DVD_NOPTS_VALUE) + cur_pts = m_frame_queue->dts; + + pthread_mutex_unlock(&m_queue_mutex); + + float duration = cur_pts - m_last_pts; + m_last_pts = cur_pts; + + // clamp duration to sensible range, + // 66 fsp to 20 fsp + if (duration >= 15000.0 && duration <= 50000.0) + { + double framerate; + switch((int)(0.5 + duration)) + { + // 59.940 (16683.333333) + case 16000 ... 17000: + framerate = 60000.0 / 1001.0; + break; + + // 50.000 (20000.000000) + case 20000: + framerate = 50000.0 / 1000.0; + break; + + // 49.950 (20020.000000) + case 20020: + framerate = 50000.0 / 1001.0; + break; + + // 29.970 (33366.666656) + case 32000 ... 35000: + framerate = 30000.0 / 1001.0; + break; + + // 25.000 (40000.000000) + case 40000: + framerate = 25000.0 / 1000.0; + break; + + // 24.975 (40040.000000) + case 40040: + framerate = 25000.0 / 1001.0; + break; + + /* + // 24.000 (41666.666666) + case 41667: + framerate = 24000.0 / 1000.0; + break; + */ + + // 23.976 (41708.33333) + case 40200 ... 43200: + // 23.976 seems to have the crappiest encodings :) + framerate = 24000.0 / 1001.0; + break; + + default: + framerate = 0.0; + //CLog::Log(LOGDEBUG, "%s: unknown duration(%f), cur_pts(%f)", + // __MODULE_NAME__, duration, cur_pts); + break; + } + + if (framerate > 0.0 && (int)m_framerate != (int)framerate) + { + m_framerate = framerate; + m_video_rate = (int)(0.5 + (96000.0 / framerate)); + CLog::Log(LOGDEBUG, "%s: detected new framerate(%f), video_rate(%d)", + __MODULE_NAME__, m_framerate, m_video_rate); + } + } + + FrameQueuePop(); + } +} diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h new file mode 100644 index 0000000000..a78a953b68 --- /dev/null +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h @@ -0,0 +1,67 @@ +#pragma once +/* + * Copyright (C) 2005-2012 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 "DVDVideoCodec.h" +#include "DVDStreamInfo.h" + +class CAMLCodec; +struct frame_queue; +struct mpeg2_sequence; + +class CDVDVideoCodecAmlogic : public CDVDVideoCodec +{ +public: + CDVDVideoCodecAmlogic(); + virtual ~CDVDVideoCodecAmlogic(); + + // Required overrides + virtual bool Open(CDVDStreamInfo &hints, CDVDCodecOptions &options); + virtual void Dispose(void); + virtual int Decode(BYTE *pData, int iSize, double dts, double pts); + virtual void Reset(void); + virtual bool GetPicture(DVDVideoPicture *pDvdVideoPicture); + virtual void SetSpeed(int iSpeed); + virtual void SetDropState(bool bDrop); + virtual int GetDataSize(void); + virtual double GetTimeSize(void); + virtual const char* GetName(void) { return (const char*)m_pFormatName; } + +protected: + void FrameQueuePop(void); + void FrameQueuePush(double dts, double pts); + void FrameRateTracking(BYTE *pData, int iSize, double dts, double pts); + + CAMLCodec *m_Codec; + const char *m_pFormatName; + DVDVideoPicture m_videobuffer; + bool m_opened; + CDVDStreamInfo m_hints; + double m_last_pts; + frame_queue *m_frame_queue; + int32_t m_queue_depth; + pthread_mutex_t m_queue_mutex; + double m_framerate; + int m_video_rate; + float m_aspect_ratio; + mpeg2_sequence *m_mpeg2_sequence; + double m_mpeg2_sequence_pts; +}; diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecCrystalHD.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecCrystalHD.cpp index c5e1fbabca..74fd066cb4 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecCrystalHD.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecCrystalHD.cpp @@ -26,10 +26,10 @@ #endif #if defined(HAVE_LIBCRYSTALHD) -#include "settings/GUISettings.h" #include "DVDClock.h" #include "DVDStreamInfo.h" #include "DVDVideoCodecCrystalHD.h" +#include "settings/Settings.h" #include "utils/log.h" #include "utils/TimeUtils.h" @@ -51,7 +51,7 @@ CDVDVideoCodecCrystalHD::~CDVDVideoCodecCrystalHD() bool CDVDVideoCodecCrystalHD::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) { - if (g_guiSettings.GetBool("videoplayer.usechd") && !hints.software) + if (CSettings::Get().GetBool("videoplayer.usechd") && !hints.software) { switch (hints.codec) { diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp index 633172292b..6ce6e8b7af 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp @@ -33,7 +33,7 @@ #include "utils/CPUInfo.h" #endif #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "utils/log.h" #include "boost/shared_ptr.hpp" #include "threads/Atomics.h" @@ -72,11 +72,8 @@ enum PixelFormat CDVDVideoCodecFFmpeg::GetFormat( struct AVCodecContext * avctx while(*cur != PIX_FMT_NONE) { #ifdef HAVE_LIBVDPAU - if(CVDPAU::IsVDPAUFormat(*cur) && g_guiSettings.GetBool("videoplayer.usevdpau")) + if(CVDPAU::IsVDPAUFormat(*cur) && CSettings::Get().GetBool("videoplayer.usevdpau")) { - if(ctx->GetHardware()) - return *cur; - CLog::Log(LOGNOTICE,"CDVDVideoCodecFFmpeg::GetFormat - Creating VDPAU(%ix%i)", avctx->width, avctx->height); CVDPAU* vdp = new CVDPAU(); if(vdp->Open(avctx, *cur)) @@ -89,7 +86,7 @@ enum PixelFormat CDVDVideoCodecFFmpeg::GetFormat( struct AVCodecContext * avctx } #endif #ifdef HAS_DX - if(DXVA::CDecoder::Supports(*cur) && g_guiSettings.GetBool("videoplayer.usedxva2")) + if(DXVA::CDecoder::Supports(*cur) && CSettings::Get().GetBool("videoplayer.usedxva2")) { DXVA::CDecoder* dec = new DXVA::CDecoder(); if(dec->Open(avctx, *cur, ctx->m_uSurfacesCount)) @@ -103,7 +100,7 @@ enum PixelFormat CDVDVideoCodecFFmpeg::GetFormat( struct AVCodecContext * avctx #endif #ifdef HAVE_LIBVA // mpeg4 vaapi decoding is disabled - if(*cur == PIX_FMT_VAAPI_VLD && g_guiSettings.GetBool("videoplayer.usevaapi") + if(*cur == PIX_FMT_VAAPI_VLD && CSettings::Get().GetBool("videoplayer.usevaapi") && (avctx->codec_id != CODEC_ID_MPEG4 || g_advancedSettings.m_videoAllowMpeg4VAAPI)) { if (ctx->GetHardware() != NULL) @@ -203,39 +200,6 @@ bool CDVDVideoCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options } } -#ifdef HAVE_LIBVDPAU - if(g_guiSettings.GetBool("videoplayer.usevdpau") && !m_bSoftware) - { - while((pCodec = m_dllAvCodec.av_codec_next(pCodec))) - { - if(pCodec->id == hints.codec - && pCodec->capabilities & CODEC_CAP_HWACCEL_VDPAU) - { - if ((pCodec->id == CODEC_ID_MPEG4) && !g_advancedSettings.m_videoAllowMpeg4VDPAU) - continue; - - CLog::Log(LOGNOTICE,"CDVDVideoCodecFFmpeg::Open() Creating VDPAU(%ix%i, %d)",hints.width, hints.height, hints.codec); - CVDPAU* vdp = new CVDPAU(); - m_pCodecContext = m_dllAvCodec.avcodec_alloc_context3(pCodec); - m_pCodecContext->codec_id = hints.codec; - m_pCodecContext->width = hints.width; - m_pCodecContext->height = hints.height; - m_pCodecContext->coded_width = hints.width; - m_pCodecContext->coded_height = hints.height; - if(vdp->Open(m_pCodecContext, pCodec->pix_fmts ? pCodec->pix_fmts[0] : PIX_FMT_NONE)) - { - m_pHardware = vdp; - m_pCodecContext->codec_id = CODEC_ID_NONE; // ffmpeg will complain if this has been set - break; - } - m_dllAvUtil.av_freep(&m_pCodecContext); - CLog::Log(LOGNOTICE,"CDVDVideoCodecFFmpeg::Open() Failed to get VDPAU device"); - vdp->Release(); - } - } - } -#endif - if(pCodec == NULL) pCodec = m_dllAvCodec.avcodec_find_decoder(hints.codec); diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp index fdd947227e..3eb722c90f 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp @@ -26,7 +26,6 @@ #if defined(HAVE_LIBOPENMAX) #include "DVDClock.h" -#include "settings/GUISettings.h" #include "DVDStreamInfo.h" #include "DVDVideoCodecOpenMax.h" #include "OpenMaxVideo.h" @@ -52,7 +51,7 @@ CDVDVideoCodecOpenMax::~CDVDVideoCodecOpenMax() bool CDVDVideoCodecOpenMax::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) { // we always qualify even if DVDFactoryCodec does this too. - if (g_guiSettings.GetBool("videoplayer.useomx") && !hints.software) + if (CSettings::Get().GetBool("videoplayer.useomx") && !hints.software) { m_convert_bitstream = false; diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecVDA.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecVDA.cpp index e41ea34d65..bb5e23af8c 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecVDA.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecVDA.cpp @@ -29,11 +29,11 @@ #include "DVDStreamInfo.h" #include "cores/dvdplayer/DVDCodecs/DVDCodecUtils.h" #include "osx/CocoaInterface.h" -#include "settings/GUISettings.h" #include "windowing/WindowingFactory.h" #include "utils/BitstreamConverter.h" #include "utils/log.h" #include "utils/TimeUtils.h" +#include "settings/Settings.h" #include <CoreFoundation/CoreFoundation.h> @@ -236,7 +236,7 @@ bool CDVDVideoCodecVDA::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) else m_dll = g_DllLibVDADecoder; - if (g_guiSettings.GetBool("videoplayer.usevda") && !hints.software) + if (CSettings::Get().GetBool("videoplayer.usevda") && !hints.software) { CCocoaAutoPool pool; diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecVideoToolBox.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecVideoToolBox.cpp index bba603dd73..905a355f2a 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecVideoToolBox.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecVideoToolBox.cpp @@ -23,13 +23,13 @@ #endif #if defined(HAVE_VIDEOTOOLBOXDECODER) -#include "GUISettings.h" #include "DVDClock.h" #include "DVDStreamInfo.h" #include "DVDCodecUtils.h" #include "DVDVideoCodecVideoToolBox.h" #include "lib/DllSwScale.h" #include "lib/DllAvFormat.h" +#include "settings/Settings.h" #include "utils/log.h" #include "utils/TimeUtils.h" #include "osx/DarwinUtils.h" @@ -1058,7 +1058,7 @@ CDVDVideoCodecVideoToolBox::~CDVDVideoCodecVideoToolBox() bool CDVDVideoCodecVideoToolBox::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) { - if (g_guiSettings.GetBool("videoplayer.usevideotoolbox") && !hints.software) + if (CSettings::Get().GetBool("videoplayer.usevideotoolbox") && !hints.software) { m_dllAvUtil = new DllAvUtil; m_dllAvFormat = new DllAvFormat; diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DXVA.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DXVA.cpp index 147d954a66..e1a3dd476f 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DXVA.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DXVA.cpp @@ -36,6 +36,7 @@ #include "windowing/WindowingFactory.h" #include "../../../VideoRenderers/WinRenderer.h" #include "settings/Settings.h" +#include "settings/MediaSettings.h" #include "boost/shared_ptr.hpp" #include "utils/AutoPtrHandle.h" #include "settings/AdvancedSettings.h" diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in index 176ceff899..157b6b325e 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in @@ -23,6 +23,12 @@ SRCS += OpenMaxVideo.cpp SRCS += DVDVideoCodecOpenMax.cpp endif +ifeq (@USE_LIBAMCODEC@,1) +SRCS += AMLCodec.cpp +SRCS += DVDVideoCodecAmlogic.cpp +INCLUDES += -I$(prefix)/include/amlplayer +endif + LIB=Video.a include @abs_top_srcdir@/Makefile.include diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp index a781585984..3ad5f78ed6 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp @@ -29,7 +29,6 @@ #include "DVDVideoCodecFFmpeg.h" #include "DVDClock.h" #include "settings/Settings.h" -#include "settings/GUISettings.h" #include "settings/AdvancedSettings.h" #include "settings/MediaSettings.h" #include "Application.h" @@ -185,6 +184,9 @@ bool CVDPAU::Open(AVCodecContext* avctx, const enum PixelFormat, unsigned int su return false; } + if ((avctx->codec_id == CODEC_ID_MPEG4) && !g_advancedSettings.m_videoAllowMpeg4VDPAU) + return false; + if (!dl_handle) { dl_handle = dlopen("libvdpau.so.1", RTLD_LAZY); @@ -240,10 +242,15 @@ bool CVDPAU::Open(AVCodecContext* avctx, const enum PixelFormat, unsigned int su InitCSCMatrix(avctx->coded_height); /* finally setup ffmpeg */ + memset(&m_hwContext, 0, sizeof(AVVDPAUContext)); + m_hwContext.render = CVDPAU::Render; + m_hwContext.bitstream_buffers_allocated = 0; avctx->get_buffer = CVDPAU::FFGetBuffer; avctx->release_buffer = CVDPAU::FFReleaseBuffer; avctx->draw_horiz_band = CVDPAU::FFDrawSlice; avctx->slice_flags=SLICE_FLAG_CODED_ORDER|SLICE_FLAG_ALLOW_FIELD; + avctx->hwaccel_context = &m_hwContext; + avctx->thread_count = 1; g_Windowing.Register(this); return true; @@ -273,6 +280,11 @@ void CVDPAU::Close() free(render); } + if (m_hwContext.bitstream_buffers_allocated) + { + m_dllAvUtil.av_freep(&m_hwContext.bitstream_buffers); + } + g_Windowing.Unregister(this); m_dllAvUtil.Unload(); } @@ -498,11 +510,10 @@ int CVDPAU::Check(AVCodecContext* avctx) bool CVDPAU::IsVDPAUFormat(PixelFormat format) { - if ((format >= PIX_FMT_VDPAU_H264) && (format <= PIX_FMT_VDPAU_VC1)) return true; -#if (defined PIX_FMT_VDPAU_MPEG4_IN_AVUTIL) - if (format == PIX_FMT_VDPAU_MPEG4) return true; -#endif - else return false; + if (format == AV_PIX_FMT_VDPAU) + return true; + else + return false; } void CVDPAU::CheckFeatures() @@ -617,7 +628,7 @@ void CVDPAU::SetColor() vdp_st = vdp_generate_csc_matrix(&m_Procamp, VDP_COLOR_STANDARD_ITUR_BT_601, &m_CSCMatrix); VdpVideoMixerAttribute attributes[] = { VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX }; - if (g_guiSettings.GetBool("videoscreen.limitedrange")) + if (CSettings::Get().GetBool("videoscreen.limitedrange")) { void const * pm_CSCMatix[] = { &studioCSC }; vdp_st = vdp_video_mixer_set_attribute_values(videoMixer, ARSIZE(attributes), attributes, pm_CSCMatix); @@ -915,35 +926,35 @@ void CVDPAU::FiniVDPAUOutput() } -void CVDPAU::ReadFormatOf( PixelFormat fmt +void CVDPAU::ReadFormatOf( AVCodecID codec , VdpDecoderProfile &vdp_decoder_profile , VdpChromaType &vdp_chroma_type) { - switch (fmt) + switch (codec) { - case PIX_FMT_VDPAU_MPEG1: + case AV_CODEC_ID_MPEG1VIDEO: vdp_decoder_profile = VDP_DECODER_PROFILE_MPEG1; vdp_chroma_type = VDP_CHROMA_TYPE_420; break; - case PIX_FMT_VDPAU_MPEG2: + case AV_CODEC_ID_MPEG2VIDEO: vdp_decoder_profile = VDP_DECODER_PROFILE_MPEG2_MAIN; vdp_chroma_type = VDP_CHROMA_TYPE_420; break; - case PIX_FMT_VDPAU_H264: + case AV_CODEC_ID_H264: vdp_decoder_profile = VDP_DECODER_PROFILE_H264_HIGH; vdp_chroma_type = VDP_CHROMA_TYPE_420; break; - case PIX_FMT_VDPAU_WMV3: + case AV_CODEC_ID_WMV3: vdp_decoder_profile = VDP_DECODER_PROFILE_VC1_MAIN; vdp_chroma_type = VDP_CHROMA_TYPE_420; break; - case PIX_FMT_VDPAU_VC1: + case AV_CODEC_ID_VC1: vdp_decoder_profile = VDP_DECODER_PROFILE_VC1_ADVANCED; vdp_chroma_type = VDP_CHROMA_TYPE_420; break; #if (defined PIX_FMT_VDPAU_MPEG4_IN_AVUTIL) && \ (defined VDP_DECODER_PROFILE_MPEG4_PART2_ASP) - case PIX_FMT_VDPAU_MPEG4: + case AV_CODEC_ID_MPEG4: vdp_decoder_profile = VDP_DECODER_PROFILE_MPEG4_PART2_ASP; vdp_chroma_type = VDP_CHROMA_TYPE_420; break; @@ -970,9 +981,9 @@ bool CVDPAU::ConfigVDPAU(AVCodecContext* avctx, int ref_frames) past[1] = past[0] = current = future = NULL; CLog::Log(LOGNOTICE, " (VDPAU) screenWidth:%i vidWidth:%i surfaceWidth:%i",OutWidth,vid_width,surface_width); CLog::Log(LOGNOTICE, " (VDPAU) screenHeight:%i vidHeight:%i surfaceHeight:%i",OutHeight,vid_height,surface_height); - ReadFormatOf(avctx->pix_fmt, vdp_decoder_profile, vdp_chroma_type); + ReadFormatOf(avctx->codec_id, vdp_decoder_profile, vdp_chroma_type); - if(avctx->pix_fmt == PIX_FMT_VDPAU_H264) + if(avctx->codec_id == AV_CODEC_ID_H264) { max_references = ref_frames; if (max_references > 16) max_references = 16; @@ -1230,7 +1241,7 @@ int CVDPAU::FFGetBuffer(AVCodecContext *avctx, AVFrame *pic) { // create a new surface VdpDecoderProfile profile; - ReadFormatOf(avctx->pix_fmt, profile, vdp->vdp_chroma_type); + ReadFormatOf(avctx->codec_id, profile, vdp->vdp_chroma_type); render = (vdpau_render_state*)calloc(sizeof(vdpau_render_state), 1); if (render == NULL) { @@ -1260,8 +1271,9 @@ int CVDPAU::FFGetBuffer(AVCodecContext *avctx, AVFrame *pic) if (render == NULL) return -1; - pic->data[1] = pic->data[2] = NULL; - pic->data[0]= (uint8_t*)render; + pic->data[1] = pic->data[2] = NULL; + pic->data[0] = (uint8_t*)render; + pic->data[3] = (uint8_t*)(uintptr_t)render->surface; pic->linesize[0] = pic->linesize[1] = pic->linesize[2] = 0; @@ -1314,6 +1326,13 @@ void CVDPAU::FFReleaseBuffer(AVCodecContext *avctx, AVFrame *pic) render->state &= ~FF_VDPAU_STATE_USED_FOR_REFERENCE; } +VdpStatus CVDPAU::Render(VdpDecoder decoder, VdpVideoSurface target, + VdpPictureInfo const *picture_info, + uint32_t bitstream_buffer_count, + VdpBitstreamBuffer const * bitstream_buffers) +{ + return VDP_STATUS_OK; +} void CVDPAU::FFDrawSlice(struct AVCodecContext *s, const AVFrame *src, int offset[4], @@ -1356,8 +1375,8 @@ void CVDPAU::FFDrawSlice(struct AVCodecContext *s, } uint32_t max_refs = 0; - if(s->pix_fmt == PIX_FMT_VDPAU_H264) - max_refs = render->info.h264.num_ref_frames; + if(s->codec_id == AV_CODEC_ID_H264) + max_refs = vdp->m_hwContext.info.h264.num_ref_frames; if(vdp->decoder == VDP_INVALID_HANDLE || vdp->vdpauConfigured == false @@ -1369,9 +1388,9 @@ void CVDPAU::FFDrawSlice(struct AVCodecContext *s, vdp_st = vdp->vdp_decoder_render(vdp->decoder, render->surface, - (VdpPictureInfo const *)&(render->info), - render->bitstream_buffers_used, - render->bitstream_buffers); + (VdpPictureInfo const *)&(vdp->m_hwContext.info), + vdp->m_hwContext.bitstream_buffers_used, + vdp->m_hwContext.bitstream_buffers); vdp->CheckStatus(vdp_st, __LINE__); } diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h index fa1ca38b7b..70f809792b 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h @@ -94,6 +94,10 @@ public: const AVFrame *src, int offset[4], int y, int type, int height); static int FFGetBuffer(AVCodecContext *avctx, AVFrame *pic); + static VdpStatus Render(VdpDecoder decoder, VdpVideoSurface target, + VdpPictureInfo const *picture_info, + uint32_t bitstream_buffer_count, + VdpBitstreamBuffer const * bitstream_buffers); void Present(); bool ConfigVDPAU(AVCodecContext *avctx, int ref_frames); @@ -222,11 +226,12 @@ public: int m_feature_count; static bool IsVDPAUFormat(PixelFormat fmt); - static void ReadFormatOf( PixelFormat fmt + static void ReadFormatOf( AVCodecID codec , VdpDecoderProfile &decoder_profile , VdpChromaType &chroma_type); std::vector<vdpau_render_state*> m_videoSurfaces; + AVVDPAUContext m_hwContext; DllAvUtil m_dllAvUtil; enum VDPAUOutputMethod diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.h b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.h index bdad65b300..45f72ac06b 100644 --- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.h +++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.h @@ -102,9 +102,13 @@ public: disabled = false; changes = 0; flags = FLAG_NONE; + orig_type = 0; } - virtual ~CDemuxStream() {} + virtual ~CDemuxStream() + { + delete [] ExtraData; + } virtual void GetStreamInfo(std::string& strInfo) { @@ -127,7 +131,7 @@ public: int iDuration; // in mseconds void* pPrivate; // private pointer for the demuxer - void* ExtraData; // extra data for codec to use + uint8_t* ExtraData; // extra data for codec to use unsigned int ExtraSize; // size of extra data char language[4]; // ISO 639 3-letter language code (empty string if undefined) @@ -135,6 +139,8 @@ public: int changes; // increment on change which player may need to know about + int orig_type; // type of original source + enum EFlags { FLAG_NONE = 0x0000 , FLAG_DEFAULT = 0x0001 @@ -154,6 +160,8 @@ public: { iFpsScale = 0; iFpsRate = 0; + irFpsScale = 0; + irFpsRate = 0; iHeight = 0; iWidth = 0; fAspect = 0.0; @@ -168,6 +176,8 @@ public: virtual ~CDemuxStreamVideo() {} int iFpsScale; // scale of 1000 and a rate of 29970 will result in 29.97 fps int iFpsRate; + int irFpsScale; + int irFpsRate; int iHeight; // height of the stream reported by the demuxer int iWidth; // width of the stream reported by the demuxer float fAspect; // display aspect of stream diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxBXA.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxBXA.cpp index e53edb355a..a498c5ed97 100644 --- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxBXA.cpp +++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxBXA.cpp @@ -51,6 +51,7 @@ CDVDDemuxBXA::CDVDDemuxBXA() : CDVDDemux() { m_pInput = NULL; m_stream = NULL; + m_bytes = 0; memset(&m_header, 0x0, sizeof(Demux_BXA_FmtHeader)); } @@ -101,7 +102,7 @@ void CDVDDemuxBXA::Dispose() m_stream = NULL; m_pInput = NULL; - m_pts = 0; + m_bytes = 0; memset(&m_header, 0x0, sizeof(Demux_BXA_FmtHeader)); } @@ -151,9 +152,9 @@ DemuxPacket* CDVDDemuxBXA::Read() int n = (m_header.channels * m_header.bitsPerSample * m_header.sampleRate)>>3; if (n > 0) { - m_pts += ((double)pPacket->iSize * DVD_TIME_BASE) / n; - pPacket->dts = m_pts; - pPacket->pts = m_pts; + m_bytes += pPacket->iSize; + pPacket->dts = (double)m_bytes * DVD_TIME_BASE / n; + pPacket->pts = pPacket->dts; } else { diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxBXA.h b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxBXA.h index 98c8582e09..56fd5fdf09 100644 --- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxBXA.h +++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxBXA.h @@ -76,7 +76,7 @@ public: protected: friend class CDemuxStreamAudioBXA; CDVDInputStream* m_pInput; - double m_pts; + int64_t m_bytes; CDemuxStreamAudioBXA *m_stream; diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxCDDA.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxCDDA.cpp new file mode 100644 index 0000000000..912678a713 --- /dev/null +++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxCDDA.cpp @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2013 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 "DVDInputStreams/DVDInputStream.h" +#include "DVDDemuxCDDA.h" +#include "DVDDemuxUtils.h" +#include "utils/log.h" +#include "../DVDClock.h" + +// CDDA audio demuxer based on AirTunes audio Demuxer. + +using namespace std; + +class CDemuxStreamAudioCDDA + : public CDemuxStreamAudio +{ +public: + void GetStreamInfo(string& strInfo) + { + strInfo = "pcm"; + } +}; + +CDVDDemuxCDDA::CDVDDemuxCDDA() : CDVDDemux() +{ + m_pInput = NULL; + m_stream = NULL; + m_bytes = 0; +} + +CDVDDemuxCDDA::~CDVDDemuxCDDA() +{ + Dispose(); +} + +bool CDVDDemuxCDDA::Open(CDVDInputStream* pInput) +{ + Abort(); + + Dispose(); + + if(!pInput || !pInput->IsStreamType(DVDSTREAM_TYPE_FILE)) + return false; + + m_pInput = pInput; + + m_stream = new CDemuxStreamAudioCDDA(); + + if(!m_stream) + return false; + + m_stream->iSampleRate = 44100; + m_stream->iBitsPerSample = 16; + m_stream->iBitRate = 44100 * 2 * 16; + m_stream->iChannels = 2; + m_stream->type = STREAM_AUDIO; + m_stream->codec = CODEC_ID_PCM_S16LE; + + return true; +} + +void CDVDDemuxCDDA::Dispose() +{ + delete m_stream; + m_stream = NULL; + + m_pInput = NULL; + m_bytes = 0; +} + +void CDVDDemuxCDDA::Reset() +{ + CDVDInputStream* pInputStream = m_pInput; + Dispose(); + Open(pInputStream); +} + +void CDVDDemuxCDDA::Abort() +{ + if(m_pInput) + return m_pInput->Abort(); +} + +void CDVDDemuxCDDA::Flush() +{ +} + +#define CDDA_READ_SIZE 4096 +DemuxPacket* CDVDDemuxCDDA::Read() +{ + if(!m_pInput) + return NULL; + + DemuxPacket* pPacket = CDVDDemuxUtils::AllocateDemuxPacket(CDDA_READ_SIZE); + + if (!pPacket) + { + if (m_pInput) + m_pInput->Close(); + return NULL; + } + + pPacket->iSize = m_pInput->Read(pPacket->pData, CDDA_READ_SIZE); + pPacket->iStreamId = 0; + + if(pPacket->iSize < 1) + { + delete pPacket; + pPacket = NULL; + } + else + { + int n = m_stream->iBitRate>>3; + if (n > 0) + { + m_bytes += pPacket->iSize; + pPacket->dts = (double)m_bytes * DVD_TIME_BASE / n; + pPacket->pts = pPacket->dts; + } + else + { + pPacket->dts = DVD_NOPTS_VALUE; + pPacket->pts = DVD_NOPTS_VALUE; + } + } + + return pPacket; +} + +int CDVDDemuxCDDA::GetStreamLength() +{ + int64_t num_track_bytes = m_pInput->GetLength(); + int bytes_per_second = (m_stream->iBitRate>>3); + int64_t track_mseconds = num_track_bytes*1000 / bytes_per_second; + return (int)track_mseconds; +} + +CDemuxStream* CDVDDemuxCDDA::GetStream(int iStreamId) +{ + if(iStreamId != 0) + return NULL; + + return m_stream; +} + +int CDVDDemuxCDDA::GetNrOfStreams() +{ + return (m_stream == NULL ? 0 : 1); +} + +std::string CDVDDemuxCDDA::GetFileName() +{ + if(m_pInput) + return m_pInput->GetFileName(); + else + return ""; +} + +void CDVDDemuxCDDA::GetStreamCodecName(int iStreamId, CStdString &strName) +{ + if (m_stream && iStreamId == 0) + strName = "pcm"; +} diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxCDDA.h b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxCDDA.h new file mode 100644 index 0000000000..76b1dea91c --- /dev/null +++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxCDDA.h @@ -0,0 +1,59 @@ +#pragma once +/* + * Copyright (C) 2013 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 "DVDDemux.h" + +#ifdef _WIN32 +#define __attribute__(dummy_val) +#else +#include <config.h> +#endif + +class CDemuxStreamAudioCDDA; + +class CDVDDemuxCDDA : public CDVDDemux +{ +public: + + CDVDDemuxCDDA(); + ~CDVDDemuxCDDA(); + + bool Open(CDVDInputStream* pInput); + void Dispose(); + void Reset(); + void Abort(); + void Flush(); + DemuxPacket* Read(); + bool SeekTime(int time, bool backwords = false, double* startpts = NULL) { return false; }; + void SetSpeed(int iSpeed) {}; + int GetStreamLength() ; + CDemuxStream* GetStream(int iStreamId); + int GetNrOfStreams(); + std::string GetFileName(); + virtual void GetStreamCodecName(int iStreamId, CStdString &strName); + +protected: + friend class CDemuxStreamAudioCDDA; + CDVDInputStream* m_pInput; + int64_t m_bytes; + + CDemuxStreamAudioCDDA *m_stream; +}; diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp index 0f2deaf0bb..014237db40 100644 --- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp @@ -40,7 +40,7 @@ #include "DVDClock.h" // for DVD_TIME_BASE #include "commons/Exception.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "filesystem/File.h" #include "filesystem/Directory.h" #include "utils/log.h" @@ -104,7 +104,8 @@ void ff_avutil_log(void* ptr, int level, const char* format, va_list va) AVClass* avc= ptr ? *(AVClass**)ptr : NULL; - if(level >= AV_LOG_DEBUG && g_advancedSettings.m_logLevel <= LOG_LEVEL_DEBUG_SAMBA) + if(level >= AV_LOG_DEBUG && + (g_advancedSettings.m_extraLogLevels & LOGFFMPEG) == 0) return; else if(g_advancedSettings.m_logLevel <= LOG_LEVEL_NORMAL) return; @@ -207,12 +208,13 @@ CDVDDemuxFFmpeg::CDVDDemuxFFmpeg() : CDVDDemux() m_pFormatContext = NULL; m_pInput = NULL; m_ioContext = NULL; - for (int i = 0; i < MAX_STREAMS; i++) m_streams[i] = NULL; m_iCurrentPts = DVD_NOPTS_VALUE; m_bMatroska = false; m_bAVI = false; m_speed = DVD_PLAYSPEED_NORMAL; m_program = UINT_MAX; + m_pkt.result = -1; + memset(&m_pkt.pkt, 0, sizeof(AVPacket)); } CDVDDemuxFFmpeg::~CDVDDemuxFFmpeg() @@ -476,37 +478,16 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput) UpdateCurrentPTS(); - // add the ffmpeg streams to our own stream array - if (m_pFormatContext->nb_programs) - { - // look for first non empty stream and discard nonselected programs - for (unsigned int i = 0; i < m_pFormatContext->nb_programs; i++) - { - if(m_program == UINT_MAX && m_pFormatContext->programs[i]->nb_stream_indexes > 0) - m_program = i; - - if(i != m_program) - m_pFormatContext->programs[i]->discard = AVDISCARD_ALL; - } - if(m_program != UINT_MAX) - { - // add streams from selected program - for (unsigned int i = 0; i < m_pFormatContext->programs[m_program]->nb_stream_indexes; i++) - AddStream(m_pFormatContext->programs[m_program]->stream_index[i]); - } - } - // if there were no programs or they were all empty, add all streams - if (m_program == UINT_MAX) - { - for (unsigned int i = 0; i < m_pFormatContext->nb_streams; i++) - AddStream(i); - } + CreateStreams(); return true; } void CDVDDemuxFFmpeg::Dispose() { + m_pkt.result = -1; + m_dllAvCodec.av_free_packet(&m_pkt.pkt); + if (m_pFormatContext) { if (m_ioContext && m_pFormatContext->pb && m_pFormatContext->pb != m_ioContext) @@ -527,16 +508,8 @@ void CDVDDemuxFFmpeg::Dispose() m_pFormatContext = NULL; m_speed = DVD_PLAYSPEED_NORMAL; - for (int i = 0; i < MAX_STREAMS; i++) - { - if (m_streams[i]) - { - if (m_streams[i]->ExtraData) - delete[] (BYTE*)(m_streams[i]->ExtraData); - delete m_streams[i]; - } - m_streams[i] = NULL; - } + DisposeStreams(); + m_pInput = NULL; m_dllAvFormat.Unload(); @@ -558,6 +531,9 @@ void CDVDDemuxFFmpeg::Flush() m_dllAvFormat.av_read_frame_flush(m_pFormatContext); m_iCurrentPts = DVD_NOPTS_VALUE; + + m_pkt.result = -1; + m_dllAvCodec.av_free_packet(&m_pkt.pkt); } void CDVDDemuxFFmpeg::Abort() @@ -627,7 +603,6 @@ double CDVDDemuxFFmpeg::ConvertTimestamp(int64_t pts, int den, int num) DemuxPacket* CDVDDemuxFFmpeg::Read() { - AVPacket pkt; DemuxPacket* pPacket = NULL; // on some cases where the received packet is invalid we will need to return an empty packet (0 length) otherwise the main loop (in CDVDPlayer) // would consider this the end of stream and stop. @@ -639,26 +614,42 @@ DemuxPacket* CDVDDemuxFFmpeg::Read() if(m_pFormatContext->pb) m_pFormatContext->pb->eof_reached = 0; - // keep track if ffmpeg doesn't always set these - pkt.size = 0; - pkt.data = NULL; - pkt.stream_index = MAX_STREAMS; - - // timeout reads after 100ms - m_timeout.Set(20000); - int result = m_dllAvFormat.av_read_frame(m_pFormatContext, &pkt); - m_timeout.SetInfinite(); + // check for saved packet after a program change + if (m_pkt.result < 0) + { + // keep track if ffmpeg doesn't always set these + m_pkt.pkt.size = 0; + m_pkt.pkt.data = NULL; + + // timeout reads after 100ms + m_timeout.Set(20000); + m_pkt.result = m_dllAvFormat.av_read_frame(m_pFormatContext, &m_pkt.pkt); + m_timeout.SetInfinite(); + } - if (result == AVERROR(EINTR) || result == AVERROR(EAGAIN)) + if (m_pkt.result == AVERROR(EINTR) || m_pkt.result == AVERROR(EAGAIN)) { // timeout, probably no real error, return empty packet bReturnEmpty = true; } - else if (result < 0) + else if (m_pkt.result < 0) { Flush(); } - else if (pkt.size < 0 || pkt.stream_index >= MAX_STREAMS) + else if (IsProgramChange()) + { + // update streams + CreateStreams(m_program); + + pPacket = CDVDDemuxUtils::AllocateDemuxPacket(0); + pPacket->iStreamId = DMX_SPECIALID_STREAMCHANGE; + + return pPacket; + } + // check size and stream index for being in a valid range + else if (m_pkt.pkt.size < 0 || + m_pkt.pkt.stream_index < 0 || + m_pkt.pkt.stream_index >= m_pFormatContext->nb_streams) { // XXX, in some cases ffmpeg returns a negative packet size if(m_pFormatContext->pb && !m_pFormatContext->pb->eof_reached) @@ -670,20 +661,21 @@ DemuxPacket* CDVDDemuxFFmpeg::Read() else CLog::Log(LOGERROR, "CDVDDemuxFFmpeg::Read() returned invalid packet and eof reached"); - m_dllAvCodec.av_free_packet(&pkt); + m_pkt.result = -1; + m_dllAvCodec.av_free_packet(&m_pkt.pkt); } else { - AVStream *stream = m_pFormatContext->streams[pkt.stream_index]; + AVStream *stream = m_pFormatContext->streams[m_pkt.pkt.stream_index]; if (m_program != UINT_MAX) { /* check so packet belongs to selected program */ for (unsigned int i = 0; i < m_pFormatContext->programs[m_program]->nb_stream_indexes; i++) { - if(pkt.stream_index == (int)m_pFormatContext->programs[m_program]->stream_index[i]) + if(m_pkt.pkt.stream_index == (int)m_pFormatContext->programs[m_program]->stream_index[i]) { - pPacket = CDVDDemuxUtils::AllocateDemuxPacket(pkt.size); + pPacket = CDVDDemuxUtils::AllocateDemuxPacket(m_pkt.pkt.size); break; } } @@ -692,17 +684,17 @@ DemuxPacket* CDVDDemuxFFmpeg::Read() bReturnEmpty = true; } else - pPacket = CDVDDemuxUtils::AllocateDemuxPacket(pkt.size); + pPacket = CDVDDemuxUtils::AllocateDemuxPacket(m_pkt.pkt.size); if (pPacket) { // lavf sometimes bugs out and gives 0 dts/pts instead of no dts/pts // since this could only happens on initial frame under normal // circomstances, let's assume it is wrong all the time - if(pkt.dts == 0) - pkt.dts = AV_NOPTS_VALUE; - if(pkt.pts == 0) - pkt.pts = AV_NOPTS_VALUE; + if(m_pkt.pkt.dts == 0) + m_pkt.pkt.dts = AV_NOPTS_VALUE; + if(m_pkt.pkt.pts == 0) + m_pkt.pkt.pts = AV_NOPTS_VALUE; if(m_bMatroska && stream->codec && stream->codec->codec_type == AVMEDIA_TYPE_VIDEO) { // matroska can store different timestamps @@ -712,32 +704,32 @@ DemuxPacket* CDVDDemuxFFmpeg::Read() // sets these two timestamps equal all the // time, so we select it here instead if(stream->codec->codec_tag == 0) - pkt.dts = AV_NOPTS_VALUE; + m_pkt.pkt.dts = AV_NOPTS_VALUE; else - pkt.pts = AV_NOPTS_VALUE; + m_pkt.pkt.pts = AV_NOPTS_VALUE; } // we need to get duration slightly different for matroska embedded text subtitels - if(m_bMatroska && stream->codec->codec_id == CODEC_ID_TEXT && pkt.convergence_duration != 0) - pkt.duration = pkt.convergence_duration; + if(m_bMatroska && stream->codec->codec_id == CODEC_ID_TEXT && m_pkt.pkt.convergence_duration != 0) + m_pkt.pkt.duration = m_pkt.pkt.convergence_duration; if(m_bAVI && stream->codec && stream->codec->codec_type == AVMEDIA_TYPE_VIDEO) { // AVI's always have borked pts, specially if m_pFormatContext->flags includes // AVFMT_FLAG_GENPTS so always use dts - pkt.pts = AV_NOPTS_VALUE; + m_pkt.pkt.pts = AV_NOPTS_VALUE; } // copy contents into our own packet - pPacket->iSize = pkt.size; + pPacket->iSize = m_pkt.pkt.size; // maybe we can avoid a memcpy here by detecting where pkt.destruct is pointing too? - if (pkt.data) - memcpy(pPacket->pData, pkt.data, pPacket->iSize); + if (m_pkt.pkt.data) + memcpy(pPacket->pData, m_pkt.pkt.data, pPacket->iSize); - pPacket->pts = ConvertTimestamp(pkt.pts, stream->time_base.den, stream->time_base.num); - pPacket->dts = ConvertTimestamp(pkt.dts, stream->time_base.den, stream->time_base.num); - pPacket->duration = DVD_SEC_TO_TIME((double)pkt.duration * stream->time_base.num / stream->time_base.den); + pPacket->pts = ConvertTimestamp(m_pkt.pkt.pts, stream->time_base.den, stream->time_base.num); + pPacket->dts = ConvertTimestamp(m_pkt.pkt.dts, stream->time_base.den, stream->time_base.num); + pPacket->duration = DVD_SEC_TO_TIME((double)m_pkt.pkt.duration * stream->time_base.num / stream->time_base.den); // used to guess streamlength if (pPacket->dts != DVD_NOPTS_VALUE && (pPacket->dts > m_iCurrentPts || m_iCurrentPts == DVD_NOPTS_VALUE)) @@ -745,10 +737,10 @@ DemuxPacket* CDVDDemuxFFmpeg::Read() // check if stream has passed full duration, needed for live streams - if(pkt.dts != (int64_t)AV_NOPTS_VALUE) + if(m_pkt.pkt.dts != (int64_t)AV_NOPTS_VALUE) { int64_t duration; - duration = pkt.dts; + duration = m_pkt.pkt.dts; if(stream->start_time != (int64_t)AV_NOPTS_VALUE) duration -= stream->start_time; @@ -762,9 +754,12 @@ DemuxPacket* CDVDDemuxFFmpeg::Read() } } - pPacket->iStreamId = pkt.stream_index; // XXX just for now + // store internal id until we know the continuous id presented to player + // the stream might not have been created yet + pPacket->iStreamId = m_pkt.pkt.stream_index; } - m_dllAvCodec.av_free_packet(&pkt); + m_pkt.result = -1; + m_dllAvCodec.av_free_packet(&m_pkt.pkt); } } } // end of lock scope @@ -774,34 +769,43 @@ DemuxPacket* CDVDDemuxFFmpeg::Read() if (!pPacket) return NULL; // check streams, can we make this a bit more simple? - if (pPacket && pPacket->iStreamId >= 0 && pPacket->iStreamId < MAX_STREAMS) + if (pPacket && pPacket->iStreamId >= 0) { - if (!m_streams[pPacket->iStreamId] || - m_streams[pPacket->iStreamId]->pPrivate != m_pFormatContext->streams[pPacket->iStreamId] || - m_streams[pPacket->iStreamId]->codec != m_pFormatContext->streams[pPacket->iStreamId]->codec->codec_id) + CDemuxStream *stream = GetStreamInternal(pPacket->iStreamId); + if (!stream || + stream->pPrivate != m_pFormatContext->streams[pPacket->iStreamId] || + stream->codec != m_pFormatContext->streams[pPacket->iStreamId]->codec->codec_id) { // content has changed, or stream did not yet exist - AddStream(pPacket->iStreamId); + stream = AddStream(pPacket->iStreamId); } // we already check for a valid m_streams[pPacket->iStreamId] above - else if (m_streams[pPacket->iStreamId]->type == STREAM_AUDIO) + else if (stream->type == STREAM_AUDIO) { - if (((CDemuxStreamAudio*)m_streams[pPacket->iStreamId])->iChannels != m_pFormatContext->streams[pPacket->iStreamId]->codec->channels || - ((CDemuxStreamAudio*)m_streams[pPacket->iStreamId])->iSampleRate != m_pFormatContext->streams[pPacket->iStreamId]->codec->sample_rate) + if (((CDemuxStreamAudio*)stream)->iChannels != m_pFormatContext->streams[pPacket->iStreamId]->codec->channels || + ((CDemuxStreamAudio*)stream)->iSampleRate != m_pFormatContext->streams[pPacket->iStreamId]->codec->sample_rate) { // content has changed - AddStream(pPacket->iStreamId); + stream = AddStream(pPacket->iStreamId); } } - else if (m_streams[pPacket->iStreamId]->type == STREAM_VIDEO) + else if (stream->type == STREAM_VIDEO) { - if (((CDemuxStreamVideo*)m_streams[pPacket->iStreamId])->iWidth != m_pFormatContext->streams[pPacket->iStreamId]->codec->width || - ((CDemuxStreamVideo*)m_streams[pPacket->iStreamId])->iHeight != m_pFormatContext->streams[pPacket->iStreamId]->codec->height) + if (((CDemuxStreamVideo*)stream)->iWidth != m_pFormatContext->streams[pPacket->iStreamId]->codec->width || + ((CDemuxStreamVideo*)stream)->iHeight != m_pFormatContext->streams[pPacket->iStreamId]->codec->height) { // content has changed - AddStream(pPacket->iStreamId); + stream = AddStream(pPacket->iStreamId); } } + if (!stream) + { + CLog::Log(LOGERROR, "CDVDDemuxFFmpeg::AddStream - internal error, stream is null"); + CDVDDemuxUtils::FreeDemuxPacket(pPacket); + return NULL; + } + // set continuous stream id for player + pPacket->iStreamId = stream->iId; } return pPacket; } @@ -811,6 +815,9 @@ bool CDVDDemuxFFmpeg::SeekTime(int time, bool backwords, double *startpts) if(time < 0) time = 0; + m_pkt.result = -1; + m_dllAvCodec.av_free_packet(&m_pkt.pkt); + CDVDInputStream::ISeekTime* ist = dynamic_cast<CDVDInputStream::ISeekTime*>(m_pInput); if (ist) { @@ -872,6 +879,9 @@ bool CDVDDemuxFFmpeg::SeekByte(int64_t pos) if(ret >= 0) UpdateCurrentPTS(); + m_pkt.result = -1; + m_dllAvCodec.av_free_packet(&m_pkt.pkt); + return (ret >= 0); } @@ -901,17 +911,32 @@ int CDVDDemuxFFmpeg::GetStreamLength() return (int)(m_pFormatContext->duration / (AV_TIME_BASE / 1000)); } +/** + * @brief Finds stream based on demuxer index + */ CDemuxStream* CDVDDemuxFFmpeg::GetStream(int iStreamId) { - if (iStreamId < 0 || iStreamId >= MAX_STREAMS) return NULL; - return m_streams[iStreamId]; + if(iStreamId >= 0 && (size_t)iStreamId < m_stream_index.size()) + return m_stream_index[iStreamId]->second; + else + return NULL; +} + +/** + * @brief Finds stream based on ffmpeg index + */ +CDemuxStream* CDVDDemuxFFmpeg::GetStreamInternal(int iId) +{ + std::map<int, CDemuxStream*>::iterator it = m_streams.find(iId); + if (it == m_streams.end()) + return NULL; + else + return it->second; } int CDVDDemuxFFmpeg::GetNrOfStreams() { - int i = 0; - while (i < MAX_STREAMS && m_streams[i]) i++; - return i; + return m_stream_index.size(); } static double SelectAspect(AVStream* st, bool* forced) @@ -930,25 +955,72 @@ static double SelectAspect(AVStream* st, bool* forced) return 0.0; } -void CDVDDemuxFFmpeg::AddStream(int iId) +void CDVDDemuxFFmpeg::CreateStreams(unsigned int program) { - if(iId >= MAX_STREAMS) + DisposeStreams(); + + // add the ffmpeg streams to our own stream map + if (m_pFormatContext->nb_programs) { - CLog::Log(LOGWARNING, "%s - streams id %d exeeds maximum supported", __FUNCTION__, iId); - return; + // check if desired program is available + if (program < m_pFormatContext->nb_programs && m_pFormatContext->programs[program]->nb_stream_indexes > 0) + { + m_program = program; + } + else + m_program = UINT_MAX; + + // look for first non empty stream and discard nonselected programs + for (unsigned int i = 0; i < m_pFormatContext->nb_programs; i++) + { + if(m_program == UINT_MAX && m_pFormatContext->programs[i]->nb_stream_indexes > 0) + { + m_program = i; + } + + if(i != m_program) + m_pFormatContext->programs[i]->discard = AVDISCARD_ALL; + } + if(m_program != UINT_MAX) + { + // add streams from selected program + for (unsigned int i = 0; i < m_pFormatContext->programs[m_program]->nb_stream_indexes; i++) + AddStream(m_pFormatContext->programs[m_program]->stream_index[i]); + } + } + else + m_program = UINT_MAX; + + // if there were no programs or they were all empty, add all streams + if (m_program == UINT_MAX) + { + for (unsigned int i = 0; i < m_pFormatContext->nb_streams; i++) + AddStream(i); } +} +void CDVDDemuxFFmpeg::DisposeStreams() +{ + std::map<int, CDemuxStream*>::iterator it; + for(it = m_streams.begin(); it != m_streams.end(); ++it) + delete it->second; + m_streams.clear(); + m_stream_index.clear(); +} + +CDemuxStream* CDVDDemuxFFmpeg::AddStream(int iId) +{ AVStream* pStream = m_pFormatContext->streams[iId]; if (pStream) { - CDemuxStream* old = m_streams[iId]; + CDemuxStream* stream = NULL; switch (pStream->codec->codec_type) { case AVMEDIA_TYPE_AUDIO: { CDemuxStreamAudioFFmpeg* st = new CDemuxStreamAudioFFmpeg(this, pStream); - m_streams[iId] = st; + stream = st; st->iChannels = pStream->codec->channels; st->iSampleRate = pStream->codec->sample_rate; st->iBlockAlign = pStream->codec->block_align; @@ -963,7 +1035,7 @@ void CDVDDemuxFFmpeg::AddStream(int iId) case AVMEDIA_TYPE_VIDEO: { CDemuxStreamVideoFFmpeg* st = new CDemuxStreamVideoFFmpeg(this, pStream); - m_streams[iId] = st; + stream = st; if(strcmp(m_pFormatContext->iformat->name, "flv") == 0) st->bVFR = true; else @@ -990,6 +1062,18 @@ void CDVDDemuxFFmpeg::AddStream(int iId) st->iFpsScale = 0; } + // added for aml hw decoder, mkv frame-rate can be wrong. + if (pStream->r_frame_rate.den && pStream->r_frame_rate.num) + { + st->irFpsRate = pStream->r_frame_rate.num; + st->irFpsScale = pStream->r_frame_rate.den; + } + else + { + st->irFpsRate = 0; + st->irFpsScale = 0; + } + if (pStream->codec_info_nb_frames > 0 && pStream->codec_info_nb_frames <= 2 && m_pInput->IsStreamType(DVDSTREAM_TYPE_DVD)) @@ -1007,7 +1091,7 @@ void CDVDDemuxFFmpeg::AddStream(int iId) AVDictionaryEntry *rtag = m_dllAvUtil.av_dict_get(pStream->metadata, "rotate", NULL, 0); if (rtag) - st->iOrientation = atoi(rtag->value); + st->iOrientation = atoi(rtag->value); if ( m_pInput->IsStreamType(DVDSTREAM_TYPE_DVD) ) { @@ -1027,23 +1111,23 @@ void CDVDDemuxFFmpeg::AddStream(int iId) } case AVMEDIA_TYPE_DATA: { - m_streams[iId] = new CDemuxStream(); - m_streams[iId]->type = STREAM_DATA; + stream = new CDemuxStream(); + stream->type = STREAM_DATA; break; } case AVMEDIA_TYPE_SUBTITLE: { - if (pStream->codec->codec_id == CODEC_ID_DVB_TELETEXT && g_guiSettings.GetBool("videoplayer.teletextenabled")) + if (pStream->codec->codec_id == CODEC_ID_DVB_TELETEXT && CSettings::Get().GetBool("videoplayer.teletextenabled")) { CDemuxStreamTeletext* st = new CDemuxStreamTeletext(); - m_streams[iId] = st; - m_streams[iId]->type = STREAM_TELETEXT; + stream = st; + stream->type = STREAM_TELETEXT; break; } else { CDemuxStreamSubtitleFFmpeg* st = new CDemuxStreamSubtitleFFmpeg(this, pStream); - m_streams[iId] = st; + stream = st; if(m_dllAvUtil.av_dict_get(pStream->metadata, "title", NULL, 0)) st->m_description = m_dllAvUtil.av_dict_get(pStream->metadata, "title", NULL, 0)->value; @@ -1074,87 +1158,113 @@ void CDVDDemuxFFmpeg::AddStream(int iId) file.Close(); } } - m_streams[iId] = new CDemuxStream(); - m_streams[iId]->type = STREAM_NONE; + stream = new CDemuxStream(); + stream->type = STREAM_NONE; break; } default: { - m_streams[iId] = new CDemuxStream(); - m_streams[iId]->type = STREAM_NONE; + stream = new CDemuxStream(); + stream->type = STREAM_NONE; break; } } - // delete old stream after new is created - // since dvdplayer uses the pointer to know - // if something changed in the demuxer - if (old) - { - if( old->ExtraData ) delete[] (BYTE*)(old->ExtraData); - delete old; - } + // set ffmpeg type + stream->orig_type = pStream->codec->codec_type; // generic stuff - if (pStream->duration != (int64_t)AV_NOPTS_VALUE) m_streams[iId]->iDuration = (int)((pStream->duration / AV_TIME_BASE) & 0xFFFFFFFF); + if (pStream->duration != (int64_t)AV_NOPTS_VALUE) + stream->iDuration = (int)((pStream->duration / AV_TIME_BASE) & 0xFFFFFFFF); - m_streams[iId]->codec = pStream->codec->codec_id; - m_streams[iId]->codec_fourcc = pStream->codec->codec_tag; - m_streams[iId]->profile = pStream->codec->profile; - m_streams[iId]->level = pStream->codec->level; + stream->codec = pStream->codec->codec_id; + stream->codec_fourcc = pStream->codec->codec_tag; + stream->profile = pStream->codec->profile; + stream->level = pStream->codec->level; - m_streams[iId]->iId = iId; - m_streams[iId]->source = STREAM_SOURCE_DEMUX; - m_streams[iId]->pPrivate = pStream; - m_streams[iId]->flags = (CDemuxStream::EFlags)pStream->disposition; + stream->source = STREAM_SOURCE_DEMUX; + stream->pPrivate = pStream; + stream->flags = (CDemuxStream::EFlags)pStream->disposition; AVDictionaryEntry *langTag = m_dllAvUtil.av_dict_get(pStream->metadata, "language", NULL, 0); if (langTag) - strncpy(m_streams[iId]->language, langTag->value, 3); + strncpy(stream->language, langTag->value, 3); if( pStream->codec->extradata && pStream->codec->extradata_size > 0 ) { - m_streams[iId]->ExtraSize = pStream->codec->extradata_size; - m_streams[iId]->ExtraData = new BYTE[pStream->codec->extradata_size]; - memcpy(m_streams[iId]->ExtraData, pStream->codec->extradata, pStream->codec->extradata_size); + stream->ExtraSize = pStream->codec->extradata_size; + stream->ExtraData = new BYTE[pStream->codec->extradata_size]; + memcpy(stream->ExtraData, pStream->codec->extradata, pStream->codec->extradata_size); } #ifdef HAVE_LIBBLURAY if( m_pInput->IsStreamType(DVDSTREAM_TYPE_BLURAY) ) - static_cast<CDVDInputStreamBluray*>(m_pInput)->GetStreamInfo(pStream->id, m_streams[iId]->language); + static_cast<CDVDInputStreamBluray*>(m_pInput)->GetStreamInfo(pStream->id, stream->language); #endif if( m_pInput->IsStreamType(DVDSTREAM_TYPE_DVD) ) { // this stuff is really only valid for dvd's. // this is so that the physicalid matches the // id's reported from libdvdnav - switch(m_streams[iId]->codec) + switch(stream->codec) { case CODEC_ID_AC3: - m_streams[iId]->iPhysicalId = pStream->id - 128; + stream->iPhysicalId = pStream->id - 128; break; case CODEC_ID_DTS: - m_streams[iId]->iPhysicalId = pStream->id - 136; + stream->iPhysicalId = pStream->id - 136; break; case CODEC_ID_MP2: - m_streams[iId]->iPhysicalId = pStream->id - 448; + stream->iPhysicalId = pStream->id - 448; break; case CODEC_ID_PCM_S16BE: - m_streams[iId]->iPhysicalId = pStream->id - 160; + stream->iPhysicalId = pStream->id - 160; break; case CODEC_ID_DVD_SUBTITLE: - m_streams[iId]->iPhysicalId = pStream->id - 0x20; + stream->iPhysicalId = pStream->id - 0x20; break; default: - m_streams[iId]->iPhysicalId = pStream->id & 0x1f; + stream->iPhysicalId = pStream->id & 0x1f; break; } } else - m_streams[iId]->iPhysicalId = pStream->id; + stream->iPhysicalId = pStream->id; + + AddStream(iId, stream); + return stream; + } + else + return NULL; +} + +/** + * @brief Adds or updates a demux stream based in ffmpeg id + */ +void CDVDDemuxFFmpeg::AddStream(int iId, CDemuxStream* stream) +{ + std::pair<std::map<int, CDemuxStream*>::iterator, bool> res; + + res = m_streams.insert(std::make_pair(iId, stream)); + if(res.second) + { + /* was new stream */ + stream->iId = m_stream_index.size(); + m_stream_index.push_back(res.first); + } + else + { + /* replace old stream, keeping old index */ + stream->iId = res.first->second->iId; + + delete res.first->second; + res.first->second = stream; } + if(g_advancedSettings.m_logLevel > LOG_LEVEL_NORMAL) + CLog::Log(LOGDEBUG, "CDVDDemuxFFmpeg::AddStream(%d, ...) -> %d", iId, stream->iId); } + std::string CDVDDemuxFFmpeg::GetFileName() { if(m_pInput) @@ -1293,3 +1403,26 @@ void CDVDDemuxFFmpeg::GetStreamCodecName(int iStreamId, CStdString &strName) strName = codec->name; } } + +bool CDVDDemuxFFmpeg::IsProgramChange() +{ + if (m_program == UINT_MAX) + return false; + + if(m_pFormatContext->programs[m_program]->nb_stream_indexes != m_streams.size()) + return true; + + if (m_program >= m_pFormatContext->nb_programs) + return true; + + for (unsigned int i = 0; i < m_pFormatContext->programs[m_program]->nb_stream_indexes; i++) + { + int idx = m_pFormatContext->programs[m_program]->stream_index[i]; + CDemuxStream *stream = GetStreamInternal(idx); + if(!stream) + return true; + if(m_pFormatContext->streams[idx]->codec->codec_type != stream->orig_type) + return true; + } + return false; +} diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h index eb2f68c60a..568dc874fe 100644 --- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h +++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h @@ -28,6 +28,8 @@ #include "threads/CriticalSection.h" #include "threads/SystemClock.h" +#include <map> + class CDVDDemuxFFmpeg; class CDemuxStreamVideoFFmpeg @@ -119,14 +121,19 @@ protected: friend class CDemuxStreamSubtitleFFmpeg; int ReadFrame(AVPacket *packet); - void AddStream(int iId); + CDemuxStream* AddStream(int iId); + void AddStream(int iId, CDemuxStream* stream); + CDemuxStream* GetStreamInternal(int iStreamId); + void CreateStreams(unsigned int program = UINT_MAX); + void DisposeStreams(); double ConvertTimestamp(int64_t pts, int den, int num); void UpdateCurrentPTS(); + bool IsProgramChange(); CCriticalSection m_critSection; - #define MAX_STREAMS 100 - CDemuxStream* m_streams[MAX_STREAMS]; // maximum number of streams that ffmpeg can handle + std::map<int, CDemuxStream*> m_streams; + std::vector<std::map<int, CDemuxStream*>::iterator> m_stream_index; AVIOContext* m_ioContext; @@ -141,5 +148,13 @@ protected: unsigned m_program; XbmcThreads::EndTime m_timeout; + // Due to limitations of ffmpeg, we only can detect a program change + // with a packet. This struct saves the packet for the next read and + // signals STREAMCHANGE to player + struct + { + AVPacket pkt; // packet ffmpeg returned + int result; // result from av_read_packet + }m_pkt; }; diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp index 58bea8d10b..2c10a7be34 100644 --- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp +++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp @@ -136,12 +136,7 @@ void CDVDDemuxPVRClient::Dispose() { for (int i = 0; i < MAX_STREAMS; i++) { - if (m_streams[i]) - { - if (m_streams[i]->ExtraData) - delete[] (BYTE*)(m_streams[i]->ExtraData); - delete m_streams[i]; - } + delete m_streams[i]; m_streams[i] = NULL; } @@ -154,11 +149,6 @@ void CDVDDemuxPVRClient::DisposeStream(int iStreamId) { if (iStreamId < 0 || iStreamId >= MAX_STREAMS) return; - if (m_streams[iStreamId]->ExtraData) - { - delete[] (uint8_t*)m_streams[iStreamId]->ExtraData; - m_streams[iStreamId]->ExtraData = NULL; - } delete m_streams[iStreamId]; m_streams[iStreamId] = NULL; } diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxVobsub.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxVobsub.cpp index 88daeeed0f..dc8053faa0 100644 --- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxVobsub.cpp +++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxVobsub.cpp @@ -28,6 +28,8 @@ #include "DVDClock.h" #include "DVDSubtitles/DVDSubtitleStream.h" +#include <string.h> + using namespace std; CDVDDemuxVobsub::CDVDDemuxVobsub() @@ -38,8 +40,6 @@ CDVDDemuxVobsub::~CDVDDemuxVobsub() { for(unsigned i=0;i<m_Streams.size();i++) { - if(m_Streams[i]->ExtraData) - free(m_Streams[i]->ExtraData); delete m_Streams[i]; } m_Streams.clear(); @@ -112,7 +112,8 @@ bool CDVDDemuxVobsub::Open(const string& filename, const string& subfilename) for(unsigned i=0;i<m_Streams.size();i++) { m_Streams[i]->ExtraSize = state.extra.length()+1; - m_Streams[i]->ExtraData = strdup(state.extra.c_str()); + m_Streams[i]->ExtraData = new uint8_t[m_Streams[i]->ExtraSize]; + strcpy((char*)m_Streams[i]->ExtraData, state.extra.c_str()); } return true; diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp index 19a5c5077b..8e4c86cf1e 100644 --- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp +++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp @@ -31,6 +31,7 @@ #include "DVDDemuxHTSP.h" #endif #include "DVDDemuxBXA.h" +#include "DVDDemuxCDDA.h" #include "DVDDemuxPVRClient.h" #include "pvr/PVRManager.h" #include "pvr/addons/PVRClients.h" @@ -40,6 +41,9 @@ using namespace PVR; CDVDDemux* CDVDFactoryDemuxer::CreateDemuxer(CDVDInputStream* pInputStream) { + if (!pInputStream) + return NULL; + // Try to open the AirTunes demuxer if (pInputStream->IsStreamType(DVDSTREAM_TYPE_FILE) && pInputStream->GetContent().compare("audio/x-xbmc-pcm") == 0 ) { @@ -51,6 +55,22 @@ CDVDDemux* CDVDFactoryDemuxer::CreateDemuxer(CDVDInputStream* pInputStream) else return NULL; } + + // Try to open CDDA demuxer + if (pInputStream->IsStreamType(DVDSTREAM_TYPE_FILE) && pInputStream->GetContent().compare("application/octet-stream") == 0) + { + std::string filename = pInputStream->GetFileName(); + if (filename.substr(0, 7) == "cdda://") + { + CLog::Log(LOGDEBUG, "DVDFactoryDemuxer: Stream is probably CD audio. Creating CDDA demuxer."); + + auto_ptr<CDVDDemuxCDDA> demuxer(new CDVDDemuxCDDA()); + if (demuxer->Open(pInputStream)) + { + return demuxer.release(); + } + } + } if (pInputStream->IsStreamType(DVDSTREAM_TYPE_HTTP)) { diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/Makefile.in b/xbmc/cores/dvdplayer/DVDDemuxers/Makefile.in index b83c63114a..658c451ee2 100644 --- a/xbmc/cores/dvdplayer/DVDDemuxers/Makefile.in +++ b/xbmc/cores/dvdplayer/DVDDemuxers/Makefile.in @@ -2,6 +2,7 @@ INCLUDES+=-I@abs_top_srcdir@/xbmc/cores/dvdplayer SRCS = DVDDemux.cpp SRCS += DVDDemuxBXA.cpp +SRCS += DVDDemuxCDDA.cpp SRCS += DVDDemuxFFmpeg.cpp SRCS += DVDDemuxHTSP.cpp SRCS += DVDDemuxPVRClient.cpp diff --git a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.cpp b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.cpp index 58b29688fd..7352aa10aa 100644 --- a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.cpp +++ b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamBluray.cpp @@ -24,7 +24,7 @@ #include "IDVDPlayer.h" #include "DVDCodecs/Overlay/DVDOverlay.h" #include "DVDCodecs/Overlay/DVDOverlayImage.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "LangInfo.h" #include "utils/log.h" #include "utils/URIUtils.h" @@ -380,7 +380,7 @@ bool CDVDInputStreamBluray::Open(const char* strFile, const std::string& content if(m_navmode) { - int region = g_guiSettings.GetInt("dvds.playerregion"); + int region = CSettings::Get().GetInt("dvds.playerregion"); if(region == 0) { CLog::Log(LOGWARNING, "CDVDInputStreamBluray::Open - region dvd must be set in setting, assuming region 1"); diff --git a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamNavigator.cpp b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamNavigator.cpp index 67daf84767..eba4b0df36 100644 --- a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamNavigator.cpp +++ b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamNavigator.cpp @@ -22,7 +22,7 @@ #include "utils/LangCodeExpander.h" #include "../DVDDemuxSPU.h" #include "DVDStateSerializer.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "LangInfo.h" #include "utils/log.h" #include "guilib/Geometry.h" @@ -104,7 +104,7 @@ bool CDVDInputStreamNavigator::Open(const char* strFile, const std::string& cont return false; } - int region = g_guiSettings.GetInt("dvds.playerregion"); + int region = CSettings::Get().GetInt("dvds.playerregion"); int mask = 0; if(region > 0) mask = 1 << (region-1); @@ -179,7 +179,7 @@ bool CDVDInputStreamNavigator::Open(const char* strFile, const std::string& cont } // jump directly to title menu - if(g_guiSettings.GetBool("dvds.automenu")) + if(CSettings::Get().GetBool("dvds.automenu")) { int len, event; uint8_t buf[2048]; diff --git a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamPVRManager.cpp b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamPVRManager.cpp index 431c280a5e..aa3298b953 100644 --- a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamPVRManager.cpp +++ b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamPVRManager.cpp @@ -28,7 +28,7 @@ #include "utils/StringUtils.h" #include "pvr/addons/PVRClients.h" #include "pvr/channels/PVRChannelGroupsContainer.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" using namespace XFILE; using namespace PVR; @@ -131,7 +131,7 @@ bool CDVDInputStreamPVRManager::Open(const char* strFile, const std::string& con } } - ResetScanTimeout((unsigned int) g_guiSettings.GetInt("pvrplayback.scantime") * 1000); + ResetScanTimeout((unsigned int) CSettings::Get().GetInt("pvrplayback.scantime") * 1000); m_content = content; CLog::Log(LOGDEBUG, "CDVDInputStreamPVRManager::Open - stream opened: %s", transFile.c_str()); diff --git a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamRTMP.cpp b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamRTMP.cpp index fb8164f81f..7d31f71db5 100644 --- a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamRTMP.cpp +++ b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamRTMP.cpp @@ -73,12 +73,15 @@ CDVDInputStreamRTMP::CDVDInputStreamRTMP() : CDVDInputStream(DVDSTREAM_TYPE_RTMP m_libRTMP.LogSetCallback(CDVDInputStreamRTMP_Log); switch (g_advancedSettings.m_logLevel) { - case LOG_LEVEL_DEBUG_SAMBA: level = RTMP_LOGDEBUG2; break; case LOG_LEVEL_DEBUG_FREEMEM: case LOG_LEVEL_DEBUG: level = RTMP_LOGDEBUG; break; case LOG_LEVEL_NORMAL: level = RTMP_LOGINFO; break; default: level = RTMP_LOGCRIT; break; } + + if (g_advancedSettings.m_extraLogLevels & LOGRTMP) + level = RTMP_LOGDEBUG2; + m_libRTMP.LogSetLevel(level); RTMP_level = level; diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp index 95eb8aef56..4ab4057e6b 100644 --- a/xbmc/cores/dvdplayer/DVDPlayer.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp @@ -63,10 +63,9 @@ #endif #include "settings/AdvancedSettings.h" #include "FileItem.h" -#include "settings/GUISettings.h" -#include "settings/MediaSettings.h" #include "GUIUserMessages.h" #include "settings/Settings.h" +#include "settings/MediaSettings.h" #include "utils/log.h" #include "utils/TimeUtils.h" #include "utils/StreamDetails.h" @@ -142,7 +141,7 @@ static bool PredicateAudioPriority(const SelectionStream& lh, const SelectionStr PREDICATE_RETURN(lh.type_index == CMediaSettings::Get().GetCurrentVideoSettings().m_AudioStream , rh.type_index == CMediaSettings::Get().GetCurrentVideoSettings().m_AudioStream); - if(!g_guiSettings.GetString("locale.audiolanguage").Equals("original")) + if(!StringUtils::EqualsNoCase(CSettings::Get().GetString("locale.audiolanguage"), "original")) { CStdString audio_language = g_langInfo.GetAudioLanguage(); PREDICATE_RETURN(audio_language.Equals(lh.language.c_str()) @@ -172,7 +171,7 @@ static bool PredicateSubtitlePriority(const SelectionStream& lh, const Selection , rh.type_index == CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleStream); CStdString subtitle_language = g_langInfo.GetSubtitleLanguage(); - if(!g_guiSettings.GetString("locale.subtitlelanguage").Equals("original")) + if(!StringUtils::EqualsNoCase(CSettings::Get().GetString("locale.subtitlelanguage"), "original")) { PREDICATE_RETURN((lh.source == STREAM_SOURCE_DEMUX_SUB || lh.source == STREAM_SOURCE_TEXT) && subtitle_language.Equals(lh.language.c_str()) , (rh.source == STREAM_SOURCE_DEMUX_SUB || rh.source == STREAM_SOURCE_TEXT) && subtitle_language.Equals(rh.language.c_str())); @@ -184,7 +183,7 @@ static bool PredicateSubtitlePriority(const SelectionStream& lh, const Selection PREDICATE_RETURN(lh.source == STREAM_SOURCE_TEXT , rh.source == STREAM_SOURCE_TEXT); - if(!g_guiSettings.GetString("locale.subtitlelanguage").Equals("original")) + if(!StringUtils::EqualsNoCase(CSettings::Get().GetString("locale.subtitlelanguage"), "original")) { PREDICATE_RETURN(subtitle_language.Equals(lh.language.c_str()) , subtitle_language.Equals(rh.language.c_str())); @@ -583,7 +582,7 @@ bool CDVDPlayer::OpenInputStream() if (filename.Left(7) == "http://" && CURL(filename).GetFileName().Right(5) == ".m3u8") { // get the available bandwidth (as per user settings) - int maxrate = g_guiSettings.GetInt("network.bandwidth"); + int maxrate = CSettings::Get().GetInt("network.bandwidth"); if(maxrate <= 0) maxrate = INT_MAX; @@ -1190,10 +1189,6 @@ void CDVDPlayer::Process() m_CurrentVideo.inited = false; m_CurrentSubtitle.inited = false; m_CurrentTeletext.inited = false; - m_CurrentAudio.started = false; - m_CurrentVideo.started = false; - m_CurrentSubtitle.started = false; - m_CurrentTeletext.started = false; // if we are caching, start playing it again SetCaching(CACHESTATE_DONE); @@ -1209,6 +1204,11 @@ void CDVDPlayer::Process() if (!m_pInputStream->IsEOF()) CLog::Log(LOGINFO, "%s - eof reading from demuxer", __FUNCTION__); + m_CurrentAudio.started = false; + m_CurrentVideo.started = false; + m_CurrentSubtitle.started = false; + m_CurrentTeletext.started = false; + break; } @@ -2068,7 +2068,10 @@ void CDVDPlayer::HandleMessages() CLog::Log(LOGDEBUG, "failed to seek subtitle demuxer: %d, success", time); } // dts after successful seek - m_StateInput.dts = start; + if (m_StateInput.time_src == ETIMESOURCE_CLOCK && start == DVD_NOPTS_VALUE) + m_StateInput.dts = DVD_MSEC_TO_TIME(time); + else + m_StateInput.dts = start; FlushBuffers(!msg.GetFlush(), start, msg.GetAccurate()); } @@ -2273,7 +2276,7 @@ void CDVDPlayer::HandleMessages() if(input) { bool bSwitchSuccessful(false); - bool bShowPreview(g_guiSettings.GetInt("pvrplayback.channelentrytimeout") > 0); + bool bShowPreview(CSettings::Get().GetInt("pvrplayback.channelentrytimeout") > 0); if (!bShowPreview) { @@ -2291,7 +2294,7 @@ void CDVDPlayer::HandleMessages() if (bShowPreview) { UpdateApplication(0); - m_iChannelEntryTimeOut = XbmcThreads::SystemClockMillis() + g_guiSettings.GetInt("pvrplayback.channelentrytimeout"); + m_iChannelEntryTimeOut = XbmcThreads::SystemClockMillis() + CSettings::Get().GetInt("pvrplayback.channelentrytimeout"); } else { @@ -2374,7 +2377,7 @@ void CDVDPlayer::SetCaching(ECacheState state) m_dvdPlayerVideo.SendMessage(new CDVDMsg(CDVDMsg::PLAYER_STARTED), 1); if (state == CACHESTATE_PVR) - m_pInputStream->ResetScanTimeout((unsigned int) g_guiSettings.GetInt("pvrplayback.scantime") * 1000); + m_pInputStream->ResetScanTimeout((unsigned int) CSettings::Get().GetInt("pvrplayback.scantime") * 1000); } if(state == CACHESTATE_PLAY @@ -3450,9 +3453,9 @@ bool CDVDPlayer::ShowPVRChannelInfo(void) { bool bReturn(false); - if (g_guiSettings.GetBool("pvrmenu.infoswitch")) + if (CSettings::Get().GetBool("pvrmenu.infoswitch")) { - int iTimeout = g_guiSettings.GetBool("pvrmenu.infotimeout") ? g_guiSettings.GetInt("pvrmenu.infotime") : 0; + int iTimeout = CSettings::Get().GetBool("pvrmenu.infotimeout") ? CSettings::Get().GetInt("pvrmenu.infotime") : 0; g_PVRManager.ShowPlayerInfo(iTimeout); bReturn = true; diff --git a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp index 3c55b52bd3..e2ea458495 100644 --- a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp @@ -25,7 +25,7 @@ #include "DVDCodecs/DVDCodecs.h" #include "DVDCodecs/DVDFactoryCodec.h" #include "DVDPerformanceCounter.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "video/VideoReferenceClock.h" #include "utils/log.h" #include "utils/TimeUtils.h" @@ -145,7 +145,7 @@ CDVDPlayerAudio::~CDVDPlayerAudio() bool CDVDPlayerAudio::OpenStream( CDVDStreamInfo &hints ) { - bool passthrough = AUDIO_IS_BITSTREAM(g_guiSettings.GetInt("audiooutput.mode")); + bool passthrough = AUDIO_IS_BITSTREAM(CSettings::Get().GetInt("audiooutput.mode")); CLog::Log(LOGNOTICE, "Finding audio codec for: %i", hints.codec); CDVDAudioCodec* codec = CDVDFactoryCodec::CreateAudioCodec(hints, passthrough); @@ -191,8 +191,8 @@ void CDVDPlayerAudio::OpenStream( CDVDStreamInfo &hints, CDVDAudioCodec* codec ) m_synctype = SYNC_DISCON; m_setsynctype = SYNC_DISCON; - if (g_guiSettings.GetBool("videoplayer.usedisplayasclock")) - m_setsynctype = g_guiSettings.GetInt("videoplayer.synctype"); + if (CSettings::Get().GetBool("videoplayer.usedisplayasclock")) + m_setsynctype = CSettings::Get().GetInt("videoplayer.synctype"); m_prevsynctype = -1; m_error = 0; @@ -205,7 +205,7 @@ void CDVDPlayerAudio::OpenStream( CDVDStreamInfo &hints, CDVDAudioCodec* codec ) m_errortime = CurrentHostCounter(); m_silence = false; - m_maxspeedadjust = g_guiSettings.GetFloat("videoplayer.maxspeedadjust"); + m_maxspeedadjust = CSettings::Get().GetNumber("videoplayer.maxspeedadjust"); } void CDVDPlayerAudio::CloseStream(bool bWaitForBuffers) @@ -840,7 +840,7 @@ void CDVDPlayerAudio::WaitForBuffers() bool CDVDPlayerAudio::SwitchCodecIfNeeded() { // check if passthrough is disabled - if (!AUDIO_IS_BITSTREAM(g_guiSettings.GetInt("audiooutput.mode"))) + if (!AUDIO_IS_BITSTREAM(CSettings::Get().GetInt("audiooutput.mode"))) return false; CLog::Log(LOGDEBUG, "CDVDPlayerAudio: Sample rate changed, checking for passthrough"); diff --git a/xbmc/cores/dvdplayer/DVDPlayerAudioResampler.cpp b/xbmc/cores/dvdplayer/DVDPlayerAudioResampler.cpp deleted file mode 100644 index cfb1332c5e..0000000000 --- a/xbmc/cores/dvdplayer/DVDPlayerAudioResampler.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (C) 2005-2013 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 "DVDPlayerAudioResampler.h" -#include "DVDPlayerAudio.h" -#include "utils/log.h" -#include "utils/MathUtils.h" - -#ifdef _WIN32 -#pragma comment(lib, "libsamplerate-0.lib") -#endif - -CDVDPlayerResampler::CDVDPlayerResampler() -{ - m_nrchannels = -1; - m_converter = NULL; - - memset(&m_converterdata, 0, sizeof(m_converterdata)); - m_converterdata.src_ratio = 1.0; - - m_quality = SRC_LINEAR; - m_ratio = 1.0; - - m_buffer = NULL; - m_ptsbuffer = NULL; - m_buffersize = 0; - m_bufferfill = 0; -} - -CDVDPlayerResampler::~CDVDPlayerResampler() -{ - Clean(); -} - -void CDVDPlayerResampler::Add(DVDAudioFrame &audioframe, double pts) -{ - //check if nr of channels changed so we can allocate new buffers if necessary - CheckResampleBuffers(audioframe.channel_count); - - //value to divide samples by to get them into -1.0:1.0 range - float scale = (float)(1 << (audioframe.bits_per_sample - 1)); - int nrframes = audioframe.size / audioframe.channel_count / (audioframe.bits_per_sample / 8); - - //resize sample buffer if necessary - //we want the buffer to be large enough to hold the current frames in it, - //the number of frames needed for libsamplerate's input - //and the maximum number of frames libsamplerate might generate, times 2 for safety - ResizeSampleBuffer(m_bufferfill + nrframes + nrframes * MathUtils::round_int(m_ratio + 0.5) * 2); - - //assign samplebuffers - m_converterdata.input_frames = nrframes; - m_converterdata.output_frames = m_buffersize - m_bufferfill - m_converterdata.input_frames; - //output buffer starts at the place where the buffer doesn't hold samples - m_converterdata.data_out = m_buffer + m_bufferfill * m_nrchannels; - //intput buffer is a block of data at the end of the buffer - m_converterdata.data_in = m_converterdata.data_out + m_converterdata.output_frames * m_nrchannels; - - //add samples to the resample input buffer - int16_t* inputptr = (int16_t*)audioframe.data; - float* outputptr = m_converterdata.data_in; - - for (int i = 0; i < nrframes * m_nrchannels; i++) - *outputptr++ = (float)*inputptr++ / scale; - - //resample - m_converterdata.src_ratio = m_ratio; - src_set_ratio(m_converter, m_ratio); - src_process(m_converter, &m_converterdata); - - //calculate a pts for each sample - for (int i = 0; i < m_converterdata.output_frames_gen; i++) - { - m_ptsbuffer[m_bufferfill] = pts + i * (audioframe.duration / (double)m_converterdata.output_frames_gen); - m_bufferfill++; - } -} - -bool CDVDPlayerResampler::Retrieve(DVDAudioFrame &audioframe, double &pts) -{ - //check if nr of channels changed so we can allocate new buffers if necessary - CheckResampleBuffers(audioframe.channel_count); - - //value to divide samples by to get them into -1.0:1.0 range - float scale = (float)(1 << (audioframe.bits_per_sample - 1)); - int nrframes = audioframe.size / audioframe.channel_count / (audioframe.bits_per_sample / 8); - - //if we don't have enough in the samplebuffer, return false - if (nrframes > m_bufferfill) - { - return false; - } - - //use the pts of the first fresh value in the samplebuffer - pts = m_ptsbuffer[0]; - - //add from samplebuffer to audioframe - float* inputptr = m_buffer; - int16_t* outputptr = (int16_t*)audioframe.data; - - for (int i = 0; i < nrframes * m_nrchannels; i++) - *outputptr++ = MathUtils::round_int(Clamp(*inputptr++ * scale, scale * -1.0f, scale - 1.0f)); - - m_bufferfill -= nrframes; - - //shift old data to the beginning of the buffer - memmove(m_buffer, m_buffer + (nrframes * m_nrchannels), m_bufferfill * m_nrchannels * sizeof(float)); - memmove(m_ptsbuffer, m_ptsbuffer + nrframes, m_bufferfill * sizeof(double)); - - return true; -} - -void CDVDPlayerResampler::CheckResampleBuffers(int channels) -{ - int error; - if (channels != m_nrchannels) - { - Clean(); - - m_nrchannels = channels; - m_converter = src_new(m_quality, m_nrchannels, &error); - } -} - -void CDVDPlayerResampler::ResizeSampleBuffer(int nrframes) -{ - if (m_buffersize < nrframes) - { - int newBufferSize = nrframes * 2; - float* newBuffer = (float*)realloc(m_buffer, newBufferSize * m_nrchannels * sizeof(float)); - if (newBuffer) - { - m_buffer = newBuffer; - m_buffersize = newBufferSize; - - double* newPtsBuffer = (double*)realloc(m_ptsbuffer, m_buffersize * sizeof(double)); - if (newPtsBuffer) - { - m_ptsbuffer = newPtsBuffer; - CLog::Log(LOGDEBUG, "CDVDPlayerResampler: resized buffers to hold %i frames", m_buffersize); - } - else - { - CLog::Log(LOGERROR, "ResizeSampleBuffer - %s - failed : could not realloc the buffer m_ptsbuffer", __FUNCTION__); - } - } - else - { - CLog::Log(LOGERROR, "ResizeSampleBuffer - %s - failed : could not realloc the buffer m_buffer", __FUNCTION__); - } - } -} - -void CDVDPlayerResampler::SetRatio(double ratio) -{ - m_ratio = Clamp(ratio, 1.0 / (double)MAXRATIO, (double)MAXRATIO); -} - -void CDVDPlayerResampler::Flush() -{ - m_bufferfill = 0; -} - -void CDVDPlayerResampler::SetQuality(int quality) -{ - int qualitylookup[] = {SRC_LINEAR, SRC_SINC_FASTEST, SRC_SINC_MEDIUM_QUALITY, SRC_SINC_BEST_QUALITY}; - m_quality = qualitylookup[Clamp(quality, 0, 3)]; - Clean(); -} - -void CDVDPlayerResampler::Clean() -{ - if (m_converter) src_delete(m_converter); - m_converter = NULL; - - free(m_buffer); - m_buffer = NULL; - free(m_ptsbuffer); - m_ptsbuffer = NULL; - - m_bufferfill = 0; - m_buffersize = 0; - - m_nrchannels = -1; - m_converterdata.end_of_input = 0; - m_converterdata.src_ratio = 1.0; - m_ratio = 1.0; -} diff --git a/xbmc/cores/dvdplayer/DVDPlayerAudioResampler.h b/xbmc/cores/dvdplayer/DVDPlayerAudioResampler.h deleted file mode 100644 index a81f19086a..0000000000 --- a/xbmc/cores/dvdplayer/DVDPlayerAudioResampler.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2005-2013 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/>. - * - */ -#pragma once - -#include <samplerate.h> - -#define MAXRATIO 30 - -#define PROPORTIONAL 20.0 -#define PROPREF 0.01 -#define PROPDIVMIN 2.0 -#define PROPDIVMAX 40.0 -#define INTEGRAL 200.0 - -//forward declaration of struct stDVDAudioFrame -typedef struct stDVDAudioFrame DVDAudioFrame; - -class CDVDPlayerResampler -{ - public: - CDVDPlayerResampler(); - ~CDVDPlayerResampler(); - - void Add(DVDAudioFrame &audioframe, double pts); //add audioframes and resample - bool Retrieve(DVDAudioFrame &audioframe, double &pts); //get audioframes fromt the samplebuffer - void SetRatio(double ratio); //ratio higher than 1.0 means more output samples than input - void Flush(); //clear samplebuffer - void SetQuality(int quality); - void Clean(); //free buffers - - private: - - int m_nrchannels; - int m_quality; - SRC_STATE* m_converter; - SRC_DATA m_converterdata; - double m_ratio; - - float* m_buffer; //buffer for the audioframes - int m_bufferfill; //how many unread frames there are in the buffer - int m_buffersize; //size of allocated buffer in frames - double* m_ptsbuffer; //ringbuffer for the pts value, each frame gets its own pts - - void CheckResampleBuffers(int channels); - void ResizeSampleBuffer(int nrframes); - - //this makes sure value is bewteen min and max - template <typename A, typename B, typename C> - inline A Clamp(A value, B min, C max){ return value < max ? (value > min ? value : min) : max; } -}; diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp index 5585de2aa2..fddfffd520 100644 --- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp @@ -22,7 +22,6 @@ #include "cores/VideoRenderers/RenderFlags.h" #include "windowing/WindowingFactory.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" #include "settings/MediaSettings.h" #include "settings/Settings.h" #include "video/VideoReferenceClock.h" @@ -44,6 +43,7 @@ #include <iomanip> #include <numeric> #include <iterator> +#include "guilib/GraphicContext.h" #include "utils/log.h" using namespace std; @@ -204,7 +204,7 @@ bool CDVDPlayerVideo::OpenStream( CDVDStreamInfo &hint ) return false; } - if(g_guiSettings.GetBool("videoplayer.usedisplayasclock") && !g_VideoReferenceClock.IsRunning()) + if(CSettings::Get().GetBool("videoplayer.usedisplayasclock") && !g_VideoReferenceClock.IsRunning()) { g_VideoReferenceClock.Create(); //we have to wait for the clock to start otherwise alsa can cause trouble @@ -234,8 +234,8 @@ void CDVDPlayerVideo::OpenStream(CDVDStreamInfo &hint, CDVDVideoCodec* codec) m_bFpsInvalid = (hint.fpsrate == 0 || hint.fpsscale == 0); - m_bCalcFrameRate = g_guiSettings.GetBool("videoplayer.usedisplayasclock") || - g_guiSettings.GetInt("videoplayer.adjustrefreshrate") != ADJUST_REFRESHRATE_OFF; + m_bCalcFrameRate = CSettings::Get().GetBool("videoplayer.usedisplayasclock") || + CSettings::Get().GetInt("videoplayer.adjustrefreshrate") != ADJUST_REFRESHRATE_OFF; ResetFrameRateCalc(); m_iDroppedRequest = 0; @@ -1188,8 +1188,11 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) limited = true; //correct any pattern in the timestamps - m_pullupCorrection.Add(pts); - pts += m_pullupCorrection.GetCorrection(); + if (m_output.color_format != RENDER_FMT_BYPASS) + { + m_pullupCorrection.Add(pts); + pts += m_pullupCorrection.GetCorrection(); + } //try to calculate the framerate CalcFrameRate(); @@ -1203,8 +1206,11 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts) pts -= DVD_TIME_BASE * interval; } - // Correct pts by user set delay and rendering delay - pts += m_iVideoDelay - DVD_SEC_TO_TIME(g_renderManager.GetDisplayLatency()); + if (m_output.color_format != RENDER_FMT_BYPASS) + { + // Correct pts by user set delay and rendering delay + pts += m_iVideoDelay - DVD_SEC_TO_TIME(g_renderManager.GetDisplayLatency()); + } // calculate the time we need to delay this picture before displaying double iSleepTime, iClockSleep, iFrameSleep, iPlayingClock, iCurrentClock, iFrameDuration; diff --git a/xbmc/cores/dvdplayer/DVDStreamInfo.cpp b/xbmc/cores/dvdplayer/DVDStreamInfo.cpp index 2619ab5ed0..8947481267 100644 --- a/xbmc/cores/dvdplayer/DVDStreamInfo.cpp +++ b/xbmc/cores/dvdplayer/DVDStreamInfo.cpp @@ -50,6 +50,8 @@ void CDVDStreamInfo::Clear() fpsscale = 0; fpsrate = 0; + rfpsscale= 0; + rfpsrate = 0; height = 0; width = 0; aspect = 0.0; @@ -60,6 +62,7 @@ void CDVDStreamInfo::Clear() ptsinvalid = false; forced_aspect = false; bitsperpixel = 0; + pid = 0; channels = 0; samplerate = 0; @@ -89,6 +92,8 @@ bool CDVDStreamInfo::Equal(const CDVDStreamInfo& right, bool withextradata) // VIDEO if( fpsscale != right.fpsscale || fpsrate != right.fpsrate + || rfpsscale!= right.rfpsscale + || rfpsrate != right.rfpsrate || height != right.height || width != right.width || stills != right.stills @@ -97,6 +102,7 @@ bool CDVDStreamInfo::Equal(const CDVDStreamInfo& right, bool withextradata) || ptsinvalid != right.ptsinvalid || forced_aspect != right.forced_aspect || bitsperpixel != right.bitsperpixel + || pid != right.pid || vfr != right.vfr) return false; // AUDIO @@ -143,6 +149,8 @@ void CDVDStreamInfo::Assign(const CDVDStreamInfo& right, bool withextradata) // VIDEO fpsscale = right.fpsscale; fpsrate = right.fpsrate; + rfpsscale= right.rfpsscale; + rfpsrate = right.rfpsrate; height = right.height; width = right.width; aspect = right.aspect; @@ -153,6 +161,7 @@ void CDVDStreamInfo::Assign(const CDVDStreamInfo& right, bool withextradata) forced_aspect = right.forced_aspect; orientation = right.orientation; bitsperpixel = right.bitsperpixel; + pid = right.pid; vfr = right.vfr; software = right.software; @@ -197,6 +206,8 @@ void CDVDStreamInfo::Assign(const CDemuxStream& right, bool withextradata) const CDemuxStreamVideo *stream = static_cast<const CDemuxStreamVideo*>(&right); fpsscale = stream->iFpsScale; fpsrate = stream->iFpsRate; + rfpsscale = stream->irFpsScale; + rfpsrate = stream->irFpsRate; height = stream->iHeight; width = stream->iWidth; aspect = stream->fAspect; @@ -205,6 +216,7 @@ void CDVDStreamInfo::Assign(const CDemuxStream& right, bool withextradata) forced_aspect = stream->bForcedAspect; orientation = stream->iOrientation; bitsperpixel = stream->iBitsPerPixel; + pid = stream->iPhysicalId; } else if( right.type == STREAM_SUBTITLE ) { diff --git a/xbmc/cores/dvdplayer/DVDStreamInfo.h b/xbmc/cores/dvdplayer/DVDStreamInfo.h index 80669b12a4..f27d6cb39d 100644 --- a/xbmc/cores/dvdplayer/DVDStreamInfo.h +++ b/xbmc/cores/dvdplayer/DVDStreamInfo.h @@ -63,6 +63,8 @@ public: // VIDEO int fpsscale; // scale of 1000 and a rate of 29970 will result in 29.97 fps int fpsrate; + int rfpsscale; + int rfpsrate; int height; // height of the stream reported by the demuxer int width; // width of the stream reported by the demuxer float aspect; // display aspect as reported by demuxer @@ -74,6 +76,7 @@ public: bool forced_aspect; // aspect is forced from container int orientation; // orientation of the video in degress counter clockwise int bitsperpixel; + int pid; // AUDIO int channels; diff --git a/xbmc/cores/dvdplayer/DVDSubtitles/DVDSubtitlesLibass.cpp b/xbmc/cores/dvdplayer/DVDSubtitles/DVDSubtitlesLibass.cpp index 357593ee3b..0da385c8d7 100644 --- a/xbmc/cores/dvdplayer/DVDSubtitles/DVDSubtitlesLibass.cpp +++ b/xbmc/cores/dvdplayer/DVDSubtitles/DVDSubtitlesLibass.cpp @@ -21,7 +21,7 @@ #include "DVDSubtitlesLibass.h" #include "DVDClock.h" #include "filesystem/SpecialProtocol.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "utils/log.h" #include "threads/SingleLock.h" #include "threads/Atomics.h" @@ -77,8 +77,8 @@ CDVDSubtitlesLibass::CDVDSubtitlesLibass() //Setting default font to the Arial in \media\fonts (used if FontConfig fails) strPath = "special://xbmc/media/Fonts/"; - strPath += g_guiSettings.GetString("subtitles.font"); - int fc = !g_guiSettings.GetBool("subtitles.overrideassfonts"); + strPath += CSettings::Get().GetString("subtitles.font"); + int fc = !CSettings::Get().GetBool("subtitles.overrideassfonts"); m_dll.ass_set_margins(m_renderer, 0, 0, 0, 0); m_dll.ass_set_use_margins(m_renderer, 0); diff --git a/xbmc/cores/dvdplayer/Makefile.in b/xbmc/cores/dvdplayer/Makefile.in index a977ec5c17..6572157a64 100644 --- a/xbmc/cores/dvdplayer/Makefile.in +++ b/xbmc/cores/dvdplayer/Makefile.in @@ -12,7 +12,6 @@ SRCS += DVDOverlayRenderer.cpp SRCS += DVDPerformanceCounter.cpp SRCS += DVDPlayer.cpp SRCS += DVDPlayerAudio.cpp -SRCS += DVDPlayerAudioResampler.cpp SRCS += DVDPlayerSubtitle.cpp SRCS += DVDPlayerTeletext.cpp SRCS += DVDPlayerVideo.cpp diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp index 273d0b2bb6..3395372e65 100644 --- a/xbmc/cores/omxplayer/OMXAudio.cpp +++ b/xbmc/cores/omxplayer/OMXAudio.cpp @@ -33,7 +33,8 @@ #include "linux/XMemUtils.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" +#include "settings/MediaSettings.h" +#include "settings/Settings.h" #include "guilib/LocalizeStrings.h" #include "cores/AudioEngine/Utils/AEConvert.h" @@ -710,7 +711,7 @@ bool COMXAudio::SetCurrentVolume(float fVolume) const float* coeff = downmixing_coefficients_8; // normally we normalalise the levels, can be skipped (boosted) at risk of distortion - if(!g_guiSettings.GetBool("audiooutput.normalizelevels")) + if(!CSettings::Get().GetBool("audiooutput.normalizelevels")) { double sum_L = 0; double sum_R = 0; diff --git a/xbmc/cores/omxplayer/OMXImage.cpp b/xbmc/cores/omxplayer/OMXImage.cpp index 7ab856d3de..674e0fc112 100644 --- a/xbmc/cores/omxplayer/OMXImage.cpp +++ b/xbmc/cores/omxplayer/OMXImage.cpp @@ -34,9 +34,9 @@ #include <sys/time.h> #include <inttypes.h> #include "guilib/GraphicContext.h" -#include "settings/DisplaySettings.h" -#include "settings/GUISettings.h" #include "settings/AdvancedSettings.h" +#include "settings/DisplaySettings.h" +#include "settings/Settings.h" #ifdef CLASSNAME #undef CLASSNAME diff --git a/xbmc/cores/omxplayer/OMXPlayer.cpp b/xbmc/cores/omxplayer/OMXPlayer.cpp index 313833ef80..156a3ad78a 100644 --- a/xbmc/cores/omxplayer/OMXPlayer.cpp +++ b/xbmc/cores/omxplayer/OMXPlayer.cpp @@ -39,7 +39,7 @@ #include "guilib/GUIWindowManager.h" #include "settings/AdvancedSettings.h" #include "settings/MediaSettings.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "threads/SingleLock.h" #include "windowing/WindowingFactory.h" @@ -142,7 +142,7 @@ static bool PredicateAudioPriority(const OMXSelectionStream& lh, const OMXSelect PREDICATE_RETURN(lh.type_index == CMediaSettings::Get().GetCurrentVideoSettings().m_AudioStream , rh.type_index == CMediaSettings::Get().GetCurrentVideoSettings().m_AudioStream); - if(!g_guiSettings.GetString("locale.audiolanguage").Equals("original")) + if(!StringUtils::EqualsNoCase(CSettings::Get().GetString("locale.audiolanguage"), "original")) { CStdString audio_language = g_langInfo.GetAudioLanguage(); PREDICATE_RETURN(audio_language.Equals(lh.language.c_str()) @@ -172,7 +172,7 @@ static bool PredicateSubtitlePriority(const OMXSelectionStream& lh, const OMXSel , rh.type_index == CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleStream); CStdString subtitle_language = g_langInfo.GetSubtitleLanguage(); - if(!g_guiSettings.GetString("locale.subtitlelanguage").Equals("original")) + if(!StringUtils::EqualsNoCase(CSettings::Get().GetString("locale.subtitlelanguage"), "original")) { PREDICATE_RETURN((lh.source == STREAM_SOURCE_DEMUX_SUB || lh.source == STREAM_SOURCE_TEXT) && subtitle_language.Equals(lh.language.c_str()) , (rh.source == STREAM_SOURCE_DEMUX_SUB || rh.source == STREAM_SOURCE_TEXT) && subtitle_language.Equals(rh.language.c_str())); @@ -184,7 +184,7 @@ static bool PredicateSubtitlePriority(const OMXSelectionStream& lh, const OMXSel PREDICATE_RETURN(lh.source == STREAM_SOURCE_TEXT , rh.source == STREAM_SOURCE_TEXT); - if(!g_guiSettings.GetString("locale.subtitlelanguage").Equals("original")) + if(!StringUtils::EqualsNoCase(CSettings::Get().GetString("locale.subtitlelanguage"), "original")) { PREDICATE_RETURN(subtitle_language.Equals(lh.language.c_str()) , subtitle_language.Equals(rh.language.c_str())); @@ -457,7 +457,7 @@ bool COMXPlayer::OpenFile(const CFileItem &file, const CPlayerOptions &options) { return false; } - if(g_guiSettings.GetBool("videoplayer.adjustrefreshrate")) + if(CSettings::Get().GetBool("videoplayer.adjustrefreshrate")) m_av_clock.HDMIClockSync(); m_playSpeed = DVD_PLAYSPEED_NORMAL; @@ -584,7 +584,7 @@ bool COMXPlayer::OpenInputStream() if (filename.Left(7) == "http://" && filename.Right(5) == ".m3u8") { // get the available bandwidth (as per user settings) - int maxrate = g_guiSettings.GetInt("network.bandwidth"); + int maxrate = CSettings::Get().GetInt("network.bandwidth"); if(maxrate <= 0) maxrate = INT_MAX; @@ -1302,7 +1302,7 @@ void COMXPlayer::Process() if (IsBetterStream(m_CurrentSubtitle, pStream)) OpenSubtitleStream(pStream->iId, pStream->source); if (IsBetterStream(m_CurrentTeletext, pStream)) OpenTeletextStream(pStream->iId, pStream->source); - if(m_change_volume) + if(m_change_volume && m_CurrentAudio.started) { m_player_audio.SetCurrentVolume(m_current_mute ? VOLUME_MINIMUM : m_current_volume); m_change_volume = false; @@ -2149,9 +2149,15 @@ void COMXPlayer::HandleMessages() CLog::Log(LOGDEBUG, "failed to seek subtitle demuxer: %d, success", time); } // dts after successful seek - m_StateInput.dts = start; + if (m_StateInput.time_src == ETIMESOURCE_CLOCK && start == DVD_NOPTS_VALUE) + m_StateInput.dts = DVD_MSEC_TO_TIME(time); + else + m_StateInput.dts = start; FlushBuffers(!msg.GetFlush(), start, msg.GetAccurate()); + // let clock know the new time so progress bar updates immediately + if(m_StateInput.dts != DVD_NOPTS_VALUE) + m_av_clock.OMXMediaTime(m_StateInput.dts); } else CLog::Log(LOGWARNING, "error while seeking"); @@ -2177,6 +2183,10 @@ void COMXPlayer::HandleMessages() if(m_pDemuxer && m_pDemuxer->SeekChapter(msg.GetChapter(), &start)) { FlushBuffers(false, start, true); + // let clock know the new time so progress bar updates immediately + if(start != DVD_NOPTS_VALUE) + m_av_clock.OMXMediaTime(start); + m_callback.OnPlayBackSeekChapter(msg.GetChapter()); } @@ -2357,7 +2367,7 @@ void COMXPlayer::HandleMessages() if(input) { bool bSwitchSuccessful(false); - bool bShowPreview(g_guiSettings.GetInt("pvrplayback.channelentrytimeout") > 0); + bool bShowPreview(CSettings::Get().GetInt("pvrplayback.channelentrytimeout") > 0); if (!bShowPreview) { @@ -2375,7 +2385,7 @@ void COMXPlayer::HandleMessages() if (bShowPreview) { UpdateApplication(0); - m_iChannelEntryTimeOut = XbmcThreads::SystemClockMillis() + g_guiSettings.GetInt("pvrplayback.channelentrytimeout"); + m_iChannelEntryTimeOut = XbmcThreads::SystemClockMillis() + CSettings::Get().GetInt("pvrplayback.channelentrytimeout"); } else { @@ -2459,7 +2469,7 @@ void COMXPlayer::SetCaching(ECacheState state) m_player_video.SendMessage(new CDVDMsg(CDVDMsg::PLAYER_STARTED), 1); if (state == CACHESTATE_PVR) - m_pInputStream->ResetScanTimeout((unsigned int) g_guiSettings.GetInt("pvrplayback.scantime") * 1000); + m_pInputStream->ResetScanTimeout((unsigned int) CSettings::Get().GetInt("pvrplayback.scantime") * 1000); } if(state == CACHESTATE_PLAY @@ -3347,9 +3357,6 @@ void COMXPlayer::FlushBuffers(bool queued, double pts, bool accurate) CSingleLock lock(m_StateSection); m_State = m_StateInput; } - // let clock know the new time so progress bar updates immediately - if(startpts != DVD_NOPTS_VALUE) - m_av_clock.OMXMediaTime(startpts); } // since we call ffmpeg functions to decode, this is being called in the same thread as ::Process() is @@ -3554,9 +3561,9 @@ bool COMXPlayer::ShowPVRChannelInfo(void) { bool bReturn(false); - if (g_guiSettings.GetBool("pvrmenu.infoswitch")) + if (CSettings::Get().GetBool("pvrmenu.infoswitch")) { - int iTimeout = g_guiSettings.GetBool("pvrmenu.infotimeout") ? g_guiSettings.GetInt("pvrmenu.infotime") : 0; + int iTimeout = CSettings::Get().GetBool("pvrmenu.infotimeout") ? CSettings::Get().GetInt("pvrmenu.infotime") : 0; g_PVRManager.ShowPlayerInfo(iTimeout); bReturn = true; diff --git a/xbmc/cores/omxplayer/OMXPlayerAudio.cpp b/xbmc/cores/omxplayer/OMXPlayerAudio.cpp index 38344441f8..bacd11961a 100644 --- a/xbmc/cores/omxplayer/OMXPlayerAudio.cpp +++ b/xbmc/cores/omxplayer/OMXPlayerAudio.cpp @@ -32,10 +32,9 @@ #include "linux/XMemUtils.h" #include "utils/BitstreamStats.h" -#include "settings/GUISettings.h" -#include "settings/Settings.h" #include "DVDDemuxers/DVDDemuxUtils.h" +#include "cores/AudioEngine/Utils/AEUtil.h" #include "utils/MathUtils.h" #include "settings/AdvancedSettings.h" #include "settings/Settings.h" @@ -165,7 +164,7 @@ void OMXPlayerAudio::OpenStream(CDVDStreamInfo &hints, COMXAudioCodecOMX *codec) m_nChannels = 0; m_synctype = SYNC_DISCON; m_stalled = m_messageQueue.GetPacketCount(CDVDMsg::DEMUXER_PACKET) == 0; - m_use_passthrough = (g_guiSettings.GetInt("audiooutput.mode") == AUDIO_HDMI) ? true : false ; + m_use_passthrough = (CSettings::Get().GetInt("audiooutput.mode") == AUDIO_HDMI) ? true : false ; m_use_hw_decode = g_advancedSettings.m_omxHWAudioDecode; } @@ -692,14 +691,14 @@ AEDataFormat OMXPlayerAudio::GetDataFormat(CDVDStreamInfo hints) /* check our audio capabilties */ /* pathrought is overriding hw decode*/ - if(AUDIO_IS_BITSTREAM(g_guiSettings.GetInt("audiooutput.mode")) && m_use_passthrough) + if(AUDIO_IS_BITSTREAM(CSettings::Get().GetInt("audiooutput.mode")) && m_use_passthrough) { - if(hints.codec == CODEC_ID_AC3 && g_guiSettings.GetBool("audiooutput.ac3passthrough") && hdmi_passthrough_ac3) + if(hints.codec == CODEC_ID_AC3 && CSettings::Get().GetBool("audiooutput.ac3passthrough") && hdmi_passthrough_ac3) { dataFormat = AE_FMT_AC3; m_passthrough = true; } - if(hints.codec == CODEC_ID_DTS && g_guiSettings.GetBool("audiooutput.dtspassthrough") && hdmi_passthrough_dts) + if(hints.codec == CODEC_ID_DTS && CSettings::Get().GetBool("audiooutput.dtspassthrough") && hdmi_passthrough_dts) { dataFormat = AE_FMT_DTS; m_passthrough = true; @@ -757,7 +756,7 @@ bool OMXPlayerAudio::OpenDecoder() std::string device = ""; - if(g_guiSettings.GetInt("audiooutput.mode") == AUDIO_HDMI) + if(CSettings::Get().GetInt("audiooutput.mode") == AUDIO_HDMI) device = "hdmi"; else device = "local"; diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp index bd5711c15d..9613e57e4f 100644 --- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp @@ -41,7 +41,6 @@ #include "windowing/WindowingFactory.h" #include "DVDOverlayRenderer.h" #include "settings/DisplaySettings.h" -#include "settings/GUISettings.h" #include "settings/Settings.h" #include "settings/MediaSettings.h" #include "cores/VideoRenderers/RenderFormats.h" @@ -119,7 +118,7 @@ bool OMXPlayerVideo::OpenStream(CDVDStreamInfo &hints) m_hints = hints; m_Deinterlace = ( CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode == VS_DEINTERLACEMODE_OFF ) ? false : true; - m_hdmi_clock_sync = (g_guiSettings.GetInt("videoplayer.adjustrefreshrate") != ADJUST_REFRESHRATE_OFF); + m_hdmi_clock_sync = (CSettings::Get().GetInt("videoplayer.adjustrefreshrate") != ADJUST_REFRESHRATE_OFF); m_started = false; m_flush = false; m_stalled = m_messageQueue.GetPacketCount(CDVDMsg::DEMUXER_PACKET) == 0; diff --git a/xbmc/cores/omxplayer/OMXVideo.cpp b/xbmc/cores/omxplayer/OMXVideo.cpp index 8e2e3da800..4443faec13 100644 --- a/xbmc/cores/omxplayer/OMXVideo.cpp +++ b/xbmc/cores/omxplayer/OMXVideo.cpp @@ -34,7 +34,6 @@ #include "settings/Settings.h" #include "utils/BitstreamConverter.h" - #include <sys/time.h> #include <inttypes.h> diff --git a/xbmc/cores/paplayer/AudioDecoder.cpp b/xbmc/cores/paplayer/AudioDecoder.cpp index 95440fa1b2..b0201b477d 100644 --- a/xbmc/cores/paplayer/AudioDecoder.cpp +++ b/xbmc/cores/paplayer/AudioDecoder.cpp @@ -20,15 +20,14 @@ #include "AudioDecoder.h" #include "CodecFactory.h" -#include "settings/GUISettings.h" +#include "Application.h" +#include "settings/Settings.h" #include "FileItem.h" #include "music/tags/MusicInfoTag.h" #include "threads/SingleLock.h" #include "utils/log.h" #include <math.h> -ReplayGainSettings CAudioDecoder::m_replayGainSettings; - CAudioDecoder::CAudioDecoder() { m_codec = NULL; @@ -74,13 +73,13 @@ bool CAudioDecoder::Create(const CFileItem &file, int64_t seekOffset) m_eof = false; // get correct cache size - unsigned int filecache = g_guiSettings.GetInt("cacheaudio.internet"); + unsigned int filecache = CSettings::Get().GetInt("cacheaudio.internet"); if ( file.IsHD() ) - filecache = g_guiSettings.GetInt("cache.harddisk"); + filecache = CSettings::Get().GetInt("cache.harddisk"); else if ( file.IsOnDVD() ) - filecache = g_guiSettings.GetInt("cacheaudio.dvdrom"); + filecache = CSettings::Get().GetInt("cacheaudio.dvdrom"); else if ( file.IsOnLAN() ) - filecache = g_guiSettings.GetInt("cacheaudio.lan"); + filecache = CSettings::Get().GetInt("cacheaudio.lan"); // create our codec m_codec=CodecFactory::CreateCodecDemux(file.GetPath(), file.GetMimeType(), filecache * 1024); @@ -243,42 +242,43 @@ int CAudioDecoder::ReadSamples(int numsamples) float CAudioDecoder::GetReplayGain() { #define REPLAY_GAIN_DEFAULT_LEVEL 89.0f - if (m_replayGainSettings.iType == REPLAY_GAIN_NONE) + const ReplayGainSettings &replayGainSettings = g_application.GetReplayGainSettings(); + if (replayGainSettings.iType == REPLAY_GAIN_NONE) return 1.0f; // Compute amount of gain - float replaydB = (float)m_replayGainSettings.iNoGainPreAmp; + float replaydB = (float)replayGainSettings.iNoGainPreAmp; float peak = 0.0f; - if (m_replayGainSettings.iType == REPLAY_GAIN_ALBUM) + if (replayGainSettings.iType == REPLAY_GAIN_ALBUM) { if (m_codec->m_tag.HasReplayGainInfo() & REPLAY_GAIN_HAS_ALBUM_INFO) { - replaydB = (float)m_replayGainSettings.iPreAmp + (float)m_codec->m_tag.GetReplayGainAlbumGain() * 0.01f; + replaydB = (float)replayGainSettings.iPreAmp + (float)m_codec->m_tag.GetReplayGainAlbumGain() * 0.01f; peak = m_codec->m_tag.GetReplayGainAlbumPeak(); } else if (m_codec->m_tag.HasReplayGainInfo() & REPLAY_GAIN_HAS_TRACK_INFO) { - replaydB = (float)m_replayGainSettings.iPreAmp + (float)m_codec->m_tag.GetReplayGainTrackGain() * 0.01f; + replaydB = (float)replayGainSettings.iPreAmp + (float)m_codec->m_tag.GetReplayGainTrackGain() * 0.01f; peak = m_codec->m_tag.GetReplayGainTrackPeak(); } } - else if (m_replayGainSettings.iType == REPLAY_GAIN_TRACK) + else if (replayGainSettings.iType == REPLAY_GAIN_TRACK) { if (m_codec->m_tag.HasReplayGainInfo() & REPLAY_GAIN_HAS_TRACK_INFO) { - replaydB = (float)m_replayGainSettings.iPreAmp + (float)m_codec->m_tag.GetReplayGainTrackGain() * 0.01f; + replaydB = (float)replayGainSettings.iPreAmp + (float)m_codec->m_tag.GetReplayGainTrackGain() * 0.01f; peak = m_codec->m_tag.GetReplayGainTrackPeak(); } else if (m_codec->m_tag.HasReplayGainInfo() & REPLAY_GAIN_HAS_ALBUM_INFO) { - replaydB = (float)m_replayGainSettings.iPreAmp + (float)m_codec->m_tag.GetReplayGainAlbumGain() * 0.01f; + replaydB = (float)replayGainSettings.iPreAmp + (float)m_codec->m_tag.GetReplayGainAlbumGain() * 0.01f; peak = m_codec->m_tag.GetReplayGainAlbumPeak(); } } // convert to a gain type float replaygain = pow(10.0f, (replaydB - REPLAY_GAIN_DEFAULT_LEVEL)* 0.05f); // check peaks - if (m_replayGainSettings.bAvoidClipping) + if (replayGainSettings.bAvoidClipping) { if (fabs(peak * replaygain) > 1.0f) replaygain = 1.0f / fabs(peak); diff --git a/xbmc/cores/paplayer/AudioDecoder.h b/xbmc/cores/paplayer/AudioDecoder.h index a933f4d508..14cd0ed87d 100644 --- a/xbmc/cores/paplayer/AudioDecoder.h +++ b/xbmc/cores/paplayer/AudioDecoder.h @@ -50,24 +50,12 @@ class CFileItem; #define RET_SUCCESS 0 #define RET_SLEEP 1 -// replay gain settings struct for quick access by the player multiple -// times per second (saves doing settings lookup) -struct ReplayGainSettings -{ - int iPreAmp; - int iNoGainPreAmp; - int iType; - bool bAvoidClipping; -}; - class CAudioDecoder { public: CAudioDecoder(); ~CAudioDecoder(); - static ReplayGainSettings& GetReplayGainSettings() { return m_replayGainSettings; } - bool Create(const CFileItem &file, int64_t seekOffset); void Destroy(); @@ -89,8 +77,6 @@ public: float GetReplayGain(); private: - static ReplayGainSettings m_replayGainSettings; - // pcm buffer CRingBuffer m_pcmBuffer; diff --git a/xbmc/cores/paplayer/CDDAcodec.cpp b/xbmc/cores/paplayer/CDDAcodec.cpp deleted file mode 100644 index 993c17267d..0000000000 --- a/xbmc/cores/paplayer/CDDAcodec.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (C) 2005-2013 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 "CDDAcodec.h" -#if !defined(TARGET_DARWIN_IOS) -#include <cdio/sector.h> -#else -typedef int32_t lsn_t; -#define CDIO_CD_FRAMESIZE_RAW 2352 -#define CDIO_CD_FRAMES_PER_SEC 75 -#endif -#include "cores/AudioEngine/Utils/AEUtil.h" - -#define SECTOR_COUNT 55 // max. sectors that can be read at once -#define MAX_BUFFER_SIZE 2*SECTOR_COUNT*CDIO_CD_FRAMESIZE_RAW - -CDDACodec::CDDACodec() -{ - m_SampleRate = 44100; - m_Channels = 2; - m_BitsPerSample = 16; - m_DataFormat = AE_FMT_S16NE; - m_TotalTime = 0; - m_Bitrate = 0; - m_CodecName = "cdda"; - - m_BufferSize=0; - m_Buffer = new BYTE[MAX_BUFFER_SIZE]; - m_BufferPos = 0; -} - -CDDACodec::~CDDACodec() -{ - DeInit(); - - if (m_Buffer) - { - delete[] m_Buffer; - m_Buffer = NULL; - } -} - -bool CDDACodec::Init(const CStdString &strFile, unsigned int filecache) -{ - if (!m_file.Open(strFile, READ_CACHED)) - return false; - - // Calculate total time of the track - m_TotalTime=(m_file.GetLength()/CDIO_CD_FRAMESIZE_RAW)/CDIO_CD_FRAMES_PER_SEC; - if (m_TotalTime > 0) - m_Bitrate = (int)((m_file.GetLength() * 8) / m_TotalTime); - else - m_Bitrate = 0; - m_TotalTime*=1000; // ms - return true; -} - -void CDDACodec::DeInit() -{ - m_file.Close(); -} - -int64_t CDDACodec::Seek(int64_t iSeekTime) -{ - // Calculate the next full second... - int iSeekTimeFullSec=(int)(iSeekTime+(1000-(iSeekTime%1000)))/1000; - - // ...and the logical sector on the cd... - lsn_t lsnSeek=iSeekTimeFullSec*CDIO_CD_FRAMES_PER_SEC; - - // ... then seek to its position... - int iNewOffset=(int)m_file.Seek(lsnSeek*CDIO_CD_FRAMESIZE_RAW, SEEK_SET); - m_BufferSize=m_BufferPos=0; - - // ... and look if we really got there. - int iNewSeekTime=(iNewOffset/CDIO_CD_FRAMESIZE_RAW)/CDIO_CD_FRAMES_PER_SEC; - return iNewSeekTime*(int64_t)1000; // ms -} - -int CDDACodec::ReadPCM(BYTE *pBuffer, int size, int *actualsize) -{ - *actualsize=0; - - bool bEof=false; - // Reached end of track? - if (m_file.GetLength()==m_file.GetPosition()) - bEof=true; - - // Do we have to refill our audio buffer? - if (m_BufferSize-m_BufferPos<MAX_BUFFER_SIZE/2 && !bEof) - { - // Move the remaining audio data to the beginning of the buffer - memmove(m_Buffer, m_Buffer + m_BufferPos, m_BufferSize-m_BufferPos); - m_BufferSize=m_BufferSize-m_BufferPos; - m_BufferPos = 0; - - // Fill our buffer with a chunk of audio data - int iAmountRead=m_file.Read(m_Buffer+m_BufferSize, MAX_BUFFER_SIZE/2); - if (iAmountRead<=0) - return READ_ERROR; - - m_BufferSize+=iAmountRead; - } - - // Our buffer is empty and no data left to read from the cd - if (m_BufferSize-m_BufferPos==0 && bEof) - return READ_EOF; - - // Try to give the player the amount of audio data he wants - if (m_BufferSize-m_BufferPos>=size) - { // we have enough data in our buffer - memcpy(pBuffer, m_Buffer + m_BufferPos, size); - m_BufferPos+=size; - *actualsize=size; - } - else - { // Only a smaller amount of data left as the player wants - memcpy(pBuffer, m_Buffer + m_BufferPos, m_BufferSize-m_BufferPos); - *actualsize=m_BufferSize-m_BufferPos; - m_BufferPos+=m_BufferSize-m_BufferPos; - } - - return READ_SUCCESS; -} - -bool CDDACodec::CanInit() -{ - return true; -} - -CAEChannelInfo CDDACodec::GetChannelInfo() -{ - static enum AEChannel map[2][3] = { - {AE_CH_FC, AE_CH_NULL}, - {AE_CH_FL, AE_CH_FR , AE_CH_NULL} - }; - - if (m_Channels > 2) - return CAEUtil::GuessChLayout(m_Channels); - - return CAEChannelInfo(map[m_Channels - 1]); -} diff --git a/xbmc/cores/paplayer/CodecFactory.cpp b/xbmc/cores/paplayer/CodecFactory.cpp index 7decb523dc..c35d91375c 100644 --- a/xbmc/cores/paplayer/CodecFactory.cpp +++ b/xbmc/cores/paplayer/CodecFactory.cpp @@ -21,7 +21,6 @@ #include "system.h" #include "CodecFactory.h" #include "MP3codec.h" -#include "CDDAcodec.h" #include "OGGcodec.h" #include "FLACcodec.h" #include "WAVcodec.h" @@ -51,7 +50,7 @@ ICodec* CodecFactory::CreateCodec(const CStdString& strFileType) else if (strFileType.Equals("ape") || strFileType.Equals("mac")) return new DVDPlayerCodec(); else if (strFileType.Equals("cdda")) - return new CDDACodec(); + return new DVDPlayerCodec(); else if (strFileType.Equals("mpc") || strFileType.Equals("mp+") || strFileType.Equals("mpp")) return new DVDPlayerCodec(); else if (strFileType.Equals("shn")) @@ -183,20 +182,6 @@ ICodec* CodecFactory::CreateCodecDemux(const CStdString& strFile, const CStdStri } delete codec; } - if (urlFile.GetFileType().Equals("cdda")) - { - //lets see what it contains... - //this kinda sucks 'cause if it's plain cdda the file - //will be opened, sniffed and closed before it is opened *again* for cdda - //would be better if the papcodecs could work with bitstreams instead of filenames. - DVDPlayerCodec *dvdcodec = new DVDPlayerCodec(); - dvdcodec->SetContentType("audio/x-spdif-compressed"); - if (dvdcodec->Init(strFile, filecache)) - { - return dvdcodec; - } - delete dvdcodec; - } else if (urlFile.GetFileType().Equals("ogg") || urlFile.GetFileType().Equals("oggstream") || urlFile.GetFileType().Equals("oga")) return CreateOGGCodec(strFile,filecache); diff --git a/xbmc/cores/paplayer/DVDPlayerCodec.cpp b/xbmc/cores/paplayer/DVDPlayerCodec.cpp index 562c96d68e..edf0eb6251 100644 --- a/xbmc/cores/paplayer/DVDPlayerCodec.cpp +++ b/xbmc/cores/paplayer/DVDPlayerCodec.cpp @@ -27,7 +27,7 @@ #include "cores/dvdplayer/DVDStreamInfo.h" #include "cores/dvdplayer/DVDCodecs/DVDFactoryCodec.h" #include "utils/log.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "URL.h" #include "AudioDecoder.h" @@ -132,7 +132,7 @@ bool DVDPlayerCodec::Init(const CStdString &strFile, unsigned int filecache) CDVDStreamInfo hint(*pStream, true); - bool passthrough = AUDIO_IS_BITSTREAM(g_guiSettings.GetInt("audiooutput.mode")); + bool passthrough = AUDIO_IS_BITSTREAM(CSettings::Get().GetInt("audiooutput.mode")); m_pAudioCodec = CDVDFactoryCodec::CreateAudioCodec(hint, passthrough); if (!m_pAudioCodec) { diff --git a/xbmc/cores/paplayer/Makefile.in b/xbmc/cores/paplayer/Makefile.in index 31cc8bd7b0..fa40ee844d 100644 --- a/xbmc/cores/paplayer/Makefile.in +++ b/xbmc/cores/paplayer/Makefile.in @@ -9,7 +9,6 @@ endif SRCS = ADPCMCodec.cpp SRCS += AudioDecoder.cpp -SRCS += CDDAcodec.cpp SRCS += CodecFactory.cpp SRCS += DVDPlayerCodec.cpp SRCS += FLACcodec.cpp diff --git a/xbmc/cores/paplayer/PAPlayer.cpp b/xbmc/cores/paplayer/PAPlayer.cpp index 8ab075e5a5..cfde8fbf6b 100644 --- a/xbmc/cores/paplayer/PAPlayer.cpp +++ b/xbmc/cores/paplayer/PAPlayer.cpp @@ -22,7 +22,6 @@ #include "CodecFactory.h" #include "FileItem.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" #include "settings/Settings.h" #include "music/tags/MusicInfoTag.h" #include "utils/TimeUtils.h" @@ -224,7 +223,7 @@ void PAPlayer::CloseAllStreams(bool fade/* = true */) bool PAPlayer::OpenFile(const CFileItem& file, const CPlayerOptions &options) { - m_defaultCrossfadeMS = g_guiSettings.GetInt("musicplayer.crossfade") * 1000; + m_defaultCrossfadeMS = CSettings::Get().GetInt("musicplayer.crossfade") * 1000; if (m_streams.size() > 1 || !m_defaultCrossfadeMS || m_isPaused) { @@ -260,12 +259,12 @@ bool PAPlayer::OpenFile(const CFileItem& file, const CPlayerOptions &options) void PAPlayer::UpdateCrossfadeTime(const CFileItem& file) { - m_upcomingCrossfadeMS = m_defaultCrossfadeMS = g_guiSettings.GetInt("musicplayer.crossfade") * 1000; + m_upcomingCrossfadeMS = m_defaultCrossfadeMS = CSettings::Get().GetInt("musicplayer.crossfade") * 1000; if (m_upcomingCrossfadeMS) { if (m_streams.size() == 0 || ( - file.HasMusicInfoTag() && !g_guiSettings.GetBool("musicplayer.crossfadealbumtracks") && + file.HasMusicInfoTag() && !CSettings::Get().GetBool("musicplayer.crossfadealbumtracks") && m_FileItem->HasMusicInfoTag() && (m_FileItem->GetMusicInfoTag()->GetAlbum() != "") && (m_FileItem->GetMusicInfoTag()->GetAlbum() == file.GetMusicInfoTag()->GetAlbum()) && diff --git a/xbmc/cores/playercorefactory/PlayerCoreFactory.cpp b/xbmc/cores/playercorefactory/PlayerCoreFactory.cpp index 8775c17226..5e57f335b3 100644 --- a/xbmc/cores/playercorefactory/PlayerCoreFactory.cpp +++ b/xbmc/cores/playercorefactory/PlayerCoreFactory.cpp @@ -21,12 +21,13 @@ #include "utils/BitstreamStats.h" #include "PlayerCoreFactory.h" #include "threads/SingleLock.h" +#include "cores/AudioEngine/Utils/AEUtil.h" #include "cores/dvdplayer/DVDPlayer.h" #include "cores/paplayer/PAPlayer.h" #include "cores/paplayer/DVDPlayerCodec.h" #include "dialogs/GUIDialogContextMenu.h" #include "utils/HttpHeader.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "URL.h" #include "FileItem.h" #include "profiles/ProfilesManager.h" @@ -80,7 +81,7 @@ template<typename T> void unique (T &con) IPlayer* CPlayerCoreFactory::CreatePlayer(const CStdString& strCore, IPlayerCallback& callback) const { - return CreatePlayer( GetPlayerCore(strCore), callback ); + return CreatePlayer(GetPlayerCore(strCore), callback ); } IPlayer* CPlayerCoreFactory::CreatePlayer(const PLAYERCOREID eCore, IPlayerCallback& callback) const @@ -188,7 +189,7 @@ void CPlayerCoreFactory::GetPlayers( const CFileItem& item, VECPLAYERCORES &vecC if (bAdd) { - if( g_guiSettings.GetInt("audiooutput.mode") == AUDIO_ANALOG ) + if( CSettings::Get().GetInt("audiooutput.mode") == AUDIO_ANALOG ) { CLog::Log(LOGDEBUG, "CPlayerCoreFactory::GetPlayers: adding PAPlayer (%d)", EPC_PAPLAYER); vecCores.push_back(EPC_PAPLAYER); @@ -298,6 +299,7 @@ PLAYERCOREID CPlayerCoreFactory::SelectPlayerDialog(float posX, float posY) cons bool CPlayerCoreFactory::LoadConfiguration(const std::string &file, bool clear) { CSingleLock lock(m_section); + CLog::Log(LOGNOTICE, "Loading player core factory settings from %s.", file.c_str()); if (!XFILE::CFile::Exists(file)) { // tell the user it doesn't exist diff --git a/xbmc/cores/playercorefactory/PlayerCoreFactory.h b/xbmc/cores/playercorefactory/PlayerCoreFactory.h index 559ee0fae1..1f9405dab0 100644 --- a/xbmc/cores/playercorefactory/PlayerCoreFactory.h +++ b/xbmc/cores/playercorefactory/PlayerCoreFactory.h @@ -20,15 +20,14 @@ * */ -#include "system.h" +#include <vector> +#include "system.h" #include "cores/IPlayerCallback.h" #include "settings/ISettingsHandler.h" #include "threads/CriticalSection.h" #include "utils/StdString.h" -#include <vector> - /*---------------------------------------------------------------------- | forward references +---------------------------------------------------------------------*/ diff --git a/xbmc/cores/playercorefactory/PlayerSelectionRule.cpp b/xbmc/cores/playercorefactory/PlayerSelectionRule.cpp index 52361a0c07..f3ba67563f 100644 --- a/xbmc/cores/playercorefactory/PlayerSelectionRule.cpp +++ b/xbmc/cores/playercorefactory/PlayerSelectionRule.cpp @@ -22,7 +22,7 @@ #include "PlayerSelectionRule.h" #include "video/VideoInfoTag.h" #include "utils/StreamDetails.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "utils/log.h" #include "utils/RegExp.h" #include "utils/XBMCTinyXML.h" @@ -67,7 +67,7 @@ void CPlayerSelectionRule::Initialize(TiXmlElement* pRule) m_bStreamDetails = m_audioCodec.length() > 0 || m_audioChannels.length() > 0 || m_videoCodec.length() > 0 || m_videoResolution.length() > 0 || m_videoAspect.length() > 0; - if (m_bStreamDetails && !g_guiSettings.GetBool("myvideos.extractflags")) + if (m_bStreamDetails && !CSettings::Get().GetBool("myvideos.extractflags")) { CLog::Log(LOGWARNING, "CPlayerSelectionRule::Initialize: rule: %s needs media flagging, which is disabled", m_name.c_str()); } diff --git a/xbmc/dbwrappers/sqlitedataset.cpp b/xbmc/dbwrappers/sqlitedataset.cpp index 07cc9e2792..2226683a60 100644 --- a/xbmc/dbwrappers/sqlitedataset.cpp +++ b/xbmc/dbwrappers/sqlitedataset.cpp @@ -211,8 +211,7 @@ int SqliteDatabase::connect(bool create) { //CLog::Log(LOGDEBUG, "Connecting to sqlite:%s:%s", host.c_str(), db.c_str()); - CStdString db_fullpath; - URIUtils::AddFileToFolder(host, db, db_fullpath); + CStdString db_fullpath = URIUtils::AddFileToFolder(host, db); try { diff --git a/xbmc/dialogs/GUIDialogContextMenu.cpp b/xbmc/dialogs/GUIDialogContextMenu.cpp index 3c95aaab2e..da7d4854f1 100644 --- a/xbmc/dialogs/GUIDialogContextMenu.cpp +++ b/xbmc/dialogs/GUIDialogContextMenu.cpp @@ -28,8 +28,8 @@ #include "GUIPassword.h" #include "Util.h" #include "utils/URIUtils.h" -#include "settings/GUISettings.h" #include "settings/MediaSourceSettings.h" +#include "settings/Settings.h" #include "GUIDialogMediaSource.h" #include "profiles/ProfilesManager.h" #include "profiles/dialogs/GUIDialogLockSettings.h" @@ -40,7 +40,6 @@ #include "addons/AddonManager.h" #include "FileItem.h" #include "filesystem/File.h" -#include "settings/Settings.h" #include "guilib/LocalizeStrings.h" #include "TextureCache.h" #include "video/windows/GUIWindowVideoBase.h" @@ -368,8 +367,8 @@ void CGUIDialogContextMenu::GetContextButtons(const CStdString &type, const CFil buttons.Add(CONTEXT_BUTTON_REMOVE_LOCK, 12335); bool maxRetryExceeded = false; - if (g_guiSettings.GetInt("masterlock.maxretries") != 0) - maxRetryExceeded = (share->m_iBadPwdCount >= g_guiSettings.GetInt("masterlock.maxretries")); + if (CSettings::Get().GetInt("masterlock.maxretries") != 0) + maxRetryExceeded = (share->m_iBadPwdCount >= CSettings::Get().GetInt("masterlock.maxretries")); if (maxRetryExceeded) buttons.Add(CONTEXT_BUTTON_RESET_LOCK, 12334); @@ -607,8 +606,8 @@ bool CGUIDialogContextMenu::OnContextButton(const CStdString &type, const CFileI case CONTEXT_BUTTON_REACTIVATE_LOCK: { bool maxRetryExceeded = false; - if (g_guiSettings.GetInt("masterlock.maxretries") != 0) - maxRetryExceeded = (share->m_iBadPwdCount >= g_guiSettings.GetInt("masterlock.maxretries")); + if (CSettings::Get().GetInt("masterlock.maxretries") != 0) + maxRetryExceeded = (share->m_iBadPwdCount >= CSettings::Get().GetInt("masterlock.maxretries")); if (!maxRetryExceeded) { // don't prompt user for mastercode when reactivating a lock diff --git a/xbmc/dialogs/GUIDialogContextMenu.h b/xbmc/dialogs/GUIDialogContextMenu.h index 2347b03d9c..38e7ed657b 100644 --- a/xbmc/dialogs/GUIDialogContextMenu.h +++ b/xbmc/dialogs/GUIDialogContextMenu.h @@ -128,6 +128,7 @@ enum CONTEXT_BUTTON { CONTEXT_BUTTON_CANCELLED = 0, CONTEXT_BUTTON_TAGS_REMOVE_ITEMS, CONTEXT_BUTTON_SET_MOVIESET, CONTEXT_BUTTON_MOVIESET_ADD_REMOVE_ITEMS, + CONTEXT_BUTTON_BROWSE_INTO, CONTEXT_BUTTON_USER1, CONTEXT_BUTTON_USER2, CONTEXT_BUTTON_USER3, diff --git a/xbmc/dialogs/GUIDialogFileBrowser.cpp b/xbmc/dialogs/GUIDialogFileBrowser.cpp index 31d2ef5d39..7e3c517519 100644 --- a/xbmc/dialogs/GUIDialogFileBrowser.cpp +++ b/xbmc/dialogs/GUIDialogFileBrowser.cpp @@ -40,8 +40,8 @@ #include "filesystem/MultiPathDirectory.h" #include "profiles/ProfilesManager.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" #include "settings/MediaSourceSettings.h" +#include "settings/Settings.h" #include "guilib/Key.h" #include "guilib/LocalizeStrings.h" #include "utils/log.h" @@ -205,7 +205,6 @@ bool CGUIDialogFileBrowser::OnMessage(CGUIMessage& message) { if (m_browsingForFolders == 2) { - CStdString strTest; int iItem = m_viewControl.GetSelectedItem(); CStdString strPath; @@ -214,7 +213,7 @@ bool CGUIDialogFileBrowser::OnMessage(CGUIMessage& message) else strPath = (*m_vecItems)[iItem]->GetPath(); - URIUtils::AddFileToFolder(strPath,"1",strTest); + CStdString strTest = URIUtils::AddFileToFolder(strPath, "1"); CFile file; if (file.OpenForWrite(strTest,true)) { @@ -252,8 +251,7 @@ bool CGUIDialogFileBrowser::OnMessage(CGUIMessage& message) CStdString strInput; if (CGUIKeyboardFactory::ShowAndGetInput(strInput,g_localizeStrings.Get(119),false)) { - CStdString strPath; - URIUtils::AddFileToFolder(m_vecItems->GetPath(),strInput,strPath); + CStdString strPath = URIUtils::AddFileToFolder(m_vecItems->GetPath(), strInput); if (CDirectory::Create(strPath)) Update(m_vecItems->GetPath()); else diff --git a/xbmc/dialogs/GUIDialogMediaSource.cpp b/xbmc/dialogs/GUIDialogMediaSource.cpp index 0c8f39baec..8314e1403e 100644 --- a/xbmc/dialogs/GUIDialogMediaSource.cpp +++ b/xbmc/dialogs/GUIDialogMediaSource.cpp @@ -31,8 +31,8 @@ #include "filesystem/PVRDirectory.h" #include "GUIDialogYesNo.h" #include "FileItem.h" -#include "settings/GUISettings.h" #include "settings/MediaSourceSettings.h" +#include "settings/Settings.h" #include "guilib/LocalizeStrings.h" #include "PasswordManager.h" #include "URL.h" @@ -252,13 +252,12 @@ void CGUIDialogMediaSource::OnPathBrowse(int item) share1.strName = "SAP Streams"; extraShares.push_back(share1); - if (g_guiSettings.GetString("audiocds.recordingpath",false) != "") + if (CSettings::Get().GetString("audiocds.recordingpath") != "") { share1.strPath = "special://recordings/"; share1.strName = g_localizeStrings.Get(21883); extraShares.push_back(share1); } - } else if (m_type == "video") { @@ -326,7 +325,7 @@ void CGUIDialogMediaSource::OnPathBrowse(int item) #endif share1.m_ignore = true; - if (g_guiSettings.GetString("debug.screenshotpath",false)!= "") + if (CSettings::Get().GetString("debug.screenshotpath") != "") { share1.strPath = "special://screenshots/"; share1.strName = g_localizeStrings.Get(20008); diff --git a/xbmc/dialogs/GUIDialogSeekBar.cpp b/xbmc/dialogs/GUIDialogSeekBar.cpp index 22e9ad36a6..60ac273430 100644 --- a/xbmc/dialogs/GUIDialogSeekBar.cpp +++ b/xbmc/dialogs/GUIDialogSeekBar.cpp @@ -24,7 +24,6 @@ #include "GUIInfoManager.h" #include "utils/TimeUtils.h" #include "FileItem.h" -#include "settings/GUISettings.h" #include "utils/SeekHandler.h" #define SEEK_BAR_DISPLAY_TIME 2000L diff --git a/xbmc/dialogs/GUIDialogSmartPlaylistEditor.cpp b/xbmc/dialogs/GUIDialogSmartPlaylistEditor.cpp index 451be19223..80642906e9 100644 --- a/xbmc/dialogs/GUIDialogSmartPlaylistEditor.cpp +++ b/xbmc/dialogs/GUIDialogSmartPlaylistEditor.cpp @@ -21,12 +21,13 @@ #include "GUIDialogSmartPlaylistEditor.h" #include "guilib/GUIKeyboardFactory.h" #include "Util.h" +#include "utils/StringUtils.h" #include "utils/URIUtils.h" #include "GUIDialogSmartPlaylistRule.h" #include "guilib/GUIWindowManager.h" #include "filesystem/File.h" #include "profiles/ProfilesManager.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "FileItem.h" #include "guilib/Key.h" #include "guilib/LocalizeStrings.h" @@ -166,7 +167,7 @@ void CGUIDialogSmartPlaylistEditor::OnOK() CStdString path; if (CGUIKeyboardFactory::ShowAndGetInput(filename, g_localizeStrings.Get(16013), false)) { - path = URIUtils::AddFileToFolder(g_guiSettings.GetString("system.playlistspath"),m_playlist.GetSaveLocation()); + path = URIUtils::AddFileToFolder(CSettings::Get().GetString("system.playlistspath"),m_playlist.GetSaveLocation()); path = URIUtils::AddFileToFolder(path, CUtil::MakeLegalFileName(filename)); } else @@ -181,14 +182,14 @@ void CGUIDialogSmartPlaylistEditor::OnOK() { // check if we need to actually change the save location for this playlist // this occurs if the user switches from music video <> songs <> mixed - if (m_path.Left(g_guiSettings.GetString("system.playlistspath").size()).Equals(g_guiSettings.GetString("system.playlistspath"))) // fugly, well aware + if (StringUtils::EqualsNoCase(m_path.Left(CSettings::Get().GetString("system.playlistspath").size()), CSettings::Get().GetString("system.playlistspath"))) // fugly, well aware { CStdString filename = URIUtils::GetFileName(m_path); - CStdString strFolder = m_path.Mid(g_guiSettings.GetString("system.playlistspath").size(),m_path.size()-filename.size()-g_guiSettings.GetString("system.playlistspath").size()-1); + CStdString strFolder = m_path.Mid(CSettings::Get().GetString("system.playlistspath").size(),m_path.size()-filename.size()-CSettings::Get().GetString("system.playlistspath").size()-1); if (strFolder != m_playlist.GetSaveLocation()) { // move to the correct folder XFILE::CFile::Delete(m_path); - m_path = URIUtils::AddFileToFolder(g_guiSettings.GetString("system.playlistspath"),m_playlist.GetSaveLocation()); + m_path = URIUtils::AddFileToFolder(CSettings::Get().GetString("system.playlistspath"),m_playlist.GetSaveLocation()); m_path = URIUtils::AddFileToFolder(m_path, filename); } } diff --git a/xbmc/epg/Epg.cpp b/xbmc/epg/Epg.cpp index cfef9fd9b4..095c67bab5 100644 --- a/xbmc/epg/Epg.cpp +++ b/xbmc/epg/Epg.cpp @@ -20,7 +20,7 @@ #include "guilib/LocalizeStrings.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "threads/SingleLock.h" #include "utils/log.h" #include "utils/TimeUtils.h" @@ -96,7 +96,10 @@ CEpg &CEpg::operator =(const CEpg &right) m_pvrChannel = right.m_pvrChannel; for (map<CDateTime, CEpgInfoTagPtr>::const_iterator it = right.m_tags.begin(); it != right.m_tags.end(); it++) - m_tags.insert(make_pair(it->first, new CEpgInfoTag(*it->second))); + { + CEpgInfoTagPtr EITPtr (new CEpgInfoTag(*it->second)); + m_tags.insert(make_pair(it->first, EITPtr)); + } return *this; } @@ -354,7 +357,7 @@ bool CEpg::UpdateEntry(const CEpgInfoTag &tag, bool bUpdateDatabase /* = false * infoTag->m_pvrChannel = m_pvrChannel; if (bUpdateDatabase) - m_changedTags.insert(make_pair<int, CEpgInfoTagPtr>(infoTag->UniqueBroadcastID(), infoTag)); + m_changedTags.insert(make_pair(infoTag->UniqueBroadcastID(), infoTag)); return true; } @@ -425,7 +428,7 @@ CDateTime CEpg::GetLastScanTime(void) if (!m_lastScanTime.IsValid()) { - if (!g_guiSettings.GetBool("epg.ignoredbforclient")) + if (!CSettings::Get().GetBool("epg.ignoredbforclient")) { CEpgDatabase *database = g_EpgContainer.GetDatabase(); CDateTime dtReturn; dtReturn.SetValid(false); @@ -530,7 +533,7 @@ int CEpg::Get(CFileItemList &results, const EpgSearchFilter &filter) const bool CEpg::Persist(void) { - if (g_guiSettings.GetBool("epg.ignoredbforclient") || !NeedsSave()) + if (CSettings::Get().GetBool("epg.ignoredbforclient") || !NeedsSave()) return true; #if EPG_DEBUGGING @@ -617,7 +620,7 @@ bool CEpg::FixOverlappingEvents(bool bUpdateDb /* = false */) { // delete the current tag. it's completely overlapped if (bUpdateDb) - m_deletedTags.insert(make_pair<int, CEpgInfoTagPtr>(currentTag->UniqueBroadcastID(), currentTag)); + m_deletedTags.insert(make_pair(currentTag->UniqueBroadcastID(), currentTag)); if (m_nowActiveStart == it->first) m_nowActiveStart.SetValid(false); @@ -629,7 +632,7 @@ bool CEpg::FixOverlappingEvents(bool bUpdateDb /* = false */) { currentTag->SetStartFromUTC(previousTag->EndAsUTC()); if (bUpdateDb) - m_changedTags.insert(make_pair<int, CEpgInfoTagPtr>(currentTag->UniqueBroadcastID(), currentTag)); + m_changedTags.insert(make_pair(currentTag->UniqueBroadcastID(), currentTag)); previousTag = it->second; } @@ -649,8 +652,8 @@ bool CEpg::FixOverlappingEvents(bool bUpdateDb /* = false */) if (bUpdateDb) { - m_changedTags.insert(make_pair<int, CEpgInfoTagPtr>(currentTag->UniqueBroadcastID(), currentTag)); - m_changedTags.insert(make_pair<int, CEpgInfoTagPtr>(previousTag->UniqueBroadcastID(), previousTag)); + m_changedTags.insert(make_pair(currentTag->UniqueBroadcastID(), currentTag)); + m_changedTags.insert(make_pair(previousTag->UniqueBroadcastID(), previousTag)); } previousTag = it->second; @@ -788,13 +791,13 @@ bool CEpg::LoadFromClients(time_t start, time_t end) { CEpg tmpEpg(channel); if (tmpEpg.UpdateFromScraper(start, end)) - bReturn = UpdateEntries(tmpEpg, !g_guiSettings.GetBool("epg.ignoredbforclient")); + bReturn = UpdateEntries(tmpEpg, !CSettings::Get().GetBool("epg.ignoredbforclient")); } else { CEpg tmpEpg(m_iEpgID, m_strName, m_strScraperName); if (tmpEpg.UpdateFromScraper(start, end)) - bReturn = UpdateEntries(tmpEpg, !g_guiSettings.GetBool("epg.ignoredbforclient")); + bReturn = UpdateEntries(tmpEpg, !CSettings::Get().GetBool("epg.ignoredbforclient")); } return bReturn; diff --git a/xbmc/epg/EpgContainer.cpp b/xbmc/epg/EpgContainer.cpp index baa4220567..7307bbf26d 100644 --- a/xbmc/epg/EpgContainer.cpp +++ b/xbmc/epg/EpgContainer.cpp @@ -21,7 +21,7 @@ #include "Application.h" #include "threads/SingleLock.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "dialogs/GUIDialogExtendedProgressBar.h" #include "dialogs/GUIDialogProgress.h" #include "guilib/GUIWindowManager.h" @@ -131,7 +131,6 @@ void CEpgContainer::Start(void) m_bIsInitialising = true; m_bStop = false; - g_guiSettings.RegisterObserver(this); LoadSettings(); m_iNextEpgUpdate = 0; @@ -157,14 +156,19 @@ bool CEpgContainer::Stop(void) void CEpgContainer::Notify(const Observable &obs, const ObservableMessage msg) { - /* settings were updated */ - if (msg == ObservableMessageGuiSettings) + SetChanged(); + NotifyObservers(msg); +} + +void CEpgContainer::OnSettingChanged(const CSetting *setting) +{ + if (setting == NULL) + return; + + const std::string &settingId = setting->GetId(); + if (settingId == "epg.ignoredbforclient" || settingId == "epg.epgupdate" || + settingId == "epg.daystodisplay") LoadSettings(); - else - { - SetChanged(); - NotifyObservers(msg); - } } void CEpgContainer::LoadFromDB(void) @@ -275,8 +279,6 @@ void CEpgContainer::Process(void) Sleep(1000); } - - g_guiSettings.UnregisterObserver(this); } CEpg *CEpgContainer::GetById(int iEpgId) const @@ -359,9 +361,9 @@ CEpg *CEpgContainer::CreateChannelEpg(CPVRChannelPtr channel) bool CEpgContainer::LoadSettings(void) { - m_bIgnoreDbForClient = g_guiSettings.GetBool("epg.ignoredbforclient"); - m_iUpdateTime = g_guiSettings.GetInt ("epg.epgupdate") * 60; - m_iDisplayTime = g_guiSettings.GetInt ("epg.daystodisplay") * 24 * 60 * 60; + m_bIgnoreDbForClient = CSettings::Get().GetBool("epg.ignoredbforclient"); + m_iUpdateTime = CSettings::Get().GetInt ("epg.epgupdate") * 60; + m_iDisplayTime = CSettings::Get().GetInt ("epg.daystodisplay") * 24 * 60 * 60; return true; } @@ -447,7 +449,7 @@ bool CEpgContainer::InterruptUpdate(void) const lock.Leave(); return bReturn || - (g_guiSettings.GetBool("epg.preventupdateswhileplayingtv") && + (CSettings::Get().GetBool("epg.preventupdateswhileplayingtv") && g_PVRManager.IsStarted() && g_PVRManager.IsPlaying()); } diff --git a/xbmc/epg/EpgContainer.h b/xbmc/epg/EpgContainer.h index 7b27c4ce4c..7b9166e112 100644 --- a/xbmc/epg/EpgContainer.h +++ b/xbmc/epg/EpgContainer.h @@ -21,6 +21,7 @@ */ #include "XBDateTime.h" +#include "settings/ISettingCallback.h" #include "threads/CriticalSection.h" #include "threads/Thread.h" #include "utils/Observer.h" @@ -38,8 +39,9 @@ namespace EPG #define g_EpgContainer CEpgContainer::Get() class CEpgContainer : public Observer, - public Observable, - private CThread + public Observable, + public ISettingCallback, + private CThread { friend class CEpgDatabase; @@ -107,6 +109,8 @@ namespace EPG */ virtual void Notify(const Observable &obs, const ObservableMessage msg); + virtual void OnSettingChanged(const CSetting *setting); + CEpg *CreateChannelEpg(PVR::CPVRChannelPtr channel); /*! diff --git a/xbmc/epg/EpgInfoTag.cpp b/xbmc/epg/EpgInfoTag.cpp index c6dfb47490..b2783d6504 100644 --- a/xbmc/epg/EpgInfoTag.cpp +++ b/xbmc/epg/EpgInfoTag.cpp @@ -27,7 +27,7 @@ #include "pvr/timers/PVRTimers.h" #include "pvr/PVRManager.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "utils/log.h" #include "utils/Variant.h" #include "addons/include/xbmc_pvr_types.h" @@ -444,7 +444,7 @@ CStdString CEpgInfoTag::Title(bool bOverrideParental /* = false */) const if (!bOverrideParental && bParentalLocked) strTitle = g_localizeStrings.Get(19266); // parental locked - else if (strTitle.empty() && !g_guiSettings.GetBool("epg.hidenoinfoavailable")) + else if (strTitle.empty() && !CSettings::Get().GetBool("epg.hidenoinfoavailable")) strTitle = g_localizeStrings.Get(19055); // no information available return strTitle; diff --git a/xbmc/epg/GUIEPGGridContainer.cpp b/xbmc/epg/GUIEPGGridContainer.cpp index ee44c32375..3243a40aed 100644 --- a/xbmc/epg/GUIEPGGridContainer.cpp +++ b/xbmc/epg/GUIEPGGridContainer.cpp @@ -26,6 +26,7 @@ #include "guilib/DirtyRegion.h" #include <tinyxml.h> #include "utils/log.h" +#include "utils/MathUtils.h" #include "utils/Variant.h" #include "threads/SystemClock.h" #include "GUIInfoManager.h" @@ -62,7 +63,6 @@ CGUIEPGGridContainer::CGUIEPGGridContainer(int parentID, int controlID, float po m_programmeScrollSpeed = 0; m_programmeScrollLastTime = 0; m_scrollTime = scrollTime ? scrollTime : 1; - m_renderTime = 0; m_item = NULL; m_lastItem = NULL; m_lastChannel = NULL; @@ -99,34 +99,35 @@ CGUIEPGGridContainer::~CGUIEPGGridContainer(void) void CGUIEPGGridContainer::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions) { - bool changed = false; - m_renderTime = currentTime; + ValidateOffset(); - changed = true; + if (m_bInvalidated) + UpdateLayout(); - if (changed) - MarkDirtyRegion(); + UpdateScrollOffset(currentTime); + ProcessChannels(currentTime, dirtyregions); + ProcessRuler(currentTime, dirtyregions); + ProcessProgrammeGrid(currentTime, dirtyregions); CGUIControl::Process(currentTime, dirtyregions); } void CGUIEPGGridContainer::Render() { - ValidateOffset(); + RenderChannels(); + RenderRuler(); + RenderProgrammeGrid(); - if (m_bInvalidated) - UpdateLayout(); + CGUIControl::Render(); +} - if (!m_focusedChannelLayout || !m_channelLayout || !m_rulerLayout || !m_focusedProgrammeLayout || !m_programmeLayout || m_rulerItems.size()<=1 || (m_gridEnd - m_gridStart) == CDateTimeSpan(0, 0, 0, 0)) +void CGUIEPGGridContainer::ProcessChannels(unsigned int currentTime, CDirtyRegionList &dirtyregions) +{ + if (!m_focusedChannelLayout || !m_channelLayout) return; - UpdateScrollOffset(); - int chanOffset = (int)floorf(m_channelScrollOffset / m_programmeLayout->Size(m_orientation)); - int blockOffset = (int)floorf(m_programmeScrollOffset / m_blockSize); - int rulerOffset = (int)floorf(m_programmeScrollOffset / m_blockSize); - /// Render channel names int cacheBeforeChannel, cacheAfterChannel; GetChannelCacheOffsets(cacheBeforeChannel, cacheAfterChannel); @@ -134,6 +135,51 @@ void CGUIEPGGridContainer::Render() if ((int)m_channelItems.size() > m_channelsPerPage + cacheBeforeChannel + cacheAfterChannel) FreeChannelMemory(CorrectOffset(chanOffset - cacheBeforeChannel, 0), CorrectOffset(chanOffset + m_channelsPerPage + 1 + cacheAfterChannel, 0)); + CPoint originChannel = CPoint(m_channelPosX, m_channelPosY) + m_renderOffset; + float pos = (m_orientation == VERTICAL) ? originChannel.y : originChannel.x; + float end = (m_orientation == VERTICAL) ? m_posY + m_height : m_posX + m_width; + + // we offset our draw position to take into account scrolling and whether or not our focused + // item is offscreen "above" the list. + float drawOffset = (chanOffset - cacheBeforeChannel) * m_channelLayout->Size(m_orientation) - m_channelScrollOffset; + if (m_channelOffset + m_channelCursor < chanOffset) + drawOffset += m_focusedChannelLayout->Size(m_orientation) - m_channelLayout->Size(m_orientation); + pos += drawOffset; + end += cacheAfterChannel * m_channelLayout->Size(m_orientation); + + int current = chanOffset;// - cacheBeforeChannel; + while (pos < end && (int)m_channelItems.size()) + { + int itemNo = CorrectOffset(current, 0); + if (itemNo >= (int)m_channelItems.size()) + break; + bool focused = (current == m_channelOffset + m_channelCursor); + if (itemNo >= 0) + { + CGUIListItemPtr item = m_channelItems[itemNo]; + // process our item + if (m_orientation == VERTICAL) + ProcessItem(originChannel.x, pos, item.get(), m_lastItem, focused, m_channelLayout, m_focusedChannelLayout, currentTime, dirtyregions); + else + ProcessItem(pos, originChannel.y, item.get(), m_lastItem, focused, m_channelLayout, m_focusedChannelLayout, currentTime, dirtyregions); + } + // increment our position + pos += focused ? m_focusedChannelLayout->Size(m_orientation) : m_channelLayout->Size(m_orientation); + current++; + } +} + +void CGUIEPGGridContainer::RenderChannels() +{ + if (!m_focusedChannelLayout || !m_channelLayout) + return; + + int chanOffset = (int)floorf(m_channelScrollOffset / m_programmeLayout->Size(m_orientation)); + + /// Render channel names + int cacheBeforeChannel, cacheAfterChannel; + GetChannelCacheOffsets(cacheBeforeChannel, cacheAfterChannel); + if (m_orientation == VERTICAL) g_graphicsContext.SetClipRegion(m_channelPosX, m_channelPosY, m_channelWidth, m_gridHeight); else @@ -172,9 +218,9 @@ void CGUIEPGGridContainer::Render() else { if (m_orientation == VERTICAL) - RenderChannelItem(originChannel.x, pos, item.get(), false); + RenderItem(originChannel.x, pos, item.get(), false); else - RenderChannelItem(pos, originChannel.y, item.get(), false); + RenderItem(pos, originChannel.y, item.get(), false); } } // increment our position @@ -185,42 +231,84 @@ void CGUIEPGGridContainer::Render() if (focusedItem) { if (m_orientation == VERTICAL) - RenderChannelItem(originChannel.x, focusedPos, focusedItem.get(), true); + RenderItem(originChannel.x, focusedPos, focusedItem.get(), true); else - RenderChannelItem(focusedPos, originChannel.y, focusedItem.get(), true); + RenderItem(focusedPos, originChannel.y, focusedItem.get(), true); } g_graphicsContext.RestoreClipRegion(); +} - /// Render the ruler items - g_graphicsContext.SetClipRegion(m_posX, m_posY, m_width, m_height); +void CGUIEPGGridContainer::ProcessRuler(unsigned int currentTime, CDirtyRegionList &dirtyregions) +{ + if (!m_rulerLayout || m_rulerItems.size()<=1 || (m_gridEnd - m_gridStart) == CDateTimeSpan(0, 0, 0, 0)) + return; + + int rulerOffset = (int)floorf(m_programmeScrollOffset / m_blockSize); CGUIListItemPtr item = m_rulerItems[0]; - g_graphicsContext.SetOrigin(m_posX, m_posY); item->SetLabel(m_rulerItems[rulerOffset/m_rulerUnit+1]->GetLabel2()); - if (!item->GetLayout()) + CGUIListItem* lastitem = NULL; // dummy pointer needed to be passed as reference to ProcessItem() method + ProcessItem(m_posX, m_posY, item.get(), lastitem, false, m_rulerLayout, m_rulerLayout, currentTime, dirtyregions, (m_orientation == VERTICAL ? m_channelWidth : m_channelHeight)); + + // render ruler items + int cacheBeforeRuler, cacheAfterRuler; + GetProgrammeCacheOffsets(cacheBeforeRuler, cacheAfterRuler); + + // Free memory not used on screen + if ((int)m_rulerItems.size() > m_blocksPerPage + cacheBeforeRuler + cacheAfterRuler) + FreeRulerMemory(CorrectOffset(rulerOffset/m_rulerUnit+1 - cacheBeforeRuler, 0), CorrectOffset(rulerOffset/m_rulerUnit+1 + m_blocksPerPage + 1 + cacheAfterRuler, 0)); + + CPoint originRuler = CPoint(m_rulerPosX, m_rulerPosY) + m_renderOffset; + float pos = (m_orientation == VERTICAL) ? originRuler.x : originRuler.y; + float end = (m_orientation == VERTICAL) ? m_posX + m_width : m_posY + m_height; + float drawOffset = (rulerOffset - cacheBeforeRuler) * m_blockSize - m_programmeScrollOffset; + pos += drawOffset; + end += cacheAfterRuler * m_rulerLayout->Size(m_orientation == VERTICAL ? HORIZONTAL : VERTICAL); + + if (rulerOffset % m_rulerUnit != 0) { - CGUIListItemLayout *layout = new CGUIListItemLayout(*m_rulerLayout); - if (m_orientation == VERTICAL) - layout->SetWidth(m_channelWidth); - else - layout->SetHeight(m_channelHeight); - item->SetLayout(layout); + /* first ruler marker starts before current view */ + int startBlock = rulerOffset - 1; + + while (startBlock % m_rulerUnit != 0) + startBlock--; + + int missingSection = rulerOffset - startBlock; + + pos -= missingSection * m_blockSize; } - if (item->GetLayout()) + while (pos < end && (rulerOffset/m_rulerUnit+1) < (int)m_rulerItems.size()) { - CDirtyRegionList dirtyRegions; - item->GetLayout()->Process(item.get(),m_parentID,m_renderTime,dirtyRegions); - item->GetLayout()->Render(item.get(), m_parentID); + item = m_rulerItems[rulerOffset/m_rulerUnit+1]; + if (m_orientation == VERTICAL) + { + ProcessItem(pos, originRuler.y, item.get(), lastitem, false, m_rulerLayout, m_rulerLayout, currentTime, dirtyregions, m_rulerWidth); + pos += m_rulerWidth; + } + else + { + ProcessItem(originRuler.x, pos, item.get(), lastitem, false, m_rulerLayout, m_rulerLayout, currentTime, dirtyregions, m_rulerWidth); + pos += m_rulerHeight; + } + rulerOffset += m_rulerUnit; } - g_graphicsContext.RestoreOrigin(); +} - int cacheBeforeRuler, cacheAfterRuler; - GetRulerCacheOffsets(cacheBeforeRuler, cacheAfterRuler); +void CGUIEPGGridContainer::RenderRuler() +{ + if (!m_rulerLayout || m_rulerItems.size()<=1 || (m_gridEnd - m_gridStart) == CDateTimeSpan(0, 0, 0, 0)) + return; + + int rulerOffset = (int)floorf(m_programmeScrollOffset / m_blockSize); + /// Render single ruler item with date of selected programme + g_graphicsContext.SetClipRegion(m_posX, m_posY, m_width, m_height); + CGUIListItemPtr item = m_rulerItems[0]; + RenderItem(m_posX, m_posY, item.get(), false); g_graphicsContext.RestoreClipRegion(); - // Free memory not used on screen - if ((int)m_rulerItems.size() > m_blocksPerPage + cacheBeforeRuler + cacheAfterRuler) - FreeRulerMemory(CorrectOffset(rulerOffset - cacheBeforeRuler, 0), CorrectOffset(rulerOffset + m_blocksPerPage + 1 + cacheAfterRuler, 0)); + // render ruler items + int cacheBeforeRuler, cacheAfterRuler; + GetProgrammeCacheOffsets(cacheBeforeRuler, cacheAfterRuler); if (m_orientation == VERTICAL) g_graphicsContext.SetClipRegion(m_rulerPosX, m_rulerPosY, m_gridWidth, m_rulerHeight); @@ -228,9 +316,9 @@ void CGUIEPGGridContainer::Render() g_graphicsContext.SetClipRegion(m_rulerPosX, m_rulerPosY, m_rulerWidth, m_gridHeight); CPoint originRuler = CPoint(m_rulerPosX, m_rulerPosY) + m_renderOffset; - pos = (m_orientation == VERTICAL) ? originRuler.x : originRuler.y; - end = (m_orientation == VERTICAL) ? m_posX + m_width : m_posY + m_height; - drawOffset = (rulerOffset - cacheBeforeRuler) * m_blockSize - m_programmeScrollOffset; + float pos = (m_orientation == VERTICAL) ? originRuler.x : originRuler.y; + float end = (m_orientation == VERTICAL) ? m_posX + m_width : m_posY + m_height; + float drawOffset = (rulerOffset - cacheBeforeRuler) * m_blockSize - m_programmeScrollOffset; pos += drawOffset; end += cacheAfterRuler * m_rulerLayout->Size(m_orientation == VERTICAL ? HORIZONTAL : VERTICAL); @@ -251,44 +339,112 @@ void CGUIEPGGridContainer::Render() item = m_rulerItems[rulerOffset/m_rulerUnit+1]; if (m_orientation == VERTICAL) { - g_graphicsContext.SetOrigin(pos, originRuler.y); + RenderItem(pos, originRuler.y, item.get(), false); pos += m_rulerWidth; } else { - g_graphicsContext.SetOrigin(originRuler.x, pos); + RenderItem(originRuler.x, pos, item.get(), false); pos += m_rulerHeight; } - if (!item->GetLayout()) + rulerOffset += m_rulerUnit; + } + g_graphicsContext.RestoreClipRegion(); +} + +void CGUIEPGGridContainer::ProcessProgrammeGrid(unsigned int currentTime, CDirtyRegionList &dirtyregions) +{ + if (!m_focusedProgrammeLayout || !m_programmeLayout || m_rulerItems.size()<=1 || (m_gridEnd - m_gridStart) == CDateTimeSpan(0, 0, 0, 0)) + return; + + int blockOffset = (int)floorf(m_programmeScrollOffset / m_blockSize); + int chanOffset = (int)floorf(m_channelScrollOffset / m_programmeLayout->Size(m_orientation)); + + int cacheBeforeProgramme, cacheAfterProgramme; + GetProgrammeCacheOffsets(cacheBeforeProgramme, cacheAfterProgramme); + + CPoint originProgramme = CPoint(m_gridPosX, m_gridPosY) + m_renderOffset; + float posA = (m_orientation != VERTICAL) ? originProgramme.y : originProgramme.x; + float endA = (m_orientation != VERTICAL) ? m_posY + m_height : m_posX + m_width; + float posB = (m_orientation == VERTICAL) ? originProgramme.y : originProgramme.x; + float endB = (m_orientation == VERTICAL) ? m_gridPosY + m_gridHeight : m_posX + m_width; + endA += cacheAfterProgramme * m_blockSize; + + float DrawOffsetA = blockOffset * m_blockSize - m_programmeScrollOffset; + posA += DrawOffsetA; + float DrawOffsetB = (chanOffset - cacheBeforeProgramme) * m_channelLayout->Size(m_orientation) - m_channelScrollOffset; + posB += DrawOffsetB; + + int channel = chanOffset; + + while (posB < endB && m_channelItems.size()) + { + if (channel >= (int)m_channelItems.size()) + break; + + // Free memory not used on screen + FreeProgrammeMemory(channel, CorrectOffset(blockOffset - cacheBeforeProgramme, 0), CorrectOffset(blockOffset + m_ProgrammesPerPage + 1 + cacheAfterProgramme, 0)); + + int block = blockOffset; + float posA2 = posA; + + CGUIListItemPtr item = m_gridIndex[channel][block].item; + if (blockOffset > 0 && item == m_gridIndex[channel][blockOffset-1].item) { - CGUIListItemLayout *layout = new CGUIListItemLayout(*m_rulerLayout); - if (m_orientation == VERTICAL) - layout->SetWidth(m_rulerWidth); - else - layout->SetHeight(m_rulerHeight); + /* first program starts before current view */ + int startBlock = blockOffset - 1; + while (startBlock >= 0 && m_gridIndex[channel][startBlock].item == item) + startBlock--; - item->SetLayout(layout); + block = startBlock + 1; + int missingSection = blockOffset - block; + posA2 -= missingSection * m_blockSize; } - if (item->GetLayout()) + + while (posA2 < endA && m_programmeItems.size()) // FOR EACH ITEM /////////////// { - CDirtyRegionList dirtyRegions; - item->GetLayout()->Process(item.get(),m_parentID,m_renderTime,dirtyRegions); - item->GetLayout()->Render(item.get(), m_parentID); + item = m_gridIndex[channel][block].item; + if (!item || !item.get()->IsFileItem()) + break; + + bool focused = (channel == m_channelOffset + m_channelCursor) && (item == m_gridIndex[m_channelOffset + m_channelCursor][m_blockOffset + m_blockCursor].item); + + if (m_orientation == VERTICAL) + ProcessItem(posA2, posB, item.get(), m_lastChannel, focused, m_programmeLayout, m_focusedProgrammeLayout, currentTime, dirtyregions, m_gridIndex[channel][block].width); + else + ProcessItem(posB, posA2, item.get(), m_lastChannel, focused, m_programmeLayout, m_focusedProgrammeLayout, currentTime, dirtyregions, m_gridIndex[channel][block].height); + + // increment our X position + if (m_orientation == VERTICAL) + { + posA2 += m_gridIndex[channel][block].width; // assumes focused & unfocused layouts have equal length + block += (int)(m_gridIndex[channel][block].width / m_blockSize); + } + else + { + posA2 += m_gridIndex[channel][block].height; // assumes focused & unfocused layouts have equal length + block += (int)(m_gridIndex[channel][block].height / m_blockSize); + } } - g_graphicsContext.RestoreOrigin(); - rulerOffset += m_rulerUnit; + // increment our Y position + channel++; + posB += m_orientation == VERTICAL ? m_channelHeight : m_channelWidth; } - g_graphicsContext.RestoreClipRegion(); +} + +void CGUIEPGGridContainer::RenderProgrammeGrid() +{ + if (!m_focusedProgrammeLayout || !m_programmeLayout || m_rulerItems.size()<=1 || (m_gridEnd - m_gridStart) == CDateTimeSpan(0, 0, 0, 0)) + return; + + int blockOffset = (int)floorf(m_programmeScrollOffset / m_blockSize); + int chanOffset = (int)floorf(m_channelScrollOffset / m_programmeLayout->Size(m_orientation)); /// Render programmes int cacheBeforeProgramme, cacheAfterProgramme; GetProgrammeCacheOffsets(cacheBeforeProgramme, cacheAfterProgramme); - // Free memory not used on screen - if ((int)m_programmeItems.size() > m_ProgrammesPerPage + cacheBeforeProgramme + cacheAfterProgramme) - FreeProgrammeMemory(CorrectOffset(blockOffset - cacheBeforeProgramme, 0), CorrectOffset(blockOffset + m_ProgrammesPerPage + 1 + cacheAfterProgramme, 0)); - g_graphicsContext.SetClipRegion(m_gridPosX, m_gridPosY, m_gridWidth, m_gridHeight); CPoint originProgramme = CPoint(m_gridPosX, m_gridPosY) + m_renderOffset; float posA = (m_orientation != VERTICAL) ? originProgramme.y : originProgramme.x; @@ -306,8 +462,8 @@ void CGUIEPGGridContainer::Render() float focusedPosX = 0; float focusedPosY = 0; - float focusedwidth = 0; - float focusedheight = 0; + float focusedsize = 0; + CGUIListItemPtr focusedItem; while (posB < endB && m_channelItems.size()) { if (channel >= (int)m_channelItems.size()) @@ -351,15 +507,14 @@ void CGUIEPGGridContainer::Render() focusedPosY = posA2; } focusedItem = item; - focusedwidth = m_gridIndex[channel][block].width; - focusedheight = m_gridIndex[channel][block].height; + focusedsize = (m_orientation == VERTICAL ? m_gridIndex[channel][block].width : m_gridIndex[channel][block].height); } else { if (m_orientation == VERTICAL) - RenderProgrammeItem(posA2, posB, m_gridIndex[channel][block].width, m_gridIndex[channel][block].height, item.get(), focused); + RenderItem(posA2, posB, item.get(), focused); else - RenderProgrammeItem(posB, posA2, m_gridIndex[channel][block].width, m_gridIndex[channel][block].height, item.get(), focused); + RenderItem(posB, posA2, item.get(), focused); } // increment our X position @@ -382,16 +537,16 @@ void CGUIEPGGridContainer::Render() // and render the focused item last (for overlapping purposes) if (focusedItem) - RenderProgrammeItem(focusedPosX, focusedPosY, focusedwidth, focusedheight, focusedItem.get(), true); + RenderItem(focusedPosX, focusedPosY, focusedItem.get(), true); g_graphicsContext.RestoreClipRegion(); - - CGUIControl::Render(); } -void CGUIEPGGridContainer::RenderChannelItem(float posX, float posY, CGUIListItem *item, bool focused) +void CGUIEPGGridContainer::ProcessItem(float posX, float posY, CGUIListItem* item, CGUIListItem *&lastitem, + bool focused, CGUIListItemLayout* normallayout, CGUIListItemLayout* focusedlayout, + unsigned int currentTime, CDirtyRegionList &dirtyregions, float resize /* = -1.0f */) { - if (!m_focusedChannelLayout || !m_channelLayout) return; + if (!normallayout || !focusedlayout) return; // set the origin g_graphicsContext.SetOrigin(posX, posY); @@ -402,28 +557,33 @@ void CGUIEPGGridContainer::RenderChannelItem(float posX, float posY, CGUIListIte { if (!item->GetFocusedLayout()) { - CGUIListItemLayout *layout = new CGUIListItemLayout(*m_focusedChannelLayout); + CGUIListItemLayout *layout = new CGUIListItemLayout(*focusedlayout); + if (resize != -1.0f) + { + if (m_orientation == VERTICAL) + layout->SetWidth(resize); + else + layout->SetHeight(resize); + } item->SetFocusedLayout(layout); } if (item->GetFocusedLayout()) { - if (item != m_lastChannel || !HasFocus()) + if (item != lastitem || !HasFocus()) { item->GetFocusedLayout()->SetFocusedItem(0); } - if (item != m_lastChannel && HasFocus()) + if (item != lastitem && HasFocus()) { item->GetFocusedLayout()->ResetAnimation(ANIM_TYPE_UNFOCUS); unsigned int subItem = 1; - if (m_lastChannel && m_lastChannel->GetFocusedLayout()) - subItem = m_lastChannel->GetFocusedLayout()->GetFocusedItem(); + if (lastitem && lastitem->GetFocusedLayout()) + subItem = lastitem->GetFocusedLayout()->GetFocusedItem(); item->GetFocusedLayout()->SetFocusedItem(subItem ? subItem : 1); } - CDirtyRegionList dirtyRegions; - item->GetFocusedLayout()->Process(item,m_parentID,m_renderTime,dirtyRegions); - item->GetFocusedLayout()->Render(item, m_parentID); + item->GetFocusedLayout()->Process(item,m_parentID,currentTime,dirtyregions); } - m_lastChannel = item; + lastitem = item; } else { @@ -431,104 +591,40 @@ void CGUIEPGGridContainer::RenderChannelItem(float posX, float posY, CGUIListIte item->GetFocusedLayout()->SetFocusedItem(0); // focus is not set if (!item->GetLayout()) { - CGUIListItemLayout *layout = new CGUIListItemLayout(*m_channelLayout); + CGUIListItemLayout *layout = new CGUIListItemLayout(*normallayout); + if (resize != -1.0f) + { + if (m_orientation == VERTICAL) + layout->SetWidth(resize); + else + layout->SetHeight(resize); + } item->SetLayout(layout); } if (item->GetFocusedLayout() && item->GetFocusedLayout()->IsAnimating(ANIM_TYPE_UNFOCUS)) - { - CDirtyRegionList dirtyRegions; - item->GetFocusedLayout()->Process(item,m_parentID,m_renderTime,dirtyRegions); - item->GetFocusedLayout()->Render(item, m_parentID); - } + item->GetFocusedLayout()->Process(item,m_parentID,currentTime,dirtyregions); else if (item->GetLayout()) - { - CDirtyRegionList dirtyRegions; - item->GetLayout()->Process(item,m_parentID,m_renderTime,dirtyRegions); - item->GetLayout()->Render(item, m_parentID); - } + item->GetLayout()->Process(item,m_parentID,currentTime,dirtyregions); } g_graphicsContext.RestoreOrigin(); } -void CGUIEPGGridContainer::RenderProgrammeItem(float posX, float posY, float width, float height, CGUIListItem *item, bool focused) +void CGUIEPGGridContainer::RenderItem(float posX, float posY, CGUIListItem *item, bool focused) { - if (!m_focusedProgrammeLayout || !m_programmeLayout) return; - // set the origin g_graphicsContext.SetOrigin(posX, posY); - if (m_bInvalidated) - item->SetInvalid(); if (focused) { - if (!item->GetFocusedLayout()) - { - CGUIListItemLayout *layout = new CGUIListItemLayout(*m_focusedProgrammeLayout); - CFileItem *fileItem = item->IsFileItem() ? (CFileItem *)item : NULL; - if (fileItem) - { - const CEpgInfoTag* tag = fileItem->GetEPGInfoTag(); - if (m_orientation == VERTICAL) - layout->SetWidth(width); - else - layout->SetHeight(height); - - item->SetProperty("GenreType", tag->GenreType()); - } - item->SetFocusedLayout(layout); - } if (item->GetFocusedLayout()) - { - if (item != m_lastItem || !HasFocus()) - { - item->GetFocusedLayout()->SetFocusedItem(0); - } - if (item != m_lastItem && HasFocus()) - { - item->GetFocusedLayout()->ResetAnimation(ANIM_TYPE_UNFOCUS); - unsigned int subItem = 1; - if (m_lastItem && m_lastItem->GetFocusedLayout()) - subItem = m_lastItem->GetFocusedLayout()->GetFocusedItem(); - item->GetFocusedLayout()->SetFocusedItem(subItem ? subItem : 1); - } - CDirtyRegionList dirtyRegions; - item->GetFocusedLayout()->Process(item,m_parentID,m_renderTime,dirtyRegions); item->GetFocusedLayout()->Render(item, m_parentID); - } - m_lastItem = item; } else { - if (item->GetFocusedLayout()) - item->GetFocusedLayout()->SetFocusedItem(0); // focus is not set - if (!item->GetLayout()) - { - CGUIListItemLayout *layout = new CGUIListItemLayout(*m_programmeLayout); - CFileItem *fileItem = item->IsFileItem() ? (CFileItem *)item : NULL; - if (fileItem) - { - const CEpgInfoTag* tag = fileItem->GetEPGInfoTag(); - if (m_orientation == VERTICAL) - layout->SetWidth(width); - else - layout->SetHeight(height); - - item->SetProperty("GenreType", tag->GenreType()); - } - item->SetLayout(layout); - } if (item->GetFocusedLayout() && item->GetFocusedLayout()->IsAnimating(ANIM_TYPE_UNFOCUS)) - { - CDirtyRegionList dirtyRegions; - item->GetFocusedLayout()->Process(item,m_parentID,m_renderTime,dirtyRegions); item->GetFocusedLayout()->Render(item, m_parentID); - } else if (item->GetLayout()) - { - CDirtyRegionList dirtyRegions; - item->GetLayout()->Process(item,m_parentID,m_renderTime,dirtyRegions); item->GetLayout()->Render(item, m_parentID); - } } g_graphicsContext.RestoreOrigin(); } @@ -1204,10 +1300,10 @@ CGUIListItemLayout *CGUIEPGGridContainer::GetFocusedLayout() const return NULL; } -bool CGUIEPGGridContainer::SelectItemFromPoint(const CPoint &point) +bool CGUIEPGGridContainer::SelectItemFromPoint(const CPoint &point, bool justGrid /* = false */) { /* point has already had origin set to m_posX, m_posY */ - if (!m_focusedProgrammeLayout || !m_programmeLayout) + if (!m_focusedProgrammeLayout || !m_programmeLayout || (justGrid && point.x < 0)) return false; int channel = (int)(point.y / m_channelHeight); @@ -1219,6 +1315,10 @@ bool CGUIEPGGridContainer::SelectItemFromPoint(const CPoint &point) if (block > m_blocksPerPage) block = m_blocksPerPage - 1; if (block < 0) block = 0; + // bail if block isn't occupied + if (!m_gridIndex[channel + m_channelOffset][block + m_blockOffset].item) + return false; + SetChannel(channel); SetBlock(block); return true; @@ -1243,6 +1343,40 @@ EVENT_RESULT CGUIEPGGridContainer::OnMouseEvent(const CPoint &point, const CMous case ACTION_MOUSE_WHEEL_DOWN: OnMouseWheel(1, point); return EVENT_RESULT_HANDLED; + case ACTION_GESTURE_BEGIN: + { + // we want exclusive access + CGUIMessage msg(GUI_MSG_EXCLUSIVE_MOUSE, GetID(), GetParentID()); + SendWindowMessage(msg); + return EVENT_RESULT_HANDLED; + } + case ACTION_GESTURE_END: + { + // we're done with exclusive access + CGUIMessage msg(GUI_MSG_EXCLUSIVE_MOUSE, 0, GetParentID()); + SendWindowMessage(msg); + ScrollToChannelOffset(MathUtils::round_int(m_channelScrollOffset / m_channelLayout->Size(m_orientation))); + ScrollToBlockOffset(MathUtils::round_int(m_programmeScrollOffset / m_blockSize)); + return EVENT_RESULT_HANDLED; + } + case ACTION_GESTURE_PAN: + { + if (m_orientation == VERTICAL) + { + m_programmeScrollOffset -= event.m_offsetX; + m_channelScrollOffset -= event.m_offsetY; + } + else + { + m_channelScrollOffset -= event.m_offsetX; + m_programmeScrollOffset -= event.m_offsetY; + } + + m_channelOffset = MathUtils::round_int(m_channelScrollOffset / m_channelLayout->Size(m_orientation)); + m_blockOffset = MathUtils::round_int(m_programmeScrollOffset / m_blockSize); + ValidateOffset(); + return EVENT_RESULT_HANDLED; + } default: return EVENT_RESULT_UNHANDLED; } @@ -1251,7 +1385,7 @@ EVENT_RESULT CGUIEPGGridContainer::OnMouseEvent(const CPoint &point, const CMous bool CGUIEPGGridContainer::OnMouseOver(const CPoint &point) { // select the item under the pointer - SelectItemFromPoint(point - CPoint(m_gridPosX, m_posY + m_rulerHeight)); + SelectItemFromPoint(point - CPoint(m_gridPosX, m_posY + m_rulerHeight), false); return CGUIControl::OnMouseOver(point); } @@ -1528,25 +1662,25 @@ void CGUIEPGGridContainer::ValidateOffset() if (!m_programmeLayout) return; - if (m_channelOffset > m_channels - m_channelsPerPage) + if (m_channelOffset > m_channels - m_channelsPerPage || m_channelScrollOffset > (m_channels - m_channelsPerPage) * m_channelHeight) { m_channelOffset = m_channels - m_channelsPerPage; m_channelScrollOffset = m_channelOffset * m_channelHeight; } - if (m_channelOffset < 0) + if (m_channelOffset < 0 || m_channelScrollOffset < 0) { m_channelOffset = 0; m_channelScrollOffset = 0; } - if (m_blockOffset > m_blocks - m_blocksPerPage) + if (m_blockOffset > m_blocks - m_blocksPerPage || m_programmeScrollOffset > (m_blocks - m_blocksPerPage) * m_blockSize) { m_blockOffset = m_blocks - m_blocksPerPage; m_programmeScrollOffset = m_blockOffset * m_blockSize; } - if (m_blockOffset < 0) + if (m_blockOffset < 0 || m_programmeScrollOffset < 0) { m_blockOffset = 0; m_programmeScrollOffset = 0; @@ -1758,25 +1892,25 @@ void CGUIEPGGridContainer::CalculateLayout() m_programmeScrollOffset = m_blockOffset * m_blockSize; } -void CGUIEPGGridContainer::UpdateScrollOffset() +void CGUIEPGGridContainer::UpdateScrollOffset(unsigned int currentTime) { - m_channelScrollOffset += m_channelScrollSpeed * (m_renderTime - m_channelScrollLastTime); + m_channelScrollOffset += m_channelScrollSpeed * (currentTime - m_channelScrollLastTime); if ((m_channelScrollSpeed < 0 && m_channelScrollOffset < m_channelOffset * m_programmeLayout->Size(m_orientation)) || (m_channelScrollSpeed > 0 && m_channelScrollOffset > m_channelOffset * m_programmeLayout->Size(m_orientation))) { m_channelScrollOffset = m_channelOffset * m_programmeLayout->Size(m_orientation); m_channelScrollSpeed = 0; } - m_channelScrollLastTime = m_renderTime; + m_channelScrollLastTime = currentTime; - m_programmeScrollOffset += m_programmeScrollSpeed * (m_renderTime - m_programmeScrollLastTime); + m_programmeScrollOffset += m_programmeScrollSpeed * (currentTime - m_programmeScrollLastTime); if ((m_programmeScrollSpeed < 0 && m_programmeScrollOffset < m_blockOffset * m_blockSize) || (m_programmeScrollSpeed > 0 && m_programmeScrollOffset > m_blockOffset * m_blockSize)) { m_programmeScrollOffset = m_blockOffset * m_blockSize; m_programmeScrollSpeed = 0; } - m_programmeScrollLastTime = m_renderTime; + m_programmeScrollLastTime = currentTime; } void CGUIEPGGridContainer::GetCurrentLayouts() @@ -1868,30 +2002,42 @@ void CGUIEPGGridContainer::FreeChannelMemory(int keepStart, int keepEnd) } } -void CGUIEPGGridContainer::FreeProgrammeMemory(int keepStart, int keepEnd) +void CGUIEPGGridContainer::FreeProgrammeMemory(int channel, int keepStart, int keepEnd) { if (keepStart < keepEnd) { // remove before keepStart and after keepEnd - for (unsigned int i = 0; i < m_epgItemsPtr.size(); i++) + if (keepStart > 0 && keepStart < m_blocks) { - unsigned long progIdx = m_epgItemsPtr[i].start; - unsigned long lastIdx = m_epgItemsPtr[i].stop; - - for (unsigned int j = progIdx; j < keepStart+progIdx && j < lastIdx; ++j) - m_programmeItems[j]->FreeMemory(); - for (unsigned int j = keepEnd+progIdx + 1; j < lastIdx; ++j) - m_programmeItems[j]->FreeMemory(); + // if item exist and block is not part of visible item + CGUIListItemPtr last = m_gridIndex[channel][keepStart].item; + for (int i = keepStart - 1 ; i > 0 ; i--) + { + if (m_gridIndex[channel][i].item && m_gridIndex[channel][i].item != last) + { + m_gridIndex[channel][i].item->FreeMemory(); + // FreeMemory() is smart enough to not cause any problems when called multiple times on same item + // but we can make use of condition needed to not call FreeMemory() on item that is partially visible + // to avoid calling FreeMemory() multiple times on item that ocupy few blocks in a row + last = m_gridIndex[channel][i].item; + } + } } - } - else - { // wrapping - for (unsigned int i = 0; i < m_epgItemsPtr.size(); i++) - { - unsigned long progIdx = m_epgItemsPtr[i].start; - unsigned long lastIdx = m_epgItemsPtr[i].stop; - for (unsigned int j = keepEnd+progIdx + 1; j < keepStart+progIdx && j < lastIdx; ++j) - m_programmeItems[j]->FreeMemory(); + if (keepEnd > 0 && keepEnd < m_blocks) + { + CGUIListItemPtr last = m_gridIndex[channel][keepEnd].item; + for (int i = keepEnd + 1 ; i < m_blocks ; i++) + { + // if item exist and block is not part of visible item + if (m_gridIndex[channel][i].item && m_gridIndex[channel][i].item != last) + { + m_gridIndex[channel][i].item->FreeMemory(); + // FreeMemory() is smart enough to not cause any problems when called multiple times on same item + // but we can make use of condition needed to not call FreeMemory() on item that is partially visible + // to avoid calling FreeMemory() multiple times on item that ocupy few blocks in a row + last = m_gridIndex[channel][i].item; + } + } } } } @@ -1953,22 +2099,3 @@ void CGUIEPGGridContainer::GetProgrammeCacheOffsets(int &cacheBefore, int &cache cacheAfter = m_cacheProgrammeItems / 2; } } - -void CGUIEPGGridContainer::GetRulerCacheOffsets(int &cacheBefore, int &cacheAfter) -{ - if (m_programmeScrollSpeed > 0) - { - cacheBefore = 0; - cacheAfter = m_cacheRulerItems; - } - else if (m_programmeScrollSpeed < 0) - { - cacheBefore = m_cacheRulerItems; - cacheAfter = 0; - } - else - { - cacheBefore = m_cacheRulerItems / 2; - cacheAfter = m_cacheRulerItems / 2; - } -} diff --git a/xbmc/epg/GUIEPGGridContainer.h b/xbmc/epg/GUIEPGGridContainer.h index c9e3d2edf5..9a59195acd 100644 --- a/xbmc/epg/GUIEPGGridContainer.h +++ b/xbmc/epg/GUIEPGGridContainer.h @@ -98,7 +98,7 @@ namespace EPG protected: bool OnClick(int actionID); - bool SelectItemFromPoint(const CPoint &point); + bool SelectItemFromPoint(const CPoint &point, bool justGrid = true); void UpdateItems(); @@ -128,11 +128,18 @@ namespace EPG void ScrollToBlockOffset(int offset); void ScrollToChannelOffset(int offset); - void UpdateScrollOffset(); - void RenderChannelItem(float posX, float posY, CGUIListItem *item, bool focused); - void RenderProgrammeItem(float posX, float posY, float width, float height, CGUIListItem *item, bool focused); + void UpdateScrollOffset(unsigned int currentTime); + void ProcessItem(float posX, float posY, CGUIListItem *item, CGUIListItem *&lastitem, bool focused, CGUIListItemLayout* normallayout, CGUIListItemLayout* focusedlayout, unsigned int currentTime, CDirtyRegionList &dirtyregions, float resize = -1.0f); + void RenderItem(float posX, float posY, CGUIListItem *item, bool focused); void GetCurrentLayouts(); + void ProcessChannels(unsigned int currentTime, CDirtyRegionList &dirtyregions); + void ProcessRuler(unsigned int currentTime, CDirtyRegionList &dirtyregions); + void ProcessProgrammeGrid(unsigned int currentTime, CDirtyRegionList &dirtyregions); + void RenderChannels(); + void RenderRuler(); + void RenderProgrammeGrid(); + CPoint m_renderOffset; ///< \brief render offset of the first item in the list \sa SetRenderOffset ORIENTATION m_orientation; @@ -166,12 +173,11 @@ namespace EPG // changing around) void FreeChannelMemory(int keepStart, int keepEnd); - void FreeProgrammeMemory(int keepStart, int keepEnd); + void FreeProgrammeMemory(int channel, int keepStart, int keepEnd); void FreeRulerMemory(int keepStart, int keepEnd); void GetChannelCacheOffsets(int &cacheBefore, int &cacheAfter); void GetProgrammeCacheOffsets(int &cacheBefore, int &cacheAfter); - void GetRulerCacheOffsets(int &cacheBefore, int &cacheAfter); private: int m_rulerUnit; //! number of blocks that makes up one element of the ruler @@ -211,8 +217,6 @@ namespace EPG CGUIListItem *m_lastItem; CGUIListItem *m_lastChannel; - unsigned int m_renderTime; - int m_scrollTime; bool m_gridWrapAround; //! only when no more data available should this be true diff --git a/xbmc/filesystem/AFPFile.cpp b/xbmc/filesystem/AFPFile.cpp index 05d17dd55f..921e350e67 100644 --- a/xbmc/filesystem/AFPFile.cpp +++ b/xbmc/filesystem/AFPFile.cpp @@ -30,7 +30,6 @@ #include "AFPDirectory.h" #include "Util.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" #include "threads/SingleLock.h" #include "utils/log.h" #include "utils/TimeUtils.h" diff --git a/xbmc/filesystem/CurlFile.cpp b/xbmc/filesystem/CurlFile.cpp index 80c1837ebb..04018086a1 100644 --- a/xbmc/filesystem/CurlFile.cpp +++ b/xbmc/filesystem/CurlFile.cpp @@ -23,9 +23,10 @@ #include "Util.h" #include "URL.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "File.h" +#include <map> #include <vector> #include <climits> @@ -42,9 +43,12 @@ #include "SpecialProtocol.h" #include "utils/CharsetConverter.h" #include "utils/log.h" +#include "utils/TimeUtils.h" +using namespace std; using namespace XFILE; using namespace XCURL; +using namespace XbmcThreads; #define XMIN(a,b) ((a)<(b)?(a):(b)) #define FITS_INT(a) (((a) <= INT_MAX) && ((a) >= INT_MIN)) @@ -60,14 +64,16 @@ curl_proxytype proxyType2CUrlProxyType[] = { CURLPROXY_SOCKS5_HOSTNAME, }; +static CCriticalSection s_hostMapLock; +static map<string, EndTime> s_hostLastAccessTime; // used to rate-limit queries by host/domain + // curl calls this routine to debug extern "C" int debug_callback(CURL_HANDLE *handle, curl_infotype info, char *output, size_t size, void *data) { if (info == CURLINFO_DATA_IN || info == CURLINFO_DATA_OUT) return 0; - // Only shown cURL debug into with loglevel DEBUG_SAMBA or higher - if( g_advancedSettings.m_logLevel < LOG_LEVEL_DEBUG_SAMBA ) + if ((g_advancedSettings.m_extraLogLevels & LOGCURL) == 0) return 0; CStdString strLine; @@ -376,6 +382,7 @@ void CCurlFile::CReadState::Disconnect() CCurlFile::~CCurlFile() { + CSingleLock lock(s_hostMapLock); Close(); delete m_state; delete m_oldState; @@ -474,7 +481,7 @@ void CCurlFile::SetCommonOptions(CReadState* state) // Enable cookie engine for current handle to re-use them in future requests CStdString strCookieFile; CStdString strTempPath = CSpecialProtocol::TranslatePath(g_advancedSettings.m_cachePath); - URIUtils::AddFileToFolder(strTempPath, "cookies.dat", strCookieFile); + strCookieFile = URIUtils::AddFileToFolder(strTempPath, "cookies.dat"); g_curlInterface.easy_setopt(h, CURLOPT_COOKIEFILE, strCookieFile.c_str()); g_curlInterface.easy_setopt(h, CURLOPT_COOKIEJAR, strCookieFile.c_str()); @@ -723,19 +730,19 @@ void CCurlFile::ParseAndCorrectUrl(CURL &url2) else if( strProtocol.Equals("http") || strProtocol.Equals("https")) { - if (g_guiSettings.GetBool("network.usehttpproxy") - && !g_guiSettings.GetString("network.httpproxyserver").empty() - && !g_guiSettings.GetString("network.httpproxyport").empty() + if (CSettings::Get().GetBool("network.usehttpproxy") + && !CSettings::Get().GetString("network.httpproxyserver").empty() + && !CSettings::Get().GetString("network.httpproxyport").empty() && m_proxy.IsEmpty()) { - m_proxy = g_guiSettings.GetString("network.httpproxyserver"); - m_proxy += ":" + g_guiSettings.GetString("network.httpproxyport"); - if (g_guiSettings.GetString("network.httpproxyusername").length() > 0 && m_proxyuserpass.IsEmpty()) + m_proxy = CSettings::Get().GetString("network.httpproxyserver"); + m_proxy += ":" + CSettings::Get().GetString("network.httpproxyport"); + if (CSettings::Get().GetString("network.httpproxyusername").length() > 0 && m_proxyuserpass.IsEmpty()) { - m_proxyuserpass = g_guiSettings.GetString("network.httpproxyusername"); - m_proxyuserpass += ":" + g_guiSettings.GetString("network.httpproxypassword"); + m_proxyuserpass = CSettings::Get().GetString("network.httpproxyusername"); + m_proxyuserpass += ":" + CSettings::Get().GetString("network.httpproxypassword"); } - m_proxytype = (ProxyType)g_guiSettings.GetInt("network.httpproxytype"); + m_proxytype = (ProxyType)CSettings::Get().GetInt("network.httpproxytype"); CLog::Log(LOGDEBUG, "Using proxy %s, type %d", m_proxy.c_str(), proxyType2CUrlProxyType[m_proxytype]); } @@ -889,17 +896,38 @@ void CCurlFile::Reset() bool CCurlFile::Open(const CURL& url) { m_opened = true; + m_seekable = true; CURL url2(url); ParseAndCorrectUrl(url2); + map<string, EndTime>::iterator it; + + // Rate-limit queries per domain to 1 per 2s + CSingleLock lock(s_hostMapLock); + it = s_hostLastAccessTime.find(url2.GetHostName()); + if (it != s_hostLastAccessTime.end()) + { + EndTime endTime = it->second; + if (endTime.IsTimePast()) { + CLog::Log(LOGDEBUG, "CurlFile::Open(%p) rate limiting queries to '%s' to avoid saturating, waiting %dmsec", (void*)this, url2.GetHostName().c_str(), endTime.MillisLeft()); + lock.Leave(); + Sleep(endTime.MillisLeft()); + lock.Enter(); + } + it = s_hostLastAccessTime.find(url2.GetHostName()); + if (it != s_hostLastAccessTime.end()) + s_hostLastAccessTime.erase(it); + } + s_hostLastAccessTime.insert(make_pair(url2.GetHostName(), EndTime(2000))); + lock.Leave(); + CLog::Log(LOGDEBUG, "CurlFile::Open(%p) %s", (void*)this, m_url.c_str()); ASSERT(!(!m_state->m_easyHandle ^ !m_state->m_multiHandle)); if( m_state->m_easyHandle == NULL ) g_curlInterface.easy_aquire(url2.GetProtocol(), url2.GetHostName(), &m_state->m_easyHandle, &m_state->m_multiHandle ); - m_seekable = true; // setup common curl options SetCommonOptions(m_state); SetRequestHeaders(m_state); diff --git a/xbmc/filesystem/Directory.cpp b/xbmc/filesystem/Directory.cpp index dac2e7ac32..9235fec03b 100644 --- a/xbmc/filesystem/Directory.cpp +++ b/xbmc/filesystem/Directory.cpp @@ -24,7 +24,7 @@ #include "commons/Exception.h" #include "FileItem.h" #include "DirectoryCache.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "utils/log.h" #include "utils/Job.h" #include "utils/JobManager.h" @@ -209,7 +209,7 @@ bool CDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items, c // TODO: we shouldn't be checking the gui setting here; // callers should use getHidden instead if ((!item->m_bIsFolder && !pDirectory->IsAllowed(item->GetPath())) || - (item->GetProperty("file:hidden").asBoolean() && !(hints.flags & DIR_FLAG_GET_HIDDEN) && !g_guiSettings.GetBool("filelists.showhidden"))) + (item->GetProperty("file:hidden").asBoolean() && !(hints.flags & DIR_FLAG_GET_HIDDEN) && !CSettings::Get().GetBool("filelists.showhidden"))) { items.Remove(i); i--; // don't confuse loop @@ -302,7 +302,7 @@ void CDirectory::FilterFileDirectories(CFileItemList &items, const CStdString &m for (int i=0; i< items.Size(); ++i) { CFileItemPtr pItem=items[i]; - if ((!pItem->m_bIsFolder) && (!pItem->IsInternetStream())) + if (!pItem->m_bIsFolder && pItem->IsFileFolder(EFILEFOLDER_TYPE_ALWAYS)) { auto_ptr<IFileDirectory> pDirectory(CFileDirectoryFactory::Create(pItem->GetPath(),pItem.get(),mask)); if (pDirectory.get()) diff --git a/xbmc/filesystem/FileDirectoryFactory.cpp b/xbmc/filesystem/FileDirectoryFactory.cpp index e6daf38c5e..a6c80711e1 100644 --- a/xbmc/filesystem/FileDirectoryFactory.cpp +++ b/xbmc/filesystem/FileDirectoryFactory.cpp @@ -28,6 +28,7 @@ #include "NSFFileDirectory.h" #include "SIDFileDirectory.h" #include "ASAPFileDirectory.h" +#include "UDFDirectory.h" #include "RSSDirectory.h" #include "cores/paplayer/ASAPCodec.h" #endif @@ -113,6 +114,9 @@ IFileDirectory* CFileDirectoryFactory::Create(const CStdString& strPath, CFileIt if (pItem->IsRSS()) return new CRSSDirectory(); + if (pItem->IsDVDImage()) + return new CUDFDirectory(); + #endif #if defined(TARGET_ANDROID) if (strExtension.Equals(".apk")) @@ -224,7 +228,7 @@ IFileDirectory* CFileDirectoryFactory::Create(const CStdString& strPath, CFileIt IFileDirectory* pDir=new CSmartPlaylistDirectory; return pDir; // treat as directory } - if (g_advancedSettings.m_playlistAsFolders && CPlayListFactory::IsPlaylist(strPath)) + if (CPlayListFactory::IsPlaylist(strPath)) { // Playlist file // currently we only return the directory if it contains // more than one file. Reason is that .pls and .m3u may be used diff --git a/xbmc/filesystem/HTSPDirectory.cpp b/xbmc/filesystem/HTSPDirectory.cpp index 8331cf9a30..87d307d121 100644 --- a/xbmc/filesystem/HTSPDirectory.cpp +++ b/xbmc/filesystem/HTSPDirectory.cpp @@ -22,7 +22,7 @@ #include "HTSPDirectory.h" #include "URL.h" #include "FileItem.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "guilib/LocalizeStrings.h" #include "cores/dvdplayer/DVDInputStreams/DVDInputStreamHTSP.h" #include "threads/SingleLock.h" @@ -391,12 +391,12 @@ bool CHTSPDirectory::GetChannels( const CURL &base items.AddSortMethod(SORT_METHOD_TRACKNUM, 554, LABEL_MASKS("%K[ - %B]", "%Z", "%L", "")); - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) items.AddSortMethod(SORT_METHOD_ALBUM_IGNORE_THE, 558, LABEL_MASKS("%B", "%Z", "%L", "")); else items.AddSortMethod(SORT_METHOD_ALBUM, 558, LABEL_MASKS("%B", "%Z", "%L", "")); - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) items.AddSortMethod(SORT_METHOD_LABEL_IGNORE_THE, 551, LABEL_MASKS("%Z", "%B", "%L", "")); else items.AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS("%Z", "%B", "%L", "")); diff --git a/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeArtist.cpp b/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeArtist.cpp index 2bbc6c705a..5ce4974242 100644 --- a/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeArtist.cpp +++ b/xbmc/filesystem/MusicDatabaseDirectory/DirectoryNodeArtist.cpp @@ -21,7 +21,7 @@ #include "DirectoryNodeArtist.h" #include "QueryParams.h" #include "music/MusicDatabase.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" using namespace XFILE::MUSICDATABASEDIRECTORY; @@ -55,7 +55,7 @@ bool CDirectoryNodeArtist::GetContent(CFileItemList& items) const CQueryParams params; CollectQueryParams(params); - bool bSuccess = musicdatabase.GetArtistsNav(BuildPath(), items, !g_guiSettings.GetBool("musiclibrary.showcompilationartists"), params.GetGenreId()); + bool bSuccess = musicdatabase.GetArtistsNav(BuildPath(), items, !CSettings::Get().GetBool("musiclibrary.showcompilationartists"), params.GetGenreId()); musicdatabase.Close(); diff --git a/xbmc/filesystem/MusicDatabaseFile.cpp b/xbmc/filesystem/MusicDatabaseFile.cpp index a6a2d45582..a4c84346cb 100644 --- a/xbmc/filesystem/MusicDatabaseFile.cpp +++ b/xbmc/filesystem/MusicDatabaseFile.cpp @@ -54,7 +54,7 @@ CStdString CMusicDatabaseFile::TranslateUrl(const CURL& url) long idSong=atol(strFileName.c_str()); CSong song; - if (!musicDatabase.GetSongById(idSong, song)) + if (!musicDatabase.GetSong(idSong, song)) return ""; CStdString strExtensionFromDb; diff --git a/xbmc/filesystem/MythDirectory.cpp b/xbmc/filesystem/MythDirectory.cpp index e0ce987224..5e234770cc 100644 --- a/xbmc/filesystem/MythDirectory.cpp +++ b/xbmc/filesystem/MythDirectory.cpp @@ -24,8 +24,8 @@ #include "DllLibCMyth.h" #include "video/VideoInfoTag.h" #include "URL.h" -#include "settings/GUISettings.h" #include "settings/AdvancedSettings.h" +#include "settings/Settings.h" #include "FileItem.h" #include "utils/StringUtils.h" #include "guilib/LocalizeStrings.h" @@ -326,7 +326,7 @@ bool CMythDirectory::GetRecordings(const CStdString& base, CFileItemList &items, */ if (type != TV_SHOWS) { - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) items.AddSortMethod(SORT_METHOD_VIDEO_SORT_TITLE_IGNORE_THE, 556, LABEL_MASKS("%K", "%J")); else items.AddSortMethod(SORT_METHOD_VIDEO_SORT_TITLE, 556, LABEL_MASKS("%K", "%J")); @@ -392,7 +392,7 @@ bool CMythDirectory::GetTvShowFolders(const CStdString& base, CFileItemList &ite } m_dll->ref_release(list); - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) items.AddSortMethod(SORT_METHOD_LABEL_IGNORE_THE, 551 /* Name */, LABEL_MASKS("", "", "%L", "%J")); else items.AddSortMethod(SORT_METHOD_LABEL, 551 /* Name */, LABEL_MASKS("", "", "%L", "%J")); @@ -469,7 +469,7 @@ bool CMythDirectory::GetChannels(const CStdString& base, CFileItemList &items) /* * Video sort title is set to the channel number. */ - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) items.AddSortMethod(SORT_METHOD_VIDEO_SORT_TITLE_IGNORE_THE, 556 /* Title */, LABEL_MASKS("%K", "%B")); else items.AddSortMethod(SORT_METHOD_VIDEO_SORT_TITLE, 556 /* Title */, LABEL_MASKS("%K", "%B")); diff --git a/xbmc/filesystem/MythSession.cpp b/xbmc/filesystem/MythSession.cpp index 419b25624f..e669d5ce0a 100644 --- a/xbmc/filesystem/MythSession.cpp +++ b/xbmc/filesystem/MythSession.cpp @@ -373,7 +373,7 @@ CMythSession::CMythSession(const CURL& url) : CThread("MythSession") if (m_dll->IsLoaded()) { m_dll->set_dbg_msgcallback(&CMythSession::LogCMyth); - if (g_advancedSettings.m_logLevel >= LOG_LEVEL_DEBUG_SAMBA) + if (g_advancedSettings.m_extraLogLevels & LOGCMYTH) m_dll->dbg_level(CMYTH_DBG_ALL); else if (g_advancedSettings.m_logLevel >= LOG_LEVEL_DEBUG) m_dll->dbg_level(CMYTH_DBG_DETAIL); diff --git a/xbmc/filesystem/PluginDirectory.cpp b/xbmc/filesystem/PluginDirectory.cpp index aff6c68b29..59e0aa4b3d 100644 --- a/xbmc/filesystem/PluginDirectory.cpp +++ b/xbmc/filesystem/PluginDirectory.cpp @@ -32,7 +32,7 @@ #include "threads/SingleLock.h" #include "guilib/GUIWindowManager.h" #include "dialogs/GUIDialogProgress.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "FileItem.h" #include "video/VideoInfoTag.h" #include "guilib/LocalizeStrings.h" @@ -231,7 +231,7 @@ void CPluginDirectory::AddSortMethod(int handle, SORT_METHOD sortMethod, const C case SORT_METHOD_LABEL: case SORT_METHOD_LABEL_IGNORE_THE: { - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) dir->m_listItems->AddSortMethod(SORT_METHOD_LABEL_IGNORE_THE, 551, LABEL_MASKS("%T", label2Mask)); else dir->m_listItems->AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS("%T", label2Mask)); @@ -240,7 +240,7 @@ void CPluginDirectory::AddSortMethod(int handle, SORT_METHOD sortMethod, const C case SORT_METHOD_TITLE: case SORT_METHOD_TITLE_IGNORE_THE: { - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) dir->m_listItems->AddSortMethod(SORT_METHOD_TITLE_IGNORE_THE, 556, LABEL_MASKS("%T", label2Mask)); else dir->m_listItems->AddSortMethod(SORT_METHOD_TITLE, 556, LABEL_MASKS("%T", label2Mask)); @@ -249,7 +249,7 @@ void CPluginDirectory::AddSortMethod(int handle, SORT_METHOD sortMethod, const C case SORT_METHOD_ARTIST: case SORT_METHOD_ARTIST_IGNORE_THE: { - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) dir->m_listItems->AddSortMethod(SORT_METHOD_ARTIST_IGNORE_THE, 557, LABEL_MASKS("%T", "%A")); else dir->m_listItems->AddSortMethod(SORT_METHOD_ARTIST, 557, LABEL_MASKS("%T", "%A")); @@ -258,7 +258,7 @@ void CPluginDirectory::AddSortMethod(int handle, SORT_METHOD sortMethod, const C case SORT_METHOD_ALBUM: case SORT_METHOD_ALBUM_IGNORE_THE: { - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) dir->m_listItems->AddSortMethod(SORT_METHOD_ALBUM_IGNORE_THE, 558, LABEL_MASKS("%T", "%B")); else dir->m_listItems->AddSortMethod(SORT_METHOD_ALBUM, 558, LABEL_MASKS("%T", "%B")); @@ -327,7 +327,7 @@ void CPluginDirectory::AddSortMethod(int handle, SORT_METHOD sortMethod, const C case SORT_METHOD_VIDEO_SORT_TITLE: case SORT_METHOD_VIDEO_SORT_TITLE_IGNORE_THE: { - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) dir->m_listItems->AddSortMethod(SORT_METHOD_VIDEO_SORT_TITLE_IGNORE_THE, 556, LABEL_MASKS("%T", label2Mask)); else dir->m_listItems->AddSortMethod(SORT_METHOD_VIDEO_SORT_TITLE, 556, LABEL_MASKS("%T", label2Mask)); @@ -346,7 +346,7 @@ void CPluginDirectory::AddSortMethod(int handle, SORT_METHOD sortMethod, const C case SORT_METHOD_STUDIO: case SORT_METHOD_STUDIO_IGNORE_THE: { - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) dir->m_listItems->AddSortMethod(SORT_METHOD_STUDIO_IGNORE_THE, 572, LABEL_MASKS("%T", "%U")); else dir->m_listItems->AddSortMethod(SORT_METHOD_STUDIO, 572, LABEL_MASKS("%T", "%U")); @@ -374,8 +374,8 @@ void CPluginDirectory::AddSortMethod(int handle, SORT_METHOD sortMethod, const C } case SORT_METHOD_PLAYLIST_ORDER: { - CStdString strTrackLeft=g_guiSettings.GetString("musicfiles.trackformat"); - CStdString strTrackRight=g_guiSettings.GetString("musicfiles.trackformatright"); + CStdString strTrackLeft=CSettings::Get().GetString("musicfiles.trackformat"); + CStdString strTrackRight=CSettings::Get().GetString("musicfiles.trackformatright"); dir->m_listItems->AddSortMethod(SORT_METHOD_PLAYLIST_ORDER, 559, LABEL_MASKS(strTrackLeft, strTrackRight)); break; diff --git a/xbmc/filesystem/RSSDirectory.cpp b/xbmc/filesystem/RSSDirectory.cpp index 1c702ae638..dabab2937b 100644 --- a/xbmc/filesystem/RSSDirectory.cpp +++ b/xbmc/filesystem/RSSDirectory.cpp @@ -22,6 +22,8 @@ #include "FileItem.h" #include "CurlFile.h" #include "settings/AdvancedSettings.h" +#include "settings/MediaSettings.h" +#include "settings/Settings.h" #include "utils/URIUtils.h" #include "utils/XBMCTinyXML.h" #include "utils/HTMLUtil.h" @@ -30,7 +32,6 @@ #include "music/tags/MusicInfoTag.h" #include "utils/log.h" #include "URL.h" -#include "settings/GUISettings.h" #include "climits" #include "threads/SingleLock.h" @@ -491,7 +492,7 @@ static void ParseItem(CFileItem* item, TiXmlElement* root, const CStdString& pat else if(FindMime(resources, "image/")) mime = "image/"; - int maxrate = g_guiSettings.GetInt("network.bandwidth"); + int maxrate = CSettings::Get().GetInt("network.bandwidth"); if(maxrate == 0) maxrate = INT_MAX; diff --git a/xbmc/filesystem/RarManager.cpp b/xbmc/filesystem/RarManager.cpp index 501d80184e..81811f54ef 100644 --- a/xbmc/filesystem/RarManager.cpp +++ b/xbmc/filesystem/RarManager.cpp @@ -136,8 +136,8 @@ bool CRarManager::CacheRarredFile(CStdString& strPathInCache, const CStdString& strPath.Replace('/', '\\'); #endif //g_charsetConverter.unknownToUTF8(strPath); - CStdString strCachedPath; - URIUtils::AddFileToFolder(strDir + "rarfolder%04d", URIUtils::GetFileName(strPathInRar), strCachedPath); + CStdString strCachedPath = URIUtils::AddFileToFolder(strDir + "rarfolder%04d", + URIUtils::GetFileName(strPathInRar)); strCachedPath = CUtil::GetNextPathname(strCachedPath, 9999); if (strCachedPath.IsEmpty()) { diff --git a/xbmc/filesystem/ShoutcastFile.cpp b/xbmc/filesystem/ShoutcastFile.cpp index 9f674d280d..5c81be0980 100644 --- a/xbmc/filesystem/ShoutcastFile.cpp +++ b/xbmc/filesystem/ShoutcastFile.cpp @@ -26,7 +26,6 @@ #include "threads/SystemClock.h" #include "system.h" #include "ShoutcastFile.h" -#include "settings/GUISettings.h" #include "guilib/GUIWindowManager.h" #include "URL.h" #include "utils/RegExp.h" diff --git a/xbmc/filesystem/SmartPlaylistDirectory.cpp b/xbmc/filesystem/SmartPlaylistDirectory.cpp index 2c99e2f558..d353fa9101 100644 --- a/xbmc/filesystem/SmartPlaylistDirectory.cpp +++ b/xbmc/filesystem/SmartPlaylistDirectory.cpp @@ -26,7 +26,7 @@ #include "filesystem/File.h" #include "music/MusicDatabase.h" #include "playlists/SmartPlayList.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "utils/log.h" #include "utils/StringUtils.h" #include "utils/URIUtils.h" @@ -70,7 +70,7 @@ namespace XFILE sorting.limitEnd = playlist.GetLimit(); sorting.sortBy = playlist.GetOrder(); sorting.sortOrder = playlist.GetOrderAscending() ? SortOrderAscending : SortOrderDescending; - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) sorting.sortAttributes = SortAttributeIgnoreArticle; std::string option = !filter ? "xsp" : "filter"; diff --git a/xbmc/filesystem/SmbFile.cpp b/xbmc/filesystem/SmbFile.cpp index 1080a04a13..1300f242b9 100644 --- a/xbmc/filesystem/SmbFile.cpp +++ b/xbmc/filesystem/SmbFile.cpp @@ -29,9 +29,10 @@ #include "Util.h" #include <libsmbclient.h> #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "threads/SingleLock.h" #include "utils/log.h" +#include "utils/StringUtils.h" #include "utils/TimeUtils.h" #include "commons/Exception.h" @@ -122,9 +123,9 @@ void CSMB::Init() // set wins server if there's one. name resolve order defaults to 'lmhosts host wins bcast'. // if no WINS server has been specified the wins method will be ignored. - if ( g_guiSettings.GetString("smb.winsserver").length() > 0 && !g_guiSettings.GetString("smb.winsserver").Equals("0.0.0.0") ) + if (CSettings::Get().GetString("smb.winsserver").length() > 0 && !StringUtils::EqualsNoCase(CSettings::Get().GetString("smb.winsserver"), "0.0.0.0") ) { - fprintf(f, "\twins server = %s\n", g_guiSettings.GetString("smb.winsserver").c_str()); + fprintf(f, "\twins server = %s\n", CSettings::Get().GetString("smb.winsserver").c_str()); fprintf(f, "\tname resolve order = bcast wins host\n"); } else @@ -136,8 +137,8 @@ void CSMB::Init() fprintf(f, "\tdos charset = %s\n", g_advancedSettings.m_sambadoscodepage.c_str()); // if no workgroup string is specified, samba will use the default value 'WORKGROUP' - if ( g_guiSettings.GetString("smb.workgroup").length() > 0 ) - fprintf(f, "\tworkgroup = %s\n", g_guiSettings.GetString("smb.workgroup").c_str()); + if ( CSettings::Get().GetString("smb.workgroup").length() > 0 ) + fprintf(f, "\tworkgroup = %s\n", CSettings::Get().GetString("smb.workgroup").c_str()); fclose(f); } } @@ -155,7 +156,7 @@ void CSMB::Init() // setup our context m_context = smbc_new_context(); #ifdef DEPRECATED_SMBC_INTERFACE - smbc_setDebug(m_context, g_advancedSettings.m_logLevel == LOG_LEVEL_DEBUG_SAMBA ? 10 : 0); + smbc_setDebug(m_context, (g_advancedSettings.m_extraLogLevels & LOGSAMBA)?10:0); smbc_setFunctionAuthData(m_context, xb_smbc_auth); orig_cache = smbc_getFunctionGetCachedServer(m_context); smbc_setFunctionGetCachedServer(m_context, xb_smbc_cache); @@ -164,7 +165,7 @@ void CSMB::Init() smbc_setTimeout(m_context, g_advancedSettings.m_sambaclienttimeout * 1000); smbc_setUser(m_context, strdup("guest")); #else - m_context->debug = g_advancedSettings.m_logLevel == LOG_LEVEL_DEBUG_SAMBA ? 10 : 0; + m_context->debug = (g_advancedSettings.m_extraLogLevels & LOGSAMBA?10:0); m_context->callbacks.auth_fn = xb_smbc_auth; orig_cache = m_context->callbacks.get_cached_srv_fn; m_context->callbacks.get_cached_srv_fn = xb_smbc_cache; @@ -182,9 +183,9 @@ void CSMB::Init() #ifdef TARGET_WINDOWS // if a wins-server is set, we have to change name resolve order to - if ( g_guiSettings.GetString("smb.winsserver").length() > 0 && !g_guiSettings.GetString("smb.winsserver").Equals("0.0.0.0") ) + if ( CSettings::Get().GetString("smb.winsserver").length() > 0 && !CSettings::Get().GetString("smb.winsserver").Equals("0.0.0.0") ) { - lp_do_parameter( -1, "wins server", g_guiSettings.GetString("smb.winsserver").c_str()); + lp_do_parameter( -1, "wins server", CSettings::Get().GetString("smb.winsserver").c_str()); lp_do_parameter( -1, "name resolve order", "bcast wins host"); } else diff --git a/xbmc/filesystem/SpecialProtocol.cpp b/xbmc/filesystem/SpecialProtocol.cpp index ee96019c98..584a3db68b 100644 --- a/xbmc/filesystem/SpecialProtocol.cpp +++ b/xbmc/filesystem/SpecialProtocol.cpp @@ -24,7 +24,7 @@ #include "guilib/GraphicContext.h" #include "profiles/ProfilesManager.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "utils/log.h" #include "utils/URIUtils.h" @@ -129,25 +129,25 @@ CStdString CSpecialProtocol::TranslatePath(const CURL &url) RootDir = FullFileName; if (RootDir.Equals("subtitles")) - URIUtils::AddFileToFolder(g_guiSettings.GetString("subtitles.custompath"), FileName, translatedPath); + translatedPath = URIUtils::AddFileToFolder(CSettings::Get().GetString("subtitles.custompath"), FileName); else if (RootDir.Equals("userdata")) - URIUtils::AddFileToFolder(CProfilesManager::Get().GetUserDataFolder(), FileName, translatedPath); + translatedPath = URIUtils::AddFileToFolder(CProfilesManager::Get().GetUserDataFolder(), FileName); else if (RootDir.Equals("database")) - URIUtils::AddFileToFolder(CProfilesManager::Get().GetDatabaseFolder(), FileName, translatedPath); + translatedPath = URIUtils::AddFileToFolder(CProfilesManager::Get().GetDatabaseFolder(), FileName); else if (RootDir.Equals("thumbnails")) - URIUtils::AddFileToFolder(CProfilesManager::Get().GetThumbnailsFolder(), FileName, translatedPath); + translatedPath = URIUtils::AddFileToFolder(CProfilesManager::Get().GetThumbnailsFolder(), FileName); else if (RootDir.Equals("recordings") || RootDir.Equals("cdrips")) - URIUtils::AddFileToFolder(g_guiSettings.GetString("audiocds.recordingpath", false), FileName, translatedPath); + translatedPath = URIUtils::AddFileToFolder(CSettings::Get().GetString("audiocds.recordingpath"), FileName); else if (RootDir.Equals("screenshots")) - URIUtils::AddFileToFolder(g_guiSettings.GetString("debug.screenshotpath", false), FileName, translatedPath); + translatedPath = URIUtils::AddFileToFolder(CSettings::Get().GetString("debug.screenshotpath"), FileName); else if (RootDir.Equals("musicplaylists")) - URIUtils::AddFileToFolder(CUtil::MusicPlaylistsLocation(), FileName, translatedPath); + translatedPath = URIUtils::AddFileToFolder(CUtil::MusicPlaylistsLocation(), FileName); else if (RootDir.Equals("videoplaylists")) - URIUtils::AddFileToFolder(CUtil::VideoPlaylistsLocation(), FileName, translatedPath); + translatedPath = URIUtils::AddFileToFolder(CUtil::VideoPlaylistsLocation(), FileName); else if (RootDir.Equals("skin")) - URIUtils::AddFileToFolder(g_graphicsContext.GetMediaDir(), FileName, translatedPath); + translatedPath = URIUtils::AddFileToFolder(g_graphicsContext.GetMediaDir(), FileName); else if (RootDir.Equals("logpath")) - URIUtils::AddFileToFolder(g_advancedSettings.m_logFolder, FileName, translatedPath); + translatedPath = URIUtils::AddFileToFolder(g_advancedSettings.m_logFolder, FileName); // from here on, we have our "real" special paths @@ -162,7 +162,7 @@ CStdString CSpecialProtocol::TranslatePath(const CURL &url) { CStdString basePath = GetPath(RootDir); if (!basePath.IsEmpty()) - URIUtils::AddFileToFolder(basePath, FileName, translatedPath); + translatedPath = URIUtils::AddFileToFolder(basePath, FileName); else translatedPath.clear(); } diff --git a/xbmc/filesystem/StackDirectory.cpp b/xbmc/filesystem/StackDirectory.cpp index 663d6e0592..7df46febd3 100644 --- a/xbmc/filesystem/StackDirectory.cpp +++ b/xbmc/filesystem/StackDirectory.cpp @@ -48,7 +48,6 @@ namespace XFILE { CStdString file = files[i]; CFileItemPtr item(new CFileItem(file)); - //URIUtils::AddFileToFolder(folder, file, item->GetPath()); item->SetPath(file); item->m_bIsFolder = false; items.Add(item); @@ -159,7 +158,7 @@ namespace XFILE { // the stacked files are always in volume order, so just get up to the first filename // occurence of " , " - CStdString path, file, folder; + CStdString file, folder; int pos = strPath.Find(" , "); if (pos > 0) URIUtils::Split(strPath.Left(pos), folder, file); @@ -169,9 +168,8 @@ namespace XFILE // remove "stack://" from the folder folder = folder.Mid(8); file.Replace(",,", ","); - URIUtils::AddFileToFolder(folder, file, path); - return path; + return URIUtils::AddFileToFolder(folder, file); } bool CStackDirectory::GetPaths(const CStdString& strPath, vector<CStdString>& vecPaths) diff --git a/xbmc/filesystem/UDFDirectory.cpp b/xbmc/filesystem/UDFDirectory.cpp index 11d64a35d2..e3d42ffb7c 100644 --- a/xbmc/filesystem/UDFDirectory.cpp +++ b/xbmc/filesystem/UDFDirectory.cpp @@ -57,7 +57,10 @@ bool CUDFDirectory::GetDirectory(const CStdString& strPath, URIUtils::AddSlashAtEnd(strSub); udf25 udfIsoReader; - udf_dir_t *dirp = udfIsoReader.OpenDir(url.GetHostName(), strSub); + if(!udfIsoReader.Open(url.GetHostName())) + return false; + + udf_dir_t *dirp = udfIsoReader.OpenDir(strSub); if (dirp == NULL) return false; diff --git a/xbmc/filesystem/UDFDirectory.h b/xbmc/filesystem/UDFDirectory.h index 0c2753ba1f..c67232a226 100644 --- a/xbmc/filesystem/UDFDirectory.h +++ b/xbmc/filesystem/UDFDirectory.h @@ -21,18 +21,19 @@ * */ -#include "IDirectory.h" +#include "IFileDirectory.h" namespace XFILE { class CUDFDirectory : - public IDirectory + public IFileDirectory { public: CUDFDirectory(void); virtual ~CUDFDirectory(void); virtual bool GetDirectory(const CStdString& strPath, CFileItemList &items); virtual bool Exists(const char* strPath); + virtual bool ContainsFiles(const CStdString& strPath) { return true; } }; } diff --git a/xbmc/filesystem/UDFFile.cpp b/xbmc/filesystem/UDFFile.cpp index 62ad531401..3904831963 100644 --- a/xbmc/filesystem/UDFFile.cpp +++ b/xbmc/filesystem/UDFFile.cpp @@ -48,7 +48,10 @@ CUDFFile::~CUDFFile() //********************************************************************************************* bool CUDFFile::Open(const CURL& url) { - m_hFile = m_udfIsoReaderLocal.OpenFile(url.GetHostName(), url.GetFileName()); + if(!m_udfIsoReaderLocal.Open(url.GetHostName())) + return false; + + m_hFile = m_udfIsoReaderLocal.OpenFile(url.GetFileName()); if (m_hFile == INVALID_HANDLE_VALUE) { m_bOpened = false; @@ -76,6 +79,7 @@ void CUDFFile::Close() { if (!m_bOpened) return ; m_udfIsoReaderLocal.CloseFile( m_hFile); + m_bOpened = false; } //********************************************************************************************* @@ -102,7 +106,10 @@ int64_t CUDFFile::GetPosition() bool CUDFFile::Exists(const CURL& url) { - m_hFile = m_udfIsoReaderLocal.OpenFile(url.GetHostName(), url.GetFileName()); + if(!m_udfIsoReaderLocal.Open(url.GetHostName())) + return false; + + m_hFile = m_udfIsoReaderLocal.OpenFile(url.GetFileName()); if (m_hFile == INVALID_HANDLE_VALUE) return false; @@ -113,7 +120,10 @@ bool CUDFFile::Exists(const CURL& url) int CUDFFile::Stat(const CURL& url, struct __stat64* buffer) { - m_hFile = m_udfIsoReaderLocal.OpenFile(url.GetHostName(), url.GetFileName()); + if(!m_udfIsoReaderLocal.Open(url.GetHostName())) + return -1; + + m_hFile = m_udfIsoReaderLocal.OpenFile(url.GetFileName()); if (m_hFile != INVALID_HANDLE_VALUE) { buffer->st_size = m_udfIsoReaderLocal.GetFileSize(m_hFile); diff --git a/xbmc/filesystem/VideoDatabaseDirectory.cpp b/xbmc/filesystem/VideoDatabaseDirectory.cpp index 8e4da794a9..6b0635dd64 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory.cpp @@ -25,7 +25,7 @@ #include "guilib/TextureManager.h" #include "File.h" #include "FileItem.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "utils/Crc32.h" #include "guilib/LocalizeStrings.h" #include "utils/log.h" @@ -229,7 +229,7 @@ CStdString CVideoDatabaseDirectory::GetIcon(const CStdString &strDirectory) case NODE_TYPE_TITLE_MOVIES: if (strDirectory.Equals("videodb://movies/titles/")) { - if (g_guiSettings.GetBool("myvideos.flatten")) + if (CSettings::Get().GetBool("myvideos.flatten")) return "DefaultMovies.png"; return "DefaultMovieTitle.png"; } @@ -237,7 +237,7 @@ CStdString CVideoDatabaseDirectory::GetIcon(const CStdString &strDirectory) case NODE_TYPE_TITLE_TVSHOWS: if (strDirectory.Equals("videodb://tvshows/titles/")) { - if (g_guiSettings.GetBool("myvideos.flatten")) + if (CSettings::Get().GetBool("myvideos.flatten")) return "DefaultTVShows.png"; return "DefaultTVShowTitle.png"; } @@ -245,7 +245,7 @@ CStdString CVideoDatabaseDirectory::GetIcon(const CStdString &strDirectory) case NODE_TYPE_TITLE_MUSICVIDEOS: if (strDirectory.Equals("videodb://musicvideos/titles/")) { - if (g_guiSettings.GetBool("myvideos.flatten")) + if (CSettings::Get().GetBool("myvideos.flatten")) return "DefaultMusicVideos.png"; return "DefaultMusicVideoTitle.png"; } diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeOverview.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeOverview.cpp index ecdedc9685..019c6f287c 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeOverview.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeOverview.cpp @@ -20,7 +20,7 @@ #include "video/VideoDatabase.h" #include "DirectoryNodeOverview.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "FileItem.h" #include "guilib/LocalizeStrings.h" #include "video/VideoDbUrl.h" @@ -71,21 +71,21 @@ bool CDirectoryNodeOverview::GetContent(CFileItemList& items) const vector<pair<const char*, int> > vec; if (hasMovies) { - if (g_guiSettings.GetBool("myvideos.flatten")) + if (CSettings::Get().GetBool("myvideos.flatten")) vec.push_back(make_pair("movies/titles", 342)); else vec.push_back(make_pair("movies", 342)); // Movies } if (hasTvShows) { - if (g_guiSettings.GetBool("myvideos.flatten")) + if (CSettings::Get().GetBool("myvideos.flatten")) vec.push_back(make_pair("tvshows/titles", 20343)); else vec.push_back(make_pair("tvshows", 20343)); // TV Shows } if (hasMusicVideos) { - if (g_guiSettings.GetBool("myvideos.flatten")) + if (CSettings::Get().GetBool("myvideos.flatten")) vec.push_back(make_pair("musicvideos/titles", 20389)); else vec.push_back(make_pair("musicvideos", 20389)); // Music Videos diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeSeasons.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeSeasons.cpp index aaaab2a7c1..c0902a15bd 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeSeasons.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeSeasons.cpp @@ -22,8 +22,8 @@ #include "QueryParams.h" #include "video/VideoDatabase.h" #include "video/VideoDbUrl.h" -#include "settings/GUISettings.h" #include "settings/MediaSettings.h" +#include "settings/Settings.h" #include "FileItem.h" #include "utils/Variant.h" @@ -71,14 +71,14 @@ bool CDirectoryNodeSeasons::GetContent(CFileItemList& items) const CQueryParams params; CollectQueryParams(params); - int iFlatten = g_guiSettings.GetInt("videolibrary.flattentvshows"); + int iFlatten = CSettings::Get().GetInt("videolibrary.flattentvshows"); bool bSuccess=videodatabase.GetSeasonsNav(BuildPath(), items, params.GetActorId(), params.GetDirectorId(), params.GetGenreId(), params.GetYear(), params.GetTvShowId()); bool bFlatten = (items.GetObjectCount() == 1 && iFlatten == 1) || iFlatten == 2; if (items.GetObjectCount() == 2 && iFlatten == 1) if (items[0]->GetVideoInfoTag()->m_iSeason == 0 || items[1]->GetVideoInfoTag()->m_iSeason == 0) bFlatten = true; // flatten if one season + specials - if (iFlatten > 0 && !bFlatten && CMediaSettings::Get().GetWatchedMode("tvshows") == WatchedModeUnwatched) + if (iFlatten > 0 && !bFlatten && CMediaSettings::Get().GetWatchedMode("tvshows") == WatchedModeUnwatched) { int count = 0; for(int i = 0; i < items.Size(); i++) diff --git a/xbmc/filesystem/test/TestFileFactory.cpp b/xbmc/filesystem/test/TestFileFactory.cpp index 732e53b35e..52cf7a0a4a 100644 --- a/xbmc/filesystem/test/TestFileFactory.cpp +++ b/xbmc/filesystem/test/TestFileFactory.cpp @@ -20,8 +20,7 @@ #include "filesystem/File.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" -#include "utils/XBMCTinyXML.h" +#include "settings/Settings.h" #include "test/TestUtils.h" #include "gtest/gtest.h" @@ -31,26 +30,29 @@ class TestFileFactory : public testing::Test protected: TestFileFactory() { - std::vector<CStdString> advancedsettings = - CXBMCTestUtils::Instance().getAdvancedSettingsFiles(); - std::vector<CStdString> guisettings = - CXBMCTestUtils::Instance().getGUISettingsFiles(); - std::vector<CStdString>::iterator it; - for (it = advancedsettings.begin(); it < advancedsettings.end(); it++) + if (CSettings::Get().Initialize()) { - g_advancedSettings.ParseSettingsFile(*it); - } - for (it = guisettings.begin(); it < guisettings.end(); it++) - { - CXBMCTinyXML xml(*it); - g_guiSettings.LoadXML(xml.RootElement()); - } + std::vector<CStdString> advancedsettings = + CXBMCTestUtils::Instance().getAdvancedSettingsFiles(); + std::vector<CStdString> guisettings = + CXBMCTestUtils::Instance().getGUISettingsFiles(); + + std::vector<CStdString>::iterator it; + for (it = guisettings.begin(); it < guisettings.end(); it++) + CSettings::Get().Load(*it); + + for (it = advancedsettings.begin(); it < advancedsettings.end(); it++) + g_advancedSettings.ParseSettingsFile(*it); + + CSettings::Get().SetLoaded(); + } } ~TestFileFactory() { g_advancedSettings.Clear(); - g_guiSettings.Clear(); + CSettings::Get().Unload(); + CSettings::Get().Uninitialize(); } }; diff --git a/xbmc/filesystem/test/TestRarFile.cpp b/xbmc/filesystem/test/TestRarFile.cpp index a29430249f..e63ae700e3 100644 --- a/xbmc/filesystem/test/TestRarFile.cpp +++ b/xbmc/filesystem/test/TestRarFile.cpp @@ -23,7 +23,6 @@ #include "filesystem/Directory.h" #include "filesystem/File.h" #include "filesystem/NFSFile.h" -#include "settings/GUISettings.h" #include "utils/URIUtils.h" #include "FileItem.h" #include "test/TestUtils.h" diff --git a/xbmc/filesystem/test/TestZipFile.cpp b/xbmc/filesystem/test/TestZipFile.cpp index 923a7c5fe7..7f94680e62 100644 --- a/xbmc/filesystem/test/TestZipFile.cpp +++ b/xbmc/filesystem/test/TestZipFile.cpp @@ -20,9 +20,9 @@ #include "filesystem/Directory.h" #include "filesystem/File.h" -#include "settings/GUISettings.h" #include "utils/URIUtils.h" #include "FileItem.h" +#include "settings/Settings.h" #include "test/TestUtils.h" #include <errno.h> @@ -37,19 +37,21 @@ protected: /* Add default settings for locale. * Settings here are taken from CGUISettings::Initialize() */ - CSettingsCategory *loc = g_guiSettings.AddCategory(7, "locale", 14090); - g_guiSettings.AddString(loc, "locale.language",248,"english", + /* TODO + CSettingsCategory *loc = CSettings::Get().AddCategory(7, "locale", 14090); + CSettings::Get().AddString(loc, "locale.language",248,"english", SPIN_CONTROL_TEXT); - g_guiSettings.AddString(loc, "locale.country", 20026, "USA", + CSettings::Get().AddString(loc, "locale.country", 20026, "USA", SPIN_CONTROL_TEXT); - g_guiSettings.AddString(loc, "locale.charset", 14091, "DEFAULT", + CSettings::Get().AddString(loc, "locale.charset", 14091, "DEFAULT", SPIN_CONTROL_TEXT); // charset is set by the // language file + */ } ~TestZipFile() { - g_guiSettings.Clear(); + CSettings::Get().Unload(); } }; diff --git a/xbmc/filesystem/udf25.cpp b/xbmc/filesystem/udf25.cpp index ec5cc2ba56..cf44303e96 100644 --- a/xbmc/filesystem/udf25.cpp +++ b/xbmc/filesystem/udf25.cpp @@ -74,14 +74,12 @@ static int UDFExtentAD( uint8_t *data, uint32_t *Length, uint32_t *Location ) return 0; } -static int UDFShortAD( uint8_t *data, struct AD *ad, - struct Partition *partition ) +static int UDFShortAD( uint8_t *data, struct AD *ad ) { ad->Length = GETN4(0); ad->Flags = ad->Length >> 30; ad->Length &= 0x3FFFFFFF; ad->Location = GETN4(4); - ad->Partition = partition->Number; /* use number of current partition */ return 0; } @@ -107,6 +105,47 @@ static int UDFExtAD( uint8_t *data, struct AD *ad ) return 0; } +static int UDFAD( uint8_t *ptr, uint32_t len, struct FileAD *fad) +{ + struct AD *ad; + + if (fad->num_AD >= UDF_MAX_AD_CHAINS) + return len; + + ad = &fad->AD_chain[fad->num_AD]; + ad->Partition = fad->Partition; + ad->Flags = 0; + fad->num_AD++; + + switch( fad->Flags & 0x0007 ) { + case 0: + UDFShortAD( ptr, ad ); + return 8; + case 1: + UDFLongAD( ptr, ad ); + return 16; + case 2: + UDFExtAD( ptr, ad ); + return 20; + case 3: + switch( len ) { + case 8: + UDFShortAD( ptr, ad ); + break; + case 16: + UDFLongAD( ptr, ad ); + break; + case 20: + UDFExtAD( ptr, ad ); + break; + } + break; + default: + break; + } + + return len; +} static int UDFICB( uint8_t *data, uint8_t *FileType, uint16_t *Flags ) { @@ -135,14 +174,25 @@ static int UDFLogVolume( uint8_t *data, char *VolumeDescriptor ) return 0; } -static int UDFExtFileEntry( uint8_t *data, uint8_t *FileType, - struct Partition *partition, struct FileAD *fad ) +static int UDFAdEntry( uint8_t *data, struct FileAD *fad ) +{ + uint32_t L_AD; + unsigned int p; + + L_AD = GETN4(20); + p = 24; + while( p < 24 + L_AD ) { + p += UDFAD( &data[ p ], L_AD, fad ); + } + return 0; +} + +static int UDFExtFileEntry( uint8_t *data, struct FileAD *fad ) { - uint16_t flags; uint32_t L_EA, L_AD; unsigned int p; - UDFICB( &data[ 16 ], FileType, &flags ); + UDFICB( &data[ 16 ], &fad->Type, &fad->Flags ); /* Init ad for an empty file (i.e. there isn't a AD, L_AD == 0 ) */ fad->Length = GETN8(56); // 64-bit. @@ -152,46 +202,7 @@ static int UDFExtFileEntry( uint8_t *data, uint8_t *FileType, p = 216 + L_EA; fad->num_AD = 0; while( p < 216 + L_EA + L_AD ) { - struct AD *ad; - - if (fad->num_AD >= UDF_MAX_AD_CHAINS) return 0; - - ad = &fad->AD_chain[fad->num_AD]; - ad->Partition = partition->Number; - ad->Flags = 0; - fad->num_AD++; - - switch( flags & 0x0007 ) { - case 0: - UDFShortAD( &data[ p ], ad, partition ); - p += 8; - break; - case 1: - UDFLongAD( &data[ p ], ad ); - p += 16; - break; - case 2: - UDFExtAD( &data[ p ], ad ); - p += 20; - break; - case 3: - switch( L_AD ) { - case 8: - UDFShortAD( &data[ p ], ad, partition ); - break; - case 16: - UDFLongAD( &data[ p ], ad ); - break; - case 20: - UDFExtAD( &data[ p ], ad ); - break; - } - p += L_AD; - break; - default: - p += L_AD; - break; - } + p += UDFAD( &data[ p ], L_AD, fad ); } return 0; @@ -232,15 +243,13 @@ static int UDFExtFileEntry( uint8_t *data, uint8_t *FileType, * Lund */ -static int UDFFileEntry( uint8_t *data, uint8_t *FileType, - struct Partition *partition, struct FileAD *fad ) +static int UDFFileEntry( uint8_t *data, struct FileAD *fad ) { - uint16_t flags; uint32_t L_EA, L_AD; unsigned int p; unsigned int curr_ad; - UDFICB( &data[ 16 ], FileType, &flags ); + UDFICB( &data[ 16 ], &fad->Type, &fad->Flags ); fad->Length = GETN8( 56 ); /* Was 4 bytes at 60, changed for 64bit. */ @@ -251,91 +260,41 @@ static int UDFFileEntry( uint8_t *data, uint8_t *FileType, return 0; p = 176 + L_EA; - curr_ad = 0; - - /* Function changed to record all AD chains, not just the last one! */ + fad->num_AD = 0; while( p < 176 + L_EA + L_AD ) { - struct AD *ad; - - if (curr_ad >= UDF_MAX_AD_CHAINS) return 0; - - ad = &fad->AD_chain[curr_ad]; - ad->Partition = partition->Number; - ad->Flags = 0; - // Increase AD chain ptr - curr_ad++; - - switch( flags & 0x0007 ) { - case 0: - UDFShortAD( &data[ p ], ad, partition ); - p += 8; - break; - case 1: - UDFLongAD( &data[ p ], ad ); - p += 16; - break; - case 2: - UDFExtAD( &data[ p ], ad ); - p += 20; - break; - case 3: - switch( L_AD ) { - case 8: - UDFShortAD( &data[ p ], ad, partition ); - break; - case 16: - UDFLongAD( &data[ p ], ad ); - break; - case 20: - UDFExtAD( &data[ p ], ad ); - break; - } - p += L_AD; - break; - default: - p += L_AD; - break; - } + p += UDFAD( &data[ p ], L_AD, fad ); } return 0; } - -// The API users will refer to block 0 as start of file and going up -// we need to convert that to actual disk block; -// partition_start + file_start + offset -// but keep in mind that file_start is chained, and not contiguous. -// -// We return "0" as error, since a File can not start at physical block 0 -// -// Who made Location be blocks, but Length be bytes? Can bytes be uneven -// blocksize in the middle of a chain? -// -uint32_t UDFFileBlockPos(struct FileAD *File, uint32_t file_block) +uint32_t UDFFilePos(struct FileAD *File, uint64_t pos, uint64_t *res) { - uint32_t result, i, offset; - - if (!File) return 0; + uint32_t i; - // Look through the chain to see where this block would belong. - for (i = 0, offset = 0; i < File->num_AD; i++) { + for (i = 0; i < File->num_AD; i++) { - // Is "file_block" inside this chain? Then use this chain. - if (file_block < (offset + (File->AD_chain[i].Length / DVD_VIDEO_LB_LEN))) + if (pos < File->AD_chain[i].Length) break; - offset += (File->AD_chain[i].Length / DVD_VIDEO_LB_LEN); - + pos -= File->AD_chain[i].Length; } - if (i >= File->num_AD) - i = 0; // This was the default behavior before I fixed things. + if (i == File->num_AD) + return 0; - //if(offset == 0) - // offset = 32; + *res = (uint64_t)(File->Partition_Start + File->AD_chain[i].Location) * DVD_VIDEO_LB_LEN + pos; + return File->AD_chain[i].Length - pos; +} - result = File->Partition_Start + File->AD_chain[i].Location + file_block - offset; - return result; +uint32_t UDFFileBlockPos(struct FileAD *File, uint32_t lb) +{ + uint64_t res; + uint32_t rem; + rem = UDFFilePos(File, lb * DVD_VIDEO_LB_LEN, &res); + if(rem > 0) + return res / DVD_VIDEO_LB_LEN; + else + return 0; } static int UDFFileIdentifier( uint8_t *data, uint8_t *FileCharacteristics, @@ -360,110 +319,6 @@ static int UDFDescriptor( uint8_t *data, uint16_t *TagID ) return 0; } -/** - * initialize and open a DVD device or file. - */ -static CFile* file_open(const char *target) -{ - CFile* fp = new CFile(); - - if(!fp->Open(target)) - { - CLog::Log(LOGERROR,"file_open - Could not open input"); - delete fp; - return NULL; - } - - return fp; -} - - -/** - * seek into the device. - */ -static int file_seek(CFile* fp, int blocks) -{ - off64_t pos; - - pos = fp->Seek((off64_t)blocks * (off64_t)DVD_VIDEO_LB_LEN, SEEK_SET); - - if(pos < 0) { - return (int) pos; - } - /* assert pos % DVD_VIDEO_LB_LEN == 0 */ - return (int) (pos / DVD_VIDEO_LB_LEN); -} - -/** - * read data from the device. - */ -static int file_read(CFile* fp, void *buffer, int blocks, int flags) -{ - size_t len; - ssize_t ret; - - len = (size_t)blocks * DVD_VIDEO_LB_LEN; - - while(len > 0) { - - ret = fp->Read(buffer, len); - - if(ret < 0) { - /* One of the reads failed, too bad. We won't even bother - * returning the reads that went OK, and as in the POSIX spec - * the file position is left unspecified after a failure. */ - return ret; - } - - if(ret == 0) { - /* Nothing more to read. Return all of the whole blocks, if any. - * Adjust the file position back to the previous block boundary. */ - size_t bytes = (size_t)blocks * DVD_VIDEO_LB_LEN - len; - off_t over_read = -(off_t)(bytes % DVD_VIDEO_LB_LEN); - /*off_t pos =*/ fp->Seek(over_read, SEEK_CUR); - /* should have pos % 2048 == 0 */ - return (int) (bytes / DVD_VIDEO_LB_LEN); - } - - len -= ret; - } - - return blocks; -} - -/** - * close the DVD device and clean up. - */ -static int file_close(CFile* fp) -{ - fp->Close(); - - return 0; -} - -// offset is in bytes, force_size is in sectors -uint64_t DVDFileSeekForce(BD_FILE bdfile, uint64_t offset, int64_t force_size) -{ - /* Check arguments. */ - if( bdfile == NULL || offset <= 0 ) - return -1; - - // if -1 then round up to the next block - if( force_size < 0 ) - force_size = (offset + DVD_VIDEO_LB_LEN) - (offset % DVD_VIDEO_LB_LEN); - - if(bdfile->filesize < (uint64_t)force_size ) { - bdfile->filesize = force_size; - CLog::Log(LOGERROR, "DVDFileSeekForce - ignored size of file indicated in UDF"); - } - - if( offset > bdfile->filesize ) - return -1; - - bdfile->seek_pos = offset; - return offset; -} - int udf25::UDFScanDirX( udf_dir_t *dirp ) { char filename[ MAX_UDF_FILE_NAME_LEN ]; @@ -476,10 +331,11 @@ int udf25::UDFScanDirX( udf_dir_t *dirp ) struct AD FileICB; struct FileAD File; struct Partition partition; - uint8_t filetype; - if(!(GetUDFCache(PartitionCache, 0, &partition))) - return 0; + if(!(GetUDFCache(PartitionCache, 0, &partition))) { + if(!UDFFindPartition(0, &partition)) + return 0; + } /* Scan dir for ICB of file */ lbnum = dirp->dir_current; @@ -530,9 +386,9 @@ int udf25::UDFScanDirX( udf_dir_t *dirp ) // Look up the Filedata - if( !UDFMapICB( FileICB, &filetype, &partition, &File)) + if( !UDFMapICB( FileICB, &partition, &File)) return 0; - if (filetype == 4) + if (File.Type == 4) dirp->entry.d_type = DVD_DT_DIR; else dirp->entry.d_type = DVD_DT_REG; // Add more types? @@ -730,40 +586,39 @@ int udf25::GetUDFCache(UDFCacheType type, uint32_t nr, void *data) return 0; } -int udf25::UDFReadBlocksRaw( uint32_t lb_number, size_t block_count, unsigned char *data, int encrypted ) +int udf25::ReadAt( int64_t pos, size_t len, unsigned char *data ) { - int ret; + int64_t ret; + ret = m_fp->Seek(pos, SEEK_SET); + if(ret != pos) + return -1; - ret = file_seek( m_fp, (int) lb_number ); - if( ret != (int) lb_number ) { - CLog::Log(LOGERROR, "udf25::UDFReadBlocksRaw - Can't seek to block %u (got %u)", lb_number, ret ); - return 0; + ret = m_fp->Read(data, len); + if(ret < (int64_t)len) + { + CLog::Log(LOGERROR, "udf25::ReadFile - less data than requested available!" ); + return (int)ret; } - - ret = file_read( m_fp, (char *) data, (int) block_count, encrypted ); - return ret; + return (int)ret; } int udf25::DVDReadLBUDF( uint32_t lb_number, size_t block_count, unsigned char *data, int encrypted ) { int ret; - size_t count = block_count; - - while(count > 0) { + size_t len = block_count * DVD_VIDEO_LB_LEN; + int64_t pos = lb_number * DVD_VIDEO_LB_LEN; - ret = UDFReadBlocksRaw(lb_number, count, data, encrypted); + ret = ReadAt(pos, len, data); + if(ret < 0) + return ret; - if(ret <= 0) { - /* One of the reads failed or nothing more to read, too bad. - * We won't even bother returning the reads that went ok. */ - return ret; - } - - count -= (size_t)ret; - lb_number += (uint32_t)ret; + if((unsigned int)ret < len) + { + CLog::Log(LOGERROR, "udf25::DVDReadLBUDF - Block was not complete, setting to wanted %u (got %u)", (unsigned int)len, (unsigned int)ret); + memset(&data[ret], 0, len - ret); } - return block_count; + return len / DVD_VIDEO_LB_LEN; } int udf25::UDFGetAVDP( struct avdp_t *avdp) @@ -882,11 +737,43 @@ int udf25::UDFFindPartition( int partnum, struct Partition *part ) } } while( i-- && ( ( !part->valid ) || ( !volvalid ) ) ); + /* Look for a metadata partition */ + lbnum = part->Start; + do { + if( DVDReadLBUDF( lbnum++, 1, LogBlock, 0 ) <= 0 ) + TagID = 0; + else + UDFDescriptor( LogBlock, &TagID ); + + /* + * It seems that someone added a FileType of 250, which seems to be + * a "redirect" style file entry. If we discover such an entry, we + * add on the "location" to partition->Start, and try again. + * Who added this? Is there any official guide somewhere? + * 2008/09/17 lundman + * Should we handle 261(250) as well? FileEntry+redirect + */ + if( TagID == 266 ) { + struct FileAD File; + File.Partition = part->Number; + File.Partition_Start = part->Start; + + UDFExtFileEntry( LogBlock, &File ); + if (File.Type == 250) { + part->Start += File.AD_chain[0].Location; + part->Length = File.AD_chain[0].Length; + break; + } + } + + } while( ( lbnum < part->Start + part->Length ) + && ( TagID != 8 ) && ( TagID != 256 ) ); + /* We only care for the partition, not the volume */ return part->valid; } -int udf25::UDFMapICB( struct AD ICB, uint8_t *FileType, struct Partition *partition, struct FileAD *File ) +int udf25::UDFMapICB( struct AD ICB, struct Partition *partition, struct FileAD *File ) { uint8_t LogBlock_base[DVD_VIDEO_LB_LEN + 2048]; uint8_t *LogBlock = (uint8_t *)(((uintptr_t)LogBlock_base & ~((uintptr_t)2047)) + 2048); @@ -897,11 +784,14 @@ int udf25::UDFMapICB( struct AD ICB, uint8_t *FileType, struct Partition *partit lbnum = partition->Start + ICB.Location; tmpmap.lbn = lbnum; if(GetUDFCache(MapCache, lbnum, &tmpmap)) { - *FileType = tmpmap.filetype; memcpy(File, &tmpmap.file, sizeof(tmpmap.file)); return 1; } + memset(File, 0, sizeof(*File)); + File->Partition = partition->Number; + File->Partition_Start = partition->Start; + do { if( DVDReadLBUDF( lbnum++, 1, LogBlock, 0 ) <= 0 ) TagID = 0; @@ -909,32 +799,51 @@ int udf25::UDFMapICB( struct AD ICB, uint8_t *FileType, struct Partition *partit UDFDescriptor( LogBlock, &TagID ); if( TagID == 261 ) { - UDFFileEntry( LogBlock, FileType, partition, File ); - memcpy(&tmpmap.file, File, sizeof(tmpmap.file)); - tmpmap.filetype = *FileType; - SetUDFCache(MapCache, tmpmap.lbn, &tmpmap); - return 1; + UDFFileEntry( LogBlock, File ); + break; }; /* ExtendedFileInfo */ if( TagID == 266 ) { - UDFExtFileEntry( LogBlock, FileType, partition, File ); - memcpy(&tmpmap.file, File, sizeof(tmpmap.file)); - tmpmap.filetype = *FileType; - SetUDFCache(MapCache, tmpmap.lbn, &tmpmap); - return 1; - } + UDFExtFileEntry( LogBlock, File ); + break; + } + + + } while( lbnum <= partition->Start + ICB.Location + ( ICB.Length - 1 ) + / DVD_VIDEO_LB_LEN ); + + if(File->Type) { - } while( ( lbnum <= partition->Start + ICB.Location + ( ICB.Length - 1 ) - / DVD_VIDEO_LB_LEN ) && ( TagID != 261 ) && (TagID != 266) ); + /* check if ad chain continues elsewhere */ + while(File->num_AD && File->AD_chain[File->num_AD-1].Flags == 3) { + struct AD* ad = &File->AD_chain[File->num_AD-1]; + + /* remove the forward pointer from the list */ + File->num_AD--; + + if( DVDReadLBUDF( File->Partition_Start + ad->Location, 1, LogBlock, 0 ) <= 0 ) + TagID = 0; + else + UDFDescriptor( LogBlock, &TagID ); + + if( TagID == 258 ) { + /* add all additional entries */ + UDFAdEntry( LogBlock, File ); + } else { + return 0; + } + } + + memcpy(&tmpmap.file, File, sizeof(tmpmap.file)); + SetUDFCache(MapCache, tmpmap.lbn, &tmpmap); + + return 1; + } return 0; } -void udf25::UDFFreeFile(UDF_FILE file) -{ - free(file); -} int udf25::UDFScanDir( struct FileAD Dir, char *FileName, struct Partition *partition, struct AD *FileICB, int cache_file_info) { @@ -992,7 +901,6 @@ int udf25::UDFScanDir( struct FileAD Dir, char *FileName, struct Partition *part p += UDFFileIdentifier( &cached_dir[ p ], &filechar, filename, &tmpICB ); if(cache_file_info && !in_cache) { - uint8_t tmpFiletype; struct FileAD tmpFile; memset(&tmpFile, 0, sizeof(tmpFile)); @@ -1001,7 +909,7 @@ int udf25::UDFScanDir( struct FileAD Dir, char *FileName, struct Partition *part memcpy(FileICB, &tmpICB, sizeof(tmpICB)); found = 1; } - UDFMapICB(tmpICB, &tmpFiletype, partition, &tmpFile); + UDFMapICB(tmpICB, partition, &tmpFile); } else { if( !strcasecmp( FileName, filename ) ) { memcpy(FileICB, &tmpICB, sizeof(tmpICB)); @@ -1055,8 +963,8 @@ udf25::udf25( ) udf25::~udf25( ) { - if(m_fp) - m_fp->Close(); + delete m_fp; + free(m_udfcache); } UDF_FILE udf25::UDFFindFile( const char* filename, uint64_t *filesize ) @@ -1070,7 +978,6 @@ UDF_FILE udf25::UDFFindFile( const char* filename, uint64_t *filesize ) struct FileAD File; char tokenline[ MAX_UDF_FILE_NAME_LEN ]; char *token; - uint8_t filetype; struct FileAD *result; *filesize = 0; @@ -1093,24 +1000,6 @@ UDF_FILE udf25::UDFFindFile( const char* filename, uint64_t *filesize ) else UDFDescriptor( LogBlock, &TagID ); - /* - * It seems that someone added a FileType of 250, which seems to be - * a "redirect" style file entry. If we discover such an entry, we - * add on the "location" to partition->Start, and try again. - * Who added this? Is there any official guide somewhere? - * 2008/09/17 lundman - * Should we handle 261(250) as well? FileEntry+redirect - */ - if( TagID == 266 ) { - UDFExtFileEntry( LogBlock, &filetype, &partition, &File ); - if (filetype == 250) { - partition.Start += File.AD_chain[0].Location; - lbnum = partition.Start; - SetUDFCache(PartitionCache, 0, &partition); - continue; - } - } - /* File Set Descriptor */ if( TagID == 256 ) /* File Set Descriptor */ UDFLongAD( &LogBlock[ 400 ], &RootICB ); @@ -1128,9 +1017,9 @@ UDF_FILE udf25::UDFFindFile( const char* filename, uint64_t *filesize ) } /* Find root dir */ - if( !UDFMapICB( RootICB, &filetype, &partition, &File ) ) + if( !UDFMapICB( RootICB, &partition, &File ) ) return NULL; - if( filetype != 4 ) + if( File.Type != 4 ) return NULL; /* Root dir should be dir */ { int cache_file_info = 0; @@ -1141,7 +1030,7 @@ UDF_FILE udf25::UDFFindFile( const char* filename, uint64_t *filesize ) if( !UDFScanDir( File, token, &partition, &ICB, cache_file_info)) return NULL; - if( !UDFMapICB( ICB, &filetype, &partition, &File ) ) + if( !UDFMapICB( ICB, &partition, &File ) ) return NULL; if(!strcmp(token, "index.bdmv")) cache_file_info = 1; @@ -1162,100 +1051,97 @@ UDF_FILE udf25::UDFFindFile( const char* filename, uint64_t *filesize ) if (!result) return NULL; memcpy(result, &File, sizeof(*result)); + return result; +} - result->Partition_Start = partition.Start; +bool udf25::Open(const char *isofile) +{ + m_fp = new CFile(); - return result; + if(!m_fp->Open(isofile)) + { + CLog::Log(LOGERROR,"file_open - Could not open input"); + delete m_fp; + m_fp = NULL; + return false; + } + return true; } -HANDLE udf25::OpenFile( const char* isoname, const char* filename ) +HANDLE udf25::OpenFile( const char* filename ) { uint64_t filesize; UDF_FILE file = NULL; BD_FILE bdfile = NULL; - m_fp = file_open(isoname); - if(m_fp) - { - file = UDFFindFile(filename, &filesize); - if(file) - { - bdfile = (BD_FILE)malloc(sizeof(*bdfile)); - memset(bdfile, 0, sizeof(*bdfile)); + if(!m_fp) + return INVALID_HANDLE_VALUE; - bdfile->file = file; - bdfile->filesize = filesize; - } - else - { - CloseFile(NULL); - } - } + file = UDFFindFile(filename, &filesize); + if(!file) + return INVALID_HANDLE_VALUE; - return bdfile ? (HANDLE)bdfile : INVALID_HANDLE_VALUE; + bdfile = (BD_FILE)calloc(1, sizeof(*bdfile)); + + bdfile->file = file; + bdfile->filesize = filesize; + return (HANDLE)bdfile; } long udf25::ReadFile(HANDLE hFile, unsigned char *pBuffer, long lSize) { BD_FILE bdfile = (BD_FILE)hFile; - unsigned char *secbuf_base, *secbuf; - unsigned int numsec, seek_sector, seek_byte, fileoff; - int ret; + long len_origin; + uint64_t pos; + uint32_t len; + int ret; /* Check arguments. */ if( bdfile == NULL || pBuffer == NULL ) return -1; - seek_sector =(unsigned int) (bdfile->seek_pos / DVD_VIDEO_LB_LEN); - seek_byte = bdfile->seek_pos % DVD_VIDEO_LB_LEN; + len_origin = lSize; + while(lSize > 0) + { + len = UDFFilePos(bdfile->file, bdfile->seek_pos, &pos); + if(len == 0) + break; - numsec = ( ( seek_byte + lSize ) / DVD_VIDEO_LB_LEN ) + - ( ( ( seek_byte + lSize ) % DVD_VIDEO_LB_LEN ) ? 1 : 0 ); + pos -= 32 * DVD_VIDEO_LB_LEN; /* why? */ - secbuf_base = (unsigned char *) malloc( numsec * DVD_VIDEO_LB_LEN + 2048 ); - secbuf = (unsigned char *)(((uintptr_t)secbuf_base & ~((uintptr_t)2047)) + 2048); - if( !secbuf_base ) { - CLog::Log(LOGERROR, "udf25::ReadFile - Can't allocate memory for file read!" ); - return 0; - } + if(lSize < len) + len = lSize; - fileoff = UDFFileBlockPos(bdfile->file, seek_sector); - fileoff -= 32; + ret = ReadAt(pos, len, pBuffer); + if(ret < 0) + { + CLog::Log(LOGERROR, "udf25::ReadFile - error during read" ); + return ret; + } - ret = UDFReadBlocksRaw( fileoff, (size_t) numsec, secbuf, 0 ); + if(ret == 0) + break; - if( ret != (int) numsec ) { - free( secbuf_base ); - return ret < 0 ? ret : 0; + bdfile->seek_pos += ret; + pBuffer += ret; + lSize -= ret; } - memcpy( pBuffer, &(secbuf[ seek_byte ]), lSize ); - free( secbuf_base ); - - DVDFileSeekForce(bdfile, bdfile->seek_pos + lSize, -1); - - return lSize; + return len_origin - lSize; } void udf25::CloseFile(HANDLE hFile) { + if(hFile == INVALID_HANDLE_VALUE) + return; + BD_FILE bdfile = (BD_FILE)hFile; if(bdfile) { free(bdfile->file); free(bdfile); } - - free(m_udfcache); - m_udfcache = NULL; - - if(m_fp) - { - file_close(m_fp); - delete(m_fp); - m_fp = NULL; - } } int64_t udf25::Seek(HANDLE hFile, int64_t lOffset, int whence) @@ -1312,31 +1198,26 @@ int64_t udf25::GetFilePosition(HANDLE hFile) return bdfile->seek_pos; } -udf_dir_t *udf25::OpenDir( const char *isofile, const char *subdir ) +udf_dir_t *udf25::OpenDir( const char *subdir ) { udf_dir_t *result; BD_FILE bd_file; - bd_file = (BD_FILE)OpenFile(isofile, subdir); + bd_file = (BD_FILE)OpenFile(subdir); if (bd_file == (BD_FILE)INVALID_HANDLE_VALUE) - { return NULL; - } - result = (udf_dir_t *)malloc(sizeof(*result)); + + result = (udf_dir_t *)calloc(1, sizeof(udf_dir_t)); if (!result) { - UDFFreeFile(bd_file->file); - free(bd_file); + CloseFile((HANDLE)bd_file); return NULL; } - memset(result, 0, sizeof(*result)); - result->dir_location = UDFFileBlockPos(bd_file->file, 0); result->dir_current = UDFFileBlockPos(bd_file->file, 0); result->dir_length = (uint32_t) bd_file->filesize; - UDFFreeFile(bd_file->file); - free(bd_file); + CloseFile((HANDLE)bd_file); return result; } diff --git a/xbmc/filesystem/udf25.h b/xbmc/filesystem/udf25.h index d5a3676181..e255d9e35b 100644 --- a/xbmc/filesystem/udf25.h +++ b/xbmc/filesystem/udf25.h @@ -61,14 +61,20 @@ struct AD { * a 4.4GB file uses 5 AD chains. A BluRay disk can store 50GB of data, so the * largest file should be 50 GB. So the maximum number of chains should be * around 62. + * + * However, with AD chain extensions there has been examples of chains up to + * around 1600 entries. */ -#define UDF_MAX_AD_CHAINS 50 +#define UDF_MAX_AD_CHAINS 2000 struct FileAD { uint64_t Length; uint32_t num_AD; + uint16_t Partition; uint32_t Partition_Start; + uint8_t Type; + uint16_t Flags; struct AD AD_chain[UDF_MAX_AD_CHAINS]; }; @@ -97,7 +103,6 @@ struct lbudf { struct icbmap { uint32_t lbn; struct FileAD file; - uint8_t filetype; }; struct udf_cache { @@ -183,11 +188,12 @@ public: int64_t GetFileSize(HANDLE hFile); int64_t GetFilePosition(HANDLE hFile); int64_t Seek(HANDLE hFile, int64_t lOffset, int whence); - HANDLE OpenFile( const char *isofile, const char* filename ); + bool Open(const char *isofile); + HANDLE OpenFile( const char* filename ); long ReadFile(HANDLE fd, unsigned char *pBuffer, long lSize); void CloseFile(HANDLE hFile); - udf_dir_t *OpenDir( const char *isofile, const char *subdir ); + udf_dir_t *OpenDir( const char *subdir ); udf_dirent_t *ReadDir( udf_dir_t *dirp ); int CloseDir( udf_dir_t *dirp ); @@ -198,7 +204,6 @@ public: private: UDF_FILE UDFFindFile( const char* filename, uint64_t *filesize ); int UDFScanDirX( udf_dir_t *dirp ); - void UDFFreeFile(UDF_FILE file); int DVDUDFCacheLevel(int level); void* GetUDFCacheHandle(); void SetUDFCacheHandle(void *cache); @@ -206,8 +211,8 @@ private: int UDFFindPartition( int partnum, struct Partition *part ); int UDFGetAVDP( struct avdp_t *avdp); int DVDReadLBUDF( uint32_t lb_number, size_t block_count, unsigned char *data, int encrypted ); - int UDFReadBlocksRaw( uint32_t lb_number, size_t block_count, unsigned char *data, int encrypted ); - int UDFMapICB( struct AD ICB, uint8_t *FileType, struct Partition *partition, struct FileAD *File ); + int ReadAt( int64_t pos, size_t len, unsigned char *data ); + int UDFMapICB( struct AD ICB, struct Partition *partition, struct FileAD *File ); int UDFScanDir( struct FileAD Dir, char *FileName, struct Partition *partition, struct AD *FileICB, int cache_file_info); int SetUDFCache(UDFCacheType type, uint32_t nr, void *data); protected: diff --git a/xbmc/filesystem/windows/WINFileSMB.cpp b/xbmc/filesystem/windows/WINFileSMB.cpp index c54145473c..b46355a58d 100644 --- a/xbmc/filesystem/windows/WINFileSMB.cpp +++ b/xbmc/filesystem/windows/WINFileSMB.cpp @@ -20,7 +20,7 @@ */ #include "WINFileSMB.h" #include "URL.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include <sys/stat.h> #include <io.h> @@ -343,4 +343,4 @@ int CWINFileSMB::Truncate(int64_t size) int result = _chsize_s(fd, (long) size); _close(fd); return result; -}
\ No newline at end of file +} diff --git a/xbmc/filesystem/windows/WINSMBDirectory.cpp b/xbmc/filesystem/windows/WINSMBDirectory.cpp index f840870fab..c69ea28a96 100644 --- a/xbmc/filesystem/windows/WINSMBDirectory.cpp +++ b/xbmc/filesystem/windows/WINSMBDirectory.cpp @@ -22,7 +22,7 @@ #include "WINSMBDirectory.h" #include "URL.h" #include "utils/URIUtils.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "FileItem.h" #include "WIN32Util.h" #include "utils/AutoPtrHandle.h" diff --git a/xbmc/guilib/GUIAudioManager.cpp b/xbmc/guilib/GUIAudioManager.cpp index 8b0fa947a3..3143b9f6d5 100644 --- a/xbmc/guilib/GUIAudioManager.cpp +++ b/xbmc/guilib/GUIAudioManager.cpp @@ -21,7 +21,6 @@ #include "system.h" #include "GUIAudioManager.h" #include "Key.h" -#include "settings/GUISettings.h" #include "input/ButtonTranslator.h" #include "threads/SingleLock.h" #include "utils/URIUtils.h" @@ -42,6 +41,19 @@ CGUIAudioManager::~CGUIAudioManager() { } +void CGUIAudioManager::OnSettingChanged(const CSetting *setting) +{ + if (setting == NULL) + return; + + const std::string &settingId = setting->GetId(); + if (settingId == "lookandfeel.soundskin") + { + Enable(true); + Load(); + } +} + void CGUIAudioManager::Initialize() { } @@ -189,17 +201,17 @@ bool CGUIAudioManager::Load() UnLoad(); - if (g_guiSettings.GetString("lookandfeel.soundskin")=="OFF") + if (CSettings::Get().GetString("lookandfeel.soundskin")=="OFF") return true; else Enable(true); - if (g_guiSettings.GetString("lookandfeel.soundskin")=="SKINDEFAULT") + if (CSettings::Get().GetString("lookandfeel.soundskin")=="SKINDEFAULT") { m_strMediaDir = URIUtils::AddFileToFolder(g_SkinInfo->Path(), "sounds"); } else - m_strMediaDir = URIUtils::AddFileToFolder("special://xbmc/sounds", g_guiSettings.GetString("lookandfeel.soundskin")); + m_strMediaDir = URIUtils::AddFileToFolder("special://xbmc/sounds", CSettings::Get().GetString("lookandfeel.soundskin")); CStdString strSoundsXml = URIUtils::AddFileToFolder(m_strMediaDir, "sounds.xml"); @@ -339,7 +351,7 @@ IAESound* CGUIAudioManager::LoadWindowSound(TiXmlNode* pWindowNode, const CStdSt void CGUIAudioManager::Enable(bool bEnable) { // always deinit audio when we don't want gui sounds - if (g_guiSettings.GetString("lookandfeel.soundskin")=="OFF") + if (CSettings::Get().GetString("lookandfeel.soundskin")=="OFF") bEnable = false; CSingleLock lock(m_cs); diff --git a/xbmc/guilib/GUIAudioManager.h b/xbmc/guilib/GUIAudioManager.h index 625c2b933e..99b5ba06a4 100644 --- a/xbmc/guilib/GUIAudioManager.h +++ b/xbmc/guilib/GUIAudioManager.h @@ -20,12 +20,13 @@ * */ +#include <map> + +#include "cores/AudioEngine/Interfaces/AESound.h" +#include "settings/ISettingCallback.h" #include "threads/CriticalSection.h" #include "utils/log.h" #include "utils/StdString.h" -#include "cores/AudioEngine/Interfaces/AESound.h" - -#include <map> // forward definitions class CAction; @@ -34,7 +35,7 @@ class IAESound; enum WINDOW_SOUND { SOUND_INIT = 0, SOUND_DEINIT }; -class CGUIAudioManager +class CGUIAudioManager : public ISettingCallback { class CWindowSounds { @@ -54,6 +55,8 @@ public: CGUIAudioManager(); ~CGUIAudioManager(); + virtual void OnSettingChanged(const CSetting *setting); + void Initialize(); void DeInitialize(); diff --git a/xbmc/guilib/GUIColorManager.cpp b/xbmc/guilib/GUIColorManager.cpp index f3e293c80b..b1039416db 100644 --- a/xbmc/guilib/GUIColorManager.cpp +++ b/xbmc/guilib/GUIColorManager.cpp @@ -52,9 +52,8 @@ void CGUIColorManager::Load(const CStdString &colorFile) LoadXML(xmlDoc); // first load the default color map if it exists - CStdString path, basePath; - URIUtils::AddFileToFolder(g_SkinInfo->Path(), "colors", basePath); - URIUtils::AddFileToFolder(basePath, "defaults.xml", path); + CStdString basePath = URIUtils::AddFileToFolder(g_SkinInfo->Path(), "colors"); + CStdString path = URIUtils::AddFileToFolder(basePath, "defaults.xml"); if (xmlDoc.LoadFile(CSpecialProtocol::TranslatePathConvertCase(path))) LoadXML(xmlDoc); @@ -63,7 +62,7 @@ void CGUIColorManager::Load(const CStdString &colorFile) if (colorFile.CompareNoCase("SKINDEFAULT") == 0) return; // nothing to do - URIUtils::AddFileToFolder(basePath, colorFile, path); + path = URIUtils::AddFileToFolder(basePath, colorFile); CLog::Log(LOGINFO, "Loading colors from %s", path.c_str()); if (xmlDoc.LoadFile(path)) diff --git a/xbmc/guilib/GUIControlFactory.cpp b/xbmc/guilib/GUIControlFactory.cpp index b6492e27f5..6821cbad7f 100644 --- a/xbmc/guilib/GUIControlFactory.cpp +++ b/xbmc/guilib/GUIControlFactory.cpp @@ -18,6 +18,7 @@ * */ +#include "system.h" #include "GUIControlFactory.h" #include "LocalizeStrings.h" #include "GUIButtonControl.h" @@ -59,10 +60,10 @@ #include "utils/XMLUtils.h" #include "GUIFontManager.h" #include "GUIColorManager.h" -#include "settings/Settings.h" #include "utils/RssManager.h" #include "utils/StringUtils.h" #include "GUIAction.h" +#include "utils/RssReader.h" using namespace std; using namespace EPG; diff --git a/xbmc/guilib/GUIControlGroupList.cpp b/xbmc/guilib/GUIControlGroupList.cpp index 8b4975a5a3..0bd122be15 100644 --- a/xbmc/guilib/GUIControlGroupList.cpp +++ b/xbmc/guilib/GUIControlGroupList.cpp @@ -481,6 +481,25 @@ EVENT_RESULT CGUIControlGroupList::OnMouseEvent(const CPoint &point, const CMous offset = nextOffset; } } + else if (event.m_id == ACTION_GESTURE_BEGIN) + { // grab exclusive access + CGUIMessage msg(GUI_MSG_EXCLUSIVE_MOUSE, GetID(), GetParentID()); + SendWindowMessage(msg); + return EVENT_RESULT_HANDLED; + } + else if (event.m_id == ACTION_GESTURE_END) + { // release exclusive access + CGUIMessage msg(GUI_MSG_EXCLUSIVE_MOUSE, 0, GetParentID()); + SendWindowMessage(msg); + return EVENT_RESULT_HANDLED; + } + else if (event.m_id == ACTION_GESTURE_PAN) + { // do the drag and validate our offset (corrects for end of scroll) + m_scroller.SetValue(CLAMP(m_scroller.GetValue() - ((m_orientation == HORIZONTAL) ? event.m_offsetX : event.m_offsetY), 0, m_totalSize - Size())); + SetInvalid(); + return EVENT_RESULT_HANDLED; + } + return EVENT_RESULT_UNHANDLED; } diff --git a/xbmc/guilib/GUIFadeLabelControl.cpp b/xbmc/guilib/GUIFadeLabelControl.cpp index 706d073219..ecbd69ebbc 100644 --- a/xbmc/guilib/GUIFadeLabelControl.cpp +++ b/xbmc/guilib/GUIFadeLabelControl.cpp @@ -35,7 +35,7 @@ CGUIFadeLabelControl::CGUIFadeLabelControl(int parentID, int controlID, float po m_lastLabel = -1; m_scrollSpeed = labelInfo.scrollSpeed; // save it for later m_resetOnLabelChange = resetOnLabelChange; - m_shortText = false; + m_shortText = true; } CGUIFadeLabelControl::CGUIFadeLabelControl(const CGUIFadeLabelControl &from) diff --git a/xbmc/guilib/GUIFontManager.cpp b/xbmc/guilib/GUIFontManager.cpp index e8127ef3b4..8ca6ff5c07 100644 --- a/xbmc/guilib/GUIFontManager.cpp +++ b/xbmc/guilib/GUIFontManager.cpp @@ -26,13 +26,17 @@ #include "GUIFont.h" #include "utils/XMLUtils.h" #include "GUIControlFactory.h" +#include "filesystem/Directory.h" #include "filesystem/File.h" #include "filesystem/SpecialProtocol.h" +#include "settings/Setting.h" #include "utils/log.h" #include "utils/URIUtils.h" #include "utils/StringUtils.h" #include "windowing/WindowingFactory.h" +#include "FileItem.h" #include "URL.h" +#include "Util.h" using namespace std; @@ -576,3 +580,29 @@ bool GUIFontManager::IsFontSetUnicode(const CStdString& strFontSet) return false; } + +void GUIFontManager::SettingOptionsFontsFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t) +{ + CFileItemList items; + CFileItemList items2; + + // find TTF fonts + XFILE::CDirectory::GetDirectory("special://home/media/Fonts/", items2); + + if (XFILE::CDirectory::GetDirectory("special://xbmc/media/Fonts/", items)) + { + items.Append(items2); + for (int i = 0; i < items.Size(); ++i) + { + CFileItemPtr pItem = items[i]; + + if (!pItem->m_bIsFolder) + { + if (!URIUtils::GetExtension(pItem->GetLabel()).Equals(".ttf")) + continue; + + list.push_back(make_pair(pItem->GetLabel(), pItem->GetLabel())); + } + } + } +} diff --git a/xbmc/guilib/GUIFontManager.h b/xbmc/guilib/GUIFontManager.h index 40f8227a0d..48b8e27d74 100644 --- a/xbmc/guilib/GUIFontManager.h +++ b/xbmc/guilib/GUIFontManager.h @@ -37,6 +37,7 @@ class CGUIFont; class CGUIFontTTFBase; class CXBMCTinyXML; class TiXmlNode; +class CSetting; struct OrigFontInfo { @@ -82,6 +83,8 @@ public: void ReloadTTFFonts(); void UnloadTTFFonts(); + static void SettingOptionsFontsFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t); + protected: void RescaleFontSizeAndAspect(float *size, float *aspect, const RESOLUTION_INFO &sourceRes, bool preserveAspect) const; void LoadFonts(const TiXmlNode* fontNode); diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp index 4071c081e5..ef3018c45f 100644 --- a/xbmc/guilib/GUIFontTTF.cpp +++ b/xbmc/guilib/GUIFontTTF.cpp @@ -27,7 +27,6 @@ #include "utils/MathUtils.h" #include "utils/log.h" #include "windowing/WindowingFactory.h" -#include "settings/GUISettings.h" #include <math.h> diff --git a/xbmc/guilib/GUIKeyboardFactory.cpp b/xbmc/guilib/GUIKeyboardFactory.cpp index a019b95c95..493f995e36 100644 --- a/xbmc/guilib/GUIKeyboardFactory.cpp +++ b/xbmc/guilib/GUIKeyboardFactory.cpp @@ -19,13 +19,13 @@ */ #include "Application.h" +#include "ApplicationMessenger.h" #include "LocalizeStrings.h" #include "GUIKeyboardFactory.h" #include "dialogs/GUIDialogOK.h" #include "GUIUserMessages.h" #include "GUIWindowManager.h" -#include "settings/GUISettings.h" -#include "ApplicationMessenger.h" +#include "settings/Settings.h" #include "utils/md5.h" @@ -190,7 +190,7 @@ int CGUIKeyboardFactory::ShowAndVerifyPassword(CStdString& strPassword, const CS if (1 > iRetries && strHeading.size()) strHeadingTemp = strHeading; else - strHeadingTemp.Format("%s - %i %s", g_localizeStrings.Get(12326).c_str(), g_guiSettings.GetInt("masterlock.maxretries") - iRetries, g_localizeStrings.Get(12343).c_str()); + strHeadingTemp.Format("%s - %i %s", g_localizeStrings.Get(12326).c_str(), CSettings::Get().GetInt("masterlock.maxretries") - iRetries, g_localizeStrings.Get(12343).c_str()); CStdString strUserInput = ""; if (!ShowAndGetInput(strUserInput, strHeadingTemp, false, true, autoCloseMs)) //bool hiddenInput = false/true ? TODO: GUI Setting to enable disable this feature y/n? diff --git a/xbmc/guilib/GUIListContainer.cpp b/xbmc/guilib/GUIListContainer.cpp index 6e11a6dfff..9b0243e6bf 100644 --- a/xbmc/guilib/GUIListContainer.cpp +++ b/xbmc/guilib/GUIListContainer.cpp @@ -18,6 +18,7 @@ * */ +#include "system.h" #include "GUIListContainer.h" #include "GUIListItem.h" #include "Key.h" diff --git a/xbmc/guilib/GUIListItemLayout.cpp b/xbmc/guilib/GUIListItemLayout.cpp index ba45efb628..d0dbeb6068 100644 --- a/xbmc/guilib/GUIListItemLayout.cpp +++ b/xbmc/guilib/GUIListItemLayout.cpp @@ -18,6 +18,7 @@ * */ +#include "system.h" #include "GUIListItemLayout.h" #include "FileItem.h" #include "GUIControlFactory.h" @@ -107,16 +108,22 @@ unsigned int CGUIListItemLayout::GetFocusedItem() const void CGUIListItemLayout::SetWidth(float width) { - m_group.EnlargeWidth(width - m_width); - m_width = width; - SetInvalid(); + if (m_width != width) + { + m_group.EnlargeWidth(width - m_width); + m_width = width; + SetInvalid(); + } } void CGUIListItemLayout::SetHeight(float height) { - m_group.EnlargeHeight(height - m_height); - m_height = height; - SetInvalid(); + if (m_height != height) + { + m_group.EnlargeHeight(height - m_height); + m_height = height; + SetInvalid(); + } } void CGUIListItemLayout::SelectItemFromPoint(const CPoint &point) diff --git a/xbmc/guilib/GUIRSSControl.cpp b/xbmc/guilib/GUIRSSControl.cpp index 6dbf3be529..51c2454a39 100644 --- a/xbmc/guilib/GUIRSSControl.cpp +++ b/xbmc/guilib/GUIRSSControl.cpp @@ -20,7 +20,7 @@ #include "GUIRSSControl.h" #include "GUIWindowManager.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "threads/CriticalSection.h" #include "threads/SingleLock.h" #include "utils/RssManager.h" @@ -112,7 +112,7 @@ void CGUIRSSControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyre void CGUIRSSControl::Render() { // only render the control if they are enabled - if (g_guiSettings.GetBool("lookandfeel.enablerssfeeds") && CRssManager::Get().IsActive()) + if (CSettings::Get().GetBool("lookandfeel.enablerssfeeds") && CRssManager::Get().IsActive()) { CSingleLock lock(m_criticalSection); // Create RSS background/worker thread if needed diff --git a/xbmc/guilib/GUISpinControl.cpp b/xbmc/guilib/GUISpinControl.cpp index 660bf8e738..c141cf286a 100644 --- a/xbmc/guilib/GUISpinControl.cpp +++ b/xbmc/guilib/GUISpinControl.cpp @@ -207,8 +207,9 @@ void CGUISpinControl::OnRight() void CGUISpinControl::Clear() { - m_vecLabels.erase(m_vecLabels.begin(), m_vecLabels.end()); - m_vecValues.erase(m_vecValues.begin(), m_vecValues.end()); + m_vecLabels.clear(); + m_vecValues.clear(); + m_vecStrValues.clear(); SetValue(0); } @@ -492,7 +493,6 @@ void CGUISpinControl::SetRange(int iStart, int iEnd) m_iEnd = iEnd; } - void CGUISpinControl::SetFloatRange(float fStart, float fEnd) { m_fStart = fStart; @@ -532,6 +532,19 @@ void CGUISpinControl::SetFloatValue(float fValue) m_fValue = fValue; } +void CGUISpinControl::SetStringValue(const std::string& strValue) +{ + if (m_iType == SPIN_CONTROL_TYPE_TEXT) + { + m_iValue = 0; + for (unsigned int i = 0; i < m_vecStrValues.size(); i++) + if (strValue == m_vecStrValues[i]) + m_iValue = i; + } + + SetInvalid(); +} + int CGUISpinControl::GetValue() const { if (m_iType == SPIN_CONTROL_TYPE_TEXT) @@ -547,6 +560,17 @@ float CGUISpinControl::GetFloatValue() const return m_fValue; } +std::string CGUISpinControl::GetStringValue() const +{ + if (m_iType == SPIN_CONTROL_TYPE_TEXT && m_iValue >= 0 && m_iValue < (int)m_vecLabels.size()) + { + if (m_iValue < (int)m_vecStrValues.size()) + return m_vecStrValues[m_iValue]; + + return m_vecLabels[m_iValue]; + } + return ""; +} void CGUISpinControl::AddLabel(const string& strLabel, int iValue) { @@ -554,11 +578,17 @@ void CGUISpinControl::AddLabel(const string& strLabel, int iValue) m_vecValues.push_back(iValue); } +void CGUISpinControl::AddLabel(const string& strLabel, const string& strValue) +{ + m_vecLabels.push_back(strLabel); + m_vecStrValues.push_back(strValue); +} + const string CGUISpinControl::GetLabel() const { if (m_iValue >= 0 && m_iValue < (int)m_vecLabels.size()) { - return m_vecLabels[ m_iValue]; + return m_vecLabels[m_iValue]; } return ""; } diff --git a/xbmc/guilib/GUISpinControl.h b/xbmc/guilib/GUISpinControl.h index 3f2a54aaa5..5624ce148c 100644 --- a/xbmc/guilib/GUISpinControl.h +++ b/xbmc/guilib/GUISpinControl.h @@ -67,9 +67,12 @@ public: void SetValue(int iValue); void SetValueFromLabel(const CStdString &label); void SetFloatValue(float fValue); + void SetStringValue(const std::string& strValue); int GetValue() const; float GetFloatValue() const; + std::string GetStringValue() const; void AddLabel(const std::string& strLabel, int iValue); + void AddLabel(const std::string& strLabel, const std::string& strValue); const std::string GetLabel() const; void SetReverse(bool bOnOff); int GetMaximum() const; @@ -117,6 +120,7 @@ protected: float m_fInterval; std::vector<std::string> m_vecLabels; std::vector<int> m_vecValues; + std::vector<std::string> m_vecStrValues; CGUITexture m_imgspinUp; CGUITexture m_imgspinDown; CGUITexture m_imgspinUpFocus; diff --git a/xbmc/guilib/GUIVideoControl.cpp b/xbmc/guilib/GUIVideoControl.cpp index 4f159e15ea..7d322ba7f3 100644 --- a/xbmc/guilib/GUIVideoControl.cpp +++ b/xbmc/guilib/GUIVideoControl.cpp @@ -43,7 +43,8 @@ CGUIVideoControl::~CGUIVideoControl(void) void CGUIVideoControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions) { // TODO Proper processing which marks when its actually changed. Just mark always for now. - MarkDirtyRegion(); + if (g_renderManager.RendererHandlesPresent()) + MarkDirtyRegion(); CGUIControl::Process(currentTime, dirtyregions); } diff --git a/xbmc/guilib/GUIWindow.cpp b/xbmc/guilib/GUIWindow.cpp index db92847842..5e400769dd 100644 --- a/xbmc/guilib/GUIWindow.cpp +++ b/xbmc/guilib/GUIWindow.cpp @@ -26,7 +26,6 @@ #include "GUIControlFactory.h" #include "GUIControlGroup.h" #include "GUIControlProfiler.h" -#include "settings/Settings.h" #ifdef PRE_SKIN_VERSION_9_10_COMPATIBILITY #include "GUIEditControl.h" #endif diff --git a/xbmc/guilib/GUIWindowManager.cpp b/xbmc/guilib/GUIWindowManager.cpp index b4d7b59d8f..039d3b1eeb 100644 --- a/xbmc/guilib/GUIWindowManager.cpp +++ b/xbmc/guilib/GUIWindowManager.cpp @@ -27,8 +27,8 @@ #include "GUIInfoManager.h" #include "threads/SingleLock.h" #include "utils/URIUtils.h" -#include "settings/GUISettings.h" #include "settings/AdvancedSettings.h" +#include "settings/Settings.h" #include "addons/Skin.h" #include "GUITexture.h" #include "windowing/WindowingFactory.h" @@ -360,7 +360,7 @@ void CGUIWindowManager::ActivateWindow_Internal(int iWindowID, const vector<CStd // virtual music window which returns the last open music window (aka the music start window) if (iWindowID == WINDOW_MUSIC) { - iWindowID = g_guiSettings.GetInt("mymusic.startwindow"); + iWindowID = CSettings::Get().GetInt("mymusic.startwindow"); // ensure the music virtual window only returns music files and music library windows if (iWindowID != WINDOW_MUSIC_NAV) iWindowID = WINDOW_MUSIC_FILES; diff --git a/xbmc/guilib/GraphicContext.cpp b/xbmc/guilib/GraphicContext.cpp index 6d88955dbc..71367ed9bf 100644 --- a/xbmc/guilib/GraphicContext.cpp +++ b/xbmc/guilib/GraphicContext.cpp @@ -23,9 +23,9 @@ #include "threads/SingleLock.h" #include "Application.h" #include "ApplicationMessenger.h" -#include "settings/DisplaySettings.h" -#include "settings/GUISettings.h" #include "settings/AdvancedSettings.h" +#include "settings/DisplaySettings.h" +#include "settings/Settings.h" #include "cores/VideoRenderers/RenderManager.h" #include "windowing/WindowingFactory.h" #include "TextureManager.h" @@ -67,6 +67,19 @@ CGraphicContext::~CGraphicContext(void) { } +void CGraphicContext::OnSettingChanged(const CSetting *setting) +{ + if (setting == NULL) + return; + + const std::string &settingId = setting->GetId(); + if (settingId == "videoscreen.fakefullscreen") + { + if (IsFullScreenRoot()) + SetVideoResolution(GetVideoResolution(), true); + } +} + void CGraphicContext::SetOrigin(float x, float y) { if (m_origins.size()) @@ -279,7 +292,7 @@ void CGraphicContext::SetFullScreenVideo(bool bOnOff) #if defined(HAS_VIDEO_PLAYBACK) if(m_bFullScreenRoot) { - bool allowDesktopRes = g_guiSettings.GetInt("videoplayer.adjustrefreshrate") == ADJUST_REFRESHRATE_ALWAYS; + bool allowDesktopRes = CSettings::Get().GetInt("videoplayer.adjustrefreshrate") == ADJUST_REFRESHRATE_ALWAYS; if(m_bFullScreenVideo || (!allowDesktopRes && g_application.IsPlayingVideo())) SetVideoResolution(g_renderManager.GetResolution()); else if(CDisplaySettings::Get().GetCurrentResolution() > RES_DESKTOP) @@ -340,8 +353,8 @@ void CGraphicContext::SetVideoResolution(RESOLUTION res, bool forceUpdate) if ((res != RES_DESKTOP && res != RES_WINDOW) || (lastRes != RES_DESKTOP && lastRes != RES_WINDOW)) { //pause the player during the refreshrate change - int delay = g_guiSettings.GetInt("videoplayer.pauseafterrefreshchange"); - if (delay > 0 && g_guiSettings.GetInt("videoplayer.adjustrefreshrate") != ADJUST_REFRESHRATE_OFF && g_application.IsPlayingVideo() && !g_application.IsPaused()) + int delay = CSettings::Get().GetInt("videoplayer.pauseafterrefreshchange"); + if (delay > 0 && CSettings::Get().GetInt("videoplayer.adjustrefreshrate") != ADJUST_REFRESHRATE_OFF && g_application.IsPlayingVideo() && !g_application.IsPaused()) { g_application.m_pPlayer->Pause(); ThreadMessage msg = {TMSG_MEDIA_UNPAUSE}; @@ -375,7 +388,7 @@ void CGraphicContext::SetVideoResolution(RESOLUTION res, bool forceUpdate) if (g_advancedSettings.m_fullScreen) { #if defined (TARGET_DARWIN) || defined (_WIN32) - bool blankOtherDisplays = g_guiSettings.GetBool("videoscreen.blankdisplays"); + bool blankOtherDisplays = CSettings::Get().GetBool("videoscreen.blankdisplays"); g_Windowing.SetFullScreen(true, CDisplaySettings::Get().GetResolutionInfo(res), blankOtherDisplays); #else g_Windowing.SetFullScreen(true, CDisplaySettings::Get().GetResolutionInfo(res), false); @@ -637,11 +650,11 @@ void CGraphicContext::SetScalingResolution(const RESOLUTION_INFO &res, bool need } if(!g_guiSkinzoom) // lookup gui setting if we didn't have it already - g_guiSkinzoom = (CSettingInt*)g_guiSettings.GetSetting("lookandfeel.skinzoom"); + g_guiSkinzoom = (CSettingInt*)CSettings::Get().GetSetting("lookandfeel.skinzoom"); float fZoom = 1.0f; if(g_guiSkinzoom) - fZoom *= (100 + g_guiSkinzoom->GetData()) * 0.01f; + fZoom *= (100 + g_guiSkinzoom->GetValue()) * 0.01f; fZoom -= 1.0f; fToPosX -= fToWidth * fZoom * 0.5f; diff --git a/xbmc/guilib/GraphicContext.h b/xbmc/guilib/GraphicContext.h index 0ce3087d2b..adbbae41d8 100644 --- a/xbmc/guilib/GraphicContext.h +++ b/xbmc/guilib/GraphicContext.h @@ -47,6 +47,7 @@ #include "Resolution.h" #include "utils/GlobalsHandling.h" #include "DirtyRegion.h" +#include "settings/ISettingCallback.h" enum VIEW_TYPE { VIEW_TYPE_NONE = 0, VIEW_TYPE_LIST, @@ -62,13 +63,22 @@ enum VIEW_TYPE { VIEW_TYPE_NONE = 0, VIEW_TYPE_AUTO, VIEW_TYPE_MAX }; +enum AdjustRefreshRate +{ + ADJUST_REFRESHRATE_OFF = 0, + ADJUST_REFRESHRATE_ALWAYS, + ADJUST_REFRESHRATE_ON_STARTSTOP +}; -class CGraphicContext : public CCriticalSection +class CGraphicContext : public CCriticalSection, + public ISettingCallback { public: CGraphicContext(void); virtual ~CGraphicContext(void); + virtual void OnSettingChanged(const CSetting *setting); + // the following two functions should wrap any // GL calls to maintain thread safety void BeginPaint(bool lock=true); diff --git a/xbmc/guilib/Key.h b/xbmc/guilib/Key.h index bc1acb8a09..960c8e3430 100644 --- a/xbmc/guilib/Key.h +++ b/xbmc/guilib/Key.h @@ -315,6 +315,9 @@ #define ACTION_SWITCH_PLAYER 234 +#define ACTION_SETTINGS_RESET 240 +#define ACTION_SETTINGS_LEVEL_CHANGE 241 + // touch actions #define ACTION_TOUCH_TAP 401 #define ACTION_TOUCH_TAP_TEN 410 diff --git a/xbmc/guilib/TextureBundleXBT.cpp b/xbmc/guilib/TextureBundleXBT.cpp index fa8e863795..ce366c27b7 100644 --- a/xbmc/guilib/TextureBundleXBT.cpp +++ b/xbmc/guilib/TextureBundleXBT.cpp @@ -25,7 +25,7 @@ #include "GraphicContext.h" #include "utils/log.h" #include "addons/Skin.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "filesystem/SpecialProtocol.h" #include "utils/EndianSwap.h" #include "utils/URIUtils.h" @@ -58,7 +58,7 @@ bool CTextureBundleXBT::OpenBundle() { // if we are the theme bundle, we only load if the user has chosen // a valid theme (or the skin has a default one) - CStdString theme = g_guiSettings.GetString("lookandfeel.skintheme"); + CStdString theme = CSettings::Get().GetString("lookandfeel.skintheme"); if (!theme.IsEmpty() && theme.CompareNoCase("SKINDEFAULT")) { CStdString themeXBT(URIUtils::ReplaceExtension(theme, ".xbt")); diff --git a/xbmc/guilib/TextureBundleXPR.cpp b/xbmc/guilib/TextureBundleXPR.cpp index f9c8aae6f3..20b50b5877 100644 --- a/xbmc/guilib/TextureBundleXPR.cpp +++ b/xbmc/guilib/TextureBundleXPR.cpp @@ -30,7 +30,7 @@ #endif #include <lzo/lzo1x.h> #include "addons/Skin.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "filesystem/SpecialProtocol.h" #include "utils/EndianSwap.h" #include "utils/URIUtils.h" @@ -125,7 +125,7 @@ bool CTextureBundleXPR::OpenBundle() { // if we are the theme bundle, we only load if the user has chosen // a valid theme (or the skin has a default one) - CStdString theme = g_guiSettings.GetString("lookandfeel.skintheme"); + CStdString theme = CSettings::Get().GetString("lookandfeel.skintheme"); if (!theme.IsEmpty() && theme.CompareNoCase("SKINDEFAULT")) { CStdString themeXPR(URIUtils::ReplaceExtension(theme, ".xpr")); diff --git a/xbmc/input/ButtonTranslator.cpp b/xbmc/input/ButtonTranslator.cpp index 6f71b53474..d4ff71dc75 100644 --- a/xbmc/input/ButtonTranslator.cpp +++ b/xbmc/input/ButtonTranslator.cpp @@ -220,6 +220,8 @@ static const ActionMapping actions[] = {"volampdown" , ACTION_VOLAMP_DOWN}, {"createbookmark" , ACTION_CREATE_BOOKMARK}, {"createepisodebookmark" , ACTION_CREATE_EPISODE_BOOKMARK}, + {"settingsreset" , ACTION_SETTINGS_RESET}, + {"settingslevelchange", ACTION_SETTINGS_LEVEL_CHANGE}, // PVR actions {"channelup" , ACTION_CHANNEL_UP}, @@ -562,8 +564,7 @@ bool CButtonTranslator::Load(bool AlwaysLoad) #else #define REMOTEMAP "IRSSmap.xml" #endif - CStdString lircmapPath; - URIUtils::AddFileToFolder("special://xbmc/system/", REMOTEMAP, lircmapPath); + CStdString lircmapPath = URIUtils::AddFileToFolder("special://xbmc/system/", REMOTEMAP); lircRemotesMap.clear(); if(CFile::Exists(lircmapPath)) success |= LoadLircMap(lircmapPath); diff --git a/xbmc/input/ButtonTranslator.h b/xbmc/input/ButtonTranslator.h index 6280ae47dc..4b26a9fe0b 100644 --- a/xbmc/input/ButtonTranslator.h +++ b/xbmc/input/ButtonTranslator.h @@ -30,6 +30,7 @@ #ifdef HAS_EVENT_SERVER #include "network/EventClient.h" #endif +#include "utils/StdString.h" class CKey; class CAction; diff --git a/xbmc/input/MouseStat.cpp b/xbmc/input/MouseStat.cpp index cef30c3907..954ad1fc37 100644 --- a/xbmc/input/MouseStat.cpp +++ b/xbmc/input/MouseStat.cpp @@ -20,8 +20,9 @@ #include "MouseStat.h" #include "guilib/Key.h" -#include "windowing/WindowingFactory.h" +#include "settings/Setting.h" #include "utils/TimeUtils.h" +#include "windowing/WindowingFactory.h" CMouseStat::CMouseStat() { @@ -37,6 +38,16 @@ CMouseStat::~CMouseStat() { } +void CMouseStat::OnSettingChanged(const CSetting *setting) +{ + if (setting == NULL) + return; + + const std::string &settingId = setting->GetId(); + if (settingId == "input.enablemouse") + SetEnabled(((CSettingBool*)setting)->GetValue()); +} + void CMouseStat::Initialize() { // Set the default resolution (PAL) diff --git a/xbmc/input/MouseStat.h b/xbmc/input/MouseStat.h index f6822ea9e4..71a70ec81f 100644 --- a/xbmc/input/MouseStat.h +++ b/xbmc/input/MouseStat.h @@ -21,6 +21,7 @@ * */ +#include "settings/ISettingCallback.h" #include "windowing/XBMC_events.h" #define XBMC_BUTTON(X) (1 << ((X)-1)) @@ -58,13 +59,14 @@ struct MouseState class CAction; -class CMouseStat +class CMouseStat : public ISettingCallback { public: - CMouseStat(); virtual ~CMouseStat(); + virtual void OnSettingChanged(const CSetting *setting); + void Initialize(); void HandleEvent(XBMC_Event& newEvent); void SetResolution(int maxX, int maxY, float speedX, float speedY); diff --git a/xbmc/input/SDLJoystick.cpp b/xbmc/input/SDLJoystick.cpp index ab556fc965..fd8597af47 100644 --- a/xbmc/input/SDLJoystick.cpp +++ b/xbmc/input/SDLJoystick.cpp @@ -21,6 +21,7 @@ #include "system.h" #include "SDLJoystick.h" #include "ButtonTranslator.h" +#include "peripherals/devices/PeripheralImon.h" #include "settings/AdvancedSettings.h" #include "utils/log.h" @@ -45,6 +46,16 @@ CJoystick::CJoystick() SetDeadzone(0); } +void CJoystick::OnSettingChanged(const CSetting *setting) +{ + if (setting == NULL) + return; + + const std::string &settingId = setting->GetId(); + if (settingId == "input.enablejoystick") + SetEnabled(((CSettingBool*)setting)->GetValue() && PERIPHERALS::CPeripheralImon::GetCountOfImonsConflictWithDInput() == 0); +} + void CJoystick::Initialize() { if (!IsEnabled()) diff --git a/xbmc/input/SDLJoystick.h b/xbmc/input/SDLJoystick.h index 7bd336c1d8..4b07458c1a 100644 --- a/xbmc/input/SDLJoystick.h +++ b/xbmc/input/SDLJoystick.h @@ -22,6 +22,7 @@ #define SDL_JOYSTICK_H #include "system.h" // for HAS_SDL_JOYSTICK +#include "settings/ISettingCallback.h" #include <vector> #include <string> @@ -45,11 +46,13 @@ // Class to manage all connected joysticks -class CJoystick +class CJoystick : public ISettingCallback { public: CJoystick(); + virtual void OnSettingChanged(const CSetting *setting); + void Initialize(); void Reset(bool axis=false); void ResetAxis(int axisId) { m_Amount[axisId] = 0; } diff --git a/xbmc/input/linux/LinuxInputDevices.cpp b/xbmc/input/linux/LinuxInputDevices.cpp index 1d3d3155ff..458f74081b 100644 --- a/xbmc/input/linux/LinuxInputDevices.cpp +++ b/xbmc/input/linux/LinuxInputDevices.cpp @@ -986,7 +986,6 @@ bool CLinuxInputDevices::CheckDevice(const char *device) { int fd; - CLog::Log(LOGDEBUG, "Checking device: %s\n", device); /* Check if we are able to open the device */ fd = open(device, O_RDWR); if (fd < 0) diff --git a/xbmc/input/windows/WINJoystick.cpp b/xbmc/input/windows/WINJoystick.cpp index 293593be0c..02dc08c125 100644 --- a/xbmc/input/windows/WINJoystick.cpp +++ b/xbmc/input/windows/WINJoystick.cpp @@ -20,7 +20,9 @@ #include "WINJoystick.h" #include "input/ButtonTranslator.h" +#include "peripherals/devices/PeripheralImon.h" #include "settings/AdvancedSettings.h" +#include "settings/Setting.h" #include "utils/log.h" #include <math.h> @@ -72,6 +74,16 @@ CJoystick::~CJoystick() ReleaseJoysticks(); } +void CJoystick::OnSettingChanged(const CSetting *setting) +{ + if (setting == NULL) + return; + + const std::string &settingId = setting->GetId(); + if (settingId == "input.enablejoystick") + SetEnabled(((CSettingBool*)setting)->GetValue() && PERIPHERALS::CPeripheralImon::GetCountOfImonsConflictWithDInput() == 0); +} + void CJoystick::ReleaseJoysticks() { CSingleLock lock(m_critSection); diff --git a/xbmc/input/windows/WINJoystick.h b/xbmc/input/windows/WINJoystick.h index f77c96e787..b6da4612ee 100644 --- a/xbmc/input/windows/WINJoystick.h +++ b/xbmc/input/windows/WINJoystick.h @@ -21,6 +21,7 @@ #include <vector> #include <string> +#include "settings/ISettingCallback.h" #include "threads/CriticalSection.h" #define JACTIVE_BUTTON 0x00000001 @@ -36,12 +37,14 @@ // Class to manage all connected joysticks -class CJoystick +class CJoystick : public ISettingCallback { public: CJoystick(); ~CJoystick(); + virtual void OnSettingChanged(const CSetting *setting); + void Initialize(); void Reset(bool axis=false); void ResetAxis(int axisId) { m_Amount[axisId] = 0; } diff --git a/xbmc/interfaces/Builtins.cpp b/xbmc/interfaces/Builtins.cpp index 660023324a..8b73ecdacc 100644 --- a/xbmc/interfaces/Builtins.cpp +++ b/xbmc/interfaces/Builtins.cpp @@ -44,6 +44,7 @@ #include "addons/AddonInstaller.h" #include "addons/AddonManager.h" #include "addons/PluginSource.h" +#include "network/NetworkServices.h" #include "utils/log.h" #include "storage/MediaManager.h" #include "utils/RssManager.h" @@ -93,7 +94,8 @@ #endif #include <vector> -#include "xbmc/settings/AdvancedSettings.h" +#include "settings/AdvancedSettings.h" +#include "settings/DisplaySettings.h" using namespace std; using namespace XFILE; @@ -636,6 +638,18 @@ int CBuiltins::Execute(const CStdString& execString) } } } + else if (execute.Equals("showPicture")) + { + if (!params.size()) + { + CLog::Log(LOGERROR, "XBMC.ShowPicture called with empty parameter"); + return -2; + } + CGUIMessage msg(GUI_MSG_SHOW_PICTURE, 0, 0); + msg.SetStringParam(params[0]); + CGUIWindow *pWindow = g_windowManager.GetWindow(WINDOW_SLIDESHOW); + if (pWindow) pWindow->OnMessage(msg); + } else if (execute.Equals("slideShow") || execute.Equals("recursiveslideShow")) { if (!params.size()) @@ -768,7 +782,6 @@ int CBuiltins::Execute(const CStdString& execString) else if (parameter.Left(14).Equals("seekpercentage")) { CStdString offset = ""; - float offsetpercent; if (parameter.size() == 14) CLog::Log(LOGERROR,"PlayerControl(seekpercentage(n)) called with no argument"); else if (parameter.size() < 17) // arg must be at least "(N)" @@ -777,7 +790,7 @@ int CBuiltins::Execute(const CStdString& execString) { // Don't bother checking the argument: an invalid arg will do seek(0) offset = parameter.Mid(15).TrimRight(")"); - offsetpercent = (float) atof(offset.c_str()); + float offsetpercent = (float) atof(offset.c_str()); if (offsetpercent < 0 || offsetpercent > 100) CLog::Log(LOGERROR,"PlayerControl(seekpercentage(n)) argument, %f, must be 0-100", offsetpercent); else if (g_application.IsPlaying()) @@ -835,11 +848,11 @@ int CBuiltins::Execute(const CStdString& execString) { case PLAYLIST_MUSIC: CMediaSettings::Get().SetMusicPlaylistShuffled(g_playlistPlayer.IsShuffled(iPlaylist)); - g_settings.Save(); + CSettings::Get().Save(); break; case PLAYLIST_VIDEO: CMediaSettings::Get().SetVideoPlaylistShuffled(g_playlistPlayer.IsShuffled(iPlaylist)); - g_settings.Save(); + CSettings::Get().Save(); } // send message @@ -879,11 +892,11 @@ int CBuiltins::Execute(const CStdString& execString) { case PLAYLIST_MUSIC: CMediaSettings::Get().SetMusicPlaylistRepeat(state == PLAYLIST::REPEAT_ALL); - g_settings.Save(); + CSettings::Get().Save(); break; case PLAYLIST_VIDEO: CMediaSettings::Get().SetVideoPlaylistRepeat(state == PLAYLIST::REPEAT_ALL); - g_settings.Save(); + CSettings::Get().Save(); } // send messages so now playing window can get updated @@ -1044,7 +1057,7 @@ int CBuiltins::Execute(const CStdString& execString) { int setting = CSkinSettings::Get().TranslateBool(parameter); CSkinSettings::Get().SetBool(setting, !CSkinSettings::Get().GetBool(setting)); - g_settings.Save(); + CSettings::Get().Save(); } else if (execute.Equals("skin.setbool") && params.size()) { @@ -1052,23 +1065,23 @@ int CBuiltins::Execute(const CStdString& execString) { int string = CSkinSettings::Get().TranslateBool(params[0]); CSkinSettings::Get().SetBool(string, params[1].CompareNoCase("true") == 0); - g_settings.Save(); + CSettings::Get().Save(); return 0; } // default is to set it to true int setting = CSkinSettings::Get().TranslateBool(params[0]); CSkinSettings::Get().SetBool(setting, true); - g_settings.Save(); + CSettings::Get().Save(); } else if (execute.Equals("skin.reset")) { CSkinSettings::Get().Reset(parameter); - g_settings.Save(); + CSettings::Get().Save(); } else if (execute.Equals("skin.resetsettings")) { CSkinSettings::Get().Reset(); - g_settings.Save(); + CSettings::Get().Save(); } else if (execute.Equals("skin.theme")) { @@ -1079,11 +1092,11 @@ int CBuiltins::Execute(const CStdString& execString) int iTheme = -1; // find current theme - if (!g_guiSettings.GetString("lookandfeel.skintheme").Equals("SKINDEFAULT")) + if (!StringUtils::EqualsNoCase(CSettings::Get().GetString("lookandfeel.skintheme"), "SKINDEFAULT")) { for (unsigned int i=0;i<vecTheme.size();++i) { - CStdString strTmpTheme(g_guiSettings.GetString("lookandfeel.skintheme")); + CStdString strTmpTheme(CSettings::Get().GetString("lookandfeel.skintheme")); URIUtils::RemoveExtension(strTmpTheme); if (vecTheme[i].Equals(strTmpTheme)) { @@ -1107,12 +1120,12 @@ int CBuiltins::Execute(const CStdString& execString) if (iTheme != -1 && iTheme < (int)vecTheme.size()) strSkinTheme = vecTheme[iTheme]; - g_guiSettings.SetString("lookandfeel.skintheme", strSkinTheme); + CSettings::Get().SetString("lookandfeel.skintheme", strSkinTheme); // also set the default color theme CStdString colorTheme(URIUtils::ReplaceExtension(strSkinTheme, ".xml")); if (colorTheme.Equals("Textures.xml")) colorTheme = "defaults.xml"; - g_guiSettings.SetString("lookandfeel.skincolors", colorTheme); + CSettings::Get().SetString("lookandfeel.skincolors", colorTheme); g_application.ReloadSkin(); } else if (execute.Equals("skin.setstring") || execute.Equals("skin.setimage") || execute.Equals("skin.setfile") || @@ -1126,7 +1139,7 @@ int CBuiltins::Execute(const CStdString& execString) if (execute.Equals("skin.setstring")) { CSkinSettings::Get().SetString(string, params[1]); - g_settings.Save(); + CSettings::Get().Save(); return 0; } } @@ -1225,7 +1238,7 @@ int CBuiltins::Execute(const CStdString& execString) if (CGUIDialogFileBrowser::ShowAndGetDirectory(localShares, g_localizeStrings.Get(1031), value)) CSkinSettings::Get().SetString(string, value); } - g_settings.Save(); + CSettings::Get().Save(); } else if (execute.Equals("skin.setaddon") && params.size() > 1) { @@ -1241,7 +1254,7 @@ int CBuiltins::Execute(const CStdString& execString) if (types.size() > 0 && CGUIWindowAddonBrowser::SelectAddonID(types, result, true) == 1) { CSkinSettings::Get().SetString(string, result); - g_settings.Save(); + CSettings::Get().Save(); } } else if (execute.Equals("dialog.close") && params.size()) @@ -1282,8 +1295,8 @@ int CBuiltins::Execute(const CStdString& execString) CProfilesManager::Get().LoadMasterProfileForLogin(); g_passwordManager.bMasterUser = false; g_windowManager.ActivateWindow(WINDOW_LOGIN_SCREEN); - if (!g_application.StartEventServer()) // event server could be needed in some situations - CGUIDialogKaiToast::QueueNotification("DefaultIconWarning.png", g_localizeStrings.Get(33102), g_localizeStrings.Get(33100)); + if (!CNetworkServices::Get().StartEventServer()) // event server could be needed in some situations + CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Warning, g_localizeStrings.Get(33102), g_localizeStrings.Get(33100)); } else if (execute.Equals("pagedown")) { @@ -1408,7 +1421,7 @@ int CBuiltins::Execute(const CStdString& execString) else { if (URIUtils::HasSlashAtEnd(path)) - URIUtils::AddFileToFolder(path, "musicdb.xml", path); + path = URIUtils::AddFileToFolder(path, "musicdb.xml"); CMusicDatabase musicdatabase; musicdatabase.Open(); musicdatabase.ExportToXML(path, singleFile, thumbs, overwrite); @@ -1623,8 +1636,8 @@ int CBuiltins::Execute(const CStdString& execString) } else if (execute.Equals("toggledebug")) { - bool debug = g_guiSettings.GetBool("debug.showloginfo"); - g_guiSettings.SetBool("debug.showloginfo", !debug); + bool debug = CSettings::Get().GetBool("debug.showloginfo"); + CSettings::Get().SetBool("debug.showloginfo", !debug); g_advancedSettings.SetDebugMode(!debug); } else if (execute.Equals("startpvrmanager")) diff --git a/xbmc/interfaces/info/InfoBool.cpp b/xbmc/interfaces/info/InfoBool.cpp index f35dd313d1..1def87b8f3 100644 --- a/xbmc/interfaces/info/InfoBool.cpp +++ b/xbmc/interfaces/info/InfoBool.cpp @@ -92,7 +92,7 @@ void InfoExpression::Parse(const CStdString &expression) // handle closing parenthesis if (expression[i] == ']') { - while (operators.size()) + while (!operators.empty()) { char oper = operators.top(); operators.pop(); @@ -156,7 +156,7 @@ bool InfoExpression::Evaluate(const CGUIListItem *item, bool &result) short expr = *it; if (expr == -OPERATOR_NOT) { // NOT the top item on the stack - if (save.size() < 1) return false; + if (save.empty()) return false; bool expr = save.top(); save.pop(); save.push(!expr); diff --git a/xbmc/interfaces/info/SkinVariable.cpp b/xbmc/interfaces/info/SkinVariable.cpp index 22917a922a..abc86bc67b 100644 --- a/xbmc/interfaces/info/SkinVariable.cpp +++ b/xbmc/interfaces/info/SkinVariable.cpp @@ -76,7 +76,7 @@ const CStdString& CSkinVariableString::GetName() const CStdString CSkinVariableString::GetValue(bool preferImage /* = false*/, const CGUIListItem *item /* = NULL */) { - for (VECCONDITIONLABELPAIR::const_iterator it = m_conditionLabelPairs.begin() ; it != m_conditionLabelPairs.end(); it++) + for (VECCONDITIONLABELPAIR::const_iterator it = m_conditionLabelPairs.begin() ; it != m_conditionLabelPairs.end(); ++it) { if (it->m_condition == DEFAULT_VALUE || g_infoManager.GetBoolValue(it->m_condition, item)) { diff --git a/xbmc/interfaces/json-rpc/AddonsOperations.cpp b/xbmc/interfaces/json-rpc/AddonsOperations.cpp index d06b0c66d2..bb02af989c 100644 --- a/xbmc/interfaces/json-rpc/AddonsOperations.cpp +++ b/xbmc/interfaces/json-rpc/AddonsOperations.cpp @@ -73,7 +73,7 @@ JSONRPC_STATUS CAddonsOperations::GetAddons(const CStdString &method, ITransport addonTypes.push_back(addonType); VECADDONS addons; - for (vector<TYPE>::const_iterator typeIt = addonTypes.begin(); typeIt != addonTypes.end(); typeIt++) + for (vector<TYPE>::const_iterator typeIt = addonTypes.begin(); typeIt != addonTypes.end(); ++typeIt) { VECADDONS typeAddons; if (*typeIt == ADDON_UNKNOWN) diff --git a/xbmc/interfaces/json-rpc/ApplicationOperations.cpp b/xbmc/interfaces/json-rpc/ApplicationOperations.cpp index 51dbb41282..7834e300ed 100644 --- a/xbmc/interfaces/json-rpc/ApplicationOperations.cpp +++ b/xbmc/interfaces/json-rpc/ApplicationOperations.cpp @@ -109,7 +109,7 @@ JSONRPC_STATUS CApplicationOperations::Quit(const CStdString &method, ITransport JSONRPC_STATUS CApplicationOperations::GetPropertyValue(const CStdString &property, CVariant &result) { if (property.Equals("volume")) - result = g_application.GetVolume(); + result = (int)g_application.GetVolume(); else if (property.Equals("muted")) result = g_application.IsMuted(); else if (property.Equals("name")) diff --git a/xbmc/interfaces/json-rpc/AudioLibrary.cpp b/xbmc/interfaces/json-rpc/AudioLibrary.cpp index 9f91cc286a..4b83b2f919 100644 --- a/xbmc/interfaces/json-rpc/AudioLibrary.cpp +++ b/xbmc/interfaces/json-rpc/AudioLibrary.cpp @@ -32,7 +32,7 @@ #include "ApplicationMessenger.h" #include "filesystem/Directory.h" #include "filesystem/File.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" using namespace MUSIC_INFO; using namespace JSONRPC; @@ -67,7 +67,7 @@ JSONRPC_STATUS CAudioLibrary::GetArtists(const CStdString &method, ITransportLay musicUrl.AddOption("xsp", xsp); } - bool albumArtistsOnly = !g_guiSettings.GetBool("musiclibrary.showcompilationartists"); + bool albumArtistsOnly = !CSettings::Get().GetBool("musiclibrary.showcompilationartists"); if (parameterObject["albumartistsonly"].isBoolean()) albumArtistsOnly = parameterObject["albumartistsonly"].asBoolean(); @@ -261,7 +261,7 @@ JSONRPC_STATUS CAudioLibrary::GetSongDetails(const CStdString &method, ITranspor return InternalError; CSong song; - if (!musicdatabase.GetSongById(idSong, song)) + if (!musicdatabase.GetSong(idSong, song)) return InvalidParams; CFileItemList items; @@ -484,7 +484,7 @@ JSONRPC_STATUS CAudioLibrary::SetSongDetails(const CStdString &method, ITranspor return InternalError; CSong song; - if (!musicdatabase.GetSongById(id, song) || song.idSong != id) + if (!musicdatabase.GetSong(id, song) || song.idSong != id) return InvalidParams; if (ParameterNotNull(parameterObject, "title")) @@ -511,14 +511,8 @@ JSONRPC_STATUS CAudioLibrary::SetSongDetails(const CStdString &method, ITranspor song.strComment = parameterObject["comment"].asString(); if (ParameterNotNull(parameterObject, "musicbrainztrackid")) song.strMusicBrainzTrackID = parameterObject["musicbrainztrackid"].asString(); - if (ParameterNotNull(parameterObject, "musicbrainzartistid")) - song.strMusicBrainzArtistID = parameterObject["musicbrainzartistid"].asString(); - if (ParameterNotNull(parameterObject, "musicbrainzalbumid")) - song.strMusicBrainzAlbumID = parameterObject["musicbrainzalbumid"].asString(); - if (ParameterNotNull(parameterObject, "musicbrainzalbumartistid")) - song.strMusicBrainzAlbumArtistID = parameterObject["musicbrainzalbumartistid"].asString(); - - if (musicdatabase.UpdateSong(song, id) <= 0) + + if (musicdatabase.UpdateSong(id, song.strTitle, song.strMusicBrainzTrackID, song.strFileName, song.strComment, song.strThumb, song.artist, song.genre, song.iTrack, song.iDuration, song.iYear, song.iTimesPlayed, song.iStartOffset, song.iEndOffset, song.lastPlayed, song.rating, song.iKaraokeNumber) <= 0) return InternalError; CJSONRPCUtils::NotifyItemUpdated(); @@ -626,7 +620,7 @@ bool CAudioLibrary::FillFileItemList(const CVariant ¶meterObject, CFileItemL if (songID != -1) { CSong song; - if (musicdatabase.GetSongById(songID, song)) + if (musicdatabase.GetSong(songID, song)) { list.Add(CFileItemPtr(new CFileItem(song))); success = true; @@ -678,7 +672,7 @@ JSONRPC_STATUS CAudioLibrary::GetAdditionalAlbumDetails(const CVariant ¶mete if (musicdatabase.GetGenresByAlbum(item->GetMusicInfoTag()->GetDatabaseId(), genreids)) { CVariant genreidObj(CVariant::VariantTypeArray); - for (std::vector<int>::const_iterator genreid = genreids.begin(); genreid != genreids.end(); genreid++) + for (std::vector<int>::const_iterator genreid = genreids.begin(); genreid != genreids.end(); ++genreid) genreidObj.push_back(*genreid); item->SetProperty("genreid", genreidObj); @@ -690,7 +684,7 @@ JSONRPC_STATUS CAudioLibrary::GetAdditionalAlbumDetails(const CVariant ¶mete if (musicdatabase.GetArtistsByAlbum(item->GetMusicInfoTag()->GetDatabaseId(), true, artistids)) { CVariant artistidObj(CVariant::VariantTypeArray); - for (std::vector<int>::const_iterator artistid = artistids.begin(); artistid != artistids.end(); artistid++) + for (std::vector<int>::const_iterator artistid = artistids.begin(); artistid != artistids.end(); ++artistid) artistidObj.push_back(*artistid); item->SetProperty("artistid", artistidObj); @@ -723,7 +717,7 @@ JSONRPC_STATUS CAudioLibrary::GetAdditionalSongDetails(const CVariant ¶meter if (musicdatabase.GetGenresBySong(item->GetMusicInfoTag()->GetDatabaseId(), genreids)) { CVariant genreidObj(CVariant::VariantTypeArray); - for (std::vector<int>::const_iterator genreid = genreids.begin(); genreid != genreids.end(); genreid++) + for (std::vector<int>::const_iterator genreid = genreids.begin(); genreid != genreids.end(); ++genreid) genreidObj.push_back(*genreid); item->SetProperty("genreid", genreidObj); @@ -735,7 +729,7 @@ JSONRPC_STATUS CAudioLibrary::GetAdditionalSongDetails(const CVariant ¶meter if (musicdatabase.GetArtistsBySong(item->GetMusicInfoTag()->GetDatabaseId(), true, artistids)) { CVariant artistidObj(CVariant::VariantTypeArray); - for (std::vector<int>::const_iterator artistid = artistids.begin(); artistid != artistids.end(); artistid++) + for (std::vector<int>::const_iterator artistid = artistids.begin(); artistid != artistids.end(); ++artistid) artistidObj.push_back(*artistid); item->SetProperty("artistid", artistidObj); @@ -747,7 +741,7 @@ JSONRPC_STATUS CAudioLibrary::GetAdditionalSongDetails(const CVariant ¶meter if (musicdatabase.GetArtistsByAlbum(item->GetMusicInfoTag()->GetAlbumId(), true, albumartistids)) { CVariant albumartistidObj(CVariant::VariantTypeArray); - for (std::vector<int>::const_iterator albumartistid = albumartistids.begin(); albumartistid != albumartistids.end(); albumartistid++) + for (std::vector<int>::const_iterator albumartistid = albumartistids.begin(); albumartistid != albumartistids.end(); ++albumartistid) albumartistidObj.push_back(*albumartistid); item->SetProperty("albumartistid", albumartistidObj); diff --git a/xbmc/interfaces/json-rpc/FavouritesOperations.cpp b/xbmc/interfaces/json-rpc/FavouritesOperations.cpp new file mode 100644 index 0000000000..e74957fdc7 --- /dev/null +++ b/xbmc/interfaces/json-rpc/FavouritesOperations.cpp @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2011-2013 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 "FavouritesOperations.h" +#include "Favourites.h" +#include "input/ButtonTranslator.h" +#include "utils/RegExp.h" +#include "utils/StringUtils.h" +#include "Util.h" +#include "utils/URIUtils.h" +#include "guilib/WindowIDs.h" +#include <vector> + +using namespace std; +using namespace JSONRPC; + +JSONRPC_STATUS CFavouritesOperations::GetFavourites(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result) +{ + CFileItemList favourites; + CFavourites::Load(favourites); + + string type = !parameterObject["type"].isNull() ? parameterObject["type"].asString() : ""; + + set<string> fields; + if (parameterObject.isMember("properties") && parameterObject["properties"].isArray()) + { + for (CVariant::const_iterator_array field = parameterObject["properties"].begin_array(); field != parameterObject["properties"].end_array(); field++) + fields.insert(field->asString()); + } + + for (int i = 0; i < favourites.Size(); i++) + { + CVariant object; + CFileItemPtr item = favourites.Get(i); + + CStdString function; + vector<CStdString> parameters; + CUtil::SplitExecFunction(item->GetPath(), function, parameters); + if (parameters.size() == 0) + continue; + + object["title"] = item->GetLabel(); + if (fields.find("thumbnail") != fields.end()) + object["thumbnail"] = item->GetArt("thumb"); + + if (function.CompareNoCase("ActivateWindow") == 0) + { + object["type"] = "window"; + if (fields.find("window") != fields.end()) + { + if (StringUtils::IsNaturalNumber(parameters[0])) + object["window"] = CButtonTranslator::TranslateWindow(strtol(parameters[0], NULL, 10)); + else + object["window"] = parameters[0]; + } + if (fields.find("windowparameter") != fields.end()) + { + if (parameters.size() > 1) + object["windowparameter"] = parameters[1]; + else + object["windowparameter"] = ""; + } + } + else if (function.CompareNoCase("PlayMedia") == 0) + { + object["type"] = "media"; + if (fields.find("path") != fields.end()) + object["path"] = parameters[0]; + } + else if (function.CompareNoCase("RunScript") == 0) + { + object["type"] = "script"; + if (fields.find("path") != fields.end()) + object["path"] = parameters[0]; + } + else + object["type"] = "unknown"; + + if (type.empty() || type.compare(object["type"].asString()) == 0) + result["favourites"].append(object); + } + + int start, end; + HandleLimits(parameterObject, result, result["favourites"].size(), start, end); + + return OK; +} + +JSONRPC_STATUS CFavouritesOperations::AddFavourite(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result) +{ + string type = parameterObject["type"].asString(); + + if (type.compare("unknown") == 0) + return InvalidParams; + + if ((type.compare("media") == 0 || type.compare("script") == 0) && !ParameterNotNull(parameterObject, "path")) + { + result["method"] = "Favourites.AddFavourite"; + result["stack"]["message"] = "Missing parameter"; + result["stack"]["name"] = "path"; + result["stack"]["type"] = "string"; + return InvalidParams; + } + + if (type.compare("window") == 0 && !ParameterNotNull(parameterObject, "window")) + { + result["method"] = "Favourites.AddFavourite"; + result["stack"]["message"] = "Missing parameter"; + result["stack"]["name"] = "window"; + result["stack"]["type"] = "string"; + return InvalidParams; + } + + string title = parameterObject["title"].asString(); + string path = parameterObject["path"].asString(); + + CFileItem item; + int contextWindow = 0; + if (type.compare("window") == 0) + { + item = CFileItem(parameterObject["windowparameter"].asString(), true); + contextWindow = CButtonTranslator::TranslateWindow(parameterObject["window"].asString()); + if (contextWindow == WINDOW_INVALID) + return InvalidParams; + } + else if (type.compare("script") == 0) + { + if (!URIUtils::IsScript(path)) + path = "script://" + path; + item = CFileItem(path, false); + } + else if (type.compare("media") == 0) + { + item = CFileItem(path, false); + } + else + return InvalidParams; + + item.SetLabel(title); + if (ParameterNotNull(parameterObject,"thumbnail")) + item.SetArt("thumb", parameterObject["thumbnail"].asString()); + + if (CFavourites::AddOrRemove(&item, contextWindow)) + return ACK; + else + return FailedToExecute; +} diff --git a/xbmc/interfaces/json-rpc/FavouritesOperations.h b/xbmc/interfaces/json-rpc/FavouritesOperations.h new file mode 100644 index 0000000000..f4ce20dc45 --- /dev/null +++ b/xbmc/interfaces/json-rpc/FavouritesOperations.h @@ -0,0 +1,33 @@ +#pragma once +/* + * Copyright (C) 2011-2013 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 "JSONRPC.h" + +namespace JSONRPC +{ + class CFavouritesOperations : public CJSONUtils + { + public: + static JSONRPC_STATUS GetFavourites(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result); + static JSONRPC_STATUS AddFavourite(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result); + }; +} diff --git a/xbmc/interfaces/json-rpc/FileItemHandler.cpp b/xbmc/interfaces/json-rpc/FileItemHandler.cpp index 58efd23f78..a6af66f876 100644 --- a/xbmc/interfaces/json-rpc/FileItemHandler.cpp +++ b/xbmc/interfaces/json-rpc/FileItemHandler.cpp @@ -99,7 +99,7 @@ bool CFileItemHandler::GetField(const std::string &field, const CVariant &info, CGUIListItem::ArtMap artMap = item->GetArt(); CVariant artObj(CVariant::VariantTypeObject); - for (CGUIListItem::ArtMap::const_iterator artIt = artMap.begin(); artIt != artMap.end(); artIt++) + for (CGUIListItem::ArtMap::const_iterator artIt = artMap.begin(); artIt != artMap.end(); ++artIt) { if (!artIt->second.empty()) artObj[artIt->first] = CTextureCache::GetWrappedImageURL(artIt->second); @@ -187,7 +187,7 @@ void CFileItemHandler::FillDetails(const ISerializable *info, const CFileItemPtr std::set<std::string> originalFields = fields; - for (std::set<std::string>::const_iterator fieldIt = originalFields.begin(); fieldIt != originalFields.end(); fieldIt++) + for (std::set<std::string>::const_iterator fieldIt = originalFields.begin(); fieldIt != originalFields.end(); ++fieldIt) { if (GetField(*fieldIt, serialization, item, result, fetchedArt, thumbLoader) && result.isMember(*fieldIt) && !result[*fieldIt].empty()) fields.erase(*fieldIt); diff --git a/xbmc/interfaces/json-rpc/FileOperations.cpp b/xbmc/interfaces/json-rpc/FileOperations.cpp index 55e8e2cb79..90524942b5 100644 --- a/xbmc/interfaces/json-rpc/FileOperations.cpp +++ b/xbmc/interfaces/json-rpc/FileOperations.cpp @@ -83,11 +83,10 @@ JSONRPC_STATUS CFileOperations::GetDirectory(const CStdString &method, ITranspor CStdString strPath = parameterObject["directory"].asString(); // Check if this directory is part of a source and whether it's locked - VECSOURCES *sources; bool isSource; for (unsigned int index = 0; index < SourcesSize; index++) { - sources = CMediaSourceSettings::Get().GetSources(SourceNames[index]); + VECSOURCES* sources = CMediaSourceSettings::Get().GetSources(SourceNames[index]); int sourceIndex = CUtil::GetMatchingSource(strPath, *sources, isSource); if (sourceIndex >= 0 && sourceIndex < (int)sources->size() && sources->at(sourceIndex).m_iHasLock == 2) return InvalidParams; diff --git a/xbmc/interfaces/json-rpc/GUIOperations.cpp b/xbmc/interfaces/json-rpc/GUIOperations.cpp index 4701e06c18..0d5518b840 100644 --- a/xbmc/interfaces/json-rpc/GUIOperations.cpp +++ b/xbmc/interfaces/json-rpc/GUIOperations.cpp @@ -27,7 +27,7 @@ #include "interfaces/Builtins.h" #include "dialogs/GUIDialogKaiToast.h" #include "addons/AddonManager.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "utils/Variant.h" using namespace std; @@ -111,7 +111,7 @@ JSONRPC_STATUS CGUIOperations::GetPropertyValue(const CStdString &property, CVar result["label"] = g_infoManager.GetLabel(g_infoManager.TranslateString("System.CurrentControl")); else if (property.Equals("skin")) { - CStdString skinId = g_guiSettings.GetString("lookandfeel.skin"); + CStdString skinId = CSettings::Get().GetString("lookandfeel.skin"); AddonPtr addon; CAddonMgr::Get().GetAddon(skinId, addon, ADDON_SKIN); diff --git a/xbmc/interfaces/json-rpc/JSONRPC.cpp b/xbmc/interfaces/json-rpc/JSONRPC.cpp index 0b5b9cd04e..03e5497b10 100644 --- a/xbmc/interfaces/json-rpc/JSONRPC.cpp +++ b/xbmc/interfaces/json-rpc/JSONRPC.cpp @@ -281,7 +281,6 @@ bool CJSONRPC::HandleMethodCall(const CVariant& request, CVariant& response, ITr JSONRPC::MethodCall method; CVariant params; - CLog::Log(LOGDEBUG, "JSONRPC: Calling %s", methodName.c_str()); if ((errorCode = CJSONServiceDescription::CheckCall(methodName, request["params"], transport, client, isNotification, method, params)) == OK) errorCode = method(methodName, transport, client, params, result); else diff --git a/xbmc/interfaces/json-rpc/JSONServiceDescription.cpp b/xbmc/interfaces/json-rpc/JSONServiceDescription.cpp index ab38267aad..84cfaed249 100644 --- a/xbmc/interfaces/json-rpc/JSONServiceDescription.cpp +++ b/xbmc/interfaces/json-rpc/JSONServiceDescription.cpp @@ -36,6 +36,7 @@ #include "XBMCOperations.h" #include "ApplicationOperations.h" #include "PVROperations.h" +#include "FavouritesOperations.h" using namespace std; using namespace JSONRPC; @@ -191,6 +192,10 @@ JsonRpcMethodMap CJSONServiceDescription::m_methodMaps[] = { { "Application.SetMute", CApplicationOperations::SetMute }, { "Application.Quit", CApplicationOperations::Quit }, +// Favourites operations + { "Favourites.GetFavourites", CFavouritesOperations::GetFavourites }, + { "Favourites.AddFavourite", CFavouritesOperations::AddFavourite }, + // XBMC operations { "XBMC.GetInfoLabels", CXBMCOperations::GetInfoLabels }, { "XBMC.GetInfoBooleans", CXBMCOperations::GetInfoBooleans } @@ -253,7 +258,7 @@ bool JSONSchemaTypeDefinition::Parse(const CVariant &value, bool isParameter /* // sure that the default value is a valid enum value else { - for (std::vector<CVariant>::const_iterator itr = enums.begin(); itr != enums.end(); itr++) + for (std::vector<CVariant>::const_iterator itr = enums.begin(); itr != enums.end(); ++itr) { if (value["default"] == *itr) { @@ -342,7 +347,7 @@ bool JSONSchemaTypeDefinition::Parse(const CVariant &value, bool isParameter /* { // Get all child elements of the "properties" // object and loop through them - for (CVariant::const_iterator_map itr = value["properties"].begin_map(); itr != value["properties"].end_map(); itr++) + for (CVariant::const_iterator_map itr = value["properties"].begin_map(); itr != value["properties"].end_map(); ++itr) { // Create a new type definition, store the name // of the current property into it, parse it @@ -464,7 +469,7 @@ bool JSONSchemaTypeDefinition::Parse(const CVariant &value, bool isParameter /* // parse all elements and store them else if (value["items"].isArray()) { - for (CVariant::const_iterator_array itemItr = value["items"].begin_array(); itemItr != value["items"].end_array(); itemItr++) + for (CVariant::const_iterator_array itemItr = value["items"].begin_array(); itemItr != value["items"].end_array(); ++itemItr) { JSONSchemaTypeDefinitionPtr item = JSONSchemaTypeDefinitionPtr(new JSONSchemaTypeDefinition()); if (!item->Parse(*itemItr)) @@ -512,7 +517,7 @@ bool JSONSchemaTypeDefinition::Parse(const CVariant &value, bool isParameter /* if (value.isMember("enum") && value["enum"].isArray()) { // Loop through all elements in the "enum" array - for (CVariant::const_iterator_array enumItr = value["enum"].begin_array(); enumItr != value["enum"].end_array(); enumItr++) + for (CVariant::const_iterator_array enumItr = value["enum"].begin_array(); enumItr != value["enum"].end_array(); ++enumItr) { // Check for duplicates and eliminate them bool approved = true; @@ -545,7 +550,7 @@ bool JSONSchemaTypeDefinition::Parse(const CVariant &value, bool isParameter /* // sure that the default value is a valid enum value else { - for (std::vector<CVariant>::const_iterator itr = enums.begin(); itr != enums.end(); itr++) + for (std::vector<CVariant>::const_iterator itr = enums.begin(); itr != enums.end(); ++itr) { if (value["default"] == *itr) { @@ -591,14 +596,12 @@ JSONRPC_STATUS JSONSchemaTypeDefinition::Check(const CVariant &value, CVariant & // Let's check the type of the provided parameter if (!IsType(value, type)) { - CLog::Log(LOGDEBUG, "JSONRPC: Type mismatch in type %s", name.c_str()); errorMessage.Format("Invalid type %s received", ValueTypeToString(value.type())); errorData["message"] = errorMessage.c_str(); return InvalidParams; } else if (value.isNull() && !HasType(type, NullValue)) { - CLog::Log(LOGDEBUG, "JSONRPC: Value is NULL in type %s", name.c_str()); errorData["message"] = "Received value is null"; return InvalidParams; } @@ -621,7 +624,6 @@ JSONRPC_STATUS JSONSchemaTypeDefinition::Check(const CVariant &value, CVariant & if (!ok) { - CLog::Log(LOGDEBUG, "JSONRPC: Value in type %s does not match any of the union type definitions", name.c_str()); errorData["message"] = "Received value does not match any of the union type definitions"; return InvalidParams; } @@ -778,7 +780,7 @@ JSONRPC_STATUS JSONSchemaTypeDefinition::Check(const CVariant &value, CVariant & unsigned int handled = 0; JSONSchemaTypeDefinition::CJsonSchemaPropertiesMap::JSONSchemaPropertiesIterator propertiesEnd = properties.end(); JSONSchemaTypeDefinition::CJsonSchemaPropertiesMap::JSONSchemaPropertiesIterator propertiesIterator; - for (propertiesIterator = properties.begin(); propertiesIterator != propertiesEnd; propertiesIterator++) + for (propertiesIterator = properties.begin(); propertiesIterator != propertiesEnd; ++propertiesIterator) { if (value.isMember(propertiesIterator->second->name)) { @@ -852,7 +854,7 @@ JSONRPC_STATUS JSONSchemaTypeDefinition::Check(const CVariant &value, CVariant & if (enums.size() > 0) { bool valid = false; - for (std::vector<CVariant>::const_iterator enumItr = enums.begin(); enumItr != enums.end(); enumItr++) + for (std::vector<CVariant>::const_iterator enumItr = enums.begin(); enumItr != enums.end(); ++enumItr) { if (*enumItr == value) { @@ -1073,7 +1075,7 @@ void JSONSchemaTypeDefinition::Print(bool isParameter, bool isGlobal, bool print JSONSchemaTypeDefinition::CJsonSchemaPropertiesMap::JSONSchemaPropertiesIterator propertiesEnd = properties.end(); JSONSchemaTypeDefinition::CJsonSchemaPropertiesMap::JSONSchemaPropertiesIterator propertiesIterator; - for (propertiesIterator = properties.begin(); propertiesIterator != propertiesEnd; propertiesIterator++) + for (propertiesIterator = properties.begin(); propertiesIterator != propertiesEnd; ++propertiesIterator) { propertiesIterator->second->Print(false, false, true, printDescriptions, output["properties"][propertiesIterator->first]); } @@ -1632,7 +1634,7 @@ bool CJSONServiceDescription::AddEnum(const std::string &name, const std::vector bool CJSONServiceDescription::AddEnum(const std::string &name, const std::vector<std::string> &values) { std::vector<CVariant> enums; - for (std::vector<std::string>::const_iterator it = values.begin(); it != values.end(); it++) + for (std::vector<std::string>::const_iterator it = values.begin(); it != values.end(); ++it) enums.push_back(CVariant(*it)); return AddEnum(name, enums, CVariant::VariantTypeString); @@ -1641,7 +1643,7 @@ bool CJSONServiceDescription::AddEnum(const std::string &name, const std::vector bool CJSONServiceDescription::AddEnum(const std::string &name, const std::vector<int> &values) { std::vector<CVariant> enums; - for (std::vector<int>::const_iterator it = values.begin(); it != values.end(); it++) + for (std::vector<int>::const_iterator it = values.begin(); it != values.end(); ++it) enums.push_back(CVariant(*it)); return AddEnum(name, enums, CVariant::VariantTypeInteger); @@ -1723,7 +1725,7 @@ JSONRPC_STATUS CJSONServiceDescription::Print(CVariant &result, ITransportLayer // Loop through all printed types to get all referenced types std::map<std::string, JSONSchemaTypeDefinitionPtr>::const_iterator typeIterator; std::map<std::string, JSONSchemaTypeDefinitionPtr>::const_iterator typeIteratorEnd = types.end(); - for (typeIterator = types.begin(); typeIterator != typeIteratorEnd; typeIterator++) + for (typeIterator = types.begin(); typeIterator != typeIteratorEnd; ++typeIterator) getReferencedTypes(typeIterator->second, referencedTypes); // Loop through all printed method's parameters and return value to get all referenced types @@ -1759,7 +1761,7 @@ JSONRPC_STATUS CJSONServiceDescription::Print(CVariant &result, ITransportLayer std::map<std::string, JSONSchemaTypeDefinitionPtr>::const_iterator typeIterator; std::map<std::string, JSONSchemaTypeDefinitionPtr>::const_iterator typeIteratorEnd = types.end(); - for (typeIterator = types.begin(); typeIterator != typeIteratorEnd; typeIterator++) + for (typeIterator = types.begin(); typeIterator != typeIteratorEnd; ++typeIterator) { CVariant currentType = CVariant(CVariant::VariantTypeObject); typeIterator->second->Print(false, true, true, printDescriptions, currentType); @@ -1811,7 +1813,7 @@ JSONRPC_STATUS CJSONServiceDescription::Print(CVariant &result, ITransportLayer // Print notification description std::map<std::string, CVariant>::const_iterator notificationIterator; std::map<std::string, CVariant>::const_iterator notificationIteratorEnd = notifications.end(); - for (notificationIterator = notifications.begin(); notificationIterator != notificationIteratorEnd; notificationIterator++) + for (notificationIterator = notifications.begin(); notificationIterator != notificationIteratorEnd; ++notificationIterator) result["notifications"][notificationIterator->first] = notificationIterator->second[notificationIterator->first]; return OK; @@ -1947,7 +1949,7 @@ void CJSONServiceDescription::getReferencedTypes(const JSONSchemaTypeDefinitionP { JSONSchemaTypeDefinition::CJsonSchemaPropertiesMap::JSONSchemaPropertiesIterator iter; JSONSchemaTypeDefinition::CJsonSchemaPropertiesMap::JSONSchemaPropertiesIterator iterEnd = type->properties.end(); - for (iter = type->properties.begin(); iter != iterEnd; iter++) + for (iter = type->properties.begin(); iter != iterEnd; ++iter) getReferencedTypes(iter->second, referencedTypes); } // If the current type is an array we need to check its items diff --git a/xbmc/interfaces/json-rpc/Makefile b/xbmc/interfaces/json-rpc/Makefile index f8113bcb86..6dc3ae65f4 100644 --- a/xbmc/interfaces/json-rpc/Makefile +++ b/xbmc/interfaces/json-rpc/Makefile @@ -1,6 +1,7 @@ SRCS=AddonsOperations.cpp \ ApplicationOperations.cpp \ AudioLibrary.cpp \ + FavouritesOperations.cpp \ FileItemHandler.cpp \ FileOperations.cpp \ GUIOperations.cpp \ diff --git a/xbmc/interfaces/json-rpc/PlayerOperations.cpp b/xbmc/interfaces/json-rpc/PlayerOperations.cpp index a947ad65a5..2e317242c9 100644 --- a/xbmc/interfaces/json-rpc/PlayerOperations.cpp +++ b/xbmc/interfaces/json-rpc/PlayerOperations.cpp @@ -285,14 +285,13 @@ JSONRPC_STATUS CPlayerOperations::Stop(const CStdString &method, ITransportLayer JSONRPC_STATUS CPlayerOperations::SetSpeed(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result) { - int speed; switch (GetPlayer(parameterObject["playerid"])) { case Video: case Audio: if (parameterObject["speed"].isInteger()) { - speed = (int)parameterObject["speed"].asInteger(); + int speed = (int)parameterObject["speed"].asInteger(); if (speed != 0) { // If the player is paused we first need to unpause @@ -305,7 +304,6 @@ JSONRPC_STATUS CPlayerOperations::SetSpeed(const CStdString &method, ITransportL } else if (parameterObject["speed"].isString()) { - speed = g_application.GetPlaySpeed(); if (parameterObject["speed"].asString().compare("increment") == 0) CBuiltins::Execute("playercontrol(forward)"); else diff --git a/xbmc/interfaces/json-rpc/PlaylistOperations.cpp b/xbmc/interfaces/json-rpc/PlaylistOperations.cpp index ab2534b063..5e39e708f2 100644 --- a/xbmc/interfaces/json-rpc/PlaylistOperations.cpp +++ b/xbmc/interfaces/json-rpc/PlaylistOperations.cpp @@ -95,12 +95,29 @@ JSONRPC_STATUS CPlaylistOperations::GetItems(const CStdString &method, ITranspor return OK; } +bool CPlaylistOperations::CheckMediaParameter(int playlist, const CVariant ¶meterObject) +{ + if (parameterObject["item"].isMember("media")) + { + if (playlist == PLAYLIST_VIDEO && parameterObject["item"]["media"].asString().compare("video") != 0) + return false; + if (playlist == PLAYLIST_MUSIC && parameterObject["item"]["media"].asString().compare("music") != 0) + return false; + if (playlist == PLAYLIST_PICTURE && parameterObject["item"]["media"].asString().compare("video") != 0 && parameterObject["item"]["media"].asString().compare("pictures") != 0) + return false; + } + return true; +} + JSONRPC_STATUS CPlaylistOperations::Add(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result) { int playlist = GetPlaylist(parameterObject["playlistid"]); CFileItemList list; CVariant params = parameterObject; + if (!CheckMediaParameter(playlist, parameterObject)) + return InvalidParams; + CGUIWindowSlideShow *slideshow = NULL; switch (playlist) { @@ -122,8 +139,8 @@ JSONRPC_STATUS CPlaylistOperations::Add(const CStdString &method, ITransportLaye slideshow = (CGUIWindowSlideShow*)g_windowManager.GetWindow(WINDOW_SLIDESHOW); if (!slideshow) return FailedToExecute; - - params["item"]["media"] = "pictures"; + if (!parameterObject["item"].isMember("media")) + params["item"]["media"] = "pictures"; if (!FillFileItemList(params["item"], list)) return InvalidParams; @@ -149,6 +166,9 @@ JSONRPC_STATUS CPlaylistOperations::Insert(const CStdString &method, ITransportL if (playlist == PLAYLIST_PICTURE) return FailedToExecute; + if (!CheckMediaParameter(playlist, parameterObject)) + return InvalidParams; + CFileItemList list; CVariant params = parameterObject; if (playlist == PLAYLIST_VIDEO) diff --git a/xbmc/interfaces/json-rpc/PlaylistOperations.h b/xbmc/interfaces/json-rpc/PlaylistOperations.h index e6df3f32d9..cb1dd6ad7a 100644 --- a/xbmc/interfaces/json-rpc/PlaylistOperations.h +++ b/xbmc/interfaces/json-rpc/PlaylistOperations.h @@ -41,5 +41,6 @@ namespace JSONRPC static int GetPlaylist(const CVariant &playlist); static inline void NotifyAll(); static JSONRPC_STATUS GetPropertyValue(int playlist, const CStdString &property, CVariant &result); + static bool CheckMediaParameter(int playlist, const CVariant ¶meterObject); }; } diff --git a/xbmc/interfaces/json-rpc/ServiceDescription.h b/xbmc/interfaces/json-rpc/ServiceDescription.h index 111435abd4..69615a331e 100644 --- a/xbmc/interfaces/json-rpc/ServiceDescription.h +++ b/xbmc/interfaces/json-rpc/ServiceDescription.h @@ -22,7 +22,7 @@ namespace JSONRPC { const char* const JSONRPC_SERVICE_ID = "http://www.xbmc.org/jsonrpc/ServiceDescription.json"; - const char* const JSONRPC_SERVICE_VERSION = "6.3.0"; + const char* const JSONRPC_SERVICE_VERSION = "6.5.1"; const char* const JSONRPC_SERVICE_DESCRIPTION = "JSON-RPC API of XBMC"; const char* const JSONRPC_SERVICE_TYPES[] = { @@ -174,7 +174,7 @@ namespace JSONRPC "\"Playlist.Item\": {" "\"type\": [" "{ \"type\": \"object\", \"properties\": { \"file\": { \"type\": \"string\", \"description\": \"Path to a file (not a directory) to be added to the playlist\", \"required\": true } }, \"additionalProperties\": false }," - "{ \"type\": \"object\", \"properties\": { \"directory\": { \"type\": \"string\", \"required\": true }, \"recursive\": { \"type\": \"boolean\", \"default\": false } }, \"additionalProperties\": false }," + "{ \"type\": \"object\", \"properties\": { \"directory\": { \"type\": \"string\", \"required\": true }, \"recursive\": { \"type\": \"boolean\", \"default\": false }, \"media\": { \"$ref\": \"Files.Media\" } }, \"additionalProperties\": false }," "{ \"type\": \"object\", \"properties\": { \"movieid\": { \"$ref\": \"Library.Id\", \"required\": true } }, \"additionalProperties\": false }," "{ \"type\": \"object\", \"properties\": { \"episodeid\": { \"$ref\": \"Library.Id\", \"required\": true } }, \"additionalProperties\": false }," "{ \"type\": \"object\", \"properties\": { \"musicvideoid\": { \"$ref\": \"Library.Id\", \"required\": true } }, \"additionalProperties\": false }," @@ -408,7 +408,7 @@ namespace JSONRPC "\"enum\": [ \"instrument\", \"style\", \"mood\", \"born\", \"formed\"," "\"description\", \"genre\", \"died\", \"disbanded\"," "\"yearsactive\", \"musicbrainzartistid\", \"fanart\"," - "\"compilationartist\", \"thumbnail\" ]" + "\"thumbnail\", \"compilationartist\" ]" "}" "}", "\"Audio.Fields.Album\": {" @@ -1241,6 +1241,30 @@ namespace JSONRPC "}" "}" "}" + "}", + "\"Favourite.Fields.Favourite\": {" + "\"extends\": \"Item.Fields.Base\"," + "\"items\": { \"type\": \"string\"," + "\"enum\": [ \"window\", \"windowparameter\", \"thumbnail\", \"path\" ]" + "}" + "}", + "\"Favourite.Type\": {" + "\"type\": \"string\"," + "\"enum\": [ \"media\", \"window\", \"script\", \"unknown\" ]" + "}", + "\"Favourite.Details.Favourite\": {" + "\"type\": \"array\"," + "\"items\": { \"type\": \"object\"," + "\"properties\": {" + "\"title\": { \"type\": \"string\", \"required\": true }," + "\"type\": { \"$ref\": \"Favourite.Type\", \"required\": true }," + "\"path\": { \"type\": \"string\" }," + "\"window\": { \"type\": \"string\" }," + "\"windowparameter\": { \"type\": \"string\" }," + "\"thumbnail\": { \"type\": \"string\" }" + "}," + "\"additionalProperties\": false" + "}" "}" }; @@ -3139,6 +3163,40 @@ namespace JSONRPC "\"description\": \"Object containing key-value pairs of the retrieved info booleans\"," "\"additionalProperties\": { \"type\": \"string\" }" "}" + "}", + "\"Favourites.GetFavourites\": {" + "\"type\": \"method\"," + "\"description\": \"Retrieve all favourites\"," + "\"transport\": \"Response\"," + "\"permission\": \"ReadData\"," + "\"params\": [" + "{ \"name\": \"type\", \"type\": [ \"null\", { \"$ref\": \"Favourite.Type\" } ], \"default\": null }," + "{ \"name\": \"properties\", \"$ref\": \"Favourite.Fields.Favourite\" }" + "]," + "\"returns\": {" + "\"type\": \"object\"," + "\"properties\": {" + "\"limits\": { \"$ref\": \"List.LimitsReturned\", \"required\": true }," + "\"favourites\": { \"type\": \"array\"," + "\"items\": { \"$ref\": \"Favourite.Details.Favourite\" }" + "}" + "}" + "}" + "}", + "\"Favourites.AddFavourite\": {" + "\"type\": \"method\"," + "\"description\": \"Add a favourite with the given details\"," + "\"transport\": \"Response\"," + "\"permission\": \"UpdateData\"," + "\"params\": [" + "{ \"name\": \"title\", \"type\": \"string\", \"required\": true }," + "{ \"name\": \"type\", \"$ref\": \"Favourite.Type\", \"required\": true }," + "{ \"name\": \"path\", \"$ref\": \"Optional.String\", \"description\": \"Required for media and script favourites types\" }," + "{ \"name\": \"window\", \"$ref\": \"Optional.String\", \"description\": \"Required for window favourite type\" }," + "{ \"name\": \"windowparameter\", \"$ref\": \"Optional.String\" }," + "{ \"name\": \"thumbnail\", \"$ref\": \"Optional.String\" }" + "]," + "\"returns\": \"string\"" "}" }; diff --git a/xbmc/interfaces/json-rpc/methods.json b/xbmc/interfaces/json-rpc/methods.json index e9fd4b7e36..f8a551cf5a 100644 --- a/xbmc/interfaces/json-rpc/methods.json +++ b/xbmc/interfaces/json-rpc/methods.json @@ -1333,7 +1333,7 @@ { "name": "thumbnail", "$ref": "Optional.String" }, { "name": "fanart", "$ref": "Optional.String" }, { "name": "art", "type": [ "null", { "$ref": "Media.Artwork", "required": true } ], "default": null }, - { "name": "resume", "type": [ "null", { "$ref": "Video.Resume", "required": true } ], "default": null } + { "name": "resume", "type": [ "null", { "$ref": "Video.Resume", "required": true } ], "default": null } ], "returns": "string" }, @@ -1360,7 +1360,7 @@ { "name": "fanart", "$ref": "Optional.String" }, { "name": "tag", "type": [ "null", { "$ref": "Array.String", "required": true } ], "default": null }, { "name": "art", "type": [ "null", { "$ref": "Media.Artwork", "required": true } ], "default": null }, - { "name": "resume", "type": [ "null", { "$ref": "Video.Resume", "required": true } ], "default": null } + { "name": "resume", "type": [ "null", { "$ref": "Video.Resume", "required": true } ], "default": null } ], "returns": "string" }, @@ -1893,5 +1893,39 @@ "description": "Object containing key-value pairs of the retrieved info booleans", "additionalProperties": { "type": "string" } } + }, + "Favourites.GetFavourites": { + "type": "method", + "description": "Retrieve all favourites", + "transport": "Response", + "permission": "ReadData", + "params": [ + { "name": "type", "type": [ "null", { "$ref": "Favourite.Type" } ], "default": null }, + { "name": "properties", "$ref": "Favourite.Fields.Favourite" } + ], + "returns": { + "type": "object", + "properties": { + "limits": { "$ref": "List.LimitsReturned", "required": true }, + "favourites": { "type": "array", + "items": { "$ref": "Favourite.Details.Favourite" } + } + } + } + }, + "Favourites.AddFavourite": { + "type": "method", + "description": "Add a favourite with the given details", + "transport": "Response", + "permission": "UpdateData", + "params": [ + { "name": "title", "type": "string", "required": true }, + { "name": "type", "$ref": "Favourite.Type", "required": true }, + { "name": "path", "$ref": "Optional.String", "description": "Required for media and script favourites types" }, + { "name": "window", "$ref": "Optional.String", "description": "Required for window favourite type" }, + { "name": "windowparameter", "$ref": "Optional.String" }, + { "name": "thumbnail", "$ref": "Optional.String" } + ], + "returns": "string" } -} +}
\ No newline at end of file diff --git a/xbmc/interfaces/json-rpc/types.json b/xbmc/interfaces/json-rpc/types.json index e35e5892b2..bf70608f38 100644 --- a/xbmc/interfaces/json-rpc/types.json +++ b/xbmc/interfaces/json-rpc/types.json @@ -147,7 +147,7 @@ "Playlist.Item": { "type": [ { "type": "object", "properties": { "file": { "type": "string", "description": "Path to a file (not a directory) to be added to the playlist", "required": true } }, "additionalProperties": false }, - { "type": "object", "properties": { "directory": { "type": "string", "required": true }, "recursive": { "type": "boolean", "default": false } }, "additionalProperties": false }, + { "type": "object", "properties": { "directory": { "type": "string", "required": true }, "recursive": { "type": "boolean", "default": false }, "media": { "$ref": "Files.Media" } }, "additionalProperties": false }, { "type": "object", "properties": { "movieid": { "$ref": "Library.Id", "required": true } }, "additionalProperties": false }, { "type": "object", "properties": { "episodeid": { "$ref": "Library.Id", "required": true } }, "additionalProperties": false }, { "type": "object", "properties": { "musicvideoid": { "$ref": "Library.Id", "required": true } }, "additionalProperties": false }, @@ -1214,5 +1214,29 @@ } } } + }, + "Favourite.Fields.Favourite": { + "extends": "Item.Fields.Base", + "items": { "type": "string", + "enum": [ "window", "windowparameter", "thumbnail", "path" ] + } + }, + "Favourite.Type": { + "type": "string", + "enum": [ "media", "window", "script", "unknown" ] + }, + "Favourite.Details.Favourite": { + "type": "array", + "items": { "type": "object", + "properties": { + "title": { "type": "string", "required": true }, + "type": { "$ref": "Favourite.Type", "required": true }, + "path": { "type": "string" }, + "window": { "type": "string" }, + "windowparameter": { "type": "string" }, + "thumbnail": { "type": "string" } + }, + "additionalProperties": false + } } } diff --git a/xbmc/interfaces/legacy/AddonClass.h b/xbmc/interfaces/legacy/AddonClass.h index 56d3a56825..208c9e911e 100644 --- a/xbmc/interfaces/legacy/AddonClass.h +++ b/xbmc/interfaces/legacy/AddonClass.h @@ -70,6 +70,9 @@ namespace XBMCAddon String classname; CCriticalSection thisLock; bool m_isDeallocating; + // no copying + inline AddonClass(const AddonClass&); + #ifdef XBMC_ADDON_DEBUG_MEMORY bool isDeleted; @@ -94,9 +97,6 @@ namespace XBMCAddon m_isDeallocating = true; } - // no copying - inline AddonClass(const AddonClass& other) {} - public: AddonClass(const char* classname); virtual ~AddonClass(); diff --git a/xbmc/interfaces/legacy/CallbackHandler.cpp b/xbmc/interfaces/legacy/CallbackHandler.cpp index 3c43c27027..b4d82679d4 100644 --- a/xbmc/interfaces/legacy/CallbackHandler.cpp +++ b/xbmc/interfaces/legacy/CallbackHandler.cpp @@ -69,7 +69,7 @@ namespace XBMCAddon iter = g_callQueue.begin(); } else - iter++; + ++iter; } } } @@ -127,7 +127,7 @@ namespace XBMCAddon iter = g_callQueue.begin(); } else // if we're not in the right thread for this callback... - iter++; + ++iter; } } @@ -148,7 +148,7 @@ namespace XBMCAddon iter = g_callQueue.erase(iter); } else - iter++; + ++iter; } } } diff --git a/xbmc/interfaces/legacy/Control.cpp b/xbmc/interfaces/legacy/Control.cpp index 346be6b8b9..5003dc00d7 100644 --- a/xbmc/interfaces/legacy/Control.cpp +++ b/xbmc/interfaces/legacy/Control.cpp @@ -1013,7 +1013,7 @@ namespace XBMCAddon { if (!pGUIControl) return NULL; - return strText.c_str(); + return strText; } // ============================================================ @@ -1079,7 +1079,7 @@ namespace XBMCAddon { if (!pGUIControl) return NULL; - return strText.c_str(); + return strText; } void ControlEdit::setText(const String& text) throw(UnimplementedException) diff --git a/xbmc/interfaces/legacy/Control.h b/xbmc/interfaces/legacy/Control.h index acbc1c3d49..a34a5ef4a8 100644 --- a/xbmc/interfaces/legacy/Control.h +++ b/xbmc/interfaces/legacy/Control.h @@ -475,7 +475,11 @@ namespace XBMCAddon const char* focusedColor = NULL, const String& label2 = emptyString) throw(UnimplementedException); #ifndef SWIG - ControlLabel() : Control("ControlLabel") {} + ControlLabel() : + Control ("ControlLabel"), + bHasPath(false), + iAngle (0) + {} std::string strFont; std::string strText; @@ -573,7 +577,10 @@ namespace XBMCAddon virtual String getText() throw(UnimplementedException); #ifndef SWIG - ControlEdit() : Control("ControlEdit") {} + ControlEdit() : + Control ("ControlEdit"), + bIsPassword (false) + {} std::string strFont; std::string strText; @@ -815,7 +822,15 @@ namespace XBMCAddon // This is called from AddonWindow.cpp but shouldn't be available // to the scripting languages. - ControlList() : Control("ControlList") {} + ControlList() : + Control("ControlList"), + imageHeight (0), + imageWidth (0), + itemHeight (0), + space (0), + itemTextOffsetX (0), + itemTextOffsetY (0) + {} std::vector<AddonClass::Ref<ListItem> > vecItems; std::string strFont; @@ -1016,7 +1031,10 @@ namespace XBMCAddon virtual void setColorDiffuse(const char* hexString) throw (UnimplementedException); #ifndef SWIG - ControlImage() : Control("ControlImage") {} + ControlImage() : + Control ("ControlImage"), + aspectRatio (0) + {} std::string strFileName; int aspectRatio; @@ -1066,7 +1084,10 @@ namespace XBMCAddon color_t colorDiffuse; SWIGHIDDENVIRTUAL CGUIControl* Create() throw (WindowException); - ControlProgress() : Control("ControlProgress") {} + ControlProgress() : + Control ("ControlProgress"), + aspectRatio (0) + {} #endif }; @@ -1186,7 +1207,14 @@ namespace XBMCAddon SWIGHIDDENVIRTUAL CGUIControl* Create() throw (WindowException); - ControlButton() : Control("ControlButton") {} + ControlButton() : + Control ("ControlButton"), + textOffsetX (0), + textOffsetY (0), + iAngle (0), + shadowColor (0), + focusedColor(0) + {} #endif }; @@ -1294,7 +1322,11 @@ namespace XBMCAddon SWIGHIDDENVIRTUAL CGUIControl* Create() throw (WindowException); - ControlCheckMark() : Control("ControlCheckMark") {} + ControlCheckMark() : + Control ("ControlCheckMark"), + checkWidth (0), + checkHeight (0) + {} #endif }; @@ -1422,7 +1454,12 @@ namespace XBMCAddon SWIGHIDDENVIRTUAL CGUIControl* Create() throw (WindowException); - ControlRadioButton() : Control("ControlRadioButton") {} + ControlRadioButton() : + Control ("ControlRadioButton"), + textOffsetX (0), + textOffsetY (0), + iAngle (0) + {} #endif }; diff --git a/xbmc/interfaces/legacy/Dialog.cpp b/xbmc/interfaces/legacy/Dialog.cpp index b5869f2062..0b0f571448 100644 --- a/xbmc/interfaces/legacy/Dialog.cpp +++ b/xbmc/interfaces/legacy/Dialog.cpp @@ -29,7 +29,8 @@ namespace XBMCAddon const String& line2, const String& line3, const String& nolabel, - const String& yeslabel) throw (WindowException) + const String& yeslabel, + int autoclose) throw (WindowException) { DelayedCallGuard dcguard(languageHook); const int window = WINDOW_DIALOG_YES_NO; @@ -52,6 +53,9 @@ namespace XBMCAddon if (!yeslabel.empty()) pDialog->SetChoice(1,yeslabel); + if (autoclose > 0) + pDialog->SetAutoClose(autoclose); + //send message and wait for user input XBMCWaitForThreadMessage(TMSG_DIALOG_DOMODAL, window, ACTIVE_WINDOW); @@ -134,7 +138,7 @@ namespace XBMCAddon std::string mask = maskparam; VECSOURCES *shares = CMediaSourceSettings::Get().GetSources(s_shares); if (!shares) - throw WindowException("Error: GetSourcesFromType given %s is NULL.",s_shares.c_str()); + throw WindowException("Error: GetSources given %s is NULL.",s_shares.c_str()); if (useFileDirectories && (!maskparam.empty() && !maskparam.size() == 0)) mask += "|.rar|.zip"; @@ -158,7 +162,7 @@ namespace XBMCAddon CStdStringArray tmpret; String lmask = mask; if (!shares) - throw WindowException("Error: GetSourcesFromType given %s is NULL.",s_shares.c_str()); + throw WindowException("Error: GetSources given %s is NULL.",s_shares.c_str()); if (useFileDirectories && (!lmask.empty() && !(lmask.size() == 0))) lmask += "|.rar|.zip"; @@ -172,7 +176,7 @@ namespace XBMCAddon std::vector<String> valuelist; int index = 0; - for (CStdStringArray::iterator iter = tmpret.begin(); iter != tmpret.end(); iter++) + for (CStdStringArray::iterator iter = tmpret.begin(); iter != tmpret.end(); ++iter) valuelist[index++] = (*iter); return valuelist; diff --git a/xbmc/interfaces/legacy/Dialog.h b/xbmc/interfaces/legacy/Dialog.h index f64b6eb1a7..52638e1e0f 100644 --- a/xbmc/interfaces/legacy/Dialog.h +++ b/xbmc/interfaces/legacy/Dialog.h @@ -54,6 +54,7 @@ namespace XBMCAddon * line3 : [opt] string or unicode - line #3 text. * nolabel : [opt] label to put on the no button. * yeslabel : [opt] label to put on the yes button. + * autoclose : [opt] integer - milliseconds to autoclose dialog. (default=do not autoclose) * * *Note, Returns True if 'Yes' was pressed, else False. * @@ -65,7 +66,8 @@ namespace XBMCAddon const String& line2 = emptyString, const String& line3 = emptyString, const String& nolabel = emptyString, - const String& yeslabel = emptyString) throw (WindowException); + const String& yeslabel = emptyString, + int autoclose = 0) throw (WindowException); /** * select(heading, list) -- Show a select dialog. diff --git a/xbmc/interfaces/legacy/InfoTagVideo.cpp b/xbmc/interfaces/legacy/InfoTagVideo.cpp index fc9083d6d3..5a4e1b3887 100644 --- a/xbmc/interfaces/legacy/InfoTagVideo.cpp +++ b/xbmc/interfaces/legacy/InfoTagVideo.cpp @@ -55,7 +55,7 @@ namespace XBMCAddon String InfoTagVideo::getGenre() { - return StringUtils::Join(infoTag->m_genre, g_advancedSettings.m_videoItemSeparator).c_str(); + return StringUtils::Join(infoTag->m_genre, g_advancedSettings.m_videoItemSeparator); } String InfoTagVideo::getTagLine() diff --git a/xbmc/interfaces/legacy/ListItem.cpp b/xbmc/interfaces/legacy/ListItem.cpp index f432de6a86..d04e436ce7 100644 --- a/xbmc/interfaces/legacy/ListItem.cpp +++ b/xbmc/interfaces/legacy/ListItem.cpp @@ -251,7 +251,7 @@ namespace XBMCAddon if (strcmpi(type, "video") == 0) { - for (Dictionary::const_iterator it = infoLabels.begin(); it != infoLabels.end(); it++) + for (Dictionary::const_iterator it = infoLabels.begin(); it != infoLabels.end(); ++it) { CStdString key = it->first; key.ToLower(); @@ -379,7 +379,7 @@ namespace XBMCAddon } else if (strcmpi(type, "music") == 0) { - for (Dictionary::const_iterator it = infoLabels.begin(); it != infoLabels.end(); it++) + for (Dictionary::const_iterator it = infoLabels.begin(); it != infoLabels.end(); ++it) { CStdString key = it->first; @@ -418,11 +418,11 @@ namespace XBMCAddon else if (key == "musicbrainztrackid") item->GetMusicInfoTag()->SetMusicBrainzTrackID(value); else if (key == "musicbrainzartistid") - item->GetMusicInfoTag()->SetMusicBrainzArtistID(value); + item->GetMusicInfoTag()->SetMusicBrainzArtistID(StringUtils::Split(value, g_advancedSettings.m_musicItemSeparator)); else if (key == "musicbrainzalbumid") item->GetMusicInfoTag()->SetMusicBrainzAlbumID(value); else if (key == "musicbrainzalbumartistid") - item->GetMusicInfoTag()->SetMusicBrainzAlbumArtistID(value); + item->GetMusicInfoTag()->SetMusicBrainzAlbumArtistID(StringUtils::Split(value, g_advancedSettings.m_musicItemSeparator)); else if (key == "musicbrainztrmid") item->GetMusicInfoTag()->SetMusicBrainzTRMID(value); else if (key == "comment") @@ -442,7 +442,7 @@ namespace XBMCAddon } else if (strcmpi(type,"pictures") == 0) { - for (Dictionary::const_iterator it = infoLabels.begin(); it != infoLabels.end(); it++) + for (Dictionary::const_iterator it = infoLabels.begin(); it != infoLabels.end(); ++it) { CStdString key = it->first; key.ToLower(); @@ -476,11 +476,10 @@ namespace XBMCAddon { LOCKGUI; - String tmp; if (strcmpi(cType, "video") == 0) { CStreamDetailVideo* video = new CStreamDetailVideo; - for (Dictionary::const_iterator it = dictionary.begin(); it != dictionary.end(); it++) + for (Dictionary::const_iterator it = dictionary.begin(); it != dictionary.end(); ++it) { const String& key = it->first; const CStdString value(it->second.c_str()); @@ -501,7 +500,7 @@ namespace XBMCAddon else if (strcmpi(cType, "audio") == 0) { CStreamDetailAudio* audio = new CStreamDetailAudio; - for (Dictionary::const_iterator it = dictionary.begin(); it != dictionary.end(); it++) + for (Dictionary::const_iterator it = dictionary.begin(); it != dictionary.end(); ++it) { const String& key = it->first; const String& value = it->second; @@ -518,7 +517,7 @@ namespace XBMCAddon else if (strcmpi(cType, "subtitle") == 0) { CStreamDetailSubtitle* subtitle = new CStreamDetailSubtitle; - for (Dictionary::const_iterator it = dictionary.begin(); it != dictionary.end(); it++) + for (Dictionary::const_iterator it = dictionary.begin(); it != dictionary.end(); ++it) { const String& key = it->first; const String& value = it->second; @@ -534,7 +533,7 @@ namespace XBMCAddon throw (ListItemException) { int itemCount = 0; - for (std::vector<Tuple<String,String> >::const_iterator iter = items.begin(); iter < items.end(); iter++, itemCount++) + for (std::vector<Tuple<String,String> >::const_iterator iter = items.begin(); iter < items.end(); ++iter, ++itemCount) { Tuple<String,String> tuple = *iter; if (tuple.GetNumValuesSet() != 2) diff --git a/xbmc/interfaces/legacy/ModuleXbmc.cpp b/xbmc/interfaces/legacy/ModuleXbmc.cpp index 01ec5f9e5b..41c3b3934b 100644 --- a/xbmc/interfaces/legacy/ModuleXbmc.cpp +++ b/xbmc/interfaces/legacy/ModuleXbmc.cpp @@ -36,8 +36,6 @@ #include "XTimeUtils.h" #endif #include "guilib/LocalizeStrings.h" -#include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" #include "GUIInfoManager.h" #include "guilib/GUIAudioManager.h" #include "guilib/GUIWindowManager.h" @@ -46,12 +44,15 @@ #include "utils/Crc32.h" #include "FileItem.h" #include "LangInfo.h" +#include "settings/AdvancedSettings.h" +#include "settings/Settings.h" #include "guilib/TextureManager.h" #include "Util.h" #include "URL.h" #include "cores/AudioEngine/AEFactory.h" #include "storage/MediaManager.h" #include "utils/FileUtils.h" +#include "utils/LangCodeExpander.h" #include "CallbackHandler.h" #include "AddonUtils.h" @@ -177,13 +178,57 @@ namespace XBMCAddon String getSkinDir() { TRACE; - return g_guiSettings.GetString("lookandfeel.skin"); + return CSettings::Get().GetString("lookandfeel.skin"); } - String getLanguage() + String getLanguage(int format /* = CLangCodeExpander::ENGLISH_NAME */, bool region /*= false*/) { TRACE; - return g_guiSettings.GetString("locale.language"); + CStdString lang = CSettings::Get().GetString("locale.language"); + + switch (format) + { + case CLangCodeExpander::ENGLISH_NAME: + { + if (region) + { + CStdString region = "-" + g_langInfo.GetCurrentRegion(); + return (lang += region); + } + return lang; + } + case CLangCodeExpander::ISO_639_1: + { + CStdString langCode; + g_LangCodeExpander.ConvertToTwoCharCode(langCode, lang); + if (region) + { + CStdString region = g_langInfo.GetRegionLocale(); + CStdString region2Code; + g_LangCodeExpander.ConvertToTwoCharCode(region2Code, region); + region2Code = "-" + region2Code; + return (langCode += region2Code); + } + return langCode; + } + case CLangCodeExpander::ISO_639_2: + { + CStdString langCode; + g_LangCodeExpander.ConvertToThreeCharCode(langCode, lang); + if (region) + { + CStdString region = g_langInfo.GetRegionLocale(); + CStdString region3Code; + g_LangCodeExpander.ConvertToThreeCharCode(region3Code, region); + region3Code = "-" + region3Code; + return (langCode += region3Code); + } + + return langCode; + } + default: + return ""; + } } String getIPAddress() @@ -304,12 +349,11 @@ namespace XBMCAddon if (!condition) return false; - int id; bool ret; { LOCKGUI; - id = g_windowManager.GetTopMostModalDialogID(); + int id = g_windowManager.GetTopMostModalDialogID(); if (id == WINDOW_INVALID) id = g_windowManager.GetActiveWindow(); ret = g_infoManager.EvaluateBool(condition,id); } @@ -446,6 +490,34 @@ namespace XBMCAddon CAEFactory::Resume(); } + String convertLanguage(const char* language, int format) + { + CStdString convertedLanguage; + switch (format) + { + case CLangCodeExpander::ENGLISH_NAME: + { + g_LangCodeExpander.Lookup(convertedLanguage, language); + // maybe it's a check whether the language exists or not + if (convertedLanguage.empty()) + { + g_LangCodeExpander.ConvertToThreeCharCode(convertedLanguage, language); + g_LangCodeExpander.Lookup(convertedLanguage, convertedLanguage); + } + break; + } + case CLangCodeExpander::ISO_639_1: + g_LangCodeExpander.ConvertToTwoCharCode(convertedLanguage, language); + break; + case CLangCodeExpander::ISO_639_2: + g_LangCodeExpander.ConvertToThreeCharCode(convertedLanguage, language); + break; + default: + return ""; + } + return convertedLanguage; + } + int getSERVER_WEBSERVER() { return CApplication::ES_WEBSERVER; } int getSERVER_AIRPLAYSERVER() { return CApplication::ES_AIRPLAYSERVER; } int getSERVER_UPNPSERVER() { return CApplication::ES_UPNPSERVER; } @@ -482,6 +554,11 @@ namespace XBMCAddon int getCAPTURE_FLAG_CONTINUOUS() { return (int)CAPTUREFLAG_CONTINUOUS; } int getCAPTURE_FLAG_IMMEDIATELY() { return (int)CAPTUREFLAG_IMMEDIATELY; } + // language string formats + int getISO_639_1() { return CLangCodeExpander::ISO_639_1; } + int getISO_639_2(){ return CLangCodeExpander::ISO_639_2; } + int getENGLISH_NAME() { return CLangCodeExpander::ENGLISH_NAME; } + const int lLOGNOTICE = LOGNOTICE; } } diff --git a/xbmc/interfaces/legacy/ModuleXbmc.h b/xbmc/interfaces/legacy/ModuleXbmc.h index 6c8cf09700..45f16667f2 100644 --- a/xbmc/interfaces/legacy/ModuleXbmc.h +++ b/xbmc/interfaces/legacy/ModuleXbmc.h @@ -23,6 +23,7 @@ #include "Tuple.h" //#include "Monitor.h" +#include "utils/LangCodeExpander.h" #include "utils/log.h" #include "utils/StdString.h" @@ -150,12 +151,20 @@ namespace XBMCAddon String getSkinDir(); /** - * getLanguage() -- Returns the active language as a string. - * - * example: - * - language = xbmc.getLanguage() - */ - String getLanguage(); + * getLanguage([format], [region]) -- Returns the active language as a string. + * + * format: [opt] format of the returned language string + * xbmc.ISO_639_1: two letter code as defined in ISO 639-1 + * xbmc.ISO_639_2: three letter code as defined in ISO 639-2/T or ISO 639-2/B + * xbmc.ENGLISH_NAME: full language name in English (default) + * + * region: [opt] append the region delimited by "-" of the language (setting) + * to the returned language string + * + * example: + * - language = xbmc.getLanguage(xbmc.ENGLISH_NAME) + */ + String getLanguage(int format = CLangCodeExpander::ENGLISH_NAME, bool region = false); /** * getIPAddress() -- Returns the current ip address as a string. @@ -395,6 +404,21 @@ namespace XBMCAddon */ void audioResume(); + /** + * convertLanguage(language, format) -- Returns the given language converted to the given format as a string. + * + * language: string either as name in English, two letter code (ISO 639-1), or three letter code (ISO 639-2/T(B) + * + * format: format of the returned language string + * xbmc.ISO_639_1: two letter code as defined in ISO 639-1 + * xbmc.ISO_639_2: three letter code as defined in ISO 639-2/T or ISO 639-2/B + * xbmc.ENGLISH_NAME: full language name in English (default) + * + * example: + * - language = xbmc.convertLanguage(English, xbmc.ISO_639_2) + */ + String convertLanguage(const char* language, int format); + SWIG_CONSTANT_FROM_GETTER(int,SERVER_WEBSERVER); SWIG_CONSTANT_FROM_GETTER(int,SERVER_AIRPLAYSERVER); SWIG_CONSTANT_FROM_GETTER(int,SERVER_UPNPSERVER); @@ -429,6 +453,9 @@ namespace XBMCAddon SWIG_CONSTANT_FROM_GETTER(int,CAPTURE_FLAG_CONTINUOUS); SWIG_CONSTANT_FROM_GETTER(int,CAPTURE_FLAG_IMMEDIATELY); + SWIG_CONSTANT_FROM_GETTER(int,ISO_639_1); + SWIG_CONSTANT_FROM_GETTER(int,ISO_639_2); + SWIG_CONSTANT_FROM_GETTER(int,ENGLISH_NAME); #if 0 void registerMonitor(Monitor* monitor); void unregisterMonitor(Monitor* monitor); diff --git a/xbmc/interfaces/legacy/ModuleXbmcplugin.cpp b/xbmc/interfaces/legacy/ModuleXbmcplugin.cpp index 9501faa861..e6a07d5370 100644 --- a/xbmc/interfaces/legacy/ModuleXbmcplugin.cpp +++ b/xbmc/interfaces/legacy/ModuleXbmcplugin.cpp @@ -46,7 +46,7 @@ namespace XBMCAddon { CFileItemList fitems; for (std::vector<Tuple<String,const XBMCAddon::xbmcgui::ListItem*,bool> >::const_iterator item = items.begin(); - item < items.end(); item++ ) + item < items.end(); ++item ) { const Tuple<String,const XBMCAddon::xbmcgui::ListItem*,bool>* pItem = &(*item); const String& url = pItem->first(); diff --git a/xbmc/interfaces/legacy/PlayList.cpp b/xbmc/interfaces/legacy/PlayList.cpp index b27372c6d1..6ce1f4ca53 100644 --- a/xbmc/interfaces/legacy/PlayList.cpp +++ b/xbmc/interfaces/legacy/PlayList.cpp @@ -143,10 +143,9 @@ namespace XBMCAddon XBMCAddon::xbmcgui::ListItem* PlayList::operator [](long i) throw (PlayListException) { - long pos = -1; int iPlayListSize = size(); - pos = i; + long pos = i; if (pos < 0) pos += iPlayListSize; if (pos < 0 || pos >= iPlayListSize) diff --git a/xbmc/interfaces/legacy/Player.cpp b/xbmc/interfaces/legacy/Player.cpp index 73ecb512a7..ed7887fdde 100644 --- a/xbmc/interfaces/legacy/Player.cpp +++ b/xbmc/interfaces/legacy/Player.cpp @@ -112,7 +112,7 @@ namespace XBMCAddon CApplicationMessenger::Get().PlayListPlayerPlay(g_playlistPlayer.GetCurrentSong()); } - void Player::playPlaylist(const PlayList* playlist, bool windowed) + void Player::playPlaylist(const PlayList* playlist, bool windowed, int startpos) { TRACE; DelayedCallGuard dc(languageHook); @@ -127,7 +127,9 @@ namespace XBMCAddon // play a python playlist (a playlist from playlistplayer.cpp) iPlayList = playlist->getPlayListId(); g_playlistPlayer.SetCurrentPlaylist(iPlayList); - CApplicationMessenger::Get().PlayListPlayerPlay(); + if (startpos > -1) + g_playlistPlayer.SetCurrentSong(startpos); + CApplicationMessenger::Get().PlayListPlayerPlay(startpos); } else playCurrent(windowed); diff --git a/xbmc/interfaces/legacy/Player.h b/xbmc/interfaces/legacy/Player.h index bfda0868cd..bf5fe66539 100644 --- a/xbmc/interfaces/legacy/Player.h +++ b/xbmc/interfaces/legacy/Player.h @@ -92,10 +92,11 @@ namespace XBMCAddon void playStream(const String& item = emptyString, const XBMCAddon::xbmcgui::ListItem* listitem = NULL, bool windowed = false); /** - * playPlaylist([playlist, windowed]) -- Play this item. + * playPlaylist([playlist, windowed, startpos]) -- Play this item. * * playlist : [opt] playlist. * windowed : [opt] bool - true=play video windowed, false=play users preference.(default) + * startpos : [opt] int - Playlist starting position (0 based). If not given, current position is used * * *Note, If playlist is not given then the Player will try to play the current item * in the current playlist. @@ -105,7 +106,8 @@ namespace XBMCAddon * * example: */ - void playPlaylist(const PlayList* playlist = NULL, bool windowed = false); + void playPlaylist(const PlayList* playlist = NULL, + bool windowed = false, int startpos=-1); /** * play() -- try to play the current item in the current playlist. diff --git a/xbmc/interfaces/legacy/Window.cpp b/xbmc/interfaces/legacy/Window.cpp index 8477ed796f..dea419762a 100644 --- a/xbmc/interfaces/legacy/Window.cpp +++ b/xbmc/interfaces/legacy/Window.cpp @@ -653,7 +653,7 @@ namespace XBMCAddon SingleLockWithDelayGuard gslock(g_graphicsContext,languageHook); CStdString lowerKey = key; std::string value = ref(window)->GetProperty(lowerKey.ToLower()).asString(); - return value.c_str(); + return value; } void Window::clearProperty(const char* key) diff --git a/xbmc/interfaces/legacy/WindowXML.cpp b/xbmc/interfaces/legacy/WindowXML.cpp index b518fc37d4..6de431fe23 100644 --- a/xbmc/interfaces/legacy/WindowXML.cpp +++ b/xbmc/interfaces/legacy/WindowXML.cpp @@ -23,7 +23,7 @@ #include "WindowInterceptor.h" #include "guilib/GUIWindowManager.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "addons/Skin.h" #include "filesystem/File.h" #include "utils/URIUtils.h" @@ -512,13 +512,12 @@ namespace XBMCAddon { TRACE; // Path where the language strings reside - CStdString pathToLanguageFile = m_scriptPath; - URIUtils::AddFileToFolder(pathToLanguageFile, "resources", pathToLanguageFile); - URIUtils::AddFileToFolder(pathToLanguageFile, "language", pathToLanguageFile); + CStdString pathToLanguageFile = URIUtils::AddFileToFolder(m_scriptPath, "resources"); + pathToLanguageFile = URIUtils::AddFileToFolder(pathToLanguageFile, "language"); URIUtils::AddSlashAtEnd(pathToLanguageFile); // allocate a bunch of strings - return g_localizeStrings.LoadBlock(m_scriptPath, pathToLanguageFile, g_guiSettings.GetString("locale.language")); + return g_localizeStrings.LoadBlock(m_scriptPath, pathToLanguageFile, CSettings::Get().GetString("locale.language")); } void WindowXML::ClearScriptStrings() diff --git a/xbmc/interfaces/python/LanguageHook.cpp b/xbmc/interfaces/python/LanguageHook.cpp index cc2a470731..138117481c 100644 --- a/xbmc/interfaces/python/LanguageHook.cpp +++ b/xbmc/interfaces/python/LanguageHook.cpp @@ -101,7 +101,7 @@ namespace XBMCAddon bool LanguageHook::IsAddonClassInstanceRegistered(AddonClass* obj) { for (std::map<PyInterpreterState*,AddonClass::Ref<LanguageHook> >::iterator iter = hooks.begin(); - iter != hooks.end(); iter++) + iter != hooks.end(); ++iter) { if ((iter->second)->HasRegisteredAddonClassInstance(obj)) return true; diff --git a/xbmc/interfaces/python/LanguageHook.h b/xbmc/interfaces/python/LanguageHook.h index 5c9832c937..e1898839d9 100644 --- a/xbmc/interfaces/python/LanguageHook.h +++ b/xbmc/interfaces/python/LanguageHook.h @@ -94,7 +94,7 @@ namespace XBMCAddon void RegisterAddonClassInstance(AddonClass* obj); void UnregisterAddonClassInstance(AddonClass* obj); bool HasRegisteredAddonClassInstance(AddonClass* obj); - inline bool HasRegisteredAddonClasses() { Synchronize l(*this); return currentObjects.size() > 0; } + inline bool HasRegisteredAddonClasses() { Synchronize l(*this); return !currentObjects.empty(); } // You should hold the lock on the LanguageHook itself if you're // going to do anything with the set that gets returned. diff --git a/xbmc/interfaces/python/XBPyThread.cpp b/xbmc/interfaces/python/XBPyThread.cpp index e081f939d5..238fb9d37b 100644 --- a/xbmc/interfaces/python/XBPyThread.cpp +++ b/xbmc/interfaces/python/XBPyThread.cpp @@ -159,7 +159,7 @@ static const CStdString getListOfAddonClassesAsString(XBMCAddon::AddonClass::Ref std::set<XBMCAddon::AddonClass*>& acs = languageHook->GetRegisteredAddonClasses(); bool firstTime = true; for (std::set<XBMCAddon::AddonClass*>::iterator iter = acs.begin(); - iter != acs.end(); iter++) + iter != acs.end(); ++iter) { if (!firstTime) message += ","; else firstTime = false; @@ -341,14 +341,21 @@ void XBPyThread::Process() if (pDlgToast) { CStdString desc; - CStdString path; CStdString script; - URIUtils::Split(m_source, path, script); - if (script.Equals("default.py")) + if (addon.get() != NULL) + { + script = addon->Name(); + } + else { - CStdString path2; - URIUtils::RemoveSlashAtEnd(path); - URIUtils::Split(path, path2, script); + CStdString path; + URIUtils::Split(m_source, path, script); + if (script.Equals("default.py")) + { + CStdString path2; + URIUtils::RemoveSlashAtEnd(path); + URIUtils::Split(path, path2, script); + } } desc.Format(g_localizeStrings.Get(2100), script); diff --git a/xbmc/interfaces/python/XBPython.cpp b/xbmc/interfaces/python/XBPython.cpp index 9fef88a311..4d78a45cb7 100644 --- a/xbmc/interfaces/python/XBPython.cpp +++ b/xbmc/interfaces/python/XBPython.cpp @@ -40,6 +40,7 @@ #include "pythreadstate.h" #include "utils/TimeUtils.h" #include "Util.h" +#include "guilib/GraphicContext.h" #include "threads/SystemClock.h" #include "addons/Addon.h" @@ -97,7 +98,7 @@ void XBPython::OnPlayBackEnded() { TRACE; LOCK_AND_COPY(std::vector<PVOID>,tmp,m_vecPlayerCallbackList); - for (PlayerCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++) + for (PlayerCallbackList::iterator it = tmp.begin(); (it != tmp.end()); ++it) if (CHECK_FOR_ENTRY(m_vecPlayerCallbackList,(*it))) ((IPlayerCallback*)(*it))->OnPlayBackEnded(); } @@ -132,7 +133,7 @@ void XBPython::OnPlayBackStarted() { TRACE; LOCK_AND_COPY(std::vector<PVOID>,tmp,m_vecPlayerCallbackList); - for (PlayerCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++) + for (PlayerCallbackList::iterator it = tmp.begin(); (it != tmp.end()); ++it) if (CHECK_FOR_ENTRY(m_vecPlayerCallbackList,(*it))) ((IPlayerCallback*)(*it))->OnPlayBackStarted(); } @@ -142,7 +143,7 @@ void XBPython::OnPlayBackPaused() { TRACE; LOCK_AND_COPY(std::vector<PVOID>,tmp,m_vecPlayerCallbackList); - for (PlayerCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++) + for (PlayerCallbackList::iterator it = tmp.begin(); (it != tmp.end()); ++it) if (CHECK_FOR_ENTRY(m_vecPlayerCallbackList,(*it))) ((IPlayerCallback*)(*it))->OnPlayBackPaused(); } @@ -152,7 +153,7 @@ void XBPython::OnPlayBackResumed() { TRACE; LOCK_AND_COPY(std::vector<PVOID>,tmp,m_vecPlayerCallbackList); - for (PlayerCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++) + for (PlayerCallbackList::iterator it = tmp.begin(); (it != tmp.end()); ++it) if (CHECK_FOR_ENTRY(m_vecPlayerCallbackList,(*it))) ((IPlayerCallback*)(*it))->OnPlayBackResumed(); } @@ -162,7 +163,7 @@ void XBPython::OnPlayBackStopped() { TRACE; LOCK_AND_COPY(std::vector<PVOID>,tmp,m_vecPlayerCallbackList); - for (PlayerCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++) + for (PlayerCallbackList::iterator it = tmp.begin(); (it != tmp.end()); ++it) if (CHECK_FOR_ENTRY(m_vecPlayerCallbackList,(*it))) ((IPlayerCallback*)(*it))->OnPlayBackStopped(); } @@ -172,7 +173,7 @@ void XBPython::OnPlayBackSpeedChanged(int iSpeed) { TRACE; LOCK_AND_COPY(std::vector<PVOID>,tmp,m_vecPlayerCallbackList); - for (PlayerCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++) + for (PlayerCallbackList::iterator it = tmp.begin(); (it != tmp.end()); ++it) if (CHECK_FOR_ENTRY(m_vecPlayerCallbackList,(*it))) ((IPlayerCallback*)(*it))->OnPlayBackSpeedChanged(iSpeed); } @@ -182,7 +183,7 @@ void XBPython::OnPlayBackSeek(int iTime, int seekOffset) { TRACE; LOCK_AND_COPY(std::vector<PVOID>,tmp,m_vecPlayerCallbackList); - for (PlayerCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++) + for (PlayerCallbackList::iterator it = tmp.begin(); (it != tmp.end()); ++it) if (CHECK_FOR_ENTRY(m_vecPlayerCallbackList,(*it))) ((IPlayerCallback*)(*it))->OnPlayBackSeek(iTime, seekOffset); } @@ -192,7 +193,7 @@ void XBPython::OnPlayBackSeekChapter(int iChapter) { TRACE; LOCK_AND_COPY(std::vector<PVOID>,tmp,m_vecPlayerCallbackList); - for (PlayerCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++) + for (PlayerCallbackList::iterator it = tmp.begin(); (it != tmp.end()); ++it) if (CHECK_FOR_ENTRY(m_vecPlayerCallbackList,(*it))) ((IPlayerCallback*)(*it))->OnPlayBackSeekChapter(iChapter); } @@ -202,7 +203,7 @@ void XBPython::OnQueueNextItem() { TRACE; LOCK_AND_COPY(std::vector<PVOID>,tmp,m_vecPlayerCallbackList); - for (PlayerCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++) + for (PlayerCallbackList::iterator it = tmp.begin(); (it != tmp.end()); ++it) if (CHECK_FOR_ENTRY(m_vecPlayerCallbackList,(*it))) ((IPlayerCallback*)(*it))->OnQueueNextItem(); } @@ -227,7 +228,7 @@ void XBPython::UnregisterPythonPlayerCallBack(IPlayerCallback* pCallback) m_vecPlayerCallbackList.hadSomethingRemoved = true; } else - it++; + ++it; } } @@ -251,7 +252,7 @@ void XBPython::UnregisterPythonMonitorCallBack(XBMCAddon::xbmc::Monitor* pCallba m_vecMonitorCallbackList.hadSomethingRemoved = true; } else - it++; + ++it; } } @@ -259,7 +260,7 @@ void XBPython::OnSettingsChanged(const CStdString &ID) { TRACE; LOCK_AND_COPY(std::vector<XBMCAddon::xbmc::Monitor*>,tmp,m_vecMonitorCallbackList); - for (MonitorCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++) + for (MonitorCallbackList::iterator it = tmp.begin(); (it != tmp.end()); ++it) if (CHECK_FOR_ENTRY(m_vecMonitorCallbackList,(*it)) && ((*it)->GetId() == ID)) (*it)->OnSettingsChanged(); } @@ -268,7 +269,7 @@ void XBPython::OnScreensaverActivated() { TRACE; LOCK_AND_COPY(std::vector<XBMCAddon::xbmc::Monitor*>,tmp,m_vecMonitorCallbackList); - for (MonitorCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++) + for (MonitorCallbackList::iterator it = tmp.begin(); (it != tmp.end()); ++it) if (CHECK_FOR_ENTRY(m_vecMonitorCallbackList,(*it))) (*it)->OnScreensaverActivated(); } @@ -277,7 +278,7 @@ void XBPython::OnScreensaverDeactivated() { TRACE; LOCK_AND_COPY(std::vector<XBMCAddon::xbmc::Monitor*>,tmp,m_vecMonitorCallbackList); - for (MonitorCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++) + for (MonitorCallbackList::iterator it = tmp.begin(); (it != tmp.end()); ++it) if (CHECK_FOR_ENTRY(m_vecMonitorCallbackList,(*it))) (*it)->OnScreensaverDeactivated(); } @@ -286,7 +287,7 @@ void XBPython::OnDatabaseUpdated(const std::string &database) { TRACE; LOCK_AND_COPY(std::vector<XBMCAddon::xbmc::Monitor*>,tmp,m_vecMonitorCallbackList); - for (MonitorCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++) + for (MonitorCallbackList::iterator it = tmp.begin(); (it != tmp.end()); ++it) if (CHECK_FOR_ENTRY(m_vecMonitorCallbackList,(*it))) (*it)->OnDatabaseUpdated(database); } @@ -295,7 +296,7 @@ void XBPython::OnDatabaseScanStarted(const std::string &database) { TRACE; LOCK_AND_COPY(std::vector<XBMCAddon::xbmc::Monitor*>,tmp,m_vecMonitorCallbackList); - for (MonitorCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++) + for (MonitorCallbackList::iterator it = tmp.begin(); (it != tmp.end()); ++it) if (CHECK_FOR_ENTRY(m_vecMonitorCallbackList,(*it))) (*it)->OnDatabaseScanStarted(database); } @@ -304,7 +305,7 @@ void XBPython::OnAbortRequested(const CStdString &ID) { TRACE; LOCK_AND_COPY(std::vector<XBMCAddon::xbmc::Monitor*>,tmp,m_vecMonitorCallbackList); - for (MonitorCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++) + for (MonitorCallbackList::iterator it = tmp.begin(); (it != tmp.end()); ++it) { if (CHECK_FOR_ENTRY(m_vecMonitorCallbackList,(*it))) { @@ -358,7 +359,7 @@ void XBPython::UnregisterExtensionLib(LibraryLoader *pLib) m_extensions.erase(iter); break; } - iter++; + ++iter; } } @@ -370,7 +371,7 @@ void XBPython::UnloadExtensionLibs() while (iter != m_extensions.end()) { DllLoaderContainer::ReleaseModule(*iter); - iter++; + ++iter; } m_extensions.clear(); } @@ -646,7 +647,7 @@ void XBPython::Process() m_vecPyList.hadSomethingRemoved = true; } else - it++; + ++it; } lock.Leave(); @@ -803,7 +804,7 @@ bool XBPython::isRunning(int scriptId) { CSingleLock lock(m_vecPyList); - for(PyList::iterator it = m_vecPyList.begin(); it != m_vecPyList.end(); it++) + for(PyList::iterator it = m_vecPyList.begin(); it != m_vecPyList.end(); ++it) { if (it->id == scriptId) { diff --git a/xbmc/linux/DBusMessage.cpp b/xbmc/linux/DBusMessage.cpp index 40caa9f05a..7665d99da8 100644 --- a/xbmc/linux/DBusMessage.cpp +++ b/xbmc/linux/DBusMessage.cpp @@ -28,8 +28,7 @@ CDBusMessage::CDBusMessage(const char *destination, const char *object, const ch m_message = dbus_message_new_method_call (destination, object, interface, method); m_haveArgs = false; - if (g_advancedSettings.m_logLevel >= LOG_LEVEL_DEBUG_SAMBA) - CLog::Log(LOGDEBUG, "DBus: Creating message to %s on %s with interface %s and method %s\n", destination, object, interface, method); + CLog::Log(LOGDEBUG|LOGDBUS, "DBus: Creating message to %s on %s with interface %s and method %s\n", destination, object, interface, method); } CDBusMessage::~CDBusMessage() diff --git a/xbmc/linux/HALManager.h b/xbmc/linux/HALManager.h index 48f6e58487..e2433a3936 100644 --- a/xbmc/linux/HALManager.h +++ b/xbmc/linux/HALManager.h @@ -34,7 +34,6 @@ #include "threads/CriticalSection.h" #include "utils/URIUtils.h" #include "MediaSource.h" -#include "settings/GUISettings.h" class CHALDevice { diff --git a/xbmc/linux/LinuxTimezone.cpp b/xbmc/linux/LinuxTimezone.cpp index 5df42d01b7..370653feb0 100644 --- a/xbmc/linux/LinuxTimezone.cpp +++ b/xbmc/linux/LinuxTimezone.cpp @@ -34,6 +34,8 @@ #endif #include "Util.h" +#include "XBDateTime.h" +#include "settings/Settings.h" using namespace std; @@ -145,6 +147,26 @@ CLinuxTimezone::CLinuxTimezone() : m_IsDST(0) free(line); } +void CLinuxTimezone::OnSettingChanged(const CSetting *setting) +{ + if (setting == NULL) + return; + + const std::string &settingId = setting->GetId(); + if (settingId == "locale.timezone") + { + SetTimezone(((CSettingString*)setting)->GetValue()); + + CDateTime::ResetTimezoneBias(); + } + else if (settingId == "locale.timezonecountry") + { + // nothing to do here. Changing locale.timezonecountry will trigger an + // update of locale.timezone and automatically adjust its value + // and execute OnSettingChanged() for it as well (see above) + } +} + vector<CStdString> CLinuxTimezone::GetCounties() { return m_counties; @@ -221,4 +243,28 @@ CStdString CLinuxTimezone::GetOSConfiguredTimezone() return timezoneName; } +void CLinuxTimezone::SettingOptionsTimezoneCountriesFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t) +{ + vector<CStdString> countries = g_timezone.GetCounties(); + for (unsigned int i = 0; i < countries.size(); i++) + list.push_back(make_pair(countries[i], countries[i])); +} + +void CLinuxTimezone::SettingOptionsTimezonesFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t) +{ + current = ((const CSettingString*)setting)->GetValue(); + bool found = false; + vector<CStdString> timezones = g_timezone.GetTimezonesByCountry(CSettings::Get().GetString("locale.timezonecountry")); + for (unsigned int i = 0; i < timezones.size(); i++) + { + if (!found && timezones[i].Equals(current.c_str())) + found = true; + + list.push_back(make_pair(timezones[i], timezones[i])); + } + + if (!found && timezones.size() > 0) + current = timezones[0]; +} + CLinuxTimezone g_timezone; diff --git a/xbmc/linux/LinuxTimezone.h b/xbmc/linux/LinuxTimezone.h index 858bd0a9e8..e29cb122a2 100644 --- a/xbmc/linux/LinuxTimezone.h +++ b/xbmc/linux/LinuxTimezone.h @@ -21,14 +21,20 @@ * */ +#include "settings/ISettingCallback.h" #include "utils/StdString.h" #include <vector> #include <map> -class CLinuxTimezone +class CSetting; + +class CLinuxTimezone : public ISettingCallback { public: CLinuxTimezone(); + + virtual void OnSettingChanged(const CSetting *setting); + CStdString GetOSConfiguredTimezone(); std::vector<CStdString> GetCounties(); @@ -37,6 +43,10 @@ public: void SetTimezone(CStdString timezone); int m_IsDST; + + static void SettingOptionsTimezoneCountriesFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t); + static void SettingOptionsTimezonesFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t); + private: std::vector<CStdString> m_counties; std::map<CStdString, CStdString> m_countryByCode; diff --git a/xbmc/linux/OMXClock.cpp b/xbmc/linux/OMXClock.cpp index 38608186b3..1b849188a2 100644 --- a/xbmc/linux/OMXClock.cpp +++ b/xbmc/linux/OMXClock.cpp @@ -27,7 +27,7 @@ #if defined(HAVE_OMXLIB) #include "video/VideoReferenceClock.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "OMXClock.h" #include "utils/MathUtils.h" @@ -318,7 +318,7 @@ bool OMXClock::OMXSetReferenceClock(bool lock /* = true */) OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE refClock; OMX_INIT_STRUCTURE(refClock); - if(g_guiSettings.GetBool("videoplayer.usedisplayasclock") && m_has_video) + if(CSettings::Get().GetBool("videoplayer.usedisplayasclock") && m_has_video) refClock.eClock = OMX_TIME_RefClockVideo; else if(m_has_audio) refClock.eClock = OMX_TIME_RefClockAudio; @@ -761,7 +761,7 @@ bool OMXClock::OMXMediaTime(double pts, bool fixPreroll /* = true*/, bool lock / OMX_INIT_STRUCTURE(timeStamp); timeStamp.nPortIndex = m_omx_clock.GetInputPort(); - if(g_guiSettings.GetBool("videoplayer.usedisplayasclock") && m_has_video) + if(CSettings::Get().GetBool("videoplayer.usedisplayasclock") && m_has_video) index = OMX_IndexConfigTimeCurrentVideoReference; else if(m_has_audio) index = OMX_IndexConfigTimeCurrentAudioReference; diff --git a/xbmc/music/Album.cpp b/xbmc/music/Album.cpp index 21011e4679..266f06bf09 100644 --- a/xbmc/music/Album.cpp +++ b/xbmc/music/Album.cpp @@ -23,13 +23,43 @@ #include "utils/StringUtils.h" #include "utils/XMLUtils.h" #include "utils/MathUtils.h" +#include "FileItem.h" using namespace std; using namespace MUSIC_INFO; +CAlbum::CAlbum(const CFileItem& item) +{ + Reset(); + const CMusicInfoTag& tag = *item.GetMusicInfoTag(); + SYSTEMTIME stTime; + tag.GetReleaseDate(stTime); + strAlbum = tag.GetAlbum(); + strMusicBrainzAlbumID = tag.GetMusicBrainzAlbumID(); + genre = tag.GetGenre(); + artist = tag.GetAlbumArtist(); + iYear = stTime.wYear; + bCompilation = tag.GetCompilation(); + iTimesPlayed = 0; +} + +CStdString CAlbum::GetArtistString() const +{ + return StringUtils::Join(artist, g_advancedSettings.m_musicItemSeparator); +} + +CStdString CAlbum::GetGenreString() const +{ + return StringUtils::Join(artist, g_advancedSettings.m_musicItemSeparator); +} + bool CAlbum::operator<(const CAlbum &a) const { - return strAlbum +StringUtils::Join(artist, g_advancedSettings.m_musicItemSeparator) < a.strAlbum + StringUtils::Join(a.artist, g_advancedSettings.m_musicItemSeparator); + if (strAlbum < a.strAlbum) return true; + if (strAlbum > a.strAlbum) return false; + if (strMusicBrainzAlbumID < a.strMusicBrainzAlbumID) return true; + if (strMusicBrainzAlbumID > a.strMusicBrainzAlbumID) return false; + return false; } bool CAlbum::Load(const TiXmlElement *album, bool append, bool prioritise) @@ -38,13 +68,15 @@ bool CAlbum::Load(const TiXmlElement *album, bool append, bool prioritise) if (!append) Reset(); - XMLUtils::GetString(album,"title",strAlbum); + XMLUtils::GetString(album, "title", strAlbum); + XMLUtils::GetString(album, "musicBrainzAlbumID", strMusicBrainzAlbumID); XMLUtils::GetStringArray(album, "artist", artist, prioritise, g_advancedSettings.m_musicItemSeparator); XMLUtils::GetStringArray(album, "genre", genre, prioritise, g_advancedSettings.m_musicItemSeparator); XMLUtils::GetStringArray(album, "style", styles, prioritise, g_advancedSettings.m_musicItemSeparator); XMLUtils::GetStringArray(album, "mood", moods, prioritise, g_advancedSettings.m_musicItemSeparator); XMLUtils::GetStringArray(album, "theme", themes, prioritise, g_advancedSettings.m_musicItemSeparator); + XMLUtils::GetBoolean(album, "compilation", bCompilation); XMLUtils::GetString(album,"review",strReview); XMLUtils::GetString(album,"releasedate",m_strDateOfRelease); @@ -88,6 +120,25 @@ bool CAlbum::Load(const TiXmlElement *album, bool append, bool prioritise) thumbURL.m_xml = xmlAdd; } + const TiXmlElement* albumArtistCreditsNode = album->FirstChildElement("albumArtistCredits"); + if (albumArtistCreditsNode) + artistCredits.clear(); + + while (albumArtistCreditsNode) + { + if (albumArtistCreditsNode->FirstChild()) + { + CArtistCredit artistCredit; + XMLUtils::GetString(albumArtistCreditsNode, "artist", artistCredit.m_strArtist); + XMLUtils::GetString(albumArtistCreditsNode, "musicBrainzArtistID", artistCredit.m_strMusicBrainzArtistID); + XMLUtils::GetString(albumArtistCreditsNode, "joinphrase", artistCredit.m_strJoinPhrase); + XMLUtils::GetBoolean(albumArtistCreditsNode, "featuring", artistCredit.m_boolFeatured); + artistCredits.push_back(artistCredit); + } + + albumArtistCreditsNode = albumArtistCreditsNode->NextSiblingElement("albumArtistCredits"); + } + const TiXmlElement* node = album->FirstChildElement("track"); if (node) songs.clear(); // this means that the tracks can't be spread over separate pages @@ -99,7 +150,27 @@ bool CAlbum::Load(const TiXmlElement *album, bool append, bool prioritise) { CSong song; - XMLUtils::GetInt(node,"position",song.iTrack); + const TiXmlElement* songArtistCreditsNode = node->FirstChildElement("songArtistCredits"); + if (songArtistCreditsNode) + song.artistCredits.clear(); + + while (songArtistCreditsNode) + { + if (songArtistCreditsNode->FirstChild()) + { + CArtistCredit artistCredit; + XMLUtils::GetString(songArtistCreditsNode, "artist", artistCredit.m_strArtist); + XMLUtils::GetString(songArtistCreditsNode, "musicBrainzArtistID", artistCredit.m_strMusicBrainzArtistID); + XMLUtils::GetString(songArtistCreditsNode, "joinphrase", artistCredit.m_strJoinPhrase); + XMLUtils::GetBoolean(songArtistCreditsNode, "featuring", artistCredit.m_boolFeatured); + song.artistCredits.push_back(artistCredit); + } + + songArtistCreditsNode = songArtistCreditsNode->NextSiblingElement("albumArtistCredits"); + } + + XMLUtils::GetString(node, "musicBrainzTrackID", song.strMusicBrainzTrackID); + XMLUtils::GetInt(node, "position", song.iTrack); if (song.iTrack == 0) bIncrement = true; @@ -130,12 +201,14 @@ bool CAlbum::Save(TiXmlNode *node, const CStdString &tag, const CStdString& strP if (!album) return false; - XMLUtils::SetString(album, "title", strAlbum); - XMLUtils::SetStringArray(album, "artist", artist); - XMLUtils::SetStringArray(album, "genre", genre); - XMLUtils::SetStringArray(album, "style", styles); - XMLUtils::SetStringArray(album, "mood", moods); - XMLUtils::SetStringArray(album, "theme", themes); + XMLUtils::SetString(album, "title", strAlbum); + XMLUtils::SetString(album, "musicBrainzAlbumID", strMusicBrainzAlbumID); + XMLUtils::SetStringArray(album, "artist", artist); + XMLUtils::SetStringArray(album, "genre", genre); + XMLUtils::SetStringArray(album, "style", styles); + XMLUtils::SetStringArray(album, "mood", moods); + XMLUtils::SetStringArray(album, "theme", themes); + XMLUtils::SetBoolean(album, "compilation", bCompilation); XMLUtils::SetString(album, "review", strReview); XMLUtils::SetString(album, "type", strType); @@ -158,25 +231,36 @@ bool CAlbum::Save(TiXmlNode *node, const CStdString &tag, const CStdString& strP XMLUtils::SetInt(album, "rating", iRating); XMLUtils::SetInt(album, "year", iYear); - for( VECSONGS::const_iterator it = songs.begin();it != songs.end();++it) + for( VECARTISTCREDITS::const_iterator artistCredit = artistCredits.begin();artistCredit != artistCredits.end();++artistCredit) + { + // add an <albumArtistCredits> tag + TiXmlElement albumArtistCreditsElement("albumArtistCredits"); + TiXmlNode *albumArtistCreditsNode = album->InsertEndChild(albumArtistCreditsElement); + XMLUtils::SetString(albumArtistCreditsNode, "artist", artistCredit->m_strArtist); + XMLUtils::SetString(albumArtistCreditsNode, "musicBrainzArtistID", artistCredit->m_strMusicBrainzArtistID); + XMLUtils::SetString(albumArtistCreditsNode, "joinphrase", artistCredit->m_strJoinPhrase); + XMLUtils::SetString(albumArtistCreditsNode, "featuring", artistCredit->GetArtist()); + } + + for( VECSONGS::const_iterator song = songs.begin(); song != songs.end(); ++song) { // add a <song> tag TiXmlElement cast("track"); TiXmlNode *node = album->InsertEndChild(cast); - TiXmlElement title("title"); - TiXmlNode *titleNode = node->InsertEndChild(title); - TiXmlText name(it->strTitle); - titleNode->InsertEndChild(name); - TiXmlElement year("position"); - TiXmlNode *yearNode = node->InsertEndChild(year); - CStdString strTrack; - strTrack.Format("%i",it->iTrack); - TiXmlText name2(strTrack); - yearNode->InsertEndChild(name2); - TiXmlElement duration("duration"); - TiXmlNode *durNode = node->InsertEndChild(duration); - TiXmlText name3(StringUtils::SecondsToTimeString(it->iDuration)); - durNode->InsertEndChild(name3); + for( VECARTISTCREDITS::const_iterator artistCredit = song->artistCredits.begin(); artistCredit != artistCredits.end(); ++artistCredit) + { + // add an <albumArtistCredits> tag + TiXmlElement songArtistCreditsElement("songArtistCredits"); + TiXmlNode *songArtistCreditsNode = node->InsertEndChild(songArtistCreditsElement); + XMLUtils::SetString(songArtistCreditsNode, "artist", artistCredit->m_strArtist); + XMLUtils::SetString(songArtistCreditsNode, "musicBrainzArtistID", artistCredit->m_strMusicBrainzArtistID); + XMLUtils::SetString(songArtistCreditsNode, "joinphrase", artistCredit->m_strJoinPhrase); + XMLUtils::SetString(songArtistCreditsNode, "featuring", artistCredit->GetArtist()); + } + XMLUtils::SetString(node, "musicBrainzTrackID", song->strMusicBrainzTrackID); + XMLUtils::SetString(node, "title", song->strTitle); + XMLUtils::SetInt(node, "position", song->iTrack); + XMLUtils::SetString(node, "duration", StringUtils::SecondsToTimeString(song->iDuration)); } return true; diff --git a/xbmc/music/Album.h b/xbmc/music/Album.h index a10200bd77..4db82e48e2 100644 --- a/xbmc/music/Album.h +++ b/xbmc/music/Album.h @@ -26,15 +26,16 @@ #include <map> #include <vector> - +#include "Artist.h" #include "Song.h" #include "utils/ScraperUrl.h" class TiXmlNode; - +class CFileItem; class CAlbum { public: + CAlbum(const CFileItem& item); CAlbum() { idAlbum = 0; iRating = 0; iYear = 0; iTimesPlayed = 0; }; bool operator<(const CAlbum &a) const; @@ -42,7 +43,9 @@ public: { idAlbum = -1; strAlbum.Empty(); + strMusicBrainzAlbumID.Empty(); artist.clear(); + artistCredits.clear(); genre.clear(); thumbURL.Clear(); moods.clear(); @@ -52,6 +55,7 @@ public: strReview.Empty(); strLabel.Empty(); strType.Empty(); + strPath.Empty(); m_strDateOfRelease.Empty(); iRating=-1; iYear=-1; @@ -60,6 +64,9 @@ public: songs.clear(); } + CStdString GetArtistString() const; + CStdString GetGenreString() const; + /*! \brief Load album information from an XML file. See CVideoInfoTag::Load for a description of the types of elements we load. \param element the root XML element to parse. @@ -72,7 +79,9 @@ public: long idAlbum; CStdString strAlbum; + CStdString strMusicBrainzAlbumID; std::vector<std::string> artist; + VECARTISTCREDITS artistCredits; std::vector<std::string> genre; CScraperUrl thumbURL; std::vector<std::string> moods; @@ -82,6 +91,7 @@ public: CStdString strReview; CStdString strLabel; CStdString strType; + CStdString strPath; CStdString m_strDateOfRelease; int iRating; int iYear; diff --git a/xbmc/music/Artist.cpp b/xbmc/music/Artist.cpp index 1c72531dea..e29f68c3f1 100644 --- a/xbmc/music/Artist.cpp +++ b/xbmc/music/Artist.cpp @@ -30,17 +30,19 @@ bool CArtist::Load(const TiXmlElement *artist, bool append, bool prioritise) if (!append) Reset(); - XMLUtils::GetString(artist,"name",strArtist); - XMLUtils::GetStringArray(artist, "genre", genre, prioritise, g_advancedSettings.m_musicItemSeparator); - XMLUtils::GetStringArray(artist, "style", styles, prioritise, g_advancedSettings.m_musicItemSeparator); - XMLUtils::GetStringArray(artist, "mood", moods, prioritise, g_advancedSettings.m_musicItemSeparator); + XMLUtils::GetString(artist, "name", strArtist); + XMLUtils::GetString(artist, "musicBrainzArtistID", strMusicBrainzArtistID); + + XMLUtils::GetStringArray(artist, "genre", genre, prioritise, g_advancedSettings.m_musicItemSeparator); + XMLUtils::GetStringArray(artist, "style", styles, prioritise, g_advancedSettings.m_musicItemSeparator); + XMLUtils::GetStringArray(artist, "mood", moods, prioritise, g_advancedSettings.m_musicItemSeparator); XMLUtils::GetStringArray(artist, "yearsactive", yearsActive, prioritise, g_advancedSettings.m_musicItemSeparator); XMLUtils::GetStringArray(artist, "instruments", instruments, prioritise, g_advancedSettings.m_musicItemSeparator); - XMLUtils::GetString(artist, "born", strBorn); - XMLUtils::GetString(artist, "formed", strFormed); + XMLUtils::GetString(artist, "born", strBorn); + XMLUtils::GetString(artist, "formed", strFormed); XMLUtils::GetString(artist, "biography", strBiography); - XMLUtils::GetString(artist, "died", strDied); + XMLUtils::GetString(artist, "died", strDied); XMLUtils::GetString(artist, "disbanded", strDisbanded); size_t iThumbCount = thumbURL.m_url.size(); @@ -111,17 +113,18 @@ bool CArtist::Save(TiXmlNode *node, const CStdString &tag, const CStdString& str if (!artist) return false; - XMLUtils::SetString(artist, "name", strArtist); - XMLUtils::SetStringArray(artist, "genre", genre); - XMLUtils::SetStringArray(artist, "style", styles); - XMLUtils::SetStringArray(artist, "mood", moods); - XMLUtils::SetStringArray(artist, "yearsactive", yearsActive); - XMLUtils::SetStringArray(artist, "instruments", instruments); - XMLUtils::SetString(artist, "born", strBorn); - XMLUtils::SetString(artist, "formed", strFormed); - XMLUtils::SetString(artist, "biography", strBiography); - XMLUtils::SetString(artist, "died", strDied); - XMLUtils::SetString(artist, "disbanded", strDisbanded); + XMLUtils::SetString(artist, "name", strArtist); + XMLUtils::SetString(artist, "musicBrainzArtistID", strMusicBrainzArtistID); + XMLUtils::SetStringArray(artist, "genre", genre); + XMLUtils::SetStringArray(artist, "style", styles); + XMLUtils::SetStringArray(artist, "mood", moods); + XMLUtils::SetStringArray(artist, "yearsactive", yearsActive); + XMLUtils::SetStringArray(artist, "instruments", instruments); + XMLUtils::SetString(artist, "born", strBorn); + XMLUtils::SetString(artist, "formed", strFormed); + XMLUtils::SetString(artist, "biography", strBiography); + XMLUtils::SetString(artist, "died", strDied); + XMLUtils::SetString(artist, "disbanded", strDisbanded); if (!thumbURL.m_xml.empty()) { CXBMCTinyXML doc; diff --git a/xbmc/music/Artist.h b/xbmc/music/Artist.h index e9b9ad5dbd..a2ad4703a6 100644 --- a/xbmc/music/Artist.h +++ b/xbmc/music/Artist.h @@ -27,6 +27,8 @@ #include "utils/Fanart.h" class TiXmlNode; +class CAlbum; +class CMusicDatabase; class CArtist { @@ -34,7 +36,11 @@ public: long idArtist; bool operator<(const CArtist& a) const { - return strArtist < a.strArtist; + if (strArtist < a.strArtist) return true; + if (strArtist > a.strArtist) return false; + if (strMusicBrainzArtistID < a.strMusicBrainzArtistID) return true; + if (strMusicBrainzArtistID > a.strMusicBrainzArtistID) return false; + return false; } void Reset() @@ -53,6 +59,7 @@ public: thumbURL.Clear(); discography.clear(); idArtist = -1; + strPath.Empty(); } /*! \brief Load artist information from an XML file. @@ -66,6 +73,7 @@ public: bool Save(TiXmlNode *node, const CStdString &tag, const CStdString& strPath); CStdString strArtist; + CStdString strMusicBrainzArtistID; std::vector<std::string> genre; CStdString strBiography; std::vector<std::string> styles; @@ -76,9 +84,46 @@ public: CStdString strDied; CStdString strDisbanded; std::vector<std::string> yearsActive; + CStdString strPath; CScraperUrl thumbURL; CFanart fanart; std::vector<std::pair<CStdString,CStdString> > discography; }; +class CArtistCredit +{ + friend class CAlbum; + friend class CMusicDatabase; + +public: + CArtistCredit() { } + CArtistCredit(std::string strArtist, std::string strJoinPhrase) : m_strArtist(strArtist), m_strJoinPhrase(strJoinPhrase), m_boolFeatured(false) { } + CArtistCredit(std::string strArtist, std::string strMusicBrainzArtistID, std::string strJoinPhrase) + : m_strArtist(strArtist), m_strMusicBrainzArtistID(strMusicBrainzArtistID), m_strJoinPhrase(strJoinPhrase), m_boolFeatured(false) { } + bool operator<(const CArtistCredit& a) const + { + if (m_strArtist < a.m_strArtist) return true; + if (m_strArtist > a.m_strArtist) return false; + if (m_strMusicBrainzArtistID < a.m_strMusicBrainzArtistID) return true; + if (m_strMusicBrainzArtistID > a.m_strMusicBrainzArtistID) return false; + return false; + } + + std::string GetArtist() const { return m_strArtist; } + std::string GetMusicBrainzArtistID() const { return m_strMusicBrainzArtistID; } + std::string GetJoinPhrase() const { return m_strJoinPhrase; } + void SetArtist(const std::string &strArtist) { m_strArtist = strArtist; } + void SetMusicBrainzArtistID(const std::string &strMusicBrainzArtistID) { m_strMusicBrainzArtistID = strMusicBrainzArtistID; } + void SetJoinPhrase(const std::string &strJoinPhrase) { m_strJoinPhrase = strJoinPhrase; } + +private: + long idArtist; + std::string m_strArtist; + std::string m_strMusicBrainzArtistID; + std::string m_strJoinPhrase; + bool m_boolFeatured; +}; + typedef std::vector<CArtist> VECARTISTS; +typedef std::vector<CArtistCredit> VECARTISTCREDITS; + diff --git a/xbmc/music/GUIViewStateMusic.cpp b/xbmc/music/GUIViewStateMusic.cpp index 02be182e42..a9f2fff1e5 100644 --- a/xbmc/music/GUIViewStateMusic.cpp +++ b/xbmc/music/GUIViewStateMusic.cpp @@ -21,9 +21,9 @@ #include "GUIViewStateMusic.h" #include "PlayListPlayer.h" #include "video/VideoDatabase.h" -#include "settings/GUISettings.h" #include "settings/AdvancedSettings.h" #include "settings/MediaSourceSettings.h" +#include "settings/Settings.h" #include "FileItem.h" #include "guilib/WindowIDs.h" #include "Util.h" @@ -46,8 +46,8 @@ int CGUIViewStateWindowMusic::GetPlaylist() bool CGUIViewStateWindowMusic::AutoPlayNextItem() { - return g_guiSettings.GetBool("musicplayer.autoplaynextitem") && - !g_guiSettings.GetBool("musicplayer.queuebydefault"); + return CSettings::Get().GetBool("musicplayer.autoplaynextitem") && + !CSettings::Get().GetBool("musicplayer.queuebydefault"); } CStdString CGUIViewStateWindowMusic::GetLockType() @@ -68,12 +68,12 @@ VECSOURCES& CGUIViewStateWindowMusic::GetSources() CGUIViewStateMusicSearch::CGUIViewStateMusicSearch(const CFileItemList& items) : CGUIViewStateWindowMusic(items) { - CStdString strTrackLeft=g_guiSettings.GetString("musicfiles.librarytrackformat"); + CStdString strTrackLeft=CSettings::Get().GetString("musicfiles.librarytrackformat"); if (strTrackLeft.IsEmpty()) - strTrackLeft = g_guiSettings.GetString("musicfiles.trackformat"); - CStdString strTrackRight=g_guiSettings.GetString("musicfiles.librarytrackformatright"); + strTrackLeft = CSettings::Get().GetString("musicfiles.trackformat"); + CStdString strTrackRight=CSettings::Get().GetString("musicfiles.librarytrackformatright"); if (strTrackRight.IsEmpty()) - strTrackRight = g_guiSettings.GetString("musicfiles.trackformatright"); + strTrackRight = CSettings::Get().GetString("musicfiles.trackformatright"); CStdString strAlbumLeft = g_advancedSettings.m_strMusicLibraryAlbumFormat; if (strAlbumLeft.IsEmpty()) @@ -82,7 +82,7 @@ CGUIViewStateMusicSearch::CGUIViewStateMusicSearch(const CFileItemList& items) : if (strAlbumRight.IsEmpty()) strAlbumRight = "%A"; // artist - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) { AddSortMethod(SORT_METHOD_TITLE_IGNORE_THE, 556, LABEL_MASKS("%T - %A", "%D", "%L", "%A")); // Title, Artist, Duration| empty, empty SetSortMethod(SORT_METHOD_TITLE_IGNORE_THE); @@ -93,7 +93,7 @@ CGUIViewStateMusicSearch::CGUIViewStateMusicSearch(const CFileItemList& items) : SetSortMethod(SORT_METHOD_TITLE); } - CViewState *viewState = CViewStateSettings::Get().Get("musicnavsongs"); + const CViewState *viewState = CViewStateSettings::Get().Get("musicnavsongs"); SetViewAsControl(viewState->m_viewMode); SetSortOrder(viewState->m_sortOrder); @@ -110,12 +110,12 @@ CGUIViewStateMusicDatabase::CGUIViewStateMusicDatabase(const CFileItemList& item CMusicDatabaseDirectory dir; NODE_TYPE NodeType=dir.GetDirectoryChildType(items.GetPath()); - CStdString strTrackLeft=g_guiSettings.GetString("musicfiles.librarytrackformat"); + CStdString strTrackLeft=CSettings::Get().GetString("musicfiles.librarytrackformat"); if (strTrackLeft.IsEmpty()) - strTrackLeft = g_guiSettings.GetString("musicfiles.trackformat"); - CStdString strTrackRight=g_guiSettings.GetString("musicfiles.librarytrackformatright"); + strTrackLeft = CSettings::Get().GetString("musicfiles.trackformat"); + CStdString strTrackRight=CSettings::Get().GetString("musicfiles.librarytrackformatright"); if (strTrackRight.IsEmpty()) - strTrackRight = g_guiSettings.GetString("musicfiles.trackformatright"); + strTrackRight = CSettings::Get().GetString("musicfiles.trackformatright"); CStdString strAlbumLeft = g_advancedSettings.m_strMusicLibraryAlbumFormat; if (strAlbumLeft.IsEmpty()) @@ -171,7 +171,7 @@ CGUIViewStateMusicDatabase::CGUIViewStateMusicDatabase(const CFileItemList& item break; case NODE_TYPE_ARTIST: { - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) { AddSortMethod(SORT_METHOD_ARTIST_IGNORE_THE, 557, LABEL_MASKS("%F", "", "%A", "")); // Filename, empty | Artist, empty SetSortMethod(SORT_METHOD_ARTIST_IGNORE_THE); @@ -181,8 +181,8 @@ CGUIViewStateMusicDatabase::CGUIViewStateMusicDatabase(const CFileItemList& item AddSortMethod(SORT_METHOD_ARTIST, 557, LABEL_MASKS("%F", "", "%A", "")); // Filename, empty | Artist, empty SetSortMethod(SORT_METHOD_ARTIST); } - - CViewState *viewState = CViewStateSettings::Get().Get("musicnavartists"); + + const CViewState *viewState = CViewStateSettings::Get().Get("musicnavartists"); SetViewAsControl(viewState->m_viewMode); SetSortOrder(viewState->m_sortOrder); } @@ -192,13 +192,13 @@ CGUIViewStateMusicDatabase::CGUIViewStateMusicDatabase(const CFileItemList& item case NODE_TYPE_YEAR_ALBUM: { // album - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) AddSortMethod(SORT_METHOD_ALBUM_IGNORE_THE, 558, LABEL_MASKS("%F", "", strAlbumLeft, strAlbumRight)); // Filename, empty | Userdefined, Userdefined else AddSortMethod(SORT_METHOD_ALBUM, 558, LABEL_MASKS("%F", "", strAlbumLeft, strAlbumRight)); // Filename, empty | Userdefined, Userdefined // artist - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) AddSortMethod(SORT_METHOD_ARTIST_IGNORE_THE, 557, LABEL_MASKS("%F", "", strAlbumLeft, strAlbumRight)); // Filename, empty | Userdefined, Userdefined else AddSortMethod(SORT_METHOD_ARTIST, 557, LABEL_MASKS("%F", "", strAlbumLeft, strAlbumRight)); // Filename, empty | Userdefined, Userdefined @@ -206,7 +206,7 @@ CGUIViewStateMusicDatabase::CGUIViewStateMusicDatabase(const CFileItemList& item // year AddSortMethod(SORT_METHOD_YEAR, 562, LABEL_MASKS("%F", "", strAlbumLeft, strAlbumRight)); - CViewState *viewState = CViewStateSettings::Get().Get("musicnavalbums"); + const CViewState *viewState = CViewStateSettings::Get().Get("musicnavalbums"); SetSortMethod(viewState->m_sortMethod); SetViewAsControl(viewState->m_viewMode); SetSortOrder(viewState->m_sortOrder); @@ -258,13 +258,12 @@ CGUIViewStateMusicDatabase::CGUIViewStateMusicDatabase(const CFileItemList& item SetSortMethod(SORT_METHOD_NONE); SetViewAsControl(DEFAULT_VIEW_LIST); - SetSortOrder(SortOrderNone); } break; case NODE_TYPE_SINGLES: { - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) { AddSortMethod(SORT_METHOD_ARTIST_IGNORE_THE, 557, LABEL_MASKS("%A - %T", "%D")); // Artist, Title, Duration| empty, empty AddSortMethod(SORT_METHOD_TITLE_IGNORE_THE, 556, LABEL_MASKS("%T - %A", "%D")); // Title, Artist, Duration| empty, empty @@ -278,8 +277,8 @@ CGUIViewStateMusicDatabase::CGUIViewStateMusicDatabase(const CFileItemList& item } AddSortMethod(SORT_METHOD_DURATION, 180, LABEL_MASKS("%T - %A", "%D")); // Titel, Artist, Duration| empty, empty AddSortMethod(SORT_METHOD_SONG_RATING, 563, LABEL_MASKS("%T - %A", "%R")); // Title - Artist, Rating - - CViewState *viewState = CViewStateSettings::Get().Get("musicnavsongs"); + + const CViewState *viewState = CViewStateSettings::Get().Get("musicnavsongs"); SetSortMethod(viewState->m_sortMethod); SetViewAsControl(viewState->m_viewMode); SetSortOrder(viewState->m_sortOrder); @@ -291,7 +290,7 @@ CGUIViewStateMusicDatabase::CGUIViewStateMusicDatabase(const CFileItemList& item case NODE_TYPE_SONG: { AddSortMethod(SORT_METHOD_TRACKNUM, 554, LABEL_MASKS(strTrackLeft, strTrackRight)); // Userdefined, Userdefined| empty, empty - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) { AddSortMethod(SORT_METHOD_TITLE_IGNORE_THE, 556, LABEL_MASKS("%T - %A", "%D")); // Title, Artist, Duration| empty, empty AddSortMethod(SORT_METHOD_ALBUM_IGNORE_THE, 558, LABEL_MASKS("%B - %T - %A", "%D")); // Album, Title, Artist, Duration| empty, empty @@ -308,12 +307,12 @@ CGUIViewStateMusicDatabase::CGUIViewStateMusicDatabase(const CFileItemList& item AddSortMethod(SORT_METHOD_DURATION, 180, LABEL_MASKS("%T - %A", "%D")); // Titel, Artist, Duration| empty, empty AddSortMethod(SORT_METHOD_SONG_RATING, 563, LABEL_MASKS("%T - %A", "%R")); // Title - Artist, Rating AddSortMethod(SORT_METHOD_YEAR, 562, LABEL_MASKS("%T - %A", "%Y")); // Title, Artist, Year - - CViewState *viewState = CViewStateSettings::Get().Get("musicnavsongs"); + + const CViewState *viewState = CViewStateSettings::Get().Get("musicnavsongs"); // the "All Albums" entries always default to SORT_METHOD_ALBUM as this is most logical - user can always // change it and the change will be saved for this particular path if (dir.IsAllItem(items.GetPath())) - SetSortMethod(g_guiSettings.GetBool("filelists.ignorethewhensorting") ? SORT_METHOD_ALBUM_IGNORE_THE : SORT_METHOD_ALBUM); + SetSortMethod(CSettings::Get().GetBool("filelists.ignorethewhensorting") ? SORT_METHOD_ALBUM_IGNORE_THE : SORT_METHOD_ALBUM); else SetSortMethod(viewState->m_sortMethod); @@ -382,11 +381,11 @@ CGUIViewStateMusicSmartPlaylist::CGUIViewStateMusicSmartPlaylist(const CFileItem { if (items.GetContent() == "songs" || items.GetContent() == "mixed") { - CStdString strTrackLeft=g_guiSettings.GetString("musicfiles.trackformat"); - CStdString strTrackRight=g_guiSettings.GetString("musicfiles.trackformatright"); + CStdString strTrackLeft=CSettings::Get().GetString("musicfiles.trackformat"); + CStdString strTrackRight=CSettings::Get().GetString("musicfiles.trackformatright"); AddSortMethod(SORT_METHOD_TRACKNUM, 554, LABEL_MASKS(strTrackLeft, strTrackRight)); // Userdefined, Userdefined| empty, empty - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) { AddSortMethod(SORT_METHOD_TITLE_IGNORE_THE, 556, LABEL_MASKS("%T - %A", "%D")); // Title, Artist, Duration| empty, empty AddSortMethod(SORT_METHOD_ALBUM_IGNORE_THE, 558, LABEL_MASKS("%B - %T - %A", "%D")); // Album, Titel, Artist, Duration| empty, empty @@ -416,13 +415,13 @@ CGUIViewStateMusicSmartPlaylist::CGUIViewStateMusicSmartPlaylist(const CFileItem strAlbumRight = "%A"; // artist // album - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) AddSortMethod(SORT_METHOD_ALBUM_IGNORE_THE, 558, LABEL_MASKS("%F", "", strAlbumLeft, strAlbumRight)); // Filename, empty | Userdefined, Userdefined else AddSortMethod(SORT_METHOD_ALBUM, 558, LABEL_MASKS("%F", "", strAlbumLeft, strAlbumRight)); // Filename, empty | Userdefined, Userdefined // artist - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) AddSortMethod(SORT_METHOD_ARTIST_IGNORE_THE, 557, LABEL_MASKS("%F", "", strAlbumLeft, strAlbumRight)); // Filename, empty | Userdefined, Userdefined else AddSortMethod(SORT_METHOD_ARTIST, 557, LABEL_MASKS("%F", "", strAlbumLeft, strAlbumRight)); // Filename, empty | Userdefined, Userdefined @@ -449,12 +448,12 @@ void CGUIViewStateMusicSmartPlaylist::SaveViewState() CGUIViewStateMusicPlaylist::CGUIViewStateMusicPlaylist(const CFileItemList& items) : CGUIViewStateWindowMusic(items) { - CStdString strTrackLeft=g_guiSettings.GetString("musicfiles.trackformat"); - CStdString strTrackRight=g_guiSettings.GetString("musicfiles.trackformatright"); + CStdString strTrackLeft=CSettings::Get().GetString("musicfiles.trackformat"); + CStdString strTrackRight=CSettings::Get().GetString("musicfiles.trackformatright"); AddSortMethod(SORT_METHOD_PLAYLIST_ORDER, 559, LABEL_MASKS(strTrackLeft, strTrackRight)); AddSortMethod(SORT_METHOD_TRACKNUM, 554, LABEL_MASKS(strTrackLeft, strTrackRight)); // Userdefined, Userdefined| empty, empty - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) { AddSortMethod(SORT_METHOD_TITLE_IGNORE_THE, 556, LABEL_MASKS("%T - %A", "%D")); // Title, Artist, Duration| empty, empty AddSortMethod(SORT_METHOD_ALBUM_IGNORE_THE, 558, LABEL_MASKS("%B - %T - %A", "%D")); // Album, Titel, Artist, Duration| empty, empty @@ -472,7 +471,8 @@ CGUIViewStateMusicPlaylist::CGUIViewStateMusicPlaylist(const CFileItemList& item AddSortMethod(SORT_METHOD_SONG_RATING, 563, LABEL_MASKS("%T - %A", "%R")); // Titel, Artist, Rating| empty, empty SetSortMethod(SORT_METHOD_PLAYLIST_ORDER); - CViewState *viewState = CViewStateSettings::Get().Get("musicfiles"); + + const CViewState *viewState = CViewStateSettings::Get().Get("musicfiles"); SetViewAsControl(viewState->m_viewMode); SetSortOrder(viewState->m_sortOrder); @@ -498,18 +498,18 @@ CGUIViewStateWindowMusicNav::CGUIViewStateWindowMusicNav(const CFileItemList& it } else { - if (items.IsVideoDb() && items.Size() > (g_guiSettings.GetBool("filelists.showparentdiritems")?1:0)) + if (items.IsVideoDb() && items.Size() > (CSettings::Get().GetBool("filelists.showparentdiritems")?1:0)) { XFILE::VIDEODATABASEDIRECTORY::CQueryParams params; - XFILE::CVideoDatabaseDirectory::GetQueryParams(items[g_guiSettings.GetBool("filelists.showparentdiritems")?1:0]->GetPath(),params); + XFILE::CVideoDatabaseDirectory::GetQueryParams(items[CSettings::Get().GetBool("filelists.showparentdiritems")?1:0]->GetPath(),params); if (params.GetMVideoId() != -1) { - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) AddSortMethod(SORT_METHOD_LABEL_IGNORE_THE, 551, LABEL_MASKS("%T", "%Y")); // Filename, Duration | Foldername, empty else AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS("%T", "%Y")); // Filename, Duration | Foldername, empty AddSortMethod(SORT_METHOD_YEAR,562, LABEL_MASKS("%T", "%Y")); - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) { AddSortMethod(SORT_METHOD_ARTIST_IGNORE_THE,557, LABEL_MASKS("%A - %T", "%Y")); AddSortMethod(SORT_METHOD_ALBUM_IGNORE_THE,558, LABEL_MASKS("%B - %T", "%Y")); @@ -519,8 +519,8 @@ CGUIViewStateWindowMusicNav::CGUIViewStateWindowMusicNav(const CFileItemList& it AddSortMethod(SORT_METHOD_ARTIST,557, LABEL_MASKS("%A - %T", "%Y")); AddSortMethod(SORT_METHOD_ALBUM,558, LABEL_MASKS("%B - %T", "%Y")); } - CStdString strTrackLeft=g_guiSettings.GetString("musicfiles.trackformat"); - CStdString strTrackRight=g_guiSettings.GetString("musicfiles.trackformatright"); + CStdString strTrackLeft=CSettings::Get().GetString("musicfiles.trackformat"); + CStdString strTrackRight=CSettings::Get().GetString("musicfiles.trackformatright"); AddSortMethod(SORT_METHOD_TRACKNUM, 554, LABEL_MASKS(strTrackLeft, strTrackRight)); // Userdefined, Userdefined| empty, empty } else @@ -628,10 +628,10 @@ CGUIViewStateWindowMusicSongs::CGUIViewStateWindowMusicSongs(const CFileItemList } else { - CStdString strTrackLeft=g_guiSettings.GetString("musicfiles.trackformat"); - CStdString strTrackRight=g_guiSettings.GetString("musicfiles.trackformatright"); + CStdString strTrackLeft=CSettings::Get().GetString("musicfiles.trackformat"); + CStdString strTrackRight=CSettings::Get().GetString("musicfiles.trackformatright"); - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) AddSortMethod(SORT_METHOD_LABEL_IGNORE_THE, 551, LABEL_MASKS(strTrackLeft, strTrackRight, "%L", "")); // Userdefined, Userdefined | FolderName, empty else AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS(strTrackLeft, strTrackRight, "%L", "")); // Userdefined, Userdefined | FolderName, empty @@ -640,8 +640,8 @@ CGUIViewStateWindowMusicSongs::CGUIViewStateWindowMusicSongs(const CFileItemList AddSortMethod(SORT_METHOD_DATE, 552, LABEL_MASKS(strTrackLeft, "%J", "%L", "%J")); // Userdefined, Date | FolderName, Date AddSortMethod(SORT_METHOD_FILE, 561, LABEL_MASKS(strTrackLeft, strTrackRight, "%L", "")); // Userdefined, Userdefined | FolderName, empty AddSortMethod(SORT_METHOD_LISTENERS,20455,LABEL_MASKS(strTrackLeft, "%W", "%L", "%W")); - - CViewState *viewState = CViewStateSettings::Get().Get("musicfiles"); + + const CViewState *viewState = CViewStateSettings::Get().Get("musicfiles"); SetSortMethod(viewState->m_sortMethod); SetViewAsControl(viewState->m_viewMode); SetSortOrder(viewState->m_sortOrder); @@ -663,12 +663,12 @@ VECSOURCES& CGUIViewStateWindowMusicSongs::GetSources() CGUIViewStateWindowMusicPlaylist::CGUIViewStateWindowMusicPlaylist(const CFileItemList& items) : CGUIViewStateWindowMusic(items) { - CStdString strTrackLeft=g_guiSettings.GetString("musicfiles.nowplayingtrackformat"); + CStdString strTrackLeft=CSettings::Get().GetString("musicfiles.nowplayingtrackformat"); if (strTrackLeft.IsEmpty()) - strTrackLeft = g_guiSettings.GetString("musicfiles.trackformat"); - CStdString strTrackRight=g_guiSettings.GetString("musicfiles.nowplayingtrackformatright"); + strTrackLeft = CSettings::Get().GetString("musicfiles.trackformat"); + CStdString strTrackRight=CSettings::Get().GetString("musicfiles.nowplayingtrackformatright"); if (strTrackRight.IsEmpty()) - strTrackRight = g_guiSettings.GetString("musicfiles.trackformatright"); + strTrackRight = CSettings::Get().GetString("musicfiles.trackformatright"); AddSortMethod(SORT_METHOD_NONE, 551, LABEL_MASKS(strTrackLeft, strTrackRight, "%L", "")); // Userdefined, Userdefined | FolderName, empty SetSortMethod(SORT_METHOD_NONE); diff --git a/xbmc/music/MusicDatabase.cpp b/xbmc/music/MusicDatabase.cpp index 3c4e3cf04a..d6d02796ae 100644 --- a/xbmc/music/MusicDatabase.cpp +++ b/xbmc/music/MusicDatabase.cpp @@ -44,8 +44,6 @@ #include "dialogs/GUIDialogSelect.h" #include "filesystem/File.h" #include "profiles/ProfilesManager.h" -#include "settings/MediaSettings.h" -#include "settings/GUISettings.h" #include "settings/AdvancedSettings.h" #include "FileItem.h" #include "Application.h" @@ -53,6 +51,7 @@ #include "karaoke/karaokelyricsfactory.h" #endif #include "storage/MediaManager.h" +#include "settings/MediaSettings.h" #include "settings/Settings.h" #include "utils/StringUtils.h" #include "guilib/LocalizeStrings.h" @@ -80,6 +79,22 @@ using ADDON::AddonPtr; using namespace CDDB; #endif +static void AnnounceRemove(const std::string& content, int id) +{ + CVariant data; + data["type"] = content; + data["id"] = id; + ANNOUNCEMENT::CAnnouncementManager::Announce(ANNOUNCEMENT::AudioLibrary, "xbmc", "OnRemove", data); +} + +static void AnnounceUpdate(const std::string& content, int id) +{ + CVariant data; + data["type"] = content; + data["id"] = id; + ANNOUNCEMENT::CAnnouncementManager::Announce(ANNOUNCEMENT::AudioLibrary, "xbmc", "OnUpdate", data); +} + CMusicDatabase::CMusicDatabase(void) { } @@ -102,11 +117,11 @@ bool CMusicDatabase::CreateTables() CDatabase::CreateTables(); CLog::Log(LOGINFO, "create artist table"); - m_pDS->exec("CREATE TABLE artist ( idArtist integer primary key, strArtist varchar(256))\n"); + m_pDS->exec("CREATE TABLE artist ( idArtist integer primary key, strArtist varchar(256), strMusicBrainzArtistID text)\n"); CLog::Log(LOGINFO, "create album table"); - m_pDS->exec("CREATE TABLE album ( idAlbum integer primary key, strAlbum varchar(256), strArtists text, strGenres text, iYear integer, idThumb integer, bCompilation integer not null default '0' )\n"); + m_pDS->exec("CREATE TABLE album ( idAlbum integer primary key, strAlbum varchar(256), strArtists text, strGenres text, iYear integer, idThumb integer, bCompilation integer not null default '0', strMusicBrainzAlbumID text )\n"); CLog::Log(LOGINFO, "create album_artist table"); - m_pDS->exec("CREATE TABLE album_artist ( idArtist integer, idAlbum integer, boolFeatured integer, iOrder integer )\n"); + m_pDS->exec("CREATE TABLE album_artist ( idArtist integer, idAlbum integer, strJoinPhrase text, boolFeatured integer, iOrder integer )\n"); CLog::Log(LOGINFO, "create album_genre table"); m_pDS->exec("CREATE TABLE album_genre ( idGenre integer, idAlbum integer, iOrder integer )\n"); @@ -115,9 +130,9 @@ bool CMusicDatabase::CreateTables() CLog::Log(LOGINFO, "create path table"); m_pDS->exec("CREATE TABLE path ( idPath integer primary key, strPath varchar(512), strHash text)\n"); CLog::Log(LOGINFO, "create song table"); - m_pDS->exec("CREATE TABLE song ( idSong integer primary key, idAlbum integer, idPath integer, strArtists text, strGenres text, strTitle varchar(512), iTrack integer, iDuration integer, iYear integer, dwFileNameCRC text, strFileName text, strMusicBrainzTrackID text, strMusicBrainzArtistID text, strMusicBrainzAlbumID text, strMusicBrainzAlbumArtistID text, strMusicBrainzTRMID text, iTimesPlayed integer, iStartOffset integer, iEndOffset integer, idThumb integer, lastplayed varchar(20) default NULL, rating char default '0', comment text)\n"); + m_pDS->exec("CREATE TABLE song ( idSong integer primary key, idAlbum integer, idPath integer, strArtists text, strGenres text, strTitle varchar(512), iTrack integer, iDuration integer, iYear integer, dwFileNameCRC text, strFileName text, strMusicBrainzTrackID text, iTimesPlayed integer, iStartOffset integer, iEndOffset integer, idThumb integer, lastplayed varchar(20) default NULL, rating char default '0', comment text)\n"); CLog::Log(LOGINFO, "create song_artist table"); - m_pDS->exec("CREATE TABLE song_artist ( idArtist integer, idSong integer, boolFeatured integer, iOrder integer )\n"); + m_pDS->exec("CREATE TABLE song_artist ( idArtist integer, idSong integer, strJoinPhrase text, boolFeatured integer, iOrder integer )\n"); CLog::Log(LOGINFO, "create song_genre table"); m_pDS->exec("CREATE TABLE song_genre ( idGenre integer, idSong integer, iOrder integer )\n"); @@ -140,6 +155,8 @@ bool CMusicDatabase::CreateTables() m_pDS->exec("CREATE INDEX idxAlbum ON album(strAlbum)"); CLog::Log(LOGINFO, "create album compilation index"); m_pDS->exec("CREATE INDEX idxAlbum_1 ON album(bCompilation)"); + CLog::Log(LOGINFO, "create unique album name index"); + m_pDS->exec("CREATE UNIQUE INDEX idxAlbum_2 ON album(strMusicBrainzAlbumID(36))"); CLog::Log(LOGINFO, "create album_artist indexes"); m_pDS->exec("CREATE UNIQUE INDEX idxAlbumArtist_1 ON album_artist ( idAlbum, idArtist )\n"); @@ -152,8 +169,11 @@ bool CMusicDatabase::CreateTables() CLog::Log(LOGINFO, "create genre index"); m_pDS->exec("CREATE INDEX idxGenre ON genre(strGenre)"); - CLog::Log(LOGINFO, "create artist index"); + + CLog::Log(LOGINFO, "create artist indexes"); m_pDS->exec("CREATE INDEX idxArtist ON artist(strArtist)"); + m_pDS->exec("CREATE UNIQUE INDEX idxArtist1 ON artist(strMusicBrainzArtistID(36))"); + CLog::Log(LOGINFO, "create path index"); m_pDS->exec("CREATE INDEX idxPath ON path(strPath)"); @@ -167,6 +187,8 @@ bool CMusicDatabase::CreateTables() m_pDS->exec("CREATE INDEX idxSong3 ON song(idAlbum)"); CLog::Log(LOGINFO, "create song index6"); m_pDS->exec("CREATE UNIQUE INDEX idxSong6 ON song( idPath, strFileName(255) )"); + CLog::Log(LOGINFO, "create song index7"); + m_pDS->exec("CREATE UNIQUE INDEX idxSong7 ON song( idAlbum, strMusicBrainzTrackID(36) )"); CLog::Log(LOGINFO, "create song_artist indexes"); m_pDS->exec("CREATE UNIQUE INDEX idxSongArtist_1 ON song_artist ( idSong, idArtist )\n"); @@ -224,8 +246,7 @@ void CMusicDatabase::CreateViews() " song.strGenres AS strGenres," " strTitle, iTrack, iDuration," " song.iYear AS iYear, dwFileNameCRC, strFileName, strMusicBrainzTrackID," - " strMusicBrainzArtistID, strMusicBrainzAlbumID, strMusicBrainzAlbumArtistID," - " strMusicBrainzTRMID, iTimesPlayed, iStartOffset, iEndOffset, lastplayed," + " iTimesPlayed, iStartOffset, iEndOffset, lastplayed," " rating, comment, song.idAlbum AS idAlbum, strAlbum, strPath," " iKaraNumber, iKaraDelay, strKaraEncoding," " album.bCompilation AS bCompilation," @@ -240,26 +261,70 @@ void CMusicDatabase::CreateViews() CLog::Log(LOGINFO, "create album view"); m_pDS->exec("DROP VIEW IF EXISTS albumview"); - m_pDS->exec("CREATE VIEW albumview AS SELECT" - " album.idAlbum AS idAlbum, strAlbum, " - " album.strArtists AS strArtists," - " album.strGenres AS strGenres, " - " album.iYear AS iYear," - " idAlbumInfo, strMoods, strStyles, strThemes," - " strReview, strLabel, strType, strImage, iRating, " - " bCompilation, " - " MIN(song.iTimesPlayed) AS iTimesPlayed " - "FROM album " - " LEFT OUTER JOIN albuminfo ON" - " album.idAlbum=albuminfo.idAlbum" - " LEFT OUTER JOIN song ON" - " album.idAlbum=song.idAlbum " - "GROUP BY album.idAlbum"); + if (m_sqlite) + { + m_pDS->exec("CREATE VIEW albumview AS SELECT " + " album.idAlbum AS idAlbum, " + " strAlbum, " + " strMusicBrainzAlbumID, " + " GROUP_CONCAT(strArtist || strJoinPhrase, '') as strArtists, " + " album.strGenres AS strGenres, " + " album.iYear AS iYear, " + " idAlbumInfo, " + " strMoods, " + " strStyles, " + " strThemes, " + " strReview, " + " strLabel, " + " strType, " + " strImage, " + " iRating, " + " bCompilation, " + " (SELECT MIN(iTimesPlayed) AS iTimesPlayed FROM song WHERE song.idAlbum = album.idAlbum)" + " FROM album " + " LEFT OUTER JOIN " + " albuminfo ON album.idAlbum = albuminfo.idAlbum " + " LEFT OUTER JOIN album_artist ON " + " album.idAlbum = album_artist.idAlbum " + " LEFT OUTER JOIN artist ON " + " album_artist.idArtist = artist.idArtist " + " GROUP BY album.idAlbum"); + } + else + { + m_pDS->exec("CREATE VIEW albumview AS SELECT " + " album.idAlbum AS idAlbum, " + " strAlbum, " + " strMusicBrainzAlbumID, " + " GROUP_CONCAT(strArtist, strJoinPhrase ORDER BY iOrder SEPARATOR '') as strArtists, " + " album.strGenres AS strGenres, " + " album.iYear AS iYear, " + " idAlbumInfo, " + " strMoods, " + " strStyles, " + " strThemes, " + " strReview, " + " strLabel, " + " strType, " + " strImage, " + " iRating, " + " bCompilation, " + " (SELECT MIN(iTimesPlayed) AS iTimesPlayed FROM song WHERE song.idAlbum = album.idAlbum)" + " FROM album " + " LEFT OUTER JOIN " + " albuminfo ON album.idAlbum = albuminfo.idAlbum " + " LEFT OUTER JOIN album_artist ON " + " album.idAlbum = album_artist.idAlbum " + " LEFT OUTER JOIN artist ON " + " album_artist.idArtist = artist.idArtist " + " GROUP BY album.idAlbum"); + } CLog::Log(LOGINFO, "create artist view"); m_pDS->exec("DROP VIEW IF EXISTS artistview"); m_pDS->exec("CREATE VIEW artistview AS SELECT" " artist.idArtist AS idArtist, strArtist, " + " artist.strMusicBrainzArtistID AS strMusicBrainzArtistID, " " strBorn, strFormed, strGenres," " strMoods, strStyles, strInstruments, " " strBiography, strDied, strDisbanded, " @@ -269,124 +334,80 @@ void CMusicDatabase::CreateViews() " artist.idArtist = artistinfo.idArtist"); } -int CMusicDatabase::AddAlbum(const CAlbum &album, vector<int> &songIDs) -{ - // add the album - int idAlbum = AddAlbum(album.strAlbum, StringUtils::Join(album.artist, g_advancedSettings.m_musicItemSeparator), StringUtils::Join(album.genre, g_advancedSettings.m_musicItemSeparator), album.iYear, album.bCompilation); - - SetArtForItem(idAlbum, "album", album.art); - - // add the songs - for (VECSONGS::const_iterator i = album.songs.begin(); i != album.songs.end(); ++i) - songIDs.push_back(AddSong(*i, false, idAlbum)); - - return idAlbum; -} - -int CMusicDatabase::AddSong(const CSong& song, bool bCheck, int idAlbum) +int CMusicDatabase::AddSong(const int idAlbum, + const CStdString& strTitle, const CStdString& strMusicBrainzTrackID, + const CStdString& strPathAndFileName, const CStdString& strComment, const CStdString& strThumb, + const std::vector<std::string>& artists, const std::vector<std::string>& genres, + int iTrack, int iDuration, int iYear, + const int iTimesPlayed, int iStartOffset, int iEndOffset, + const CDateTime& dtLastPlayed, char rating, int iKaraokeNumber) { int idSong = -1; CStdString strSQL; try { // We need at least the title - if (song.strTitle.IsEmpty()) + if (strTitle.IsEmpty()) return -1; - CStdString strPath, strFileName; - URIUtils::Split(song.strFileName, strPath, strFileName); - if (NULL == m_pDB.get()) return -1; if (NULL == m_pDS.get()) return -1; + CStdString strPath, strFileName; + URIUtils::Split(strPathAndFileName, strPath, strFileName); int idPath = AddPath(strPath); - if (idAlbum < 0) - { - if (!song.albumArtist.empty()) // have an album artist - idAlbum = AddAlbum(song.strAlbum, StringUtils::Join(song.albumArtist, g_advancedSettings.m_musicItemSeparator), StringUtils::Join(song.genre, g_advancedSettings.m_musicItemSeparator), song.iYear, song.bCompilation); - else - idAlbum = AddAlbum(song.strAlbum, StringUtils::Join(song.artist, g_advancedSettings.m_musicItemSeparator), StringUtils::Join(song.genre, g_advancedSettings.m_musicItemSeparator), song.iYear, song.bCompilation); - } - - DWORD crc = ComputeCRC(song.strFileName); + DWORD crc = ComputeCRC(strFileName); - bool bInsert = true; bool bHasKaraoke = false; #ifdef HAS_KARAOKE - bHasKaraoke = CKaraokeLyricsFactory::HasLyrics( song.strFileName ); + bHasKaraoke = CKaraokeLyricsFactory::HasLyrics(strPathAndFileName); #endif - if (bCheck) - { - strSQL=PrepareSQL("select * from song where idAlbum=%i and dwFileNameCRC='%ul' and strTitle='%s'", - idAlbum, crc, song.strTitle.c_str()); + strSQL=PrepareSQL("SELECT * FROM song WHERE (idAlbum = %i AND strMusicBrainzTrackID = '%s') OR (idAlbum=%i AND dwFileNameCRC='%ul' AND strTitle='%s' AND strMusicBrainzTrackID IS NULL)", + idAlbum, + strMusicBrainzTrackID.c_str(), + idAlbum, + crc, + strTitle.c_str()); - if (!m_pDS->query(strSQL.c_str())) - return -1; + if (!m_pDS->query(strSQL.c_str())) + return -1; - if (m_pDS->num_rows() != 0) - { - idSong = m_pDS->fv("idSong").get_asInt(); - bInsert = false; - } - m_pDS->close(); - } - if (bInsert) + if (m_pDS->num_rows() == 0) { - CStdString strSQL1; - - CStdString strIdSong; - if (song.idSong < 0) - strIdSong = "NULL"; - else - strIdSong.Format("%d", song.idSong); - - // we use replace because it can handle both inserting a new song - // and replacing an existing song's record if the given idSong already exists - strSQL=PrepareSQL("replace into song (idSong,idAlbum,idPath,strArtists,strGenres,strTitle,iTrack,iDuration,iYear,dwFileNameCRC,strFileName,strMusicBrainzTrackID,strMusicBrainzArtistID,strMusicBrainzAlbumID,strMusicBrainzAlbumArtistID,strMusicBrainzTRMID,iTimesPlayed,iStartOffset,iEndOffset,lastplayed,rating,comment) values (%s,%i,%i,'%s','%s','%s',%i,%i,%i,'%ul','%s','%s','%s','%s','%s','%s'", - strIdSong.c_str(), - idAlbum, idPath, - StringUtils::Join(song.artist, g_advancedSettings.m_musicItemSeparator).c_str(), - StringUtils::Join(song.genre, g_advancedSettings.m_musicItemSeparator).c_str(), - song.strTitle.c_str(), - song.iTrack, song.iDuration, song.iYear, - crc, strFileName.c_str(), - song.strMusicBrainzTrackID.c_str(), - song.strMusicBrainzArtistID.c_str(), - song.strMusicBrainzAlbumID.c_str(), - song.strMusicBrainzAlbumArtistID.c_str(), - song.strMusicBrainzTRMID.c_str()); - - if (song.lastPlayed.IsValid()) - strSQL1=PrepareSQL(",%i,%i,%i,'%s','%c','%s')", - song.iTimesPlayed, song.iStartOffset, song.iEndOffset, song.lastPlayed.GetAsDBDateTime().c_str(), song.rating, song.strComment.c_str()); + m_pDS->close(); + strSQL=PrepareSQL("INSERT INTO song (idSong,idAlbum,idPath,strArtists,strGenres,strTitle,iTrack,iDuration,iYear,dwFileNameCRC,strFileName,strMusicBrainzTrackID,iTimesPlayed,iStartOffset,iEndOffset,lastplayed,rating,comment) values (NULL, %i, %i, '%s', '%s', '%s', %i, %i, %i, '%ul', '%s'", + idAlbum, + idPath, + StringUtils::Join(artists, g_advancedSettings.m_musicItemSeparator).c_str(), + StringUtils::Join(genres, g_advancedSettings.m_musicItemSeparator).c_str(), + strTitle.c_str(), + iTrack, iDuration, iYear, + crc, strFileName.c_str()); + + if (strMusicBrainzTrackID.IsEmpty()) + strSQL += PrepareSQL(",NULL"); else - strSQL1=PrepareSQL(",%i,%i,%i,NULL,'%c','%s')", - song.iTimesPlayed, song.iStartOffset, song.iEndOffset, song.rating, song.strComment.c_str()); - strSQL+=strSQL1; - - m_pDS->exec(strSQL.c_str()); + strSQL += PrepareSQL(",'%s'", strMusicBrainzTrackID.c_str()); - if (song.idSong < 0) - idSong = (int)m_pDS->lastinsertid(); + if (dtLastPlayed.IsValid()) + strSQL += PrepareSQL(",%i,%i,%i,'%s','%c','%s')", + iTimesPlayed, iStartOffset, iEndOffset, dtLastPlayed.GetAsDBDateTime().c_str(), rating, strComment.c_str()); else - idSong = song.idSong; + strSQL += PrepareSQL(",%i,%i,%i,NULL,'%c','%s')", + iTimesPlayed, iStartOffset, iEndOffset, rating, strComment.c_str()); + m_pDS->exec(strSQL.c_str()); + idSong = (int)m_pDS->lastinsertid(); } - - if (!song.strThumb.empty()) - SetArtForItem(idSong, "song", "thumb", song.strThumb); - - for (unsigned int index = 0; index < song.albumArtist.size(); index++) + else { - int idAlbumArtist = AddArtist(song.albumArtist[index]); - AddAlbumArtist(idAlbumArtist, idAlbum, index > 0 ? true : false, index); + idSong = m_pDS->fv("idSong").get_asInt(); + m_pDS->close(); + UpdateSong(idSong, strTitle, strMusicBrainzTrackID, strPathAndFileName, strComment, strThumb, artists, genres, iTrack, iDuration, iYear, iTimesPlayed, iStartOffset, iEndOffset, dtLastPlayed, rating, iKaraokeNumber); } - for (unsigned int index = 0; index < song.artist.size(); index++) - { - int idArtist = AddArtist(song.artist[index]); - AddSongArtist(idArtist, idSong, index > 0 ? true : false, index); - } + if (!strThumb.empty()) + SetArtForItem(idSong, "song", "thumb", strThumb); unsigned int index = 0; // If this is karaoke song, change the genre to 'Karaoke' (and add it if it's not there) @@ -396,7 +417,7 @@ int CMusicDatabase::AddSong(const CSong& song, bool bCheck, int idAlbum) AddSongGenre(idGenre, idSong, index); AddAlbumGenre(idGenre, idAlbum, index++); } - for (vector<string>::const_iterator i = song.genre.begin(); i != song.genre.end(); ++i) + for (vector<string>::const_iterator i = genres.begin(); i != genres.end(); ++i) { // index will be wrong for albums, but ordering is not all that relevant // for genres anyway @@ -406,8 +427,8 @@ int CMusicDatabase::AddSong(const CSong& song, bool bCheck, int idAlbum) } // Add karaoke information (if any) - if ( bHasKaraoke ) - AddKaraokeData(idSong, song ); + if (bHasKaraoke) + AddKaraokeData(idSong, iKaraokeNumber, crc); AnnounceUpdate("song", idSong); } @@ -418,88 +439,106 @@ int CMusicDatabase::AddSong(const CSong& song, bool bCheck, int idAlbum) return idSong; } -int CMusicDatabase::UpdateSong(const CSong& song, int idSong /* = -1 */) + int CMusicDatabase::UpdateSong(int idSong, + const CStdString& strTitle, const CStdString& strMusicBrainzTrackID, + const CStdString& strPathAndFileName, const CStdString& strComment, const CStdString& strThumb, + const std::vector<std::string>& artists, const std::vector<std::string>& genres, + int iTrack, int iDuration, int iYear, + int iTimesPlayed, int iStartOffset, int iEndOffset, + const CDateTime& dtLastPlayed, char rating, int iKaraokeNumber) { CStdString sql; if (idSong < 0) - idSong = song.idSong; - - if (idSong < 0) return -1; - - // delete linked songs - // we don't delete from the song table here because - // AddSong will update the existing record - sql.Format("delete from song_artist where idSong=%d", idSong); - ExecuteQuery(sql); - sql.Format("delete from song_genre where idSong=%d", idSong); - ExecuteQuery(sql); - sql.Format("delete from karaokedata where idSong=%d", idSong); - ExecuteQuery(sql); - - CSong newSong = song; - // Make sure newSong.idSong has a valid value (> 0) - newSong.idSong = idSong; - // re-add the song - newSong.idSong = AddSong(newSong, false); - if (newSong.idSong < 0) - return -1; - - return newSong.idSong; + + CStdString strSQL; + try + { + CStdString strPath, strFileName; + URIUtils::Split(strPathAndFileName, strPath, strFileName); + int idPath = AddPath(strPath); + DWORD crc = ComputeCRC(strFileName); + + strSQL = PrepareSQL("UPDATE song SET idPath = %i, strArtists = '%s', strGenres = '%s', strTitle = '%s', iTrack = %i, iDuration = %i, iYear = %i, dwFileNameCRC = '%ul', strFileName = '%s'", + idPath, + StringUtils::Join(artists, g_advancedSettings.m_musicItemSeparator).c_str(), + StringUtils::Join(genres, g_advancedSettings.m_musicItemSeparator).c_str(), + strTitle.c_str(), + iTrack, iDuration, iYear, + crc, strFileName.c_str()); + if (strMusicBrainzTrackID.IsEmpty()) + strSQL += PrepareSQL(", strMusicBrainzTrackID = NULL"); + else + strSQL += PrepareSQL(", strMusicBrainzTrackID = '%s'", strMusicBrainzTrackID.c_str()); + + if (dtLastPlayed.IsValid()) + strSQL += PrepareSQL(", iTimesPlayed = %i, iStartOffset = %i, iEndOffset = %i, lastplayed = '%s', rating = '%c', comment = '%s'", + iTimesPlayed, iStartOffset, iEndOffset, dtLastPlayed.GetAsDBDateTime().c_str(), rating, strComment.c_str()); + else + strSQL += PrepareSQL(", iTimesPlayed = %i, iStartOffset = %i, iEndOffset = %i, lastplayed = NULL, rating = '%c', comment = '%s'", + iTimesPlayed, iStartOffset, iEndOffset, rating, strComment.c_str()); + strSQL += PrepareSQL(" WHERE idSong = %i", idSong); + m_pDS->exec(strSQL.c_str()); + } + catch (...) + { + CLog::Log(LOGERROR, "musicdatabase:unable to addsong (%s)", strSQL.c_str()); + } + return idSong; } -int CMusicDatabase::AddAlbum(const CStdString& strAlbum1, const CStdString &strArtist, const CStdString& strGenre, int year, bool bCompilation) +int CMusicDatabase::AddAlbum(const CStdString& strAlbum, const CStdString& strMusicBrainzAlbumID, + const CStdString& strArtist, const CStdString& strGenre, int year, bool bCompilation) { CStdString strSQL; try { - CStdString strAlbum=strAlbum1; - strAlbum.Trim(); - if (NULL == m_pDB.get()) return -1; if (NULL == m_pDS.get()) return -1; - map <CStdString, CAlbum>::const_iterator it; - - it = m_albumCache.find(strAlbum + strArtist); - if (it != m_albumCache.end()) - return it->second.idAlbum; - - strSQL=PrepareSQL("select * from album where strArtists='%s' and strAlbum like '%s'", strArtist.c_str(), strAlbum.c_str()); + strSQL=PrepareSQL("SELECT * FROM album WHERE strMusicBrainzAlbumID = '%s' OR (strArtists = '%s' AND strAlbum like '%s' and strMusicBrainzAlbumID IS NULL)", + strMusicBrainzAlbumID.c_str(), + strArtist.c_str(), + strAlbum.c_str()); m_pDS->query(strSQL.c_str()); if (m_pDS->num_rows() == 0) { m_pDS->close(); // doesnt exists, add it - strSQL=PrepareSQL("insert into album (idAlbum, strAlbum, strArtists, strGenres, iYear, bCompilation) values( NULL, '%s', '%s', '%s', %i, %i)", strAlbum.c_str(), strArtist.c_str(), strGenre.c_str(), year, bCompilation); + if (strMusicBrainzAlbumID.IsEmpty()) + strSQL=PrepareSQL("insert into album (idAlbum, strAlbum, strMusicBrainzAlbumID, strArtists, strGenres, iYear, bCompilation) values( NULL, '%s', NULL, '%s', '%s', %i, %i)", + strAlbum.c_str(), + strArtist.c_str(), + strGenre.c_str(), + year, + bCompilation); + else + strSQL=PrepareSQL("insert into album (idAlbum, strAlbum, strMusicBrainzAlbumID, strArtists, strGenres, iYear, bCompilation) values( NULL, '%s', '%s', '%s', '%s', %i, %i)", + strAlbum.c_str(), + strMusicBrainzAlbumID.c_str(), + strArtist.c_str(), + strGenre.c_str(), + year, + bCompilation); m_pDS->exec(strSQL.c_str()); - CAlbum album; - album.idAlbum = (int)m_pDS->lastinsertid(); - album.strAlbum = strAlbum; - album.artist = StringUtils::Split(strArtist, g_advancedSettings.m_musicItemSeparator); - m_albumCache.insert(pair<CStdString, CAlbum>(album.strAlbum + strArtist, album)); - return album.idAlbum; + return (int)m_pDS->lastinsertid(); } else { // exists in our database and not scanned during this scan, so we should update it as the details // may have changed (there's a reason we're rescanning, afterall!) - CAlbum album; - album.idAlbum = m_pDS->fv("idAlbum").get_asInt(); - album.strAlbum = strAlbum; - album.artist = StringUtils::Split(strArtist, g_advancedSettings.m_musicItemSeparator); - m_albumCache.insert(pair<CStdString, CAlbum>(album.strAlbum + strArtist, album)); + int idAlbum = m_pDS->fv("idAlbum").get_asInt(); m_pDS->close(); - strSQL=PrepareSQL("update album set strGenres='%s', iYear=%i where idAlbum=%i", strGenre.c_str(), year, album.idAlbum); + strSQL=PrepareSQL("update album set strGenres='%s', iYear=%i where idAlbum=%i", strGenre.c_str(), year, idAlbum); m_pDS->exec(strSQL.c_str()); // and clear the link tables - these are updated in AddSong() - strSQL=PrepareSQL("delete from album_artist where idAlbum=%i", album.idAlbum); + strSQL=PrepareSQL("delete from album_artist where idAlbum=%i", idAlbum); m_pDS->exec(strSQL.c_str()); - strSQL=PrepareSQL("delete from album_genre where idAlbum=%i", album.idAlbum); + strSQL=PrepareSQL("delete from album_genre where idAlbum=%i", idAlbum); m_pDS->exec(strSQL.c_str()); - return album.idAlbum; + return idAlbum; } } catch (...) @@ -559,43 +598,37 @@ int CMusicDatabase::AddGenre(const CStdString& strGenre1) return -1; } -int CMusicDatabase::AddArtist(const CStdString& strArtist1) +int CMusicDatabase::AddArtist(const CStdString& strArtist, const CStdString& strMusicBrainzArtistID) { CStdString strSQL; try { - CStdString strArtist = strArtist1; - strArtist.Trim(); - - if (strArtist.IsEmpty()) - strArtist=g_localizeStrings.Get(13205); // Unknown - if (NULL == m_pDB.get()) return -1; if (NULL == m_pDS.get()) return -1; - map <CStdString, int>::const_iterator it; - - it = m_artistCache.find(strArtist); - if (it != m_artistCache.end()) - return it->second;//.idArtist; - - strSQL=PrepareSQL("select * from artist where strArtist like '%s'", strArtist.c_str()); + strSQL = PrepareSQL("SELECT * FROM artist WHERE strMusicBrainzArtistID = '%s' OR (strArtist = '%s' AND strMusicBrainzArtistID IS NULL)", + strMusicBrainzArtistID.IsEmpty() ? "x" : strMusicBrainzArtistID.c_str(), + strArtist.c_str()); m_pDS->query(strSQL.c_str()); if (m_pDS->num_rows() == 0) { m_pDS->close(); // doesnt exists, add it - strSQL=PrepareSQL("insert into artist (idArtist, strArtist) values( NULL, '%s' )", strArtist.c_str()); + if (strMusicBrainzArtistID.IsEmpty()) + strSQL = PrepareSQL("INSERT INTO artist (idArtist, strArtist, strMusicBrainzArtistID) VALUES( NULL, '%s', NULL )", + strArtist.c_str()); + else + strSQL = PrepareSQL("INSERT INTO artist (idArtist, strArtist, strMusicBrainzArtistID) VALUES( NULL, '%s', '%s' )", + strArtist.c_str(), + strMusicBrainzArtistID.c_str()); m_pDS->exec(strSQL.c_str()); int idArtist = (int)m_pDS->lastinsertid(); - m_artistCache.insert(pair<CStdString, int>(strArtist1, idArtist)); return idArtist; } else { int idArtist = (int)m_pDS->fv("idArtist").get_asInt(); - m_artistCache.insert(pair<CStdString, int>(strArtist1, idArtist)); m_pDS->close(); return idArtist; } @@ -608,19 +641,19 @@ int CMusicDatabase::AddArtist(const CStdString& strArtist1) return -1; } -bool CMusicDatabase::AddSongArtist(int idArtist, int idSong, bool featured, int iOrder) +bool CMusicDatabase::AddSongArtist(int idArtist, int idSong, std::string joinPhrase, bool featured, int iOrder) { CStdString strSQL; - strSQL=PrepareSQL("replace into song_artist (idArtist, idSong, boolFeatured, iOrder) values(%i,%i,%i,%i)", - idArtist, idSong, featured == true ? 1 : 0, iOrder); + strSQL=PrepareSQL("replace into song_artist (idArtist, idSong, strJoinPhrase, boolFeatured, iOrder) values(%i,%i,'%s',%i,%i)", + idArtist, idSong, joinPhrase.c_str(), featured == true ? 1 : 0, iOrder); return ExecuteQuery(strSQL); }; -bool CMusicDatabase::AddAlbumArtist(int idArtist, int idAlbum, bool featured, int iOrder) +bool CMusicDatabase::AddAlbumArtist(int idArtist, int idAlbum, std::string joinPhrase, bool featured, int iOrder) { CStdString strSQL; - strSQL=PrepareSQL("replace into album_artist (idArtist, idAlbum, boolFeatured, iOrder) values(%i,%i,%i,%i)", - idArtist, idAlbum, featured == true ? 1 : 0, iOrder); + strSQL=PrepareSQL("replace into album_artist (idArtist, idAlbum, strJoinPhrase, boolFeatured, iOrder) values(%i,%i,'%s',%i,%i)", + idArtist, idAlbum, joinPhrase.c_str(), featured == true ? 1 : 0, iOrder); return ExecuteQuery(strSQL); }; @@ -896,7 +929,7 @@ CSong CMusicDatabase::GetSongFromDataset(bool bWithMusicDbPath/*=false*/) song.genre = StringUtils::Split(m_pDS->fv(song_strGenres).get_asString(), g_advancedSettings.m_musicItemSeparator); // and the rest... song.strAlbum = m_pDS->fv(song_strAlbum).get_asString(); - song.iAlbumId = m_pDS->fv(song_idAlbum).get_asInt(); + song.idAlbum = m_pDS->fv(song_idAlbum).get_asInt(); song.iTrack = m_pDS->fv(song_iTrack).get_asInt() ; song.iDuration = m_pDS->fv(song_iDuration).get_asInt() ; song.iYear = m_pDS->fv(song_iYear).get_asInt() ; @@ -906,10 +939,6 @@ CSong CMusicDatabase::GetSongFromDataset(bool bWithMusicDbPath/*=false*/) song.iStartOffset = m_pDS->fv(song_iStartOffset).get_asInt(); song.iEndOffset = m_pDS->fv(song_iEndOffset).get_asInt(); song.strMusicBrainzTrackID = m_pDS->fv(song_strMusicBrainzTrackID).get_asString(); - song.strMusicBrainzArtistID = m_pDS->fv(song_strMusicBrainzArtistID).get_asString(); - song.strMusicBrainzAlbumID = m_pDS->fv(song_strMusicBrainzAlbumID).get_asString(); - song.strMusicBrainzAlbumArtistID = m_pDS->fv(song_strMusicBrainzAlbumArtistID).get_asString(); - song.strMusicBrainzTRMID = m_pDS->fv(song_strMusicBrainzTRMID).get_asString(); song.rating = m_pDS->fv(song_rating).get_asChar(); song.strComment = m_pDS->fv(song_comment).get_asString(); song.iKaraokeNumber = m_pDS->fv(song_iKarNumber).get_asInt(); @@ -920,7 +949,7 @@ CSong CMusicDatabase::GetSongFromDataset(bool bWithMusicDbPath/*=false*/) // Get filename with full path if (!bWithMusicDbPath) - URIUtils::AddFileToFolder(m_pDS->fv(song_strPath).get_asString(), m_pDS->fv(song_strFileName).get_asString(), song.strFileName); + song.strFileName = URIUtils::AddFileToFolder(m_pDS->fv(song_strPath).get_asString(), m_pDS->fv(song_strFileName).get_asString()); else { CStdString strFileName = m_pDS->fv(song_strFileName).get_asString(); @@ -957,16 +986,11 @@ void CMusicDatabase::GetFileItemFromDataset(const dbiplus::sql_record* const rec item->SetProperty("item_start", item->m_lStartOffset); item->m_lEndOffset = record->at(song_iEndOffset).get_asInt(); item->GetMusicInfoTag()->SetMusicBrainzTrackID(record->at(song_strMusicBrainzTrackID).get_asString()); - item->GetMusicInfoTag()->SetMusicBrainzArtistID(record->at(song_strMusicBrainzArtistID).get_asString()); - item->GetMusicInfoTag()->SetMusicBrainzAlbumID(record->at(song_strMusicBrainzAlbumID).get_asString()); - item->GetMusicInfoTag()->SetMusicBrainzAlbumArtistID(record->at(song_strMusicBrainzAlbumArtistID).get_asString()); - item->GetMusicInfoTag()->SetMusicBrainzTRMID(record->at(song_strMusicBrainzTRMID).get_asString()); item->GetMusicInfoTag()->SetRating(record->at(song_rating).get_asChar()); item->GetMusicInfoTag()->SetComment(record->at(song_comment).get_asString()); item->GetMusicInfoTag()->SetPlayCount(record->at(song_iTimesPlayed).get_asInt()); item->GetMusicInfoTag()->SetLastPlayed(record->at(song_lastplayed).get_asString()); - CStdString strRealPath; - URIUtils::AddFileToFolder(record->at(song_strPath).get_asString(), record->at(song_strFileName).get_asString(), strRealPath); + CStdString strRealPath = URIUtils::AddFileToFolder(record->at(song_strPath).get_asString(), record->at(song_strFileName).get_asString()); item->GetMusicInfoTag()->SetURL(strRealPath); item->GetMusicInfoTag()->SetCompilation(record->at(song_bCompilation).get_asInt() == 1); item->GetMusicInfoTag()->SetAlbumArtist(record->at(song_strAlbumArtists).get_asString()); @@ -1000,6 +1024,7 @@ CAlbum CMusicDatabase::GetAlbumFromDataset(const dbiplus::sql_record* const reco album.strAlbum = record->at(album_strAlbum).get_asString(); if (album.strAlbum.IsEmpty()) album.strAlbum = g_localizeStrings.Get(1050); + album.strMusicBrainzAlbumID = record->at(album_strMusicBrainzAlbumID).get_asString(); album.artist = StringUtils::Split(record->at(album_strArtists).get_asString(), g_advancedSettings.m_musicItemSeparator); album.genre = StringUtils::Split(record->at(album_strGenres).get_asString(), g_advancedSettings.m_musicItemSeparator); album.iYear = record->at(album_iYear).get_asInt(); @@ -1018,6 +1043,17 @@ CAlbum CMusicDatabase::GetAlbumFromDataset(const dbiplus::sql_record* const reco return album; } +CArtistCredit CMusicDatabase::GetAlbumArtistCreditFromDataset(const dbiplus::sql_record* const record) +{ + CArtistCredit artistCredit; + artistCredit.idArtist = record->at(album_idArtist).get_asInt(); + artistCredit.m_strArtist = record->at(album_strArtist).get_asString(); + artistCredit.m_strMusicBrainzArtistID = record->at(album_strMusicBrainzArtistID).get_asString(); + artistCredit.m_boolFeatured = record->at(album_bFeatured).get_asBool(); + artistCredit.m_strJoinPhrase = record->at(album_strJoinPhrase).get_asString(); + return artistCredit; +} + CArtist CMusicDatabase::GetArtistFromDataset(dbiplus::Dataset* pDS, bool needThumb) { return GetArtistFromDataset(pDS->get_sql_record(), needThumb); @@ -1028,6 +1064,7 @@ CArtist CMusicDatabase::GetArtistFromDataset(const dbiplus::sql_record* const re CArtist artist; artist.idArtist = record->at(artist_idArtist).get_asInt(); artist.strArtist = record->at(artist_strArtist).get_asString(); + artist.strMusicBrainzArtistID = record->at(artist_strMusicBrainzArtistID).get_asString(); artist.genre = StringUtils::Split(record->at(artist_strGenres).get_asString(), g_advancedSettings.m_musicItemSeparator); artist.strBiography = record->at(artist_strBiography).get_asString(); artist.styles = StringUtils::Split(record->at(artist_strStyles).get_asString(), g_advancedSettings.m_musicItemSeparator); @@ -1060,7 +1097,7 @@ bool CMusicDatabase::GetSongByFileName(const CStdString& strFileName, CSong& son { CStdString strFile = URIUtils::GetFileName(strFileName); URIUtils::RemoveExtension(strFile); - return GetSongById(atol(strFile.c_str()), song); + return GetSong(atol(strFile.c_str()), song); } CStdString strPath; @@ -1147,7 +1184,7 @@ int CMusicDatabase::GetSongByArtistAndAlbumAndTitle(const CStdString& strArtist, return -1; } -bool CMusicDatabase::GetSongById(int idSong, CSong& song) +bool CMusicDatabase::GetSong(int idSong, CSong& song) { try { @@ -1186,18 +1223,16 @@ bool CMusicDatabase::SearchArtists(const CStdString& search, CFileItemList &arti if (NULL == m_pDB.get()) return false; if (NULL == m_pDS.get()) return false; - // Exclude "Various Artists" - int idVariousArtist = AddArtist(g_localizeStrings.Get(340)); - + CStdString strVariousArtists = g_localizeStrings.Get(340).c_str(); CStdString strSQL; if (search.GetLength() >= MIN_FULL_SEARCH_LENGTH) strSQL=PrepareSQL("select * from artist " - "where (strArtist like '%s%%' or strArtist like '%% %s%%') and idArtist <> %i " - , search.c_str(), search.c_str(), idVariousArtist ); + "where (strArtist like '%s%%' or strArtist like '%% %s%%') and strArtist <> '%s' " + , search.c_str(), search.c_str(), strVariousArtists.c_str() ); else strSQL=PrepareSQL("select * from artist " - "where strArtist like '%s%%' and idArtist <> %i " - , search.c_str(), idVariousArtist ); + "where strArtist like '%s%%' and strArtist <> '%s' " + , search.c_str(), strVariousArtists.c_str() ); if (!m_pDS->query(strSQL.c_str())) return false; if (m_pDS->num_rows() == 0) @@ -1243,25 +1278,32 @@ bool CMusicDatabase::GetAlbumInfo(int idAlbum, CAlbum &info, VECSONGS* songs, bo if (idAlbum == -1) return false; // not in the database - CStdString strSQL=PrepareSQL("select * from albumview where idAlbum = %ld", idAlbum); + CStdString strSQL=PrepareSQL("SELECT albumview.*, album_artist.idArtist, artist.strArtist, artist.strMusicBrainzArtistID, album_artist.boolFeatured, album_artist.strJoinPhrase FROM albumview JOIN album_artist ON albumview.idAlbum = album_artist.idAlbum JOIN artist ON album_artist.idArtist = artist.idArtist WHERE albumview.idAlbum = %ld", idAlbum); if (scrapedInfo) // require additional information strSQL += " and idAlbumInfo > 0"; if (!m_pDS2->query(strSQL.c_str())) return false; - int iRowsFound = m_pDS2->num_rows(); - if (iRowsFound != 0) + if (m_pDS2->num_rows() == 0) { - info = GetAlbumFromDataset(m_pDS2.get(), true); // true to grab the thumburl rather than the thumb - int idAlbumInfo = m_pDS2->fv(album_idAlbumInfo).get_asInt(); - m_pDS2->close(); // cleanup recordset data - - if (songs) - GetAlbumInfoSongs(idAlbumInfo, *songs); + m_pDS2->close(); + return false; + } - return true; + info = GetAlbumFromDataset(m_pDS2.get()->get_sql_record(), true); // true to grab the thumburl rather than the thumb + int idAlbumInfo = m_pDS2->fv(album_idAlbumInfo).get_asInt(); + while (!m_pDS2->eof()) + { + if (!info.artistCredits.empty() && (m_pDS2->fv(album_idArtist).get_asInt() != info.artistCredits.back().idArtist)) + { + info.artistCredits.push_back(GetAlbumArtistCreditFromDataset(m_pDS2.get()->get_sql_record())); + } + m_pDS2->next(); } - m_pDS2->close(); - return false; + if (songs) + GetAlbumInfoSongs(idAlbumInfo, *songs); + + m_pDS2->close(); // cleanup recordset data + return true; } catch (...) { @@ -1974,8 +2016,7 @@ bool CMusicDatabase::CleanupSongsByIds(const CStdString &strSongIds) CStdString strSongsToDelete = ""; while (!m_pDS->eof()) { // get the full song path - CStdString strFileName; - URIUtils::AddFileToFolder(m_pDS->fv("path.strPath").get_asString(), m_pDS->fv("song.strFileName").get_asString(), strFileName); + CStdString strFileName = URIUtils::AddFileToFolder(m_pDS->fv("path.strPath").get_asString(), m_pDS->fv("song.strFileName").get_asString()); // Special case for streams inside an ogg file. (oggstream) // The last dir in the path is the ogg file that @@ -2158,13 +2199,9 @@ bool CMusicDatabase::CleanupArtists() // (nested queries by Bobbin007) // must be executed AFTER the song, album and their artist link tables are cleaned. // don't delete the "Various Artists" string - CStdString strVariousArtists = g_localizeStrings.Get(340); - int idVariousArtists = AddArtist(strVariousArtists); CStdString strSQL = "delete from artist where idArtist not in (select idArtist from song_artist)"; strSQL += " and idArtist not in (select idArtist from album_artist)"; CStdString strSQL2; - strSQL2.Format(" and idArtist<>%i", idVariousArtists); - strSQL += strSQL2; m_pDS->exec(strSQL.c_str()); m_pDS->exec("delete from artistinfo where idArtist not in (select idArtist from artist)"); m_pDS->exec("delete from album_artist where idArtist not in (select idArtist from artist)"); @@ -2384,7 +2421,7 @@ void CMusicDatabase::DeleteAlbumInfo() bool CMusicDatabase::LookupCDDBInfo(bool bRequery/*=false*/) { #ifdef HAS_DVD_DRIVE - if (!g_guiSettings.GetBool("audiocds.usecddb")) + if (!CSettings::Get().GetBool("audiocds.usecddb")) return false; // check network connectivity @@ -2484,7 +2521,7 @@ bool CMusicDatabase::LookupCDDBInfo(bool bRequery/*=false*/) } // if ( !cddb.queryCDinfo( pCdInfo ) ) else pDialogProgress->Close(); - } // if (pCdInfo->HasCDDBInfo() && g_settings.m_bUseCDDB) + } // Filling the file items with cddb info happens in CMusicInfoTagLoaderCDDA @@ -3056,40 +3093,6 @@ bool CMusicDatabase::GetAlbumFromSong(int idSong, CAlbum &album) return false; } -// This function won't be required if/when the fileitem tag has idSong information -bool CMusicDatabase::GetAlbumFromSong(const CSong &song, CAlbum &album) -{ - try - { - if (NULL == m_pDB.get()) return false; - if (NULL == m_pDS.get()) return false; - - if (song.idSong != -1) return GetAlbumFromSong(song.idSong, album); - - CStdString path, file; - URIUtils::Split(song.strFileName, path, file); - - CStdString strSQL = PrepareSQL("select albumview.* from song join albumview on song.idAlbum = albumview.idAlbum join path on song.idPath = path.idPath where song.strFileName='%s' and path.strPath='%s'", file.c_str(), path.c_str()); - if (!m_pDS->query(strSQL.c_str())) return false; - int iRowsFound = m_pDS->num_rows(); - if (iRowsFound != 1) - { - m_pDS->close(); - return false; - } - - album = GetAlbumFromDataset(m_pDS.get()); - - m_pDS->close(); - return true; - } - catch (...) - { - CLog::Log(LOGERROR, "%s failed", __FUNCTION__); - } - return false; -} - bool CMusicDatabase::GetAlbumsNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre /* = -1 */, int idArtist /* = -1 */, const Filter &filter /* = Filter() */, const SortDescription &sortDescription /* = SortDescription() */, bool countOnly /* = false */) { CMusicDbUrl musicUrl; @@ -3683,7 +3686,7 @@ bool CMusicDatabase::UpdateOldVersion(int version) m_pDS->exec("DROP TABLE thumb"); CMediaSettings::Get().SetMusicNeedsUpdate(27); - g_settings.Save(); + CSettings::Get().Save(); } if (version < 29) @@ -3722,6 +3725,36 @@ bool CMusicDatabase::UpdateOldVersion(int version) m_pDS->exec("DROP INDEX idxSong6 ON song"); m_pDS->exec("CREATE UNIQUE INDEX idxSong6 on song( idPath, strFileName(255) )"); } + + if (version < 34) + { + m_pDS->exec("ALTER TABLE artist ADD strMusicBrainzArtistID text\n"); + m_pDS->exec("ALTER TABLE album ADD strMusicBrainzAlbumID text\n"); + m_pDS->exec("CREATE TABLE song_new ( idSong integer primary key, idAlbum integer, idPath integer, strArtists text, strGenres text, strTitle varchar(512), iTrack integer, iDuration integer, iYear integer, dwFileNameCRC text, strFileName text, strMusicBrainzTrackID text, iTimesPlayed integer, iStartOffset integer, iEndOffset integer, idThumb integer, lastplayed varchar(20) default NULL, rating char default '0', comment text)\n"); + m_pDS->exec("INSERT INTO song_new ( idSong, idAlbum, idPath, strArtists, strTitle, iTrack, iDuration, iYear, dwFileNameCRC, strFileName, strMusicBrainzTrackID, iTimesPlayed, iStartOffset, iEndOffset, idThumb, lastplayed, rating, comment) SELECT idSong, idAlbum, idPath, strArtists, strTitle, iTrack, iDuration, iYear, dwFileNameCRC, strFileName, strMusicBrainzTrackID, iTimesPlayed, iStartOffset, iEndOffset, idThumb, lastplayed, rating, comment FROM song"); + + m_pDS->exec("DROP TABLE song"); + m_pDS->exec("ALTER TABLE song_new RENAME TO song"); + m_pDS->exec("CREATE INDEX idxSong ON song(strTitle)"); + m_pDS->exec("CREATE INDEX idxSong1 ON song(iTimesPlayed)"); + m_pDS->exec("CREATE INDEX idxSong2 ON song(lastplayed)"); + m_pDS->exec("CREATE INDEX idxSong3 ON song(idAlbum)"); + m_pDS->exec("CREATE INDEX idxSong6 ON song(idPath)"); + + m_pDS->exec("UPDATE song SET strMusicBrainzTrackID = NULL"); + m_pDS->exec("CREATE UNIQUE INDEX idxArtist1 ON artist(strMusicBrainzArtistID(36))"); + } + + if (version < 35) + { + m_pDS->exec("CREATE UNIQUE INDEX idxAlbum_2 ON album(strMusicBrainzAlbumID(36))"); + m_pDS->exec("CREATE UNIQUE INDEX idxSong7 ON song( idAlbum, strMusicBrainzTrackID(36) )"); + m_pDS->exec("ALTER TABLE album_artist ADD strJoinPhrase text\n"); + m_pDS->exec("ALTER TABLE song_artist ADD strJoinPhrase text\n"); + CMediaSettings::Get().SetMusicNeedsUpdate(35); + CSettings::Get().Save(); + } + // always recreate the views after any table change CreateViews(); @@ -3730,7 +3763,7 @@ bool CMusicDatabase::UpdateOldVersion(int version) int CMusicDatabase::GetMinVersion() const { - return 33; + return 35; } unsigned int CMusicDatabase::GetSongIDs(const Filter &filter, vector<pair<int,int> > &songIDs) @@ -4223,7 +4256,7 @@ bool CMusicDatabase::RemoveSongsFromPath(const CStdString &path1, MAPSONGS& song return false; } -bool CMusicDatabase::GetPaths(set<CStdString> &paths) +bool CMusicDatabase::GetPaths(set<string> &paths) { try { @@ -4373,7 +4406,7 @@ bool CMusicDatabase::GetScraperForPath(const CStdString& strPath, ADDON::Scraper } if (m_pDS->eof() && params.GetAlbumId() != -1) // check album { - strSQL = PrepareSQL("select * from content where strPath='musicdb://albums/%i/'",params.GetGenreId()); + strSQL = PrepareSQL("select * from content where strPath='musicdb://albums/%i/'",params.GetAlbumId()); m_pDS->query(strSQL.c_str()); } if (m_pDS->eof() && params.GetArtistId() != -1) // check artist @@ -4479,7 +4512,7 @@ bool CMusicDatabase::GetItems(const CStdString &strBaseDir, const CStdString &it else if (itemType.Equals("years")) return GetYearsNav(strBaseDir, items, filter); else if (itemType.Equals("artists")) - return GetArtistsNav(strBaseDir, items, !g_guiSettings.GetBool("musiclibrary.showcompilationartists"), -1, -1, -1, filter, sortDescription); + return GetArtistsNav(strBaseDir, items, !CSettings::Get().GetBool("musiclibrary.showcompilationartists"), -1, -1, -1, filter, sortDescription); else if (itemType.Equals("albums")) return GetAlbumsByWhere(strBaseDir, filter, items, sortDescription); else if (itemType.Equals("songs")) @@ -4562,8 +4595,7 @@ void CMusicDatabase::ExportToXML(const CStdString &xmlFile, bool singleFiles, bo CLog::Log(LOGDEBUG, "%s - Not exporting item %s as it does not exist", __FUNCTION__, strPath.c_str()); else { - CStdString nfoFile; - URIUtils::AddFileToFolder(strPath, "album.nfo", nfoFile); + CStdString nfoFile = URIUtils::AddFileToFolder(strPath, "album.nfo"); if (overwrite || !CFile::Exists(nfoFile)) { if (!xmlDoc.SaveFile(nfoFile)) @@ -4601,7 +4633,8 @@ void CMusicDatabase::ExportToXML(const CStdString &xmlFile, bool singleFiles, bo // find all artists sql = "SELECT artist.idArtist AS idArtist, strArtist, " - " strBorn, strFormed, strGenres," + " strMusicBrainzArtistID, " + " strBorn, strFormed, strGenres, " " strMoods, strStyles, strInstruments, " " strBiography, strDied, strDisbanded, " " strYearsActive, strImage, strFanart " @@ -4646,8 +4679,7 @@ void CMusicDatabase::ExportToXML(const CStdString &xmlFile, bool singleFiles, bo CLog::Log(LOGDEBUG, "%s - Not exporting item %s as it does not exist", __FUNCTION__, strPath.c_str()); else { - CStdString nfoFile; - URIUtils::AddFileToFolder(strPath, "artist.nfo", nfoFile); + CStdString nfoFile = URIUtils::AddFileToFolder(strPath, "artist.nfo"); if (overwrite || !CFile::Exists(nfoFile)) { if (!xmlDoc.SaveFile(nfoFile)) @@ -4788,23 +4820,20 @@ void CMusicDatabase::ImportFromXML(const CStdString &xmlFile) progress->Close(); } -void CMusicDatabase::AddKaraokeData(int idSong, const CSong& song) +void CMusicDatabase::AddKaraokeData(int idSong, int iKaraokeNumber, DWORD crc) { try { CStdString strSQL; // If song.iKaraokeNumber is non-zero, we already have it in the database. Just replace the song ID. - if ( song.iKaraokeNumber > 0 ) + if (iKaraokeNumber > 0) { - CStdString strSQL = PrepareSQL("UPDATE karaokedata SET idSong=%i WHERE iKaraNumber=%i", idSong, song.iKaraokeNumber); + CStdString strSQL = PrepareSQL("UPDATE karaokedata SET idSong=%i WHERE iKaraNumber=%i", idSong, iKaraokeNumber); m_pDS->exec(strSQL.c_str()); return; } - // Add new karaoke data - DWORD crc = ComputeCRC( song.strFileName ); - // Get the maximum number allocated strSQL=PrepareSQL( "SELECT MAX(iKaraNumber) FROM karaokedata" ); if (!m_pDS->query(strSQL.c_str())) return; @@ -4822,7 +4851,7 @@ void CMusicDatabase::AddKaraokeData(int idSong, const CSong& song) } catch (...) { - CLog::Log(LOGERROR, "%s -(%s) failed", __FUNCTION__, song.strFileName.c_str()); + CLog::Log(LOGERROR, "%s -(%i, %i) failed", __FUNCTION__, idSong, iKaraokeNumber); } } @@ -4846,7 +4875,7 @@ bool CMusicDatabase::GetSongByKaraokeNumber(int number, CSong & song) int idSong = m_pDS->fv("karaokedata.idSong").get_asInt(); m_pDS->close(); - return GetSongById( idSong, song ); + return GetSong( idSong, song ); } catch (...) { @@ -5215,22 +5244,6 @@ void CMusicDatabase::SetPropertiesForFileItem(CFileItem& item) } } -void CMusicDatabase::AnnounceRemove(std::string content, int id) -{ - CVariant data; - data["type"] = content; - data["id"] = id; - ANNOUNCEMENT::CAnnouncementManager::Announce(ANNOUNCEMENT::AudioLibrary, "xbmc", "OnRemove", data); -} - -void CMusicDatabase::AnnounceUpdate(std::string content, int id) -{ - CVariant data; - data["type"] = content; - data["id"] = id; - ANNOUNCEMENT::CAnnouncementManager::Announce(ANNOUNCEMENT::AudioLibrary, "xbmc", "OnUpdate", data); -} - void CMusicDatabase::SetArtForItem(int mediaId, const string &mediaType, const map<string, string> &art) { for (map<string, string>::const_iterator i = art.begin(); i != art.end(); ++i) @@ -5405,7 +5418,7 @@ bool CMusicDatabase::GetFilter(CDbUrl &musicUrl, Filter &filter, SortDescription // 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 += " WHERE album_artist.boolFeatured = 0"; // then exclude those that have no extra artists + strSQL += " JOIN album ON album.idAlbum = album_artist.idAlbum WHERE album.bCompilation = 0 "; // then exclude those that have no extra artists strSQL += ")"; } @@ -5416,8 +5429,7 @@ bool CMusicDatabase::GetFilter(CDbUrl &musicUrl, Filter &filter, SortDescription if (!albumArtistsOnly) { CStdString strVariousArtists = g_localizeStrings.Get(340); - int idVariousArtists = AddArtist(strVariousArtists); - strSQL += PrepareSQL(" and artistview.idArtist <> %i", idVariousArtists); + strSQL += PrepareSQL(" and artistview.strArtist <> '%s'", strVariousArtists.c_str()); } filter.AppendWhere(strSQL); @@ -5442,9 +5454,15 @@ bool CMusicDatabase::GetFilter(CDbUrl &musicUrl, Filter &filter, SortDescription option = options.find("artistid"); if (option != options.end()) - filter.AppendWhere(PrepareSQL("albumview.idAlbum IN (SELECT song.idAlbum FROM song JOIN song_artist ON song.idSong = song_artist.idSong WHERE song_artist.idArtist = %i)" // All albums linked to this artist via songs - " OR albumview.idAlbum IN (SELECT album_artist.idAlbum FROM album_artist WHERE album_artist.idArtist = %i)", // All albums where album artists fit + { + filter.AppendJoin("JOIN song ON song.idAlbum = albumview.idAlbum " + "JOIN song_artist ON song.idSong = song_artist.idSong " + "JOIN album_artist ON albumview.idAlbum = album_artist.idAlbum"); + filter.AppendWhere(PrepareSQL(" song_artist.idArtist = %i" // All albums linked to this artist via songs + " OR album_artist.idArtist = %i", // All albums where album artists fit (int)option->second.asInteger(), (int)option->second.asInteger())); + filter.AppendGroup("albumview.idAlbum"); + } else { option = options.find("artist"); @@ -5519,7 +5537,7 @@ bool CMusicDatabase::GetFilter(CDbUrl &musicUrl, Filter &filter, SortDescription if (xsp.GetOrder() != SortByNone) sorting.sortBy = xsp.GetOrder(); sorting.sortOrder = xsp.GetOrderAscending() ? SortOrderAscending : SortOrderDescending; - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) sorting.sortAttributes = SortAttributeIgnoreArticle; } } diff --git a/xbmc/music/MusicDatabase.h b/xbmc/music/MusicDatabase.h index 6c66afa1c2..1819794e53 100644 --- a/xbmc/music/MusicDatabase.h +++ b/xbmc/music/MusicDatabase.h @@ -102,63 +102,186 @@ public: bool LookupCDDBInfo(bool bRequery=false); void DeleteCDDBInfo(); + ///////////////////////////////////////////////// + // Song CRUD + ///////////////////////////////////////////////// + /*! \brief Add a song to the database + \param idAlbum [in] the database ID of the album for the song + \param strTitle [in] the title of the song (required to be non-empty) + \param strMusicBrainzTrackID [in] the MusicBrainz track ID of the song + \param strPathAndFileName [in] the path and filename to the song + \param strComment [in] the ids of the added songs + \param strThumb [in] the ids of the added songs + \param artists [in] a vector of artist names (will only be used for the cache names in the album views) + \param genres [in] a vector of genres to which this song belongs + \param iTrack [in] the track number and disc number of the song + \param iDuration [in] the duration of the song + \param iYear [in] the year of the song + \param iTimesPlayed [in] the number of times the song has been played + \param iStartOffset [in] the start offset of the song (when using a single audio file with a .cue) + \param iEndOffset [in] the end offset of the song (when using a single audio file with .cue) + \param dtLastPlayed [in] the time the song was last played + \param rating [in] a rating for the song + \param iKaraokeNumber [in] the karaoke id of the song + \return the id of the song + */ + int AddSong(const int idAlbum, const CStdString& strTitle, const CStdString& strMusicBrainzTrackID, const CStdString& strPathAndFileName, const CStdString& strComment, const CStdString& strThumb, const std::vector<std::string>& artists, const std::vector<std::string>& genres, int iTrack, int iDuration, int iYear, const int iTimesPlayed, int iStartOffset, int iEndOffset, const CDateTime& dtLastPlayed, char rating, int iKaraokeNumber); + bool GetSong(int idSong, CSong& song); + + /*! \brief Update a song in the database + \param idSong [in] the database ID of the song to update + \param strTitle [in] the title of the song (required to be non-empty) + \param strMusicBrainzTrackID [in] the MusicBrainz track ID of the song + \param strPathAndFileName [in] the path and filename to the song + \param strComment [in] the ids of the added songs + \param strThumb [in] the ids of the added songs + \param artists [in] a vector of artist names (will only be used for the cache names in the album views) + \param genres [in] a vector of genres to which this song belongs + \param iTrack [in] the track number and disc number of the song + \param iDuration [in] the duration of the song + \param iYear [in] the year of the song + \param iTimesPlayed [in] the number of times the song has been played + \param iStartOffset [in] the start offset of the song (when using a single audio file with a .cue) + \param iEndOffset [in] the end offset of the song (when using a single audio file with .cue) + \param dtLastPlayed [in] the time the song was last played + \param rating [in] a rating for the song + \param iKaraokeNumber [in] the karaoke id of the song + \return the id of the song + */ + int UpdateSong(int idSong, const CStdString& strTitle, const CStdString& strMusicBrainzTrackID, const CStdString& strPathAndFileName, const CStdString& strComment, const CStdString& strThumb, const std::vector<std::string>& artists, const std::vector<std::string>& genres, int iTrack, int iDuration, int iYear, int iTimesPlayed, int iStartOffset, int iEndOffset, const CDateTime& dtLastPlayed, char rating, int iKaraokeNumber); + // bool DeleteSong(int idSong); + + //// Misc Song + bool GetSongByFileName(const CStdString& strFileName, CSong& song, int startOffset = 0); + bool GetSongsByPath(const CStdString& strPath, MAPSONGS& songs, bool bAppendToMap = false); + bool Search(const CStdString& search, CFileItemList &items); + bool RemoveSongsFromPath(const CStdString &path, MAPSONGS& songs, bool exact=true); + bool SetSongRating(const CStdString &filePath, char rating); + int GetSongByArtistAndAlbumAndTitle(const CStdString& strArtist, const CStdString& strAlbum, const CStdString& strTitle); + + ///////////////////////////////////////////////// + // Album + ///////////////////////////////////////////////// /*! \brief Add an album and all its songs to the database \param album the album to add \param songIDs [out] the ids of the added songs \return the id of the album */ - int AddAlbum(const CAlbum &album, std::vector<int> &songIDs); + int AddAlbum(const CStdString& strAlbum, const CStdString& strMusicBrainzAlbumID, const CStdString& strArtist, const CStdString& strGenre, int year, bool bCompilation); + bool GetAlbum(int idAlbum, CAlbum& album); + int UpdateAlbum(int idAlbum, const CAlbum &album); + bool DeleteAlbum(int idAlbum); + + //// Misc Album + int GetAlbumIdByPath(const CStdString& path); + bool GetAlbumFromSong(int idSong, CAlbum &album); + int GetAlbumByName(const CStdString& strAlbum, const CStdString& strArtist=""); + int GetAlbumByName(const CStdString& strAlbum, const std::vector<std::string>& artist); + CStdString GetAlbumById(int id); + + ///////////////////////////////////////////////// + // Artist CRUD + ///////////////////////////////////////////////// + int AddArtist(const CStdString& strArtist, const CStdString& strMusicBrainzArtistID); + bool GetArtist(int idArtist, CArtist& artist); + int UpdateArtist(int idArtist, const CArtist& artist); + bool DeleteArtist(int idArtist); + + CStdString GetArtistById(int id); + int GetArtistByName(const CStdString& strArtist); + + ///////////////////////////////////////////////// + // Paths + ///////////////////////////////////////////////// + int AddPath(const CStdString& strPath); + + bool GetPaths(std::set<std::string> &paths); + bool SetPathHash(const CStdString &path, const CStdString &hash); + bool GetPathHash(const CStdString &path, CStdString &hash); + bool GetAlbumPath(int idAlbum, CStdString &path); + bool GetArtistPath(int idArtist, CStdString &path); - int UpdateSong(const CSong& song, int idSong = -1); + ///////////////////////////////////////////////// + // Genres + ///////////////////////////////////////////////// + int AddGenre(const CStdString& strGenre); + CStdString GetGenreById(int id); + int GetGenreByName(const CStdString& strGenre); + + ///////////////////////////////////////////////// + // AlbumInfo + ///////////////////////////////////////////////// + bool HasAlbumInfo(int idAlbum); int SetAlbumInfo(int idAlbum, const CAlbum& album, const VECSONGS& songs, bool bTransaction=true); - bool DeleteAlbumInfo(int idArtist); - int SetArtistInfo(int idArtist, const CArtist& artist); - bool DeleteArtistInfo(int idArtist); bool GetAlbumInfo(int idAlbum, CAlbum &info, VECSONGS* songs, bool scrapedInfo = false); - bool HasAlbumInfo(int idAlbum); - bool GetArtistInfo(int idArtist, CArtist &info, bool needAll=true); + bool DeleteAlbumInfo(int idArtist); + bool SetAlbumInfoSongs(int idAlbumInfo, const VECSONGS& songs); + bool GetAlbumInfoSongs(int idAlbumInfo, VECSONGS& songs); + ///////////////////////////////////////////////// + // ArtistInfo + ///////////////////////////////////////////////// /*! \brief Check if an artist entity has additional metadata (scraped) \param idArtist the id of the Artist to check \return true or false - whether the artist has metadata */ bool HasArtistInfo(int idArtist); - bool GetSongByFileName(const CStdString& strFileName, CSong& song, int startOffset = 0); - int GetAlbumIdByPath(const CStdString& path); - bool GetSongById(int idSong, CSong& song); - bool GetSongByKaraokeNumber( int number, CSong& song ); - bool SetKaraokeSongDelay( int idSong, int delay ); - bool GetSongsByPath(const CStdString& strPath, MAPSONGS& songs, bool bAppendToMap = false); - bool Search(const CStdString& search, CFileItemList &items); + int SetArtistInfo(int idArtist, const CArtist& artist); + bool GetArtistInfo(int idArtist, CArtist &info, bool needAll=true); + bool DeleteArtistInfo(int idArtist); - bool GetAlbumFromSong(int idSong, CAlbum &album); - bool GetAlbumFromSong(const CSong &song, CAlbum &album); - + ///////////////////////////////////////////////// + // Link tables + ///////////////////////////////////////////////// + bool AddAlbumArtist(int idArtist, int idAlbum, std::string joinPhrase, bool featured, int iOrder); bool GetAlbumsByArtist(int idArtist, bool includeFeatured, std::vector<int>& albums); bool GetArtistsByAlbum(int idAlbum, bool includeFeatured, std::vector<int>& artists); + + bool AddSongArtist(int idArtist, int idSong, std::string joinPhrase, bool featured, int iOrder); bool GetSongsByArtist(int idArtist, bool includeFeatured, std::vector<int>& songs); bool GetArtistsBySong(int idSong, bool includeFeatured, std::vector<int>& artists); - bool GetGenresByAlbum(int idAlbum, std::vector<int>& genres); + bool AddSongGenre(int idGenre, int idSong, int iOrder); bool GetGenresBySong(int idSong, std::vector<int>& genres); + bool AddAlbumGenre(int idGenre, int idAlbum, int iOrder); + bool GetGenresByAlbum(int idAlbum, std::vector<int>& genres); + + ///////////////////////////////////////////////// + // Top 100 + ///////////////////////////////////////////////// bool GetTop100(const CStdString& strBaseDir, CFileItemList& items); bool GetTop100Albums(VECALBUMS& albums); bool GetTop100AlbumSongs(const CStdString& strBaseDir, CFileItemList& item); + + ///////////////////////////////////////////////// + // Recently added + ///////////////////////////////////////////////// bool GetRecentlyAddedAlbums(VECALBUMS& albums, unsigned int limit=0); bool GetRecentlyAddedAlbumSongs(const CStdString& strBaseDir, CFileItemList& item, unsigned int limit=0); bool GetRecentlyPlayedAlbums(VECALBUMS& albums); bool GetRecentlyPlayedAlbumSongs(const CStdString& strBaseDir, CFileItemList& item); + + ///////////////////////////////////////////////// + // Compilations + ///////////////////////////////////////////////// + bool GetCompilationAlbums(const CStdString& strBaseDir, CFileItemList& items); + bool GetCompilationSongs(const CStdString& strBaseDir, CFileItemList& items); + int GetCompilationAlbumsCount(); + bool GetVariousArtistsAlbums(const CStdString& strBaseDir, CFileItemList& items); + bool GetVariousArtistsAlbumsSongs(const CStdString& strBaseDir, CFileItemList& items); + int GetVariousArtistsAlbumsCount(); + /*! \brief Increment the playcount of an item Increments the playcount and updates the last played date \param item CFileItem to increment the playcount for */ void IncrementPlayCount(const CFileItem &item); - bool RemoveSongsFromPath(const CStdString &path, MAPSONGS& songs, bool exact=true); bool CleanupOrphanedItems(); - bool GetPaths(std::set<CStdString> &paths); - bool SetPathHash(const CStdString &path, const CStdString &hash); - bool GetPathHash(const CStdString &path, CStdString &hash); + + ///////////////////////////////////////////////// + // VIEWS + ///////////////////////////////////////////////// bool GetGenresNav(const CStdString& strBaseDir, CFileItemList& items, const Filter &filter = Filter(), bool countOnly = false); bool GetYearsNav(const CStdString& strBaseDir, CFileItemList& items, const Filter &filter = Filter()); bool GetArtistsNav(const CStdString& strBaseDir, CFileItemList& items, bool albumArtistsOnly = false, int idGenre = -1, int idAlbum = -1, int idSong = -1, const Filter &filter = Filter(), const SortDescription &sortDescription = SortDescription(), bool countOnly = false); @@ -173,56 +296,56 @@ public: bool GetAlbumsByWhere(const CStdString &baseDir, const Filter &filter, CFileItemList &items, const SortDescription &sortDescription = SortDescription(), bool countOnly = false); bool GetArtistsByWhere(const CStdString& strBaseDir, const Filter &filter, CFileItemList& items, const SortDescription &sortDescription = SortDescription(), bool countOnly = false); bool GetRandomSong(CFileItem* item, int& idSong, const Filter &filter); - int GetKaraokeSongsCount(); int GetSongsCount(const Filter &filter = Filter()); unsigned int GetSongIDs(const Filter &filter, std::vector<std::pair<int,int> > &songIDs); + virtual bool GetFilter(CDbUrl &musicUrl, Filter &filter, SortDescription &sorting); - bool GetAlbumPath(int idAlbum, CStdString &path); - bool SaveAlbumThumb(int idAlbum, const CStdString &thumb); - bool GetArtistPath(int idArtist, CStdString &path); - - CStdString GetGenreById(int id); - CStdString GetArtistById(int id); - CStdString GetAlbumById(int id); - - int GetArtistByName(const CStdString& strArtist); - int GetAlbumByName(const CStdString& strAlbum, const CStdString& strArtist=""); - int GetAlbumByName(const CStdString& strAlbum, const std::vector<std::string>& artist); - int GetGenreByName(const CStdString& strGenre); - int GetSongByArtistAndAlbumAndTitle(const CStdString& strArtist, const CStdString& strAlbum, const CStdString& strTitle); - - bool GetCompilationAlbums(const CStdString& strBaseDir, CFileItemList& items); - bool GetCompilationSongs(const CStdString& strBaseDir, CFileItemList& items); - int GetCompilationAlbumsCount(); - bool GetVariousArtistsAlbums(const CStdString& strBaseDir, CFileItemList& items); - bool GetVariousArtistsAlbumsSongs(const CStdString& strBaseDir, CFileItemList& items); - int GetVariousArtistsAlbumsCount(); - - bool SetSongRating(const CStdString &filePath, char rating); + ///////////////////////////////////////////////// + // Scraper + ///////////////////////////////////////////////// bool SetScraperForPath(const CStdString& strPath, const ADDON::ScraperPtr& info); bool GetScraperForPath(const CStdString& strPath, ADDON::ScraperPtr& info, const ADDON::TYPE &type); - + /*! \brief Check whether a given scraper is in use. \param scraperID the scraper to check for. \return true if the scraper is in use, false otherwise. */ bool ScraperInUse(const CStdString &scraperID) const; - // retrieve a list of items + ///////////////////////////////////////////////// + // Karaoke + ///////////////////////////////////////////////// + void AddKaraokeData(int idSong, int iKaraokeNumber, DWORD crc); + bool GetSongByKaraokeNumber( int number, CSong& song ); + bool SetKaraokeSongDelay( int idSong, int delay ); + int GetKaraokeSongsCount(); + void ExportKaraokeInfo(const CStdString &outFile, bool asHTML ); + void ImportKaraokeInfo(const CStdString &inputFile ); + + ///////////////////////////////////////////////// + // Filters + ///////////////////////////////////////////////// bool GetItems(const CStdString &strBaseDir, CFileItemList &items, const Filter &filter = Filter(), const SortDescription &sortDescription = SortDescription()); bool GetItems(const CStdString &strBaseDir, const CStdString &itemType, CFileItemList &items, const Filter &filter = Filter(), const SortDescription &sortDescription = SortDescription()); CStdString GetItemById(const CStdString &itemType, int id); + ///////////////////////////////////////////////// + // XML + ///////////////////////////////////////////////// void ExportToXML(const CStdString &xmlFile, bool singleFiles = false, bool images=false, bool overwrite=false); void ImportFromXML(const CStdString &xmlFile); - void ExportKaraokeInfo(const CStdString &outFile, bool asHTML ); - void ImportKaraokeInfo(const CStdString &inputFile ); - + ///////////////////////////////////////////////// + // Properties + ///////////////////////////////////////////////// void SetPropertiesForFileItem(CFileItem& item); static void SetPropertiesFromArtist(CFileItem& item, const CArtist& artist); static void SetPropertiesFromAlbum(CFileItem& item, const CAlbum& album); + ///////////////////////////////////////////////// + // Art + ///////////////////////////////////////////////// + bool SaveAlbumThumb(int idAlbum, const CStdString &thumb); /*! \brief Sets art for a database item. Sets a single piece of art for a database item. \param mediaId the id in the media (song/artist/album) table. @@ -282,8 +405,6 @@ public: */ std::string GetArtistArtForItem(int mediaId, const std::string &mediaType, const std::string &artType); - virtual bool GetFilter(CDbUrl &musicUrl, Filter &filter, SortDescription &sorting); - protected: std::map<CStdString, int> m_artistCache; std::map<CStdString, int> m_genreCache; @@ -293,22 +414,10 @@ protected: virtual bool CreateTables(); virtual int GetMinVersion() const; - const char *GetBaseDBName() const { return "MyMusic"; }; - int AddSong(const CSong& song, bool bCheck = true, int idAlbum = -1); - int AddAlbum(const CStdString& strAlbum1, const CStdString &strArtist1, const CStdString& strGenre, int year, bool bCompilation); - int AddGenre(const CStdString& strGenre); - int AddArtist(const CStdString& strArtist); - int AddPath(const CStdString& strPath); + const char *GetBaseDBName() const { return "MyMusic"; }; - bool AddAlbumArtist(int idArtist, int idAlbum, bool featured, int iOrder); - bool AddSongArtist(int idArtist, int idSong, bool featured, int iOrder); - bool AddSongGenre(int idGenre, int idSong, int iOrder); - bool AddAlbumGenre(int idGenre, int idAlbum, int iOrder); - void AddKaraokeData(int idSong, const CSong& song); - bool SetAlbumInfoSongs(int idAlbumInfo, const VECSONGS& songs); - bool GetAlbumInfoSongs(int idAlbumInfo, VECSONGS& songs); private: /*! \brief (Re)Create the generic database views for songs and albums */ @@ -320,6 +429,7 @@ private: CArtist GetArtistFromDataset(const dbiplus::sql_record* const record, bool needThumb = true); CAlbum GetAlbumFromDataset(dbiplus::Dataset* pDS, bool imageURL=false); CAlbum GetAlbumFromDataset(const dbiplus::sql_record* const record, bool imageURL=false); + CArtistCredit GetAlbumArtistCreditFromDataset(const dbiplus::sql_record* const record); void GetFileItemFromDataset(CFileItem* item, const CStdString& strMusicDBbasePath); void GetFileItemFromDataset(const dbiplus::sql_record* const record, CFileItem* item, const CStdString& strMusicDBbasePath); bool CleanupSongs(); @@ -348,10 +458,6 @@ private: song_dwFileNameCRC, song_strFileName, song_strMusicBrainzTrackID, - song_strMusicBrainzArtistID, - song_strMusicBrainzAlbumID, - song_strMusicBrainzAlbumArtistID, - song_strMusicBrainzTRMID, song_iTimesPlayed, song_iStartOffset, song_iEndOffset, @@ -374,6 +480,7 @@ private: { album_idAlbum=0, album_strAlbum, + album_strMusicBrainzAlbumID, album_strArtists, album_strGenres, album_iYear, @@ -387,13 +494,21 @@ private: album_strThumbURL, album_iRating, album_bCompilation, - album_iTimesPlayed + album_iTimesPlayed, + + // used for GetAlbumInfo to get the cascaded artist credits + album_idArtist, + album_strArtist, + album_strMusicBrainzArtistID, + album_bFeatured, + album_strJoinPhrase } AlbumFields; enum _ArtistFields { artist_idArtist=0, artist_strArtist, + artist_strMusicBrainzArtistID, artist_strBorn, artist_strFormed, artist_strGenres, @@ -407,7 +522,4 @@ private: artist_strImage, artist_strFanart } ArtistFields; - - void AnnounceRemove(std::string content, int id); - void AnnounceUpdate(std::string content, int id); }; diff --git a/xbmc/music/MusicInfoLoader.cpp b/xbmc/music/MusicInfoLoader.cpp index 66fb833a92..4cb41c2f6c 100644 --- a/xbmc/music/MusicInfoLoader.cpp +++ b/xbmc/music/MusicInfoLoader.cpp @@ -29,7 +29,7 @@ #include "utils/URIUtils.h" #include "music/tags/MusicInfoTag.h" #include "filesystem/File.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "FileItem.h" #include "utils/log.h" #include "Artist.h" @@ -166,14 +166,14 @@ bool CMusicInfoLoader::LoadItem(CFileItem* pItem) XFILE::MUSICDATABASEDIRECTORY::CQueryParams param; XFILE::MUSICDATABASEDIRECTORY::CDirectoryNode::GetDatabaseInfo(pItem->GetPath(),param); CSong song; - if (m_musicDatabase.GetSongById(param.GetSongId(), song)) + if (m_musicDatabase.GetSong(param.GetSongId(), song)) { pItem->GetMusicInfoTag()->SetSong(song); if (!song.strThumb.empty()) pItem->SetArt("thumb", song.strThumb); } } - else if (g_guiSettings.GetBool("musicfiles.usetags") || pItem->IsCDDA()) + else if (CSettings::Get().GetBool("musicfiles.usetags") || pItem->IsCDDA()) { // Nothing found, load tag from file, // always try to load cddb info // get correct tag parser diff --git a/xbmc/music/Song.cpp b/xbmc/music/Song.cpp index 3c96f67528..52553e89cf 100644 --- a/xbmc/music/Song.cpp +++ b/xbmc/music/Song.cpp @@ -21,25 +21,24 @@ #include "Song.h" #include "music/tags/MusicInfoTag.h" #include "utils/Variant.h" +#include "FileItem.h" +#include "settings/AdvancedSettings.h" +#include "utils/StringUtils.h" using namespace std; using namespace MUSIC_INFO; -CSong::CSong(CMusicInfoTag& tag) +CSong::CSong(CFileItem& item) { + CMusicInfoTag& tag = *item.GetMusicInfoTag(); SYSTEMTIME stTime; tag.GetReleaseDate(stTime); strTitle = tag.GetTitle(); genre = tag.GetGenre(); - strFileName = tag.GetURL(); artist = tag.GetArtist(); strAlbum = tag.GetAlbum(); albumArtist = tag.GetAlbumArtist(); strMusicBrainzTrackID = tag.GetMusicBrainzTrackID(); - strMusicBrainzArtistID = tag.GetMusicBrainzArtistID(); - strMusicBrainzAlbumID = tag.GetMusicBrainzAlbumID(); - strMusicBrainzAlbumArtistID = tag.GetMusicBrainzAlbumArtistID(); - strMusicBrainzTRMID = tag.GetMusicBrainzTRMID(); strComment = tag.GetComment(); rating = tag.GetRating(); iYear = stTime.wYear; @@ -47,14 +46,15 @@ CSong::CSong(CMusicInfoTag& tag) iDuration = tag.GetDuration(); bCompilation = tag.GetCompilation(); embeddedArt = tag.GetCoverArtInfo(); - strThumb = ""; - iStartOffset = 0; - iEndOffset = 0; + strFileName = tag.GetURL().IsEmpty() ? item.GetPath() : tag.GetURL(); + strThumb = item.GetUserMusicThumb(true); + iStartOffset = item.m_lStartOffset; + iEndOffset = item.m_lEndOffset; idSong = -1; iTimesPlayed = 0; iKaraokeNumber = 0; iKaraokeDelay = 0; //! Karaoke song lyrics-music delay in 1/10 seconds. - iAlbumId = -1; + idAlbum = -1; } CSong::CSong() @@ -74,16 +74,12 @@ void CSong::Serialize(CVariant& value) const value["track"] = iTrack; value["year"] = iYear; value["musicbrainztrackid"] = strMusicBrainzTrackID; - value["musicbrainzartistid"] = strMusicBrainzArtistID; - value["musicbrainzalbumid"] = strMusicBrainzAlbumID; - value["musicbrainzalbumartistid"] = strMusicBrainzAlbumArtistID; - value["musicbrainztrmid"] = strMusicBrainzTRMID; value["comment"] = strComment; value["rating"] = rating; value["timesplayed"] = iTimesPlayed; value["lastplayed"] = lastPlayed.IsValid() ? lastPlayed.GetAsDBDateTime() : ""; value["karaokenumber"] = (int64_t) iKaraokeNumber; - value["albumid"] = iAlbumId; + value["albumid"] = idAlbum; } void CSong::Clear() @@ -96,10 +92,6 @@ void CSong::Clear() genre.clear(); strThumb.Empty(); strMusicBrainzTrackID.Empty(); - strMusicBrainzArtistID.Empty(); - strMusicBrainzAlbumID.Empty(); - strMusicBrainzAlbumArtistID.Empty(); - strMusicBrainzTRMID.Empty(); strComment.Empty(); rating = '0'; iTrack = 0; @@ -113,7 +105,7 @@ void CSong::Clear() iKaraokeNumber = 0; strKaraokeLyrEncoding.Empty(); iKaraokeDelay = 0; - iAlbumId = -1; + idAlbum = -1; bCompilation = false; embeddedArt.clear(); } diff --git a/xbmc/music/Song.h b/xbmc/music/Song.h index e346212808..13d74bfdcb 100644 --- a/xbmc/music/Song.h +++ b/xbmc/music/Song.h @@ -27,7 +27,7 @@ #include "utils/ISerializable.h" #include "XBDateTime.h" #include "music/tags/MusicInfoTag.h" // for EmbeddedArt - +#include "Artist.h" #include <map> #include <vector> @@ -44,6 +44,7 @@ public: CStdString strGenre; }; +class CFileItem; /*! \ingroup music @@ -54,7 +55,7 @@ class CSong: public ISerializable { public: CSong() ; - CSong(MUSIC_INFO::CMusicInfoTag& tag); + CSong(CFileItem& item); virtual ~CSong(){}; void Clear() ; virtual void Serialize(CVariant& value) const; @@ -78,19 +79,17 @@ public: bool ArtMatches(const CSong &right) const; long idSong; + int idAlbum; CStdString strFileName; CStdString strTitle; std::vector<std::string> artist; + VECARTISTCREDITS artistCredits; CStdString strAlbum; std::vector<std::string> albumArtist; std::vector<std::string> genre; CStdString strThumb; MUSIC_INFO::EmbeddedArtInfo embeddedArt; CStdString strMusicBrainzTrackID; - CStdString strMusicBrainzArtistID; - CStdString strMusicBrainzAlbumID; - CStdString strMusicBrainzAlbumArtistID; - CStdString strMusicBrainzTRMID; CStdString strComment; char rating; int iTrack; @@ -100,7 +99,6 @@ public: CDateTime lastPlayed; int iStartOffset; int iEndOffset; - int iAlbumId; bool bCompilation; // Karaoke-specific information diff --git a/xbmc/music/dialogs/GUIDialogMusicInfo.cpp b/xbmc/music/dialogs/GUIDialogMusicInfo.cpp index e4a6717e7b..8668db7057 100644 --- a/xbmc/music/dialogs/GUIDialogMusicInfo.cpp +++ b/xbmc/music/dialogs/GUIDialogMusicInfo.cpp @@ -32,8 +32,8 @@ #include "storage/MediaManager.h" #include "utils/AsyncFileCopy.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" #include "settings/MediaSourceSettings.h" +#include "settings/Settings.h" #include "guilib/Key.h" #include "guilib/LocalizeStrings.h" #include "utils/log.h" @@ -373,7 +373,7 @@ void CGUIDialogMusicInfo::OnGetThumb() database.Open(); CStdString strArtistPath; if (database.GetArtistPath(m_artist.idArtist,strArtistPath)) - URIUtils::AddFileToFolder(strArtistPath,"folder.jpg",localThumb); + localThumb = URIUtils::AddFileToFolder(strArtistPath, "folder.jpg"); } else localThumb = m_albumItem->GetUserMusicThumb(); @@ -494,7 +494,7 @@ void CGUIDialogMusicInfo::OnGetFanart() } CStdString result; - VECSOURCES sources(*CMediaSourceSettings::Get().GetSources("music")); + VECSOURCES sources = *CMediaSourceSettings::Get().GetSources("music"); g_mediaManager.GetLocalDrives(sources); bool flip=false; if (!CGUIDialogFileBrowser::ShowAndGetImage(items, sources, g_localizeStrings.Get(20437), result, &flip, 20445)) diff --git a/xbmc/music/dialogs/GUIDialogMusicOSD.cpp b/xbmc/music/dialogs/GUIDialogMusicOSD.cpp index e3ae7ad01d..a517a57588 100644 --- a/xbmc/music/dialogs/GUIDialogMusicOSD.cpp +++ b/xbmc/music/dialogs/GUIDialogMusicOSD.cpp @@ -24,7 +24,6 @@ #include "input/MouseStat.h" #include "GUIUserMessages.h" #include "settings/Settings.h" -#include "settings/GUISettings.h" #include "addons/GUIWindowAddonBrowser.h" #define CONTROL_VIS_BUTTON 500 @@ -52,8 +51,8 @@ bool CGUIDialogMusicOSD::OnMessage(CGUIMessage &message) CStdString addonID; if (CGUIWindowAddonBrowser::SelectAddonID(ADDON::ADDON_VIZ, addonID, true) == 1) { - g_guiSettings.SetString("musicplayer.visualisation", addonID); - g_settings.Save(); + CSettings::Get().SetString("musicplayer.visualisation", addonID); + CSettings::Get().Save(); g_windowManager.SendMessage(GUI_MSG_VISUALISATION_RELOAD, 0, 0); } } diff --git a/xbmc/music/dialogs/GUIDialogSongInfo.cpp b/xbmc/music/dialogs/GUIDialogSongInfo.cpp index f36b1e0546..c33b3cda2b 100644 --- a/xbmc/music/dialogs/GUIDialogSongInfo.cpp +++ b/xbmc/music/dialogs/GUIDialogSongInfo.cpp @@ -33,8 +33,8 @@ #include "filesystem/CurlFile.h" #include "FileItem.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" #include "settings/MediaSourceSettings.h" +#include "settings/Settings.h" #include "guilib/LocalizeStrings.h" #include "TextureCache.h" #include "music/Album.h" @@ -201,11 +201,28 @@ void CGUIDialogSongInfo::SetSong(CFileItem *item) m_song->LoadMusicTag(); m_startRating = m_song->GetMusicInfoTag()->GetRating(); MUSIC_INFO::CMusicInfoLoader::LoadAdditionalTagInfo(m_song.get()); - // set artist thumb as well - if (m_song->HasMusicInfoTag() && !m_song->GetMusicInfoTag()->GetArtist().empty()) + // set artist thumb as well + CMusicDatabase db; + db.Open(); + if (item->IsMusicDb()) + { + std::vector<int> artists; + CVariant artistthumbs; + db.GetArtistsBySong(item->GetMusicInfoTag()->GetDatabaseId(), true, artists); + for (std::vector<int>::const_iterator artistId = artists.begin(); artistId != artists.end(); ++artistId) + { + std::string thumb = db.GetArtForItem(*artistId, "artist", "thumb"); + if (!thumb.empty()) + artistthumbs.push_back(thumb); + } + if (artistthumbs.size()) + { + m_song->SetProperty("artistthumbs", artistthumbs); + m_song->SetProperty("artistthumb", artistthumbs[0]); + } + } + else if (m_song->HasMusicInfoTag() && !m_song->GetMusicInfoTag()->GetArtist().empty()) { - CMusicDatabase db; - db.Open(); int idArtist = db.GetArtistByName(m_song->GetMusicInfoTag()->GetArtist()[0]); std::string thumb = db.GetArtForItem(idArtist, "artist", "thumb"); if (!thumb.empty()) @@ -243,9 +260,9 @@ void CGUIDialogSongInfo::OnGetThumb() // Grab the thumbnail from the web - CStdString thumbFromWeb; /* - URIUtils::AddFileToFolder(g_advancedSettings.m_cachePath, "allmusicThumb.jpg", thumbFromWeb); + CStdString thumbFromWeb; + thumbFromWeb = URIUtils::AddFileToFolder(g_advancedSettings.m_cachePath, "allmusicThumb.jpg"); if (DownloadThumbnail(thumbFromWeb)) { CFileItemPtr item(new CFileItem("thumb://allmusic.com", false)); @@ -305,7 +322,7 @@ void CGUIDialogSongInfo::OnGetThumb() if (result == "thumb://None") newThumb = "-"; else if (result == "thumb://allmusic.com") - newThumb = thumbFromWeb; + newThumb.clear(); else if (result == "thumb://Local") newThumb = localThumb; else diff --git a/xbmc/music/infoscanner/MusicInfoScanner.cpp b/xbmc/music/infoscanner/MusicInfoScanner.cpp index c088d64616..382354477a 100644 --- a/xbmc/music/infoscanner/MusicInfoScanner.cpp +++ b/xbmc/music/infoscanner/MusicInfoScanner.cpp @@ -39,7 +39,7 @@ #include "filesystem/File.h" #include "filesystem/Directory.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "FileItem.h" #include "guilib/LocalizeStrings.h" #include "utils/StringUtils.h" @@ -50,15 +50,19 @@ #include "music/MusicThumbLoader.h" #include "interfaces/AnnouncementManager.h" #include "GUIUserMessages.h" +#include "addons/AddonManager.h" +#include "addons/Scraper.h" #include <algorithm> using namespace std; using namespace MUSIC_INFO; using namespace XFILE; +using namespace MUSICDATABASEDIRECTORY; using namespace MUSIC_GRABBER; +using namespace ADDON; -CMusicInfoScanner::CMusicInfoScanner() : CThread("MusicInfoScanner") +CMusicInfoScanner::CMusicInfoScanner() : CThread("MusicInfoScanner"), m_fileCountReader(this, "MusicFileCounter") { m_bRunning = false; m_showDialog = false; @@ -82,7 +86,7 @@ void CMusicInfoScanner::Process() m_musicDatabase.Open(); - if (m_showDialog && !g_guiSettings.GetBool("musiclibrary.backgroundupdate")) + if (m_showDialog && !CSettings::Get().GetBool("musiclibrary.backgroundupdate")) { CGUIDialogExtendedProgressBar* dialog = (CGUIDialogExtendedProgressBar*)g_windowManager.GetWindow(WINDOW_DIALOG_EXT_PROGRESS); @@ -104,9 +108,8 @@ void CMusicInfoScanner::Process() // Create the thread to count all files to be scanned SetPriority( GetMinPriority() ); - CThread fileCountReader(this, "MusicFileCounter"); if (m_handle) - fileCountReader.Create(); + m_fileCountReader.Create(); // Database operations should not be canceled // using Interupt() while scanning as it could @@ -116,7 +119,7 @@ void CMusicInfoScanner::Process() bool commit = false; bool cancelled = false; - while (!cancelled && m_pathsToScan.size()) + for (std::set<std::string>::const_iterator it = m_pathsToScan.begin(); it != m_pathsToScan.end(); it++) { /* * A copy of the directory path is used because the path supplied is @@ -124,8 +127,7 @@ void CMusicInfoScanner::Process() * reference points to the entry in the set a null reference error * occurs. */ - CStdString directory = *m_pathsToScan.begin(); - if (!DoScan(directory)) + if (!DoScan(*it)) cancelled = true; commit = !cancelled; } @@ -151,49 +153,62 @@ void CMusicInfoScanner::Process() } } - fileCountReader.StopThread(); + m_fileCountReader.StopThread(); m_musicDatabase.EmptyCache(); - - m_musicDatabase.Close(); - CLog::Log(LOGDEBUG, "%s - Finished scan", __FUNCTION__); - + tick = XbmcThreads::SystemClockMillis() - tick; CLog::Log(LOGNOTICE, "My Music: Scanning for music info using worker thread, operation took %s", StringUtils::SecondsToTimeString(tick / 1000).c_str()); } - bool bCanceled; if (m_scanType == 1) // load album info { - int iCurrentItem = 1; - for (set<CAlbum>::iterator it=m_albumsToScan.begin();it != m_albumsToScan.end();++it) + for (std::set<std::string>::const_iterator it = m_pathsToScan.begin(); it != m_pathsToScan.end(); ++it) { + CQueryParams params; + CDirectoryNode::GetDatabaseInfo(*it, params); + if (m_musicDatabase.HasAlbumInfo(params.GetArtistId())) // should this be here? + continue; + + CAlbum album; + m_musicDatabase.GetAlbumInfo(params.GetAlbumId(), album, &album.songs); if (m_handle) { - m_handle->SetText(StringUtils::Join(it->artist, g_advancedSettings.m_musicItemSeparator)+" - "+it->strAlbum); - m_handle->SetPercentage(iCurrentItem++/(float)m_albumsToScan.size()); + float percentage = (float) std::distance(it, m_pathsToScan.end()) / m_pathsToScan.size(); + m_handle->SetText(StringUtils::Join(album.artist, g_advancedSettings.m_musicItemSeparator) + " - " + album.strAlbum); + m_handle->SetPercentage(percentage); } CMusicAlbumInfo albumInfo; - DownloadAlbumInfo(it->genre[0],StringUtils::Join(it->artist, g_advancedSettings.m_musicItemSeparator),it->strAlbum, bCanceled, albumInfo); // genre field holds path - see fetchalbuminfo() + UpdateDatabaseAlbumInfo(*it, albumInfo, false); - if (m_bStop || bCanceled) + if (m_bStop) break; } } if (m_scanType == 2) // load artist info { - int iCurrentItem=1; - for (set<CArtist>::iterator it=m_artistsToScan.begin();it != m_artistsToScan.end();++it) + for (std::set<std::string>::const_iterator it = m_pathsToScan.begin(); it != m_pathsToScan.end(); ++it) { + CQueryParams params; + CDirectoryNode::GetDatabaseInfo(*it, params); + if (m_musicDatabase.HasArtistInfo(params.GetArtistId())) // should this be here? + continue; + + CArtist artist; + m_musicDatabase.GetArtistInfo(params.GetArtistId(), artist); + m_musicDatabase.GetArtistPath(params.GetArtistId(), artist.strPath); + if (m_handle) { - m_handle->SetText(it->strArtist); - m_handle->SetPercentage(iCurrentItem++/(float)m_artistsToScan.size()*100); + float percentage = (float) (std::distance(m_pathsToScan.begin(), it) / m_pathsToScan.size()) * 100; + m_handle->SetText(artist.strArtist); + m_handle->SetPercentage(percentage); } + + CMusicArtistInfo artistInfo; + UpdateDatabaseArtistInfo(*it, artistInfo, false); - DownloadArtistInfo(it->genre[0],it->strArtist,bCanceled); // genre field holds path - see fetchartistinfo() - - if (m_bStop || bCanceled) + if (m_bStop) break; } } @@ -203,7 +218,9 @@ void CMusicInfoScanner::Process() { CLog::Log(LOGERROR, "MusicInfoScanner: Exception while scanning."); } - + m_musicDatabase.Close(); + CLog::Log(LOGDEBUG, "%s - Finished scan", __FUNCTION__); + m_bRunning = false; ANNOUNCEMENT::CAnnouncementManager::Announce(ANNOUNCEMENT::AudioLibrary, "xbmc", "OnScanFinished"); @@ -219,9 +236,9 @@ void CMusicInfoScanner::Process() void CMusicInfoScanner::Start(const CStdString& strDirectory, int flags) { + m_fileCountReader.StopThread(); + StopThread(); m_pathsToScan.clear(); - m_albumsScanned.clear(); - m_artistsScanned.clear(); m_flags = flags; if (strDirectory.IsEmpty()) @@ -233,9 +250,8 @@ void CMusicInfoScanner::Start(const CStdString& strDirectory, int flags) } else m_pathsToScan.insert(strDirectory); - m_pathsToCount = m_pathsToScan; + m_scanType = 0; - StopThread(); Create(); m_bRunning = true; } @@ -243,8 +259,9 @@ void CMusicInfoScanner::Start(const CStdString& strDirectory, int flags) void CMusicInfoScanner::FetchAlbumInfo(const CStdString& strDirectory, bool refresh) { - m_albumsToScan.clear(); - m_albumsScanned.clear(); + m_fileCountReader.StopThread(); + StopThread(); + m_pathsToScan.clear(); CFileItemList items; if (strDirectory.IsEmpty()) @@ -270,22 +287,15 @@ void CMusicInfoScanner::FetchAlbumInfo(const CStdString& strDirectory, if (CMusicDatabaseDirectory::IsAllItem(items[i]->GetPath()) || items[i]->IsParentFolder()) continue; - CAlbum album; - album.strAlbum = items[i]->GetMusicInfoTag()->GetAlbum(); - album.artist = items[i]->GetMusicInfoTag()->GetArtist(); - album.genre.push_back(items[i]->GetPath()); // a bit hacky use of field - m_albumsToScan.insert(album); + m_pathsToScan.insert(items[i]->GetPath()); if (refresh) { - int id = m_musicDatabase.GetAlbumByName(album.strAlbum, album.artist); - if (id > -1) - m_musicDatabase.DeleteAlbumInfo(id); + m_musicDatabase.DeleteAlbumInfo(items[i]->GetMusicInfoTag()->GetDatabaseId()); } } m_musicDatabase.Close(); m_scanType = 1; - StopThread(); Create(); m_bRunning = true; } @@ -293,8 +303,9 @@ void CMusicInfoScanner::FetchAlbumInfo(const CStdString& strDirectory, void CMusicInfoScanner::FetchArtistInfo(const CStdString& strDirectory, bool refresh) { - m_artistsToScan.clear(); - m_artistsScanned.clear(); + m_fileCountReader.StopThread(); + StopThread(); + m_pathsToScan.clear(); CFileItemList items; if (strDirectory.IsEmpty()) @@ -320,21 +331,15 @@ void CMusicInfoScanner::FetchArtistInfo(const CStdString& strDirectory, if (CMusicDatabaseDirectory::IsAllItem(items[i]->GetPath()) || items[i]->IsParentFolder()) continue; - CArtist artist; - artist.strArtist = StringUtils::Join(items[i]->GetMusicInfoTag()->GetArtist(), g_advancedSettings.m_musicItemSeparator); - artist.genre.push_back(items[i]->GetPath()); // a bit hacky use of field - m_artistsToScan.insert(artist); + m_pathsToScan.insert(items[i]->GetPath()); if (refresh) { - int id = m_musicDatabase.GetArtistByName(artist.strArtist); - if (id > -1) - m_musicDatabase.DeleteArtistInfo(id); + m_musicDatabase.DeleteArtistInfo(items[i]->GetMusicInfoTag()->GetDatabaseId()); } } m_musicDatabase.Close(); m_scanType = 2; - StopThread(); Create(); m_bRunning = true; } @@ -373,19 +378,8 @@ bool CMusicInfoScanner::DoScan(const CStdString& strDirectory) if (m_handle) m_handle->SetText(Prettify(strDirectory)); - /* - * remove this path from the list we're processing. This must be done prior to - * the check for file or folder exclusion to prevent an infinite while loop - * in Process(). - */ - set<CStdString>::iterator it = m_pathsToScan.find(strDirectory); - if (it != m_pathsToScan.end()) - m_pathsToScan.erase(it); - // Discard all excluded files defined by m_musicExcludeRegExps - CStdStringArray regexps = g_advancedSettings.m_audioExcludeFromScanRegExps; - if (CUtil::ExcludeFileOrFolder(strDirectory, regexps)) return true; @@ -414,7 +408,7 @@ bool CMusicInfoScanner::DoScan(const CStdString& strDirectory) items.Sort(SORT_METHOD_LABEL, SortOrderAscending); // and then scan in the new information - if (RetrieveMusicInfo(items, strDirectory) > 0) + if (RetrieveMusicInfo(strDirectory, items) > 0) { if (m_handle) OnDirectoryScanned(strDirectory); @@ -462,209 +456,374 @@ INFO_RET CMusicInfoScanner::ScanTags(const CFileItemList& items, CFileItemList& { CStdStringArray regexps = g_advancedSettings.m_audioExcludeFromScanRegExps; - // for every file found, but skip folder for (int i = 0; i < items.Size(); ++i) { - CFileItemPtr pItem = items[i]; - if (m_bStop) return INFO_CANCELLED; - // Discard all excluded files defined by m_musicExcludeRegExps + CFileItemPtr pItem = items[i]; + if (CUtil::ExcludeFileOrFolder(pItem->GetPath(), regexps)) continue; - // dont try reading id3tags for folders, playlists or shoutcast streams - if (!pItem->m_bIsFolder && !pItem->IsPlayList() && !pItem->IsPicture() && !pItem->IsLyrics() ) - { - m_currentItem++; + if (pItem->m_bIsFolder || pItem->IsPlayList() || pItem->IsPicture() || pItem->IsLyrics()) + continue; - CMusicInfoTag& tag = *pItem->GetMusicInfoTag(); - if (!tag.Loaded()) - { - // read the tag from a file - auto_ptr<IMusicInfoTagLoader> pLoader (CMusicInfoTagLoaderFactory::CreateLoader(pItem->GetPath())); - if (NULL != pLoader.get()) - pLoader->Load(pItem->GetPath(), tag); - } + m_currentItem++; - // if we have the itemcount, update our - // dialog with the progress we made - if (m_handle && m_itemCount>0) - m_handle->SetPercentage(m_currentItem/(float)m_itemCount*100); + CMusicInfoTag& tag = *pItem->GetMusicInfoTag(); + if (!tag.Loaded()) + { + auto_ptr<IMusicInfoTagLoader> pLoader (CMusicInfoTagLoaderFactory::CreateLoader(pItem->GetPath())); + if (NULL != pLoader.get()) + pLoader->Load(pItem->GetPath(), tag); + } - if (tag.Loaded()) - scannedItems.Add(pItem); - else - CLog::Log(LOGDEBUG, "%s - No tag found for: %s", __FUNCTION__, pItem->GetPath().c_str()); + if (m_handle && m_itemCount>0) + m_handle->SetPercentage(m_currentItem/(float)m_itemCount*100); + + if (!tag.Loaded()) + { + CLog::Log(LOGDEBUG, "%s - No tag found for: %s", __FUNCTION__, pItem->GetPath().c_str()); + continue; } + scannedItems.Add(pItem); } return INFO_ADDED; } -int CMusicInfoScanner::RetrieveMusicInfo(CFileItemList& items, const CStdString& strDirectory) +void CMusicInfoScanner::FileItemsToAlbums(CFileItemList& items, VECALBUMS& albums, MAPSONGS* songsMap /* = NULL */) { - MAPSONGS songsMap; - - // get all information for all files in current directory from database, and remove them - if (m_musicDatabase.RemoveSongsFromPath(strDirectory, songsMap)) - m_needsCleanup = true; - - CFileItemList scannedItems; - if (ScanTags(items, scannedItems) == INFO_CANCELLED) - return 0; - - VECSONGS songsToAdd; - for (int i = 0; i < scannedItems.Size(); ++i) + for (int i = 0; i < items.Size(); ++i) { - CFileItemPtr pItem = scannedItems[i]; + CFileItemPtr pItem = items[i]; CMusicInfoTag& tag = *pItem->GetMusicInfoTag(); - CSong song(tag); + CSong song(*pItem); - // ensure our song has a valid filename or else it will assert in AddSong() - if (song.strFileName.IsEmpty()) + // keep the db-only fields intact on rescan... + if (songsMap != NULL) { - // copy filename from path in case UPnP or other tag loaders didn't specify one (FIXME?) - song.strFileName = pItem->GetPath(); - - // if we still don't have a valid filename, skip the song - if (song.strFileName.IsEmpty()) + MAPSONGS::iterator it = songsMap->find(pItem->GetPath()); + if (it != songsMap->end()) { - // this shouldn't ideally happen! - CLog::Log(LOGERROR, "Skipping song since it doesn't seem to have a filename"); - continue; + song.iTimesPlayed = it->second.iTimesPlayed; + song.lastPlayed = it->second.lastPlayed; + song.iKaraokeNumber = it->second.iKaraokeNumber; + if (song.rating == '0') song.rating = it->second.rating; + if (song.strThumb.empty()) song.strThumb = it->second.strThumb; } } - song.iStartOffset = pItem->m_lStartOffset; - song.iEndOffset = pItem->m_lEndOffset; - song.strThumb = pItem->GetUserMusicThumb(true); + if (!tag.GetMusicBrainzArtistID().empty()) + { + for (vector<string>::const_iterator it = tag.GetMusicBrainzArtistID().begin(); it != tag.GetMusicBrainzArtistID().end(); ++it) + { + CStdString strJoinPhrase = (it == --tag.GetMusicBrainzArtistID().end() ? "" : g_advancedSettings.m_musicItemSeparator); + CArtistCredit mbartist(tag.GetArtist().empty() ? "" : tag.GetArtist()[0], *it, strJoinPhrase); + song.artistCredits.push_back(mbartist); + } + song.artist = tag.GetArtist(); + } + else + { + for (vector<string>::const_iterator it = tag.GetArtist().begin(); it != tag.GetArtist().end(); ++it) + { + CStdString strJoinPhrase = (it == --tag.GetArtist().end() ? "" : g_advancedSettings.m_musicItemSeparator); + CArtistCredit nonmbartist(*it, strJoinPhrase); + song.artistCredits.push_back(nonmbartist); + } + song.artist = tag.GetArtist(); + } - // grab info from the song - MAPSONGS::iterator it = songsMap.find(pItem->GetPath()); - if (it != songsMap.end()) + bool found = false; + for (VECALBUMS::iterator it = albums.begin(); it != albums.end(); ++it) { - // keep the db-only fields intact on rescan... - song.iTimesPlayed = it->second.iTimesPlayed; - song.lastPlayed = it->second.lastPlayed; - song.iKaraokeNumber = it->second.iKaraokeNumber; - - if (song.rating == '0') - song.rating = it->second.rating; - if (song.strThumb.empty()) - song.strThumb = it->second.strThumb; + if (it->strAlbum == tag.GetAlbum() && it->strMusicBrainzAlbumID == tag.GetMusicBrainzAlbumID()) + { + it->songs.push_back(song); + found = true; + } + } + if (!found) + { + CAlbum album(*pItem.get()); + if (!tag.GetMusicBrainzAlbumArtistID().empty()) + { + for (vector<string>::const_iterator it = tag.GetMusicBrainzAlbumArtistID().begin(); it != tag.GetMusicBrainzAlbumArtistID().end(); ++it) + { + // Picard always stored the display artist string in the first artist slot, no need to split it + CStdString strJoinPhrase = (it == --tag.GetMusicBrainzAlbumArtistID().end() ? "" : g_advancedSettings.m_musicItemSeparator); + CArtistCredit mbartist(tag.GetAlbumArtist().empty() ? "" : tag.GetAlbumArtist()[0], *it, strJoinPhrase); + album.artistCredits.push_back(mbartist); + } + album.artist = tag.GetAlbumArtist(); + } + else + { + for (vector<string>::const_iterator it = tag.GetAlbumArtist().begin(); it != tag.GetAlbumArtist().end(); ++it) + { + CStdString strJoinPhrase = (it == --tag.GetAlbumArtist().end() ? "" : g_advancedSettings.m_musicItemSeparator); + CArtistCredit nonmbartist(*it, strJoinPhrase); + album.artistCredits.push_back(nonmbartist); + } + album.artist = tag.GetAlbumArtist(); + } + album.songs.push_back(song); + albums.push_back(album); } - songsToAdd.push_back(song); } +} + +int CMusicInfoScanner::RetrieveMusicInfo(const CStdString& strDirectory, CFileItemList& items) +{ + MAPSONGS songsMap; + + // get all information for all files in current directory from database, and remove them + if (m_musicDatabase.RemoveSongsFromPath(strDirectory, songsMap)) + m_needsCleanup = true; + + CFileItemList scannedItems; + if (ScanTags(items, scannedItems) == INFO_CANCELLED) + return 0; VECALBUMS albums; - CategoriseAlbums(songsToAdd, albums); + FileItemsToAlbums(scannedItems, albums, &songsMap); + if (!(m_flags & SCAN_ONLINE)) + FixupAlbums(albums); FindArtForAlbums(albums, items.GetPath()); - // finally, add these to the database - m_musicDatabase.BeginTransaction(); int numAdded = 0; - set<int> albumsToScan; - set<int> artistsToScan; - for (VECALBUMS::iterator i = albums.begin(); i != albums.end(); ++i) + ADDON::AddonPtr addon; + ADDON::ScraperPtr albumScraper; + ADDON::ScraperPtr artistScraper; + if(ADDON::CAddonMgr::Get().GetDefault(ADDON::ADDON_SCRAPER_ALBUMS, addon)) + albumScraper = boost::dynamic_pointer_cast<ADDON::CScraper>(addon); + + if(ADDON::CAddonMgr::Get().GetDefault(ADDON::ADDON_SCRAPER_ARTISTS, addon)) + artistScraper = boost::dynamic_pointer_cast<ADDON::CScraper>(addon); + + // Add each album + for (VECALBUMS::iterator album = albums.begin(); album != albums.end(); ++album) { - vector<int> songIDs; - int idAlbum = m_musicDatabase.AddAlbum(*i, songIDs); - numAdded += i->songs.size(); if (m_bStop) - { - m_musicDatabase.RollbackTransaction(); - return numAdded; - } + break; - // Build the artist & album sets - albumsToScan.insert(idAlbum); - for (vector<int>::iterator j = songIDs.begin(); j != songIDs.end(); ++j) - { - vector<int> songArtists; - m_musicDatabase.GetArtistsBySong(*j, false, songArtists); - artistsToScan.insert(songArtists.begin(), songArtists.end()); - } - std::vector<int> albumArtists; - m_musicDatabase.GetArtistsByAlbum(idAlbum, false, albumArtists); - artistsToScan.insert(albumArtists.begin(), albumArtists.end()); - } - m_musicDatabase.CommitTransaction(); + album->strPath = strDirectory; + m_musicDatabase.BeginTransaction(); - // Download info & artwork - bool bCanceled; - for (set<int>::iterator it = artistsToScan.begin(); it != artistsToScan.end(); ++it) - { - bCanceled = false; - if (find(m_artistsScanned.begin(),m_artistsScanned.end(), *it) == m_artistsScanned.end()) + // Check if the album has already been downloaded or failed + map<CAlbum, CAlbum>::iterator cachedAlbum = m_albumCache.find(*album); + if (cachedAlbum == m_albumCache.end()) { - CStdString strArtist = m_musicDatabase.GetArtistById(*it); - m_artistsScanned.push_back(*it); - if (!m_bStop && (m_flags & SCAN_ONLINE)) - { - CStdString strPath; - strPath.Format("musicdb://artists/%u/", *it); + // No - download the information + CMusicAlbumInfo albumInfo; + INFO_RET albumDownloadStatus = INFO_NOT_FOUND; + if (m_flags & SCAN_ONLINE) + albumDownloadStatus = DownloadAlbumInfo(*album, albumScraper, albumInfo); - if (!DownloadArtistInfo(strPath, strArtist, bCanceled)) // assume we want to retry - m_artistsScanned.pop_back(); + if (albumDownloadStatus == INFO_ADDED || albumDownloadStatus == INFO_HAVE_ALREADY) + { + CAlbum &downloadedAlbum = albumInfo.GetAlbum(); + downloadedAlbum.idAlbum = m_musicDatabase.AddAlbum(downloadedAlbum.strAlbum, + downloadedAlbum.strMusicBrainzAlbumID, + downloadedAlbum.GetArtistString(), + downloadedAlbum.GetGenreString(), + downloadedAlbum.iYear, + downloadedAlbum.bCompilation); + m_musicDatabase.SetAlbumInfo(downloadedAlbum.idAlbum, + downloadedAlbum, + downloadedAlbum.songs); + m_musicDatabase.SetArtForItem(downloadedAlbum.idAlbum, + "album", album->art); + GetAlbumArtwork(downloadedAlbum.idAlbum, downloadedAlbum); + m_albumCache.insert(make_pair(*album, albumInfo.GetAlbum())); } - else + else if (albumDownloadStatus == INFO_CANCELLED) + break; + else // Cache the lookup failure so we don't retry { - map<string, string> artwork = GetArtistArtwork(*it); - m_musicDatabase.SetArtForItem(*it, "artist", artwork); + album->idAlbum = m_musicDatabase.AddAlbum(album->strAlbum, + album->strMusicBrainzAlbumID, + album->GetArtistString(), + album->GetGenreString(), + album->iYear, + album->bCompilation); + m_albumCache.insert(make_pair(*album, *album)); } + + // Update the cache pointer with our newly created info + cachedAlbum = m_albumCache.find(*album); } - } - if (m_flags & SCAN_ONLINE) - { - for (set<int>::iterator it = albumsToScan.begin(); it != albumsToScan.end(); ++it) + if (m_bStop) + break; + + // Add the album artists + for (VECARTISTCREDITS::iterator artistCredit = cachedAlbum->second.artistCredits.begin(); artistCredit != cachedAlbum->second.artistCredits.end(); ++artistCredit) { if (m_bStop) - return songsToAdd.size(); + break; - CStdString strPath; - strPath.Format("musicdb://albums/%u/",*it); + // Check if the artist has already been downloaded or failed + map<CArtistCredit, CArtist>::iterator cachedArtist = m_artistCache.find(*artistCredit); + if (cachedArtist == m_artistCache.end()) + { + CArtist artistTmp; + artistTmp.strArtist = artistCredit->GetArtist(); + artistTmp.strMusicBrainzArtistID = artistCredit->GetMusicBrainzArtistID(); + URIUtils::GetParentPath(album->strPath, artistTmp.strPath); + + // No - download the information + CMusicArtistInfo artistInfo; + INFO_RET artistDownloadStatus = INFO_NOT_FOUND; + if (m_flags & SCAN_ONLINE) + artistDownloadStatus = DownloadArtistInfo(artistTmp, artistScraper, artistInfo); + + if (artistDownloadStatus == INFO_ADDED || artistDownloadStatus == INFO_HAVE_ALREADY) + { + CArtist &downloadedArtist = artistInfo.GetArtist(); + downloadedArtist.idArtist = m_musicDatabase.AddArtist(downloadedArtist.strArtist, + downloadedArtist.strMusicBrainzArtistID); + m_musicDatabase.SetArtistInfo(downloadedArtist.idArtist, + downloadedArtist); + + URIUtils::GetParentPath(album->strPath, downloadedArtist.strPath); + map<string, string> artwork = GetArtistArtwork(downloadedArtist); + // check thumb stuff + m_musicDatabase.SetArtForItem(downloadedArtist.idArtist, "artist", artwork); + m_artistCache.insert(make_pair(*artistCredit, downloadedArtist)); + } + else if (artistDownloadStatus == INFO_CANCELLED) + break; + else + { + // Cache the lookup failure so we don't retry + artistTmp.idArtist = m_musicDatabase.AddArtist(artistCredit->GetArtist(), artistCredit->GetMusicBrainzArtistID()); + m_artistCache.insert(make_pair(*artistCredit, artistTmp)); + } + + // Update the cache pointer with our newly created info + cachedArtist = m_artistCache.find(*artistCredit); + } - CAlbum album; - m_musicDatabase.GetAlbumInfo(*it, album, NULL); - bCanceled = false; - if (find(m_albumsScanned.begin(), m_albumsScanned.end(), *it) == m_albumsScanned.end()) + m_musicDatabase.AddAlbumArtist(cachedArtist->second.idArtist, + cachedAlbum->second.idAlbum, + artistCredit->GetJoinPhrase(), + artistCredit == album->artistCredits.begin() ? false : true, + std::distance(cachedAlbum->second.artistCredits.begin(), artistCredit)); + } + + if (m_bStop) + break; + + for (VECSONGS::iterator song = album->songs.begin(); song != album->songs.end(); ++song) + { + song->idAlbum = cachedAlbum->second.idAlbum; + song->idSong = m_musicDatabase.AddSong(cachedAlbum->second.idAlbum, + song->strTitle, song->strMusicBrainzTrackID, + song->strFileName, song->strComment, + song->strThumb, + song->artist, song->genre, + song->iTrack, song->iDuration, song->iYear, + song->iTimesPlayed, song->iStartOffset, + song->iEndOffset, + song->lastPlayed, + song->rating, + song->iKaraokeNumber); + for (VECARTISTCREDITS::iterator artistCredit = song->artistCredits.begin(); artistCredit != song->artistCredits.end(); ++artistCredit) { - CMusicAlbumInfo albumInfo; - if (DownloadAlbumInfo(strPath, StringUtils::Join(album.artist, g_advancedSettings.m_musicItemSeparator), album.strAlbum, bCanceled, albumInfo)) - m_albumsScanned.push_back(*it); + if (m_bStop) + break; + + // Check if the artist has already been downloaded or failed + map<CArtistCredit, CArtist>::iterator cachedArtist = m_artistCache.find(*artistCredit); + if (cachedArtist == m_artistCache.end()) + { + CArtist artistTmp; + artistTmp.strArtist = artistCredit->GetArtist(); + artistTmp.strMusicBrainzArtistID = artistCredit->GetMusicBrainzArtistID(); + URIUtils::GetParentPath(album->strPath, artistTmp.strPath); // FIXME + + // No - download the information + CMusicArtistInfo artistInfo; + INFO_RET artistDownloadStatus = INFO_NOT_FOUND; + if (m_flags & SCAN_ONLINE) + artistDownloadStatus = DownloadArtistInfo(artistTmp, artistScraper, artistInfo); + + if (artistDownloadStatus == INFO_ADDED || artistDownloadStatus == INFO_HAVE_ALREADY) + { + CArtist &downloadedArtist = artistInfo.GetArtist(); + downloadedArtist.idArtist = m_musicDatabase.AddArtist(downloadedArtist.strArtist, + downloadedArtist.strMusicBrainzArtistID); + m_musicDatabase.SetArtistInfo(downloadedArtist.idArtist, + downloadedArtist); + // check thumb stuff + URIUtils::GetParentPath(album->strPath, downloadedArtist.strPath); + map<string, string> artwork = GetArtistArtwork(downloadedArtist); + m_musicDatabase.SetArtForItem(downloadedArtist.idArtist, "artist", artwork); + m_artistCache.insert(make_pair(*artistCredit, downloadedArtist)); + } + else if (artistDownloadStatus == INFO_CANCELLED) + break; + else + { + // Cache the lookup failure so we don't retry + artistTmp.idArtist = m_musicDatabase.AddArtist(artistCredit->GetArtist(), artistCredit->GetMusicBrainzArtistID()); + m_artistCache.insert(make_pair(*artistCredit, artistTmp)); + } + + // Update the cache pointer with our newly created info + cachedArtist = m_artistCache.find(*artistCredit); + } + + m_musicDatabase.AddSongArtist(cachedArtist->second.idArtist, + song->idSong, + g_advancedSettings.m_musicItemSeparator, // we don't have song artist breakdowns from scrapers, yet + artistCredit == song->artistCredits.begin() ? false : true, + std::distance(song->artistCredits.begin(), artistCredit)); } } + + if (m_bStop) + break; + + // Commit the album to the DB + m_musicDatabase.CommitTransaction(); + numAdded += album->songs.size(); } + + if (m_bStop) + m_musicDatabase.RollbackTransaction(); + if (m_handle) m_handle->SetTitle(g_localizeStrings.Get(505)); - return songsToAdd.size(); + return numAdded; } -static bool SortSongsByTrack(CSong *song, CSong *song2) +static bool SortSongsByTrack(const CSong& song, const CSong& song2) { - return song->iTrack < song2->iTrack; + return song.iTrack < song2.iTrack; } -void CMusicInfoScanner::CategoriseAlbums(VECSONGS &songsToCheck, VECALBUMS &albums) +void CMusicInfoScanner::FixupAlbums(VECALBUMS &albums) { - /* Step 1: categorise on the album name */ - map<string, vector<CSong *> > albumNames; - for (VECSONGS::iterator i = songsToCheck.begin(); i != songsToCheck.end(); ++i) - albumNames[i->strAlbum].push_back(&(*i)); - /* Step 2: Split into unique albums based on album name and album artist In the case where the album artist is unknown, we use the primary artist (i.e. first artist from each song). */ - albums.clear(); - for (map<string, vector<CSong *> >::iterator i = albumNames.begin(); i != albumNames.end(); ++i) + for (VECALBUMS::iterator album = albums.begin(); album != albums.end(); ++album) { + /* + * If we have a valid MusicBrainz tag for the album, assume everything + * is okay with our tags, as Picard should set everything up correctly. + */ + if (!album->strMusicBrainzAlbumID.IsEmpty()) + continue; + + VECSONGS &songs = album->songs; // sort the songs by tracknumber to identify duplicate track numbers - vector<CSong *> &songs = i->second; sort(songs.begin(), songs.end(), SortSongsByTrack); // map the songs to their primary artists @@ -673,14 +832,13 @@ void CMusicInfoScanner::CategoriseAlbums(VECSONGS &songsToCheck, VECALBUMS &albu bool isCompilation = true; map<string, vector<CSong *> > artists; - for (vector<CSong *>::iterator j = songs.begin(); j != songs.end(); ++j) + for (VECSONGS::iterator song = songs.begin(); song != songs.end(); ++song) { - CSong *song = *j; // test for song overlap - if (j != songs.begin() && song->iTrack == (*(j-1))->iTrack) + if (song != songs.begin() && song->iTrack == (song - 1)->iTrack) tracksOverlap = true; - if (! song->bCompilation) + if (!song->bCompilation) isCompilation = false; // get primary artist @@ -694,7 +852,7 @@ void CMusicInfoScanner::CategoriseAlbums(VECSONGS &songsToCheck, VECALBUMS &albu primary = song->artist[0]; // add to the artist map - artists[primary].push_back(song); + artists[primary].push_back(&(*song)); } /* @@ -705,7 +863,7 @@ void CMusicInfoScanner::CategoriseAlbums(VECSONGS &songsToCheck, VECALBUMS &albu 3a. a unique primary artist is specified as "various" or "various artists" OR 3b. we have at least two primary artists and no album artist specified. */ - bool compilation = !i->first.empty() && (isCompilation || !tracksOverlap); // 1+2b+2a + bool compilation = !album->strAlbum.empty() && (isCompilation || !tracksOverlap); // 1+2b+2a if (artists.size() == 1) { string artist = artists.begin()->first; StringUtils::ToLower(artist); @@ -718,13 +876,15 @@ void CMusicInfoScanner::CategoriseAlbums(VECSONGS &songsToCheck, VECALBUMS &albu if (compilation) { - CLog::Log(LOGDEBUG, "Album '%s' is a compilation as there's no overlapping tracks and %s", i->first.c_str(), hasAlbumArtist ? "the album artist is 'Various'" : "there is more than one unique artist"); + CLog::Log(LOGDEBUG, "Album '%s' is a compilation as there's no overlapping tracks and %s", album->strAlbum.c_str(), hasAlbumArtist ? "the album artist is 'Various'" : "there is more than one unique artist"); artists.clear(); std::string various = g_localizeStrings.Get(340); // Various Artists vector<string> va; va.push_back(various); - for (vector<CSong *>::iterator j = songs.begin(); j != songs.end(); ++j) - (*j)->albumArtist = va; - artists.insert(make_pair(various, songs)); + for (VECSONGS::iterator song = songs.begin(); song != songs.end(); ++song) + { + song->albumArtist = va; + artists[various].push_back(&(*song)); + } } /* @@ -752,24 +912,25 @@ void CMusicInfoScanner::CategoriseAlbums(VECSONGS &songsToCheck, VECALBUMS &albu Step 4: Assign the album artist for each song that doesn't have it set and add to the album vector */ - CAlbum album; - album.strAlbum = i->first; - album.artist = common; - album.bCompilation = compilation; + album->artistCredits.clear(); + for (vector<string>::iterator it = common.begin(); it != common.end(); ++it) + { + CStdString strJoinPhrase = (it == --common.end() ? "" : g_advancedSettings.m_musicItemSeparator); + CArtistCredit artistCredit(*it, strJoinPhrase); + album->artistCredits.push_back(artistCredit); + } + album->bCompilation = compilation; for (vector<CSong *>::iterator k = artistSongs.begin(); k != artistSongs.end(); ++k) { if ((*k)->albumArtist.empty()) (*k)->albumArtist = common; - album.songs.push_back(*(*k)); // TODO: in future we may wish to union up the genres, for now we assume they're the same - if (album.genre.empty()) - album.genre = (*k)->genre; + if (album->genre.empty()) + album->genre = (*k)->genre; // in addition, we may want to use year as discriminating for albums - if (album.iYear == 0) - album.iYear = (*k)->iYear; + if (album->iYear == 0) + album->iYear = (*k)->iYear; } - - albums.push_back(album); } } } @@ -853,53 +1014,6 @@ void CMusicInfoScanner::FindArtForAlbums(VECALBUMS &albums, const CStdString &pa } } -// This function is run by another thread -void CMusicInfoScanner::Run() -{ - int count = 0; - while (!m_bStop && m_pathsToCount.size()) - count+=CountFilesRecursively(*m_pathsToCount.begin()); - m_itemCount = count; -} - -// Recurse through all folders we scan and count files -int CMusicInfoScanner::CountFilesRecursively(const CStdString& strPath) -{ - // load subfolder - CFileItemList items; -// CLog::Log(LOGDEBUG, __FUNCTION__" - processing dir: %s", strPath.c_str()); - CDirectory::GetDirectory(strPath, items, g_advancedSettings.m_musicExtensions, DIR_FLAG_NO_FILE_DIRS); - - if (m_bStop) - return 0; - - // true for recursive counting - int count = CountFiles(items, true); - - // remove this path from the list we're processing - set<CStdString>::iterator it = m_pathsToCount.find(strPath); - if (it != m_pathsToCount.end()) - m_pathsToCount.erase(it); - -// CLog::Log(LOGDEBUG, __FUNCTION__" - finished processing dir: %s", strPath.c_str()); - return count; -} - -int CMusicInfoScanner::CountFiles(const CFileItemList &items, bool recursive) -{ - int count = 0; - for (int i=0; i<items.Size(); ++i) - { - const CFileItemPtr pItem=items[i]; - - if (recursive && pItem->m_bIsFolder) - count+=CountFilesRecursively(pItem->GetPath()); - else if (pItem->IsAudio() && !pItem->IsPlayList() && !pItem->IsNFO()) - count++; - } - return count; -} - int CMusicInfoScanner::GetPathHash(const CFileItemList &items, CStdString &hash) { // Create a hash based on the filenames, filesize and filedate. Also count the number of files @@ -920,88 +1034,168 @@ int CMusicInfoScanner::GetPathHash(const CFileItemList &items, CStdString &hash) return count; } -#define THRESHOLD .95f - -bool CMusicInfoScanner::DownloadAlbumInfo(const CStdString& strPath, const CStdString& strArtist, const CStdString& strAlbum, bool& bCanceled, CMusicAlbumInfo& albumInfo, CGUIDialogProgress* pDialog) +INFO_RET CMusicInfoScanner::UpdateDatabaseAlbumInfo(const CStdString& strPath, CMusicAlbumInfo& albumInfo, bool bAllowSelection, CGUIDialogProgress* pDialog /* = NULL */) { + m_musicDatabase.Open(); + CQueryParams params; + CDirectoryNode::GetDatabaseInfo(strPath, params); + + if (params.GetAlbumId() == -1) + return INFO_ERROR; + CAlbum album; - VECSONGS songs; - XFILE::MUSICDATABASEDIRECTORY::CQueryParams params; - XFILE::MUSICDATABASEDIRECTORY::CDirectoryNode::GetDatabaseInfo(strPath, params); - bCanceled = false; + m_musicDatabase.GetAlbumInfo(params.GetAlbumId(), album, &album.songs); + + // find album info + ADDON::ScraperPtr scraper; + if (!m_musicDatabase.GetScraperForPath(strPath, scraper, ADDON::ADDON_SCRAPER_ALBUMS) || !scraper) + return INFO_ERROR; + m_musicDatabase.Close(); + +loop: + CLog::Log(LOGDEBUG, "%s downloading info for: %s", __FUNCTION__, album.strAlbum.c_str()); + INFO_RET albumDownloadStatus = DownloadAlbumInfo(album, scraper, albumInfo, pDialog); + if (albumDownloadStatus == INFO_NOT_FOUND) + { + if (pDialog && bAllowSelection) + { + if (!CGUIKeyboardFactory::ShowAndGetInput(album.strAlbum, g_localizeStrings.Get(16011), false)) + return INFO_CANCELLED; + + CStdString strTempArtist(StringUtils::Join(album.artist, g_advancedSettings.m_musicItemSeparator)); + if (!CGUIKeyboardFactory::ShowAndGetInput(strTempArtist, g_localizeStrings.Get(16025), false)) + return INFO_CANCELLED; + + album.artist = StringUtils::Split(strTempArtist, g_advancedSettings.m_musicItemSeparator); + goto loop; + } + } + else if (albumDownloadStatus == INFO_ADDED) + { + m_musicDatabase.Open(); + m_musicDatabase.SetAlbumInfo(params.GetAlbumId(), albumInfo.GetAlbum(), albumInfo.GetAlbum().songs); + GetAlbumArtwork(params.GetAlbumId(), albumInfo.GetAlbum()); + albumInfo.SetLoaded(true); + m_musicDatabase.Close(); + } + return albumDownloadStatus; +} + +INFO_RET CMusicInfoScanner::UpdateDatabaseArtistInfo(const CStdString& strPath, CMusicArtistInfo& artistInfo, bool bAllowSelection, CGUIDialogProgress* pDialog /* = NULL */) +{ m_musicDatabase.Open(); - if (m_musicDatabase.HasAlbumInfo(params.GetAlbumId()) && m_musicDatabase.GetAlbumInfo(params.GetAlbumId(),album,&songs)) - return true; + CQueryParams params; + CDirectoryNode::GetDatabaseInfo(strPath, params); + + if (params.GetArtistId() == -1) + return INFO_ERROR; + + CArtist artist; + m_musicDatabase.GetArtistInfo(params.GetArtistId(), artist); // find album info - ADDON::ScraperPtr info; - if (!m_musicDatabase.GetScraperForPath(strPath, info, ADDON::ADDON_SCRAPER_ALBUMS) || !info) + ADDON::ScraperPtr scraper; + if (!m_musicDatabase.GetScraperForPath(strPath, scraper, ADDON::ADDON_SCRAPER_ARTISTS) || !scraper) + return INFO_ERROR; + m_musicDatabase.Close(); + +loop: + CLog::Log(LOGDEBUG, "%s downloading info for: %s", __FUNCTION__, artist.strArtist.c_str()); + INFO_RET artistDownloadStatus = DownloadArtistInfo(artist, scraper, artistInfo, pDialog); + if (artistDownloadStatus == INFO_NOT_FOUND) { + if (pDialog && bAllowSelection) + { + if (!CGUIKeyboardFactory::ShowAndGetInput(artist.strArtist, g_localizeStrings.Get(16025), false)) + return INFO_CANCELLED; + goto loop; + } + } + else if (artistDownloadStatus == INFO_ADDED) + { + m_musicDatabase.Open(); + m_musicDatabase.SetArtistInfo(params.GetArtistId(), artistInfo.GetArtist()); + m_musicDatabase.GetArtistPath(params.GetArtistId(), artist.strPath); + map<string, string> artwork = GetArtistArtwork(artist); + m_musicDatabase.SetArtForItem(params.GetArtistId(), "artist", artwork); + artistInfo.SetLoaded(); m_musicDatabase.Close(); - return false; } + return artistDownloadStatus; +} +#define THRESHOLD .95f + +INFO_RET CMusicInfoScanner::DownloadAlbumInfo(const CAlbum& album, ADDON::ScraperPtr& info, CMusicAlbumInfo& albumInfo, CGUIDialogProgress* pDialog) +{ if (m_handle) { m_handle->SetTitle(StringUtils::Format(g_localizeStrings.Get(20321), info->Name().c_str())); - m_handle->SetText(strArtist+" - "+strAlbum); + m_handle->SetText(StringUtils::Join(album.artist, g_advancedSettings.m_musicItemSeparator) + " - " + album.strAlbum); } // clear our scraper cache info->ClearCache(); CMusicInfoScraper scraper(info); + bool bMusicBrainz = false; + if (!album.strMusicBrainzAlbumID.empty()) + { + CScraperUrl musicBrainzURL; + if (ResolveMusicBrainz(album.strMusicBrainzAlbumID, info, scraper, musicBrainzURL)) + { + CMusicAlbumInfo albumNfo("nfo", musicBrainzURL); + scraper.GetAlbums().clear(); + scraper.GetAlbums().push_back(albumNfo); + bMusicBrainz = true; + } + } // handle nfo files - CStdString strAlbumPath, strNfo; - m_musicDatabase.GetAlbumPath(params.GetAlbumId(),strAlbumPath); - URIUtils::AddFileToFolder(strAlbumPath,"album.nfo",strNfo); - CNfoFile::NFOResult result=CNfoFile::NO_NFO; + CStdString strNfo = URIUtils::AddFileToFolder(album.strPath, "album.nfo"); + CNfoFile::NFOResult result = CNfoFile::NO_NFO; CNfoFile nfoReader; if (XFILE::CFile::Exists(strNfo)) { CLog::Log(LOGDEBUG,"Found matching nfo file: %s", strNfo.c_str()); - result = nfoReader.Create(strNfo, info, -1, strPath); + result = nfoReader.Create(strNfo, info, -1, album.strPath); if (result == CNfoFile::FULL_NFO) { CLog::Log(LOGDEBUG, "%s Got details from nfo", __FUNCTION__); - CAlbum album; - nfoReader.GetDetails(album); - m_musicDatabase.SetAlbumInfo(params.GetAlbumId(), album, album.songs); - GetAlbumArtwork(params.GetAlbumId(), album); - m_musicDatabase.Close(); - return true; + nfoReader.GetDetails(albumInfo.GetAlbum()); + return INFO_ADDED; } else if (result == CNfoFile::URL_NFO || result == CNfoFile::COMBINED_NFO) { CScraperUrl scrUrl(nfoReader.ScraperUrl()); - CMusicAlbumInfo album("nfo",scrUrl); + CMusicAlbumInfo albumNfo("nfo",scrUrl); info = nfoReader.GetScraperInfo(); CLog::Log(LOGDEBUG,"-- nfo-scraper: %s",info->Name().c_str()); CLog::Log(LOGDEBUG,"-- nfo url: %s", scrUrl.m_url[0].m_url.c_str()); scraper.SetScraperInfo(info); - scraper.GetAlbums().push_back(album); + scraper.GetAlbums().clear(); + scraper.GetAlbums().push_back(albumNfo); } else CLog::Log(LOGERROR,"Unable to find an url in nfo file: %s", strNfo.c_str()); } - if (!scraper.CheckValidOrFallback(g_guiSettings.GetString("musiclibrary.albumsscraper"))) + if (!scraper.CheckValidOrFallback(CSettings::Get().GetString("musiclibrary.albumsscraper"))) { // the current scraper is invalid, as is the default - bail CLog::Log(LOGERROR, "%s - current and default scrapers are invalid. Pick another one", __FUNCTION__); - return false; + return INFO_ERROR; } if (!scraper.GetAlbumCount()) { - scraper.FindAlbumInfo(strAlbum, strArtist); + scraper.FindAlbumInfo(album.strAlbum, StringUtils::Join(album.artist, g_advancedSettings.m_musicItemSeparator)); while (!scraper.Completed()) { if (m_bStop) { scraper.Cancel(); - bCanceled = true; + return INFO_CANCELLED; } Sleep(1); } @@ -1009,7 +1203,7 @@ bool CMusicInfoScanner::DownloadAlbumInfo(const CStdString& strPath, const CStdS CGUIDialogSelect *pDlg = NULL; int iSelectedAlbum=0; - if (result == CNfoFile::NO_NFO) + if (result == CNfoFile::NO_NFO && !bMusicBrainz) { iSelectedAlbum = -1; // set negative so that we can detect a failure if (scraper.Succeeded() && scraper.GetAlbumCount() >= 1) @@ -1032,7 +1226,7 @@ bool CMusicInfoScanner::DownloadAlbumInfo(const CStdString& strPath, const CStdS CMusicAlbumInfo& info = scraper.GetAlbum(i); double relevance = info.GetRelevance(); if (relevance < 0) - relevance = CUtil::AlbumRelevance(info.GetAlbum().strAlbum, strAlbum, StringUtils::Join(info.GetAlbum().artist, g_advancedSettings.m_musicItemSeparator), strArtist); + relevance = CUtil::AlbumRelevance(info.GetAlbum().strAlbum, album.strAlbum, StringUtils::Join(info.GetAlbum().artist, g_advancedSettings.m_musicItemSeparator), StringUtils::Join(album.artist, g_advancedSettings.m_musicItemSeparator)); // if we're doing auto-selection (ie querying all albums at once, then allow 95->100% for perfect matches) // otherwise, perfect matches only @@ -1063,22 +1257,25 @@ bool CMusicInfoScanner::DownloadAlbumInfo(const CStdString& strPath, const CStdS if (pDlg->GetSelectedLabel() < 0) { // none chosen if (!pDlg->IsButtonPressed()) - return false; + return INFO_CANCELLED; // manual button pressed CStdString strNewAlbum = album.strAlbum; - if (!CGUIKeyboardFactory::ShowAndGetInput(strNewAlbum, g_localizeStrings.Get(16011), false)) return false; - if (strNewAlbum == "") return false; + if (!CGUIKeyboardFactory::ShowAndGetInput(strNewAlbum, g_localizeStrings.Get(16011), false)) return INFO_CANCELLED; + if (strNewAlbum == "") return INFO_CANCELLED; CStdString strNewArtist = StringUtils::Join(album.artist, g_advancedSettings.m_musicItemSeparator); - if (!CGUIKeyboardFactory::ShowAndGetInput(strNewArtist, g_localizeStrings.Get(16025), false)) return false; + if (!CGUIKeyboardFactory::ShowAndGetInput(strNewArtist, g_localizeStrings.Get(16025), false)) return INFO_CANCELLED; pDialog->SetLine(0, strNewAlbum); pDialog->SetLine(1, strNewArtist); pDialog->Progress(); - m_musicDatabase.Close(); - return DownloadAlbumInfo(strPath,strNewArtist,strNewAlbum,bCanceled,albumInfo,pDialog); + CAlbum newAlbum = album; + newAlbum.strAlbum = strNewAlbum; + newAlbum.artist = StringUtils::Split(strNewArtist, g_advancedSettings.m_musicItemSeparator); + + return DownloadAlbumInfo(newAlbum, info, albumInfo, pDialog); } iSelectedAlbum = pDlg->GetSelectedItem()->m_idepth; } @@ -1088,21 +1285,20 @@ bool CMusicInfoScanner::DownloadAlbumInfo(const CStdString& strPath, const CStdS CMusicAlbumInfo& info = scraper.GetAlbum(0); double relevance = info.GetRelevance(); if (relevance < 0) - relevance = CUtil::AlbumRelevance(info.GetAlbum().strAlbum, strAlbum, StringUtils::Join(info.GetAlbum().artist, g_advancedSettings.m_musicItemSeparator), strArtist); + relevance = CUtil::AlbumRelevance(info.GetAlbum().strAlbum, + album.strAlbum, + StringUtils::Join(info.GetAlbum().artist, g_advancedSettings.m_musicItemSeparator), + StringUtils::Join(album.artist, g_advancedSettings.m_musicItemSeparator)); if (relevance < THRESHOLD) - { - m_musicDatabase.Close(); - return false; - } + return INFO_NOT_FOUND; + iSelectedAlbum = 0; } } if (iSelectedAlbum < 0) - { - m_musicDatabase.Close(); - return false; - } + return INFO_NOT_FOUND; + } scraper.LoadAlbumInfo(iSelectedAlbum); @@ -1110,30 +1306,21 @@ bool CMusicInfoScanner::DownloadAlbumInfo(const CStdString& strPath, const CStdS { if (m_bStop) { - bCanceled = true; scraper.Cancel(); + return INFO_CANCELLED; } Sleep(1); } - if (scraper.Succeeded()) - { - albumInfo = scraper.GetAlbum(iSelectedAlbum); - album = scraper.GetAlbum(iSelectedAlbum).GetAlbum(); - if (result == CNfoFile::COMBINED_NFO) - nfoReader.GetDetails(album,NULL,true); - m_musicDatabase.SetAlbumInfo(params.GetAlbumId(), album, scraper.GetAlbum(iSelectedAlbum).GetSongs(),false); - } - else - { - m_musicDatabase.Close(); - return false; - } + if (!scraper.Succeeded()) + return INFO_ERROR; - // check thumb stuff - GetAlbumArtwork(params.GetAlbumId(), album); - m_musicDatabase.Close(); - return true; + albumInfo = scraper.GetAlbum(iSelectedAlbum); + + if (result == CNfoFile::COMBINED_NFO) + nfoReader.GetDetails(albumInfo.GetAlbum(), NULL, true); + + return INFO_ADDED; } void CMusicInfoScanner::GetAlbumArtwork(long id, const CAlbum &album) @@ -1152,38 +1339,33 @@ void CMusicInfoScanner::GetAlbumArtwork(long id, const CAlbum &album) } } -bool CMusicInfoScanner::DownloadArtistInfo(const CStdString& strPath, const CStdString& strArtist, bool& bCanceled, CGUIDialogProgress* pDialog) +INFO_RET CMusicInfoScanner::DownloadArtistInfo(const CArtist& artist, ADDON::ScraperPtr& info, MUSIC_GRABBER::CMusicArtistInfo& artistInfo, CGUIDialogProgress* pDialog) { - XFILE::MUSICDATABASEDIRECTORY::CQueryParams params; - XFILE::MUSICDATABASEDIRECTORY::CDirectoryNode::GetDatabaseInfo(strPath, params); - bCanceled = false; - CArtist artist; - m_musicDatabase.Open(); - if (m_musicDatabase.HasArtistInfo(params.GetArtistId()) && m_musicDatabase.GetArtistInfo(params.GetArtistId(),artist)) // already got the info - return true; - - // find artist info - ADDON::ScraperPtr info; - if (!m_musicDatabase.GetScraperForPath(strPath, info, ADDON::ADDON_SCRAPER_ARTISTS) || !info) - { - m_musicDatabase.Close(); - return false; - } - if (m_handle) { m_handle->SetTitle(StringUtils::Format(g_localizeStrings.Get(20320), info->Name().c_str())); - m_handle->SetText(strArtist); + m_handle->SetText(artist.strArtist); } // clear our scraper cache info->ClearCache(); CMusicInfoScraper scraper(info); + bool bMusicBrainz = false; + if (!artist.strMusicBrainzArtistID.empty()) + { + CScraperUrl musicBrainzURL; + if (ResolveMusicBrainz(artist.strMusicBrainzArtistID, info, scraper, musicBrainzURL)) + { + CMusicArtistInfo artistNfo("nfo", musicBrainzURL); + scraper.GetArtists().clear(); + scraper.GetArtists().push_back(artistNfo); + bMusicBrainz = true; + } + } + // handle nfo files - CStdString strArtistPath, strNfo; - m_musicDatabase.GetArtistPath(params.GetArtistId(),strArtistPath); - URIUtils::AddFileToFolder(strArtistPath,"artist.nfo",strNfo); + CStdString strNfo = URIUtils::AddFileToFolder(artist.strPath, "artist.nfo"); CNfoFile::NFOResult result=CNfoFile::NO_NFO; CNfoFile nfoReader; if (XFILE::CFile::Exists(strNfo)) @@ -1193,23 +1375,18 @@ bool CMusicInfoScanner::DownloadArtistInfo(const CStdString& strPath, const CStd if (result == CNfoFile::FULL_NFO) { CLog::Log(LOGDEBUG, "%s Got details from nfo", __FUNCTION__); - CArtist artist; - nfoReader.GetDetails(artist); - m_musicDatabase.SetArtistInfo(params.GetArtistId(), artist); - map<string, string> artwork = GetArtistArtwork(params.GetArtistId(), &artist); - m_musicDatabase.SetArtForItem(params.GetArtistId(), "artist", artwork); - m_musicDatabase.Close(); - return true; + nfoReader.GetDetails(artistInfo.GetArtist()); + return INFO_ADDED; } else if (result == CNfoFile::URL_NFO || result == CNfoFile::COMBINED_NFO) { CScraperUrl scrUrl(nfoReader.ScraperUrl()); - CMusicArtistInfo artist("nfo",scrUrl); + CMusicArtistInfo artistNfo("nfo",scrUrl); info = nfoReader.GetScraperInfo(); CLog::Log(LOGDEBUG,"-- nfo-scraper: %s",info->Name().c_str()); CLog::Log(LOGDEBUG,"-- nfo url: %s", scrUrl.m_url[0].m_url.c_str()); scraper.SetScraperInfo(info); - scraper.GetArtists().push_back(artist); + scraper.GetArtists().push_back(artistNfo); } else CLog::Log(LOGERROR,"Unable to find an url in nfo file: %s", strNfo.c_str()); @@ -1217,23 +1394,23 @@ bool CMusicInfoScanner::DownloadArtistInfo(const CStdString& strPath, const CStd if (!scraper.GetArtistCount()) { - scraper.FindArtistInfo(strArtist); + scraper.FindArtistInfo(artist.strArtist); while (!scraper.Completed()) { if (m_bStop) { scraper.Cancel(); - bCanceled = true; + return INFO_CANCELLED; } Sleep(1); } } int iSelectedArtist = 0; - if (result == CNfoFile::NO_NFO) + if (result == CNfoFile::NO_NFO && !bMusicBrainz) { - if (scraper.Succeeded() && scraper.GetArtistCount() >= 1) + if (scraper.GetArtistCount() >= 1) { // now load the first match if (pDialog && scraper.GetArtistCount() > 1) @@ -1269,76 +1446,141 @@ bool CMusicInfoScanner::DownloadArtistInfo(const CStdString& strPath, const CStd if (pDlg->GetSelectedLabel() < 0) { // none chosen if (!pDlg->IsButtonPressed()) - { - bCanceled = true; - return false; - } + return INFO_CANCELLED; + // manual button pressed - CStdString strNewArtist = strArtist; - if (!CGUIKeyboardFactory::ShowAndGetInput(strNewArtist, g_localizeStrings.Get(16025), false)) return false; + CStdString strNewArtist = artist.strArtist; + if (!CGUIKeyboardFactory::ShowAndGetInput(strNewArtist, g_localizeStrings.Get(16025), false)) return INFO_CANCELLED; if (pDialog) { pDialog->SetLine(0, strNewArtist); pDialog->Progress(); } - m_musicDatabase.Close(); - return DownloadArtistInfo(strPath,strNewArtist,bCanceled,pDialog); + + CArtist newArtist; + newArtist.strArtist = strNewArtist; + return DownloadArtistInfo(newArtist, info, artistInfo, pDialog); } iSelectedArtist = pDlg->GetSelectedItem()->m_idepth; } } } else - { - m_musicDatabase.Close(); - return false; - } + return INFO_NOT_FOUND; } - scraper.LoadArtistInfo(iSelectedArtist, strArtist); + scraper.LoadArtistInfo(iSelectedArtist, artist.strArtist); while (!scraper.Completed()) { if (m_bStop) { scraper.Cancel(); - bCanceled = true; + return INFO_CANCELLED; } Sleep(1); } - if (scraper.Succeeded()) + if (!scraper.Succeeded()) + return INFO_ERROR; + + artistInfo = scraper.GetArtist(iSelectedArtist); + + if (result == CNfoFile::COMBINED_NFO) + nfoReader.GetDetails(artistInfo.GetArtist(), NULL, true); + + return INFO_ADDED; +} + +bool CMusicInfoScanner::ResolveMusicBrainz(const CStdString strMusicBrainzID, ScraperPtr &preferredScraper, CMusicInfoScraper &musicInfoScraper, CScraperUrl &musicBrainzURL) +{ + // We have a MusicBrainz ID + // Get a scraper that can resolve it to a MusicBrainz URL & force our + // search directly to the specific album. + bool bMusicBrainz = false; + ADDON::TYPE type = ScraperTypeFromContent(preferredScraper->Content()); + + CFileItemList items; + ADDON::AddonPtr addon; + ADDON::ScraperPtr defaultScraper; + if (ADDON::CAddonMgr::Get().GetDefault(type, addon)) + defaultScraper = boost::dynamic_pointer_cast<CScraper>(addon); + + vector<ScraperPtr> vecScrapers; + + // add selected scraper - first proirity + if (preferredScraper) + vecScrapers.push_back(preferredScraper); + + // Add all scrapers except selected and default + VECADDONS addons; + CAddonMgr::Get().GetAddons(type, addons); + + for (unsigned i = 0; i < addons.size(); ++i) { - artist = scraper.GetArtist(iSelectedArtist).GetArtist(); - if (result == CNfoFile::COMBINED_NFO) - nfoReader.GetDetails(artist,NULL,true); - m_musicDatabase.SetArtistInfo(params.GetArtistId(), artist); + ScraperPtr scraper = boost::dynamic_pointer_cast<CScraper>(addons[i]); + + // skip if scraper requires settings and there's nothing set yet + if (!scraper || (scraper->RequiresSettings() && !scraper->HasUserSettings())) + continue; + + if((!preferredScraper || preferredScraper->ID() != scraper->ID()) && (!defaultScraper || defaultScraper->ID() != scraper->ID()) ) + vecScrapers.push_back(scraper); } - // check thumb stuff - map<string, string> artwork = GetArtistArtwork(params.GetArtistId(), &artist); - m_musicDatabase.SetArtForItem(params.GetArtistId(), "artist", artwork); + // add default scraper - not user selectable so it's last priority + if(defaultScraper && + (!preferredScraper || preferredScraper->ID() != defaultScraper->ID()) && + (!defaultScraper->RequiresSettings() || defaultScraper->HasUserSettings())) + vecScrapers.push_back(defaultScraper); - m_musicDatabase.Close(); - return true; + for (unsigned int i=0; i < vecScrapers.size(); ++i) + { + if (vecScrapers[i]->Type() != type) + continue; + + vecScrapers[i]->ClearCache(); + try + { + musicBrainzURL = vecScrapers[i]->ResolveIDToUrl(strMusicBrainzID); + } + catch (const ADDON::CScraperError &sce) + { + if (!sce.FAborted()) + continue; + } + if (!musicBrainzURL.m_url.empty()) + { + CLog::Log(LOGDEBUG,"-- nfo-scraper: %s",vecScrapers[i]->Name().c_str()); + CLog::Log(LOGDEBUG,"-- nfo url: %s", musicBrainzURL.m_url[0].m_url.c_str()); + musicInfoScraper.SetScraperInfo(vecScrapers[i]); + bMusicBrainz = true; + break; + } + } + + return bMusicBrainz; } -map<string, string> CMusicInfoScanner::GetArtistArtwork(long id, const CArtist *artist) +map<string, string> CMusicInfoScanner::GetArtistArtwork(const CArtist& artist) { - CStdString artistPath; - m_musicDatabase.Open(); - bool checkLocal = m_musicDatabase.GetArtistPath(id, artistPath); - m_musicDatabase.Close(); - - CFileItem item(artistPath, true); map<string, string> artwork; // check thumb + CStdString strFolder; CStdString thumb; - if (checkLocal) - thumb = item.GetUserMusicThumb(true); - if (thumb.IsEmpty() && artist) - thumb = CScraperUrl::GetThumbURL(artist->thumbURL.GetFirstThumb()); + if (!artist.strPath.IsEmpty()) + { + strFolder = artist.strPath; + for (int i = 0; i < 3 && thumb.IsEmpty(); ++i) + { + CFileItem item(strFolder, true); + thumb = item.GetUserMusicThumb(true); + strFolder = URIUtils::GetParentPath(strFolder); + } + } + if (thumb.IsEmpty()) + thumb = CScraperUrl::GetThumbURL(artist.thumbURL.GetFirstThumb()); if (!thumb.IsEmpty()) { CTextureCache::Get().BackgroundCacheImage(thumb); @@ -1347,10 +1589,18 @@ map<string, string> CMusicInfoScanner::GetArtistArtwork(long id, const CArtist * // check fanart CStdString fanart; - if (checkLocal) - fanart = item.GetLocalFanart(); - if (fanart.IsEmpty() && artist) - fanart = artist->fanart.GetImageURL(); + if (!artist.strPath.IsEmpty()) + { + strFolder = artist.strPath; + for (int i = 0; i < 3 && fanart.IsEmpty(); ++i) + { + CFileItem item(strFolder, true); + fanart = item.GetLocalFanart(); + strFolder = URIUtils::GetParentPath(strFolder); + } + } + if (fanart.IsEmpty()) + fanart = artist.fanart.GetImageURL(); if (!fanart.IsEmpty()) { CTextureCache::Get().BackgroundCacheImage(fanart); @@ -1359,3 +1609,45 @@ map<string, string> CMusicInfoScanner::GetArtistArtwork(long id, const CArtist * return artwork; } + +// This function is the Run() function of the IRunnable +// CFileCountReader and runs in a separate thread. +void CMusicInfoScanner::Run() +{ + int count = 0; + for (set<std::string>::iterator it = m_pathsToScan.begin(); it != m_pathsToScan.end() && !m_bStop; ++it) + { + count+=CountFilesRecursively(*it); + } + m_itemCount = count; +} + +// Recurse through all folders we scan and count files +int CMusicInfoScanner::CountFilesRecursively(const CStdString& strPath) +{ + // load subfolder + CFileItemList items; + CDirectory::GetDirectory(strPath, items, g_advancedSettings.m_musicExtensions, DIR_FLAG_NO_FILE_DIRS); + + if (m_bStop) + return 0; + + // true for recursive counting + int count = CountFiles(items, true); + return count; +} + +int CMusicInfoScanner::CountFiles(const CFileItemList &items, bool recursive) +{ + int count = 0; + for (int i=0; i<items.Size(); ++i) + { + const CFileItemPtr pItem=items[i]; + + if (recursive && pItem->m_bIsFolder) + count+=CountFilesRecursively(pItem->GetPath()); + else if (pItem->IsAudio() && !pItem->IsPlayList() && !pItem->IsNFO()) + count++; + } + return count; +} diff --git a/xbmc/music/infoscanner/MusicInfoScanner.h b/xbmc/music/infoscanner/MusicInfoScanner.h index ff62721138..32118f3c33 100644 --- a/xbmc/music/infoscanner/MusicInfoScanner.h +++ b/xbmc/music/infoscanner/MusicInfoScanner.h @@ -21,6 +21,7 @@ #include "threads/Thread.h" #include "music/MusicDatabase.h" #include "MusicAlbumInfo.h" +#include "MusicInfoScraper.h" class CAlbum; class CArtist; @@ -62,28 +63,35 @@ public: //! \brief Set whether or not to show a progress dialog void ShowDialog(bool show) { m_showDialog = show; } - /*! \brief Categorise songs into albums + /*! \brief Categorize FileItems into Albums, Songs, and Artists + This takes a list of FileItems and turns it into a tree of Albums, + Artists, and Songs. Albums are defined uniquely by the album name and album artist. + + \param songs [in/out] list of songs to categorise - albumartist field may be altered. + \param albums [out] albums found within these songs. + */ + static void FileItemsToAlbums(CFileItemList& items, VECALBUMS& albums, MAPSONGS* songsMap = NULL); + /*! \brief Fixup albums and songs + If albumartist is not available in a song, we determine it from the common portion of each song's artist list. - + eg the common artist for - Bob Dylan / Tom Petty / Roy Orbison - Bob Dylan / Tom Petty + Bob Dylan / Tom Petty / Roy Orbison + Bob Dylan / Tom Petty would be "Bob Dylan / Tom Petty". - + If all songs that share an album - 1. have a non-empty album name - 2. have at least two different primary artists - 3. have no album artist set - 4. and no track numbers overlap + 1. have a non-empty album name + 2. have at least two different primary artists + 3. have no album artist set + 4. and no track numbers overlap we assume it is a various artists album, and set the albumartist field accordingly. - - \param songs [in/out] list of songs to categorise - albumartist field may be altered. - \param albums [out] albums found within these songs. + */ - static void CategoriseAlbums(VECSONGS &songs, VECALBUMS &albums); + static void FixupAlbums(VECALBUMS &albums); /*! \brief Find art for albums Based on the albums in the folder, finds whether we have unique album art @@ -102,13 +110,69 @@ public: */ static void FindArtForAlbums(VECALBUMS &albums, const CStdString &path); - bool DownloadAlbumInfo(const CStdString& strPath, const CStdString& strArtist, const CStdString& strAlbum, bool& bCanceled, MUSIC_GRABBER::CMusicAlbumInfo& album, CGUIDialogProgress* pDialog=NULL); - bool DownloadArtistInfo(const CStdString& strPath, const CStdString& strArtist, bool& bCanceled, CGUIDialogProgress* pDialog=NULL); + /*! \brief Update the database information for a MusicDB album + Given a musicdb:// style path pointing to an album, search and update its info + with the scrapers. If info is found, update the database and artwork with the new + information. + \param strPath [in] musicdb:// style path to the album in the database + \param albumInfo [in/out] a CMusicAlbumInfo struct which will be populated with the output of the scraper + \param pDialog [in] a progress dialog which this and downstream functions can update with status, if required + \param bAllowSelection [in] should we allow the user to manually override the info with a GUI if the album is not found? + */ + INFO_RET UpdateDatabaseAlbumInfo(const CStdString& strPath, MUSIC_GRABBER::CMusicAlbumInfo& albumInfo, bool bAllowSelection, CGUIDialogProgress* pDialog = NULL); + + /*! \brief Update the database information for a MusicDB artist + Given a musicdb:// style path pointing to an artist, search and update its info + with the scrapers. If info is found, update the database and artwork with the new + information. + \param strPath [in] musicdb:// style path to the artist in the database + \param albumInfo [in/out] a CMusicArtistInfo struct which will be populated with the output of the scraper + \param pDialog [in] a progress dialog which this and downstream functions can update with status, if required + \param bAllowSelection [in] should we allow the user to manually override the info with a GUI if the album is not found? + */ + INFO_RET UpdateDatabaseArtistInfo(const CStdString& strPath, MUSIC_GRABBER::CMusicArtistInfo& artistInfo, bool bAllowSelection, CGUIDialogProgress* pDialog = NULL); + + /*! \brief Using the scrapers download metadata for an album + Given a CAlbum style struct containing some data about an album, query + the scrapers to try and get more information about the album. The responsibility + is with the caller to do something with that information. It will be passed back + in a MusicInfo struct, which you can save, display to the user or throw away. + \param album [in] a partially or fully filled out album structure containing the search query + \param scraper [in] the scraper to query, usually the default or the relevant scraper for the musicdb path + \param albumInfo [in/out] a CMusicAlbumInfo struct which will be populated with the output of the scraper + \param pDialog [in] a progress dialog which this and downstream functions can update with status, if required + */ + INFO_RET DownloadAlbumInfo(const CAlbum& album, ADDON::ScraperPtr& scraper, MUSIC_GRABBER::CMusicAlbumInfo& albumInfo, CGUIDialogProgress* pDialog = NULL); + + /*! \brief Using the scrapers download metadata for an artist + Given a CAlbum style struct containing some data about an artist, query + the scrapers to try and get more information about the artist. The responsibility + is with the caller to do something with that information. It will be passed back + in a MusicInfo struct, which you can save, display to the user or throw away. + \param artist [in] a partially or fully filled out artist structure containing the search query + \param scraper [in] the scraper to query, usually the default or the relevant scraper for the musicdb path + \param artistInfo [in/out] a CMusicAlbumInfo struct which will be populated with the output of the scraper + \param pDialog [in] a progress dialog which this and downstream functions can update with status, if required + */ + INFO_RET DownloadArtistInfo(const CArtist& artist, ADDON::ScraperPtr& scraper, MUSIC_GRABBER::CMusicArtistInfo& artistInfo, CGUIDialogProgress* pDialog = NULL); - std::map<std::string, std::string> GetArtistArtwork(long id, const CArtist *artist = NULL); + /*! \brief Search for art for an artist + Look for art for an artist. Checks the artist structure for thumbs, and checks + the artist path (if non-empty) for artist/folder tbns, etc. + \param artist [in] an artist + */ + std::map<std::string, std::string> GetArtistArtwork(const CArtist& artist); protected: virtual void Process(); - int RetrieveMusicInfo(CFileItemList& items, const CStdString& strDirectory); + + /*! \brief Scan in the ID3/Ogg/FLAC tags for a bunch of FileItems + Given a list of FileItems, scan in the tags for those FileItems + and populate a new FileItemList with the files that were successfully scanned. + Any files which couldn't be scanned (no/bad tags) are discarded in the process. + \param items [in] list of FileItems to scan + \param scannedItems [in] list to populate with the scannedItems + */ + int RetrieveMusicInfo(const CStdString& strDirectory, CFileItemList& items); /*! \brief Scan in the ID3/Ogg/FLAC tags for a bunch of FileItems Given a list of FileItems, scan in the tags for those FileItems @@ -127,6 +191,15 @@ protected: int CountFiles(const CFileItemList& items, bool recursive); int CountFilesRecursively(const CStdString& strPath); + /*! \brief Resolve a MusicBrainzID to a URL + If we have a MusicBrainz ID for an artist or album, + resolve it to an MB URL and set up the scrapers accordingly. + + \param preferredScraper [in] A ScraperPtr to the preferred album/artist scraper. + \param musicBrainzURL [out] will be populated with the MB URL for the artist/album. + */ + bool ResolveMusicBrainz(const CStdString strMusicBrainzID, ADDON::ScraperPtr &preferredScraper, MUSIC_GRABBER::CMusicInfoScraper &musicInfoScraper, CScraperUrl &musicBrainzURL); + protected: bool m_showDialog; CGUIDialogProgressBarHandle* m_handle; @@ -138,12 +211,11 @@ protected: int m_scanType; // 0 - load from files, 1 - albums, 2 - artists CMusicDatabase m_musicDatabase; - std::set<CStdString> m_pathsToScan; - std::set<CAlbum> m_albumsToScan; - std::set<CArtist> m_artistsToScan; - std::set<CStdString> m_pathsToCount; - std::vector<long> m_artistsScanned; - std::vector<long> m_albumsScanned; + std::map<CAlbum, CAlbum> m_albumCache; + std::map<CArtistCredit, CArtist> m_artistCache; + + std::set<std::string> m_pathsToScan; int m_flags; + CThread m_fileCountReader; }; } diff --git a/xbmc/music/karaoke/karaokelyricsmanager.cpp b/xbmc/music/karaoke/karaokelyricsmanager.cpp index 9801bc4add..4c856a551d 100644 --- a/xbmc/music/karaoke/karaokelyricsmanager.cpp +++ b/xbmc/music/karaoke/karaokelyricsmanager.cpp @@ -23,7 +23,7 @@ #include "threads/SystemClock.h" #include "Application.h" #include "guilib/GUIWindowManager.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "karaokelyrics.h" #include "karaokelyricsfactory.h" @@ -64,7 +64,7 @@ bool CKaraokeLyricsManager::Start(const CStdString & strSongPath) Stop(); // shouldn't happen, but... // If disabled by configuration, do nothing - if ( !g_guiSettings.GetBool("karaoke.enabled") ) + if ( !CSettings::Get().GetBool("karaoke.enabled") ) return false; m_Lyrics = CKaraokeLyricsFactory::CreateLyrics( strSongPath ); @@ -144,7 +144,7 @@ void CKaraokeLyricsManager::ProcessSlow() return; } - if ( !m_karaokeSongPlayed || !g_guiSettings.GetBool("karaoke.autopopupselector") ) + if ( !m_karaokeSongPlayed || !CSettings::Get().GetBool("karaoke.autopopupselector") ) return; // If less than 750ms passed return; we're still processing STOP events diff --git a/xbmc/music/karaoke/karaokelyricstext.cpp b/xbmc/music/karaoke/karaokelyricstext.cpp index 64d2e45335..661c3d6c3e 100644 --- a/xbmc/music/karaoke/karaokelyricstext.cpp +++ b/xbmc/music/karaoke/karaokelyricstext.cpp @@ -24,7 +24,7 @@ #include "utils/CharsetConverter.h" #include "settings/DisplaySettings.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "guilib/GUITextLayout.h" #include "guilib/GUIFont.h" #include "karaokelyricstext.h" @@ -68,7 +68,7 @@ CKaraokeLyricsText::CKaraokeLyricsText() m_preambleLayout = 0; m_karaokeFont = 0; - int coloridx = g_guiSettings.GetInt("karaoke.fontcolors"); + int coloridx = CSettings::Get().GetInt("karaoke.fontcolors"); if ( coloridx < KARAOKE_COLOR_START || coloridx >= KARAOKE_COLOR_END ) coloridx = 0; @@ -139,11 +139,11 @@ bool CKaraokeLyricsText::InitGraphics() if ( m_lyrics.empty() ) return false; - CStdString fontPath = "special://xbmc/media/Fonts/" + g_guiSettings.GetString("karaoke.font"); + CStdString fontPath = "special://xbmc/media/Fonts/" + CSettings::Get().GetString("karaoke.font"); m_karaokeFont = g_fontManager.LoadTTF("__karaoke__", fontPath, - m_colorLyrics, 0, g_guiSettings.GetInt("karaoke.fontheight"), FONT_STYLE_BOLD ); + m_colorLyrics, 0, CSettings::Get().GetInt("karaoke.fontheight"), FONT_STYLE_BOLD ); CGUIFont *karaokeBorder = g_fontManager.LoadTTF("__karaokeborder__", fontPath, - m_colorLyrics, 0, g_guiSettings.GetInt("karaoke.fontheight"), FONT_STYLE_BOLD, true ); + m_colorLyrics, 0, CSettings::Get().GetInt("karaoke.fontheight"), FONT_STYLE_BOLD, true ); if ( !m_karaokeFont ) { diff --git a/xbmc/music/karaoke/karaokelyricstext.h b/xbmc/music/karaoke/karaokelyricstext.h index cc402c4b73..d9237b220a 100644 --- a/xbmc/music/karaoke/karaokelyricstext.h +++ b/xbmc/music/karaoke/karaokelyricstext.h @@ -25,6 +25,15 @@ #include "karaokelyrics.h" +// Karaoke colours +// If you want to add more colors, it should be done the following way: +// 1. Increase KARAOKE_COLOR_END +// 2. Add a new color description in language/English/strings.xml in block +// with id 22040 + KARAOKE_COLOR_END value +// 3. Add a new color hex mask into gLyricColors structure in karaoke/karaokelyricstext.cpp +#define KARAOKE_COLOR_START 0 +#define KARAOKE_COLOR_END 4 + class CGUITextLayout; class CGUIFont; diff --git a/xbmc/music/karaoke/karaokelyricstextkar.cpp b/xbmc/music/karaoke/karaokelyricstextkar.cpp index 25ec01a9cc..efc4ea3d13 100644 --- a/xbmc/music/karaoke/karaokelyricstextkar.cpp +++ b/xbmc/music/karaoke/karaokelyricstextkar.cpp @@ -22,7 +22,7 @@ #include "utils/CharsetConverter.h" #include "filesystem/File.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "utils/log.h" #include <math.h> @@ -600,10 +600,10 @@ CStdString CKaraokeLyricsTextKAR::convertText( const char * data ) CStdString strUTF8; // Use some heuristics; need to replace by real detection stuff later - if ( g_charsetConverter.isValidUtf8(data) || g_guiSettings.GetString("karaoke.charset") == "DEFAULT" ) + if ( g_charsetConverter.isValidUtf8(data) || CSettings::Get().GetString("karaoke.charset") == "DEFAULT" ) strUTF8 = data; else - g_charsetConverter.stringCharsetToUtf8( g_guiSettings.GetString("karaoke.charset"), data, strUTF8 ); + g_charsetConverter.stringCharsetToUtf8( CSettings::Get().GetString("karaoke.charset"), data, strUTF8 ); if ( strUTF8.size() == 0 ) strUTF8 = " "; diff --git a/xbmc/music/tags/MusicInfoTag.cpp b/xbmc/music/tags/MusicInfoTag.cpp index 2806ebf570..1a28163f1c 100644 --- a/xbmc/music/tags/MusicInfoTag.cpp +++ b/xbmc/music/tags/MusicInfoTag.cpp @@ -91,9 +91,9 @@ const CMusicInfoTag& CMusicInfoTag::operator =(const CMusicInfoTag& tag) m_genre = tag.m_genre; m_strTitle = tag.m_strTitle; m_strMusicBrainzTrackID = tag.m_strMusicBrainzTrackID; - m_strMusicBrainzArtistID = tag.m_strMusicBrainzArtistID; + m_musicBrainzArtistID = tag.m_musicBrainzArtistID; m_strMusicBrainzAlbumID = tag.m_strMusicBrainzAlbumID; - m_strMusicBrainzAlbumArtistID = tag.m_strMusicBrainzAlbumArtistID; + m_musicBrainzAlbumArtistID = tag.m_musicBrainzAlbumArtistID; m_strMusicBrainzTRMID = tag.m_strMusicBrainzTRMID; m_strComment = tag.m_strComment; m_strLyrics = tag.m_strLyrics; @@ -431,9 +431,9 @@ const CStdString& CMusicInfoTag::GetMusicBrainzTrackID() const return m_strMusicBrainzTrackID; } -const CStdString& CMusicInfoTag::GetMusicBrainzArtistID() const +const std::vector<std::string>& CMusicInfoTag::GetMusicBrainzArtistID() const { - return m_strMusicBrainzArtistID; + return m_musicBrainzArtistID; } const CStdString& CMusicInfoTag::GetMusicBrainzAlbumID() const @@ -441,9 +441,9 @@ const CStdString& CMusicInfoTag::GetMusicBrainzAlbumID() const return m_strMusicBrainzAlbumID; } -const CStdString& CMusicInfoTag::GetMusicBrainzAlbumArtistID() const +const std::vector<std::string>& CMusicInfoTag::GetMusicBrainzAlbumArtistID() const { - return m_strMusicBrainzAlbumArtistID; + return m_musicBrainzAlbumArtistID; } const CStdString& CMusicInfoTag::GetMusicBrainzTRMID() const @@ -456,9 +456,9 @@ void CMusicInfoTag::SetMusicBrainzTrackID(const CStdString& strTrackID) m_strMusicBrainzTrackID=strTrackID; } -void CMusicInfoTag::SetMusicBrainzArtistID(const CStdString& strArtistID) +void CMusicInfoTag::SetMusicBrainzArtistID(const std::vector<std::string>& musicBrainzArtistId) { - m_strMusicBrainzArtistID=strArtistID; + m_musicBrainzArtistID = musicBrainzArtistId; } void CMusicInfoTag::SetMusicBrainzAlbumID(const CStdString& strAlbumID) @@ -466,9 +466,9 @@ void CMusicInfoTag::SetMusicBrainzAlbumID(const CStdString& strAlbumID) m_strMusicBrainzAlbumID=strAlbumID; } -void CMusicInfoTag::SetMusicBrainzAlbumArtistID(const CStdString& strAlbumArtistID) +void CMusicInfoTag::SetMusicBrainzAlbumArtistID(const std::vector<std::string>& musicBrainzAlbumArtistId) { - m_strMusicBrainzAlbumArtistID=strAlbumArtistID; + m_musicBrainzAlbumArtistID = musicBrainzAlbumArtistId; } void CMusicInfoTag::SetMusicBrainzTRMID(const CStdString& strTRMID) @@ -542,10 +542,6 @@ void CMusicInfoTag::SetSong(const CSong& song) SetAlbum(song.strAlbum); SetAlbumArtist(song.albumArtist); SetMusicBrainzTrackID(song.strMusicBrainzTrackID); - SetMusicBrainzArtistID(song.strMusicBrainzArtistID); - SetMusicBrainzAlbumID(song.strMusicBrainzAlbumID); - SetMusicBrainzAlbumArtistID(song.strMusicBrainzAlbumArtistID); - SetMusicBrainzTRMID(song.strMusicBrainzTRMID); SetComment(song.strComment); SetPlayCount(song.iTimesPlayed); SetLastPlayed(song.lastPlayed); @@ -560,7 +556,7 @@ void CMusicInfoTag::SetSong(const CSong& song) m_type = "song"; m_bLoaded = true; m_iTimesPlayed = song.iTimesPlayed; - m_iAlbumId = song.iAlbumId; + m_iAlbumId = song.idAlbum; } void CMusicInfoTag::Serialize(CVariant& value) const @@ -581,9 +577,9 @@ void CMusicInfoTag::Serialize(CVariant& value) const value["loaded"] = m_bLoaded; value["year"] = m_dwReleaseDate.wYear; value["musicbrainztrackid"] = m_strMusicBrainzTrackID; - value["musicbrainzartistid"] = m_strMusicBrainzArtistID; + value["musicbrainzartistid"] = StringUtils::Join(m_musicBrainzArtistID, " / "); value["musicbrainzalbumid"] = m_strMusicBrainzAlbumID; - value["musicbrainzalbumartistid"] = m_strMusicBrainzAlbumArtistID; + value["musicbrainzalbumartistid"] = StringUtils::Join(m_musicBrainzAlbumArtistID, " / "); value["musicbrainztrmid"] = m_strMusicBrainzTRMID; value["comment"] = m_strComment; value["rating"] = (int)(m_rating - '0'); @@ -627,9 +623,9 @@ void CMusicInfoTag::Archive(CArchive& ar) ar << m_bLoaded; ar << m_dwReleaseDate; ar << m_strMusicBrainzTrackID; - ar << m_strMusicBrainzArtistID; + ar << m_musicBrainzArtistID; ar << m_strMusicBrainzAlbumID; - ar << m_strMusicBrainzAlbumArtistID; + ar << m_musicBrainzAlbumArtistID; ar << m_strMusicBrainzTRMID; ar << m_lastPlayed; ar << m_strComment; @@ -655,9 +651,9 @@ void CMusicInfoTag::Archive(CArchive& ar) ar >> m_bLoaded; ar >> m_dwReleaseDate; ar >> m_strMusicBrainzTrackID; - ar >> m_strMusicBrainzArtistID; + ar >> m_musicBrainzArtistID; ar >> m_strMusicBrainzAlbumID; - ar >> m_strMusicBrainzAlbumArtistID; + ar >> m_musicBrainzAlbumArtistID; ar >> m_strMusicBrainzTRMID; ar >> m_lastPlayed; ar >> m_strComment; @@ -681,9 +677,9 @@ void CMusicInfoTag::Clear() m_genre.clear(); m_strTitle.Empty(); m_strMusicBrainzTrackID.Empty(); - m_strMusicBrainzArtistID.Empty(); + m_musicBrainzArtistID.clear(); m_strMusicBrainzAlbumID.Empty(); - m_strMusicBrainzAlbumArtistID.Empty(); + m_musicBrainzAlbumArtistID.clear(); m_strMusicBrainzTRMID.Empty(); m_iDuration = 0; m_iTrack = 0; diff --git a/xbmc/music/tags/MusicInfoTag.h b/xbmc/music/tags/MusicInfoTag.h index 606af584ef..9a5525e2a1 100644 --- a/xbmc/music/tags/MusicInfoTag.h +++ b/xbmc/music/tags/MusicInfoTag.h @@ -38,6 +38,13 @@ class CArtist; #define REPLAY_GAIN_HAS_TRACK_PEAK 4 #define REPLAY_GAIN_HAS_ALBUM_PEAK 8 +enum ReplayGain +{ + REPLAY_GAIN_NONE = 0, + REPLAY_GAIN_ALBUM, + REPLAY_GAIN_TRACK +}; + namespace MUSIC_INFO { class EmbeddedArtInfo @@ -89,9 +96,9 @@ public: void GetReleaseDate(SYSTEMTIME& dateTime) const; CStdString GetYearString() const; const CStdString& GetMusicBrainzTrackID() const; - const CStdString& GetMusicBrainzArtistID() const; + const std::vector<std::string>& GetMusicBrainzArtistID() const; const CStdString& GetMusicBrainzAlbumID() const; - const CStdString& GetMusicBrainzAlbumArtistID() const; + const std::vector<std::string>& GetMusicBrainzAlbumArtistID() const; const CStdString& GetMusicBrainzTRMID() const; const CStdString& GetComment() const; const CStdString& GetLyrics() const; @@ -129,9 +136,9 @@ public: void SetAlbum(const CAlbum& album); void SetSong(const CSong& song); void SetMusicBrainzTrackID(const CStdString& strTrackID); - void SetMusicBrainzArtistID(const CStdString& strArtistID); + void SetMusicBrainzArtistID(const std::vector<std::string>& musicBrainzArtistId); void SetMusicBrainzAlbumID(const CStdString& strAlbumID); - void SetMusicBrainzAlbumArtistID(const CStdString& strAlbumArtistID); + void SetMusicBrainzAlbumArtistID(const std::vector<std::string>& musicBrainzAlbumArtistId); void SetMusicBrainzTRMID(const CStdString& strTRMID); void SetComment(const CStdString& comment); void SetLyrics(const CStdString& lyrics); @@ -184,9 +191,9 @@ protected: std::vector<std::string> m_albumArtist; std::vector<std::string> m_genre; CStdString m_strMusicBrainzTrackID; - CStdString m_strMusicBrainzArtistID; + std::vector<std::string> m_musicBrainzArtistID; CStdString m_strMusicBrainzAlbumID; - CStdString m_strMusicBrainzAlbumArtistID; + std::vector<std::string> m_musicBrainzAlbumArtistID; CStdString m_strMusicBrainzTRMID; CStdString m_strComment; CStdString m_strLyrics; diff --git a/xbmc/music/tags/MusicInfoTagLoaderDatabase.cpp b/xbmc/music/tags/MusicInfoTagLoaderDatabase.cpp index 80a413941e..1f8137fa76 100644 --- a/xbmc/music/tags/MusicInfoTagLoaderDatabase.cpp +++ b/xbmc/music/tags/MusicInfoTagLoaderDatabase.cpp @@ -43,7 +43,7 @@ bool CMusicInfoTagLoaderDatabase::Load(const CStdString& strFileName, CMusicInfo XFILE::MUSICDATABASEDIRECTORY::CDirectoryNode::GetDatabaseInfo(strFileName,param); CSong song; - if (database.GetSongById(param.GetSongId(),song)) + if (database.GetSong(param.GetSongId(),song)) tag.SetSong(song); database.Close(); diff --git a/xbmc/music/tags/TagLoaderTagLib.cpp b/xbmc/music/tags/TagLoaderTagLib.cpp index 6b8830214f..4fb2da3d2a 100644 --- a/xbmc/music/tags/TagLoaderTagLib.cpp +++ b/xbmc/music/tags/TagLoaderTagLib.cpp @@ -263,9 +263,9 @@ bool CTagLoaderTagLib::ParseASF(ASF::Tag *asf, EmbeddedArt *art, CMusicInfoTag& else if (it->first == "WM/ArtistSortOrder") {} // Known unsupported, supress warnings else if (it->first == "WM/Script") {} // Known unsupported, supress warnings else if (it->first == "WM/Year") tag.SetYear(atoi(it->second.front().toString().toCString(true))); - else if (it->first == "MusicBrainz/Artist Id") tag.SetMusicBrainzArtistID(it->second.front().toString().to8Bit(true)); + else if (it->first == "MusicBrainz/Artist Id") tag.SetMusicBrainzArtistID(GetASFStringList(it->second)); else if (it->first == "MusicBrainz/Album Id") tag.SetMusicBrainzAlbumID(it->second.front().toString().to8Bit(true)); - else if (it->first == "MusicBrainz/Album Artist Id") tag.SetMusicBrainzAlbumArtistID(it->second.front().toString().to8Bit(true)); + else if (it->first == "MusicBrainz/Album Artist Id") tag.SetMusicBrainzAlbumArtistID(GetASFStringList(it->second)); else if (it->first == "MusicBrainz/Track Id") tag.SetMusicBrainzTrackID(it->second.front().toString().to8Bit(true)); else if (it->first == "MusicBrainz/Album Status") {} else if (it->first == "MusicBrainz/Album Type") {} @@ -375,9 +375,9 @@ bool CTagLoaderTagLib::ParseID3v2Tag(ID3v2::Tag *id3v2, EmbeddedArt *art, CMusic // First field is the same as the description StringList stringList = frame->fieldList(); stringList.erase(stringList.begin()); - if (frame->description() == "MusicBrainz Artist Id") tag.SetMusicBrainzArtistID(stringList.front().to8Bit(true)); + if (frame->description() == "MusicBrainz Artist Id") tag.SetMusicBrainzArtistID(StringListToVectorString(stringList)); else if (frame->description() == "MusicBrainz Album Id") tag.SetMusicBrainzAlbumID(stringList.front().to8Bit(true)); - else if (frame->description() == "MusicBrainz Album Artist Id") tag.SetMusicBrainzAlbumArtistID(stringList.front().to8Bit(true)); + else if (frame->description() == "MusicBrainz Album Artist Id") tag.SetMusicBrainzAlbumArtistID(StringListToVectorString(stringList)); else if (frame->description() == "replaygain_track_gain") tag.SetReplayGainTrackGain((int)(atof(stringList.front().toCString(true)) * 100 + 0.5)); else if (frame->description() == "replaygain_album_gain") tag.SetReplayGainAlbumGain((int)(atof(stringList.front().toCString(true)) * 100 + 0.5)); else if (frame->description() == "replaygain_track_peak") tag.SetReplayGainTrackPeak((float)atof(stringList.front().toCString(true))); @@ -477,8 +477,8 @@ bool CTagLoaderTagLib::ParseAPETag(APE::Tag *ape, EmbeddedArt *art, CMusicInfoTa else if (it->first == "REPLAYGAIN_ALBUM_GAIN") tag.SetReplayGainAlbumGain((int)(atof(it->second.toString().toCString(true)) * 100 + 0.5)); else if (it->first == "REPLAYGAIN_TRACK_PEAK") tag.SetReplayGainTrackPeak((float)atof(it->second.toString().toCString(true))); else if (it->first == "REPLAYGAIN_ALBUM_PEAK") tag.SetReplayGainAlbumPeak((float)atof(it->second.toString().toCString(true))); - else if (it->first == "MUSICBRAINZ_ARTISTID") tag.SetMusicBrainzArtistID(it->second.toString().to8Bit(true)); - else if (it->first == "MUSICBRAINZ_ALBUMARTISTID") tag.SetMusicBrainzAlbumArtistID(it->second.toString().to8Bit(true)); + else if (it->first == "MUSICBRAINZ_ARTISTID") tag.SetMusicBrainzArtistID(StringListToVectorString(it->second.toStringList())); + else if (it->first == "MUSICBRAINZ_ALBUMARTISTID") tag.SetMusicBrainzAlbumArtistID(StringListToVectorString(it->second.toStringList())); else if (it->first == "MUSICBRAINZ_ALBUMID") tag.SetMusicBrainzAlbumID(it->second.toString().to8Bit(true)); else if (it->first == "MUSICBRAINZ_TRACKID") tag.SetMusicBrainzTrackID(it->second.toString().to8Bit(true)); else if (g_advancedSettings.m_logLevel == LOG_LEVEL_MAX) @@ -517,8 +517,8 @@ bool CTagLoaderTagLib::ParseXiphComment(Ogg::XiphComment *xiph, EmbeddedArt *art else if (it->first == "REPLAYGAIN_ALBUM_GAIN") tag.SetReplayGainAlbumGain((int)(atof(it->second.front().toCString(true)) * 100 + 0.5)); else if (it->first == "REPLAYGAIN_TRACK_PEAK") tag.SetReplayGainTrackPeak((float)atof(it->second.front().toCString(true))); else if (it->first == "REPLAYGAIN_ALBUM_PEAK") tag.SetReplayGainAlbumPeak((float)atof(it->second.front().toCString(true))); - else if (it->first == "MUSICBRAINZ_ARTISTID") tag.SetMusicBrainzArtistID(it->second.front().to8Bit(true)); - else if (it->first == "MUSICBRAINZ_ALBUMARTISTID") tag.SetMusicBrainzAlbumArtistID(it->second.front().to8Bit(true)); + else if (it->first == "MUSICBRAINZ_ARTISTID") tag.SetMusicBrainzArtistID(StringListToVectorString(it->second)); + else if (it->first == "MUSICBRAINZ_ALBUMARTISTID") tag.SetMusicBrainzAlbumArtistID(StringListToVectorString(it->second)); else if (it->first == "MUSICBRAINZ_ALBUMID") tag.SetMusicBrainzAlbumID(it->second.front().to8Bit(true)); else if (it->first == "MUSICBRAINZ_TRACKID") tag.SetMusicBrainzTrackID(it->second.front().to8Bit(true)); else if (it->first == "RATING") @@ -599,9 +599,9 @@ bool CTagLoaderTagLib::ParseMP4Tag(MP4::Tag *mp4, EmbeddedArt *art, CMusicInfoTa else if (it->first == "disk") tag.SetPartOfSet(it->second.toIntPair().first); else if (it->first == "\251day") tag.SetYear(it->second.toStringList().front().toInt()); else if (it->first == "----:com.apple.iTunes:MusicBrainz Artist Id") - tag.SetMusicBrainzArtistID(it->second.toStringList().front().to8Bit(true)); + tag.SetMusicBrainzArtistID(StringListToVectorString(it->second.toStringList())); else if (it->first == "----:com.apple.iTunes:MusicBrainz Album Artist Id") - tag.SetMusicBrainzAlbumArtistID(it->second.toStringList().front().to8Bit(true)); + tag.SetMusicBrainzAlbumArtistID(StringListToVectorString(it->second.toStringList())); else if (it->first == "----:com.apple.iTunes:MusicBrainz Album Id") tag.SetMusicBrainzAlbumID(it->second.toStringList().front().to8Bit(true)); else if (it->first == "----:com.apple.iTunes:MusicBrainz Track Id") diff --git a/xbmc/music/windows/GUIWindowMusicBase.cpp b/xbmc/music/windows/GUIWindowMusicBase.cpp index 3c8fbd6bbb..8b4f0dfd3c 100644 --- a/xbmc/music/windows/GUIWindowMusicBase.cpp +++ b/xbmc/music/windows/GUIWindowMusicBase.cpp @@ -55,10 +55,9 @@ #include "filesystem/File.h" #include "profiles/ProfilesManager.h" #include "storage/MediaManager.h" -#include "settings/Settings.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" #include "settings/MediaSettings.h" +#include "settings/Settings.h" #include "guilib/LocalizeStrings.h" #include "utils/TimeUtils.h" #include "utils/log.h" @@ -146,10 +145,10 @@ bool CGUIWindowMusicBase::OnMessage(CGUIMessage& message) // save current window, unless the current window is the music playlist window if (GetID() != WINDOW_MUSIC_PLAYLIST && - g_guiSettings.GetInt("mymusic.startwindow") != GetID()) + CSettings::Get().GetInt("mymusic.startwindow") != GetID()) { - g_guiSettings.SetInt("mymusic.startwindow", GetID()); - g_settings.Save(); + CSettings::Get().SetInt("mymusic.startwindow", GetID()); + CSettings::Get().Save(); } return true; @@ -175,11 +174,11 @@ bool CGUIWindowMusicBase::OnMessage(CGUIMessage& message) if (nWindow == GetID()) return true; - g_guiSettings.SetInt("mymusic.startwindow", nWindow); - g_settings.Save(); + CSettings::Get().SetInt("mymusic.startwindow", nWindow); + CSettings::Get().Save(); g_windowManager.ChangeActiveWindow(nWindow); - CGUIMessage msg2(GUI_MSG_SETFOCUS, g_guiSettings.GetInt("mymusic.startwindow"), CONTROL_BTNTYPE); + CGUIMessage msg2(GUI_MSG_SETFOCUS, CSettings::Get().GetInt("mymusic.startwindow"), CONTROL_BTNTYPE); g_windowManager.SendMessage(msg2); return true; @@ -207,7 +206,7 @@ bool CGUIWindowMusicBase::OnMessage(CGUIMessage& message) // or be at the files window and have file deletion enabled else if (GetID() == WINDOW_MUSIC_FILES && - g_guiSettings.GetBool("filelists.allowfiledeletion")) + CSettings::Get().GetBool("filelists.allowfiledeletion")) { OnDeleteItem(iItem); } @@ -307,149 +306,107 @@ void CGUIWindowMusicBase::OnInfo(CFileItem *pItem, bool bShowInfo) // this function called from outside this window - make sure the database is open m_musicdatabase.Open(); - CStdString strPath = pItem->GetPath(); - - // Try to find an album to lookup from the current item - CAlbum album; - CArtist artist; - bool foundAlbum = false; - - album.idAlbum = -1; - // we have a folder if (pItem->IsMusicDb()) { CQueryParams params; CDirectoryNode::GetDatabaseInfo(pItem->GetPath(), params); if (params.GetAlbumId() == -1) - { // artist lookup - m_musicdatabase.GetArtistInfo(params.GetArtistId(), artist); - } + ShowArtistInfo(pItem); else - { // album lookup - m_musicdatabase.GetAlbumInfo(params.GetAlbumId(), album, NULL); + ShowAlbumInfo(pItem); - // we're going to need it's path as well (we assume that there's only one) - this is for - // assigning thumbs to folders, and obtaining the local folder.jpg - m_musicdatabase.GetAlbumPath(album.idAlbum, strPath); - } + if (m_dlgProgress && bShowInfo) + m_dlgProgress->Close(); + return; } - else - { // from filemode, so find the albums in the folder - CFileItemList items; - GetDirectory(strPath, items); - // show dialog box indicating we're searching the album name - if (m_dlgProgress && bShowInfo) - { - m_dlgProgress->SetHeading(185); - m_dlgProgress->SetLine(0, 501); - m_dlgProgress->SetLine(1, ""); - m_dlgProgress->SetLine(2, ""); - m_dlgProgress->StartModal(); - m_dlgProgress->Progress(); - if (m_dlgProgress->IsCanceled()) - { - m_musicdatabase.Close(); - return; - } - } - // check the first song we find in the folder, and grab it's album info - for (int i = 0; i < items.Size() && !foundAlbum; i++) + CFileItemList items; + GetDirectory(pItem->GetPath(), items); + + // show dialog box indicating we're searching the album name + if (m_dlgProgress && bShowInfo) + { + m_dlgProgress->SetHeading(185); + m_dlgProgress->SetLine(0, 501); + m_dlgProgress->SetLine(1, ""); + m_dlgProgress->SetLine(2, ""); + m_dlgProgress->StartModal(); + m_dlgProgress->Progress(); + if (m_dlgProgress->IsCanceled()) { - CFileItemPtr pItem = items[i]; - pItem->LoadMusicTag(); - if (pItem->HasMusicInfoTag() && pItem->GetMusicInfoTag()->Loaded() && - !pItem->GetMusicInfoTag()->GetAlbum().IsEmpty()) - { - // great, have a song - use it. - CSong song(*pItem->GetMusicInfoTag()); - // this function won't be needed if/when the tag has idSong information - if (!m_musicdatabase.GetAlbumFromSong(song, album)) - { // album isn't in the database - construct it from the tag info we have - CMusicInfoTag *tag = pItem->GetMusicInfoTag(); - album.strAlbum = tag->GetAlbum(); - album.artist = tag->GetAlbumArtist().empty() ? tag->GetArtist() : tag->GetAlbumArtist(); - album.idAlbum = -1; // the -1 indicates it's not in the database - } - foundAlbum = true; - } + return; } - if (!foundAlbum) + } + + // check the first song we find in the folder, and grab it's album info + for (int i = 0; i < items.Size(); i++) + { + CFileItemPtr pItem = items[i]; + pItem->LoadMusicTag(); + if (pItem->HasMusicInfoTag() && pItem->GetMusicInfoTag()->Loaded() && + !pItem->GetMusicInfoTag()->GetAlbum().IsEmpty()) { - CLog::Log(LOGINFO, "%s called on a folder containing no songs with tag info - nothing can be done", __FUNCTION__); + ShowAlbumInfo(pItem.get()); if (m_dlgProgress && bShowInfo) m_dlgProgress->Close(); - m_musicdatabase.Close(); - return; } - - if (m_dlgProgress && bShowInfo) - m_dlgProgress->Close(); } - if (album.idAlbum == -1 && foundAlbum == false) - ShowArtistInfo(artist, pItem->GetPath(), bShowInfo); - else - ShowAlbumInfo(album, strPath, bShowInfo); - m_musicdatabase.Close(); -} - -void CGUIWindowMusicBase::OnManualAlbumInfo() -{ - CAlbum album; - album.idAlbum = -1; // not in the db - if (!CGUIKeyboardFactory::ShowAndGetInput(album.strAlbum, g_localizeStrings.Get(16011), false)) - return; - - CStdString strArtist = StringUtils::Join(album.artist, g_advancedSettings.m_musicItemSeparator); - if (!CGUIKeyboardFactory::ShowAndGetInput(strArtist, g_localizeStrings.Get(16025), false)) - return; - - ShowAlbumInfo(album,"",true); + CLog::Log(LOGINFO, "%s called on a folder containing no songs with tag info - nothing can be done", __FUNCTION__); + if (m_dlgProgress && bShowInfo) + m_dlgProgress->Close(); } -void CGUIWindowMusicBase::ShowArtistInfo(const CArtist& artist, const CStdString& path, bool bShowInfo /* = true */) +void CGUIWindowMusicBase::ShowArtistInfo(const CFileItem *pItem, bool bShowInfo /* = true */) { - bool saveDb = artist.idArtist != -1; - if (!CProfilesManager::Get().GetCurrentProfile().canWriteDatabases() && !g_passwordManager.bMasterUser) - saveDb = false; - + CQueryParams params; + CDirectoryNode::GetDatabaseInfo(pItem->GetPath(), params); CMusicArtistInfo artistInfo; while (1) { - if (!m_musicdatabase.HasArtistInfo(artist.idArtist) || - !m_musicdatabase.GetArtistInfo(artist.idArtist, artistInfo.GetArtist())) + // Check if we have the information in the database first + if (!m_musicdatabase.HasArtistInfo(params.GetArtistId()) || + !m_musicdatabase.GetArtistInfo(params.GetArtistId(), artistInfo.GetArtist())) { + if (!CProfilesManager::Get().GetCurrentProfile().canWriteDatabases() && !g_passwordManager.bMasterUser) + break; // should display a dialog saying no permissions + if (g_application.IsMusicScanning()) { CGUIDialogOK::ShowAndGetInput(189, 14057, 0, 0); break; } - if (!FindArtistInfo(artist.strArtist, artistInfo, bShowInfo ? SELECTION_ALLOWED : SELECTION_AUTO)) - break; + // show dialog box indicating we're searching the album + if (m_dlgProgress && bShowInfo) + { + m_dlgProgress->SetHeading(21889); + m_dlgProgress->SetLine(0, pItem->GetMusicInfoTag()->GetArtist()); + m_dlgProgress->SetLine(1, ""); + m_dlgProgress->SetLine(2, ""); + m_dlgProgress->StartModal(); + } - if (!artistInfo.Loaded()) + CMusicInfoScanner scanner; + if (scanner.UpdateDatabaseArtistInfo(pItem->GetPath(), artistInfo, bShowInfo) != INFO_ADDED || !artistInfo.Loaded()) { - // Failed to download album info CGUIDialogOK::ShowAndGetInput(21889, 0, 20199, 0); break; } - - if (saveDb) - m_musicdatabase.SetArtistInfo(artist.idArtist, artistInfo.GetArtist()); } CGUIDialogMusicInfo *pDlgArtistInfo = (CGUIDialogMusicInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_INFO); if (pDlgArtistInfo) { - pDlgArtistInfo->SetArtist(artistInfo.GetArtist(), path); + CStdString strPath; + m_musicdatabase.GetArtistPath(params.GetArtistId(), strPath); + pDlgArtistInfo->SetArtist(artistInfo.GetArtist(), strPath); pDlgArtistInfo->DoModal(); if (pDlgArtistInfo->NeedRefresh()) { - m_musicdatabase.DeleteArtistInfo(artist.idArtist); + m_musicdatabase.DeleteArtistInfo(params.GetArtistId()); continue; } else if (pDlgArtistInfo->HasUpdatedThumb()) @@ -463,56 +420,59 @@ void CGUIWindowMusicBase::ShowArtistInfo(const CArtist& artist, const CStdString m_dlgProgress->Close(); } -void CGUIWindowMusicBase::ShowAlbumInfo(const CAlbum& album, const CStdString& path, bool bShowInfo /* = true */) +void CGUIWindowMusicBase::ShowAlbumInfo(const CFileItem *pItem, bool bShowInfo /* = true */) { - bool saveDb = album.idAlbum != -1; - if (!CProfilesManager::Get().GetCurrentProfile().canWriteDatabases() && !g_passwordManager.bMasterUser) - saveDb = false; - + CQueryParams params; + CDirectoryNode::GetDatabaseInfo(pItem->GetPath(), params); CMusicAlbumInfo albumInfo; while (1) { - if (!m_musicdatabase.HasAlbumInfo(album.idAlbum) || - !m_musicdatabase.GetAlbumInfo(album.idAlbum, albumInfo.GetAlbum(), &albumInfo.GetAlbum().songs)) + if (!m_musicdatabase.HasAlbumInfo(params.GetAlbumId()) || + !m_musicdatabase.GetAlbumInfo(params.GetAlbumId(), albumInfo.GetAlbum(), &albumInfo.GetAlbum().songs)) { + if (!CProfilesManager::Get().GetCurrentProfile().canWriteDatabases() && !g_passwordManager.bMasterUser) + break; // should display a dialog saying no permissions + if (g_application.IsMusicScanning()) { CGUIDialogOK::ShowAndGetInput(189, 14057, 0, 0); break; } - if (!FindAlbumInfo(album.strAlbum, - StringUtils::Join(album.artist, g_advancedSettings.m_musicItemSeparator), - albumInfo, - bShowInfo ? SELECTION_ALLOWED : SELECTION_AUTO)) - break; - - if (!albumInfo.Loaded()) + // show dialog box indicating we're searching the album + if (m_dlgProgress && bShowInfo) + { + m_dlgProgress->SetHeading(185); + m_dlgProgress->SetLine(0, pItem->GetMusicInfoTag()->GetAlbum()); + m_dlgProgress->SetLine(1, StringUtils::Join(pItem->GetMusicInfoTag()->GetAlbumArtist(), g_advancedSettings.m_musicItemSeparator)); + m_dlgProgress->SetLine(2, ""); + m_dlgProgress->StartModal(); + } + + CMusicInfoScanner scanner; + if (scanner.UpdateDatabaseAlbumInfo(pItem->GetPath(), albumInfo, bShowInfo) != INFO_ADDED || !albumInfo.Loaded()) { CGUIDialogOK::ShowAndGetInput(185, 0, 500, 0); break; } - - albumInfo.GetAlbum().strAlbum = album.strAlbum; - - if (saveDb) - m_musicdatabase.SetAlbumInfo(album.idAlbum, albumInfo.GetAlbum(), albumInfo.GetSongs()); } CGUIDialogMusicInfo *pDlgAlbumInfo = (CGUIDialogMusicInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_INFO); if (pDlgAlbumInfo) { - pDlgAlbumInfo->SetAlbum(albumInfo.GetAlbum(), path); + CStdString strPath; + m_musicdatabase.GetAlbumPath(params.GetAlbumId(), strPath); + pDlgAlbumInfo->SetAlbum(albumInfo.GetAlbum(), strPath); pDlgAlbumInfo->DoModal(); if (pDlgAlbumInfo->NeedRefresh()) { - m_musicdatabase.DeleteAlbumInfo(album.idAlbum); + m_musicdatabase.DeleteAlbumInfo(params.GetAlbumId()); continue; } else if (pDlgAlbumInfo->HasUpdatedThumb()) { - UpdateThumb(album, path); + UpdateThumb(albumInfo.GetAlbum(), strPath); } } break; @@ -708,108 +668,11 @@ void CGUIWindowMusicBase::UpdateButtons() g_windowManager.SendMessage(msg2); // Select the current window as default item - CONTROL_SELECT_ITEM(CONTROL_BTNTYPE, g_guiSettings.GetInt("mymusic.startwindow") - WINDOW_MUSIC_FILES); + CONTROL_SELECT_ITEM(CONTROL_BTNTYPE, CSettings::Get().GetInt("mymusic.startwindow") - WINDOW_MUSIC_FILES); CGUIMediaWindow::UpdateButtons(); } -bool CGUIWindowMusicBase::FindAlbumInfo(const CStdString& strAlbum, const CStdString& strArtist, CMusicAlbumInfo& album, ALLOW_SELECTION allowSelection) -{ - // show dialog box indicating we're searching the album - if (m_dlgProgress && allowSelection != SELECTION_AUTO) - { - m_dlgProgress->SetHeading(185); - m_dlgProgress->SetLine(0, strAlbum); - m_dlgProgress->SetLine(1, strArtist); - m_dlgProgress->SetLine(2, ""); - m_dlgProgress->StartModal(); - } - - CMusicInfoScanner scanner; - CStdString strPath; - CStdString strTempAlbum(strAlbum); - CStdString strTempArtist(strArtist); - long idAlbum = m_musicdatabase.GetAlbumByName(strAlbum,strArtist); - strPath.Format("musicdb://albums/%d/",idAlbum); - - bool bCanceled(false); - bool needsRefresh(true); - do - { - if (!scanner.DownloadAlbumInfo(strPath,strTempArtist,strTempAlbum,bCanceled,album,m_dlgProgress)) - { - if (bCanceled) - return false; - if (m_dlgProgress && allowSelection != SELECTION_AUTO) - { - if (!CGUIKeyboardFactory::ShowAndGetInput(strTempAlbum, g_localizeStrings.Get(16011), false)) - return false; - - if (!CGUIKeyboardFactory::ShowAndGetInput(strTempArtist, g_localizeStrings.Get(16025), false)) - return false; - } - else - needsRefresh = false; - } - else - needsRefresh = false; - } - while (needsRefresh || bCanceled); - - // Read the album information from the database if we are dealing with a DB album. - if (idAlbum != -1) - m_musicdatabase.GetAlbumInfo(idAlbum,album.GetAlbum(),&album.GetAlbum().songs); - - album.SetLoaded(true); - return true; -} - -bool CGUIWindowMusicBase::FindArtistInfo(const CStdString& strArtist, CMusicArtistInfo& artist, ALLOW_SELECTION allowSelection) -{ - // show dialog box indicating we're searching the album - if (m_dlgProgress && allowSelection != SELECTION_AUTO) - { - m_dlgProgress->SetHeading(21889); - m_dlgProgress->SetLine(0, strArtist); - m_dlgProgress->SetLine(1, ""); - m_dlgProgress->SetLine(2, ""); - m_dlgProgress->StartModal(); - } - - CMusicInfoScanner scanner; - CStdString strPath; - CStdString strTempArtist(strArtist); - long idArtist = m_musicdatabase.GetArtistByName(strArtist); - strPath.Format("musicdb://artists/%u/",idArtist); - - bool bCanceled(false); - bool needsRefresh(true); - do - { - if (!scanner.DownloadArtistInfo(strPath,strTempArtist,bCanceled,m_dlgProgress)) - { - if (bCanceled) - return false; - if (m_dlgProgress && allowSelection != SELECTION_AUTO) - { - if (!CGUIKeyboardFactory::ShowAndGetInput(strTempArtist, g_localizeStrings.Get(16025), false)) - return false; - } - else - needsRefresh = false; - } - else - needsRefresh = false; - } - while (needsRefresh || bCanceled); - - if (!m_musicdatabase.GetArtistInfo(idArtist,artist.GetArtist())) - return false; - - artist.SetLoaded(); - return true; -} - void CGUIWindowMusicBase::GetContextButtons(int itemNumber, CContextButtons &buttons) { CFileItemPtr item; @@ -1095,7 +958,7 @@ bool CGUIWindowMusicBase::OnPlayMedia(int iItem) // turned on, but we still want to use the playlist player in order to handle more queued items // following etc. // Karaoke items also can be added in runtime (while the song is played), so it should be queued too. - if ( (g_guiSettings.GetBool("musicplayer.queuebydefault") && g_windowManager.GetActiveWindow() != WINDOW_MUSIC_PLAYLIST_EDITOR) + if ( (CSettings::Get().GetBool("musicplayer.queuebydefault") && g_windowManager.GetActiveWindow() != WINDOW_MUSIC_PLAYLIST_EDITOR) || pItem->IsKaraoke() ) { // TODO: Should the playlist be cleared if nothing is already playing? @@ -1157,18 +1020,8 @@ void CGUIWindowMusicBase::UpdateThumb(const CAlbum &album, const CStdString &pat CFileItemList items; GetDirectory(albumPath, items); OnRetrieveMusicInfo(items); - VECSONGS songs; - for (int i = 0; i < items.Size(); i++) - { - CFileItemPtr item = items[i]; - if (item->HasMusicInfoTag() && item->GetMusicInfoTag()->Loaded()) - { - CSong song(*item->GetMusicInfoTag()); - songs.push_back(song); - } - } VECALBUMS albums; - CMusicInfoScanner::CategoriseAlbums(songs, albums); + CMusicInfoScanner::FileItemsToAlbums(items, albums); if (albums.size() == 1) { // set as folder thumb as well CThumbLoader::SetCachedImage(items, "thumb", albumPath); @@ -1189,7 +1042,7 @@ void CGUIWindowMusicBase::UpdateThumb(const CAlbum &album, const CStdString &pat void CGUIWindowMusicBase::OnRetrieveMusicInfo(CFileItemList& items) { if (items.GetFolderCount()==items.Size() || items.IsMusicDb() || - (!g_guiSettings.GetBool("musicfiles.usetags") && !items.IsCDDA())) + (!CSettings::Get().GetBool("musicfiles.usetags") && !items.IsCDDA())) { return; } @@ -1289,15 +1142,20 @@ bool CGUIWindowMusicBase::CanContainFilter(const CStdString &strDirectory) const void CGUIWindowMusicBase::OnInitWindow() { CGUIMediaWindow::OnInitWindow(); - if (CMediaSettings::Get().GetMusicNeedsUpdate() == 27 && !g_application.IsMusicScanning() && + if (CMediaSettings::Get().GetMusicNeedsUpdate() == 35 && !g_application.IsMusicScanning() && g_infoManager.GetLibraryBool(LIBRARY_HAS_MUSIC)) { // rescan of music library required if (CGUIDialogYesNo::ShowAndGetInput(799, 800, 801, -1)) { - g_application.StartMusicScan("", CMusicInfoScanner::SCAN_RESCAN); + int flags = CMusicInfoScanner::SCAN_RESCAN; + if (CSettings::Get().GetBool("musiclibrary.downloadinfo")) + flags |= CMusicInfoScanner::SCAN_ONLINE; + if (CSettings::Get().GetBool("musiclibrary.backgroundupdate")) + flags |= CMusicInfoScanner::SCAN_BACKGROUND; + g_application.StartMusicScan("", flags); CMediaSettings::Get().SetMusicNeedsUpdate(0); // once is enough (user may interrupt, but that's up to them) - g_settings.Save(); + CSettings::Get().Save(); } } } diff --git a/xbmc/music/windows/GUIWindowMusicBase.h b/xbmc/music/windows/GUIWindowMusicBase.h index c2e6b8ff35..2b86799f07 100644 --- a/xbmc/music/windows/GUIWindowMusicBase.h +++ b/xbmc/music/windows/GUIWindowMusicBase.h @@ -85,15 +85,14 @@ protected: void OnInfoAll(int iItem, bool bCurrent=false, bool refresh=false); virtual void OnQueueItem(int iItem); enum ALLOW_SELECTION { SELECTION_ALLOWED = 0, SELECTION_AUTO, SELECTION_FORCED }; - bool FindAlbumInfo(const CStdString& strAlbum, const CStdString& strArtist, MUSIC_GRABBER::CMusicAlbumInfo& album, ALLOW_SELECTION allowSelection); - bool FindArtistInfo(const CStdString& strArtist, MUSIC_GRABBER::CMusicArtistInfo& artist, ALLOW_SELECTION allowSelection); + bool FindAlbumInfo(const CFileItem* album, MUSIC_GRABBER::CMusicAlbumInfo& albumInfo, ALLOW_SELECTION allowSelection); + bool FindArtistInfo(const CFileItem* artist, MUSIC_GRABBER::CMusicArtistInfo& artistInfo, ALLOW_SELECTION allowSelection); - void ShowAlbumInfo(const CAlbum& album, const CStdString& path, bool bShowInfo = true); - void ShowArtistInfo(const CArtist& artist, const CStdString& path, bool bShowInfo = true); + void ShowAlbumInfo(const CFileItem *pItem, bool bShowInfo = true); + void ShowArtistInfo(const CFileItem *pItem, bool bShowInfo = true); void ShowSongInfo(CFileItem* pItem); void UpdateThumb(const CAlbum &album, const CStdString &path); - void OnManualAlbumInfo(); void OnRipTrack(int iItem); void OnSearch(); virtual void LoadPlayList(const CStdString& strPlayList); @@ -101,7 +100,7 @@ protected: typedef std::vector <CFileItem*>::iterator ivecItems; ///< CFileItem* vector Iterator CGUIDialogProgress* m_dlgProgress; ///< Progress dialog - // member variables to save frequently used g_guiSettings (which is slow) + // member variables to save frequently used CSettings (which is slow) bool m_hideExtensions; CMusicDatabase m_musicdatabase; MUSIC_INFO::CMusicInfoLoader m_musicInfoLoader; diff --git a/xbmc/music/windows/GUIWindowMusicNav.cpp b/xbmc/music/windows/GUIWindowMusicNav.cpp index d334ea6d81..9442a2f944 100644 --- a/xbmc/music/windows/GUIWindowMusicNav.cpp +++ b/xbmc/music/windows/GUIWindowMusicNav.cpp @@ -46,7 +46,6 @@ #include "ApplicationMessenger.h" #include "settings/Settings.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" #include "guilib/LocalizeStrings.h" #include "utils/log.h" #include "utils/StringUtils.h" @@ -103,7 +102,7 @@ bool CGUIWindowMusicNav::OnMessage(CGUIMessage& message) // is this the first time the window is opened? if (m_vecItems->GetPath() == "?" && message.GetStringParam().IsEmpty()) - message.SetStringParam(g_guiSettings.GetString("mymusic.defaultlibview")); + message.SetStringParam(CSettings::Get().GetString("mymusic.defaultlibview")); DisplayEmptyDatabaseMessage(false); // reset message state @@ -148,11 +147,6 @@ bool CGUIWindowMusicNav::OnMessage(CGUIMessage& message) } UpdateButtons(); } - else if (iControl == CONTROL_BTNMANUALINFO) - { - OnManualAlbumInfo(); - return true; - } else if (iControl == CONTROL_SEARCH) { if (m_searchWithEdit) @@ -482,9 +476,9 @@ void CGUIWindowMusicNav::GetContextButtons(int itemNumber, CContextButtons &butt nodetype == NODE_TYPE_OVERVIEW || nodetype == NODE_TYPE_TOP100)) { - if (!item->GetPath().Equals(g_guiSettings.GetString("mymusic.defaultlibview"))) + if (!item->GetPath().Equals(CSettings::Get().GetString("mymusic.defaultlibview").c_str())) buttons.Add(CONTEXT_BUTTON_SET_DEFAULT, 13335); // set default - if (strcmp(g_guiSettings.GetString("mymusic.defaultlibview"), "")) + if (strcmp(CSettings::Get().GetString("mymusic.defaultlibview").c_str(), "")) buttons.Add(CONTEXT_BUTTON_CLEAR_DEFAULT, 13403); // clear default } NODE_TYPE childtype = dir.GetDirectoryChildType(item->GetPath()); @@ -621,13 +615,13 @@ bool CGUIWindowMusicNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button) } case CONTEXT_BUTTON_SET_DEFAULT: - g_guiSettings.SetString("mymusic.defaultlibview", GetQuickpathName(item->GetPath())); - g_settings.Save(); + CSettings::Get().SetString("mymusic.defaultlibview", GetQuickpathName(item->GetPath())); + CSettings::Get().Save(); return true; case CONTEXT_BUTTON_CLEAR_DEFAULT: - g_guiSettings.SetString("mymusic.defaultlibview", ""); - g_settings.Save(); + CSettings::Get().SetString("mymusic.defaultlibview", ""); + CSettings::Get().Save(); return true; case CONTEXT_BUTTON_GO_TO_ARTIST: diff --git a/xbmc/music/windows/GUIWindowMusicPlaylist.cpp b/xbmc/music/windows/GUIWindowMusicPlaylist.cpp index 536f7b0275..f6b292e7f6 100644 --- a/xbmc/music/windows/GUIWindowMusicPlaylist.cpp +++ b/xbmc/music/windows/GUIWindowMusicPlaylist.cpp @@ -33,9 +33,8 @@ #include "GUIUserMessages.h" #include "Favourites.h" #include "profiles/ProfilesManager.h" -#include "settings/Settings.h" -#include "settings/GUISettings.h" #include "settings/MediaSettings.h" +#include "settings/Settings.h" #include "guilib/LocalizeStrings.h" #include "utils/StringUtils.h" #include "utils/log.h" @@ -140,7 +139,7 @@ bool CGUIWindowMusicPlayList::OnMessage(CGUIMessage& message) { g_playlistPlayer.SetShuffle(PLAYLIST_MUSIC, !(g_playlistPlayer.IsShuffled(PLAYLIST_MUSIC))); CMediaSettings::Get().SetMusicPlaylistShuffled(g_playlistPlayer.IsShuffled(PLAYLIST_MUSIC)); - g_settings.Save(); + CSettings::Get().Save(); UpdateButtons(); Refresh(); } @@ -190,7 +189,7 @@ bool CGUIWindowMusicPlayList::OnMessage(CGUIMessage& message) // save settings CMediaSettings::Get().SetMusicPlaylistRepeat(g_playlistPlayer.GetRepeat(PLAYLIST_MUSIC) == PLAYLIST::REPEAT_ALL); - g_settings.Save(); + CSettings::Get().Save(); UpdateButtons(); } @@ -285,11 +284,10 @@ void CGUIWindowMusicPlayList::SavePlayList() if (CGUIKeyboardFactory::ShowAndGetInput(strNewFileName, g_localizeStrings.Get(16012), false)) { // need 2 rename it - CStdString strFolder, strPath; - URIUtils::AddFileToFolder(g_guiSettings.GetString("system.playlistspath"), "music", strFolder); - strNewFileName= CUtil::MakeLegalFileName( strNewFileName ); + CStdString strFolder = URIUtils::AddFileToFolder(CSettings::Get().GetString("system.playlistspath"), "music"); + strNewFileName = CUtil::MakeLegalFileName(strNewFileName); strNewFileName += ".m3u"; - URIUtils::AddFileToFolder(strFolder, strNewFileName, strPath); + CStdString strPath = URIUtils::AddFileToFolder(strFolder, strNewFileName); // get selected item int iItem = m_viewControl.GetSelectedItem(); @@ -449,12 +447,12 @@ void CGUIWindowMusicPlayList::OnItemLoaded(CFileItem* pItem) if (pItem->HasMusicInfoTag() && pItem->GetMusicInfoTag()->Loaded()) { // set label 1+2 from tags if (m_guiState.get()) m_hideExtensions = m_guiState->HideExtensions(); - CStdString strTrackLeft=g_guiSettings.GetString("musicfiles.nowplayingtrackformat"); + CStdString strTrackLeft=CSettings::Get().GetString("musicfiles.nowplayingtrackformat"); if (strTrackLeft.IsEmpty()) - strTrackLeft = g_guiSettings.GetString("musicfiles.trackformat"); - CStdString strTrackRight=g_guiSettings.GetString("musicfiles.nowplayingtrackformatright"); + strTrackLeft = CSettings::Get().GetString("musicfiles.trackformat"); + CStdString strTrackRight=CSettings::Get().GetString("musicfiles.nowplayingtrackformatright"); if (strTrackRight.IsEmpty()) - strTrackRight = g_guiSettings.GetString("musicfiles.trackformatright"); + strTrackRight = CSettings::Get().GetString("musicfiles.trackformatright"); CLabelFormatter formatter(strTrackLeft, strTrackRight); formatter.FormatLabels(pItem); } // if (pItem->m_musicInfoTag.Loaded()) diff --git a/xbmc/music/windows/GUIWindowMusicPlaylistEditor.cpp b/xbmc/music/windows/GUIWindowMusicPlaylistEditor.cpp index 78f612281c..2716a50234 100644 --- a/xbmc/music/windows/GUIWindowMusicPlaylistEditor.cpp +++ b/xbmc/music/windows/GUIWindowMusicPlaylistEditor.cpp @@ -32,7 +32,7 @@ #include "guilib/GUIWindowManager.h" #include "guilib/GUIKeyboardFactory.h" #include "FileItem.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "GUIUserMessages.h" #include "guilib/Key.h" #include "guilib/LocalizeStrings.h" @@ -396,9 +396,8 @@ void CGUIWindowMusicPlaylistEditor::OnSavePlaylist() { // save playlist as an .m3u PLAYLIST::CPlayListM3U playlist; playlist.Add(*m_playlist); - CStdString path, strBase; - URIUtils::AddFileToFolder(g_guiSettings.GetString("system.playlistspath"), "music", strBase); - URIUtils::AddFileToFolder(strBase, name + ".m3u", path); + CStdString strBase = URIUtils::AddFileToFolder(CSettings::Get().GetString("system.playlistspath"), "music"); + CStdString path = URIUtils::AddFileToFolder(strBase, name + ".m3u"); playlist.Save(path); m_strLoadedPlaylist = name; } @@ -407,7 +406,7 @@ void CGUIWindowMusicPlaylistEditor::OnSavePlaylist() void CGUIWindowMusicPlaylistEditor::AppendToPlaylist(CFileItemList &newItems) { OnRetrieveMusicInfo(newItems); - FormatItemLabels(newItems, LABEL_MASKS(g_guiSettings.GetString("musicfiles.trackformat"), g_guiSettings.GetString("musicfiles.trackformatright"), "%L", "")); + FormatItemLabels(newItems, LABEL_MASKS(CSettings::Get().GetString("musicfiles.trackformat"), CSettings::Get().GetString("musicfiles.trackformatright"), "%L", "")); m_playlist->Append(newItems); UpdatePlaylist(); } diff --git a/xbmc/music/windows/GUIWindowMusicSongs.cpp b/xbmc/music/windows/GUIWindowMusicSongs.cpp index 376bdd4d49..ee77acecb1 100644 --- a/xbmc/music/windows/GUIWindowMusicSongs.cpp +++ b/xbmc/music/windows/GUIWindowMusicSongs.cpp @@ -31,8 +31,8 @@ #include "FileItem.h" #include "profiles/ProfilesManager.h" #include "storage/MediaManager.h" -#include "settings/GUISettings.h" #include "settings/MediaSourceSettings.h" +#include "settings/Settings.h" #include "guilib/Key.h" #include "guilib/LocalizeStrings.h" #include "utils/log.h" @@ -354,7 +354,7 @@ void CGUIWindowMusicSongs::GetContextButtons(int itemNumber, CContextButtons &bu if (!item->IsParentFolder() && !item->IsReadOnly()) { // either we're at the playlist location or its been explicitly allowed - if (inPlaylists || g_guiSettings.GetBool("filelists.allowfiledeletion")) + if (inPlaylists || CSettings::Get().GetBool("filelists.allowfiledeletion")) { buttons.Add(CONTEXT_BUTTON_DELETE, 117); buttons.Add(CONTEXT_BUTTON_RENAME, 118); diff --git a/xbmc/music/windows/GUIWindowVisualisation.cpp b/xbmc/music/windows/GUIWindowVisualisation.cpp index 7233d14dab..2920f37a54 100644 --- a/xbmc/music/windows/GUIWindowVisualisation.cpp +++ b/xbmc/music/windows/GUIWindowVisualisation.cpp @@ -26,9 +26,8 @@ #include "music/dialogs/GUIDialogVisualisationPresetList.h" #include "guilib/GUIWindowManager.h" #include "guilib/Key.h" -#include "settings/Settings.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" using namespace MUSIC_INFO; @@ -60,7 +59,7 @@ bool CGUIWindowVisualisation::OnAction(const CAction &action) case ACTION_SHOW_INFO: { m_initTimer.Stop(); - g_guiSettings.SetBool("mymusic.songthumbinvis", g_infoManager.ToggleShowInfo()); + CSettings::Get().SetBool("mymusic.songthumbinvis", g_infoManager.ToggleShowInfo()); return true; } break; @@ -71,7 +70,7 @@ bool CGUIWindowVisualisation::OnAction(const CAction &action) case ACTION_SHOW_GUI: // save the settings - g_settings.Save(); + CSettings::Get().Save(); g_windowManager.PreviousWindow(); return true; break; @@ -152,7 +151,7 @@ bool CGUIWindowVisualisation::OnMessage(CGUIMessage& message) case GUI_MSG_WINDOW_DEINIT: { if (IsActive()) // save any changed settings from the OSD - g_settings.Save(); + CSettings::Get().Save(); // check and close any OSD windows CGUIDialogMusicOSD *pOSD = (CGUIDialogMusicOSD *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OSD); if (pOSD && pOSD->IsDialogRunning()) pOSD->Close(true); @@ -177,7 +176,7 @@ bool CGUIWindowVisualisation::OnMessage(CGUIMessage& message) if (g_infoManager.GetCurrentSongTag()) m_tag = *g_infoManager.GetCurrentSongTag(); - if (g_guiSettings.GetBool("mymusic.songthumbinvis")) + if (CSettings::Get().GetBool("mymusic.songthumbinvis")) { // always on m_initTimer.Stop(); } @@ -228,7 +227,7 @@ void CGUIWindowVisualisation::FrameMove() if (m_initTimer.IsRunning() && m_initTimer.GetElapsedSeconds() > (float)g_advancedSettings.m_songInfoDuration) { m_initTimer.Stop(); - if (!g_guiSettings.GetBool("mymusic.songthumbinvis")) + if (!CSettings::Get().GetBool("mymusic.songthumbinvis")) { // reached end of fade in, fade out again g_infoManager.SetShowInfo(false); } diff --git a/xbmc/network/AirPlayServer.cpp b/xbmc/network/AirPlayServer.cpp index c3e2de7b24..f432c97c37 100644 --- a/xbmc/network/AirPlayServer.cpp +++ b/xbmc/network/AirPlayServer.cpp @@ -212,6 +212,14 @@ void CAirPlayServer::StopServer(bool bWait) } } +bool CAirPlayServer::IsRunning() +{ + if (ServerInstance == NULL) + return false; + + return ((CThread*)ServerInstance)->IsRunning(); +} + void CAirPlayServer::AnnounceToClients(int state) { CSingleLock lock (m_connectionLock); diff --git a/xbmc/network/AirPlayServer.h b/xbmc/network/AirPlayServer.h index a830aff78a..0a30eae63f 100644 --- a/xbmc/network/AirPlayServer.h +++ b/xbmc/network/AirPlayServer.h @@ -46,6 +46,7 @@ public: //AirPlayServer impl. static bool StartServer(int port, bool nonlocal); static void StopServer(bool bWait); + static bool IsRunning(); static bool SetCredentials(bool usePassword, const CStdString& password); static bool IsPlaying(){ return m_isPlaying > 0;} static void backupVolume(); diff --git a/xbmc/network/AirTunesServer.cpp b/xbmc/network/AirTunesServer.cpp index 495c97a228..2aa5dd8c20 100644 --- a/xbmc/network/AirTunesServer.cpp +++ b/xbmc/network/AirTunesServer.cpp @@ -54,7 +54,7 @@ using namespace XFILE; using namespace ANNOUNCEMENT; -#if defined(TARGET_WINDOWS) +#if defined(HAVE_LIBSHAIRPLAY) DllLibShairplay *CAirTunesServer::m_pLibShairplay = NULL; #else DllLibShairport *CAirTunesServer::m_pLibShairport = NULL; @@ -132,7 +132,7 @@ void CAirTunesServer::SetCoverArtFromBuffer(const char *buffer, unsigned int siz } } -#if defined(TARGET_WINDOWS) +#if defined(HAVE_LIBSHAIRPLAY) #define RSA_KEY " \ -----BEGIN RSA PRIVATE KEY-----\ MIIEpQIBAAKCAQEA59dE8qLieItsH1WgjrcFRKj6eUWqi+bGLOX1HL3U3GhC/j0Qg90u3sG/1CUt\ @@ -168,6 +168,8 @@ void CAirTunesServer::AudioOutputFunctions::audio_set_coverart(void *cls, void * CAirTunesServer::SetCoverArtFromBuffer((char *)buffer, buflen); } +char *session="XBMC-AirTunes"; + void* CAirTunesServer::AudioOutputFunctions::audio_init(void *cls, int bits, int channels, int samplerate) { XFILE::CPipeFile *pipe=(XFILE::CPipeFile *)cls; @@ -192,12 +194,9 @@ void* CAirTunesServer::AudioOutputFunctions::audio_init(void *cls, int bits, int item.SetPath(pipe->GetName()); item.SetMimeType("audio/x-xbmc-pcm"); - ThreadMessage tMsg2 = { TMSG_GUI_ACTIVATE_WINDOW, WINDOW_VISUALISATION, 0 }; - CApplicationMessenger::Get().SendMessage(tMsg2, true); - CApplicationMessenger::Get().PlayFile(item); - return "XBMC-AirTunes";//session + return session;//session } void CAirTunesServer::AudioOutputFunctions::audio_set_volume(void *cls, void *session, float volume) @@ -257,7 +256,7 @@ void CAirTunesServer::AudioOutputFunctions::audio_destroy(void *cls, void *sess } } -void shairplay_log(int level, const char *msg) +void shairplay_log(void *cls, int level, const char *msg) { int xbmcLevel = LOGINFO; @@ -523,7 +522,7 @@ bool CAirTunesServer::StartServer(int port, bool nonlocal, bool usePassword, con ServerInstance = new CAirTunesServer(port, nonlocal); if (ServerInstance->Initialize(pw)) { -#ifndef TARGET_WINDOWS +#if !defined(HAVE_LIBSHAIRPLAY) ServerInstance->Create(); #endif success = true; @@ -545,7 +544,7 @@ bool CAirTunesServer::StartServer(int port, bool nonlocal, bool usePassword, con txt.push_back(std::make_pair("sm", "false")); txt.push_back(std::make_pair("ss", "16")); txt.push_back(std::make_pair("sr", "44100")); - txt.push_back(std::make_pair("pw", "false")); + txt.push_back(std::make_pair("pw", usePassword?"true":"false")); txt.push_back(std::make_pair("vn", "3")); txt.push_back(std::make_pair("da", "true")); txt.push_back(std::make_pair("vs", "130.14")); @@ -562,7 +561,7 @@ void CAirTunesServer::StopServer(bool bWait) { if (ServerInstance) { -#if !defined(TARGET_WINDOWS) +#if !defined(HAVE_LIBSHAIRPLAY) if (m_pLibShairport->IsLoaded()) { m_pLibShairport->shairport_exit(); @@ -580,10 +579,18 @@ void CAirTunesServer::StopServer(bool bWait) } } + bool CAirTunesServer::IsRunning() + { + if (ServerInstance == NULL) + return false; + + return ((CThread*)ServerInstance)->IsRunning(); + } + CAirTunesServer::CAirTunesServer(int port, bool nonlocal) : CThread("AirTunesServer") { m_port = port; -#if defined(TARGET_WINDOWS) +#if defined(HAVE_LIBSHAIRPLAY) m_pLibShairplay = new DllLibShairplay(); m_pPipe = new XFILE::CPipeFile; #else @@ -594,7 +601,7 @@ CAirTunesServer::CAirTunesServer(int port, bool nonlocal) : CThread("AirTunesSer CAirTunesServer::~CAirTunesServer() { -#if defined(TARGET_WINDOWS) +#if defined(HAVE_LIBSHAIRPLAY) if (m_pLibShairplay->IsLoaded()) { m_pLibShairplay->Unload(); @@ -615,7 +622,7 @@ void CAirTunesServer::Process() { m_bStop = false; -#if !defined(TARGET_WINDOWS) +#if !defined(HAVE_LIBSHAIRPLAY) while (!m_bStop && m_pLibShairport->shairport_is_running()) { m_pLibShairport->shairport_loop(); @@ -629,7 +636,7 @@ bool CAirTunesServer::Initialize(const CStdString &password) Deinitialize(); -#if defined(TARGET_WINDOWS) +#if defined(HAVE_LIBSHAIRPLAY) if (m_pLibShairplay->Load()) { @@ -657,7 +664,7 @@ bool CAirTunesServer::Initialize(const CStdString &password) m_pLibShairplay->raop_set_log_level(m_pRaop, RAOP_LOG_DEBUG); } - m_pLibShairplay->raop_set_log_callback(m_pRaop, shairplay_log); + m_pLibShairplay->raop_set_log_callback(m_pRaop, shairplay_log, NULL); CNetworkInterface *net = g_application.getNetwork().GetFirstConnectedInterface(); @@ -724,7 +731,7 @@ bool CAirTunesServer::Initialize(const CStdString &password) void CAirTunesServer::Deinitialize() { -#if defined(TARGET_WINDOWS) +#if defined(HAVE_LIBSHAIRPLAY) if (m_pLibShairplay && m_pLibShairplay->IsLoaded()) { m_pLibShairplay->raop_stop(m_pRaop); diff --git a/xbmc/network/AirTunesServer.h b/xbmc/network/AirTunesServer.h index b776c46506..531c05e5f0 100644 --- a/xbmc/network/AirTunesServer.h +++ b/xbmc/network/AirTunesServer.h @@ -25,7 +25,7 @@ #ifdef HAS_AIRTUNES -#if defined(TARGET_WINDOWS) +#if defined(HAVE_LIBSHAIRPLAY) #include "DllLibShairplay.h" #else #include "DllLibShairport.h" @@ -53,6 +53,7 @@ public: static bool StartServer(int port, bool nonlocal, bool usePassword, const CStdString &password=""); static void StopServer(bool bWait); + static bool IsRunning(); static void SetMetadataFromBuffer(const char *buffer, unsigned int size); static void SetCoverArtFromBuffer(const char *buffer, unsigned int size); @@ -66,7 +67,7 @@ private: void Deinitialize(); int m_port; -#if defined(TARGET_WINDOWS) +#if defined(HAVE_LIBSHAIRPLAY) static DllLibShairplay *m_pLibShairplay;//the lib raop_t *m_pRaop; XFILE::CPipeFile *m_pPipe; @@ -79,7 +80,7 @@ private: class AudioOutputFunctions { public: -#if defined(TARGET_WINDOWS) +#if defined(HAVE_LIBSHAIRPLAY) static void* audio_init(void *cls, int bits, int channels, int samplerate); static void audio_set_volume(void *cls, void *session, float volume); static void audio_set_metadata(void *cls, void *session, const void *buffer, int buflen); diff --git a/xbmc/network/DllLibShairplay.h b/xbmc/network/DllLibShairplay.h index 2c110245ac..af00ad3574 100644 --- a/xbmc/network/DllLibShairplay.h +++ b/xbmc/network/DllLibShairplay.h @@ -35,7 +35,7 @@ public: virtual raop_t * raop_init(int max_clients, raop_callbacks_t *callbacks, const char *pemkey)=0; virtual raop_t * raop_init_from_keyfile(int max_clients, raop_callbacks_t *callbacks, const char *keyfile)=0; virtual void raop_set_log_level(raop_t *raop, int level)=0; - virtual void raop_set_log_callback(raop_t *raop, raop_log_callback_t callback)=0; + virtual void raop_set_log_callback(raop_t *raop, raop_log_callback_t callback, void *cls)=0; virtual int raop_is_running(raop_t *raop)=0; virtual int raop_start(raop_t *raop, unsigned short *port, const char *hwaddr, int hwaddrlen, const char *password)=0; virtual void raop_stop(raop_t *raop)=0; @@ -48,7 +48,7 @@ class DllLibShairplay : public DllDynamic, DllLibShairplayInterface DEFINE_METHOD3(raop_t *, raop_init, (int p1, raop_callbacks_t *p2, const char *p3)) DEFINE_METHOD3(raop_t *, raop_init_from_keyfile, (int p1, raop_callbacks_t *p2, const char *p3)) DEFINE_METHOD2(void, raop_set_log_level, (raop_t *p1, int p2)) - DEFINE_METHOD2(void, raop_set_log_callback, (raop_t *p1, raop_log_callback_t p2)) + DEFINE_METHOD3(void, raop_set_log_callback, (raop_t *p1, raop_log_callback_t p2, void *p3)) DEFINE_METHOD1(int, raop_is_running, (raop_t *p1)) DEFINE_METHOD5(int, raop_start, (raop_t *p1, unsigned short *p2, const char *p3, int p4, const char *p5)) DEFINE_METHOD1(void, raop_stop, (raop_t *p1)) diff --git a/xbmc/network/EventClient.h b/xbmc/network/EventClient.h index cc1fe527fa..d58a5c7e4d 100644 --- a/xbmc/network/EventClient.h +++ b/xbmc/network/EventClient.h @@ -25,7 +25,7 @@ #include "threads/CriticalSection.h" #include "Socket.h" #include "EventPacket.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include <list> #include <map> @@ -158,8 +158,8 @@ namespace EVENTCLIENT void RefreshSettings() { - m_iRepeatDelay = g_guiSettings.GetInt("services.esinitialdelay"); - m_iRepeatSpeed = g_guiSettings.GetInt("services.escontinuousdelay"); + m_iRepeatDelay = CSettings::Get().GetInt("services.esinitialdelay"); + m_iRepeatSpeed = CSettings::Get().GetInt("services.escontinuousdelay"); } SOCKETS::CAddress& Address() diff --git a/xbmc/network/EventServer.cpp b/xbmc/network/EventServer.cpp index d9691b68c4..c07ccffeb7 100644 --- a/xbmc/network/EventServer.cpp +++ b/xbmc/network/EventServer.cpp @@ -85,13 +85,11 @@ void CEventServer::StartServer() return; // set default port - string port = (const char*)g_guiSettings.GetString("services.esport"); - assert(port.length()); - m_iPort = atoi(port.c_str()); + m_iPort = CSettings::Get().GetInt("services.esport"); assert(m_iPort <= 65535 && m_iPort >= 1); // max clients - m_iMaxClients = g_guiSettings.GetInt("services.esmaxclients"); + m_iMaxClients = CSettings::Get().GetInt("services.esmaxclients"); if (m_iMaxClients < 0) { CLog::Log(LOGERROR, "ES: Invalid maximum number of clients specified %d", m_iMaxClients); @@ -156,7 +154,6 @@ void CEventServer::Run() CAddress any_addr; CSocketListener listener; int packetSize = 0; - std::vector<std::pair<std::string, std::string> > txt; CLog::Log(LOGNOTICE, "ES: Starting UDP Event server on %s:%d", any_addr.Address(), m_iPort); @@ -178,7 +175,7 @@ void CEventServer::Run() } // bind to IP and start listening on port - int port_range = g_guiSettings.GetInt("services.esportrange"); + int port_range = CSettings::Get().GetInt("services.esportrange"); if (port_range < 1 || port_range > 100) { CLog::Log(LOGERROR, "ES: Invalid port range specified %d, defaulting to 10", port_range); @@ -191,6 +188,7 @@ void CEventServer::Run() } // publish service + std::vector<std::pair<std::string, std::string> > txt; CZeroconf::GetInstance()->PublishService("servers.eventserver", "_xbmc-events._udp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), diff --git a/xbmc/network/Makefile.in b/xbmc/network/Makefile.in index e2ffb0bce9..bf9bed9330 100644 --- a/xbmc/network/Makefile.in +++ b/xbmc/network/Makefile.in @@ -1,17 +1,18 @@ -SRCS = cddb.cpp -SRCS += DNSNameCache.cpp -SRCS += EventClient.cpp -SRCS += EventPacket.cpp -SRCS += EventServer.cpp -SRCS += GUIDialogAccessPoints.cpp -SRCS += GUIDialogNetworkSetup.cpp -SRCS += Network.cpp -SRCS += Socket.cpp -SRCS += TCPServer.cpp -SRCS += UdpClient.cpp -SRCS += WebServer.cpp -SRCS += ZeroconfBrowser.cpp -SRCS += Zeroconf.cpp +SRCS = cddb.cpp \ + DNSNameCache.cpp \ + EventClient.cpp \ + EventPacket.cpp \ + EventServer.cpp \ + GUIDialogAccessPoints.cpp \ + GUIDialogNetworkSetup.cpp \ + Network.cpp \ + NetworkServices.cpp \ + Socket.cpp \ + TCPServer.cpp \ + UdpClient.cpp \ + WebServer.cpp \ + ZeroconfBrowser.cpp \ + Zeroconf.cpp \ ifeq (@USE_AIRPLAY@, 1) SRCS += AirPlayServer.cpp diff --git a/xbmc/network/Network.cpp b/xbmc/network/Network.cpp index 02dabe3ed5..8beca4803b 100644 --- a/xbmc/network/Network.cpp +++ b/xbmc/network/Network.cpp @@ -18,19 +18,15 @@ * */ -#include "system.h" -#include "Network.h" -#include "Application.h" -#include "ApplicationMessenger.h" -#include "utils/RssManager.h" -#include "utils/log.h" -#include "guilib/LocalizeStrings.h" -#include "dialogs/GUIDialogKaiToast.h" - #include <netinet/in.h> #include <sys/socket.h> #include <arpa/inet.h> +#include "Network.h" +#include "ApplicationMessenger.h" +#include "network/NetworkServices.h" +#include "utils/log.h" + using namespace std; /* slightly modified in_ether taken from the etherboot project (http://sourceforge.net/projects/etherboot) */ @@ -128,7 +124,6 @@ CStdString CNetwork::GetHostName(void) return CStdString(hostName); } - CNetworkInterface* CNetwork::GetFirstConnectedInterface() { vector<CNetworkInterface*>& ifaces = GetInterfaceList(); @@ -204,19 +199,16 @@ void CNetwork::NetworkMessage(EMESSAGE message, int param) switch( message ) { case SERVICES_UP: - { CLog::Log(LOGDEBUG, "%s - Starting network services",__FUNCTION__); - StartServices(); - } - break; + CNetworkServices::Get().Start(); + break; + case SERVICES_DOWN: - { CLog::Log(LOGDEBUG, "%s - Signaling network services to stop",__FUNCTION__); - StopServices(false); //tell network services to stop, but don't wait for them yet + CNetworkServices::Get().Stop(false); // tell network services to stop, but don't wait for them yet CLog::Log(LOGDEBUG, "%s - Waiting for network services to stop",__FUNCTION__); - StopServices(true); //wait for network services to stop - } - break; + CNetworkServices::Get().Stop(true); // wait for network services to stop + break; } } @@ -276,58 +268,3 @@ bool CNetwork::WakeOnLan(const char* mac) CLog::Log(LOGINFO, "%s - Magic packet send to '%s'", __FUNCTION__, mac); return true; } - -void CNetwork::StartServices() -{ -#ifdef HAS_WEB_SERVER - if (!g_application.StartWebServer()) - CGUIDialogKaiToast::QueueNotification("DefaultIconWarning.png", g_localizeStrings.Get(33101), g_localizeStrings.Get(33100)); -#endif -#ifdef HAS_UPNP - g_application.StartUPnP(); -#endif -#ifdef HAS_EVENT_SERVER - if (!g_application.StartEventServer()) - CGUIDialogKaiToast::QueueNotification("DefaultIconWarning.png", g_localizeStrings.Get(33102), g_localizeStrings.Get(33100)); -#endif -#ifdef HAS_JSONRPC - if (!g_application.StartJSONRPCServer()) - CGUIDialogKaiToast::QueueNotification("DefaultIconWarning.png", g_localizeStrings.Get(33103), g_localizeStrings.Get(33100)); -#endif -#ifdef HAS_ZEROCONF - g_application.StartZeroconf(); -#endif -#ifdef HAS_AIRPLAY - g_application.StartAirplayServer(); -#endif - CRssManager::Get().Start(); -} - -void CNetwork::StopServices(bool bWait) -{ - if (bWait) - { -#ifdef HAS_UPNP - g_application.StopUPnP(bWait); -#endif -#ifdef HAS_ZEROCONF - g_application.StopZeroconf(); -#endif -#ifdef HAS_WEB_SERVER - g_application.StopWebServer(); -#endif - // smb.Deinit(); if any file is open over samba this will break. - - CRssManager::Get().Stop(); - } - -#ifdef HAS_EVENT_SERVER - g_application.StopEventServer(bWait, false); -#endif -#ifdef HAS_JSONRPC - g_application.StopJSONRPCServer(bWait); -#endif -#if defined(HAS_AIRPLAY) || defined(HAS_AIRTUNES) - g_application.StopAirplayServer(bWait); -#endif -} diff --git a/xbmc/network/Network.h b/xbmc/network/Network.h index 3f2bdf3bf9..3500b70aaf 100644 --- a/xbmc/network/Network.h +++ b/xbmc/network/Network.h @@ -1,6 +1,4 @@ -#ifndef NETWORK_H_ -#define NETWORK_H_ - +#pragma once /* * Copyright (C) 2005-2013 Team XBMC * http://www.xbmc.org @@ -22,9 +20,12 @@ */ #include <vector> -#include "utils/StdString.h" + #include "system.h" +#include "settings/ISettingCallback.h" +#include "utils/StdString.h" + enum EncMode { ENC_NONE = 0, ENC_WEP = 1, ENC_WPA = 2, ENC_WPA2 = 3 }; enum NetworkAssignment { NETWORK_DASH = 0, NETWORK_DHCP = 1, NETWORK_STATIC = 2, NETWORK_DISABLED = 3 }; @@ -74,8 +75,6 @@ public: virtual void SetSettings(NetworkAssignment& assignment, CStdString& ipAddress, CStdString& networkMask, CStdString& defaultGateway, CStdString& essId, CStdString& key, EncMode& encryptionMode) = 0; }; - - class CNetwork { public: @@ -122,9 +121,9 @@ public: static int ParseHex(char *str, unsigned char *addr); }; + #ifdef HAS_LINUX_NETWORK #include "linux/NetworkLinux.h" #else #include "windows/NetworkWin32.h" #endif -#endif diff --git a/xbmc/network/NetworkServices.cpp b/xbmc/network/NetworkServices.cpp new file mode 100644 index 0000000000..c4489d6d7a --- /dev/null +++ b/xbmc/network/NetworkServices.cpp @@ -0,0 +1,931 @@ +/* + * Copyright (C) 2005-2012 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 "NetworkServices.h" +#include "Application.h" +#include "ApplicationMessenger.h" +#include "GUIInfoManager.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" + +#ifdef HAS_AIRPLAY +#include "network/AirPlayServer.h" +#endif // HAS_AIRPLAY + +#ifdef HAS_AIRTUNES +#include "network/AirTunesServer.h" +#endif // HAS_AIRTUNES + +#ifdef HAS_EVENT_SERVER +#include "network/EventServer.h" +#endif // HAS_EVENT_SERVER + +#ifdef HAS_JSONRPC +#include "interfaces/json-rpc/JSONRPC.h" +#include "network/TCPServer.h" +#endif + +#ifdef HAS_ZEROCONF +#include "network/Zeroconf.h" +#endif // HAS_ZEROCONF + +#ifdef HAS_UPNP +#include "network/upnp/UPnP.h" +#endif // HAS_UPNP + +#ifdef HAS_WEB_SERVER +#include "network/WebServer.h" +#include "network/httprequesthandler/HTTPImageHandler.h" +#include "network/httprequesthandler/HTTPVfsHandler.h" +#ifdef HAS_JSONRPC +#include "network/httprequesthandler/HTTPJsonRpcHandler.h" +#endif // HAS_JSONRPC +#ifdef HAS_WEB_INTERFACE +#include "network/httprequesthandler/HTTPWebinterfaceHandler.h" +#include "network/httprequesthandler/HTTPWebinterfaceAddonsHandler.h" +#endif // HAS_WEB_INTERFACE +#endif // HAS_WEB_SERVER + +#if defined(TARGET_DARWIN_OSX) +#include "osx/XBMCHelper.h" +#endif + +#include "settings/AdvancedSettings.h" +#include "settings/Settings.h" +#include "utils/log.h" +#include "utils/RssManager.h" + +using namespace std; +#ifdef HAS_JSONRPC +using namespace JSONRPC; +#endif // HAS_JSONRPC +#ifdef HAS_EVENT_SERVER +using namespace EVENTSERVER; +#endif // HAS_EVENT_SERVER +#ifdef HAS_UPNP +using namespace UPNP; +#endif // HAS_UPNP + +CNetworkServices::CNetworkServices() + : +#ifdef HAS_WEB_SERVER + m_webserver(*new CWebServer), + m_httpImageHandler(*new CHTTPImageHandler), + m_httpVfsHandler(*new CHTTPVfsHandler) +#ifdef HAS_JSONRPC + , m_httpJsonRpcHandler(*new CHTTPJsonRpcHandler) +#endif // HAS_JSONRPC +#ifdef HAS_WEB_INTERFACE + , m_httpWebinterfaceHandler(*new CHTTPWebinterfaceHandler) + , m_httpWebinterfaceAddonsHandler(*new CHTTPWebinterfaceAddonsHandler) +#endif // HAS_WEB_INTERFACE +#endif // HAS_WEB_SERVER +{ +#ifdef HAS_WEB_SERVER + CWebServer::RegisterRequestHandler(&m_httpImageHandler); + CWebServer::RegisterRequestHandler(&m_httpVfsHandler); +#ifdef HAS_JSONRPC + CWebServer::RegisterRequestHandler(&m_httpJsonRpcHandler); +#endif // HAS_JSONRPC +#ifdef HAS_WEB_INTERFACE + CWebServer::RegisterRequestHandler(&m_httpWebinterfaceAddonsHandler); + CWebServer::RegisterRequestHandler(&m_httpWebinterfaceHandler); +#endif // HAS_WEB_INTERFACE +#endif // HAS_WEB_SERVER +} + +CNetworkServices::~CNetworkServices() +{ +#ifdef HAS_WEB_SERVER + CWebServer::UnregisterRequestHandler(&m_httpImageHandler); + delete &m_httpImageHandler; + CWebServer::UnregisterRequestHandler(&m_httpVfsHandler); + delete &m_httpVfsHandler; +#ifdef HAS_JSONRPC + CWebServer::UnregisterRequestHandler(&m_httpJsonRpcHandler); + delete &m_httpJsonRpcHandler; + CJSONRPC::Cleanup(); +#endif // HAS_JSONRPC +#ifdef HAS_WEB_INTERFACE + CWebServer::UnregisterRequestHandler(&m_httpWebinterfaceAddonsHandler); + delete &m_httpWebinterfaceAddonsHandler; + CWebServer::UnregisterRequestHandler(&m_httpWebinterfaceHandler); + delete &m_httpWebinterfaceHandler; +#endif // HAS_WEB_INTERFACE + delete &m_webserver; +#endif // HAS_WEB_SERVER +} + +CNetworkServices& CNetworkServices::Get() +{ + static CNetworkServices sNetworkServices; + return sNetworkServices; +} + +bool CNetworkServices::OnSettingChanging(const CSetting *setting) +{ + if (setting == NULL) + return false; + + const std::string &settingId = setting->GetId(); +#ifdef HAS_WEB_SERVER + if (settingId == "services.webserver" || + settingId == "services.webserverport") + { + if (IsWebserverRunning() && !StopWebserver()) + return false; + + if (CSettings::Get().GetBool("services.webserver")) + { + if (!StartWebserver()) + { + CGUIDialogOK::ShowAndGetInput(g_localizeStrings.Get(33101), "", g_localizeStrings.Get(33100), ""); + return false; + } + } + } + else if (settingId == "services.esport" || + settingId == "services.webserverport") + return ValidatePort(((CSettingInt*)setting)->GetValue()); + else +#endif // HAS_WEB_SERVER + +#ifdef HAS_ZEROCONF + if (settingId == "services.zeroconf") + { + if (((CSettingBool*)setting)->GetValue()) + return StartZeroconf(); +#ifdef HAS_AIRPLAY + else + { + // cannot disable + if (IsAirPlayServerRunning() || IsAirTunesServerRunning()) + { + CGUIDialogOK::ShowAndGetInput(g_localizeStrings.Get(1259), g_localizeStrings.Get(34303), g_localizeStrings.Get(34304), ""); + return false; + } + + return StopZeroconf(); + } +#endif // HAS_AIRPLAY + } + else +#endif // HAS_ZEROCONF + +#ifdef HAS_AIRPLAY + if (settingId == "services.airplay") + { + if (((CSettingBool*)setting)->GetValue()) + { +#ifdef HAS_ZEROCONF + // AirPlay needs zeroconf + if (!CSettings::Get().GetBool("services.zeroconf")) + { + CGUIDialogOK::ShowAndGetInput(g_localizeStrings.Get(1273), g_localizeStrings.Get(33100), g_localizeStrings.Get(34302), ""); + return false; + } +#endif //HAS_ZEROCONF + + if (!StartAirPlayServer()) + { + CGUIDialogOK::ShowAndGetInput(g_localizeStrings.Get(1273), "", g_localizeStrings.Get(33100), ""); + return false; + } + + if (!CAirPlayServer::SetCredentials(CSettings::Get().GetBool("services.useairplaypassword"), + CSettings::Get().GetString("services.airplaypassword"))) + { + CGUIDialogOK::ShowAndGetInput(g_localizeStrings.Get(1273), "", g_localizeStrings.Get(33100), ""); + return false; + } + + if (!StartAirTunesServer()) + { + CGUIDialogOK::ShowAndGetInput(g_localizeStrings.Get(1274), "", g_localizeStrings.Get(33100), ""); + return false; + } + } + else + { + if (!StopAirPlayServer(true) || !StopAirTunesServer(true)) + return false; + } + } + else if (settingId == "services.airplaypassword" || + settingId == "services.useairplaypassword") + { + if (!CSettings::Get().GetBool("services.airplay")) + return false; + + if (!CAirPlayServer::SetCredentials(CSettings::Get().GetBool("services.useairplaypassword"), + CSettings::Get().GetString("services.airplaypassword"))) + return false; + } + else +#endif //HAS_AIRPLAY + +#ifdef HAS_UPNP + if (settingId == "services.upnpserver") + { + if (((CSettingBool*)setting)->GetValue()) + return StartUPnPServer(); + else + return StopUPnPServer(); + } + else if (settingId == "services.upnprenderer") + { + if (((CSettingBool*)setting)->GetValue()) + return StartUPnPRenderer(); + else + return StopUPnPRenderer(); + } + else if (settingId == "services.upnpcontroller") + { + // always stop and restart + StopUPnPClient(); + if (((CSettingBool*)setting)->GetValue()) + return StartUPnPClient(); + } + else +#endif // HAS_UPNP + + if (settingId == "services.esenabled") + { +#ifdef HAS_EVENT_SERVER + if (((CSettingBool*)setting)->GetValue()) + { + if (!StartEventServer()) + { + CGUIDialogOK::ShowAndGetInput(g_localizeStrings.Get(33102), "", g_localizeStrings.Get(33100), ""); + return false; + } + } + else + return StopEventServer(true, true); +#endif // HAS_EVENT_SERVER + +#ifdef HAS_JSONRPC + if (CSettings::Get().GetBool("services.esenabled")) + { + if (!StartJSONRPCServer()) + { + CGUIDialogOK::ShowAndGetInput(g_localizeStrings.Get(33103), "", g_localizeStrings.Get(33100), ""); + return false; + } + } + else + return StopJSONRPCServer(false); +#endif // HAS_JSONRPC + } + else if (settingId == "services.esport") + { +#ifdef HAS_EVENT_SERVER + // restart eventserver without asking user + if (!StopEventServer(true, false)) + return false; + + if (!StartEventServer()) + { + CGUIDialogOK::ShowAndGetInput(g_localizeStrings.Get(33102), "", g_localizeStrings.Get(33100), ""); + return false; + } + +#if defined(TARGET_DARWIN_OSX) + // reconfigure XBMCHelper for port changes + XBMCHelper::GetInstance().Configure(); +#endif // TARGET_DARWIN_OSX +#endif // HAS_EVENT_SERVER + } + else if (settingId == "services.esallinterfaces") + { +#ifdef HAS_EVENT_SERVER + if (CSettings::Get().GetBool("services.esenabled")) + { + if (!StopEventServer(true, true)) + return false; + + if (!StartEventServer()) + { + CGUIDialogOK::ShowAndGetInput(g_localizeStrings.Get(33102), "", g_localizeStrings.Get(33100), ""); + return false; + } + } +#endif // HAS_EVENT_SERVER + +#ifdef HAS_JSONRPC + if (CSettings::Get().GetBool("services.esenabled")) + { + if (!StartJSONRPCServer()) + { + CGUIDialogOK::ShowAndGetInput(g_localizeStrings.Get(33103), "", g_localizeStrings.Get(33100), ""); + return false; + } + } +#endif // HAS_JSONRPC + } + +#ifdef HAS_EVENT_SERVER + else if (settingId == "services.esinitialdelay" || + settingId == "services.escontinuousdelay") + { + if (CSettings::Get().GetBool("services.esenabled")) + return RefreshEventServer(); + } +#endif // HAS_EVENT_SERVER + + return true; +} + +void CNetworkServices::OnSettingChanged(const CSetting *setting) +{ + if (setting == NULL) + return; + + const std::string &settingId = setting->GetId(); +#ifdef HAS_WEB_SERVER + if (settingId == "services.webserverusername" || + settingId == "services.webserverpassword") + { + m_webserver.SetCredentials(CSettings::Get().GetString("services.webserverusername"), + CSettings::Get().GetString("services.webserverpassword")); + } + else +#endif // HAS_WEB_SERVER + if (settingId == "smb.winsserver" || + settingId == "smb.workgroup") + { + // 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(14038, 14039, 14040, -1, -1)) + { + CSettings::Get().Save(); + CApplicationMessenger::Get().RestartApp(); + } + } +} + +void CNetworkServices::Start() +{ + StartZeroconf(); + if (CSettings::Get().GetBool("services.webserver") && !StartWebserver()) + CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Warning, g_localizeStrings.Get(33101), g_localizeStrings.Get(33100)); + StartUPnP(); + if (CSettings::Get().GetBool("services.esenabled") && !StartEventServer()) + CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Warning, g_localizeStrings.Get(33102), g_localizeStrings.Get(33100)); + if (CSettings::Get().GetBool("services.esenabled") && !StartJSONRPCServer()) + CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Warning, g_localizeStrings.Get(33103), g_localizeStrings.Get(33100)); + StartAirPlayServer(); + StartAirTunesServer(); + StartRss(); +} + +void CNetworkServices::Stop(bool bWait) +{ + if (bWait) + { + StopUPnP(bWait); + StopZeroconf(); + StopWebserver(); + StopRss(); + } + + StopEventServer(bWait, false); + StopJSONRPCServer(bWait); + StopAirPlayServer(bWait); + StopAirTunesServer(bWait); +} + +bool CNetworkServices::StartWebserver() +{ +#ifdef HAS_WEB_SERVER + if (!g_application.getNetwork().IsAvailable()) + return false; + + if (!CSettings::Get().GetBool("services.webserver")) + return false; + + int webPort = CSettings::Get().GetInt("services.webserverport"); + if (!ValidatePort(webPort)) + { + CLog::Log(LOGERROR, "Cannot start Web Server on port %i", webPort); + return false; + } + + if (IsWebserverRunning()) + return true; + + CLog::Log(LOGNOTICE, "Webserver: Starting..."); + if (!m_webserver.Start(webPort, CSettings::Get().GetString("services.webserverusername"), CSettings::Get().GetString("services.webserverpassword"))) + return false; + +#ifdef HAS_ZEROCONF + std::vector<std::pair<std::string, std::string> > txt; + // publish web frontend and API services +#ifdef HAS_WEB_INTERFACE + CZeroconf::GetInstance()->PublishService("servers.webserver", "_http._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), webPort, txt); +#endif // HAS_WEB_INTERFACE +#ifdef HAS_JSONRPC + CZeroconf::GetInstance()->PublishService("servers.jsonrpc-http", "_xbmc-jsonrpc-h._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), webPort, txt); +#endif // HAS_JSONRPC +#endif // HAS_ZEROCONF + + return true; +#endif // HAS_WEB_SERVER + return false; +} + +bool CNetworkServices::IsWebserverRunning() +{ +#ifdef HAS_WEB_SERVER + return m_webserver.IsStarted(); +#endif // HAS_WEB_SERVER + return false; +} + +bool CNetworkServices::StopWebserver() +{ +#ifdef HAS_WEB_SERVER + if (!IsWebserverRunning()) + return true; + + CLog::Log(LOGNOTICE, "Webserver: Stopping..."); + if (!m_webserver.Stop() || m_webserver.IsStarted()) + { + CLog::Log(LOGWARNING, "Webserver: Failed to stop."); + return false; + } + + CLog::Log(LOGNOTICE, "Webserver: Stopped..."); +#ifdef HAS_ZEROCONF +#ifdef HAS_WEB_INTERFACE + CZeroconf::GetInstance()->RemoveService("servers.webserver"); +#endif // HAS_WEB_INTERFACE +#ifdef HAS_JSONRPC + CZeroconf::GetInstance()->RemoveService("servers.jsonrpc-http"); +#endif // HAS_JSONRPC +#endif // HAS_ZEROCONF + + return true; +#endif // HAS_WEB_SERVER + return false; +} + +bool CNetworkServices::StartAirPlayServer() +{ +#ifdef HAS_AIRPLAY + if (!g_application.getNetwork().IsAvailable() || !CSettings::Get().GetBool("services.airplay")) + return false; + + if (IsAirPlayServerRunning()) + return true; + + if (!CAirPlayServer::StartServer(g_advancedSettings.m_airPlayPort, true)) + return false; + + if (!CAirPlayServer::SetCredentials(CSettings::Get().GetBool("services.useairplaypassword"), + CSettings::Get().GetString("services.airplaypassword"))) + return false; + +#ifdef HAS_ZEROCONF + std::vector<std::pair<std::string, std::string> > txt; + CNetworkInterface* iface = g_application.getNetwork().GetFirstConnectedInterface(); + txt.push_back(make_pair("deviceid", iface != NULL ? iface->GetMacAddress() : "FF:FF:FF:FF:FF:F2")); + txt.push_back(make_pair("features", "0x77")); + txt.push_back(make_pair("model", "Xbmc,1")); + txt.push_back(make_pair("srcvers", AIRPLAY_SERVER_VERSION_STR)); + CZeroconf::GetInstance()->PublishService("servers.airplay", "_airplay._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), g_advancedSettings.m_airPlayPort, txt); +#endif // HAS_ZEROCONF + + return true; +#endif // HAS_AIRPLAY + return false; +} + +bool CNetworkServices::IsAirPlayServerRunning() +{ +#ifdef HAS_AIRPLAY + return CAirPlayServer::IsRunning(); +#endif // HAS_AIRPLAY + return false; +} + +bool CNetworkServices::StopAirPlayServer(bool bWait) +{ +#ifdef HAS_AIRPLAY + if (!IsAirPlayServerRunning()) + return true; + + CAirPlayServer::StopServer(bWait); + +#ifdef HAS_ZEROCONF + CZeroconf::GetInstance()->RemoveService("servers.airplay"); +#endif // HAS_ZEROCONF + + return true; +#endif // HAS_AIRPLAY + return false; +} + +bool CNetworkServices::StartAirTunesServer() +{ +#ifdef HAS_AIRTUNES + if (!g_application.getNetwork().IsAvailable() || !CSettings::Get().GetBool("services.airplay")) + return false; + + if (IsAirTunesServerRunning()) + return true; + + if (!CAirTunesServer::StartServer(g_advancedSettings.m_airTunesPort, true, + CSettings::Get().GetBool("services.useairplaypassword"), + CSettings::Get().GetString("services.airplaypassword"))) + { + CLog::Log(LOGERROR, "Failed to start AirTunes Server"); + return false; + } + + return true; +#endif // HAS_AIRTUNES + return false; +} + +bool CNetworkServices::IsAirTunesServerRunning() +{ +#ifdef HAS_AIRTUNES + return CAirTunesServer::IsRunning(); +#endif // HAS_AIRTUNES + return false; +} + +bool CNetworkServices::StopAirTunesServer(bool bWait) +{ +#ifdef HAS_AIRTUNES + if (!IsAirTunesServerRunning()) + return true; + + CAirTunesServer::StopServer(bWait); + return true; +#endif // HAS_AIRTUNES + return false; +} + +bool CNetworkServices::StartJSONRPCServer() +{ +#ifdef HAS_JSONRPC + if (!CSettings::Get().GetBool("services.esenabled")) + return false; + + if (IsJSONRPCServerRunning()) + return true; + + if (!CTCPServer::StartServer(g_advancedSettings.m_jsonTcpPort, CSettings::Get().GetBool("services.esallinterfaces"))) + return false; + +#ifdef HAS_ZEROCONF + std::vector<std::pair<std::string, std::string> > txt; + CZeroconf::GetInstance()->PublishService("servers.jsonrpc-tpc", "_xbmc-jsonrpc._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), g_advancedSettings.m_jsonTcpPort, txt); +#endif // HAS_ZEROCONF + + return true; +#endif // HAS_JSONRPC + return false; +} + +bool CNetworkServices::IsJSONRPCServerRunning() +{ +#ifdef HAS_JSONRPC + return CTCPServer::IsRunning(); +#endif // HAS_JSONRPC + return false; +} + +bool CNetworkServices::StopJSONRPCServer(bool bWait) +{ +#ifdef HAS_JSONRPC + if (!IsJSONRPCServerRunning()) + return true; + + CTCPServer::StopServer(bWait); + +#ifdef HAS_ZEROCONF + CZeroconf::GetInstance()->RemoveService("servers.jsonrpc-tcp"); +#endif // HAS_ZEROCONF + + return true; +#endif // HAS_JSONRPC + return false; +} + +bool CNetworkServices::StartEventServer() +{ +#ifdef HAS_EVENT_SERVER + if (!CSettings::Get().GetBool("services.esenabled")) + return false; + + if (IsEventServerRunning()) + return true; + + CEventServer* server = CEventServer::GetInstance(); + if (!server) + { + CLog::Log(LOGERROR, "ES: Out of memory"); + return false; + } + + CLog::Log(LOGNOTICE, "ES: Starting event server"); + server->StartServer(); + + return true; +#endif // HAS_EVENT_SERVER + return false; +} + +bool CNetworkServices::IsEventServerRunning() +{ +#ifdef HAS_EVENT_SERVER + return CEventServer::GetInstance()->Running(); +#endif // HAS_EVENT_SERVER + return false; +} + +bool CNetworkServices::StopEventServer(bool bWait, bool promptuser) +{ +#ifdef HAS_EVENT_SERVER + if (!IsEventServerRunning()) + return true; + + CEventServer* server = CEventServer::GetInstance(); + if (!server) + { + CLog::Log(LOGERROR, "ES: Out of memory"); + return false; + } + + if (promptuser) + { + if (server->GetNumberOfClients() > 0) + { + bool cancelled = false; + if (!CGUIDialogYesNo::ShowAndGetInput(13140, 13141, 13142, 20022, + -1, -1, cancelled, 10000) + || cancelled) + { + CLog::Log(LOGNOTICE, "ES: Not stopping event server"); + return false; + } + } + CLog::Log(LOGNOTICE, "ES: Stopping event server with confirmation"); + + CEventServer::GetInstance()->StopServer(true); + } + else + { + if (!bWait) + CLog::Log(LOGNOTICE, "ES: Stopping event server"); + + CEventServer::GetInstance()->StopServer(bWait); + } + + return true; +#endif // HAS_EVENT_SERVER + return false; +} + +bool CNetworkServices::RefreshEventServer() +{ +#ifdef HAS_EVENT_SERVER + if (!CSettings::Get().GetBool("services.esenabled")) + return false; + + if (!IsEventServerRunning()) + return false; + + CEventServer::GetInstance()->RefreshSettings(); + return true; +#endif // HAS_EVENT_SERVER + return false; +} + +bool CNetworkServices::StartUPnP() +{ + bool ret = false; +#ifdef HAS_UPNP + ret |= StartUPnPClient(); + ret |= StartUPnPServer(); + ret |= StartUPnPRenderer(); + return true; +#endif // HAS_UPNP + return ret; +} + +bool CNetworkServices::StopUPnP(bool bWait) +{ +#ifdef HAS_UPNP + if (!CUPnP::IsInstantiated()) + return true; + + CLog::Log(LOGNOTICE, "stopping upnp"); + CUPnP::ReleaseInstance(bWait); + + return true; +#endif // HAS_UPNP + return false; +} + +bool CNetworkServices::StartUPnPClient() +{ +#ifdef HAS_UPNP + if (!CSettings::Get().GetBool("services.upnpcontroller")) + return false; + + CLog::Log(LOGNOTICE, "starting upnp controller"); + CUPnP::GetInstance()->StartClient(); + return IsUPnPClientRunning(); +#endif // HAS_UPNP + return false; +} + +bool CNetworkServices::IsUPnPClientRunning() +{ +#ifdef HAS_UPNP + return CUPnP::GetInstance()->IsClientStarted(); +#endif // HAS_UPNP + return false; +} + +bool CNetworkServices::StopUPnPClient() +{ +#ifdef HAS_UPNP + if (!IsUPnPRendererRunning()) + return true; + + CLog::Log(LOGNOTICE, "stopping upnp client"); + CUPnP::GetInstance()->StopClient(); + + return true; +#endif // HAS_UPNP + return false; +} + +bool CNetworkServices::StartUPnPRenderer() +{ +#ifdef HAS_UPNP + if (!CSettings::Get().GetBool("services.upnprenderer")) + return false; + + CLog::Log(LOGNOTICE, "starting upnp renderer"); + return CUPnP::GetInstance()->StartRenderer(); +#endif // HAS_UPNP + return false; +} + +bool CNetworkServices::IsUPnPRendererRunning() +{ +#ifdef HAS_UPNP + return CUPnP::GetInstance()->IsInstantiated(); +#endif // HAS_UPNP + return false; +} + +bool CNetworkServices::StopUPnPRenderer() +{ +#ifdef HAS_UPNP + if (!IsUPnPRendererRunning()) + return true; + + CLog::Log(LOGNOTICE, "stopping upnp renderer"); + CUPnP::GetInstance()->StopRenderer(); + + return true; +#endif // HAS_UPNP + return false; +} + +bool CNetworkServices::StartUPnPServer() +{ +#ifdef HAS_UPNP + if (!CSettings::Get().GetBool("services.upnpserver")) + return false; + + CLog::Log(LOGNOTICE, "starting upnp server"); + return CUPnP::GetInstance()->StartServer(); +#endif // HAS_UPNP + return false; +} + +bool CNetworkServices::IsUPnPServerRunning() +{ +#ifdef HAS_UPNP + return CUPnP::GetInstance()->IsInstantiated(); +#endif // HAS_UPNP + return false; +} + +bool CNetworkServices::StopUPnPServer() +{ +#ifdef HAS_UPNP + if (!IsUPnPRendererRunning()) + return true; + + CLog::Log(LOGNOTICE, "stopping upnp server"); + CUPnP::GetInstance()->StopServer(); + + return true; +#endif // HAS_UPNP + return false; +} + +bool CNetworkServices::StartRss() +{ + if (IsRssRunning()) + return true; + + CRssManager::Get().Start(); + return true; +} + +bool CNetworkServices::IsRssRunning() +{ + return CRssManager::Get().IsActive(); +} + +bool CNetworkServices::StopRss() +{ + if (!IsRssRunning()) + return true; + + CRssManager::Get().Stop(); + return true; +} + +bool CNetworkServices::StartZeroconf() +{ +#ifdef HAS_ZEROCONF + if (!CSettings::Get().GetBool("services.zeroconf")) + return false; + + if (IsZeroconfRunning()) + return true; + + CLog::Log(LOGNOTICE, "starting zeroconf publishing"); + return CZeroconf::GetInstance()->Start(); +#endif // HAS_ZEROCONF + return false; +} + +bool CNetworkServices::IsZeroconfRunning() +{ +#ifdef HAS_ZEROCONF + return CZeroconf::GetInstance()->IsStarted(); +#endif // HAS_ZEROCONF + return false; +} + +bool CNetworkServices::StopZeroconf() +{ +#ifdef HAS_ZEROCONF + if (!IsZeroconfRunning()) + return true; + + CLog::Log(LOGNOTICE, "stopping zeroconf publishing"); + CZeroconf::GetInstance()->Stop(); + + return true; +#endif // HAS_ZEROCONF + return false; +} + +bool CNetworkServices::ValidatePort(int port) +{ + if (port <= 0 || port > 65535) + return false; + +#ifdef TARGET_LINUX + if (!CUtil::CanBindPrivileged() && (port < 1024 || port > 65535)) + return false; +#endif + + return true; +} diff --git a/xbmc/network/NetworkServices.h b/xbmc/network/NetworkServices.h new file mode 100644 index 0000000000..750df17dd4 --- /dev/null +++ b/xbmc/network/NetworkServices.h @@ -0,0 +1,109 @@ +#pragma once +/* + * Copyright (C) 2013 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" +#include "settings/ISettingCallback.h" + +#ifdef HAS_WEB_SERVER +class CWebServer; +class CHTTPImageHandler; +class CHTTPVfsHandler; +#ifdef HAS_JSONRPC +class CHTTPJsonRpcHandler; +#endif // HAS_JSONRPC +#ifdef HAS_WEB_INTERFACE +class CHTTPWebinterfaceHandler; +class CHTTPWebinterfaceAddonsHandler; +#endif // HAS_WEB_INTERFACE +#endif // HAS_WEB_SERVER + +class CNetworkServices : public ISettingCallback +{ +public: + static CNetworkServices& Get(); + + virtual bool OnSettingChanging(const CSetting *setting); + virtual void OnSettingChanged(const CSetting *setting); + + void Start(); + void Stop(bool bWait); + + bool StartWebserver(); + bool IsWebserverRunning(); + bool StopWebserver(); + + bool StartAirPlayServer(); + bool IsAirPlayServerRunning(); + bool StopAirPlayServer(bool bWait); + bool StartAirTunesServer(); + bool IsAirTunesServerRunning(); + bool StopAirTunesServer(bool bWait); + + bool StartJSONRPCServer(); + bool IsJSONRPCServerRunning(); + bool StopJSONRPCServer(bool bWait); + + bool StartEventServer(); + bool IsEventServerRunning(); + bool StopEventServer(bool bWait, bool promptuser); + bool RefreshEventServer(); + + bool StartUPnP(); + bool StopUPnP(bool bWait); + bool StartUPnPClient(); + bool IsUPnPClientRunning(); + bool StopUPnPClient(); + bool StartUPnPRenderer(); + bool IsUPnPRendererRunning(); + bool StopUPnPRenderer(); + bool StartUPnPServer(); + bool IsUPnPServerRunning(); + bool StopUPnPServer(); + + bool StartRss(); + bool IsRssRunning(); + bool StopRss(); + + bool StartZeroconf(); + bool IsZeroconfRunning(); + bool StopZeroconf(); + +private: + CNetworkServices(); + CNetworkServices(const CNetworkServices&); + CNetworkServices const& operator=(CNetworkServices const&); + virtual ~CNetworkServices(); + + bool ValidatePort(int port); + +#ifdef HAS_WEB_SERVER + CWebServer& m_webserver; + CHTTPImageHandler& m_httpImageHandler; + CHTTPVfsHandler& m_httpVfsHandler; +#ifdef HAS_JSONRPC + CHTTPJsonRpcHandler& m_httpJsonRpcHandler; +#endif +#ifdef HAS_WEB_INTERFACE + CHTTPWebinterfaceHandler& m_httpWebinterfaceHandler; + CHTTPWebinterfaceAddonsHandler& m_httpWebinterfaceAddonsHandler; +#endif +#endif +}; diff --git a/xbmc/network/TCPServer.cpp b/xbmc/network/TCPServer.cpp index ec7d4c7cc7..9aa3894e44 100644 --- a/xbmc/network/TCPServer.cpp +++ b/xbmc/network/TCPServer.cpp @@ -85,6 +85,14 @@ void CTCPServer::StopServer(bool bWait) } } +bool CTCPServer::IsRunning() +{ + if (ServerInstance == NULL) + return false; + + return ((CThread*)ServerInstance)->IsRunning(); +} + CTCPServer::CTCPServer(int port, bool nonlocal) : CThread("TCPServer") { m_port = port; diff --git a/xbmc/network/TCPServer.h b/xbmc/network/TCPServer.h index 5de68e75dc..5fd8ac971f 100644 --- a/xbmc/network/TCPServer.h +++ b/xbmc/network/TCPServer.h @@ -36,6 +36,7 @@ namespace JSONRPC public: static bool StartServer(int port, bool nonlocal); static void StopServer(bool bWait); + static bool IsRunning(); virtual bool PrepareDownload(const char *path, CVariant &details, std::string &protocol); virtual bool Download(const char *path, CVariant &result); diff --git a/xbmc/network/WebServer.cpp b/xbmc/network/WebServer.cpp index 71ce952290..8c2f9e0da2 100644 --- a/xbmc/network/WebServer.cpp +++ b/xbmc/network/WebServer.cpp @@ -20,14 +20,20 @@ #include "WebServer.h" #ifdef HAS_WEB_SERVER +#include "URL.h" +#include "Util.h" +#include "XBDateTime.h" #include "filesystem/File.h" +#include "settings/Settings.h" +#include "threads/SingleLock.h" +#include "utils/Base64.h" #include "utils/log.h" +#include "utils/Mime.h" +#include "utils/StringUtils.h" #include "utils/URIUtils.h" #include "utils/Variant.h" -#include "utils/Base64.h" -#include "threads/SingleLock.h" -#include "XBDateTime.h" -#include "URL.h" + +//#define WEBSERVER_DEBUG #ifdef _WIN32 #pragma comment(lib, "libmicrohttpd.dll.lib") @@ -38,10 +44,24 @@ #define PAGE_FILE_NOT_FOUND "<html><head><title>File not found</title></head><body>File not found</body></html>" #define NOT_SUPPORTED "<html><head><title>Not Supported</title></head><body>The method you are trying to use is not supported by this server</body></html>" +#define CONTENT_RANGE_FORMAT "bytes %" PRId64 "-%" PRId64 "/%" PRId64 + using namespace XFILE; using namespace std; using namespace JSONRPC; +typedef struct { + CFile *file; + HttpRanges ranges; + size_t rangeCount; + int64_t rangesLength; + string boundary; + string boundaryWithHeader; + bool boundaryWritten; + string contentType; + int64_t writePosition; +} HttpFileDownloadContext; + vector<IHTTPRequestHandler *> CWebServer::m_requestHandlers; CWebServer::CWebServer() @@ -75,8 +95,8 @@ int CWebServer::AskForAuthentication(struct MHD_Connection *connection) if (!response) return MHD_NO; - ret = MHD_add_response_header(response, MHD_HTTP_HEADER_WWW_AUTHENTICATE, "Basic realm=XBMC"); - ret |= MHD_add_response_header(response, MHD_HTTP_HEADER_CONNECTION, "close"); + ret = AddHeader(response, MHD_HTTP_HEADER_WWW_AUTHENTICATE, "Basic realm=XBMC"); + ret |= AddHeader(response, MHD_HTTP_HEADER_CONNECTION, "close"); if (!ret) { MHD_destroy_response (response); @@ -322,7 +342,7 @@ int CWebServer::HandleRequest(IHTTPRequestHandler *handler, const HTTPRequest &r multimap<string, string> header = handler->GetHTTPResponseHeaderFields(); for (multimap<string, string>::const_iterator it = header.begin(); it != header.end(); it++) - MHD_add_response_header(response, it->first.c_str(), it->second.c_str()); + AddHeader(response, it->first.c_str(), it->second.c_str()); MHD_queue_response(request.connection, responseCode, response); MHD_destroy_response(response); @@ -348,7 +368,7 @@ int CWebServer::CreateRedirect(struct MHD_Connection *connection, const string & response = MHD_create_response_from_data (0, NULL, MHD_NO, MHD_NO); if (response) { - MHD_add_response_header(response, "Location", strURL.c_str()); + AddHeader(response, "Location", strURL.c_str()); return MHD_YES; } return MHD_NO; @@ -358,92 +378,197 @@ int CWebServer::CreateFileDownloadResponse(struct MHD_Connection *connection, co { CFile *file = new CFile(); +#ifdef WEBSERVER_DEBUG + CLog::Log(LOGDEBUG, "webserver [IN] %s", strURL.c_str()); + multimap<string, string> headers; + if (GetRequestHeaderValues(connection, MHD_HEADER_KIND, headers) > 0) + { + for (multimap<string, string>::const_iterator header = headers.begin(); header != headers.end(); header++) + CLog::Log(LOGDEBUG, "webserver [IN] %s: %s", header->first.c_str(), header->second.c_str()); + } +#endif + if (file->Open(strURL, READ_NO_CACHE)) { bool getData = true; + bool ranged = false; + int64_t fileLength = file->GetLength(); + + // try to get the file's last modified date + CDateTime lastModified; + if (!GetLastModifiedDateTime(file, lastModified)) + lastModified.Reset(); + + // get the MIME type for the Content-Type header + CStdString ext = URIUtils::GetExtension(strURL); + ext = ext.ToLower(); + string mimeType = CreateMimeTypeFromExtension(ext.c_str()); + if (methodType != HEAD) { + int64_t firstPosition = 0; + int64_t lastPosition = fileLength - 1; + uint64_t totalLength = 0; + HttpFileDownloadContext *context = new HttpFileDownloadContext(); + context->file = file; + context->rangesLength = fileLength; + context->contentType = mimeType; + context->boundaryWritten = false; + context->writePosition = 0; + if (methodType == GET) { + // handle If-Modified-Since string ifModifiedSince = GetRequestHeaderValue(connection, MHD_HEADER_KIND, "If-Modified-Since"); - if (!ifModifiedSince.empty()) + if (!ifModifiedSince.empty() && lastModified.IsValid()) { CDateTime ifModifiedSinceDate; ifModifiedSinceDate.SetFromRFC1123DateTime(ifModifiedSince); - struct __stat64 statBuffer; - if (file->Stat(&statBuffer) == 0) + if (lastModified.GetAsUTCDateTime() <= ifModifiedSinceDate) + { + getData = false; + response = MHD_create_response_from_data(0, NULL, MHD_NO, MHD_NO); + responseCode = MHD_HTTP_NOT_MODIFIED; + } + } + + if (getData) + { + // handle Range header + context->rangesLength = ParseRangeHeader(GetRequestHeaderValue(connection, MHD_HEADER_KIND, "Range"), fileLength, context->ranges, firstPosition, lastPosition); + + // handle If-Range header but only if the Range header is present + if (!context->ranges.empty()) { - struct tm *time = localtime((time_t *)&statBuffer.st_mtime); - if (time != NULL) + string ifRange = GetRequestHeaderValue(connection, MHD_HEADER_KIND, "If-Range"); + if (!ifRange.empty() && lastModified.IsValid()) { - CDateTime lastModified = *time; - if (lastModified.GetAsUTCDateTime() <= ifModifiedSinceDate) - { - getData = false; - response = MHD_create_response_from_data (0, NULL, MHD_NO, MHD_NO); - responseCode = MHD_HTTP_NOT_MODIFIED; - } + CDateTime ifRangeDate; + ifRangeDate.SetFromRFC1123DateTime(ifRange); + + // check if the last modification is newer than the If-Range date + // if so we have to server the whole file instead + if (lastModified.GetAsUTCDateTime() > ifRangeDate) + context->ranges.clear(); } } } } if (getData) - response = MHD_create_response_from_callback(file->GetLength(), + { + // if there are no ranges, add the whole range + if (context->ranges.empty() || context->rangesLength == fileLength) + { + if (context->rangesLength == fileLength) + context->ranges.clear(); + + context->ranges.push_back(HttpRange(0, fileLength - 1)); + context->rangesLength = fileLength; + firstPosition = 0; + lastPosition = fileLength - 1; + } + else + responseCode = MHD_HTTP_PARTIAL_CONTENT; + + // remember the total number of ranges + context->rangeCount = context->ranges.size(); + // remember the total length + totalLength = context->rangesLength; + + // we need to remember whether we are ranged because the range length + // might change and won't be reliable anymore for length comparisons + ranged = context->rangeCount > 1 || context->rangesLength < fileLength; + + // adjust the MIME type and range length in case of multiple ranges + // which requires multipart boundaries + if (context->rangeCount > 1) + { + context->boundary = GenerateMultipartBoundary(); + mimeType = "multipart/byteranges; boundary=" + context->boundary; + + // build part of the boundary with the optional Content-Type header + // "--<boundary>\r\nContent-Type: <content-type>\r\n + context->boundaryWithHeader = "\r\n--" + context->boundary + "\r\n"; + if (!context->contentType.empty()) + context->boundaryWithHeader += "Content-Type: " + context->contentType + "\r\n"; + + // for every range, we need to add a boundary with header + for (HttpRanges::const_iterator range = context->ranges.begin(); range != context->ranges.end(); range++) + { + // we need to temporarily add the Content-Range header to the + // boundary to be able to determine the length + string completeBoundaryWithHeader = context->boundaryWithHeader; + completeBoundaryWithHeader += StringUtils::Format("Content-Range: " CONTENT_RANGE_FORMAT, + range->first, range->second, range->second - range->first + 1); + completeBoundaryWithHeader += "\r\n\r\n"; + + totalLength += completeBoundaryWithHeader.size(); + } + // and at the very end a special end-boundary "\r\n--<boundary>--" + totalLength += 4 + context->boundary.size() + 2; + } + + // set the initial write position + context->writePosition = context->ranges.begin()->first; + + // create the response object + response = MHD_create_response_from_callback(totalLength, 2048, - &CWebServer::ContentReaderCallback, file, + &CWebServer::ContentReaderCallback, context, &CWebServer::ContentReaderFreeCallback); + } + if (response == NULL) { file->Close(); delete file; + delete context; return MHD_NO; } + + // add Content-Range header + if (ranged) + AddHeader(response, "Content-Range", StringUtils::Format(CONTENT_RANGE_FORMAT, firstPosition, lastPosition, fileLength).c_str()); } else { getData = false; CStdString contentLength; - contentLength.Format("%I64d", file->GetLength()); + contentLength.Format("%" PRId64, fileLength); - response = MHD_create_response_from_data (0, NULL, MHD_NO, MHD_NO); + response = MHD_create_response_from_data(0, NULL, MHD_NO, MHD_NO); if (response == NULL) { file->Close(); delete file; return MHD_NO; } - MHD_add_response_header(response, "Content-Length", contentLength); + AddHeader(response, "Content-Length", contentLength); } + // add "Accept-Ranges: bytes" header + AddHeader(response, "Accept-Ranges", "bytes"); + // set the Content-Type header - CStdString ext = URIUtils::GetExtension(strURL); - ext = ext.ToLower(); - const char *mime = CreateMimeTypeFromExtension(ext.c_str()); - if (mime) - MHD_add_response_header(response, "Content-Type", mime); + if (!mimeType.empty()) + AddHeader(response, "Content-Type", mimeType.c_str()); // set the Last-Modified header - struct __stat64 statBuffer; - if (file->Stat(&statBuffer) == 0) - { - struct tm *time = localtime((time_t *)&statBuffer.st_mtime); - if (time != NULL) - { - CDateTime lastModified = *time; - MHD_add_response_header(response, "Last-Modified", lastModified.GetAsRFC1123DateTime()); - } - } + if (lastModified.IsValid()) + AddHeader(response, "Last-Modified", lastModified.GetAsRFC1123DateTime()); // set the Expires header CDateTime expiryTime = CDateTime::GetCurrentDateTime(); - if (mime && strncmp(mime, "text/html", 9) == 0) + if (StringUtils::EqualsNoCase(mimeType, "text/html") || + StringUtils::EqualsNoCase(mimeType, "text/css") || + StringUtils::EqualsNoCase(mimeType, "application/javascript")) expiryTime += CDateTimeSpan(1, 0, 0, 0); else expiryTime += CDateTimeSpan(365, 0, 0, 0); - MHD_add_response_header(response, "Expires", expiryTime.GetAsRFC1123DateTime()); + AddHeader(response, "Expires", expiryTime.GetAsRFC1123DateTime()); // only close the CFile instance if libmicrohttpd doesn't have to grab the data of the file if (!getData) @@ -456,8 +581,9 @@ int CWebServer::CreateFileDownloadResponse(struct MHD_Connection *connection, co { delete file; CLog::Log(LOGERROR, "WebServer: Failed to open %s", strURL.c_str()); - return SendErrorResponse(connection, MHD_HTTP_NOT_FOUND, GET); /* GET Assumed Temporarily */ + return SendErrorResponse(connection, MHD_HTTP_NOT_FOUND, methodType); } + return MHD_YES; } @@ -515,28 +641,111 @@ void* CWebServer::UriRequestLogger(void *cls, const char *uri) } #if (MHD_VERSION >= 0x00090200) -ssize_t CWebServer::ContentReaderCallback (void *cls, uint64_t pos, char *buf, size_t max) +ssize_t CWebServer::ContentReaderCallback(void *cls, uint64_t pos, char *buf, size_t max) #elif (MHD_VERSION >= 0x00040001) int CWebServer::ContentReaderCallback(void *cls, uint64_t pos, char *buf, int max) #else //libmicrohttpd < 0.4.0 int CWebServer::ContentReaderCallback(void *cls, size_t pos, char *buf, int max) #endif { - CFile *file = (CFile *)cls; - if((unsigned int)pos != file->GetPosition()) - file->Seek(pos); - unsigned res = file->Read(buf, max); - if(res == 0) + HttpFileDownloadContext *context = (HttpFileDownloadContext *)cls; + if (context == NULL || context->file == NULL) + return -1; + +#ifdef WEBSERVER_DEBUG + CLog::Log(LOGDEBUG, "webserver [OUT] write maximum %d bytes from %" PRIu64 " (%" PRIu64 ")", max, context->writePosition, pos); +#endif + + // check if we need to add the end-boundary + if (context->rangeCount > 1 && context->ranges.empty()) + { + // put together the end-boundary + string endBoundary = "\r\n--" + context->boundary + "--"; + if (max != endBoundary.size()) + return -1; + + // copy the boundary into the buffer + memcpy(buf, endBoundary.c_str(), endBoundary.size()); + return endBoundary.size(); + } + + if (context->ranges.empty()) + return -1; + + int64_t start = context->ranges.at(0).first; + int64_t end = context->ranges.at(0).second; + int64_t maximum = (int64_t)max; + int written = 0; + + if (context->rangeCount > 1 && !context->boundaryWritten) + { + // put together the boundary for the current range + string boundary = context->boundaryWithHeader; + boundary += StringUtils::Format("Content-Range: " CONTENT_RANGE_FORMAT, start, end, end - start + 1) + "\r\n\r\n"; + + // copy the boundary into the buffer + memcpy(buf, boundary.c_str(), boundary.size()); + // advance the buffer position + buf += boundary.size(); + // update the number of written byte + written += boundary.size(); + // update the maximum number of bytes + maximum -= boundary.size(); + context->boundaryWritten = true; + } + + // check if the current position is within this range + // if not, set it to the start position + if (context->writePosition < start || context->writePosition > end) + context->writePosition = start; + // adjust the maximum number of read bytes + maximum = std::min(maximum, end - context->writePosition + 1); + + // seek to the position if necessary + if(context->writePosition != context->file->GetPosition()) + context->file->Seek(context->writePosition); + + // read data from the file + unsigned int res = context->file->Read(buf, maximum); + if (res == 0) return -1; - return res; + + // add the number of read bytes to the number of written bytes + written += res; +#ifdef WEBSERVER_DEBUG + CLog::Log(LOGDEBUG, "webserver [OUT] wrote %d bytes from %" PRId64 " in range (%" PRId64 " - %" PRId64 ")", written, context->writePosition, start, end); +#endif + // update the current write position + context->writePosition += res; + + // if we have read all the data from the current range + // remove it from the list + if (context->writePosition >= end + 1) + { + context->ranges.erase(context->ranges.begin()); + context->boundaryWritten = false; + } + + return written; } void CWebServer::ContentReaderFreeCallback(void *cls) { - CFile *file = (CFile *)cls; - file->Close(); + HttpFileDownloadContext *context = (HttpFileDownloadContext *)cls; + if (context == NULL) + return; - delete file; + if (context->file != NULL) + { + context->file->Close(); + delete context->file; + context->file = NULL; + } + +#ifdef WEBSERVER_DEBUG + CLog::Log(LOGDEBUG, "webserver [OUT] done"); +#endif + delete context; } struct MHD_Daemon* CWebServer::StartMHD(unsigned int flags, int port) @@ -728,60 +937,133 @@ int CWebServer::GetRequestHeaderValues(struct MHD_Connection *connection, enum M return MHD_get_connection_values(connection, kind, FillArgumentMultiMap, &headerValues); } -const char *CWebServer::CreateMimeTypeFromExtension(const char *ext) -{ - if (strcmp(ext, ".aif") == 0) return "audio/aiff"; - if (strcmp(ext, ".aiff") == 0) return "audio/aiff"; - if (strcmp(ext, ".asf") == 0) return "video/x-ms-asf"; - if (strcmp(ext, ".asx") == 0) return "video/x-ms-asf"; - if (strcmp(ext, ".avi") == 0) return "video/avi"; - if (strcmp(ext, ".avs") == 0) return "video/avs-video"; - if (strcmp(ext, ".bin") == 0) return "application/octet-stream"; - if (strcmp(ext, ".bmp") == 0) return "image/bmp"; - if (strcmp(ext, ".dv") == 0) return "video/x-dv"; - if (strcmp(ext, ".fli") == 0) return "video/fli"; - if (strcmp(ext, ".gif") == 0) return "image/gif"; - if (strcmp(ext, ".htm") == 0) return "text/html"; - if (strcmp(ext, ".html") == 0) return "text/html"; - if (strcmp(ext, ".htmls") == 0) return "text/html"; - if (strcmp(ext, ".ico") == 0) return "image/x-icon"; - if (strcmp(ext, ".it") == 0) return "audio/it"; - if (strcmp(ext, ".jpeg") == 0) return "image/jpeg"; - if (strcmp(ext, ".jpg") == 0) return "image/jpeg"; - if (strcmp(ext, ".json") == 0) return "application/json"; +std::string CWebServer::CreateMimeTypeFromExtension(const char *ext) +{ if (strcmp(ext, ".kar") == 0) return "audio/midi"; - if (strcmp(ext, ".list") == 0) return "text/plain"; - if (strcmp(ext, ".log") == 0) return "text/plain"; - if (strcmp(ext, ".lst") == 0) return "text/plain"; - if (strcmp(ext, ".m2v") == 0) return "video/mpeg"; - if (strcmp(ext, ".m3u") == 0) return "audio/x-mpequrl"; - if (strcmp(ext, ".mid") == 0) return "audio/midi"; - if (strcmp(ext, ".midi") == 0) return "audio/midi"; - if (strcmp(ext, ".mod") == 0) return "audio/mod"; - if (strcmp(ext, ".mov") == 0) return "video/quicktime"; - if (strcmp(ext, ".mp2") == 0) return "audio/mpeg"; - if (strcmp(ext, ".mp3") == 0) return "audio/mpeg3"; - if (strcmp(ext, ".mpa") == 0) return "audio/mpeg"; - if (strcmp(ext, ".mpeg") == 0) return "video/mpeg"; - if (strcmp(ext, ".mpg") == 0) return "video/mpeg"; - if (strcmp(ext, ".mpga") == 0) return "audio/mpeg"; - if (strcmp(ext, ".pcx") == 0) return "image/x-pcx"; - if (strcmp(ext, ".png") == 0) return "image/png"; - if (strcmp(ext, ".rm") == 0) return "audio/x-pn-realaudio"; - if (strcmp(ext, ".s3m") == 0) return "audio/s3m"; - if (strcmp(ext, ".sid") == 0) return "audio/x-psid"; - if (strcmp(ext, ".tif") == 0) return "image/tiff"; - if (strcmp(ext, ".tiff") == 0) return "image/tiff"; - if (strcmp(ext, ".txt") == 0) return "text/plain"; - if (strcmp(ext, ".uni") == 0) return "text/uri-list"; - if (strcmp(ext, ".viv") == 0) return "video/vivo"; - if (strcmp(ext, ".wav") == 0) return "audio/wav"; - if (strcmp(ext, ".xm") == 0) return "audio/xm"; - if (strcmp(ext, ".xml") == 0) return "text/xml"; - if (strcmp(ext, ".zip") == 0) return "application/zip"; if (strcmp(ext, ".tbn") == 0) return "image/jpeg"; - if (strcmp(ext, ".js") == 0) return "application/javascript"; - if (strcmp(ext, ".css") == 0) return "text/css"; - return NULL; + return CMime::GetMimeType(ext); +} + +int CWebServer::AddHeader(struct MHD_Response *response, const std::string &name, const std::string &value) +{ + if (response == NULL || name.empty()) + return 0; + +#ifdef WEBSERVER_DEBUG + CLog::Log(LOGDEBUG, "webserver [OUT] %s: %s", name.c_str(), value.c_str()); +#endif + return MHD_add_response_header(response, name.c_str(), value.c_str()); +} + +int64_t CWebServer::ParseRangeHeader(const std::string &rangeHeaderValue, int64_t totalLength, HttpRanges &ranges, int64_t &firstPosition, int64_t &lastPosition) +{ + firstPosition = 0; + lastPosition = totalLength - 1; + + if (rangeHeaderValue.empty() || !StringUtils::StartsWith(rangeHeaderValue, "bytes=")) + return totalLength; + + int64_t rangesLength = 0; + + // remove "bytes=" from the beginning + string rangesValue = rangeHeaderValue.substr(6); + // split the value of the "Range" header by "," + vector<string> rangeValues = StringUtils::Split(rangesValue, ","); + for (vector<string>::const_iterator range = rangeValues.begin(); range != rangeValues.end(); range++) + { + // there must be a "-" in the range definition + if (range->find("-") == string::npos) + { + ranges.clear(); + return totalLength; + } + + vector<string> positions = StringUtils::Split(*range, "-"); + if (positions.size() > 2) + { + ranges.clear(); + return totalLength; + } + + int64_t positionStart = -1; + int64_t positionEnd = -1; + if (!positions.at(0).empty()) + positionStart = str2int64(positions.at(0), -1); + if (!positions.at(1).empty()) + positionEnd = str2int64(positions.at(1), -1); + + if (positionStart < 0 && positionEnd < 0) + { + ranges.clear(); + return totalLength; + } + + // if there's no end position, use the file's length + if (positionEnd < 0) + positionEnd = totalLength - 1; + else if (positionStart < 0) + { + positionStart = totalLength - positionEnd; + positionEnd = totalLength - 1; + } + + if (positionEnd < positionStart) + { + ranges.clear(); + return totalLength; + } + + if (ranges.empty()) + { + firstPosition = positionStart; + lastPosition = positionEnd; + } + else + { + if (positionStart < firstPosition) + firstPosition = positionStart; + if (positionEnd > lastPosition) + lastPosition = positionEnd; + } + + ranges.push_back(HttpRange(positionStart, positionEnd)); + rangesLength += positionEnd - positionStart + 1; + } + + if (!ranges.empty() || rangesLength > 0) + return rangesLength; + + return totalLength; +} + +std::string CWebServer::GenerateMultipartBoundary() +{ + static char chars[] = "-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + // create a string of length 30 to 40 and pre-fill it with "-" + size_t count = (size_t)CUtil::GetRandomNumber() % 11 + 30; + string boundary(count, '-'); + + for (size_t i = (size_t)CUtil::GetRandomNumber() % 5 + 8; i < count; i++) + boundary.replace(i, 1, 1, chars[(size_t)CUtil::GetRandomNumber() % 64]); + + return boundary; +} + +bool CWebServer::GetLastModifiedDateTime(XFILE::CFile *file, CDateTime &lastModified) +{ + if (file == NULL) + return false; + + struct __stat64 statBuffer; + if (file->Stat(&statBuffer) != 0) + return false; + + struct tm *time = localtime((time_t *)&statBuffer.st_mtime); + if (time == NULL) + return false; + + lastModified = *time; + return true; } #endif diff --git a/xbmc/network/WebServer.h b/xbmc/network/WebServer.h index b48d43d844..6ed2fc1f3e 100644 --- a/xbmc/network/WebServer.h +++ b/xbmc/network/WebServer.h @@ -29,9 +29,19 @@ #include <stdio.h> #include <stdint.h> #include <vector> + #include "interfaces/json-rpc/ITransportLayer.h" +#include "network/httprequesthandler/IHTTPRequestHandler.h" #include "threads/CriticalSection.h" -#include "httprequesthandler/IHTTPRequestHandler.h" + +namespace XFILE +{ + class CFile; +} +class CDateTime; + +typedef std::pair<int64_t, int64_t> HttpRange; +typedef std::vector<HttpRange> HttpRanges; class CWebServer : public JSONRPC::ITransportLayer { @@ -54,6 +64,7 @@ public: static std::string GetRequestHeaderValue(struct MHD_Connection *connection, enum MHD_ValueKind kind, const std::string &key); static int GetRequestHeaderValues(struct MHD_Connection *connection, enum MHD_ValueKind kind, std::map<std::string, std::string> &headerValues); static int GetRequestHeaderValues(struct MHD_Connection *connection, enum MHD_ValueKind kind, std::multimap<std::string, std::string> &headerValues); + private: struct MHD_Daemon* StartMHD(unsigned int flags, int port); static int AskForAuthentication (struct MHD_Connection *connection); @@ -101,7 +112,12 @@ private: static int FillArgumentMap(void *cls, enum MHD_ValueKind kind, const char *key, const char *value); static int FillArgumentMultiMap(void *cls, enum MHD_ValueKind kind, const char *key, const char *value); - static const char *CreateMimeTypeFromExtension(const char *ext); + static std::string CreateMimeTypeFromExtension(const char *ext); + + static int AddHeader(struct MHD_Response *response, const std::string &name, const std::string &value); + static int64_t ParseRangeHeader(const std::string &rangeHeaderValue, int64_t totalLength, HttpRanges &ranges, int64_t &firstPosition, int64_t &lastPosition); + static std::string GenerateMultipartBoundary(); + static bool GetLastModifiedDateTime(XFILE::CFile *file, CDateTime &lastModified); struct MHD_Daemon *m_daemon; bool m_running, m_needcredentials; diff --git a/xbmc/network/Zeroconf.cpp b/xbmc/network/Zeroconf.cpp index b1130f6f80..f0d1ddb5f0 100644 --- a/xbmc/network/Zeroconf.cpp +++ b/xbmc/network/Zeroconf.cpp @@ -19,7 +19,7 @@ */ #include "system.h" //HAS_ZEROCONF define #include "Zeroconf.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #ifdef _LINUX #if !defined(TARGET_DARWIN) @@ -67,7 +67,7 @@ bool CZeroconf::PublishService(const std::string& fcr_identifier, const std::string& fcr_type, const std::string& fcr_name, unsigned int f_port, - const std::vector<std::pair<std::string, std::string> >& txt) + std::vector<std::pair<std::string, std::string> > txt /* = std::vector<std::pair<std::string, std::string> >() */) { CSingleLock lock(*mp_crit_sec); CZeroconf::PublishInfo info = {fcr_type, fcr_name, f_port, txt}; @@ -99,21 +99,22 @@ bool CZeroconf::HasService(const std::string& fcr_identifier) const return (m_service_map.find(fcr_identifier) != m_service_map.end()); } -void CZeroconf::Start() +bool CZeroconf::Start() { CSingleLock lock(*mp_crit_sec); if(!IsZCdaemonRunning()) { - g_guiSettings.SetBool("services.zeroconf", false); - if (g_guiSettings.GetBool("services.airplay")) - g_guiSettings.SetBool("services.airplay", false); - return; + CSettings::Get().SetBool("services.zeroconf", false); + if (CSettings::Get().GetBool("services.airplay")) + CSettings::Get().SetBool("services.airplay", false); + return false; } if(m_started) - return; + return true; m_started = true; CJobManager::GetInstance().AddJob(new CPublish(m_service_map), NULL); + return true; } void CZeroconf::Stop() diff --git a/xbmc/network/Zeroconf.h b/xbmc/network/Zeroconf.h index bf700b4a15..3b6d8a8a08 100644 --- a/xbmc/network/Zeroconf.h +++ b/xbmc/network/Zeroconf.h @@ -50,7 +50,7 @@ public: const std::string& fcr_type, const std::string& fcr_name, unsigned int f_port, - const std::vector<std::pair<std::string, std::string> >& txt); + std::vector<std::pair<std::string, std::string> > txt /*= std::vector<std::pair<std::string, std::string> >()*/); ///removes the specified service ///returns false if fcr_identifier does not exist @@ -62,7 +62,7 @@ public: //starts publishing //services that were added with PublishService(...) while Zeroconf wasn't //started, get published now. - void Start(); + bool Start(); // unpublishs all services (but keeps them stored in this class) // a call to Start() will republish them @@ -79,6 +79,8 @@ public: static bool IsInstantiated() { return smp_instance != 0; } // win32: process results from the bonjour daemon virtual void ProcessResults() {} + // returns if the service is started and services are announced + bool IsStarted() { return m_started; } protected: //methods to implement for concrete implementations diff --git a/xbmc/network/upnp/UPnP.cpp b/xbmc/network/upnp/UPnP.cpp index f3aa9dae51..6d44a86c4e 100644 --- a/xbmc/network/upnp/UPnP.cpp +++ b/xbmc/network/upnp/UPnP.cpp @@ -34,7 +34,7 @@ #include "Platinum.h" #include "URL.h" #include "profiles/ProfilesManager.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "GUIUserMessages.h" #include "FileItem.h" #include "guilib/GUIWindowManager.h" @@ -467,7 +467,7 @@ CUPnP::StartClient() m_MediaBrowser = new CMediaBrowser(m_CtrlPointHolder->m_CtrlPoint); // start controller - if (g_guiSettings.GetBool("services.upnpcontroller")) { + if (CSettings::Get().GetBool("services.upnpcontroller")) { m_MediaController = new CMediaController(m_CtrlPointHolder->m_CtrlPoint); } } @@ -504,7 +504,7 @@ CUPnP::CreateServer(int port /* = 0 */) // but it doesn't work anyways as it requires multicast for XP to detect us device->m_PresentationURL = NPT_HttpUrl(m_IP, - atoi(g_guiSettings.GetString("services.webserverport")), + CSettings::Get().GetInt("services.webserverport"), "/").ToString(); device->m_ModelName = "XBMC Media Center"; @@ -521,14 +521,13 @@ CUPnP::CreateServer(int port /* = 0 */) /*---------------------------------------------------------------------- | CUPnP::StartServer +---------------------------------------------------------------------*/ -void +bool CUPnP::StartServer() { - if (!m_ServerHolder->m_Device.IsNull()) return; + if (!m_ServerHolder->m_Device.IsNull()) return false; - // load upnpserver.xml so that g_settings.m_vecUPnPMusiCMediaSources, etc.. are loaded - CStdString filename; - URIUtils::AddFileToFolder(CProfilesManager::Get().GetUserDataFolder(), "upnpserver.xml", filename); + // load upnpserver.xml + CStdString filename = URIUtils::AddFileToFolder(CProfilesManager::Get().GetUserDataFolder(), "upnpserver.xml"); CUPnPSettings::Get().Load(filename); // create the server with a XBox compatible friendlyname and UUID from upnpserver.xml if found @@ -559,7 +558,7 @@ CUPnP::StartServer() // save UUID CUPnPSettings::Get().SetServerUUID(m_ServerHolder->m_Device->GetUUID().GetChars()); - CUPnPSettings::Get().Save(filename); + return CUPnPSettings::Get().Save(filename); } /*---------------------------------------------------------------------- @@ -588,7 +587,7 @@ CUPnP::CreateRenderer(int port /* = 0 */) device->m_PresentationURL = NPT_HttpUrl(m_IP, - atoi(g_guiSettings.GetString("services.webserverport")), + CSettings::Get().GetInt("services.webserverport"), "/").ToString(); device->m_ModelName = "XBMC Media Center"; device->m_ModelNumber = g_infoManager.GetVersion().c_str(); @@ -603,12 +602,11 @@ CUPnP::CreateRenderer(int port /* = 0 */) /*---------------------------------------------------------------------- | CUPnP::StartRenderer +---------------------------------------------------------------------*/ -void CUPnP::StartRenderer() +bool CUPnP::StartRenderer() { - if (!m_RendererHolder->m_Device.IsNull()) return; + if (!m_RendererHolder->m_Device.IsNull()) return false; - CStdString filename; - URIUtils::AddFileToFolder(CProfilesManager::Get().GetUserDataFolder(), "upnpserver.xml", filename); + CStdString filename = URIUtils::AddFileToFolder(CProfilesManager::Get().GetUserDataFolder(), "upnpserver.xml"); CUPnPSettings::Get().Load(filename); m_RendererHolder->m_Device = CreateRenderer(CUPnPSettings::Get().GetRendererPort()); @@ -629,7 +627,7 @@ void CUPnP::StartRenderer() // save UUID CUPnPSettings::Get().SetRendererUUID(m_RendererHolder->m_Device->GetUUID().GetChars()); - CUPnPSettings::Get().Save(filename); + return CUPnPSettings::Get().Save(filename); } /*---------------------------------------------------------------------- diff --git a/xbmc/network/upnp/UPnP.h b/xbmc/network/upnp/UPnP.h index eda10c470a..c55f76579d 100644 --- a/xbmc/network/upnp/UPnP.h +++ b/xbmc/network/upnp/UPnP.h @@ -49,7 +49,7 @@ public: ~CUPnP(); // server - void StartServer(); + bool StartServer(); void StopServer(); // client @@ -58,7 +58,7 @@ public: bool IsClientStarted() { return (m_MediaBrowser != NULL); } // renderer - void StartRenderer(); + bool StartRenderer(); void StopRenderer(); void UpdateState(); diff --git a/xbmc/network/upnp/UPnPServer.cpp b/xbmc/network/upnp/UPnPServer.cpp index ef7517e3c9..58fd2910aa 100644 --- a/xbmc/network/upnp/UPnPServer.cpp +++ b/xbmc/network/upnp/UPnPServer.cpp @@ -14,7 +14,7 @@ #include "guilib/WindowIDs.h" #include "music/tags/MusicInfoTag.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "utils/log.h" #include "utils/md5.h" #include "utils/StringUtils.h" @@ -137,7 +137,7 @@ CUPnPServer::PropagateUpdates() string buffer; map<string,pair<bool, unsigned long> >::iterator itr; - if (m_scanning || !g_guiSettings.GetBool("services.upnpannounce")) + if (m_scanning || !CSettings::Get().GetBool("services.upnpannounce")) return; NPT_CHECK_LABEL(FindServiceById("urn:upnp-org:serviceId:ContentDirectory", service), failed); @@ -272,7 +272,7 @@ CUPnPServer::Build(CFileItemPtr item, if (params.GetSongId() >= 0 ) { CSong song; - if (db.GetSongById(params.GetSongId(), song)) + if (db.GetSong(params.GetSongId(), song)) item->GetMusicInfoTag()->SetSong(song); } else if (params.GetAlbumId() >= 0 ) { diff --git a/xbmc/osx/IOSScreenManager.mm b/xbmc/osx/IOSScreenManager.mm index 1582fadae4..d393f11d38 100644 --- a/xbmc/osx/IOSScreenManager.mm +++ b/xbmc/osx/IOSScreenManager.mm @@ -28,7 +28,7 @@ #include "threads/Event.h" #include "Application.h" #include "WindowingFactory.h" -#include "Settings.h" +#include "settings/DisplaySettings.h" #undef BOOL #import <Foundation/Foundation.h> diff --git a/xbmc/osx/Info.plist b/xbmc/osx/Info.plist index 5eef3fdee6..6258087ae7 100644 --- a/xbmc/osx/Info.plist +++ b/xbmc/osx/Info.plist @@ -9,7 +9,7 @@ <key>CFBundleExecutable</key> <string>XBMC</string> <key>CFBundleGetInfoString</key> - <string>13.0.alpha3</string> + <string>13.0.alpha4</string> <key>CFBundleIconFile</key> <string>xbmc.icns</string> <key>CFBundleIdentifier</key> @@ -19,7 +19,7 @@ <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key> - <string>13.0.alpha3</string> + <string>13.0.alpha4</string> <key>CFBundleVersion</key> <string>r####</string> <key>CFBundleSignature</key> diff --git a/xbmc/osx/XBMCHelper.cpp b/xbmc/osx/XBMCHelper.cpp index 17e46e3e41..434ff8f2e3 100644 --- a/xbmc/osx/XBMCHelper.cpp +++ b/xbmc/osx/XBMCHelper.cpp @@ -28,9 +28,11 @@ #include "PlatformDefs.h" #include "Util.h" +#include "dialogs/GUIDialogOK.h" +#include "dialogs/GUIDialogYesNo.h" #include "utils/log.h" #include "system.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "utils/SystemInfo.h" #include "threads/Atomics.h" @@ -88,6 +90,50 @@ XBMCHelper::XBMCHelper() } ///////////////////////////////////////////////////////////////////////////// +bool XBMCHelper::OnSettingChanging(const CSetting *setting) +{ + if (setting == NULL) + return false; + + const std::string &settingId = setting->GetId(); + if (settingId == "input.appleremotemode") + { + int remoteMode = ((CSettingInt*)setting)->GetValue(); + + // if it's not disabled, start the event server or else apple remote won't work + if (remoteMode != APPLE_REMOTE_DISABLED) + { + // if starting the event server fails, we have to revert the change + if (!CSettings::Get().SetBool("services.esenabled", true)) + return false; + } + + // if XBMC helper is running, prompt user before effecting change + if (IsRunning() && GetMode() != remoteMode) + { + bool cancelled; + if (!CGUIDialogYesNo::ShowAndGetInput(13144, 13145, 13146, 13147, -1, -1, cancelled, 10000)) + return false; + // reload configuration + else + Configure(); + } + // set new configuration. + else + Configure(); + + if (ErrorStarting() == true) + { + // inform user about error + CGUIDialogOK::ShowAndGetInput(13620, 13621, 20022, 20022); + return false; + } + } + + return true; +} + +///////////////////////////////////////////////////////////////////////////// void XBMCHelper::Start() { int pid = GetProcessPid(XBMC_HELPER_PROGRAM); @@ -123,10 +169,10 @@ void XBMCHelper::Configure() // Read the new configuration. m_errorStarting = false; - m_mode = g_guiSettings.GetInt("input.appleremotemode"); - m_sequenceDelay = g_guiSettings.GetInt("input.appleremotesequencetime"); - m_alwaysOn = g_guiSettings.GetBool("input.appleremotealwayson"); - CStdString port_string = g_guiSettings.GetString("services.esport"); + m_mode = CSettings::Get().GetInt("input.appleremotemode"); + m_sequenceDelay = CSettings::Get().GetInt("input.appleremotesequencetime"); + m_alwaysOn = CSettings::Get().GetBool("input.appleremotealwayson"); + CStdString port_string = CSettings::Get().GetString("services.esport"); m_port = atoi(port_string.c_str()); @@ -138,7 +184,7 @@ void XBMCHelper::Configure() m_errorStarting = true; m_mode = APPLE_REMOTE_DISABLED; - g_guiSettings.SetInt("input.appleremotemode", APPLE_REMOTE_DISABLED); + CSettings::Get().SetInt("input.appleremotemode", APPLE_REMOTE_DISABLED); } // New configuration. diff --git a/xbmc/osx/XBMCHelper.h b/xbmc/osx/XBMCHelper.h index da9c86eb07..ba70f00bdb 100644 --- a/xbmc/osx/XBMCHelper.h +++ b/xbmc/osx/XBMCHelper.h @@ -22,12 +22,24 @@ */ #if !defined(__arm__) -class XBMCHelper + +#include "settings/ISettingCallback.h" + +enum AppleRemoteOptions { - public: + APPLE_REMOTE_DISABLED = 0, + APPLE_REMOTE_STANDARD, + APPLE_REMOTE_UNIVERSAL, + APPLE_REMOTE_MULTIREMOTE +}; +class XBMCHelper : public ISettingCallback +{ + public: static XBMCHelper& GetInstance(); + virtual bool OnSettingChanging(const CSetting *setting); + void Start(); void Stop(); diff --git a/xbmc/peripherals/Peripherals.cpp b/xbmc/peripherals/Peripherals.cpp index 9188b25a73..b9f066cf6f 100644 --- a/xbmc/peripherals/Peripherals.cpp +++ b/xbmc/peripherals/Peripherals.cpp @@ -38,7 +38,6 @@ #include "threads/SingleLock.h" #include "utils/log.h" #include "utils/XMLUtils.h" -#include "settings/GUISettings.h" #include "utils/XBMCTinyXML.h" #include "filesystem/Directory.h" #include "guilib/GUIWindowManager.h" @@ -48,6 +47,7 @@ #include "utils/StringUtils.h" #include "Util.h" #include "guilib/Key.h" +#include "settings/Setting.h" using namespace PERIPHERALS; using namespace XFILE; @@ -55,8 +55,6 @@ using namespace std; CPeripherals::CPeripherals(void) { - CDirectory::Create("special://profile/peripheral_data"); - Clear(); } @@ -78,6 +76,8 @@ void CPeripherals::Initialise(void) { m_bIsStarted = true; + CDirectory::Create("special://profile/peripheral_data"); + /* load mappings from peripherals.xml */ LoadMappings(); @@ -462,8 +462,6 @@ bool CPeripherals::LoadMappings(void) void CPeripherals::GetSettingsFromMappingsFile(TiXmlElement *xmlNode, map<CStdString, CSetting *> &m_settings) { TiXmlElement *currentNode = xmlNode->FirstChildElement("setting"); - int iMaxOrder(0); - while (currentNode) { CSetting *setting = NULL; @@ -483,7 +481,7 @@ void CPeripherals::GetSettingsFromMappingsFile(TiXmlElement *xmlNode, map<CStdSt bool bValue = (strcmp(currentNode->Attribute("value"), "no") != 0 && strcmp(currentNode->Attribute("value"), "false") != 0 && strcmp(currentNode->Attribute("value"), "0") != 0); - setting = new CSettingBool(0, strKey, iLabelId, bValue, CHECKMARK_CONTROL); + setting = new CSettingBool(strKey, iLabelId, bValue); } else if (strSettingsType.Equals("int")) { @@ -492,7 +490,7 @@ void CPeripherals::GetSettingsFromMappingsFile(TiXmlElement *xmlNode, map<CStdSt int iStep = currentNode->Attribute("step") ? atoi(currentNode->Attribute("step")) : 1; int iMax = currentNode->Attribute("max") ? atoi(currentNode->Attribute("max")) : 255; CStdString strFormat(currentNode->Attribute("format")); - setting = new CSettingInt(0, strKey, iLabelId, iValue, iMin, iStep, iMax, SPIN_CONTROL_INT, strFormat); + setting = new CSettingInt(strKey, iLabelId, iValue, iMin, iStep, iMax, strFormat); } else if (strSettingsType.Equals("float")) { @@ -500,26 +498,26 @@ void CPeripherals::GetSettingsFromMappingsFile(TiXmlElement *xmlNode, map<CStdSt float fMin = currentNode->Attribute("min") ? (float) atof(currentNode->Attribute("min")) : 0; float fStep = currentNode->Attribute("step") ? (float) atof(currentNode->Attribute("step")) : 0; float fMax = currentNode->Attribute("max") ? (float) atof(currentNode->Attribute("max")) : 0; - setting = new CSettingFloat(0, strKey, iLabelId, fValue, fMin, fStep, fMax, SPIN_CONTROL_FLOAT); + setting = new CSettingNumber(strKey, iLabelId, fValue, fMin, fStep, fMax); } else if (strSettingsType.Equals("enum")) { CStdString strEnums(currentNode->Attribute("lvalues")); if (!strEnums.IsEmpty()) { - map<int,int> enums; + vector< pair<int,int> > enums; vector<CStdString> valuesVec; CUtil::Tokenize(strEnums, valuesVec, "|"); for (unsigned int i = 0; i < valuesVec.size(); i++) - enums.insert(make_pair(atoi(valuesVec[i]), atoi(valuesVec[i]))); + enums.push_back(make_pair(atoi(valuesVec[i]), atoi(valuesVec[i]))); int iValue = currentNode->Attribute("value") ? atoi(currentNode->Attribute("value")) : 0; - setting = new CSettingInt(0, strKey, iLabelId, iValue, enums, SPIN_CONTROL_TEXT); + setting = new CSettingInt(strKey, iLabelId, iValue, enums); } } else { CStdString strValue(currentNode->Attribute("value")); - setting = new CSettingString(0, strKey, iLabelId, strValue, EDIT_CONTROL_INPUT, !bConfigurable, -1); + setting = new CSettingString(strKey, iLabelId, strValue); } if (setting) @@ -529,29 +527,12 @@ void CPeripherals::GetSettingsFromMappingsFile(TiXmlElement *xmlNode, map<CStdSt /* set the visibility */ setting->SetVisible(bConfigurable); - /* set the order */ - int iOrder(0); - currentNode->Attribute("order", &iOrder); - /* if the order attribute is invalid or 0, then the setting will be added at the end */ - if (iOrder < 0) - iOrder = 0; - setting->SetOrder(iOrder); - if (iOrder > iMaxOrder) - iMaxOrder = iOrder; - /* and add this new setting */ m_settings[strKey] = setting; } currentNode = currentNode->NextSiblingElement("setting"); } - - /* add the settings without an order attribute or an invalid order attribute set at the end */ - for (map<CStdString, CSetting *>::iterator it = m_settings.begin(); it != m_settings.end(); it++) - { - if (it->second->GetOrder() == 0) - it->second->SetOrder(++iMaxOrder); - } } void CPeripherals::GetDirectory(const CStdString &strPath, CFileItemList &items) const @@ -673,3 +654,35 @@ bool CPeripherals::GetNextKeypress(float frameTime, CKey &key) return false; } + +void CPeripherals::OnSettingChanged(const CSetting *setting) +{ + if (setting == NULL) + return; + + const std::string &settingId = setting->GetId(); + if (settingId == "locale.language") + { + // user set language, no longer use the TV's language + vector<CPeripheral *> cecDevices; + if (g_peripherals.GetPeripheralsWithFeature(cecDevices, FEATURE_CEC) > 0) + { + for (vector<CPeripheral *>::iterator it = cecDevices.begin(); it != cecDevices.end(); it++) + (*it)->SetSetting("use_tv_menu_language", false); + } + } +} + +void CPeripherals::OnSettingAction(const CSetting *setting) +{ + if (setting == NULL) + return; + + const std::string &settingId = setting->GetId(); + if (settingId == "input.peripherals") + { + CGUIDialogPeripheralManager *dialog = (CGUIDialogPeripheralManager *)g_windowManager.GetWindow(WINDOW_DIALOG_PERIPHERAL_MANAGER); + if (dialog != NULL) + dialog->DoModal(); + } +} diff --git a/xbmc/peripherals/Peripherals.h b/xbmc/peripherals/Peripherals.h index e2120493fd..1e93b3dc54 100644 --- a/xbmc/peripherals/Peripherals.h +++ b/xbmc/peripherals/Peripherals.h @@ -22,6 +22,7 @@ #include "system.h" #include "bus/PeripheralBus.h" #include "devices/Peripheral.h" +#include "settings/ISettingCallback.h" #include "threads/CriticalSection.h" #include "threads/Thread.h" @@ -36,7 +37,7 @@ namespace PERIPHERALS { #define g_peripherals CPeripherals::Get() - class CPeripherals + class CPeripherals : public ISettingCallback { public: static CPeripherals &Get(void); @@ -195,6 +196,9 @@ namespace PERIPHERALS return false; #endif } + + virtual void OnSettingChanged(const CSetting *setting); + virtual void OnSettingAction(const CSetting *setting); private: CPeripherals(void); diff --git a/xbmc/peripherals/devices/Peripheral.cpp b/xbmc/peripherals/devices/Peripheral.cpp index 03bd167a1f..084dea0d84 100644 --- a/xbmc/peripherals/devices/Peripheral.cpp +++ b/xbmc/peripherals/devices/Peripheral.cpp @@ -22,7 +22,7 @@ #include "peripherals/Peripherals.h" #include "utils/log.h" #include "utils/StringUtils.h" -#include "settings/GUISettings.h" +#include "settings/Setting.h" #include "utils/XBMCTinyXML.h" #include "utils/URIUtils.h" #include "guilib/LocalizeStrings.h" @@ -30,14 +30,6 @@ using namespace PERIPHERALS; using namespace std; -struct SortBySettingsOrder -{ - bool operator()(const CSetting *left, const CSetting *right) - { - return left->GetOrder() < right->GetOrder(); - } -}; - CPeripheral::CPeripheral(const PeripheralScanResult& scanResult) : m_type(scanResult.m_mappedType), m_busType(scanResult.m_busType), @@ -168,7 +160,6 @@ vector<CSetting *> CPeripheral::GetSettings(void) const vector<CSetting *> settings; for (map<CStdString, CSetting *>::const_iterator it = m_settings.begin(); it != m_settings.end(); it++) settings.push_back(it->second); - sort(settings.begin(), settings.end(), SortBySettingsOrder()); return settings; } @@ -184,10 +175,10 @@ void CPeripheral::AddSetting(const CStdString &strKey, const CSetting *setting) { switch(setting->GetType()) { - case SETTINGS_TYPE_BOOL: + case SettingTypeBool: { const CSettingBool *mappedSetting = (const CSettingBool *) setting; - CSettingBool *boolSetting = new CSettingBool(mappedSetting->GetOrder(), strKey.c_str(), mappedSetting->GetLabel(), mappedSetting->GetData(), mappedSetting->GetControlType()); + CSettingBool *boolSetting = new CSettingBool(strKey, *mappedSetting); if (boolSetting) { boolSetting->SetVisible(mappedSetting->IsVisible()); @@ -195,18 +186,10 @@ void CPeripheral::AddSetting(const CStdString &strKey, const CSetting *setting) } } break; - case SETTINGS_TYPE_INT: + case SettingTypeInteger: { const CSettingInt *mappedSetting = (const CSettingInt *) setting; - CSettingInt *intSetting(NULL); - if (mappedSetting->GetControlType() == SPIN_CONTROL_INT) - { - intSetting = new CSettingInt(mappedSetting->GetOrder(), strKey.c_str(), mappedSetting->GetLabel(), mappedSetting->GetData(), mappedSetting->m_iMin, mappedSetting->m_iStep, mappedSetting->m_iMax, mappedSetting->GetControlType(), mappedSetting->m_strFormat); - } - else if (mappedSetting->GetControlType() == SPIN_CONTROL_TEXT) - { - intSetting = new CSettingInt(mappedSetting->GetOrder(), strKey.c_str(), mappedSetting->GetLabel(), mappedSetting->GetData(), mappedSetting->m_entries, mappedSetting->GetControlType()); - } + CSettingInt *intSetting = new CSettingInt(strKey, *mappedSetting); if (intSetting) { intSetting->SetVisible(mappedSetting->IsVisible()); @@ -214,10 +197,10 @@ void CPeripheral::AddSetting(const CStdString &strKey, const CSetting *setting) } } break; - case SETTINGS_TYPE_FLOAT: + case SettingTypeNumber: { - const CSettingFloat *mappedSetting = (const CSettingFloat *) setting; - CSettingFloat *floatSetting = new CSettingFloat(mappedSetting->GetOrder(), strKey.c_str(), mappedSetting->GetLabel(), mappedSetting->GetData(), mappedSetting->m_fMin, mappedSetting->m_fStep, mappedSetting->m_fMax, mappedSetting->GetControlType()); + const CSettingNumber *mappedSetting = (const CSettingNumber *) setting; + CSettingNumber *floatSetting = new CSettingNumber(strKey, *mappedSetting); if (floatSetting) { floatSetting->SetVisible(mappedSetting->IsVisible()); @@ -225,10 +208,10 @@ void CPeripheral::AddSetting(const CStdString &strKey, const CSetting *setting) } } break; - case SETTINGS_TYPE_STRING: + case SettingTypeString: { const CSettingString *mappedSetting = (const CSettingString *) setting; - CSettingString *stringSetting = new CSettingString(mappedSetting->GetOrder(), strKey.c_str(), mappedSetting->GetLabel(), mappedSetting->GetData().c_str(), mappedSetting->GetControlType(), mappedSetting->m_bAllowEmpty, mappedSetting->m_iHeadingString); + CSettingString *stringSetting = new CSettingString(strKey, *mappedSetting); if (stringSetting) { stringSetting->SetVisible(mappedSetting->IsVisible()); @@ -275,11 +258,11 @@ bool CPeripheral::HasConfigurableSettings(void) const bool CPeripheral::GetSettingBool(const CStdString &strKey) const { map<CStdString, CSetting *>::const_iterator it = m_settings.find(strKey); - if (it != m_settings.end() && (*it).second->GetType() == SETTINGS_TYPE_BOOL) + if (it != m_settings.end() && (*it).second->GetType() == SettingTypeBool) { - CSettingBool *boolSetting = (CSettingBool *) (*it).second; + CSettingBool *boolSetting = (CSettingBool *) (*it).second; if (boolSetting) - return boolSetting->GetData(); + return boolSetting->GetValue(); } return false; @@ -288,11 +271,11 @@ bool CPeripheral::GetSettingBool(const CStdString &strKey) const int CPeripheral::GetSettingInt(const CStdString &strKey) const { map<CStdString, CSetting *>::const_iterator it = m_settings.find(strKey); - if (it != m_settings.end() && (*it).second->GetType() == SETTINGS_TYPE_INT) + if (it != m_settings.end() && (*it).second->GetType() == SettingTypeInteger) { - CSettingInt *intSetting = (CSettingInt *) (*it).second; + CSettingInt *intSetting = (CSettingInt *) (*it).second; if (intSetting) - return intSetting->GetData(); + return intSetting->GetValue(); } return 0; @@ -301,11 +284,11 @@ int CPeripheral::GetSettingInt(const CStdString &strKey) const float CPeripheral::GetSettingFloat(const CStdString &strKey) const { map<CStdString, CSetting *>::const_iterator it = m_settings.find(strKey); - if (it != m_settings.end() && (*it).second->GetType() == SETTINGS_TYPE_FLOAT) + if (it != m_settings.end() && (*it).second->GetType() == SettingTypeNumber) { - CSettingFloat *floatSetting = (CSettingFloat *) (*it).second; + CSettingNumber *floatSetting = (CSettingNumber *) (*it).second; if (floatSetting) - return floatSetting->GetData(); + return (float)floatSetting->GetValue(); } return 0; @@ -314,11 +297,11 @@ float CPeripheral::GetSettingFloat(const CStdString &strKey) const const CStdString CPeripheral::GetSettingString(const CStdString &strKey) const { map<CStdString, CSetting *>::const_iterator it = m_settings.find(strKey); - if (it != m_settings.end() && (*it).second->GetType() == SETTINGS_TYPE_STRING) + if (it != m_settings.end() && (*it).second->GetType() == SettingTypeString) { - CSettingString *stringSetting = (CSettingString *) (*it).second; + CSettingString *stringSetting = (CSettingString *) (*it).second; if (stringSetting) - return stringSetting->GetData(); + return stringSetting->GetValue(); } return StringUtils::EmptyString; @@ -328,13 +311,13 @@ bool CPeripheral::SetSetting(const CStdString &strKey, bool bValue) { bool bChanged(false); map<CStdString, CSetting *>::iterator it = m_settings.find(strKey); - if (it != m_settings.end() && (*it).second->GetType() == SETTINGS_TYPE_BOOL) + if (it != m_settings.end() && (*it).second->GetType() == SettingTypeBool) { - CSettingBool *boolSetting = (CSettingBool *) (*it).second; + CSettingBool *boolSetting = (CSettingBool *) (*it).second; if (boolSetting) { - bChanged = boolSetting->GetData() != bValue; - boolSetting->SetData(bValue); + bChanged = boolSetting->GetValue() != bValue; + boolSetting->SetValue(bValue); if (bChanged && m_bInitialised) m_changedSettings.insert(strKey); } @@ -346,13 +329,13 @@ bool CPeripheral::SetSetting(const CStdString &strKey, int iValue) { bool bChanged(false); map<CStdString, CSetting *>::iterator it = m_settings.find(strKey); - if (it != m_settings.end() && (*it).second->GetType() == SETTINGS_TYPE_INT) + if (it != m_settings.end() && (*it).second->GetType() == SettingTypeInteger) { - CSettingInt *intSetting = (CSettingInt *) (*it).second; + CSettingInt *intSetting = (CSettingInt *) (*it).second; if (intSetting) { - bChanged = intSetting->GetData() != iValue; - intSetting->SetData(iValue); + bChanged = intSetting->GetValue() != iValue; + intSetting->SetValue(iValue); if (bChanged && m_bInitialised) m_changedSettings.insert(strKey); } @@ -364,13 +347,13 @@ bool CPeripheral::SetSetting(const CStdString &strKey, float fValue) { bool bChanged(false); map<CStdString, CSetting *>::iterator it = m_settings.find(strKey); - if (it != m_settings.end() && (*it).second->GetType() == SETTINGS_TYPE_FLOAT) + if (it != m_settings.end() && (*it).second->GetType() == SettingTypeNumber) { - CSettingFloat *floatSetting = (CSettingFloat *) (*it).second; + CSettingNumber *floatSetting = (CSettingNumber *) (*it).second; if (floatSetting) { - bChanged = floatSetting->GetData() != fValue; - floatSetting->SetData(fValue); + bChanged = floatSetting->GetValue() != fValue; + floatSetting->SetValue(fValue); if (bChanged && m_bInitialised) m_changedSettings.insert(strKey); } @@ -399,22 +382,22 @@ bool CPeripheral::SetSetting(const CStdString &strKey, const CStdString &strValu map<CStdString, CSetting *>::iterator it = m_settings.find(strKey); if (it != m_settings.end()) { - if ((*it).second->GetType() == SETTINGS_TYPE_STRING) + if ((*it).second->GetType() == SettingTypeString) { - CSettingString *stringSetting = (CSettingString *) (*it).second; + CSettingString *stringSetting = (CSettingString *) (*it).second; if (stringSetting) { - bChanged = !stringSetting->GetData().Equals(strValue); - stringSetting->SetData(strValue); + bChanged = !StringUtils::EqualsNoCase(stringSetting->GetValue(), strValue); + stringSetting->SetValue(strValue); if (bChanged && m_bInitialised) m_changedSettings.insert(strKey); } } - else if ((*it).second->GetType() == SETTINGS_TYPE_INT) + else if ((*it).second->GetType() == SettingTypeInteger) bChanged = SetSetting(strKey, (int) (strValue.IsEmpty() ? 0 : atoi(strValue.c_str()))); - else if ((*it).second->GetType() == SETTINGS_TYPE_FLOAT) + else if ((*it).second->GetType() == SettingTypeNumber) bChanged = SetSetting(strKey, (float) (strValue.IsEmpty() ? 0 : atof(strValue.c_str()))); - else if ((*it).second->GetType() == SETTINGS_TYPE_BOOL) + else if ((*it).second->GetType() == SettingTypeBool) bChanged = SetSetting(strKey, strValue.Equals("1")); } return bChanged; @@ -432,32 +415,32 @@ void CPeripheral::PersistSettings(bool bExiting /* = false */) CStdString strValue; switch ((*itr).second->GetType()) { - case SETTINGS_TYPE_STRING: + case SettingTypeString: { CSettingString *stringSetting = (CSettingString *) (*itr).second; if (stringSetting) - strValue = stringSetting->GetData(); + strValue = stringSetting->GetValue(); } break; - case SETTINGS_TYPE_INT: + case SettingTypeInteger: { CSettingInt *intSetting = (CSettingInt *) (*itr).second; if (intSetting) - strValue.Format("%d", intSetting->GetData()); + strValue.Format("%d", intSetting->GetValue()); } break; - case SETTINGS_TYPE_FLOAT: + case SettingTypeNumber: { - CSettingFloat *floatSetting = (CSettingFloat *) (*itr).second; + CSettingNumber *floatSetting = (CSettingNumber *) (*itr).second; if (floatSetting) - strValue.Format("%.2f", floatSetting->GetData()); + strValue.Format("%.2f", floatSetting->GetValue()); } break; - case SETTINGS_TYPE_BOOL: + case SettingTypeBool: { CSettingBool *boolSetting = (CSettingBool *) (*itr).second; if (boolSetting) - strValue.Format("%d", boolSetting->GetData() ? 1:0); + strValue.Format("%d", boolSetting->GetValue() ? 1:0); } break; default: diff --git a/xbmc/peripherals/devices/Peripheral.h b/xbmc/peripherals/devices/Peripheral.h index 443f91d9aa..51f6c566c3 100644 --- a/xbmc/peripherals/devices/Peripheral.h +++ b/xbmc/peripherals/devices/Peripheral.h @@ -25,6 +25,8 @@ class TiXmlDocument; +class CSetting; + namespace PERIPHERALS { class CGUIDialogPeripheralSettings; diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp index 5cc7064d00..386d3e4165 100644 --- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp +++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp @@ -33,7 +33,7 @@ #include "peripherals/Peripherals.h" #include "peripherals/bus/PeripheralBus.h" #include "pictures/GUIWindowSlideShow.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "utils/log.h" #include "utils/Variant.h" diff --git a/xbmc/peripherals/devices/PeripheralImon.cpp b/xbmc/peripherals/devices/PeripheralImon.cpp index 1f2b034706..36532b8cd6 100644 --- a/xbmc/peripherals/devices/PeripheralImon.cpp +++ b/xbmc/peripherals/devices/PeripheralImon.cpp @@ -21,8 +21,8 @@ #include "PeripheralImon.h" #include "utils/log.h" #include "guilib/LocalizeStrings.h" +#include "settings/Settings.h" #include "threads/Atomics.h" -#include "settings/GUISettings.h" #if defined (TARGET_WINDOWS) #include "system.h" // For HAS_SDL_JOYSTICK #if defined (HAS_SDL_JOYSTICK) @@ -106,8 +106,8 @@ void CPeripheralImon::ActionOnImonConflict(bool deviceInserted /*= true*/) { if (deviceInserted || m_lCountOfImonsConflictWithDInput == 0) { -#if defined(TARGET_WINDOWS) && defined(HAS_SDL_JOYSTICK) - bool enableJoystickNow = !deviceInserted && g_guiSettings.GetBool("input.enablejoystick"); +#if defined(TARGET_WINDOWS) && defined (HAS_SDL_JOYSTICK) + bool enableJoystickNow = !deviceInserted && CSettings::Get().GetBool("input.enablejoystick"); CLog::Log(LOGNOTICE, "Problematic iMON hardware %s. Joystick usage: %s", (deviceInserted ? "detected" : "was removed"), (enableJoystickNow) ? "enabled." : "disabled." ); g_Joystick.SetEnabled(enableJoystickNow); diff --git a/xbmc/peripherals/devices/PeripheralImon.h b/xbmc/peripherals/devices/PeripheralImon.h index f8e40ffb88..a9db31b9d7 100644 --- a/xbmc/peripherals/devices/PeripheralImon.h +++ b/xbmc/peripherals/devices/PeripheralImon.h @@ -21,6 +21,8 @@ #include "PeripheralHID.h" +class CSetting; + namespace PERIPHERALS { class CPeripheralImon : public CPeripheralHID diff --git a/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.cpp b/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.cpp index da3517d78b..5dd3e83dcf 100644 --- a/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.cpp +++ b/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.cpp @@ -21,7 +21,7 @@ #include "GUIDialogPeripheralSettings.h" #include "addons/Skin.h" #include "peripherals/Peripherals.h" -#include "settings/GUISettings.h" +#include "settings/Setting.h" #include "utils/log.h" #include "video/dialogs/GUIDialogVideoSettings.h" @@ -33,7 +33,8 @@ using namespace PERIPHERALS; CGUIDialogPeripheralSettings::CGUIDialogPeripheralSettings(void) : CGUIDialogSettings(WINDOW_DIALOG_PERIPHERAL_SETTINGS, "DialogPeripheralSettings.xml"), m_item(NULL), - m_bIsInitialising(true) + m_bIsInitialising(true), + m_settingId(0) { } @@ -81,58 +82,58 @@ void CGUIDialogPeripheralSettings::CreateSettings() switch(setting->GetType()) { - case SETTINGS_TYPE_BOOL: + case SettingTypeBool: { CSettingBool *boolSetting = (CSettingBool *) setting; if (boolSetting) { - m_boolSettings.insert(make_pair(CStdString(boolSetting->GetSetting()), boolSetting->GetData())); - AddBool(boolSetting->GetOrder(), boolSetting->GetLabel(), &m_boolSettings[boolSetting->GetSetting()], true); + m_boolSettings.insert(make_pair(CStdString(boolSetting->GetId()), boolSetting->GetValue())); + AddBool(m_settingId++, boolSetting->GetLabel(), &m_boolSettings[boolSetting->GetId()], true); } } break; - case SETTINGS_TYPE_INT: + case SettingTypeInteger: { CSettingInt *intSetting = (CSettingInt *) setting; if (intSetting) { - if (intSetting->GetControlType() == SPIN_CONTROL_INT) + if (intSetting->GetControl().GetFormat() == SettingControlFormatInteger) { - m_intSettings.insert(make_pair(CStdString(intSetting->GetSetting()), (float) intSetting->GetData())); - AddSlider(intSetting->GetOrder(), intSetting->GetLabel(), &m_intSettings[intSetting->GetSetting()], (float)intSetting->m_iMin, (float)intSetting->m_iStep, (float)intSetting->m_iMax, CGUIDialogVideoSettings::FormatInteger, false); + m_intSettings.insert(make_pair(CStdString(intSetting->GetId()), (float) intSetting->GetValue())); + AddSlider(m_settingId++, intSetting->GetLabel(), &m_intSettings[intSetting->GetId()], (float)intSetting->GetMinimum(), (float)intSetting->GetStep(), (float)intSetting->GetMaximum(), CGUIDialogVideoSettings::FormatInteger, false); } - else if (intSetting->GetControlType() == SPIN_CONTROL_TEXT) + else if (intSetting->GetControl().GetFormat() == SettingControlFormatString) { - m_intTextSettings.insert(make_pair(CStdString(intSetting->GetSetting()), intSetting->GetData())); + m_intTextSettings.insert(make_pair(CStdString(intSetting->GetId()), intSetting->GetValue())); vector<pair<int, int> > entries; - map<int, int>::iterator entriesItr = intSetting->m_entries.begin(); - while (entriesItr != intSetting->m_entries.end()) + SettingOptions::const_iterator entriesItr = intSetting->GetOptions().begin(); + while (entriesItr != intSetting->GetOptions().end()) { entries.push_back(make_pair(entriesItr->first, entriesItr->second)); ++entriesItr; } - AddSpin(intSetting->GetOrder(), intSetting->GetLabel(), &m_intTextSettings[intSetting->GetSetting()], entries); + AddSpin(m_settingId++, intSetting->GetLabel(), &m_intTextSettings[intSetting->GetId()], entries); } } } break; - case SETTINGS_TYPE_FLOAT: + case SettingTypeNumber: { - CSettingFloat *floatSetting = (CSettingFloat *) setting; + CSettingNumber *floatSetting = (CSettingNumber *) setting; if (floatSetting) { - m_floatSettings.insert(make_pair(CStdString(floatSetting->GetSetting()), floatSetting->GetData())); - AddSlider(floatSetting->GetOrder(), floatSetting->GetLabel(), &m_floatSettings[floatSetting->GetSetting()], floatSetting->m_fMin, floatSetting->m_fStep, floatSetting->m_fMax, CGUIDialogVideoSettings::FormatFloat, false); + m_floatSettings.insert(make_pair(CStdString(floatSetting->GetId()), (float)floatSetting->GetValue())); + AddSlider(m_settingId++, floatSetting->GetLabel(), &m_floatSettings[floatSetting->GetId()], (float)floatSetting->GetMinimum(), (float)floatSetting->GetStep(), (float)floatSetting->GetMaximum(), CGUIDialogVideoSettings::FormatFloat, false); } } break; - case SETTINGS_TYPE_STRING: + case SettingTypeString: { CSettingString *stringSetting = (CSettingString *) setting; if (stringSetting) { - m_stringSettings.insert(make_pair(CStdString(stringSetting->GetSetting()), stringSetting->GetData())); - AddString(stringSetting->GetOrder(), stringSetting->GetLabel(), &m_stringSettings[stringSetting->GetSetting()]); + m_stringSettings.insert(make_pair(CStdString(stringSetting->GetId()), stringSetting->GetValue())); + AddString(m_settingId++, stringSetting->GetLabel(), &m_stringSettings[stringSetting->GetId()]); } } break; diff --git a/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.h b/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.h index 6c8fc812f9..4471f9359b 100644 --- a/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.h +++ b/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.h @@ -46,5 +46,6 @@ namespace PERIPHERALS std::map<CStdString, int> m_intTextSettings; std::map<CStdString, float> m_floatSettings; std::map<CStdString, CStdString> m_stringSettings; + int m_settingId; }; } diff --git a/xbmc/pictures/GUIViewStatePictures.cpp b/xbmc/pictures/GUIViewStatePictures.cpp index a801e1c324..2dfe6fbde0 100644 --- a/xbmc/pictures/GUIViewStatePictures.cpp +++ b/xbmc/pictures/GUIViewStatePictures.cpp @@ -21,9 +21,9 @@ #include "GUIViewStatePictures.h" #include "FileItem.h" #include "view/ViewState.h" -#include "settings/GUISettings.h" #include "settings/AdvancedSettings.h" #include "settings/MediaSourceSettings.h" +#include "settings/Settings.h" #include "filesystem/Directory.h" #include "filesystem/PluginDirectory.h" #include "guilib/LocalizeStrings.h" @@ -52,8 +52,8 @@ CGUIViewStateWindowPictures::CGUIViewStateWindowPictures(const CFileItemList& it AddSortMethod(SORT_METHOD_DATE, 552, LABEL_MASKS("%L", "%J", "%L", "%J")); // Filename, Date | Foldername, Date AddSortMethod(SORT_METHOD_DATE_TAKEN, 577, LABEL_MASKS("%L", "%t", "%L", "%J")); // Filename, DateTaken | Foldername, Date AddSortMethod(SORT_METHOD_FILE, 561, LABEL_MASKS("%L", "%I", "%L", "")); // Filename, Size | FolderName, empty - - CViewState *viewState = CViewStateSettings::Get().Get("pictures"); + + const CViewState *viewState = CViewStateSettings::Get().Get("pictures"); SetSortMethod(viewState->m_sortMethod); SetViewAsControl(viewState->m_viewMode); SetSortOrder(viewState->m_sortOrder); @@ -73,7 +73,7 @@ CStdString CGUIViewStateWindowPictures::GetLockType() CStdString CGUIViewStateWindowPictures::GetExtensions() { - if (g_guiSettings.GetBool("pictures.showvideos")) + if (CSettings::Get().GetBool("pictures.showvideos")) return g_advancedSettings.m_pictureExtensions+"|"+g_advancedSettings.m_videoExtensions; return g_advancedSettings.m_pictureExtensions; diff --git a/xbmc/pictures/GUIWindowPictures.cpp b/xbmc/pictures/GUIWindowPictures.cpp index e54450b8fc..0dbe98cb93 100644 --- a/xbmc/pictures/GUIWindowPictures.cpp +++ b/xbmc/pictures/GUIWindowPictures.cpp @@ -36,9 +36,8 @@ #include "dialogs/GUIDialogOK.h" #include "dialogs/GUIDialogYesNo.h" #include "playlists/PlayList.h" -#include "settings/Settings.h" -#include "settings/GUISettings.h" #include "settings/MediaSourceSettings.h" +#include "settings/Settings.h" #include "utils/TimeUtils.h" #include "utils/log.h" #include "utils/URIUtils.h" @@ -137,8 +136,8 @@ bool CGUIWindowPictures::OnMessage(CGUIMessage& message) } else if (iControl == CONTROL_SHUFFLE) { - g_guiSettings.ToggleBool("slideshow.shuffle"); - g_settings.Save(); + CSettings::Get().ToggleBool("slideshow.shuffle"); + CSettings::Get().Save(); } else if (m_viewControl.HasControl(iControl)) // list/thumb control { @@ -149,7 +148,7 @@ bool CGUIWindowPictures::OnMessage(CGUIMessage& message) if (iAction == ACTION_DELETE_ITEM) { // is delete allowed? - if (g_guiSettings.GetBool("filelists.allowfiledeletion")) + if (CSettings::Get().GetBool("filelists.allowfiledeletion")) OnDeleteItem(iItem); else return false; @@ -176,7 +175,7 @@ void CGUIWindowPictures::UpdateButtons() CGUIMediaWindow::UpdateButtons(); // Update the shuffle button - if (g_guiSettings.GetBool("slideshow.shuffle")) + if (CSettings::Get().GetBool("slideshow.shuffle")) { CGUIMessage msg2(GUI_MSG_SELECTED, GetID(), CONTROL_SHUFFLE); g_windowManager.SendMessage(msg2); @@ -217,7 +216,7 @@ void CGUIWindowPictures::OnPrepareFileItems(CFileItemList& items) if (items[i]->GetLabel().Equals("folder.jpg")) items.Remove(i); - if (items.GetFolderCount()==items.Size() || !g_guiSettings.GetBool("pictures.usetags")) + if (items.GetFolderCount()==items.Size() || !CSettings::Get().GetBool("pictures.usetags")) return; // Start the music info loader thread @@ -270,7 +269,7 @@ bool CGUIWindowPictures::Update(const CStdString &strDirectory, bool updateFilte return false; m_vecItems->SetArt("thumb", ""); - if (g_guiSettings.GetBool("pictures.generatethumbs")) + if (CSettings::Get().GetBool("pictures.generatethumbs")) m_thumbLoader.Load(*m_vecItems); m_vecItems->SetArt("thumb", CPictureThumbLoader::GetCachedImage(*m_vecItems, "thumb")); @@ -345,7 +344,7 @@ bool CGUIWindowPictures::ShowPicture(int iItem, bool startSlideShow) CFileItemPtr pItem = m_vecItems->Get(i); if (!pItem->m_bIsFolder && !(URIUtils::IsRAR(pItem->GetPath()) || URIUtils::IsZIP(pItem->GetPath())) && (pItem->IsPicture() || ( - g_guiSettings.GetBool("pictures.showvideos") && + CSettings::Get().GetBool("pictures.showvideos") && pItem->IsVideo()))) { pSlideShow->Add(pItem.get()); @@ -407,7 +406,8 @@ void CGUIWindowPictures::OnSlideShowRecursive(const CStdString &strPicture) } m_slideShowStarted = true; pSlideShow->RunSlideShow(strPicture, true, - g_guiSettings.GetBool("slideshow.shuffle"),false, + CSettings::Get().GetBool("slideshow.shuffle"),false, + "", true, m_guiState->GetSortMethod(), m_guiState->GetSortOrder(), strExtensions); @@ -440,6 +440,7 @@ void CGUIWindowPictures::OnSlideShow(const CStdString &strPicture) } m_slideShowStarted = true; pSlideShow->RunSlideShow(strPicture, false ,false, false, + "", true, m_guiState->GetSortMethod(), m_guiState->GetSortOrder(), strExtensions); @@ -481,7 +482,7 @@ void CGUIWindowPictures::GetContextButtons(int itemNumber, CContextButtons &butt if (!m_thumbLoader.IsLoading()) buttons.Add(CONTEXT_BUTTON_REFRESH_THUMBS, 13315); // Create Thumbnails - if (g_guiSettings.GetBool("filelists.allowfiledeletion") && !item->IsReadOnly()) + if (CSettings::Get().GetBool("filelists.allowfiledeletion") && !item->IsReadOnly()) { buttons.Add(CONTEXT_BUTTON_DELETE, 117); buttons.Add(CONTEXT_BUTTON_RENAME, 118); diff --git a/xbmc/pictures/GUIWindowSlideShow.cpp b/xbmc/pictures/GUIWindowSlideShow.cpp index 2c1cce6933..af11b0f595 100644 --- a/xbmc/pictures/GUIWindowSlideShow.cpp +++ b/xbmc/pictures/GUIWindowSlideShow.cpp @@ -35,7 +35,7 @@ #include "guilib/GUIWindowManager.h" #include "settings/AdvancedSettings.h" #include "settings/DisplaySettings.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "FileItem.h" #include "guilib/Texture.h" #include "windowing/WindowingFactory.h" @@ -46,6 +46,7 @@ #include "utils/TimeUtils.h" #include "interfaces/AnnouncementManager.h" #include "pictures/PictureInfoTag.h" +#include "pictures/PictureThumbLoader.h" using namespace XFILE; @@ -101,7 +102,7 @@ void CBackgroundPicLoader::Process() if (m_pCallback) { unsigned int start = XbmcThreads::SystemClockMillis(); - CBaseTexture* texture = CTexture::LoadFromFile(m_strFileName, m_maxWidth, m_maxHeight, g_guiSettings.GetBool("pictures.useexifrotation")); + CBaseTexture* texture = CTexture::LoadFromFile(m_strFileName, m_maxWidth, m_maxHeight, CSettings::Get().GetBool("pictures.useexifrotation")); totalTime += XbmcThreads::SystemClockMillis() - start; count++; // tell our parent @@ -120,7 +121,7 @@ void CBackgroundPicLoader::Process() bFullSize = true; } } - m_pCallback->OnLoadPic(m_iPic, m_iSlideNumber, texture, bFullSize); + m_pCallback->OnLoadPic(m_iPic, m_iSlideNumber, m_strFileName, texture, bFullSize); m_isLoading = false; } } @@ -160,7 +161,7 @@ CGUIWindowSlideShow::~CGUIWindowSlideShow(void) void CGUIWindowSlideShow::AnnouncePlayerPlay(const CFileItemPtr& item) { CVariant param; - param["player"]["speed"] = 1; + param["player"]["speed"] = m_bSlideShow && !m_bPause ? 1 : 0; param["player"]["playerid"] = PLAYLIST_PICTURE; ANNOUNCEMENT::CAnnouncementManager::Announce(ANNOUNCEMENT::Player, "xbmc", "OnPlay", item, param); } @@ -228,7 +229,6 @@ void CGUIWindowSlideShow::Reset() m_bPause = false; m_bPlayingVideo = false; m_bErrorMessage = false; - m_bReloadImage = false; m_Image[0].UnLoad(); m_Image[0].Close(); m_Image[1].UnLoad(); @@ -243,6 +243,7 @@ void CGUIWindowSlideShow::Reset() m_iNextSlide = 1; m_iCurrentPic = 0; m_iDirection = 1; + m_iLastFailedNextSlide = -1; CSingleLock lock(m_slideSection); m_slides->Clear(); AnnouncePlaylistClear(); @@ -263,22 +264,25 @@ void CGUIWindowSlideShow::OnDeinitWindow(int nextWindowID) g_windowManager.ShowOverlay(OVERLAY_STATE_SHOWN); - // wait for any outstanding picture loads - if (m_pBackgroundLoader) + if (nextWindowID != WINDOW_FULLSCREEN_VIDEO) { - // sleep until the loader finishes loading the current pic - CLog::Log(LOGDEBUG,"Waiting for BackgroundLoader thread to close"); - while (m_pBackgroundLoader->IsLoading()) - Sleep(10); - // stop the thread - CLog::Log(LOGDEBUG,"Stopping BackgroundLoader thread"); - m_pBackgroundLoader->StopThread(); - delete m_pBackgroundLoader; - m_pBackgroundLoader = NULL; + // wait for any outstanding picture loads + if (m_pBackgroundLoader) + { + // sleep until the loader finishes loading the current pic + CLog::Log(LOGDEBUG,"Waiting for BackgroundLoader thread to close"); + while (m_pBackgroundLoader->IsLoading()) + Sleep(10); + // stop the thread + CLog::Log(LOGDEBUG,"Stopping BackgroundLoader thread"); + m_pBackgroundLoader->StopThread(); + delete m_pBackgroundLoader; + m_pBackgroundLoader = NULL; + } + // and close the images. + m_Image[0].Close(); + m_Image[1].Close(); } - // and close the images. - m_Image[0].Close(); - m_Image[1].Close(); g_infoManager.ResetCurrentSlide(); CGUIWindow::OnDeinitWindow(nextWindowID); @@ -289,8 +293,12 @@ void CGUIWindowSlideShow::Add(const CFileItem *picture) CFileItemPtr item(new CFileItem(*picture)); if (!item->HasVideoInfoTag() && !item->HasPictureInfoTag()) { - // item without tag; assume it is a picture and force tag generation - item->GetPictureInfoTag(); + // item without tag; get mimetype then we can tell whether it's video item + item->GetMimeType(); + + if (!item->IsVideo()) + // then it is a picture and force tag generation + item->GetPictureInfoTag(); } AnnouncePlaylistAdd(item, m_slides->Size()); @@ -302,11 +310,8 @@ void CGUIWindowSlideShow::ShowNext() if (m_slides->Size() == 1) return; - m_iNextSlide = m_iCurrentSlide + 1; - if (m_iNextSlide >= m_slides->Size()) - m_iNextSlide = 0; - m_iDirection = 1; + m_iNextSlide = GetNextSlide(); m_iZoomFactor = 1; m_fZoom = 1.0f; m_fRotate = 0.0f; @@ -318,11 +323,8 @@ void CGUIWindowSlideShow::ShowPrevious() if (m_slides->Size() == 1) return; - m_iNextSlide = m_iCurrentSlide - 1; - if (m_iNextSlide < 0) - m_iNextSlide = m_slides->Size() - 1; - m_iDirection = -1; + m_iNextSlide = GetNextSlide(); m_iZoomFactor = 1; m_fZoom = 1.0f; m_fRotate = 0.0f; @@ -338,14 +340,17 @@ void CGUIWindowSlideShow::Select(const CStdString& strPicture) if (item->GetPath() == strPicture) { m_iDirection = 1; - if (IsActive()) - m_iNextSlide = i; - else + if (!m_Image[m_iCurrentPic].IsLoaded() && (!m_pBackgroundLoader || !m_pBackgroundLoader->IsLoading())) { + // will trigger loading current slide when next Process call. m_iCurrentSlide = i; m_iNextSlide = GetNextSlide(); } - m_bLoadNextPic = true; + else + { + m_iNextSlide = i; + m_bLoadNextPic = true; + } return ; } } @@ -382,11 +387,21 @@ void CGUIWindowSlideShow::StartSlideShow() AnnouncePlayerPlay(m_slides->Get(m_iCurrentSlide)); } +void CGUIWindowSlideShow::SetDirection(int direction) +{ + direction = direction >= 0 ? 1 : -1; + if (m_iDirection != direction) + { + m_iDirection = direction; + m_iNextSlide = GetNextSlide(); + } +} + void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList ®ions) { // reset the screensaver if we're in a slideshow // (unless we are the screensaver!) - if (m_bSlideShow && !g_application.IsInScreenSaver()) + if (m_bSlideShow && !m_bPause && !g_application.IsInScreenSaver()) g_application.ResetScreenSaver(); int iSlides = m_slides->Size(); if (!iSlides) return ; @@ -395,10 +410,10 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re if (!HasProcessed()) regions.push_back(CRect(0.0f, 0.0f, (float)g_graphicsContext.GetWidth(), (float)g_graphicsContext.GetHeight())); - if (m_iNextSlide < 0 || m_iNextSlide >= m_slides->Size()) - m_iNextSlide = 0; if (m_iCurrentSlide < 0 || m_iCurrentSlide >= m_slides->Size()) m_iCurrentSlide = 0; + if (m_iNextSlide < 0 || m_iNextSlide >= m_slides->Size()) + m_iNextSlide = GetNextSlide(); // Create our background loader if necessary if (!m_pBackgroundLoader) @@ -413,40 +428,66 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re } bool bSlideShow = m_bSlideShow && !m_bPause && !m_bPlayingVideo; + if (bSlideShow && m_slides->Get(m_iCurrentSlide)->HasProperty("unplayable")) + { + m_iNextSlide = GetNextSlide(); + if (m_iCurrentSlide == m_iNextSlide) + return; + m_iCurrentSlide = m_iNextSlide; + m_iNextSlide = GetNextSlide(); + } if (m_bErrorMessage) { // we have an error when loading either the current or next picture // check to see if we have a picture loaded - CLog::Log(LOGDEBUG, "We have an error loading a picture!"); - if (m_Image[m_iCurrentPic].IsLoaded()) - { // Yes. Let's let it transistion out, wait for it to be released, then try loading again. - CLog::Log(LOGERROR, "Error loading the next image %s", m_slides->Get(m_iNextSlide)->GetPath().c_str()); - if (!bSlideShow) - { // tell the pic to start transistioning out now - m_Image[m_iCurrentPic].StartTransistion(); - m_Image[m_iCurrentPic].SetTransistionTime(1, IMMEDIATE_TRANSISTION_TIME); // only 20 frames for the transistion - } - m_bWaitForNextPic = true; - m_bErrorMessage = false; - } - else - { // No. Not much we can do here. If we're in a slideshow, we mayaswell move on to the next picture - // change to next image - if (bSlideShow) + CLog::Log(LOGDEBUG, "We have an error loading picture %d!", m_pBackgroundLoader->SlideNumber()); + if (m_iCurrentSlide == m_pBackgroundLoader->SlideNumber()) + { + if (m_Image[m_iCurrentPic].IsLoaded()) { - CLog::Log(LOGERROR, "Error loading the current image %s", m_slides->Get(m_iCurrentSlide)->GetPath().c_str()); - m_iCurrentSlide = m_iNextSlide; - m_iNextSlide = GetNextSlide(); - ShowNext(); + // current image was already loaded, so we can ignore this error. m_bErrorMessage = false; } - else if (m_bLoadNextPic) + else { - m_iCurrentSlide = m_iNextSlide; - m_iNextSlide = GetNextSlide(); - m_bErrorMessage = false; + CLog::Log(LOGERROR, "Error loading the current image %d: %s", m_iCurrentSlide, m_slides->Get(m_iCurrentSlide)->GetPath().c_str()); + if (!m_slides->Get(m_iCurrentPic)->IsVideo()) + { + // try next if we are in slideshow + CLog::Log(LOGINFO, "set image %s unplayable", m_slides->Get(m_iCurrentSlide)->GetPath().c_str()); + m_slides->Get(m_iCurrentSlide)->SetProperty("unplayable", true); + } + if (m_bLoadNextPic || (bSlideShow && !m_bPause && !m_slides->Get(m_iCurrentPic)->IsVideo())) + { + // change to next item, wait loading. + m_iCurrentSlide = m_iNextSlide; + m_iNextSlide = GetNextSlide(); + m_bErrorMessage = false; + } + // else just drop through - there's nothing we can do (error message will be displayed) } - // else just drop through - there's nothing we can do (error message will be displayed) + } + else if (m_iNextSlide == m_pBackgroundLoader->SlideNumber()) + { + CLog::Log(LOGERROR, "Error loading the next image %d: %s", m_iNextSlide, m_slides->Get(m_iNextSlide)->GetPath().c_str()); + // load next image failed, then skip to load next of next if next is not video. + if (!m_slides->Get(m_iNextSlide)->IsVideo()) + { + CLog::Log(LOGINFO, "set image %s unplayable", m_slides->Get(m_iNextSlide)->GetPath().c_str()); + m_slides->Get(m_iNextSlide)->SetProperty("unplayable", true); + // change to next item, wait loading. + m_iNextSlide = GetNextSlide(); + } + else + { // prevent reload the next pic and repeat fail. + m_iLastFailedNextSlide = m_iNextSlide; + } + m_bErrorMessage = false; + } + else + { // Non-current and non-next slide, just ignore error. + CLog::Log(LOGERROR, "Error loading the non-current non-next image %d/%d: %s", m_iNextSlide, m_pBackgroundLoader->SlideNumber(), m_slides->Get(m_iNextSlide)->GetPath().c_str()); + m_bErrorMessage = false; } } @@ -456,83 +497,71 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re return; } + CSingleLock lock(m_slideSection); + if (!m_Image[m_iCurrentPic].IsLoaded() && !m_pBackgroundLoader->IsLoading()) { // load first image - CLog::Log(LOGDEBUG, "Loading the current image %s", m_slides->Get(m_iCurrentSlide)->GetPath().c_str()); - m_bWaitForNextPic = false; - m_bLoadNextPic = false; - // load using the background loader - int maxWidth, maxHeight; - GetCheckedSize((float)CDisplaySettings::Get().GetResolutionInfo(m_Resolution).iWidth * m_fZoom, - (float)CDisplaySettings::Get().GetResolutionInfo(m_Resolution).iHeight * m_fZoom, - maxWidth, maxHeight); - if (!m_slides->Get(m_iCurrentSlide)->IsVideo()) - m_pBackgroundLoader->LoadPic(m_iCurrentPic, m_iCurrentSlide, m_slides->Get(m_iCurrentSlide)->GetPath(), maxWidth, maxHeight); + CFileItemPtr item = m_slides->Get(m_iCurrentSlide); + CStdString picturePath = GetPicturePath(item.get()); + if (!picturePath.IsEmpty()) + { + if (item->IsVideo()) + CLog::Log(LOGDEBUG, "Loading the thumb %s for current video %d: %s", picturePath.c_str(), m_iCurrentSlide, item->GetPath().c_str()); + else + CLog::Log(LOGDEBUG, "Loading the current image %d: %s", m_iCurrentSlide, item->GetPath().c_str()); + + // load using the background loader + int maxWidth, maxHeight; + GetCheckedSize((float)CDisplaySettings::Get().GetResolutionInfo(m_Resolution).iWidth * m_fZoom, + (float)CDisplaySettings::Get().GetResolutionInfo(m_Resolution).iHeight * m_fZoom, + maxWidth, maxHeight); + m_pBackgroundLoader->LoadPic(m_iCurrentPic, m_iCurrentSlide, picturePath, maxWidth, maxHeight); + m_iLastFailedNextSlide = -1; + m_bLoadNextPic = false; + } } // check if we should discard an already loaded next slide - if (m_bLoadNextPic && m_Image[1 - m_iCurrentPic].IsLoaded() && m_Image[1 - m_iCurrentPic].SlideNumber() != m_iNextSlide) - m_Image[1 - m_iCurrentPic].Close(); - - // if we're reloading an image (for better res on zooming we need to close any open ones as well) - if (m_bReloadImage && m_Image[1 - m_iCurrentPic].IsLoaded() && m_Image[1 - m_iCurrentPic].SlideNumber() != m_iCurrentSlide) + if (m_Image[1 - m_iCurrentPic].IsLoaded() && m_Image[1 - m_iCurrentPic].SlideNumber() != m_iNextSlide) m_Image[1 - m_iCurrentPic].Close(); - if (m_bReloadImage) - { - if (m_Image[m_iCurrentPic].IsLoaded() && !m_Image[1 - m_iCurrentPic].IsLoaded() && !m_pBackgroundLoader->IsLoading() && !m_bWaitForNextPic) - { // reload the image if we need to - CLog::Log(LOGDEBUG, "Reloading the current image %s at zoom level %i", m_slides->Get(m_iCurrentSlide)->GetPath().c_str(), m_iZoomFactor); - // first, our maximal size for this zoom level - int maxWidth = (int)((float)CDisplaySettings::Get().GetResolutionInfo(m_Resolution).iWidth * m_fZoom); - int maxHeight = (int)((float)CDisplaySettings::Get().GetResolutionInfo(m_Resolution).iWidth * m_fZoom); - - // the actual maximal size of the image to optimize the sizing based on the known sizing (aspect ratio) - int width, height; - GetCheckedSize((float)m_Image[m_iCurrentPic].GetOriginalWidth(), (float)m_Image[m_iCurrentPic].GetOriginalHeight(), width, height); - - // use the smaller of the two (no point zooming in more than we have to) - if (maxWidth < width) - width = maxWidth; - if (maxHeight < height) - height = maxHeight; - - m_pBackgroundLoader->LoadPic(m_iCurrentPic, m_iCurrentSlide, m_slides->Get(m_iCurrentSlide)->GetPath(), width, height); - } - } - else - { - if (m_iNextSlide != m_iCurrentSlide && m_Image[m_iCurrentPic].IsLoaded() && !m_Image[1 - m_iCurrentPic].IsLoaded() && !m_pBackgroundLoader->IsLoading() && !m_bWaitForNextPic) - { // load the next image - CLog::Log(LOGDEBUG, "Loading the next image %s", m_slides->Get(m_iNextSlide)->GetPath().c_str()); + if (m_iNextSlide != m_iCurrentSlide && m_Image[m_iCurrentPic].IsLoaded() && !m_Image[1 - m_iCurrentPic].IsLoaded() && !m_pBackgroundLoader->IsLoading() && m_iLastFailedNextSlide != m_iNextSlide) + { // load the next image + m_iLastFailedNextSlide = -1; + CFileItemPtr item = m_slides->Get(m_iNextSlide); + CStdString picturePath = GetPicturePath(item.get()); + if (!picturePath.IsEmpty()) + { + if (item->IsVideo()) + CLog::Log(LOGDEBUG, "Loading the thumb %s for next video %d: %s", picturePath.c_str(), m_iNextSlide, item->GetPath().c_str()); + else + CLog::Log(LOGDEBUG, "Loading the next image %d: %s", m_iNextSlide, item->GetPath().c_str()); + int maxWidth, maxHeight; GetCheckedSize((float)CDisplaySettings::Get().GetResolutionInfo(m_Resolution).iWidth * m_fZoom, (float)CDisplaySettings::Get().GetResolutionInfo(m_Resolution).iHeight * m_fZoom, maxWidth, maxHeight); - if (!m_slides->Get(m_iNextSlide)->IsVideo()) - m_pBackgroundLoader->LoadPic(1 - m_iCurrentPic, m_iNextSlide, m_slides->Get(m_iNextSlide)->GetPath(), maxWidth, maxHeight); + m_pBackgroundLoader->LoadPic(1 - m_iCurrentPic, m_iNextSlide, picturePath, maxWidth, maxHeight); } } + if (m_slides->Get(m_iCurrentSlide)->IsVideo() && bSlideShow) + { + if (!PlayVideo()) + return; + bSlideShow = false; + } + // render the current image if (m_Image[m_iCurrentPic].IsLoaded()) { - m_Image[m_iCurrentPic].SetInSlideshow(m_bSlideShow); - m_Image[m_iCurrentPic].Pause(m_bPause); + m_Image[m_iCurrentPic].SetInSlideshow(bSlideShow); + m_Image[m_iCurrentPic].Pause(!bSlideShow); m_Image[m_iCurrentPic].Process(currentTime, regions); } - if (m_slides->Get(m_iCurrentSlide)->IsVideo() && bSlideShow) - { - CLog::Log(LOGDEBUG, "Playing slide %s as video", m_slides->Get(m_iCurrentSlide)->GetPath().c_str()); - m_bPlayingVideo = true; - CApplicationMessenger::Get().PlayFile(*m_slides->Get(m_iCurrentSlide)); - m_iCurrentSlide = m_iNextSlide; - m_iNextSlide = GetNextSlide(); - } - // Check if we should be transistioning immediately - if (m_bLoadNextPic) + if (m_bLoadNextPic && m_Image[m_iCurrentPic].IsLoaded()) { CLog::Log(LOGDEBUG, "Starting immediate transistion due to user wanting slide %s", m_slides->Get(m_iNextSlide)->GetPath().c_str()); if (m_Image[m_iCurrentPic].StartTransistion()) @@ -547,9 +576,16 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re { if (m_Image[1 - m_iCurrentPic].IsLoaded()) { + // first time render the next image, make sure using current display effect. + if (!m_Image[1 - m_iCurrentPic].IsStarted()) + { + CSlideShowPic::DISPLAY_EFFECT effect = GetDisplayEffect(m_iNextSlide); + if (m_Image[1 - m_iCurrentPic].DisplayEffectNeedChange(effect)) + m_Image[1 - m_iCurrentPic].Reset(effect); + } // set the appropriate transistion time m_Image[1 - m_iCurrentPic].SetTransistionTime(0, m_Image[m_iCurrentPic].GetTransistionTime(1)); - m_Image[1 - m_iCurrentPic].Pause(m_bPause); + m_Image[1 - m_iCurrentPic].Pause(!m_bSlideShow || m_bPause || m_slides->Get(m_iNextSlide)->IsVideo()); m_Image[1 - m_iCurrentPic].Process(currentTime, regions); } else // next pic isn't loaded. We should hang around if it is in progress @@ -563,15 +599,37 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re } // check if we should swap images now - if (m_Image[m_iCurrentPic].IsFinished()) + if (m_Image[m_iCurrentPic].IsFinished() || (m_bLoadNextPic && !m_Image[m_iCurrentPic].IsLoaded())) { - CLog::Log(LOGDEBUG, "Image %s is finished rendering, switching to %s", m_slides->Get(m_iCurrentSlide)->GetPath().c_str(), m_slides->Get(m_iNextSlide)->GetPath().c_str()); - m_Image[m_iCurrentPic].Close(); - if (m_Image[1 - m_iCurrentPic].IsLoaded()) - m_iCurrentPic = 1 - m_iCurrentPic; + m_bLoadNextPic = false; + if (m_Image[m_iCurrentPic].IsFinished()) + CLog::Log(LOGDEBUG, "Image %s is finished rendering, switching to %s", m_slides->Get(m_iCurrentSlide)->GetPath().c_str(), m_slides->Get(m_iNextSlide)->GetPath().c_str()); + else + // what if it's bg loading? + CLog::Log(LOGDEBUG, "Image %s is not loaded, switching to %s", m_slides->Get(m_iCurrentSlide)->GetPath().c_str(), m_slides->Get(m_iNextSlide)->GetPath().c_str()); - m_iCurrentSlide = m_iNextSlide; - m_iNextSlide = GetNextSlide(); + if (m_Image[m_iCurrentPic].IsFinished() && m_iCurrentSlide == m_iNextSlide && m_Image[m_iCurrentPic].SlideNumber() == m_iNextSlide) + m_Image[m_iCurrentPic].Reset(GetDisplayEffect(m_iCurrentSlide)); + else + { + if (m_Image[m_iCurrentPic].IsLoaded()) + m_Image[m_iCurrentPic].Reset(GetDisplayEffect(m_iCurrentSlide)); + else + m_Image[m_iCurrentPic].Close(); + + if ((m_Image[1 - m_iCurrentPic].IsLoaded() && m_Image[1 - m_iCurrentPic].SlideNumber() == m_iNextSlide) || + (m_pBackgroundLoader->IsLoading() && m_pBackgroundLoader->SlideNumber() == m_iNextSlide && m_pBackgroundLoader->Pic() == 1 - m_iCurrentPic)) + { + m_iCurrentPic = 1 - m_iCurrentPic; + } + else + { + m_Image[1 - m_iCurrentPic].Close(); + m_iCurrentPic = 1 - m_iCurrentPic; + } + m_iCurrentSlide = m_iNextSlide; + m_iNextSlide = GetNextSlide(); + } AnnouncePlayerPlay(m_slides->Get(m_iCurrentSlide)); m_iZoomFactor = 1; @@ -602,10 +660,15 @@ int CGUIWindowSlideShow::GetNextSlide() { if (m_slides->Size() <= 1) return m_iCurrentSlide; - if (m_bSlideShow || m_iDirection >= 0) - return (m_iCurrentSlide + 1) % m_slides->Size(); - - return (m_iCurrentSlide - 1 + m_slides->Size()) % m_slides->Size(); + int step = m_iDirection >= 0 ? 1 : -1; + int nextSlide = (m_iCurrentSlide + step + m_slides->Size()) % m_slides->Size(); + while (nextSlide != m_iCurrentSlide) + { + if (!m_slides->Get(nextSlide)->HasProperty("unplayable")) + return nextSlide; + nextSlide = (nextSlide + step + m_slides->Size()) % m_slides->Size(); + } + return m_iCurrentSlide; } EVENT_RESULT CGUIWindowSlideShow::OnMouseEvent(const CPoint &point, const CMouseEvent &event) @@ -738,30 +801,38 @@ bool CGUIWindowSlideShow::OnAction(const CAction &action) break; case ACTION_PAUSE: - if (m_bSlideShow) + case ACTION_PLAYER_PLAY: + if (m_slides->Size() == 0) + break; + if (m_slides->Get(m_iCurrentSlide)->IsVideo()) { - m_bPause = !m_bPause; - if (m_slides->Size()) + if (!m_bPlayingVideo) { - if (m_bPause) - AnnouncePlayerPause(m_slides->Get(m_iCurrentSlide)); - else - AnnouncePlayerPlay(m_slides->Get(m_iCurrentSlide)); + if (m_bSlideShow) + { + SetDirection(1); + m_bPause = false; + } + PlayVideo(); } } - break; - - case ACTION_PLAYER_PLAY: - if (!m_bSlideShow) + else if (!m_bSlideShow || m_bPause) { m_bSlideShow = true; m_bPause = false; + SetDirection(1); + if (m_Image[m_iCurrentPic].IsLoaded()) + { + CSlideShowPic::DISPLAY_EFFECT effect = GetDisplayEffect(m_iCurrentSlide); + if (m_Image[m_iCurrentPic].DisplayEffectNeedChange(effect)) + m_Image[m_iCurrentPic].Reset(effect); + } + AnnouncePlayerPlay(m_slides->Get(m_iCurrentSlide)); } - else if (m_bPause) + else if (action.GetID() == ACTION_PAUSE) { - m_bPause = false; - if (m_slides->Size()) - AnnouncePlayerPlay(m_slides->Get(m_iCurrentSlide)); + m_bPause = true; + AnnouncePlayerPause(m_slides->Get(m_iCurrentSlide)); } break; @@ -838,7 +909,7 @@ bool CGUIWindowSlideShow::OnMessage(CGUIMessage& message) { case GUI_MSG_WINDOW_INIT: { - m_Resolution = (RESOLUTION) g_guiSettings.GetInt("pictures.displayresolution"); + m_Resolution = (RESOLUTION) CSettings::Get().GetInt("pictures.displayresolution"); //FIXME: Use GUI resolution for now if (0 /*m_Resolution != CDisplaySettings::Get().GetCurrentResolution() && m_Resolution != INVALID && m_Resolution!=AUTORES*/) @@ -860,6 +931,16 @@ bool CGUIWindowSlideShow::OnMessage(CGUIMessage& message) } break; + case GUI_MSG_SHOW_PICTURE: + { + CStdString strFile = message.GetStringParam(); + Reset(); + CFileItem item(strFile, false); + Add(&item); + RunSlideShow("", false, false, true, "", false); + } + break; + case GUI_MSG_START_SLIDESHOW: { CStdString strFolder = message.GetStringParam(); @@ -881,31 +962,52 @@ bool CGUIWindowSlideShow::OnMessage(CGUIMessage& message) if ((iParams & 8) == 8) bPause = true; } - RunSlideShow(strFolder, bRecursive, bRandom, bNotRandom, SORT_METHOD_LABEL, SortOrderAscending, "", beginSlidePath, !bPause); + RunSlideShow(strFolder, bRecursive, bRandom, bNotRandom, beginSlidePath, !bPause); } break; case GUI_MSG_PLAYLISTPLAYER_STOPPED: { - m_bPlayingVideo = false; - if (m_bSlideShow) - g_windowManager.ActivateWindow(WINDOW_SLIDESHOW); } break; case GUI_MSG_PLAYBACK_STARTED: { - if (m_bSlideShow && m_bPlayingVideo) + if (m_bPlayingVideo) g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO); } break; case GUI_MSG_PLAYBACK_STOPPED: { - if (m_bSlideShow && m_bPlayingVideo) + if (m_bPlayingVideo) + { + m_bPlayingVideo = false; + if (m_bSlideShow) + m_bPause = true; + } + } + break; + + case GUI_MSG_PLAYBACK_ENDED: + { + if (m_bPlayingVideo) { - m_bSlideShow = false; - g_windowManager.PreviousWindow(); + m_bPlayingVideo = false; + if (m_bSlideShow) + { + m_bPause = false; + if (m_iCurrentSlide == m_iNextSlide) + break; + m_Image[m_iCurrentPic].Close(); + m_iCurrentPic = 1 - m_iCurrentPic; + m_iCurrentSlide = m_iNextSlide; + m_iNextSlide = GetNextSlide(); + AnnouncePlayerPlay(m_slides->Get(m_iCurrentSlide)); + m_iZoomFactor = 1; + m_fZoom = 1.0f; + m_fRotate = 0.0f; + } } } break; @@ -966,9 +1068,6 @@ void CGUIWindowSlideShow::ZoomRelative(float fZoom, bool immediate /* = false */ m_fZoom = fZoom; // find the nearest zoom factor -#ifdef RELOAD_ON_ZOOM - int iOldZoomFactor = m_iZoomFactor; -#endif for (unsigned int i = 1; i < MAX_ZOOM_FACTOR; i++) { if (m_fZoom > zoomamount[i]) @@ -982,14 +1081,7 @@ void CGUIWindowSlideShow::ZoomRelative(float fZoom, bool immediate /* = false */ break; } - // set the zoom amount and then set so that the image is reloaded at the higher (or lower) - // resolution as necessary m_Image[m_iCurrentPic].Zoom(m_fZoom, immediate); - -#ifdef RELOAD_ON_ZOOM - if (m_iZoomFactor == 1 || (iZoomFactor > iOldZoomFactor && !m_Image[m_iCurrentPic].FullSize())) - m_bReloadImage = true; -#endif } void CGUIWindowSlideShow::Move(float fX, float fY) @@ -1001,50 +1093,66 @@ void CGUIWindowSlideShow::Move(float fX, float fY) } } -void CGUIWindowSlideShow::OnLoadPic(int iPic, int iSlideNumber, CBaseTexture* pTexture, bool bFullSize) +bool CGUIWindowSlideShow::PlayVideo() +{ + CFileItemPtr item = m_slides->Get(m_iCurrentSlide); + if (!item || !item->IsVideo()) + return false; + CLog::Log(LOGDEBUG, "Playing current video slide %s", item->GetPath().c_str()); + m_bPlayingVideo = true; + PlayBackRet ret = g_application.PlayFile(*item); + if (ret == PLAYBACK_OK) + return true; + if (ret == PLAYBACK_FAIL) + { + CLog::Log(LOGINFO, "set video %s unplayable", item->GetPath().c_str()); + item->SetProperty("unplayable", true); + } + else if (ret == PLAYBACK_CANCELED) + m_bPause = true; + m_bPlayingVideo = false; + return false; +} + +CSlideShowPic::DISPLAY_EFFECT CGUIWindowSlideShow::GetDisplayEffect(int iSlideNumber) const +{ + if (m_bSlideShow && !m_bPause && !m_slides->Get(iSlideNumber)->IsVideo()) + return CSettings::Get().GetBool("slideshow.displayeffects") ? CSlideShowPic::EFFECT_RANDOM : CSlideShowPic::EFFECT_NONE; + else + return CSlideShowPic::EFFECT_NO_TIMEOUT; +} + +void CGUIWindowSlideShow::OnLoadPic(int iPic, int iSlideNumber, const CStdString &strFileName, CBaseTexture* pTexture, bool bFullSize) { if (pTexture) { // set the pic's texture + size etc. CSingleLock lock(m_slideSection); - if (iSlideNumber >= m_slides->Size()) + if (iSlideNumber >= m_slides->Size() || GetPicturePath(m_slides->Get(iSlideNumber).get()) != strFileName) { // throw this away - we must have cleared the slideshow while we were still loading delete pTexture; return; } - CLog::Log(LOGDEBUG, "Finished background loading %s", m_slides->Get(iSlideNumber)->GetPath().c_str()); - if (m_bReloadImage) - { - if (m_Image[m_iCurrentPic].IsLoaded() && m_Image[m_iCurrentPic].SlideNumber() != iSlideNumber) - { // wrong image (ie we finished loading the next image, not the current image) - delete pTexture; - return; - } - m_Image[m_iCurrentPic].UpdateTexture(pTexture); - m_Image[m_iCurrentPic].SetOriginalSize(pTexture->GetOriginalWidth(), pTexture->GetOriginalHeight(), bFullSize); - m_bReloadImage = false; - } - else + CLog::Log(LOGDEBUG, "Finished background loading slot %d, %d: %s", iPic, iSlideNumber, m_slides->Get(iSlideNumber)->GetPath().c_str()); + m_Image[iPic].SetTexture(iSlideNumber, pTexture, GetDisplayEffect(iSlideNumber)); + m_Image[iPic].SetOriginalSize(pTexture->GetOriginalWidth(), pTexture->GetOriginalHeight(), bFullSize); + + m_Image[iPic].m_bIsComic = false; + if (URIUtils::IsInRAR(m_slides->Get(m_iCurrentSlide)->GetPath()) || URIUtils::IsInZIP(m_slides->Get(m_iCurrentSlide)->GetPath())) // move to top for cbr/cbz { - if (m_bSlideShow) - m_Image[iPic].SetTexture(iSlideNumber, pTexture, g_guiSettings.GetBool("slideshow.displayeffects") ? CSlideShowPic::EFFECT_RANDOM : CSlideShowPic::EFFECT_NONE); - else - m_Image[iPic].SetTexture(iSlideNumber, pTexture, CSlideShowPic::EFFECT_NO_TIMEOUT); - m_Image[iPic].SetOriginalSize(pTexture->GetOriginalWidth(), pTexture->GetOriginalHeight(), bFullSize); - - m_Image[iPic].m_bIsComic = false; - if (URIUtils::IsInRAR(m_slides->Get(m_iCurrentSlide)->GetPath()) || URIUtils::IsInZIP(m_slides->Get(m_iCurrentSlide)->GetPath())) // move to top for cbr/cbz + CURL url(m_slides->Get(m_iCurrentSlide)->GetPath()); + CStdString strHostName = url.GetHostName(); + if (URIUtils::GetExtension(strHostName).Equals(".cbr", false) || URIUtils::GetExtension(strHostName).Equals(".cbz", false)) { - CURL url(m_slides->Get(m_iCurrentSlide)->GetPath()); - CStdString strHostName = url.GetHostName(); - if (URIUtils::GetExtension(strHostName).Equals(".cbr", false) || URIUtils::GetExtension(strHostName).Equals(".cbz", false)) - { - m_Image[iPic].m_bIsComic = true; - m_Image[iPic].Move((float)m_Image[iPic].GetOriginalWidth(),(float)m_Image[iPic].GetOriginalHeight()); - } + m_Image[iPic].m_bIsComic = true; + m_Image[iPic].Move((float)m_Image[iPic].GetOriginalWidth(),(float)m_Image[iPic].GetOriginalHeight()); } } } + else if (iSlideNumber >= m_slides->Size() || GetPicturePath(m_slides->Get(iSlideNumber).get()) != strFileName) + { // Failed to load image. and not match values calling LoadPic, then something is changed, ignore. + CLog::Log(LOGDEBUG, "CGUIWindowSlideShow::OnLoadPic(%d, %d, %s) on failure not match current state (cur %d, next %d, curpic %d, pic[0, 1].slidenumber=%d, %d, %s)", iPic, iSlideNumber, strFileName.c_str(), m_iCurrentSlide, m_iNextSlide, m_iCurrentPic, m_Image[0].SlideNumber(), m_Image[1].SlideNumber(), iSlideNumber >= m_slides->Size() ? "" : m_slides->Get(iSlideNumber)->GetPath().c_str()); + } else { // Failed to load image. What should be done?? // We should wait for the current pic to finish rendering, then transistion it out, @@ -1057,7 +1165,7 @@ void CGUIWindowSlideShow::Shuffle() { m_slides->Randomize(); m_iCurrentSlide = 0; - m_iNextSlide = 1; + m_iNextSlide = GetNextSlide(); m_bShuffled = true; AnnouncePropertyChanged("shuffled", true); @@ -1094,9 +1202,9 @@ void CGUIWindowSlideShow::AddFromPath(const CStdString &strPath, void CGUIWindowSlideShow::RunSlideShow(const CStdString &strPath, bool bRecursive /* = false */, bool bRandom /* = false */, - bool bNotRandom /* = false */, SORT_METHOD method /* = SORT_METHOD_LABEL */, - SortOrder order /* = SortOrderAscending */, const CStdString &strExtensions /* = "" */, - const CStdString &beginSlidePath /* = "" */, bool startSlideShow /* = true */) + bool bNotRandom /* = false */, const CStdString &beginSlidePath /* = "" */, + bool startSlideShow /* = true */, SORT_METHOD method /* = SORT_METHOD_LABEL */, + SortOrder order /* = SortOrderAscending */, const CStdString &strExtensions /* = "" */) { // stop any video if (g_application.IsPlayingVideo()) @@ -1113,7 +1221,7 @@ void CGUIWindowSlideShow::RunSlideShow(const CStdString &strPath, bRandom = bNotRandom = false; // NotRandom overrides the window setting - if ((!bNotRandom && g_guiSettings.GetBool("slideshow.shuffle")) || bRandom) + if ((!bNotRandom && CSettings::Get().GetBool("slideshow.shuffle")) || bRandom) Shuffle(); if (!beginSlidePath.IsEmpty()) @@ -1168,23 +1276,26 @@ void CGUIWindowSlideShow::AddItems(const CStdString &strPath, path_set *recursiv void CGUIWindowSlideShow::GetCheckedSize(float width, float height, int &maxWidth, int &maxHeight) { -#ifdef RELOAD_ON_ZOOM - if (width * height > MAX_PICTURE_SIZE) - { - float fScale = sqrt((float)MAX_PICTURE_SIZE / (width * height)); - width = fScale * width; - height = fScale * height; - } - maxWidth = (int)width; - maxHeight = (int)height; - if (maxWidth > (int)g_Windowing.GetMaxTextureSize()) - maxWidth = g_Windowing.GetMaxTextureSize(); - if (maxHeight > (int)g_Windowing.GetMaxTextureSize()) - maxHeight = g_Windowing.GetMaxTextureSize(); -#else maxWidth = g_Windowing.GetMaxTextureSize(); maxHeight = g_Windowing.GetMaxTextureSize(); -#endif } +CStdString CGUIWindowSlideShow::GetPicturePath(CFileItem *item) +{ + bool isVideo = item->IsVideo(); + CStdString picturePath = item->GetPath(); + if (isVideo) + { + picturePath = item->GetArt("thumb"); + if (picturePath.IsEmpty() && !item->HasProperty("nothumb")) + { + CPictureThumbLoader thumbLoader; + thumbLoader.LoadItem(item); + picturePath = item->GetArt("thumb"); + if (picturePath.IsEmpty()) + item->SetProperty("nothumb", true); + } + } + return picturePath; +} diff --git a/xbmc/pictures/GUIWindowSlideShow.h b/xbmc/pictures/GUIWindowSlideShow.h index 02c652083a..2328fdaf84 100644 --- a/xbmc/pictures/GUIWindowSlideShow.h +++ b/xbmc/pictures/GUIWindowSlideShow.h @@ -43,6 +43,8 @@ public: void Create(CGUIWindowSlideShow *pCallback); void LoadPic(int iPic, int iSlideNumber, const CStdString &strFileName, const int maxWidth, const int maxHeight); bool IsLoading() { return m_isLoading;}; + int SlideNumber() const { return m_iSlideNumber; } + int Pic() const { return m_iPic; } private: void Process(); @@ -75,9 +77,9 @@ public: const CFileItemPtr GetCurrentSlide(); void RunSlideShow(const CStdString &strPath, bool bRecursive = false, bool bRandom = false, bool bNotRandom = false, + const CStdString &beginSlidePath="", bool startSlideShow = true, SORT_METHOD method = SORT_METHOD_LABEL, - SortOrder order = SortOrderAscending, const CStdString &strExtensions="", - const CStdString &beginSlidePath="", bool startSlideShow = true); + SortOrder order = SortOrderAscending, const CStdString &strExtensions=""); void AddFromPath(const CStdString &strPath, bool bRecursive, SORT_METHOD method=SORT_METHOD_LABEL, SortOrder order = SortOrderAscending, const CStdString &strExtensions=""); @@ -89,18 +91,21 @@ public: virtual void Render(); virtual void Process(unsigned int currentTime, CDirtyRegionList ®ions); virtual void OnDeinitWindow(int nextWindowID); - void OnLoadPic(int iPic, int iSlideNumber, CBaseTexture* pTexture, bool bFullSize); + void OnLoadPic(int iPic, int iSlideNumber, const CStdString &strFileName, CBaseTexture* pTexture, bool bFullSize); int NumSlides() const; int CurrentSlide() const; void Shuffle(); bool IsPaused() const { return m_bPause; } bool IsShuffled() const { return m_bShuffled; } int GetDirection() const { return m_iDirection; } + void SetDirection(int direction); // -1: rewind, 1: forward private: typedef std::set<CStdString> path_set; // set to track which paths we're adding void AddItems(const CStdString &strPath, path_set *recursivePaths, SORT_METHOD method = SORT_METHOD_LABEL, SortOrder order = SortOrderAscending); + bool PlayVideo(); + CSlideShowPic::DISPLAY_EFFECT GetDisplayEffect(int iSlideNumber) const; void RenderPause(); void RenderErrorMessage(); void Rotate(float fAngle, bool immediate = false); @@ -108,6 +113,7 @@ private: void ZoomRelative(float fZoom, bool immediate = false); void Move(float fX, float fY); void GetCheckedSize(float width, float height, int &maxWidth, int &maxHeight); + CStdString GetPicturePath(CFileItem *item); int GetNextSlide(); void AnnouncePlayerPlay(const CFileItemPtr& item); @@ -140,9 +146,8 @@ private: int m_iCurrentPic; // background loader CBackgroundPicLoader* m_pBackgroundLoader; - bool m_bWaitForNextPic; + int m_iLastFailedNextSlide; bool m_bLoadNextPic; - bool m_bReloadImage; DllImageLib m_ImageLib; RESOLUTION m_Resolution; CCriticalSection m_slideSection; diff --git a/xbmc/pictures/Picture.cpp b/xbmc/pictures/Picture.cpp index 4fd93d0b4e..27a70c5c97 100644 --- a/xbmc/pictures/Picture.cpp +++ b/xbmc/pictures/Picture.cpp @@ -25,7 +25,7 @@ #include "Picture.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "FileItem.h" #include "filesystem/File.h" #include "utils/log.h" @@ -184,7 +184,7 @@ bool CPicture::CreateTiledThumb(const std::vector<std::string> &files, const std int y = i / num_across; // load in the image unsigned int width = tile_width - 2*tile_gap, height = tile_height - 2*tile_gap; - CBaseTexture *texture = CTexture::LoadFromFile(files[i], width, height, g_guiSettings.GetBool("pictures.useexifrotation")); + CBaseTexture *texture = CTexture::LoadFromFile(files[i], width, height, CSettings::Get().GetBool("pictures.useexifrotation")); if (texture && texture->GetWidth() && texture->GetHeight()) { GetScale(texture->GetWidth(), texture->GetHeight(), width, height); diff --git a/xbmc/pictures/PictureInfoLoader.cpp b/xbmc/pictures/PictureInfoLoader.cpp index ab6ec96d2c..00b30d3d9f 100644 --- a/xbmc/pictures/PictureInfoLoader.cpp +++ b/xbmc/pictures/PictureInfoLoader.cpp @@ -20,7 +20,7 @@ #include "PictureInfoLoader.h" #include "PictureInfoTag.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "FileItem.h" CPictureInfoLoader::CPictureInfoLoader() @@ -42,7 +42,7 @@ void CPictureInfoLoader::OnLoaderStart() m_mapFileItems->SetFastLookup(true); m_tagReads = 0; - m_loadTags = g_guiSettings.GetBool("pictures.usetags"); + m_loadTags = CSettings::Get().GetBool("pictures.usetags"); if (m_pProgressCallback) m_pProgressCallback->SetProgressMax(m_pVecItems->GetFileCount()); diff --git a/xbmc/pictures/PictureThumbLoader.cpp b/xbmc/pictures/PictureThumbLoader.cpp index 61c624d3b4..2eb57f6a07 100644 --- a/xbmc/pictures/PictureThumbLoader.cpp +++ b/xbmc/pictures/PictureThumbLoader.cpp @@ -27,9 +27,9 @@ #include "filesystem/MultiPathDirectory.h" #include "guilib/GUIWindowManager.h" #include "GUIUserMessages.h" -#include "settings/GUISettings.h" #include "utils/URIUtils.h" #include "settings/AdvancedSettings.h" +#include "settings/Settings.h" #include "video/VideoThumbLoader.h" using namespace XFILE; @@ -73,7 +73,7 @@ bool CPictureThumbLoader::LoadItem(CFileItem* pItem) { thumb = thumbURL; } - else if (g_guiSettings.GetBool("myvideos.extractthumb") && g_guiSettings.GetBool("myvideos.extractflags")) + else if (CSettings::Get().GetBool("myvideos.extractthumb") && CSettings::Get().GetBool("myvideos.extractflags")) { CFileItem item(*pItem); CThumbExtractor* extract = new CThumbExtractor(item, pItem->GetPath(), true, thumbURL); diff --git a/xbmc/pictures/SlideShowPicture.cpp b/xbmc/pictures/SlideShowPicture.cpp index 8c2b282ff6..7419c39a47 100644 --- a/xbmc/pictures/SlideShowPicture.cpp +++ b/xbmc/pictures/SlideShowPicture.cpp @@ -25,7 +25,6 @@ #include "settings/AdvancedSettings.h" #include "settings/DisplaySettings.h" #include "settings/Settings.h" -#include "settings/GUISettings.h" #include "windowing/WindowingFactory.h" #include "utils/log.h" #include "threads/SingleLock.h" @@ -79,10 +78,34 @@ void CSlideShowPic::Close() m_bIsDirty = true; } +void CSlideShowPic::Reset(DISPLAY_EFFECT dispEffect, TRANSISTION_EFFECT transEffect) +{ + CSingleLock lock(m_textureAccess); + if (m_pImage) + SetTexture_Internal(m_iSlideNumber, m_pImage, dispEffect, transEffect); + else + Close(); +} + +bool CSlideShowPic::DisplayEffectNeedChange(DISPLAY_EFFECT newDispEffect) const +{ + if (m_displayEffect == newDispEffect) + return false; + if (newDispEffect == EFFECT_RANDOM && m_displayEffect != EFFECT_NONE && m_displayEffect != EFFECT_NO_TIMEOUT) + return false; + return true; +} + void CSlideShowPic::SetTexture(int iSlideNumber, CBaseTexture* pTexture, DISPLAY_EFFECT dispEffect, TRANSISTION_EFFECT transEffect) { CSingleLock lock(m_textureAccess); Close(); + SetTexture_Internal(iSlideNumber, pTexture, dispEffect, transEffect); +} + +void CSlideShowPic::SetTexture_Internal(int iSlideNumber, CBaseTexture* pTexture, DISPLAY_EFFECT dispEffect, TRANSISTION_EFFECT transEffect) +{ + CSingleLock lock(m_textureAccess); m_bPause = false; m_bNoEffect = false; m_bTransistionImmediately = false; @@ -98,7 +121,7 @@ void CSlideShowPic::SetTexture(int iSlideNumber, CBaseTexture* pTexture, DISPLAY m_transistionStart.type = transEffect; m_transistionStart.start = 0; // the +1's make sure it actually occurs - float fadeTime = std::min(0.2f*g_guiSettings.GetInt("slideshow.staytime"), 3.0f); + float fadeTime = std::min(0.2f*CSettings::Get().GetInt("slideshow.staytime"), 3.0f); m_transistionStart.length = (int)(g_graphicsContext.GetFPS() * fadeTime); // transition time in frames m_transistionEnd.type = transEffect; m_transistionEnd.length = m_transistionStart.length; @@ -134,7 +157,7 @@ void CSlideShowPic::SetTexture(int iSlideNumber, CBaseTexture* pTexture, DISPLAY m_fPosX = m_fPosY = 0.0f; m_fPosZ = 1.0f; m_fVelocityX = m_fVelocityY = m_fVelocityZ = 0.0f; - int iFrames = max((int)(g_graphicsContext.GetFPS() * g_guiSettings.GetInt("slideshow.staytime")), 1); + int iFrames = max((int)(g_graphicsContext.GetFPS() * CSettings::Get().GetInt("slideshow.staytime")), 1); if (m_displayEffect == EFFECT_PANORAMA) { RESOLUTION iRes = g_graphicsContext.GetVideoResolution(); @@ -344,9 +367,9 @@ void CSlideShowPic::Process(unsigned int currentTime, CDirtyRegionList &dirtyreg else if (m_displayEffect == EFFECT_ZOOM) { m_fPosZ += m_fVelocityZ; -/* if (m_fPosZ > 1.0f + 0.01f*g_guiSettings.GetInt("Slideshow.ZoomAmount")) +/* if (m_fPosZ > 1.0f + 0.01f*CSettings::Get().GetInt("Slideshow.ZoomAmount")) { - m_fPosZ = 1.0f + 0.01f * g_guiSettings.GetInt("Slideshow.ZoomAmount"); + m_fPosZ = 1.0f + 0.01f * CSettings::Get().GetInt("Slideshow.ZoomAmount"); m_fVelocityZ = -m_fVelocityZ; } if (m_fPosZ < 1.0f) @@ -675,7 +698,7 @@ void CSlideShowPic::Rotate(float fRotateAngle, bool immediate /* = false */) m_transistionTemp.length = IMMEDIATE_TRANSISTION_TIME; m_fTransistionAngle = (float)fRotateAngle / (float)m_transistionTemp.length; // reset the timer - m_transistionEnd.start = m_iCounter + m_transistionStart.length + (int)(g_graphicsContext.GetFPS() * g_guiSettings.GetInt("slideshow.staytime")); + m_transistionEnd.start = m_iCounter + m_transistionStart.length + (int)(g_graphicsContext.GetFPS() * CSettings::Get().GetInt("slideshow.staytime")); } void CSlideShowPic::Zoom(float fZoom, bool immediate /* = false */) @@ -692,7 +715,7 @@ void CSlideShowPic::Zoom(float fZoom, bool immediate /* = false */) m_transistionTemp.length = IMMEDIATE_TRANSISTION_TIME; m_fTransistionZoom = (fZoom - m_fZoomAmount) / (float)m_transistionTemp.length; // reset the timer - m_transistionEnd.start = m_iCounter + m_transistionStart.length + (int)(g_graphicsContext.GetFPS() * g_guiSettings.GetInt("slideshow.staytime")); + m_transistionEnd.start = m_iCounter + m_transistionStart.length + (int)(g_graphicsContext.GetFPS() * CSettings::Get().GetInt("slideshow.staytime")); // turn off the render effects until we're back down to normal zoom m_bNoEffect = true; } @@ -702,7 +725,7 @@ void CSlideShowPic::Move(float fDeltaX, float fDeltaY) m_fZoomLeft += fDeltaX; m_fZoomTop += fDeltaY; // reset the timer - // m_transistionEnd.start = m_iCounter + m_transistionStart.length + (int)(g_graphicsContext.GetFPS() * g_guiSettings.GetInt("slideshow.staytime")); + // m_transistionEnd.start = m_iCounter + m_transistionStart.length + (int)(g_graphicsContext.GetFPS() * CSettings::Get().GetInt("slideshow.staytime")); } void CSlideShowPic::Render() diff --git a/xbmc/pictures/SlideShowPicture.h b/xbmc/pictures/SlideShowPicture.h index 728a9deaa6..c38aba0fc6 100644 --- a/xbmc/pictures/SlideShowPicture.h +++ b/xbmc/pictures/SlideShowPicture.h @@ -52,6 +52,10 @@ public: void Process(unsigned int currentTime, CDirtyRegionList &dirtyregions); void Render(); void Close(); + void Reset(DISPLAY_EFFECT dispEffect = EFFECT_RANDOM, TRANSISTION_EFFECT transEffect = FADEIN_FADEOUT); + DISPLAY_EFFECT DisplayEffect() const { return m_displayEffect; } + bool DisplayEffectNeedChange(DISPLAY_EFFECT newDispEffect) const; + bool IsStarted() const { return m_iCounter > 0; } bool IsFinished() const { return m_bIsFinished;}; bool DrawNextImage() const { return m_bDrawNextImage;}; @@ -81,6 +85,7 @@ public: bool m_bCanMoveHorizontally; bool m_bCanMoveVertically; private: + void SetTexture_Internal(int iSlideNumber, CBaseTexture* pTexture, DISPLAY_EFFECT dispEffect = EFFECT_RANDOM, TRANSISTION_EFFECT transEffect = FADEIN_FADEOUT); void UpdateVertices(float cur_x[4], float cur_y[4], const float new_x[4], const float new_y[4], CDirtyRegionList &dirtyregions); void Render(float *x, float *y, CBaseTexture* pTexture, color_t color); CBaseTexture *m_pImage; diff --git a/xbmc/powermanagement/PowerManager.cpp b/xbmc/powermanagement/PowerManager.cpp index 0756b1e1b1..f671959111 100644 --- a/xbmc/powermanagement/PowerManager.cpp +++ b/xbmc/powermanagement/PowerManager.cpp @@ -23,7 +23,7 @@ #include "Application.h" #include "cores/AudioEngine/AEFactory.h" #include "input/KeyboardStat.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "windowing/WindowingFactory.h" #include "utils/log.h" #include "utils/Weather.h" @@ -95,7 +95,7 @@ void CPowerManager::Initialize() void CPowerManager::SetDefaults() { - int defaultShutdown = g_guiSettings.GetInt("powermanagement.shutdownstate"); + int defaultShutdown = CSettings::Get().GetInt("powermanagement.shutdownstate"); switch (defaultShutdown) { @@ -134,7 +134,7 @@ void CPowerManager::SetDefaults() break; } - g_guiSettings.SetInt("powermanagement.shutdownstate", defaultShutdown); + ((CSettingInt*)CSettings::Get().GetSetting("powermanagement.shutdownstate"))->SetDefault(defaultShutdown); } bool CPowerManager::Powerdown() @@ -285,3 +285,20 @@ void CPowerManager::OnLowBattery() CAnnouncementManager::Announce(System, "xbmc", "OnLowBattery"); } + +void CPowerManager::SettingOptionsShutdownStatesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t) +{ + if (g_powerManager.CanPowerdown()) + list.push_back(make_pair(g_localizeStrings.Get(13005), POWERSTATE_SHUTDOWN)); + if (g_powerManager.CanHibernate()) + list.push_back(make_pair(g_localizeStrings.Get(13010), POWERSTATE_HIBERNATE)); + if (g_powerManager.CanSuspend()) + list.push_back(make_pair(g_localizeStrings.Get(13011), POWERSTATE_SUSPEND)); + if (!g_application.IsStandAlone()) + { + list.push_back(make_pair(g_localizeStrings.Get(13009), POWERSTATE_QUIT)); +#if !defined(TARGET_DARWIN_IOS) + list.push_back(make_pair(g_localizeStrings.Get(13014), POWERSTATE_MINIMIZE)); +#endif + } +} diff --git a/xbmc/powermanagement/PowerManager.h b/xbmc/powermanagement/PowerManager.h index 1a5c51fbc1..a78bac8c5b 100644 --- a/xbmc/powermanagement/PowerManager.h +++ b/xbmc/powermanagement/PowerManager.h @@ -20,8 +20,26 @@ #ifndef _POWER_MANAGER_H_ #define _POWER_MANAGER_H_ + +#include <string> +#include <vector> + #include "IPowerSyscall.h" +class CSetting; + +enum PowerState +{ + POWERSTATE_QUIT = 0, + POWERSTATE_SHUTDOWN, + POWERSTATE_HIBERNATE, + POWERSTATE_SUSPEND, + POWERSTATE_REBOOT, + POWERSTATE_MINIMIZE, + POWERSTATE_NONE, + POWERSTATE_ASK +}; + // For systems without PowerSyscalls we have a NullObject class CNullPowerSyscall : public IPowerSyscall { @@ -66,6 +84,9 @@ public: int BatteryLevel(); void ProcessEvents(); + + static void SettingOptionsShutdownStatesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t); + private: void OnSleep(); void OnWake(); diff --git a/xbmc/powermanagement/windows/Win32PowerSyscall.cpp b/xbmc/powermanagement/windows/Win32PowerSyscall.cpp index b02058371c..d88cbf7110 100644 --- a/xbmc/powermanagement/windows/Win32PowerSyscall.cpp +++ b/xbmc/powermanagement/windows/Win32PowerSyscall.cpp @@ -19,6 +19,7 @@ */ #include "Win32PowerSyscall.h" +#include "powermanagement/PowerManager.h" #ifdef _WIN32 #include "WIN32Util.h" diff --git a/xbmc/profiles/ProfilesManager.cpp b/xbmc/profiles/ProfilesManager.cpp index e05d8eddcf..46ceca08a5 100644 --- a/xbmc/profiles/ProfilesManager.cpp +++ b/xbmc/profiles/ProfilesManager.cpp @@ -36,7 +36,6 @@ #include "guilib/LocalizeStrings.h" #include "input/ButtonTranslator.h" #include "input/MouseStat.h" -#include "settings/GUISettings.h" #include "settings/Settings.h" #if !defined(TARGET_WINDOWS) && defined(HAS_DVD_DRIVE) #include "storage/DetectDVDType.h" @@ -91,11 +90,11 @@ bool CProfilesManager::OnSettingsLoading() void CProfilesManager::OnSettingsLoaded() { // check them all - string strDir = g_guiSettings.GetString("system.playlistspath"); + string strDir = CSettings::Get().GetString("system.playlistspath"); if (strDir == "set default" || strDir.empty()) { strDir = "special://profile/playlists/"; - g_guiSettings.SetString("system.playlistspath", strDir.c_str()); + CSettings::Get().SetString("system.playlistspath", strDir.c_str()); } CDirectory::Create(strDir); @@ -244,9 +243,15 @@ bool CProfilesManager::LoadProfile(size_t index) m_currentProfile = index; - // load the new settings - if (!g_settings.Load()) + // first unload any old settings + CSettings::Get().Unload(); + // then load the new settings + if (!CSettings::Get().Load()) + { + CLog::Log(LOGFATAL, "CProfilesManager: unable to load settings for profile \"%s\"", m_profiles.at(index).getName().c_str()); return false; + } + CSettings::Get().SetLoaded(); CreateProfileFolders(); @@ -254,7 +259,7 @@ bool CProfilesManager::LoadProfile(size_t index) g_charsetConverter.reset(); // Load the langinfo to have user charset <-> utf-8 conversion - string strLanguage = g_guiSettings.GetString("locale.language"); + string strLanguage = CSettings::Get().GetString("locale.language"); strLanguage[0] = toupper(strLanguage[0]); string strLangInfoPath = StringUtils::Format("special://xbmc/language/%s/langinfo.xml", strLanguage.c_str()); @@ -266,7 +271,7 @@ bool CProfilesManager::LoadProfile(size_t index) CDatabaseManager::Get().Initialize(); - g_Mouse.SetEnabled(g_guiSettings.GetBool("input.enablemouse")); + g_Mouse.SetEnabled(CSettings::Get().GetBool("input.enablemouse")); g_infoManager.ResetCache(); g_infoManager.ResetLibraryBools(); @@ -278,7 +283,10 @@ bool CProfilesManager::LoadProfile(size_t index) { CXBMCTinyXML doc; if (doc.LoadFile(URIUtils::AddFileToFolder(GetUserDataFolder(), "guisettings.xml"))) - g_guiSettings.LoadMasterLock(doc.RootElement()); + { + CSettings::Get().LoadSetting(doc.RootElement(), "masterlock.maxretries"); + CSettings::Get().LoadSetting(doc.RootElement(), "masterlock.startuplock"); + } } CPasswordManager::GetInstance().Clear(); @@ -333,7 +341,7 @@ bool CProfilesManager::DeleteProfile(size_t index) if (index == m_currentProfile) { LoadProfile(0); - g_settings.Save(); + CSettings::Get().Save(); } CFileItemPtr item = CFileItemPtr(new CFileItem(URIUtils::AddFileToFolder(GetUserDataFolder(), strDirectory))); diff --git a/xbmc/profiles/dialogs/GUIDialogProfileSettings.cpp b/xbmc/profiles/dialogs/GUIDialogProfileSettings.cpp index 23e49516f4..e6dd9f1e57 100644 --- a/xbmc/profiles/dialogs/GUIDialogProfileSettings.cpp +++ b/xbmc/profiles/dialogs/GUIDialogProfileSettings.cpp @@ -34,7 +34,6 @@ #include "filesystem/File.h" #include "FileItem.h" #include "settings/Settings.h" -#include "settings/GUISettings.h" #include "guilib/LocalizeStrings.h" #include "TextureCache.h" @@ -340,12 +339,12 @@ bool CGUIDialogProfileSettings::ShowForProfile(unsigned int iProfile, bool first else { // create some new settings - CGUISettings localSettings; - localSettings.Initialize(); CStdString path = URIUtils::AddFileToFolder("special://masterprofile/", dialog->m_strDirectory); path = URIUtils::AddFileToFolder(path, "guisettings.xml"); + CSettings settings; - settings.SaveSettings(path, &localSettings); + settings.Initialize(); + settings.Save(path); } } diff --git a/xbmc/programs/GUIViewStatePrograms.cpp b/xbmc/programs/GUIViewStatePrograms.cpp index 9c4c8c84ca..ccdf731619 100644 --- a/xbmc/programs/GUIViewStatePrograms.cpp +++ b/xbmc/programs/GUIViewStatePrograms.cpp @@ -21,24 +21,23 @@ #include "GUIViewStatePrograms.h" #include "FileItem.h" #include "view/ViewState.h" -#include "settings/GUISettings.h" #include "settings/MediaSourceSettings.h" #include "filesystem/Directory.h" #include "guilib/LocalizeStrings.h" #include "guilib/WindowIDs.h" +#include "settings/Settings.h" #include "view/ViewStateSettings.h" using namespace XFILE; -using namespace ADDON; CGUIViewStateWindowPrograms::CGUIViewStateWindowPrograms(const CFileItemList& items) : CGUIViewState(items) { - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) AddSortMethod(SORT_METHOD_LABEL_IGNORE_THE, 551, LABEL_MASKS("%K", "%I", "%L", "")); // Titel, Size | Foldername, empty else AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS("%K", "%I", "%L", "")); // Titel, Size | Foldername, empty - - CViewState *viewState = CViewStateSettings::Get().Get("programs"); + + const CViewState *viewState = CViewStateSettings::Get().Get("programs"); SetSortMethod(viewState->m_sortMethod); SetViewAsControl(viewState->m_viewMode); SetSortOrder(viewState->m_sortOrder); diff --git a/xbmc/pvr/PVRGUIInfo.cpp b/xbmc/pvr/PVRGUIInfo.cpp index 2064ba8741..787db29957 100644 --- a/xbmc/pvr/PVRGUIInfo.cpp +++ b/xbmc/pvr/PVRGUIInfo.cpp @@ -32,7 +32,7 @@ #include "pvr/channels/PVRChannel.h" #include "epg/EpgInfoTag.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" using namespace PVR; using namespace EPG; @@ -238,7 +238,7 @@ void CPVRGUIInfo::UpdateQualityData(void) ClearQualityInfo(qualityInfo); PVR_CLIENT client; - if (g_guiSettings.GetBool("pvrplayback.signalquality") && + if (CSettings::Get().GetBool("pvrplayback.signalquality") && g_PVRClients->GetPlayingClient(client)) { client->SignalQuality(qualityInfo); diff --git a/xbmc/pvr/PVRManager.cpp b/xbmc/pvr/PVRManager.cpp index 805ff02bb5..e4842248be 100644 --- a/xbmc/pvr/PVRManager.cpp +++ b/xbmc/pvr/PVRManager.cpp @@ -26,11 +26,11 @@ #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" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" #include "settings/MediaSettings.h" #include "settings/Settings.h" #include "threads/SingleLock.h" @@ -55,6 +55,7 @@ #include "interfaces/AnnouncementManager.h" #include "addons/AddonInstaller.h" #include "guilib/Key.h" +#include "dialogs/GUIDialogPVRChannelManager.h" using namespace std; using namespace MUSIC_INFO; @@ -91,6 +92,83 @@ CPVRManager &CPVRManager::Get(void) return pvrManagerInstance; } +void CPVRManager::OnSettingChanged(const CSetting *setting) +{ + if (setting == NULL) + return; + + const std::string &settingId = setting->GetId(); + if (settingId == "pvrmanager.enabled") + { + if (((CSettingBool*)setting)->GetValue()) + CApplicationMessenger::Get().ExecBuiltIn("XBMC.StartPVRManager", false); + else + CApplicationMessenger::Get().ExecBuiltIn("XBMC.StopPVRManager", false); + } + else if (settingId == "pvrparental.enabled") + { + if (((CSettingBool*)setting)->GetValue() && CSettings::Get().GetString("pvrparental.pin").empty()) + { + CStdString newPassword = ""; + // password set... save it + if (CGUIDialogNumeric::ShowAndVerifyNewPassword(newPassword)) + CSettings::Get().SetString("pvrparental.pin", newPassword); + // password not set... disable parental + else + ((CSettingBool*)setting)->SetValue(false); + } + } +} + +void CPVRManager::OnSettingAction(const CSetting *setting) +{ + if (setting == NULL) + return; + + const std::string &settingId = setting->GetId(); + if (settingId == "pvrmenu.searchicons") + { + if (IsStarted()) + SearchMissingChannelIcons(); + } + else if (settingId == "pvrmanager.resetdb") + { + if (CheckParentalPIN(g_localizeStrings.Get(19262).c_str()) && + CGUIDialogYesNo::ShowAndGetInput(19098, 19186, 750, 0)) + { + CDateTime::ResetTimezoneBias(); + ResetDatabase(false); + } + } + else if (settingId == "epg.resetepg") + { + if (CGUIDialogYesNo::ShowAndGetInput(19098, 19188, 750, 0)) + { + CDateTime::ResetTimezoneBias(); + ResetDatabase(true); + } + } + else if (settingId == "pvrmanager.channelscan") + { + if (IsStarted()) + StartChannelScan(); + } + else if (settingId == "pvrmanager.channelmanager") + { + if (IsStarted()) + { + CGUIDialogPVRChannelManager *dialog = (CGUIDialogPVRChannelManager *)g_windowManager.GetWindow(WINDOW_DIALOG_PVR_CHANNEL_MANAGER); + if (dialog) + dialog->DoModal(); + } + } + else if (settingId == "pvrclient.menuhook") + { + if (IsStarted()) + Clients()->ProcessMenuHooks(-1, PVR_MENUHOOK_SETTING); + } +} + bool CPVRManager::IsPVRWindowActive(void) const { return g_windowManager.IsWindowActive(WINDOW_PVR) || @@ -115,10 +193,10 @@ bool CPVRManager::InstallAddonAllowed(const std::string& strAddonId) const void CPVRManager::MarkAsOutdated(const std::string& strAddonId, const std::string& strReferer) { - if (IsStarted() && g_guiSettings.GetBool("general.addonautoupdate")) + if (IsStarted() && CSettings::Get().GetBool("general.addonautoupdate")) { CSingleLock lock(m_critSection); - m_outdatedAddons.insert(make_pair<string, string>(strAddonId, strReferer)); + m_outdatedAddons.insert(make_pair(strAddonId, strReferer)); } } @@ -261,7 +339,7 @@ void CPVRManager::Start(bool bAsync /* = false */, bool bOpenPVRWindow /* = fals Stop(); /* don't start if Settings->Video->TV->Enable isn't checked */ - if (!g_guiSettings.GetBool("pvrmanager.enabled")) + if (!CSettings::Get().GetBool("pvrmanager.enabled")) return; ResetProperties(); @@ -358,7 +436,7 @@ void CPVRManager::Process(void) while (GetState() == ManagerStateStarted && m_addons && m_addons->HasConnectedClients() && !bRestart) { /* continue last watched channel after first startup */ - if (m_bFirstStart && g_guiSettings.GetInt("pvrplayback.startlast") != START_LAST_CHANNEL_OFF) + if (m_bFirstStart && CSettings::Get().GetInt("pvrplayback.startlast") != START_LAST_CHANNEL_OFF) ContinueLastChannel(); /* execute the next pending jobs if there are any */ @@ -395,10 +473,10 @@ void CPVRManager::Process(void) bool CPVRManager::SetWakeupCommand(void) { - if (!g_guiSettings.GetBool("pvrpowermanagement.enabled")) + if (!CSettings::Get().GetBool("pvrpowermanagement.enabled")) return false; - const CStdString strWakeupCommand = g_guiSettings.GetString("pvrpowermanagement.setwakeupcmd", false); + const CStdString strWakeupCommand = CSettings::Get().GetString("pvrpowermanagement.setwakeupcmd"); if (!strWakeupCommand.IsEmpty() && m_timers) { time_t iWakeupTime; @@ -572,7 +650,7 @@ bool CPVRManager::ContinueLastChannel(void) if (channel && channel->HasPVRChannelInfoTag()) { CLog::Log(LOGNOTICE, "PVRManager - %s - continue playback on channel '%s'", __FUNCTION__, channel->GetPVRChannelInfoTag()->ChannelName().c_str()); - bReturn = StartPlayback(channel->GetPVRChannelInfoTag(), (g_guiSettings.GetInt("pvrplayback.startlast") == START_LAST_CHANNEL_MIN)); + bReturn = StartPlayback(channel->GetPVRChannelInfoTag(), (CSettings::Get().GetInt("pvrplayback.startlast") == START_LAST_CHANNEL_MIN)); } return bReturn; @@ -646,7 +724,7 @@ void CPVRManager::ResetDatabase(bool bResetEPGOnly /* = false */) CLog::Log(LOGNOTICE,"PVRManager - %s - %s database cleared", __FUNCTION__, bResetEPGOnly ? "EPG" : "PVR and EPG"); - if (g_guiSettings.GetBool("pvrmanager.enabled")) + if (CSettings::Get().GetBool("pvrmanager.enabled")) { CLog::Log(LOGNOTICE,"PVRManager - %s - restarting the PVRManager", __FUNCTION__); m_database->Open(); @@ -777,11 +855,11 @@ bool CPVRManager::IsParentalLocked(const CPVRChannel &channel) if (// different channel (!GetCurrentChannel(currentChannel) || channel != *currentChannel) && // parental control enabled - g_guiSettings.GetBool("pvrparental.enabled") && + CSettings::Get().GetBool("pvrparental.enabled") && // channel is locked channel.IsLocked()) { - float parentalDurationMs = g_guiSettings.GetInt("pvrparental.duration") * 1000.0f; + float parentalDurationMs = CSettings::Get().GetInt("pvrparental.duration") * 1000.0f; bReturn = m_parentalTimer && (!m_parentalTimer->IsRunning() || m_parentalTimer->GetElapsedMilliseconds() > parentalDurationMs); @@ -792,9 +870,9 @@ bool CPVRManager::IsParentalLocked(const CPVRChannel &channel) bool CPVRManager::CheckParentalPIN(const char *strTitle /* = NULL */) { - CStdString pinCode = g_guiSettings.GetString("pvrparental.pin"); + CStdString pinCode = CSettings::Get().GetString("pvrparental.pin"); - if (!g_guiSettings.GetBool("pvrparental.enabled") || pinCode.empty()) + if (!CSettings::Get().GetBool("pvrparental.enabled") || pinCode.empty()) return true; // Locked channel. Enter PIN: @@ -979,7 +1057,7 @@ bool CPVRManager::UpdateItem(CFileItem& item) { musictag->SetTitle(bHasTagNow ? epgTagNow.Title() : - g_guiSettings.GetBool("epg.hidenoinfoavailable") ? + CSettings::Get().GetBool("epg.hidenoinfoavailable") ? StringUtils::EmptyString : g_localizeStrings.Get(19055)); // no information available if (bHasTagNow) @@ -1000,7 +1078,7 @@ bool CPVRManager::UpdateItem(CFileItem& item) { videotag->m_strTitle = bHasTagNow ? epgTagNow.Title() : - g_guiSettings.GetBool("epg.hidenoinfoavailable") ? + CSettings::Get().GetBool("epg.hidenoinfoavailable") ? StringUtils::EmptyString : g_localizeStrings.Get(19055); // no information available if (bHasTagNow) @@ -1230,7 +1308,7 @@ bool CPVRManager::IsIdle(void) const else if (m_timers) // has active timers, etc.? { const CDateTime now = CDateTime::GetUTCDateTime(); - const CDateTimeSpan idle(0, 0, g_guiSettings.GetInt("pvrpowermanagement.backendidletime"), 0); + const CDateTimeSpan idle(0, 0, CSettings::Get().GetInt("pvrpowermanagement.backendidletime"), 0); const CDateTime next = m_timers->GetNextEventTime(); const CDateTimeSpan delta = next - now; @@ -1433,6 +1511,13 @@ bool CPVRManager::OnAction(const CAction &action) return false; } +void CPVRManager::SettingOptionsPvrStartLastChannelFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t) +{ + list.push_back(make_pair(g_localizeStrings.Get(106), PVR::START_LAST_CHANNEL_OFF)); + list.push_back(make_pair(g_localizeStrings.Get(19190), PVR::START_LAST_CHANNEL_MIN)); + list.push_back(make_pair(g_localizeStrings.Get(107), PVR::START_LAST_CHANNEL_ON)); +} + bool CPVRChannelSwitchJob::DoWork(void) { // announce OnStop and delete m_previous when done diff --git a/xbmc/pvr/PVRManager.h b/xbmc/pvr/PVRManager.h index 43cb555c44..8de823c193 100644 --- a/xbmc/pvr/PVRManager.h +++ b/xbmc/pvr/PVRManager.h @@ -19,15 +19,18 @@ * */ +#include <map> + +#include "addons/include/xbmc_pvr_types.h" +#include "settings/ISettingCallback.h" +#include "threads/Event.h" #include "threads/Thread.h" #include "utils/JobManager.h" -#include "threads/Event.h" -#include "addons/include/xbmc_pvr_types.h" -#include <map> class CGUIDialogProgressBarHandle; class CStopWatch; class CAction; +class CFileItemList; namespace EPG { @@ -65,6 +68,13 @@ namespace PVR PlaybackTypeRadio }; + enum ChannelStartLast + { + START_LAST_CHANNEL_OFF = 0, + START_LAST_CHANNEL_MIN, + START_LAST_CHANNEL_ON + }; + #define g_PVRManager CPVRManager::Get() #define g_PVRChannelGroups g_PVRManager.ChannelGroups() #define g_PVRTimers g_PVRManager.Timers() @@ -73,7 +83,7 @@ namespace PVR typedef boost::shared_ptr<PVR::CPVRChannelGroup> CPVRChannelGroupPtr; - class CPVRManager : private CThread + class CPVRManager : public ISettingCallback, private CThread { friend class CPVRClients; @@ -95,6 +105,9 @@ namespace PVR */ static CPVRManager &Get(void); + virtual void OnSettingChanged(const CSetting *setting); + virtual void OnSettingAction(const CSetting *setting); + /*! * @brief Get the channel groups container. * @return The groups container. @@ -495,6 +508,8 @@ namespace PVR */ bool OnAction(const CAction &action); + static void SettingOptionsPvrStartLastChannelFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t); + protected: /*! * @brief PVR update and control thread. diff --git a/xbmc/pvr/addons/PVRClient.cpp b/xbmc/pvr/addons/PVRClient.cpp index 408f163701..72aff20992 100644 --- a/xbmc/pvr/addons/PVRClient.cpp +++ b/xbmc/pvr/addons/PVRClient.cpp @@ -19,6 +19,7 @@ */ #include <vector> +#include "Application.h" #include "PVRClient.h" #include "pvr/PVRManager.h" #include "epg/Epg.h" @@ -27,8 +28,8 @@ #include "pvr/timers/PVRTimerInfoTag.h" #include "pvr/recordings/PVRRecordings.h" #include "settings/AdvancedSettings.h" +#include "settings/Settings.h" #include "utils/log.h" -#include "settings/GUISettings.h" using namespace std; using namespace ADDON; @@ -1431,7 +1432,7 @@ bool CPVRClient::CanSeekStream(void) const void CPVRClient::ResetQualityData(PVR_SIGNAL_STATUS &qualityInfo) { memset(&qualityInfo, 0, sizeof(qualityInfo)); - if (g_guiSettings.GetBool("pvrplayback.signalquality")) + if (CSettings::Get().GetBool("pvrplayback.signalquality")) { strncpy(qualityInfo.strAdapterName, g_localizeStrings.Get(13205).c_str(), PVR_ADDON_NAME_STRING_LENGTH - 1); strncpy(qualityInfo.strAdapterStatus, g_localizeStrings.Get(13205).c_str(), PVR_ADDON_NAME_STRING_LENGTH - 1); @@ -1466,7 +1467,7 @@ void CPVRClient::UpdateCharInfoSignalStatus(void) PVR_SIGNAL_STATUS qualityInfo; ResetQualityData(qualityInfo); - if (g_guiSettings.GetBool("pvrplayback.signalquality")) + if (CSettings::Get().GetBool("pvrplayback.signalquality")) SignalQuality(qualityInfo); CSingleLock lock(m_critSection); diff --git a/xbmc/pvr/addons/PVRClients.cpp b/xbmc/pvr/addons/PVRClients.cpp index f3fb8525ff..16fad4457c 100644 --- a/xbmc/pvr/addons/PVRClients.cpp +++ b/xbmc/pvr/addons/PVRClients.cpp @@ -23,15 +23,14 @@ #include "Application.h" #include "ApplicationMessenger.h" #include "GUIUserMessages.h" -#include "settings/GUISettings.h" #include "dialogs/GUIDialogOK.h" #include "dialogs/GUIDialogSelect.h" #include "pvr/PVRManager.h" #include "pvr/PVRDatabase.h" #include "guilib/GUIWindowManager.h" #include "settings/DisplaySettings.h" -#include "settings/Settings.h" #include "settings/MediaSettings.h" +#include "settings/Settings.h" #include "pvr/channels/PVRChannelGroups.h" #include "pvr/channels/PVRChannelGroupInternal.h" #include "pvr/recordings/PVRRecordings.h" @@ -1155,7 +1154,7 @@ bool CPVRClients::UpdateAddons(void) // You need a tuner, backend software, and an add-on for the backend to be able to use PVR. // Please visit xbmc.org/pvr to learn more. m_bNoAddonWarningDisplayed = true; - g_guiSettings.SetBool("pvrmanager.enabled", false); + CSettings::Get().SetBool("pvrmanager.enabled", false); CGUIDialogOK::ShowAndGetInput(19271, 19272, 19273, 19274); CGUIMessage msg(GUI_MSG_UPDATE, WINDOW_SETTINGS_MYPVR, 0); g_windowManager.SendThreadMessage(msg, WINDOW_SETTINGS_MYPVR); diff --git a/xbmc/pvr/channels/PVRChannel.cpp b/xbmc/pvr/channels/PVRChannel.cpp index 1a627a5e77..adf5a89bfb 100644 --- a/xbmc/pvr/channels/PVRChannel.cpp +++ b/xbmc/pvr/channels/PVRChannel.cpp @@ -23,7 +23,6 @@ #include "utils/log.h" #include "Util.h" #include "filesystem/File.h" -#include "settings/GUISettings.h" #include "utils/StringUtils.h" #include "threads/SingleLock.h" diff --git a/xbmc/pvr/channels/PVRChannelGroup.cpp b/xbmc/pvr/channels/PVRChannelGroup.cpp index 170f6c3512..c27f624464 100644 --- a/xbmc/pvr/channels/PVRChannelGroup.cpp +++ b/xbmc/pvr/channels/PVRChannelGroup.cpp @@ -23,8 +23,8 @@ * - use Observable here, so we can use event driven operations later */ -#include "settings/GUISettings.h" #include "settings/AdvancedSettings.h" +#include "settings/Settings.h" #include "guilib/GUIWindowManager.h" #include "dialogs/GUIDialogYesNo.h" #include "dialogs/GUIDialogOK.h" @@ -116,8 +116,8 @@ bool CPVRChannelGroup::Load(void) /* make sure this container is empty before loading */ Unload(); - m_bUsingBackendChannelOrder = g_guiSettings.GetBool("pvrmanager.backendchannelorder"); - m_bUsingBackendChannelNumbers = g_guiSettings.GetBool("pvrmanager.usebackendchannelnumbers"); + m_bUsingBackendChannelOrder = CSettings::Get().GetBool("pvrmanager.backendchannelorder"); + m_bUsingBackendChannelNumbers = CSettings::Get().GetBool("pvrmanager.usebackendchannelnumbers"); int iChannelCount = m_iGroupId > 0 ? LoadFromDb() : 0; CLog::Log(LOGDEBUG, "PVRChannelGroup - %s - %d channels loaded from the database for group '%s'", @@ -137,7 +137,6 @@ bool CPVRChannelGroup::Load(void) SortAndRenumber(); - g_guiSettings.RegisterObserver(this); m_bLoaded = true; return true; @@ -146,14 +145,13 @@ bool CPVRChannelGroup::Load(void) void CPVRChannelGroup::Unload(void) { CSingleLock lock(m_critSection); - g_guiSettings.UnregisterObserver(this); m_members.clear(); } bool CPVRChannelGroup::Update(void) { if (GroupType() == PVR_GROUP_TYPE_USER_DEFINED || - !g_guiSettings.GetBool("pvrmanager.syncchannelgroups")) + !CSettings::Get().GetBool("pvrmanager.syncchannelgroups")) return true; CPVRChannelGroup PVRChannels_tmp(m_bRadio, m_iGroupId, m_strGroupName); @@ -240,7 +238,7 @@ bool CPVRChannelGroup::SetChannelIconPath(CPVRChannelPtr channel, const std::str void CPVRChannelGroup::SearchAndSetChannelIcons(bool bUpdateDb /* = false */) { - if (g_guiSettings.GetString("pvrmenu.iconpath").IsEmpty()) + if (CSettings::Get().GetString("pvrmenu.iconpath").empty()) return; CPVRDatabase *database = GetPVRDatabase(); @@ -257,7 +255,7 @@ void CPVRChannelGroup::SearchAndSetChannelIcons(bool bUpdateDb /* = false */) if (!groupMember.channel->IconPath().IsEmpty()) continue; - CStdString strBasePath = g_guiSettings.GetString("pvrmenu.iconpath"); + CStdString strBasePath = CSettings::Get().GetString("pvrmenu.iconpath"); CStdString strSanitizedChannelName = CUtil::MakeLegalFileName(groupMember.channel->ClientChannelName()); CStdString strIconPath = strBasePath + strSanitizedChannelName; @@ -884,7 +882,7 @@ bool CPVRChannelGroup::Renumber(void) { bool bReturn(false); unsigned int iChannelNumber(0); - bool bUseBackendChannelNumbers(g_guiSettings.GetBool("pvrmanager.usebackendchannelnumbers") && g_PVRClients->EnabledClientAmount() == 1); + bool bUseBackendChannelNumbers(CSettings::Get().GetBool("pvrmanager.usebackendchannelnumbers") && g_PVRClients->EnabledClientAmount() == 1); if (PreventSortAndRenumber()) return true; @@ -978,18 +976,24 @@ void CPVRChannelGroup::ResetChannelNumbers(void) m_members.at(iChannelPtr).channel->SetCachedChannelNumber(0); } -void CPVRChannelGroup::Notify(const Observable &obs, const ObservableMessage msg) +void CPVRChannelGroup::OnSettingChanged(const CSetting *setting) { + if (setting == NULL) + return; + /* TODO: while pvr manager is starting up do accept setting changes. */ if(!g_PVRManager.IsStarted()) { CLog::Log(LOGWARNING, "CPVRChannelGroup setting change ignored while PVRManager is starting\n"); + return; } - else if (msg == ObservableMessageGuiSettings) + + const std::string &settingId = setting->GetId(); + if (settingId == "pvrmanager.backendchannelorder" || settingId == "pvrmanager.usebackendchannelnumbers") { CSingleLock lock(m_critSection); - bool bUsingBackendChannelOrder = g_guiSettings.GetBool("pvrmanager.backendchannelorder"); - bool bUsingBackendChannelNumbers = g_guiSettings.GetBool("pvrmanager.usebackendchannelnumbers"); + bool bUsingBackendChannelOrder = CSettings::Get().GetBool("pvrmanager.backendchannelorder"); + bool bUsingBackendChannelNumbers = CSettings::Get().GetBool("pvrmanager.usebackendchannelnumbers"); bool bChannelNumbersChanged = m_bUsingBackendChannelNumbers != bUsingBackendChannelNumbers; bool bChannelOrderChanged = m_bUsingBackendChannelOrder != bUsingBackendChannelOrder; diff --git a/xbmc/pvr/channels/PVRChannelGroup.h b/xbmc/pvr/channels/PVRChannelGroup.h index 18d22e4b15..b76e20ba30 100644 --- a/xbmc/pvr/channels/PVRChannelGroup.h +++ b/xbmc/pvr/channels/PVRChannelGroup.h @@ -22,6 +22,7 @@ #include "FileItem.h" #include "PVRChannel.h" +#include "settings/ISettingCallback.h" #include "utils/JobManager.h" #include <boost/shared_ptr.hpp> @@ -54,9 +55,9 @@ namespace PVR typedef boost::shared_ptr<PVR::CPVRChannelGroup> CPVRChannelGroupPtr; /** A group of channels */ - class CPVRChannelGroup : private Observer, - public Observable, - public IJobCallback + class CPVRChannelGroup : public Observable, + public IJobCallback, + public ISettingCallback { friend class CPVRChannelGroups; @@ -232,7 +233,7 @@ namespace PVR //@} - void Notify(const Observable &obs, const ObservableMessage msg); + virtual void OnSettingChanged(const CSetting *setting); /*! * @brief Get a channel given it's EPG ID. diff --git a/xbmc/pvr/channels/PVRChannelGroupInternal.cpp b/xbmc/pvr/channels/PVRChannelGroupInternal.cpp index 1073edf43c..b4556d6868 100644 --- a/xbmc/pvr/channels/PVRChannelGroupInternal.cpp +++ b/xbmc/pvr/channels/PVRChannelGroupInternal.cpp @@ -20,11 +20,10 @@ #include "PVRChannelGroupInternal.h" -#include "settings/GUISettings.h" -#include "settings/AdvancedSettings.h" #include "guilib/GUIWindowManager.h" #include "dialogs/GUIDialogYesNo.h" #include "dialogs/GUIDialogOK.h" +#include "settings/AdvancedSettings.h" #include "utils/log.h" #include "PVRChannelGroupsContainer.h" diff --git a/xbmc/pvr/channels/PVRChannelGroups.cpp b/xbmc/pvr/channels/PVRChannelGroups.cpp index c09aa1d7bd..4a2971bbf3 100644 --- a/xbmc/pvr/channels/PVRChannelGroups.cpp +++ b/xbmc/pvr/channels/PVRChannelGroups.cpp @@ -21,7 +21,7 @@ #include "PVRChannelGroups.h" #include "FileItem.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "guilib/GUIWindowManager.h" #include "utils/log.h" #include "URL.h" @@ -52,7 +52,7 @@ void CPVRChannelGroups::Clear(void) bool CPVRChannelGroups::GetGroupsFromClients(void) { - if (! g_guiSettings.GetBool("pvrmanager.syncchannelgroups")) + if (! CSettings::Get().GetBool("pvrmanager.syncchannelgroups")) return true; return g_PVRClients->GetChannelGroups(this) == PVR_ERROR_NO_ERROR; @@ -160,7 +160,7 @@ void CPVRChannelGroups::RemoveFromAllGroups(const CPVRChannel &channel) bool CPVRChannelGroups::Update(bool bChannelsOnly /* = false */) { - bool bUpdateAllGroups = !bChannelsOnly && g_guiSettings.GetBool("pvrmanager.syncchannelgroups"); + bool bUpdateAllGroups = !bChannelsOnly && CSettings::Get().GetBool("pvrmanager.syncchannelgroups"); bool bReturn(true); // sync groups @@ -218,7 +218,7 @@ bool CPVRChannelGroups::LoadUserDefinedChannelGroups(void) if (!database) return false; - bool bSyncWithBackends = g_guiSettings.GetBool("pvrmanager.syncchannelgroups"); + bool bSyncWithBackends = CSettings::Get().GetBool("pvrmanager.syncchannelgroups"); CSingleLock lock(m_critSection); diff --git a/xbmc/pvr/dialogs/GUIDialogPVRChannelManager.cpp b/xbmc/pvr/dialogs/GUIDialogPVRChannelManager.cpp index 80e397d61c..b32e781a02 100644 --- a/xbmc/pvr/dialogs/GUIDialogPVRChannelManager.cpp +++ b/xbmc/pvr/dialogs/GUIDialogPVRChannelManager.cpp @@ -38,7 +38,7 @@ #include "pvr/PVRManager.h" #include "pvr/channels/PVRChannelGroupsContainer.h" #include "pvr/addons/PVRClients.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "storage/MediaManager.h" #define BUTTON_OK 4 @@ -332,10 +332,10 @@ bool CGUIDialogPVRChannelManager::OnClickButtonChannelLogo(CGUIMessage &message) CStdString strThumb; VECSOURCES shares; - if (g_guiSettings.GetString("pvrmenu.iconpath") != "") + if (CSettings::Get().GetString("pvrmenu.iconpath") != "") { CMediaSource share1; - share1.strPath = g_guiSettings.GetString("pvrmenu.iconpath"); + share1.strPath = CSettings::Get().GetString("pvrmenu.iconpath"); share1.strName = g_localizeStrings.Get(19018); shares.push_back(share1); } diff --git a/xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp b/xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp index 040555a3b8..0e5ba03680 100644 --- a/xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp +++ b/xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp @@ -29,7 +29,7 @@ #include "dialogs/GUIDialogOK.h" #include "GUIDialogPVRGuideInfo.h" #include "view/ViewState.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "GUIInfoManager.h" #include "cores/IPlayer.h" @@ -188,7 +188,7 @@ void CGUIDialogPVRChannelsOSD::Clear() void CGUIDialogPVRChannelsOSD::CloseOrSelect(unsigned int iItem) { - if (g_guiSettings.GetBool("pvrmenu.closechannelosdonswitch")) + if (CSettings::Get().GetBool("pvrmenu.closechannelosdonswitch")) Close(); else m_viewControl.SetSelectedItem(iItem); diff --git a/xbmc/pvr/dialogs/GUIDialogPVRGuideInfo.cpp b/xbmc/pvr/dialogs/GUIDialogPVRGuideInfo.cpp index 77645db3f9..74965eb787 100644 --- a/xbmc/pvr/dialogs/GUIDialogPVRGuideInfo.cpp +++ b/xbmc/pvr/dialogs/GUIDialogPVRGuideInfo.cpp @@ -168,15 +168,15 @@ bool CGUIDialogPVRGuideInfo::OnClickButtonSwitch(CGUIMessage &message) if (message.GetSenderId() == CONTROL_BTN_SWITCH) { Close(); - + PlayBackRet ret = PLAYBACK_CANCELED; if (!m_progItem->GetEPGInfoTag()->HasPVRChannel() || - !g_application.PlayFile(CFileItem(*m_progItem->GetEPGInfoTag()->ChannelTag()))) + (ret = g_application.PlayFile(CFileItem(*m_progItem->GetEPGInfoTag()->ChannelTag()))) == PLAYBACK_FAIL) { CStdString msg; msg.Format(g_localizeStrings.Get(19035).c_str(), g_localizeStrings.Get(19029).c_str()); // Channel could not be played. Check the log for details. CGUIDialogOK::ShowAndGetInput(19033, 0, msg, 0); } - else + else if (ret == PLAYBACK_OK) { bReturn = true; } diff --git a/xbmc/pvr/dialogs/GUIDialogPVRTimerSettings.cpp b/xbmc/pvr/dialogs/GUIDialogPVRTimerSettings.cpp index 1f9fe1e6eb..69496b8858 100644 --- a/xbmc/pvr/dialogs/GUIDialogPVRTimerSettings.cpp +++ b/xbmc/pvr/dialogs/GUIDialogPVRTimerSettings.cpp @@ -21,7 +21,6 @@ #include "GUIDialogPVRTimerSettings.h" #include "guilib/GUIKeyboardFactory.h" #include "dialogs/GUIDialogNumeric.h" -#include "settings/GUISettings.h" #include "guilib/LocalizeStrings.h" #include "pvr/PVRManager.h" diff --git a/xbmc/pvr/timers/PVRTimerInfoTag.cpp b/xbmc/pvr/timers/PVRTimerInfoTag.cpp index 1356b3996b..ceb024775f 100644 --- a/xbmc/pvr/timers/PVRTimerInfoTag.cpp +++ b/xbmc/pvr/timers/PVRTimerInfoTag.cpp @@ -18,11 +18,11 @@ * */ -#include "settings/GUISettings.h" #include "dialogs/GUIDialogKaiToast.h" #include "dialogs/GUIDialogOK.h" #include "dialogs/GUIDialogYesNo.h" #include "settings/AdvancedSettings.h" +#include "settings/Settings.h" #include "utils/log.h" #include "utils/StringUtils.h" @@ -47,8 +47,8 @@ CPVRTimerInfoTag::CPVRTimerInfoTag(void) m_iClientId = g_PVRClients->GetFirstConnectedClientID(); m_iClientIndex = -1; m_iClientChannelUid = -1; - m_iPriority = g_guiSettings.GetInt("pvrrecord.defaultpriority"); - m_iLifetime = g_guiSettings.GetInt("pvrrecord.defaultlifetime"); + m_iPriority = CSettings::Get().GetInt("pvrrecord.defaultpriority"); + m_iLifetime = CSettings::Get().GetInt("pvrrecord.defaultlifetime"); m_bIsRepeating = false; m_iWeekdays = 0; m_strFileNameAndPath = StringUtils::EmptyString; @@ -56,8 +56,8 @@ CPVRTimerInfoTag::CPVRTimerInfoTag(void) m_bIsRadio = false; CEpgInfoTagPtr emptyTag; m_epgTag = emptyTag; - m_iMarginStart = g_guiSettings.GetInt("pvrrecord.marginstart"); - m_iMarginEnd = g_guiSettings.GetInt("pvrrecord.marginend"); + m_iMarginStart = CSettings::Get().GetInt("pvrrecord.marginstart"); + m_iMarginEnd = CSettings::Get().GetInt("pvrrecord.marginend"); m_iGenreType = 0; m_iGenreSubType = 0; m_StartTime = CDateTime::GetUTCDateTime(); @@ -542,7 +542,7 @@ void CPVRTimerInfoTag::GetNotificationText(CStdString &strText) const void CPVRTimerInfoTag::QueueNotification(void) const { - if (g_guiSettings.GetBool("pvrrecord.timernotifications")) + if (CSettings::Get().GetBool("pvrrecord.timernotifications")) { CStdString strMessage; GetNotificationText(strMessage); diff --git a/xbmc/pvr/timers/PVRTimers.cpp b/xbmc/pvr/timers/PVRTimers.cpp index 5335fa441a..36187f3b84 100644 --- a/xbmc/pvr/timers/PVRTimers.cpp +++ b/xbmc/pvr/timers/PVRTimers.cpp @@ -19,7 +19,7 @@ */ #include "FileItem.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "dialogs/GUIDialogKaiToast.h" #include "dialogs/GUIDialogOK.h" #include "threads/SingleLock.h" @@ -252,7 +252,7 @@ bool CPVRTimers::UpdateEntries(const CPVRTimers &timers) NotifyObservers(bAddedOrDeleted ? ObservableMessageTimersReset : ObservableMessageTimers); - if (g_guiSettings.GetBool("pvrrecord.timernotifications")) + if (CSettings::Get().GetBool("pvrrecord.timernotifications")) { /* queue notifications */ for (unsigned int iNotificationPtr = 0; iNotificationPtr < timerNotifications.size(); iNotificationPtr++) @@ -497,7 +497,7 @@ bool CPVRTimers::InstantTimer(const CPVRChannel &channel) newTimer->SetStartFromUTC(startTime); newTimer->m_iMarginStart = 0; /* set the start margin to 0 for instant timers */ - int iDuration = g_guiSettings.GetInt("pvrrecord.instantrecordtime"); + int iDuration = CSettings::Get().GetInt("pvrrecord.instantrecordtime"); CDateTime endTime = CDateTime::GetUTCDateTime() + CDateTimeSpan(0, 0, iDuration ? iDuration : 120, 0); newTimer->SetEndFromUTC(endTime); @@ -657,10 +657,10 @@ void CPVRTimers::Notify(const Observable &obs, const ObservableMessage msg) CDateTime CPVRTimers::GetNextEventTime(void) const { - const bool dailywakup = g_guiSettings.GetBool("pvrpowermanagement.dailywakeup"); + const bool dailywakup = CSettings::Get().GetBool("pvrpowermanagement.dailywakeup"); const CDateTime now = CDateTime::GetUTCDateTime(); - const CDateTimeSpan prewakeup(0, 0, g_guiSettings.GetInt("pvrpowermanagement.prewakeup"), 0); - const CDateTimeSpan idle(0, 0, g_guiSettings.GetInt("pvrpowermanagement.backendidletime"), 0); + const CDateTimeSpan prewakeup(0, 0, CSettings::Get().GetInt("pvrpowermanagement.prewakeup"), 0); + const CDateTimeSpan idle(0, 0, CSettings::Get().GetInt("pvrpowermanagement.backendidletime"), 0); CDateTime wakeuptime; @@ -678,7 +678,7 @@ CDateTime CPVRTimers::GetNextEventTime(void) const if (dailywakup) { CDateTime dailywakeuptime; - dailywakeuptime.SetFromDBTime(g_guiSettings.GetString("pvrpowermanagement.dailywakeuptime", false)); + dailywakeuptime.SetFromDBTime(CSettings::Get().GetString("pvrpowermanagement.dailywakeuptime")); dailywakeuptime = dailywakeuptime.GetAsUTCDateTime(); dailywakeuptime.SetDateTime( diff --git a/xbmc/pvr/windows/GUIViewStatePVR.cpp b/xbmc/pvr/windows/GUIViewStatePVR.cpp index c065b5f236..5390604e98 100644 --- a/xbmc/pvr/windows/GUIViewStatePVR.cpp +++ b/xbmc/pvr/windows/GUIViewStatePVR.cpp @@ -22,7 +22,7 @@ #include "GUIWindowPVR.h" #include "GUIWindowPVRCommon.h" #include "guilib/GUIWindowManager.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" using namespace PVR; @@ -32,7 +32,7 @@ CGUIViewStatePVR::CGUIViewStatePVR(const CFileItemList& items) : PVRWindow ActiveView = GetActiveView(); if (ActiveView == PVR_WINDOW_RECORDINGS) { - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) AddSortMethod(SORT_METHOD_LABEL_IGNORE_THE, 551, LABEL_MASKS("%L", "%I", "%L", "")); // FileName, Size | Foldername, e else AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS("%L", "%I", "%L", "")); // FileName, Size | Foldername, empty diff --git a/xbmc/pvr/windows/GUIWindowPVR.cpp b/xbmc/pvr/windows/GUIWindowPVR.cpp index eb69ba63b1..e455080496 100644 --- a/xbmc/pvr/windows/GUIWindowPVR.cpp +++ b/xbmc/pvr/windows/GUIWindowPVR.cpp @@ -36,6 +36,8 @@ using namespace PVR; +#define CHANNELS_REFRESH_INTERVAL 5000 + CGUIWindowPVR::CGUIWindowPVR(void) : CGUIMediaWindow(WINDOW_PVR, "MyPVR.xml"), m_guideGrid(NULL), @@ -77,6 +79,9 @@ void CGUIWindowPVR::SetActiveView(CGUIWindowPVRCommon *window) m_currentSubwindow->m_iSelected = m_viewControl.GetSelectedItem(); } + if (window == m_windowChannelsRadio || window == m_windowChannelsTV) + m_refreshWatch.StartZero(); + // update m_history if (window) m_history = window->m_history; @@ -335,3 +340,17 @@ void CGUIWindowPVR::Cleanup(void) ClearFileItems(); FreeResources(); } + +void CGUIWindowPVR::FrameMove() +{ + CGUIWindowPVRCommon* view = GetActiveView(); + if (view == m_windowChannelsRadio || view == m_windowChannelsTV) + { + if (m_refreshWatch.GetElapsedMilliseconds() > CHANNELS_REFRESH_INTERVAL) + { + view->SetInvalid(); + m_refreshWatch.Reset(); + } + } + CGUIMediaWindow::FrameMove(); +} diff --git a/xbmc/pvr/windows/GUIWindowPVR.h b/xbmc/pvr/windows/GUIWindowPVR.h index ca21791db6..06efc4c95c 100644 --- a/xbmc/pvr/windows/GUIWindowPVR.h +++ b/xbmc/pvr/windows/GUIWindowPVR.h @@ -22,6 +22,7 @@ #include "GUIWindowPVRCommon.h" #include "epg/GUIEPGGridContainer.h" +#include "utils/Stopwatch.h" #include "threads/CriticalSection.h" namespace PVR @@ -56,6 +57,7 @@ namespace PVR virtual bool OnMessage(CGUIMessage& message); virtual void OnWindowLoaded(void); virtual void OnWindowUnload(void); + virtual void FrameMove(); virtual void Reset(void); virtual void Cleanup(void); @@ -85,5 +87,7 @@ namespace PVR bool m_bWasReset; CCriticalSection m_critSection; + + CStopWatch m_refreshWatch; }; } diff --git a/xbmc/pvr/windows/GUIWindowPVRChannels.cpp b/xbmc/pvr/windows/GUIWindowPVRChannels.cpp index 992747fb38..9ce30b8b6f 100644 --- a/xbmc/pvr/windows/GUIWindowPVRChannels.cpp +++ b/xbmc/pvr/windows/GUIWindowPVRChannels.cpp @@ -37,7 +37,7 @@ #include "pvr/addons/PVRClients.h" #include "pvr/timers/PVRTimers.h" #include "epg/EpgContainer.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "storage/MediaManager.h" #include "utils/log.h" #include "threads/SingleLock.h" @@ -49,18 +49,14 @@ CGUIWindowPVRChannels::CGUIWindowPVRChannels(CGUIWindowPVR *parent, bool bRadio) CGUIWindowPVRCommon(parent, bRadio ? PVR_WINDOW_CHANNELS_RADIO : PVR_WINDOW_CHANNELS_TV, bRadio ? CONTROL_BTNCHANNELS_RADIO : CONTROL_BTNCHANNELS_TV, - bRadio ? CONTROL_LIST_CHANNELS_RADIO: CONTROL_LIST_CHANNELS_TV), - CThread("PVRChannelWin") + bRadio ? CONTROL_LIST_CHANNELS_RADIO: CONTROL_LIST_CHANNELS_TV) { m_bRadio = bRadio; m_bShowHiddenChannels = false; - m_bThreadCreated = false; } CGUIWindowPVRChannels::~CGUIWindowPVRChannels(void) { - if (m_bThreadCreated) - StopThread(true); } void CGUIWindowPVRChannels::ResetObservers(void) @@ -266,13 +262,6 @@ void CGUIWindowPVRChannels::UpdateData(bool bUpdateSelectedFile /* = true */) m_parent->SetLabel(CONTROL_LABELGROUP, g_localizeStrings.Get(19022)); else m_parent->SetLabel(CONTROL_LABELGROUP, currentGroup->GroupName()); - - if (!m_bThreadCreated) - { - m_bThreadCreated = true; - Create(); - SetPriority(-1); - } } bool CGUIWindowPVRChannels::OnClickButton(CGUIMessage &message) @@ -446,7 +435,7 @@ bool CGUIWindowPVRChannels::OnContextButtonPlay(CFileItem *item, CONTEXT_BUTTON if (button == CONTEXT_BUTTON_PLAY_ITEM) { /* play channel */ - bReturn = PlayFile(item, g_guiSettings.GetBool("pvrplayback.playminimized")); + bReturn = PlayFile(item, CSettings::Get().GetBool("pvrplayback.playminimized")); } return bReturn; @@ -492,10 +481,10 @@ bool CGUIWindowPVRChannels::OnContextButtonSetThumb(CFileItem *item, CONTEXT_BUT CStdString strThumb; VECSOURCES shares; - if (g_guiSettings.GetString("pvrmenu.iconpath") != "") + if (CSettings::Get().GetString("pvrmenu.iconpath") != "") { CMediaSource share1; - share1.strPath = g_guiSettings.GetString("pvrmenu.iconpath"); + share1.strPath = CSettings::Get().GetString("pvrmenu.iconpath"); share1.strName = g_localizeStrings.Get(19018); shares.push_back(share1); } @@ -608,18 +597,3 @@ void CGUIWindowPVRChannels::ShowGroupManager(void) return; } - -void CGUIWindowPVRChannels::Process(void) -{ - // ugly hack to refresh the progress bars and item contents every 5 seconds - int iCount(0); - while (!m_bStop) - { - if (++iCount == 100) - { - iCount = 0; - SetInvalid(); - } - Sleep(50); - } -} diff --git a/xbmc/pvr/windows/GUIWindowPVRChannels.h b/xbmc/pvr/windows/GUIWindowPVRChannels.h index 75d3ee43c5..40c5fea043 100644 --- a/xbmc/pvr/windows/GUIWindowPVRChannels.h +++ b/xbmc/pvr/windows/GUIWindowPVRChannels.h @@ -22,14 +22,13 @@ #include "GUIWindowPVRCommon.h" #include "utils/Observer.h" -#include "threads/Thread.h" #include "../channels/PVRChannelGroup.h" namespace PVR { class CGUIWindowPVR; - class CGUIWindowPVRChannels : public CGUIWindowPVRCommon, private Observer, private CThread + class CGUIWindowPVRChannels : public CGUIWindowPVRCommon, private Observer { friend class CGUIWindowPVR; @@ -48,7 +47,6 @@ namespace PVR void UnregisterObservers(void); private: - void Process(void); bool OnClickButton(CGUIMessage &message); bool OnClickList(CGUIMessage &message); @@ -70,6 +68,5 @@ namespace PVR CPVRChannelGroupPtr m_selectedGroup; bool m_bShowHiddenChannels; bool m_bRadio; - bool m_bThreadCreated; }; } diff --git a/xbmc/pvr/windows/GUIWindowPVRCommon.cpp b/xbmc/pvr/windows/GUIWindowPVRCommon.cpp index 1cfbb1afaa..d1990bd11f 100644 --- a/xbmc/pvr/windows/GUIWindowPVRCommon.cpp +++ b/xbmc/pvr/windows/GUIWindowPVRCommon.cpp @@ -41,7 +41,6 @@ #include "pvr/windows/GUIWindowPVR.h" #include "pvr/windows/GUIWindowPVRSearch.h" #include "pvr/recordings/PVRRecordings.h" -#include "settings/GUISettings.h" #include "settings/MediaSettings.h" #include "settings/Settings.h" #include "utils/log.h" @@ -517,7 +516,7 @@ bool CGUIWindowPVRCommon::ActionPlayChannel(CFileItem *item) else { /* open channel */ - bReturn = PlayFile(item, g_guiSettings.GetBool("pvrplayback.playminimized")); + bReturn = PlayFile(item, CSettings::Get().GetBool("pvrplayback.playminimized")); } return bReturn; @@ -525,27 +524,25 @@ bool CGUIWindowPVRCommon::ActionPlayChannel(CFileItem *item) bool CGUIWindowPVRCommon::ActionPlayEpg(CFileItem *item) { - bool bReturn = false; - CEpgInfoTag *epgTag = item->GetEPGInfoTag(); if (!epgTag) - return bReturn; + return false; CPVRChannelPtr channel = epgTag->ChannelTag(); if (!channel || channel->ChannelNumber() > 0 || !g_PVRManager.CheckParentalLock(*channel)) - return bReturn; + return false; - bReturn = g_application.PlayFile(CFileItem(*channel)); + PlayBackRet ret = g_application.PlayFile(CFileItem(*channel)); - if (!bReturn) + if (ret == PLAYBACK_FAIL) { CStdString msg; msg.Format(g_localizeStrings.Get(19035).c_str(), channel->ChannelName().c_str()); // CHANNELNAME could not be played. Check the log for details. CGUIDialogOK::ShowAndGetInput(19033, 0, msg, 0); } - return bReturn; + return ret == PLAYBACK_OK; } bool CGUIWindowPVRCommon::ActionDeleteChannel(CFileItem *item) diff --git a/xbmc/pvr/windows/GUIWindowPVRGuide.cpp b/xbmc/pvr/windows/GUIWindowPVRGuide.cpp index 4dfd5fb832..6b999e4238 100644 --- a/xbmc/pvr/windows/GUIWindowPVRGuide.cpp +++ b/xbmc/pvr/windows/GUIWindowPVRGuide.cpp @@ -29,7 +29,7 @@ #include "epg/EpgContainer.h" #include "pvr/windows/GUIWindowPVR.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "threads/SingleLock.h" #include "utils/log.h" #include "pvr/addons/PVRClients.h" @@ -41,7 +41,7 @@ using namespace EPG; CGUIWindowPVRGuide::CGUIWindowPVRGuide(CGUIWindowPVR *parent) : CGUIWindowPVRCommon(parent, PVR_WINDOW_EPG, CONTROL_BTNGUIDE, CONTROL_LIST_GUIDE_NOW_NEXT), Observer(), - m_iGuideView(g_guiSettings.GetInt("epg.defaultguideview")) + m_iGuideView(CSettings::Get().GetInt("epg.defaultguideview")) { m_cachedTimeline = new CFileItemList; m_cachedChannelGroup = CPVRChannelGroupPtr(new CPVRChannelGroup); @@ -427,15 +427,15 @@ bool CGUIWindowPVRGuide::PlayEpgItem(CFileItem *item) return false; CLog::Log(LOGDEBUG, "play channel '%s'", channel->ChannelName().c_str()); - bool bReturn = g_application.PlayFile(CFileItem(*channel)); - if (!bReturn) + PlayBackRet ret = g_application.PlayFile(CFileItem(*channel)); + if (ret == PLAYBACK_FAIL) { CStdString msg; msg.Format(g_localizeStrings.Get(19035).c_str(), channel->ChannelName().c_str()); // CHANNELNAME could not be played. Check the log for details. CGUIDialogOK::ShowAndGetInput(19033, 0, msg, 0); } - return bReturn; + return ret == PLAYBACK_OK; } bool CGUIWindowPVRGuide::OnContextButtonPlay(CFileItem *item, CONTEXT_BUTTON button) @@ -487,3 +487,11 @@ void CGUIWindowPVRGuide::UpdateButtons(void) else if (m_iGuideView == GUIDE_VIEW_TIMELINE) m_parent->SetLabel(m_iControlButton, g_localizeStrings.Get(19222) + ": " + g_localizeStrings.Get(19032)); } + +void CGUIWindowPVRGuide::SettingOptionsEpgGuideViewFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t) +{ + list.push_back(make_pair(g_localizeStrings.Get(19029), PVR::GUIDE_VIEW_CHANNEL)); + list.push_back(make_pair(g_localizeStrings.Get(19030), PVR::GUIDE_VIEW_NOW)); + list.push_back(make_pair(g_localizeStrings.Get(19031), PVR::GUIDE_VIEW_NEXT)); + list.push_back(make_pair(g_localizeStrings.Get(19032), PVR::GUIDE_VIEW_TIMELINE)); +} diff --git a/xbmc/pvr/windows/GUIWindowPVRGuide.h b/xbmc/pvr/windows/GUIWindowPVRGuide.h index 12ba2c5a34..83c6990603 100644 --- a/xbmc/pvr/windows/GUIWindowPVRGuide.h +++ b/xbmc/pvr/windows/GUIWindowPVRGuide.h @@ -26,8 +26,18 @@ #include "utils/Observer.h" #include "../channels/PVRChannelGroup.h" +class CSetting; + namespace PVR { + enum EpgGuideView + { + GUIDE_VIEW_CHANNEL = 0, + GUIDE_VIEW_NOW, + GUIDE_VIEW_NEXT, + GUIDE_VIEW_TIMELINE + }; + class CGUIWindowPVR; class CGUIWindowPVRGuide : public CGUIWindowPVRCommon, public Observer @@ -45,6 +55,8 @@ namespace PVR void SetInvalid(void) { UpdateData(); } void UnregisterObservers(void); void ResetObservers(void); + + static void SettingOptionsEpgGuideViewFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t); private: bool SelectPlayingFile(void); diff --git a/xbmc/rendering/dx/RenderSystemDX.cpp b/xbmc/rendering/dx/RenderSystemDX.cpp index b9b9b44e4a..b357023fa9 100644 --- a/xbmc/rendering/dx/RenderSystemDX.cpp +++ b/xbmc/rendering/dx/RenderSystemDX.cpp @@ -22,7 +22,6 @@ #ifdef HAS_DX #include "threads/SystemClock.h" -#include "settings/Settings.h" #include "RenderSystemDX.h" #include "utils/log.h" #include "utils/TimeUtils.h" @@ -30,8 +29,8 @@ #include "guilib/GUIWindowManager.h" #include "threads/SingleLock.h" #include "guilib/D3DResource.h" -#include "settings/GUISettings.h" #include "settings/AdvancedSettings.h" +#include "settings/Settings.h" #include "utils/SystemInfo.h" #include "Application.h" #include "Util.h" @@ -174,9 +173,15 @@ void CRenderSystemDX::SetMonitor(HMONITOR monitor) bool CRenderSystemDX::ResetRenderSystem(int width, int height, bool fullScreen, float refreshRate) { - HMONITOR hMonitor = MonitorFromWindow(m_hDeviceWnd, MONITOR_DEFAULTTONULL); - if (hMonitor) - SetMonitor(hMonitor); + if (!m_pD3DDevice) + return false; + + if (m_hDeviceWnd != NULL) + { + HMONITOR hMonitor = MonitorFromWindow(m_hDeviceWnd, MONITOR_DEFAULTTONULL); + if (hMonitor) + SetMonitor(hMonitor); + } SetRenderParams(width, height, fullScreen, refreshRate); diff --git a/xbmc/rendering/gles/RenderSystemGLES.cpp b/xbmc/rendering/gles/RenderSystemGLES.cpp index e7795fbe62..472f4413dd 100644 --- a/xbmc/rendering/gles/RenderSystemGLES.cpp +++ b/xbmc/rendering/gles/RenderSystemGLES.cpp @@ -138,11 +138,7 @@ bool CRenderSystemGLES::ResetRenderSystem(int width, int height, bool fullScreen g_matrices.MatrixMode(MM_PROJECTION); g_matrices.LoadIdentity(); -#ifdef TARGET_RASPBERRY_PI - g_matrices.Ortho(0.0f, width-1, height-1, 0.0f, +1.0f, 1.0f); -#else g_matrices.Ortho(0.0f, width-1, height-1, 0.0f, -1.0f, 1.0f); -#endif g_matrices.MatrixMode(MM_MODELVIEW); g_matrices.LoadIdentity(); diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp index f4b02dbdc0..11fd1e7a64 100644 --- a/xbmc/settings/AdvancedSettings.cpp +++ b/xbmc/settings/AdvancedSettings.cpp @@ -28,19 +28,25 @@ #include "utils/LangCodeExpander.h" #include "LangInfo.h" #include "profiles/ProfilesManager.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "utils/StringUtils.h" #include "utils/SystemInfo.h" #include "utils/URIUtils.h" #include "utils/XMLUtils.h" #include "utils/log.h" #include "filesystem/SpecialProtocol.h" +#include "addons/IAddon.h" +#include "addons/AddonManager.h" +#include "addons/GUIDialogAddonSettings.h" +using namespace ADDON; using namespace XFILE; +using namespace std; CAdvancedSettings::CAdvancedSettings() { m_initialized = false; + m_loaded = false; } void CAdvancedSettings::OnSettingsLoaded() @@ -54,7 +60,7 @@ void CAdvancedSettings::OnSettingsLoaded() CLog::Log(LOGNOTICE, "Default Audio Player: %s", m_audioDefaultPlayer.c_str()); // setup any logging... - if (g_guiSettings.GetBool("debug.showloginfo")) + if (CSettings::Get().GetBool("debug.showloginfo")) { m_logLevel = std::max(m_logLevelHint, LOG_LEVEL_DEBUG_FREEMEM); CLog::Log(LOGNOTICE, "Enabled debug logging due to GUI setting (%d)", m_logLevel); @@ -67,6 +73,31 @@ void CAdvancedSettings::OnSettingsLoaded() CLog::SetLogLevel(m_logLevel); } +void CAdvancedSettings::OnSettingChanged(const CSetting *setting) +{ + if (setting == NULL) + return; + + const std::string &settingId = setting->GetId(); + if (settingId == "debug.showloginfo") + SetDebugMode(((CSettingBool*)setting)->GetValue()); +} + +void CAdvancedSettings::OnSettingAction(const CSetting *setting) +{ + if (setting == NULL) + return; + + const std::string settingId = setting->GetId(); + if (settingId == "debug.setextraloglevel") + { + AddonPtr addon; + CAddonMgr::Get().GetAddon("xbmc.debug", addon); + CGUIDialogAddonSettings::ShowAndGetInput(addon, true); + SetExtraLogsFromAddon(addon.get()); + } +} + void CAdvancedSettings::Initialize() { m_audioHeadRoom = 0; @@ -351,6 +382,7 @@ void CAdvancedSettings::Initialize() m_videoExtensions += "|.pvr"; m_logLevelHint = m_logLevel = LOG_LEVEL_NORMAL; + m_extraLogLevels = 0; #if defined(TARGET_DARWIN) CStdString logDir = getenv("HOME"); @@ -378,6 +410,9 @@ bool CAdvancedSettings::Load() void CAdvancedSettings::ParseSettingsFile(const CStdString &file) { + if (m_loaded) + return; + CXBMCTinyXML advancedXML; if (!CFile::Exists(file)) { @@ -756,12 +791,12 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file) { // read the loglevel setting, so set the setting advanced to hide it in GUI // as altering it will do nothing - we don't write to advancedsettings.xml XMLUtils::GetInt(pRootElement, "loglevel", m_logLevelHint, LOG_LEVEL_NONE, LOG_LEVEL_MAX); - CSettingBool *setting = (CSettingBool *)g_guiSettings.GetSetting("debug.showloginfo"); - if (setting) + CSettingBool *setting = (CSettingBool *)CSettings::Get().GetSetting("debug.showloginfo"); + if (setting != NULL) { const char* hide; if (!((hide = pElement->Attribute("hide")) && strnicmp("false", hide, 4) == 0)) - setting->SetAdvanced(); + setting->SetVisible(false); } g_advancedSettings.m_logLevel = std::max(g_advancedSettings.m_logLevel, g_advancedSettings.m_logLevelHint); CLog::SetLogLevel(g_advancedSettings.m_logLevel); @@ -1089,8 +1124,11 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file) XMLUtils::GetInt(pElement, "nofliptimeout", m_guiDirtyRegionNoFlipTimeout); } - // load in the GUISettings overrides: - g_guiSettings.LoadXML(pRootElement, true); // true to hide the settings we read in + // must be done before calling CSettings::Load() to avoid an infinite loop + m_loaded = true; + + // load in the settings overrides + CSettings::Get().Load(pRootElement, true); // true to hide the settings we read in } void CAdvancedSettings::Clear() @@ -1112,6 +1150,8 @@ void CAdvancedSettings::Clear() m_logFolder.clear(); m_userAgent.clear(); + + m_loaded = false; } void CAdvancedSettings::GetCustomTVRegexps(TiXmlElement *pRootElement, SETTINGS_TVSHOWLIST& settings) @@ -1266,3 +1306,16 @@ void CAdvancedSettings::SetDebugMode(bool debug) CLog::SetLogLevel(level); } } + +void CAdvancedSettings::SetExtraLogsFromAddon(ADDON::IAddon* addon) +{ + m_extraLogLevels = 0; + for (int i=LOGMASKBIT;i<31;++i) + { + CStdString str; + str.Format("bit%i", i-LOGMASKBIT+1); + if (addon->GetSetting(str) == "true") + m_extraLogLevels |= (1 << i); + } + CLog::SetExtraLogLevels(m_extraLogLevels); +} diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h index b6bf23a861..8e9d9f2eac 100644 --- a/xbmc/settings/AdvancedSettings.h +++ b/xbmc/settings/AdvancedSettings.h @@ -21,11 +21,16 @@ #include <vector> +#include "settings/ISettingCallback.h" #include "settings/ISettingsHandler.h" #include "utils/StdString.h" #include "utils/GlobalsHandling.h" class TiXmlElement; +namespace ADDON +{ + class IAddon; +} class DatabaseSettings { @@ -82,7 +87,7 @@ struct RefreshVideoLatency typedef std::vector<TVShowRegexp> SETTINGS_TVSHOWLIST; -class CAdvancedSettings : public ISettingsHandler +class CAdvancedSettings : public ISettingCallback, public ISettingsHandler { public: CAdvancedSettings(); @@ -91,6 +96,10 @@ class CAdvancedSettings : public ISettingsHandler virtual void OnSettingsLoaded(); + virtual void OnSettingChanged(const CSetting *setting); + + virtual void OnSettingAction(const CSetting *setting); + void Initialize(); bool Initialized() { return m_initialized; }; void AddSettingsFile(const CStdString &filename); @@ -181,6 +190,7 @@ class CAdvancedSettings : public ISettingsHandler int m_songInfoDuration; int m_logLevel; int m_logLevelHint; + int m_extraLogLevels; CStdString m_cddbAddress; //airtunes + airplay @@ -363,8 +373,10 @@ class CAdvancedSettings : public ISettingsHandler float GetDisplayLatency(float refreshrate); bool m_initialized; + bool m_loaded; void SetDebugMode(bool debug); + void SetExtraLogsFromAddon(ADDON::IAddon* addon); // runtime settings which cannot be set from advancedsettings.xml CStdString m_pictureExtensions; diff --git a/xbmc/settings/DisplaySettings.cpp b/xbmc/settings/DisplaySettings.cpp index 7784641765..40b12635a3 100644 --- a/xbmc/settings/DisplaySettings.cpp +++ b/xbmc/settings/DisplaySettings.cpp @@ -22,12 +22,20 @@ #include <stdlib.h> #include "DisplaySettings.h" +#include "dialogs/GUIDialogYesNo.h" +#include "guilib/GraphicContext.h" #include "guilib/gui3d.h" -#include "settings/GUISettings.h" +#include "guilib/LocalizeStrings.h" +#include "settings/AdvancedSettings.h" +#include "settings/Settings.h" #include "threads/SingleLock.h" #include "utils/log.h" #include "utils/StringUtils.h" #include "utils/XMLUtils.h" +#include "windowing/WindowingFactory.h" + +// 0.1 second increments +#define MAX_REFRESH_CHANGE_DELAY 200 using namespace std; @@ -181,39 +189,103 @@ void CDisplaySettings::Clear() m_nonLinearStretched = false; } -void CDisplaySettings::SetCurrentResolution(RESOLUTION resolution, bool save /* = false */) +bool CDisplaySettings::OnSettingChanging(const CSetting *setting) { - if (save) + if (setting == NULL) + return false; + + const std::string &settingId = setting->GetId(); + if (settingId == "videoscreen.resolution" || + settingId == "videoscreen.screen" || + settingId == "videoscreen.screenmode") { - string mode; - if (resolution == RES_DESKTOP) - mode = "DESKTOP"; - else if (resolution == RES_WINDOW) - mode = "WINDOW"; - else if (resolution >= RES_CUSTOM && resolution < (RESOLUTION)m_resolutions.size()) + // check if this is the revert call for a failed OnSettingChanging + // in which case we don't want to ask the user again + if (m_ignoreSettingChanging.find(make_pair(settingId, true)) == m_ignoreSettingChanging.end()) { - const RESOLUTION_INFO &info = m_resolutions[resolution]; - mode = StringUtils::Format("%1i%05i%05i%09.5f%s", info.iScreen, - info.iScreenWidth, info.iScreenHeight, info.fRefreshRate, - (info.dwFlags & D3DPRESENTFLAG_INTERLACED) ? "i":"p"); + RESOLUTION newRes = RES_DESKTOP; + if (settingId == "videoscreen.resolution") + newRes = (RESOLUTION)((CSettingInt*)setting)->GetValue(); + else if (settingId == "videoscreen.screen") + newRes = GetResolutionForScreen(); + else if (settingId == "videoscreen.screenmode") + newRes = GetResolutionFromString(((CSettingString*)setting)->GetValue()); + + // We need to change and save videoscreen.screenmode which will + // trigger another call to this OnSettingChanging() which should not + // trigger a user-input dialog which is already triggered by the callback + // of the changed setting + bool save = settingId != "videoscreen.screenmode"; + if (save) + m_ignoreSettingChanging.insert(make_pair("videoscreen.screenmode", true)); + SetCurrentResolution(newRes, save); + g_graphicsContext.SetVideoResolution(newRes); + + // check if this setting is temporarily blocked from showing the dialog + if (m_ignoreSettingChanging.find(make_pair(settingId, false)) == m_ignoreSettingChanging.end()) + { + bool cancelled = false; + if (!CGUIDialogYesNo::ShowAndGetInput(13110, 13111, 20022, 20022, -1, -1, cancelled, 10000)) + { + // we need to ignore the next OnSettingChanging() call for + // the same setting which is executed to broadcast that + // changing the setting has failed + m_ignoreSettingChanging.insert(make_pair(settingId, false)); + return false; + } + } + else + m_ignoreSettingChanging.erase(make_pair(settingId, false)); + + if (settingId == "videoscreen.screen") + { + m_ignoreSettingChanging.insert(make_pair("videoscreen.resolution", true)); + if (CSettings::Get().GetSetting("videoscreen.screenmode")->IsVisible()) + m_ignoreSettingChanging.insert(make_pair("videoscreen.screenmode", true)); + } } else - { - CLog::Log(LOGWARNING, "CDisplaySettings: setting invalid resolution %i", resolution); - mode = "DESKTOP"; - } + m_ignoreSettingChanging.erase(make_pair(settingId, true)); + } + + return true; +} - g_guiSettings.SetString("videoscreen.screenmode", mode.c_str()); +bool CDisplaySettings::OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode) +{ + if (setting == NULL) + return false; + + const std::string &settingId = setting->GetId(); + if (settingId == "videoscreen.screenmode") + { + CSettingString *screenmodeSetting = (CSettingString*)setting; + std::string screenmode = screenmodeSetting->GetValue(); + // in Eden there was no character ("i" or "p") indicating interlaced/progressive + // at the end so we just add a "p" and assume progressive + if (screenmode.size() == 20) + return screenmodeSetting->SetValue(screenmode + "p"); + } + + return false; +} + +void CDisplaySettings::SetCurrentResolution(RESOLUTION resolution, bool save /* = false */) +{ + if (save) + { + string mode = GetStringFromResolution(resolution); + CSettings::Get().SetString("videoscreen.screenmode", mode.c_str()); } m_currentResolution = resolution; - g_guiSettings.SetChanged(); + SetChanged(); } RESOLUTION CDisplaySettings::GetDisplayResolution() const { - return GetResolutionFromString(g_guiSettings.GetString("videoscreen.screenmode")); + return GetResolutionFromString(CSettings::Get().GetString("videoscreen.screenmode")); } const RESOLUTION_INFO& CDisplaySettings::GetResolutionInfo(size_t index) const @@ -340,7 +412,7 @@ void CDisplaySettings::UpdateCalibrations() } } -RESOLUTION CDisplaySettings::GetResolutionFromString(const std::string &strResolution) const +RESOLUTION CDisplaySettings::GetResolutionFromString(const std::string &strResolution) { if (strResolution == "DESKTOP") return RES_DESKTOP; @@ -360,9 +432,10 @@ RESOLUTION CDisplaySettings::GetResolutionFromString(const std::string &strResol // find the closest match to these in our res vector. If we have the screen, we score the res RESOLUTION bestRes = RES_DESKTOP; float bestScore = FLT_MAX; - for (ResolutionInfos::const_iterator resolution = m_resolutions.begin(); resolution != m_resolutions.end(); resolution++) + + for (size_t resolution = 0; resolution < CDisplaySettings::Get().ResolutionInfoSize(); resolution++) { - const RESOLUTION_INFO &info = *resolution; + const RESOLUTION_INFO &info = CDisplaySettings::Get().GetResolutionInfo(resolution); if (info.iScreen != screen) continue; float score = 10 * (square_error((float)info.iScreenWidth, (float)width) + @@ -372,7 +445,7 @@ RESOLUTION CDisplaySettings::GetResolutionFromString(const std::string &strResol if (score < bestScore) { bestScore = score; - bestRes = (RESOLUTION)(resolution - m_resolutions.begin()); + bestRes = (RESOLUTION)resolution; } } return bestRes; @@ -380,3 +453,131 @@ RESOLUTION CDisplaySettings::GetResolutionFromString(const std::string &strResol return RES_DESKTOP; } + +std::string CDisplaySettings::GetStringFromResolution(RESOLUTION resolution, float refreshrate /* = 0.0f */) +{ + if (resolution == RES_WINDOW) + return "WINDOW"; + + if (resolution >= RES_CUSTOM && resolution < (RESOLUTION)CDisplaySettings::Get().ResolutionInfoSize()) + { + const RESOLUTION_INFO &info = CDisplaySettings::Get().GetResolutionInfo(resolution); + return StringUtils::Format("%1i%05i%05i%09.5f%s", info.iScreen, + info.iScreenWidth, info.iScreenHeight, + refreshrate > 0.0f ? refreshrate : info.fRefreshRate, + (info.dwFlags & D3DPRESENTFLAG_INTERLACED) ? "i":"p"); + } + + return "DESKTOP"; +} + +RESOLUTION CDisplaySettings::GetResolutionForScreen() +{ + DisplayMode mode = CSettings::Get().GetInt("videoscreen.screen"); + if (mode == DM_WINDOWED) + return RES_WINDOW; + + for (int idx=0; idx < g_Windowing.GetNumScreens(); idx++) + { + if (CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP + idx).iScreen == mode) + return (RESOLUTION)(RES_DESKTOP + idx); + } + + return RES_DESKTOP; +} + +void CDisplaySettings::SettingOptionsRefreshChangeDelaysFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t) +{ + list.push_back(make_pair(g_localizeStrings.Get(13551), 0)); + + for (int i = 1; i <= MAX_REFRESH_CHANGE_DELAY; i++) + list.push_back(make_pair(StringUtils::Format(g_localizeStrings.Get(13553).c_str(), (double)i / 10.0), i)); +} + +void CDisplaySettings::SettingOptionsRefreshRatesFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t) +{ + // get the proper resolution + RESOLUTION res = GetResolutionForScreen(); + if (res < RES_WINDOW) + return; + + // only add "Windowed" if in windowed mode + if (res == RES_WINDOW) + { + current = "WINDOW"; + list.push_back(make_pair(g_localizeStrings.Get(242), current)); + return; + } + + // The only meaningful parts of res here are iScreen, iScreenWidth, iScreenHeight + vector<REFRESHRATE> refreshrates = g_Windowing.RefreshRates(CDisplaySettings::Get().GetResolutionInfo(res).iScreen, + CDisplaySettings::Get().GetResolutionInfo(res).iScreenWidth, + CDisplaySettings::Get().GetResolutionInfo(res).iScreenHeight, + CDisplaySettings::Get().GetResolutionInfo(res).dwFlags); + + bool match = false; + for (vector<REFRESHRATE>::const_iterator refreshrate = refreshrates.begin(); refreshrate != refreshrates.end(); refreshrate++) + { + std::string screenmode = GetStringFromResolution(res, refreshrate->RefreshRate); + if (!match && StringUtils::EqualsNoCase(((CSettingString*)setting)->GetValue(), screenmode)) + match = true; + list.push_back(make_pair(StringUtils::Format("%.02f", refreshrate->RefreshRate), screenmode)); + } + + if (!match) + current = GetStringFromResolution(res, g_Windowing.DefaultRefreshRate(CDisplaySettings::Get().GetResolutionInfo(res).iScreen, refreshrates).RefreshRate); +} + +void CDisplaySettings::SettingOptionsResolutionsFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t) +{ + RESOLUTION res = RES_INVALID; + DisplayMode screen = CSettings::Get().GetInt("videoscreen.screen"); + if (screen == DM_WINDOWED) + { + res = RES_WINDOW; + list.push_back(make_pair(g_localizeStrings.Get(242), RES_WINDOW)); + } + else + { + vector<RESOLUTION_WHR> resolutions = g_Windowing.ScreenResolutions(screen); + for (vector<RESOLUTION_WHR>::const_iterator resolution = resolutions.begin(); resolution != resolutions.end(); resolution++) + { + list.push_back(make_pair( + StringUtils::Format("%dx%d%s", resolution->width, resolution->height, (resolution->interlaced == D3DPRESENTFLAG_INTERLACED) ? "i" : "p"), + resolution->ResInfo_Index)); + + RESOLUTION_INFO res1 = CDisplaySettings::Get().GetCurrentResolutionInfo(); + RESOLUTION_INFO res2 = CDisplaySettings::Get().GetResolutionInfo(resolution->ResInfo_Index); + if (res1.iScreen == res2.iScreen && + res1.iScreenWidth == res2.iScreenWidth && + res1.iScreenHeight == res2.iScreenHeight && + (res1.dwFlags & D3DPRESENTFLAG_INTERLACED) == (res2.dwFlags & D3DPRESENTFLAG_INTERLACED)) + res = (RESOLUTION)resolution->ResInfo_Index; + } + } + + if (res != RES_INVALID) + current = res; +} + +void CDisplaySettings::SettingOptionsScreensFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t) +{ + if (g_advancedSettings.m_canWindowed) + list.push_back(make_pair(g_localizeStrings.Get(242), DM_WINDOWED)); + + for (int idx = 0; idx < g_Windowing.GetNumScreens(); idx++) + { + int screen = CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP + idx).iScreen; + list.push_back(make_pair(StringUtils::Format(g_localizeStrings.Get(241), screen + 1), screen)); + } +} + +void CDisplaySettings::SettingOptionsVerticalSyncsFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t) +{ +#if defined(_LINUX) && !defined(TARGET_DARWIN) + list.push_back(make_pair(g_localizeStrings.Get(13101), VSYNC_DRIVER)); +#endif + list.push_back(make_pair(g_localizeStrings.Get(13106), VSYNC_DISABLED)); + list.push_back(make_pair(g_localizeStrings.Get(13107), VSYNC_VIDEO)); + list.push_back(make_pair(g_localizeStrings.Get(13108), VSYNC_ALWAYS)); +} diff --git a/xbmc/settings/DisplaySettings.h b/xbmc/settings/DisplaySettings.h index aff6ddb968..be4f159a00 100644 --- a/xbmc/settings/DisplaySettings.h +++ b/xbmc/settings/DisplaySettings.h @@ -19,15 +19,19 @@ * */ +#include <set> #include <vector> #include "guilib/Resolution.h" +#include "settings/ISettingCallback.h" #include "settings/ISubSettings.h" #include "threads/CriticalSection.h" +#include "utils/Observer.h" class TiXmlNode; -class CDisplaySettings : public ISubSettings +class CDisplaySettings : public ISettingCallback, public ISubSettings, + public Observable { public: static CDisplaySettings& Get(); @@ -36,6 +40,9 @@ public: virtual bool Save(TiXmlNode *settings) const; virtual void Clear(); + virtual bool OnSettingChanging(const CSetting *setting); + virtual bool OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode); + /*! \brief Returns the currently active resolution @@ -80,13 +87,21 @@ public: bool IsNonLinearStretched() const { return m_nonLinearStretched; } void SetNonLinearStretched(bool nonLinearStretch) { m_nonLinearStretched = nonLinearStretch; } + static void SettingOptionsRefreshChangeDelaysFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t); + static void SettingOptionsRefreshRatesFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t); + static void SettingOptionsResolutionsFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t); + static void SettingOptionsScreensFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t); + static void SettingOptionsVerticalSyncsFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t); + protected: CDisplaySettings(); CDisplaySettings(const CDisplaySettings&); CDisplaySettings const& operator=(CDisplaySettings const&); virtual ~CDisplaySettings(); - RESOLUTION GetResolutionFromString(const std::string &strResolution) const; + static RESOLUTION GetResolutionFromString(const std::string &strResolution); + static std::string GetStringFromResolution(RESOLUTION resolution, float refreshrate = 0.0f); + static RESOLUTION GetResolutionForScreen(); private: // holds the real gui resolution @@ -100,5 +115,14 @@ private: float m_pixelRatio; // current pixel ratio float m_verticalShift; // current vertical shift bool m_nonLinearStretched; // current non-linear stretch + + /*! + \brief A set of pairs consisting of a setting identifier + and a boolean value which should be ignored in specific + situations. If the boolean value is "true" the whole + OnSettingChanging() logic must be skipped once. If it + is "false" only showing the GUI dialog must be skipped. + */ + std::set< std::pair<std::string, bool> > m_ignoreSettingChanging; CCriticalSection m_critical; }; diff --git a/xbmc/settings/GUISettings.cpp b/xbmc/settings/GUISettings.cpp deleted file mode 100644 index 128a7115f3..0000000000 --- a/xbmc/settings/GUISettings.cpp +++ /dev/null @@ -1,1602 +0,0 @@ -/* - * Copyright (C) 2005-2013 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 "network/Network.h" -#include "GUISettings.h" -#include <limits.h> -#include <float.h> -#include "Settings.h" -#include "dialogs/GUIDialogFileBrowser.h" -#include "storage/MediaManager.h" -#ifdef _LINUX -#include "LinuxTimezone.h" -#endif -#include "Application.h" -#include "AdvancedSettings.h" -#include "guilib/LocalizeStrings.h" -#include "utils/CharsetConverter.h" -#include "settings/DisplaySettings.h" -#include "settings/VideoSettings.h" -#include "utils/StringUtils.h" -#include "utils/SystemInfo.h" -#include "utils/log.h" -#include "utils/XBMCTinyXML.h" -#include "windowing/WindowingFactory.h" -#include "powermanagement/PowerManager.h" -#include "cores/dvdplayer/DVDCodecs/Video/CrystalHD.h" -#include "cores/AudioEngine/AEFactory.h" -#include "cores/AudioEngine/AEAudioFormat.h" -#include "cores/paplayer/AudioDecoder.h" -#include "filesystem/CurlFile.h" -#include "guilib/GUIFont.h" // for FONT_STYLE_* definitions -#if defined(TARGET_DARWIN_OSX) - #include "cores/AudioEngine/Engines/CoreAudio/CoreAudioHardware.h" -#endif -#include "guilib/GUIFontManager.h" -#include "LangInfo.h" -#include "pvr/PVRManager.h" -#include "utils/XMLUtils.h" -#if defined(TARGET_DARWIN) - #include "osx/DarwinUtils.h" -#endif -#include "Util.h" - -using namespace std; -using namespace ADDON; -using namespace PVR; - -// String id's of the masks -#define MASK_DAYS 17999 -#define MASK_HOURS 17998 -#define MASK_MINS 14044 -#define MASK_SECS 14045 -#define MASK_MS 14046 -#define MASK_PERCENT 14047 -#define MASK_KBPS 14048 -#define MASK_MB 17997 -#define MASK_KB 14049 -#define MASK_DB 14050 - -#define MAX_RESOLUTIONS 128 - -#define TEXT_OFF 351 -#define TEXT_NONE 231 - -#ifdef _LINUX -#define DEFAULT_VISUALISATION "visualization.glspectrum" -#elif defined(_WIN32) -#ifdef HAS_DX -#define DEFAULT_VISUALISATION "visualization.milkdrop" -#else -#define DEFAULT_VISUALISATION "visualization.glspectrum" -#endif -#endif - -#define DEFAULT_WEB_INTERFACE "webinterface.default" - -#ifdef MID -#define DEFAULT_VSYNC VSYNC_DISABLED -#else // MID -#if defined(TARGET_DARWIN) || defined(_WIN32) || defined(TARGET_RASPBERRY_PI) -#define DEFAULT_VSYNC VSYNC_ALWAYS -#else -#define DEFAULT_VSYNC VSYNC_DRIVER -#endif -#endif // MID - -struct sortsettings -{ - bool operator()(const CSetting* pSetting1, const CSetting* pSetting2) - { - return pSetting1->GetOrder() < pSetting2->GetOrder(); - } -}; - -void CSettingBool::FromString(const CStdString &strValue) -{ - m_bData = (strValue == "true"); -} - -CStdString CSettingBool::ToString() const -{ - return m_bData ? "true" : "false"; -} - -CSettingSeparator::CSettingSeparator(int iOrder, const char *strSetting) - : CSetting(iOrder, strSetting, 0, SEPARATOR_CONTROL) -{ -} - -CSettingFloat::CSettingFloat(int iOrder, const char *strSetting, int iLabel, float fData, float fMin, float fStep, float fMax, int iControlType) - : CSetting(iOrder, strSetting, iLabel, iControlType) -{ - m_fData = fData; - m_fMin = fMin; - m_fStep = fStep; - m_fMax = fMax; -} - -void CSettingFloat::FromString(const CStdString &strValue) -{ - SetData((float)atof(strValue.c_str())); -} - -CStdString CSettingFloat::ToString() const -{ - CStdString strValue; - strValue.Format("%f", m_fData); - return strValue; -} - -CSettingInt::CSettingInt(int iOrder, const char *strSetting, int iLabel, int iData, int iMin, int iStep, int iMax, int iControlType, const char *strFormat) - : CSetting(iOrder, strSetting, iLabel, iControlType) -{ - m_iData = iData; - m_iMin = iMin; - m_iMax = iMax; - m_iStep = iStep; - m_iFormat = -1; - m_iLabelMin = -1; - if (strFormat) - m_strFormat = strFormat; - else - m_strFormat = "%i"; -} - -CSettingInt::CSettingInt(int iOrder, const char *strSetting, int iLabel, int iData, int iMin, int iStep, int iMax, int iControlType, int iFormat, int iLabelMin) - : CSetting(iOrder, strSetting, iLabel, iControlType) -{ - m_iData = iData; - m_iMin = iMin; - m_iMax = iMax; - m_iStep = iStep; - m_iLabelMin = iLabelMin; - m_iFormat = iFormat; - if (m_iFormat < 0) - m_strFormat = "%i"; -} - -CSettingInt::CSettingInt(int iOrder, const char *strSetting, int iLabel, - int iData, const map<int,int>& entries, int iControlType) - : CSetting(iOrder, strSetting, iLabel, iControlType), - m_entries(entries) -{ - m_iData = iData; - m_iMin = -1; - m_iMax = -1; - m_iStep = 1; - m_iLabelMin = -1; -} - -void CSettingInt::FromString(const CStdString &strValue) -{ - int id = atoi(strValue.c_str()); - SetData(id); -} - -CStdString CSettingInt::ToString() const -{ - CStdString strValue; - strValue.Format("%i", m_iData); - return strValue; -} - -void CSettingHex::FromString(const CStdString &strValue) -{ - int iHexValue; - if (sscanf(strValue, "%x", (unsigned int *)&iHexValue)) - SetData(iHexValue); -} - -CStdString CSettingHex::ToString() const -{ - CStdString strValue; - strValue.Format("%x", m_iData); - return strValue; -} - -CSettingString::CSettingString(int iOrder, const char *strSetting, int iLabel, const char *strData, int iControlType, bool bAllowEmpty, int iHeadingString) - : CSetting(iOrder, strSetting, iLabel, iControlType) -{ - m_strData = strData; - m_bAllowEmpty = bAllowEmpty; - m_iHeadingString = iHeadingString; -} - -void CSettingString::FromString(const CStdString &strValue) -{ - m_strData = strValue; -} - -CStdString CSettingString::ToString() const -{ - return m_strData; -} - -CSettingPath::CSettingPath(int iOrder, const char *strSetting, int iLabel, const char *strData, int iControlType, bool bAllowEmpty, int iHeadingString) - : CSettingString(iOrder, strSetting, iLabel, strData, iControlType, bAllowEmpty, iHeadingString) -{ -} - -CSettingAddon::CSettingAddon(int iOrder, const char *strSetting, int iLabel, const char *strData, const TYPE type) - : CSettingString(iOrder, strSetting, iLabel, strData, BUTTON_CONTROL_STANDARD, false, -1) - , m_type(type) -{ -} - -CSettingsCategory* CSettingsGroup::AddCategory(const char *strCategory, int labelID) -{ - // Remove the category if it already exists - for (vecSettingsCategory::iterator it = m_vecCategories.begin(); it != m_vecCategories.end(); it++) - { - if ((*it)->m_strCategory.Equals(strCategory)) - { - delete (*it); - m_vecCategories.erase(it); - break; - } - } - CSettingsCategory *pCategory = new CSettingsCategory(strCategory, labelID); - if (pCategory) - m_vecCategories.push_back(pCategory); - return pCategory; -} - -void CSettingsGroup::GetCategories(vecSettingsCategory &vecCategories) -{ - vecCategories.clear(); - for (unsigned int i = 0; i < m_vecCategories.size(); i++) - { - vecSettings settings; - // check whether we actually have these settings available. - g_guiSettings.GetSettingsGroup(m_vecCategories[i], settings); - if (settings.size()) - vecCategories.push_back(m_vecCategories[i]); - } -} - -#define SETTINGS_PICTURES WINDOW_SETTINGS_MYPICTURES - WINDOW_SETTINGS_START -#define SETTINGS_PROGRAMS WINDOW_SETTINGS_MYPROGRAMS - WINDOW_SETTINGS_START -#define SETTINGS_WEATHER WINDOW_SETTINGS_MYWEATHER - WINDOW_SETTINGS_START -#define SETTINGS_MUSIC WINDOW_SETTINGS_MYMUSIC - WINDOW_SETTINGS_START -#define SETTINGS_SYSTEM WINDOW_SETTINGS_SYSTEM - WINDOW_SETTINGS_START -#define SETTINGS_VIDEOS WINDOW_SETTINGS_MYVIDEOS - WINDOW_SETTINGS_START -#define SETTINGS_SERVICE WINDOW_SETTINGS_SERVICE - WINDOW_SETTINGS_START -#define SETTINGS_APPEARANCE WINDOW_SETTINGS_APPEARANCE - WINDOW_SETTINGS_START -#define SETTINGS_PVR WINDOW_SETTINGS_MYPVR - WINDOW_SETTINGS_START - -// Settings are case sensitive -CGUISettings::CGUISettings(void) -{ -} - -void CGUISettings::Initialize() -{ - // Pictures settings - AddGroup(SETTINGS_PICTURES, 1); - CSettingsCategory* pic = AddCategory(SETTINGS_PICTURES, "pictures", 14081); - AddBool(pic, "pictures.usetags", 14082, true); - AddBool(pic,"pictures.generatethumbs",13360,true); - AddBool(pic, "pictures.useexifrotation", 20184, true); - AddBool(pic, "pictures.showvideos", 22022, true); - // FIXME: hide this setting until it is properly respected. In the meanwhile, default to AUTO. - AddInt(NULL, "pictures.displayresolution", 169, (int)RES_AUTORES, (int)RES_AUTORES, 1, (int)RES_AUTORES, SPIN_CONTROL_TEXT); - - CSettingsCategory* cat = AddCategory(SETTINGS_PICTURES, "slideshow", 108); - AddInt(cat, "slideshow.staytime", 12378, 5, 1, 1, 100, SPIN_CONTROL_INT_PLUS, MASK_SECS); - AddBool(cat, "slideshow.displayeffects", 12379, true); - AddBool(NULL, "slideshow.shuffle", 13319, false); - - // Programs settings -// AddGroup(1, 0); - - // My Weather settings - AddGroup(SETTINGS_WEATHER, 8); - CSettingsCategory* wea = AddCategory(SETTINGS_WEATHER, "weather", 16000); - AddInt(NULL, "weather.currentlocation", 0, 1, 1, 1, 3, SPIN_CONTROL_INT_PLUS); - AddDefaultAddon(wea, "weather.addon", 24029, "weather.wunderground", ADDON_SCRIPT_WEATHER); - AddString(wea, "weather.addonsettings", 21417, "", BUTTON_CONTROL_STANDARD, true); - - // My Music Settings - AddGroup(SETTINGS_MUSIC, 2); - CSettingsCategory* ml = AddCategory(SETTINGS_MUSIC,"musiclibrary",14022); - AddBool(NULL, "musiclibrary.enabled", 418, true); - AddBool(ml, "musiclibrary.showcompilationartists", 13414, true); - AddSeparator(ml,"musiclibrary.sep1"); - AddBool(ml,"musiclibrary.downloadinfo", 20192, false); - AddDefaultAddon(ml, "musiclibrary.albumsscraper", 20193, "metadata.album.universal", ADDON_SCRAPER_ALBUMS); - AddDefaultAddon(ml, "musiclibrary.artistsscraper", 20194, "metadata.artists.universal", ADDON_SCRAPER_ARTISTS); - AddBool(ml, "musiclibrary.updateonstartup", 22000, false); - AddBool(ml, "musiclibrary.backgroundupdate", 22001, false); - AddSeparator(ml,"musiclibrary.sep2"); - AddString(ml, "musiclibrary.cleanup", 334, "", BUTTON_CONTROL_STANDARD); - AddString(ml, "musiclibrary.export", 20196, "", BUTTON_CONTROL_STANDARD); - AddString(ml, "musiclibrary.import", 20197, "", BUTTON_CONTROL_STANDARD); - - CSettingsCategory* mp = AddCategory(SETTINGS_MUSIC, "musicplayer", 14086); - AddBool(mp, "musicplayer.autoplaynextitem", 489, true); - AddBool(mp, "musicplayer.queuebydefault", 14084, false); - AddSeparator(mp, "musicplayer.sep1"); - map<int,int> gain; - gain.insert(make_pair(351,REPLAY_GAIN_NONE)); - gain.insert(make_pair(639,REPLAY_GAIN_TRACK)); - gain.insert(make_pair(640,REPLAY_GAIN_ALBUM)); - - AddInt(mp, "musicplayer.replaygaintype", 638, REPLAY_GAIN_ALBUM, gain, SPIN_CONTROL_TEXT); - AddInt(mp, "musicplayer.replaygainpreamp", 641, 89, 77, 1, 101, SPIN_CONTROL_INT_PLUS, MASK_DB); - AddInt(mp, "musicplayer.replaygainnogainpreamp", 642, 89, 77, 1, 101, SPIN_CONTROL_INT_PLUS, MASK_DB); - AddBool(mp, "musicplayer.replaygainavoidclipping", 643, false); - AddSeparator(mp, "musicplayer.sep2"); - AddInt(mp, "musicplayer.crossfade", 13314, 0, 0, 1, 15, SPIN_CONTROL_INT_PLUS, MASK_SECS, TEXT_OFF); - AddBool(mp, "musicplayer.crossfadealbumtracks", 13400, true); - AddSeparator(mp, "musicplayer.sep3"); - AddDefaultAddon(mp, "musicplayer.visualisation", 250, DEFAULT_VISUALISATION, ADDON_VIZ); - - CSettingsCategory* mf = AddCategory(SETTINGS_MUSIC, "musicfiles", 14081); - AddBool(mf, "musicfiles.usetags", 258, true); - AddString(mf, "musicfiles.trackformat", 13307, "[%N. ]%A - %T", EDIT_CONTROL_INPUT, false, 16016); - AddString(mf, "musicfiles.trackformatright", 13387, "%D", EDIT_CONTROL_INPUT, false, 16016); - // advanced per-view trackformats. - AddString(NULL, "musicfiles.nowplayingtrackformat", 13307, "", EDIT_CONTROL_INPUT, false, 16016); - AddString(NULL, "musicfiles.nowplayingtrackformatright", 13387, "", EDIT_CONTROL_INPUT, false, 16016); - AddString(NULL, "musicfiles.librarytrackformat", 13307, "", EDIT_CONTROL_INPUT, false, 16016); - AddString(NULL, "musicfiles.librarytrackformatright", 13387, "", EDIT_CONTROL_INPUT, false, 16016); - AddBool(mf, "musicfiles.findremotethumbs", 14059, true); - - CSettingsCategory* acd = AddCategory(SETTINGS_MUSIC, "audiocds", 620); - map<int,int> autocd; - autocd.insert(make_pair(16018, AUTOCD_NONE)); - autocd.insert(make_pair(14098, AUTOCD_PLAY)); -#ifdef HAS_CDDA_RIPPER - autocd.insert(make_pair(14096, AUTOCD_RIP)); -#endif - AddInt(acd,"audiocds.autoaction",14097,AUTOCD_NONE, autocd, SPIN_CONTROL_TEXT); - AddBool(acd, "audiocds.usecddb", 227, true); - AddSeparator(acd, "audiocds.sep1"); - AddPath(acd,"audiocds.recordingpath",20000,"select writable folder",BUTTON_CONTROL_PATH_INPUT,false,657); - AddString(acd, "audiocds.trackpathformat", 13307, "%A - %B/[%N. ][%A - ]%T", EDIT_CONTROL_INPUT, false, 16016); - map<int,int> encoders; -#ifdef HAVE_LIBMP3LAME - encoders.insert(make_pair(34000,CDDARIP_ENCODER_LAME)); -#endif -#ifdef HAVE_LIBVORBISENC - encoders.insert(make_pair(34001,CDDARIP_ENCODER_VORBIS)); -#endif - encoders.insert(make_pair(34002,CDDARIP_ENCODER_WAV)); - encoders.insert(make_pair(34005,CDDARIP_ENCODER_FLAC)); - AddInt(acd, "audiocds.encoder", 621, CDDARIP_ENCODER_FLAC, encoders, SPIN_CONTROL_TEXT); - - map<int,int> qualities; - qualities.insert(make_pair(604,CDDARIP_QUALITY_CBR)); - qualities.insert(make_pair(601,CDDARIP_QUALITY_MEDIUM)); - qualities.insert(make_pair(602,CDDARIP_QUALITY_STANDARD)); - qualities.insert(make_pair(603,CDDARIP_QUALITY_EXTREME)); - AddInt(acd, "audiocds.quality", 622, CDDARIP_QUALITY_CBR, qualities, SPIN_CONTROL_TEXT); - AddInt(acd, "audiocds.bitrate", 623, 192, 128, 32, 320, SPIN_CONTROL_INT_PLUS, MASK_KBPS); - AddInt(acd, "audiocds.compressionlevel", 665, 5, 0, 1, 8, SPIN_CONTROL_INT_PLUS); - AddBool(acd, "audiocds.ejectonrip", 14099, true); - -#ifdef HAS_KARAOKE - CSettingsCategory* kar = AddCategory(SETTINGS_MUSIC, "karaoke", 13327); - AddBool(kar, "karaoke.enabled", 13323, false); - // auto-popup the song selector dialog when the karaoke song was just finished and playlist is empty. - AddBool(kar, "karaoke.autopopupselector", 22037, false); - AddSeparator(kar, "karaoke.sep1"); - AddString(kar, "karaoke.font", 22030, "arial.ttf", SPIN_CONTROL_TEXT); - AddInt(kar, "karaoke.fontheight", 22031, 36, 16, 2, 74, SPIN_CONTROL_TEXT); // use text as there is a disk based lookup needed - map<int,int> colors; - for (int i = KARAOKE_COLOR_START; i < KARAOKE_COLOR_END; i++) - colors.insert(make_pair(22040 + i, i)); - AddInt(kar, "karaoke.fontcolors", 22032, KARAOKE_COLOR_START, colors, SPIN_CONTROL_TEXT); - AddString(kar, "karaoke.charset", 22033, "DEFAULT", SPIN_CONTROL_TEXT); - AddSeparator(kar,"karaoke.sep2"); - AddString(kar, "karaoke.export", 22038, "", BUTTON_CONTROL_STANDARD); - AddString(kar, "karaoke.importcsv", 22036, "", BUTTON_CONTROL_STANDARD); -#endif - - // System settings - AddGroup(SETTINGS_SYSTEM, 13000); - CSettingsCategory* vs = AddCategory(SETTINGS_SYSTEM, "videoscreen", 21373); - - // this setting would ideally not be saved, as its value is systematically derived from videoscreen.screenmode. - // contains a DISPLAYMODE -#if !defined(TARGET_DARWIN_IOS_ATV2) && !defined(TARGET_RASPBERRY_PI) - AddInt(vs, "videoscreen.screen", 240, 0, -1, 1, 32, SPIN_CONTROL_TEXT); -#endif - // this setting would ideally not be saved, as its value is systematically derived from videoscreen.screenmode. - // contains an index to the resolution info array in CDisplaySettings. the only meaningful fields are iScreen, iWidth, iHeight. -#if defined(TARGET_DARWIN) - #if !defined(TARGET_DARWIN_IOS_ATV2) - AddInt(vs, "videoscreen.resolution", 131, -1, 0, 1, INT_MAX, SPIN_CONTROL_TEXT); - #endif -#else - AddInt(vs, "videoscreen.resolution", 169, -1, 0, 1, INT_MAX, SPIN_CONTROL_TEXT); -#endif - AddString(g_application.IsStandAlone() ? vs : NULL, "videoscreen.screenmode", 243, "DESKTOP", SPIN_CONTROL_TEXT); - -#if defined(_WIN32) || defined(TARGET_DARWIN) - // We prefer a fake fullscreen mode (window covering the screen rather than dedicated fullscreen) - // as it works nicer with switching to other applications. However on some systems vsync is broken - // when we do this (eg non-Aero on ATI in particular) and on others (AppleTV) we can't get XBMC to - // the front - bool fakeFullScreen = true; - bool showSetting = true; - if (g_sysinfo.IsAeroDisabled()) - fakeFullScreen = false; - -#if defined(_WIN32) && defined(HAS_GL) - fakeFullScreen = true; - showSetting = false; -#endif - -#if defined(TARGET_DARWIN) - showSetting = false; -#endif - AddBool(showSetting ? vs : NULL, "videoscreen.fakefullscreen", 14083, fakeFullScreen); -#ifdef TARGET_DARWIN_IOS - AddBool(NULL, "videoscreen.blankdisplays", 13130, false); -#else - AddBool(vs, "videoscreen.blankdisplays", 13130, false); -#endif - - AddSeparator(vs, "videoscreen.sep1"); -#endif - - map<int,int> vsync; -#if defined(_LINUX) && !defined(TARGET_DARWIN) - vsync.insert(make_pair(13101,VSYNC_DRIVER)); -#endif - vsync.insert(make_pair(13106,VSYNC_DISABLED)); - vsync.insert(make_pair(13107,VSYNC_VIDEO)); - vsync.insert(make_pair(13108,VSYNC_ALWAYS)); - AddInt(vs, "videoscreen.vsync", 13105, DEFAULT_VSYNC, vsync, SPIN_CONTROL_TEXT); - - AddString(vs, "videoscreen.guicalibration",214,"", BUTTON_CONTROL_STANDARD); -#if defined(HAS_GL) - // Todo: Implement test pattern for DX - AddString(vs, "videoscreen.testpattern",226,"", BUTTON_CONTROL_STANDARD); -#endif - -#if defined(HAS_GL) || defined(HAS_DX) - AddBool(vs , "videoscreen.limitedrange", 36042, false); -#else - AddBool(NULL, "videoscreen.limitedrange", 36042, false); -#endif - - CSettingsCategory* ao = AddCategory(SETTINGS_SYSTEM, "audiooutput", 772); - - map<int,int> audiomode; - audiomode.insert(make_pair(338,AUDIO_ANALOG)); -#if !defined(TARGET_RASPBERRY_PI) - audiomode.insert(make_pair(339,AUDIO_IEC958)); -#endif - audiomode.insert(make_pair(420,AUDIO_HDMI )); -#if defined(TARGET_RASPBERRY_PI) - AddInt(ao, "audiooutput.mode", 337, AUDIO_HDMI, audiomode, SPIN_CONTROL_TEXT); -#else - AddInt(ao, "audiooutput.mode", 337, AUDIO_ANALOG, audiomode, SPIN_CONTROL_TEXT); -#endif - - map<int,int> channelLayout; - for(int layout = AE_CH_LAYOUT_2_0; layout < AE_CH_LAYOUT_MAX; ++layout) - channelLayout.insert(make_pair(34100+layout, layout)); - AddInt(ao, "audiooutput.channels", 34100, AE_CH_LAYOUT_2_0, channelLayout, SPIN_CONTROL_TEXT); - AddBool(ao, "audiooutput.normalizelevels", 346, true); - AddBool(ao, "audiooutput.stereoupmix", 252, false); - -#if defined(TARGET_DARWIN_IOS) - CSettingsCategory* aocat = g_sysinfo.IsAppleTV2() ? ao : NULL; -#else - CSettingsCategory* aocat = ao; -#endif - - AddBool(aocat, "audiooutput.ac3passthrough" , 364, true); - AddBool(aocat, "audiooutput.dtspassthrough" , 254, true); - - -#if !defined(TARGET_DARWIN) && !defined(TARGET_RASPBERRY_PI) - AddBool(aocat, "audiooutput.passthroughaac" , 299, false); -#endif -#if !defined(TARGET_DARWIN_IOS) && !defined(TARGET_RASPBERRY_PI) - AddBool(aocat, "audiooutput.multichannellpcm" , 348, true ); -#endif -#if !defined(TARGET_DARWIN) && !defined(TARGET_RASPBERRY_PI) - AddBool(aocat, "audiooutput.truehdpassthrough", 349, true ); - AddBool(aocat, "audiooutput.dtshdpassthrough" , 347, true ); -#endif - -#if !defined(TARGET_RASPBERRY_PI) -#if defined(TARGET_DARWIN) - #if defined(TARGET_DARWIN_IOS) - CStdString defaultDeviceName = "Default"; - #else - CStdString defaultDeviceName; - CCoreAudioHardware::GetOutputDeviceName(defaultDeviceName); - #endif - AddString(ao, "audiooutput.audiodevice", 545, defaultDeviceName.c_str(), SPIN_CONTROL_TEXT); - AddString(NULL, "audiooutput.passthroughdevice", 546, defaultDeviceName.c_str(), SPIN_CONTROL_TEXT); -#else - AddSeparator(ao, "audiooutput.sep1"); - AddString (ao, "audiooutput.audiodevice" , 545, CStdString(CAEFactory::GetDefaultDevice(false)), SPIN_CONTROL_TEXT); - AddString (ao, "audiooutput.passthroughdevice", 546, CStdString(CAEFactory::GetDefaultDevice(true )), SPIN_CONTROL_TEXT); - AddSeparator(ao, "audiooutput.sep2"); -#endif -#endif - -#if !defined(TARGET_RASPBERRY_PI) - map<int,int> guimode; - guimode.insert(make_pair(34121, AE_SOUND_IDLE )); - guimode.insert(make_pair(34122, AE_SOUND_ALWAYS)); - guimode.insert(make_pair(34123, AE_SOUND_OFF )); - AddInt(ao, "audiooutput.guisoundmode", 34120, AE_SOUND_IDLE, guimode, SPIN_CONTROL_TEXT); -#endif - - CSettingsCategory* in = AddCategory(SETTINGS_SYSTEM, "input", 14094); - AddString(in, "input.peripherals", 35000, "", BUTTON_CONTROL_STANDARD); -#if defined(TARGET_DARWIN) - map<int,int> remotemode; - remotemode.insert(make_pair(13610,APPLE_REMOTE_DISABLED)); - remotemode.insert(make_pair(13611,APPLE_REMOTE_STANDARD)); - remotemode.insert(make_pair(13612,APPLE_REMOTE_UNIVERSAL)); - remotemode.insert(make_pair(13613,APPLE_REMOTE_MULTIREMOTE)); - AddInt(in, "input.appleremotemode", 13600, APPLE_REMOTE_STANDARD, remotemode, SPIN_CONTROL_TEXT); -#if defined(TARGET_DARWIN_OSX) - AddBool(in, "input.appleremotealwayson", 13602, false); -#else - AddBool(NULL, "input.appleremotealwayson", 13602, false); -#endif - AddInt(NULL, "input.appleremotesequencetime", 13603, 500, 50, 50, 1000, SPIN_CONTROL_INT_PLUS, MASK_MS, TEXT_OFF); - AddSeparator(in, "input.sep1"); -#endif - AddBool(in, "input.remoteaskeyboard", 21449, false); -#if defined(TARGET_DARWIN_IOS) - AddBool(NULL, "input.enablemouse", 21369, true); -#else - AddBool(in, "input.enablemouse", 21369, true); -#endif -#if defined(HAS_SDL_JOYSTICK) - AddBool(in, "input.enablejoystick", 35100, true); -#endif - - CSettingsCategory* net = AddCategory(SETTINGS_SYSTEM, "network", 798); - if (g_application.IsStandAlone()) - { -#if !defined(TARGET_DARWIN) - AddString(NULL, "network.interface",775,"", SPIN_CONTROL_TEXT); - - map<int, int> networkAssignments; - networkAssignments.insert(make_pair(716, NETWORK_DHCP)); - networkAssignments.insert(make_pair(717, NETWORK_STATIC)); - networkAssignments.insert(make_pair(787, NETWORK_DISABLED)); - AddInt(NULL, "network.assignment", 715, NETWORK_DHCP, networkAssignments, SPIN_CONTROL_TEXT); - AddString(NULL, "network.ipaddress", 719, "0.0.0.0", EDIT_CONTROL_IP_INPUT); - AddString(NULL, "network.subnet", 720, "255.255.255.0", EDIT_CONTROL_IP_INPUT); - AddString(NULL, "network.gateway", 721, "0.0.0.0", EDIT_CONTROL_IP_INPUT); - AddString(NULL, "network.dns", 722, "0.0.0.0", EDIT_CONTROL_IP_INPUT); - AddString(NULL, "network.dnssuffix", 22002, "", EDIT_CONTROL_INPUT, true); - AddString(NULL, "network.essid", 776, "0.0.0.0", BUTTON_CONTROL_STANDARD); - - map<int, int> networkEncapsulations; - networkEncapsulations.insert(make_pair(780, ENC_NONE)); - networkEncapsulations.insert(make_pair(781, ENC_WEP)); - networkEncapsulations.insert(make_pair(782, ENC_WPA)); - networkEncapsulations.insert(make_pair(783, ENC_WPA2)); - AddInt(NULL, "network.enc", 778, ENC_NONE, networkEncapsulations, SPIN_CONTROL_TEXT); - AddString(NULL, "network.key", 777, "0.0.0.0", EDIT_CONTROL_INPUT); -#ifndef _WIN32 - AddString(NULL, "network.save", 779, "", BUTTON_CONTROL_STANDARD); -#endif - AddSeparator(NULL, "network.sep1"); -#endif - } - AddBool(net, "network.usehttpproxy", 708, false); - map<int,int> proxyTypes; - proxyTypes.insert(make_pair(1181, XFILE::CCurlFile::PROXY_HTTP)); - proxyTypes.insert(make_pair(1182, XFILE::CCurlFile::PROXY_SOCKS4)); - proxyTypes.insert(make_pair(1183, XFILE::CCurlFile::PROXY_SOCKS4A)); - proxyTypes.insert(make_pair(1184, XFILE::CCurlFile::PROXY_SOCKS5)); - proxyTypes.insert(make_pair(1185, XFILE::CCurlFile::PROXY_SOCKS5_REMOTE)); - AddInt(net, "network.httpproxytype", 1180, XFILE::CCurlFile::PROXY_HTTP, proxyTypes, SPIN_CONTROL_TEXT); - AddString(net, "network.httpproxyserver", 706, "", EDIT_CONTROL_INPUT); - AddString(net, "network.httpproxyport", 730, "8080", EDIT_CONTROL_NUMBER_INPUT, false, 707); - AddString(net, "network.httpproxyusername", 1048, "", EDIT_CONTROL_INPUT); - AddString(net, "network.httpproxypassword", 733, "", EDIT_CONTROL_HIDDEN_INPUT,true,733); - AddInt(net, "network.bandwidth", 14041, 0, 0, 512, 100*1024, SPIN_CONTROL_INT_PLUS, MASK_KBPS, TEXT_OFF); - - CSettingsCategory* pwm = AddCategory(SETTINGS_SYSTEM, "powermanagement", 14095); - // Note: Application.cpp might hide powersaving settings if not supported. - AddInt(pwm, "powermanagement.displaysoff", 1450, 0, 0, 5, 120, SPIN_CONTROL_INT_PLUS, MASK_MINS, TEXT_OFF); - AddInt(pwm, "powermanagement.shutdowntime", 357, 0, 0, 5, 120, SPIN_CONTROL_INT_PLUS, MASK_MINS, TEXT_OFF); - - map<int,int> shutdown; - if (g_powerManager.CanPowerdown()) - shutdown.insert(make_pair(13005,POWERSTATE_SHUTDOWN)); - - if (g_powerManager.CanHibernate()) - shutdown.insert(make_pair(13010,POWERSTATE_HIBERNATE)); - - if (g_powerManager.CanSuspend()) - shutdown.insert(make_pair(13011,POWERSTATE_SUSPEND)); - - // In standalone mode we default to another. - if (g_application.IsStandAlone()) - AddInt(pwm, "powermanagement.shutdownstate", 13008, POWERSTATE_SHUTDOWN, shutdown, SPIN_CONTROL_TEXT); - else - { - shutdown.insert(make_pair(13009,POWERSTATE_QUIT)); -#if !defined(TARGET_DARWIN_IOS) - shutdown.insert(make_pair(13014,POWERSTATE_MINIMIZE)); -#endif - AddInt(pwm, "powermanagement.shutdownstate", 13008, POWERSTATE_QUIT, shutdown, SPIN_CONTROL_TEXT); - } - - CSettingsCategory* dbg = AddCategory(SETTINGS_SYSTEM, "debug", 14092); - AddBool(dbg, "debug.showloginfo", 20191, false); - AddPath(dbg, "debug.screenshotpath",20004,"select writable folder",BUTTON_CONTROL_PATH_INPUT,false,657); - - CSettingsCategory* mst = AddCategory(SETTINGS_SYSTEM, "masterlock", 12360); - AddString(mst, "masterlock.lockcode" , 20100, "-", BUTTON_CONTROL_STANDARD); - AddBool(mst, "masterlock.startuplock" , 20076,false); - // hidden masterlock settings - AddInt(NULL,"masterlock.maxretries", 12364, 3, 3, 1, 100, SPIN_CONTROL_TEXT); - - AddCategory(SETTINGS_SYSTEM, "cache", 439); - AddInt(NULL, "cache.harddisk", 14025, 256, 0, 256, 4096, SPIN_CONTROL_INT_PLUS, MASK_KB, TEXT_OFF); - AddSeparator(NULL, "cache.sep1"); - AddInt(NULL, "cachevideo.dvdrom", 14026, 2048, 0, 256, 16384, SPIN_CONTROL_INT_PLUS, MASK_KB, TEXT_OFF); - AddInt(NULL, "cachevideo.lan", 14027, 2048, 0, 256, 16384, SPIN_CONTROL_INT_PLUS, MASK_KB, TEXT_OFF); - AddInt(NULL, "cachevideo.internet", 14028, 4096, 0, 256, 16384, SPIN_CONTROL_INT_PLUS, MASK_KB, TEXT_OFF); - AddSeparator(NULL, "cache.sep2"); - AddInt(NULL, "cacheaudio.dvdrom", 14030, 256, 0, 256, 4096, SPIN_CONTROL_INT_PLUS, MASK_KB, TEXT_OFF); - AddInt(NULL, "cacheaudio.lan", 14031, 256, 0, 256, 4096, SPIN_CONTROL_INT_PLUS, MASK_KB, TEXT_OFF); - AddInt(NULL, "cacheaudio.internet", 14032, 256, 0, 256, 4096, SPIN_CONTROL_INT_PLUS, MASK_KB, TEXT_OFF); - AddSeparator(NULL, "cache.sep3"); - AddInt(NULL, "cachedvd.dvdrom", 14034, 2048, 0, 256, 16384, SPIN_CONTROL_INT_PLUS, MASK_KB, TEXT_OFF); - AddInt(NULL, "cachedvd.lan", 14035, 2048, 0, 256, 16384, SPIN_CONTROL_INT_PLUS, MASK_KB, TEXT_OFF); - AddSeparator(NULL, "cache.sep4"); - AddInt(NULL, "cacheunknown.internet", 14060, 4096, 0, 256, 16384, SPIN_CONTROL_INT_PLUS, MASK_KB, TEXT_OFF); - - // video settings - AddGroup(SETTINGS_VIDEOS, 3); - CSettingsCategory* vdl = AddCategory(SETTINGS_VIDEOS, "videolibrary", 14022); - AddBool(NULL, "videolibrary.enabled", 418, true); - AddBool(vdl, "videolibrary.showunwatchedplots", 20369, true); - AddBool(NULL, "videolibrary.seasonthumbs", 20382, true); - AddBool(vdl, "videolibrary.actorthumbs", 20402, true); - - map<int, int> flattenTVShowOptions; - flattenTVShowOptions.insert(make_pair(20420, 0)); - flattenTVShowOptions.insert(make_pair(20421, 1)); - flattenTVShowOptions.insert(make_pair(20422, 2)); - AddInt(vdl, "videolibrary.flattentvshows", 20412, 1, flattenTVShowOptions, SPIN_CONTROL_TEXT); - - AddBool(vdl, "videolibrary.groupmoviesets", 20458, false); - AddBool(vdl, "videolibrary.updateonstartup", 22000, false); - AddBool(vdl, "videolibrary.backgroundupdate", 22001, false); - AddSeparator(vdl, "videolibrary.sep3"); - AddString(vdl, "videolibrary.cleanup", 334, "", BUTTON_CONTROL_STANDARD); - AddString(vdl, "videolibrary.export", 647, "", BUTTON_CONTROL_STANDARD); - AddString(vdl, "videolibrary.import", 648, "", BUTTON_CONTROL_STANDARD); - - CSettingsCategory* vp = AddCategory(SETTINGS_VIDEOS, "videoplayer", 14086); - - AddBool(vp, "videoplayer.autoplaynextitem", 13433, false); - AddSeparator(vp, "videoplayer.sep1"); - - map<int, int> renderers; - renderers.insert(make_pair(13416, RENDER_METHOD_AUTO)); - -#ifdef HAS_DX - if (g_sysinfo.IsVistaOrHigher()) - renderers.insert(make_pair(16319, RENDER_METHOD_DXVA)); - renderers.insert(make_pair(13431, RENDER_METHOD_D3D_PS)); - renderers.insert(make_pair(13419, RENDER_METHOD_SOFTWARE)); -#endif - -#ifdef HAS_GL - renderers.insert(make_pair(13417, RENDER_METHOD_ARB)); - renderers.insert(make_pair(13418, RENDER_METHOD_GLSL)); - renderers.insert(make_pair(13419, RENDER_METHOD_SOFTWARE)); -#endif - AddInt(vp, "videoplayer.rendermethod", 13415, RENDER_METHOD_AUTO, renderers, SPIN_CONTROL_TEXT); - - AddInt(vp, "videoplayer.hqscalers", 13435, 0, 0, 10, 100, SPIN_CONTROL_INT); - -#ifdef HAVE_LIBVDPAU - AddBool(vp, "videoplayer.usevdpau", 13425, true); -#endif -#ifdef HAVE_LIBVA - AddBool(vp, "videoplayer.usevaapi", 13426, true); -#endif -#ifdef HAS_DX - AddBool(g_sysinfo.IsVistaOrHigher() ? vp: NULL, "videoplayer.usedxva2", 13427, g_sysinfo.IsVistaOrHigher() ? true : false); -#endif -#ifdef HAVE_LIBCRYSTALHD - AddBool(CCrystalHD::GetInstance()->DevicePresent() ? vp: NULL, "videoplayer.usechd", 13428, true); -#endif -#ifdef HAVE_LIBVDADECODER - AddBool(g_sysinfo.HasVDADecoder() ? vp: NULL, "videoplayer.usevda", 13429, true); -#endif -#ifdef HAVE_LIBOPENMAX - AddBool(vp, "videoplayer.useomx", 13430, true); -#endif -#ifdef HAVE_VIDEOTOOLBOXDECODER - AddBool(g_sysinfo.HasVideoToolBoxDecoder() ? vp: NULL, "videoplayer.usevideotoolbox", 13432, true); -#endif - -#ifdef HAS_GL - AddBool(NULL, "videoplayer.usepbo", 13424, true); -#endif - - // FIXME: hide this setting until it is properly respected. In the meanwhile, default to AUTO. - //AddInt(5, "videoplayer.displayresolution", 169, (int)RES_AUTORES, (int)RES_AUTORES, 1, (int)CUSTOM+MAX_RESOLUTIONS, SPIN_CONTROL_TEXT); - AddInt(NULL, "videoplayer.displayresolution", 169, (int)RES_AUTORES, (int)RES_AUTORES, 1, (int)RES_AUTORES, SPIN_CONTROL_TEXT); - - map<int, int> adjustTypes; - adjustTypes.insert(make_pair(351, ADJUST_REFRESHRATE_OFF)); - adjustTypes.insert(make_pair(36035, ADJUST_REFRESHRATE_ALWAYS)); - adjustTypes.insert(make_pair(36036, ADJUST_REFRESHRATE_ON_STARTSTOP)); - -#if !defined(TARGET_DARWIN_IOS) - AddInt(vp, "videoplayer.adjustrefreshrate", 170, ADJUST_REFRESHRATE_OFF, adjustTypes, SPIN_CONTROL_TEXT); -// AddBool(vp, "videoplayer.adjustrefreshrate", 170, false); - AddInt(vp, "videoplayer.pauseafterrefreshchange", 13550, 0, 0, 1, MAXREFRESHCHANGEDELAY, SPIN_CONTROL_TEXT); -#else - AddInt(NULL, "videoplayer.adjustrefreshrate", 170, ADJUST_REFRESHRATE_OFF, adjustTypes, SPIN_CONTROL_TEXT); - //AddBool(NULL, "videoplayer.adjustrefreshrate", 170, false); - AddInt(NULL, "videoplayer.pauseafterrefreshchange", 13550, 0, 0, 1, MAXREFRESHCHANGEDELAY, SPIN_CONTROL_TEXT); -#endif - //sync settings not available on windows gl build -#if defined(_WIN32) && defined(HAS_GL) - #define SYNCSETTINGS 0 -#else - #define SYNCSETTINGS 1 -#endif - AddBool(SYNCSETTINGS ? vp : NULL, "videoplayer.usedisplayasclock", 13510, false); - - map<int, int> syncTypes; - syncTypes.insert(make_pair(13501, SYNC_DISCON)); - syncTypes.insert(make_pair(13502, SYNC_SKIPDUP)); - syncTypes.insert(make_pair(13503, SYNC_RESAMPLE)); - AddInt(SYNCSETTINGS ? vp : NULL, "videoplayer.synctype", 13500, SYNC_RESAMPLE, syncTypes, SPIN_CONTROL_TEXT); - AddFloat(NULL, "videoplayer.maxspeedadjust", 13504, 5.0f, 0.0f, 0.1f, 10.0f); - - map<int, int> resampleQualities; - resampleQualities.insert(make_pair(13506, RESAMPLE_LOW)); - resampleQualities.insert(make_pair(13507, RESAMPLE_MID)); - resampleQualities.insert(make_pair(13508, RESAMPLE_HIGH)); - resampleQualities.insert(make_pair(13509, RESAMPLE_REALLYHIGH)); - AddInt(NULL, "videoplayer.resamplequality", 13505, RESAMPLE_MID, resampleQualities, SPIN_CONTROL_TEXT); - AddInt(vp, "videoplayer.errorinaspect", 22021, 0, 0, 1, 20, SPIN_CONTROL_INT_PLUS, MASK_PERCENT, TEXT_NONE); - - map<int,int> stretch; - stretch.insert(make_pair(630,ViewModeNormal)); - stretch.insert(make_pair(633,ViewModeWideZoom)); - stretch.insert(make_pair(634,ViewModeStretch16x9)); - stretch.insert(make_pair(631,ViewModeZoom)); - AddInt(vp, "videoplayer.stretch43", 173, ViewModeNormal, stretch, SPIN_CONTROL_TEXT); -#ifdef HAVE_LIBVDPAU - AddBool(NULL, "videoplayer.vdpau_allow_xrandr", 13122, false); -#endif -#if defined(HAS_GL) || HAS_GLES == 2 // May need changing for GLES - AddSeparator(vp, "videoplayer.sep1.5"); -#ifdef HAVE_LIBVDPAU - AddBool(NULL, "videoplayer.vdpauUpscalingLevel", 13121, false); - AddBool(NULL, "videoplayer.vdpaustudiolevel", 0, false); //depreciated -#endif -#endif - AddSeparator(vp, "videoplayer.sep5"); - AddBool(vp, "videoplayer.teletextenabled", 23050, true); - AddBool(vp, "Videoplayer.teletextscale", 23055, true); - - CSettingsCategory* vid = AddCategory(SETTINGS_VIDEOS, "myvideos", 14081); - - map<int, int> myVideosSelectActions; - myVideosSelectActions.insert(make_pair(22080, SELECT_ACTION_CHOOSE)); - myVideosSelectActions.insert(make_pair(208, SELECT_ACTION_PLAY_OR_RESUME)); - myVideosSelectActions.insert(make_pair(13404, SELECT_ACTION_RESUME)); - myVideosSelectActions.insert(make_pair(22081, SELECT_ACTION_INFO)); - - AddInt(vid, "myvideos.selectaction", 22079, SELECT_ACTION_PLAY_OR_RESUME, myVideosSelectActions, SPIN_CONTROL_TEXT); - AddBool(vid, "myvideos.extractflags",20433, true); - AddBool(vid, "myvideos.replacelabels", 20419, true); - AddBool(NULL, "myvideos.extractthumb",20433, true); - - AddSeparator(NULL, "myvideos.sep1"); - AddInt(NULL, "myvideos.startwindow", 0, WINDOW_VIDEO_FILES, WINDOW_VIDEO_FILES, 1, WINDOW_VIDEO_NAV, SPIN_CONTROL_INT); - AddBool(NULL, "myvideos.stackvideos", 0, false); - AddBool(NULL, "myvideos.flatten", 0, false); - - CSettingsCategory* sub = AddCategory(SETTINGS_VIDEOS, "subtitles", 287); - AddString(sub, "subtitles.font", 14089, "arial.ttf", SPIN_CONTROL_TEXT); - AddInt(sub, "subtitles.height", 289, 28, 16, 2, 74, SPIN_CONTROL_TEXT); // use text as there is a disk based lookup needed - - map<int, int> fontStyles; - fontStyles.insert(make_pair(738, FONT_STYLE_NORMAL)); - fontStyles.insert(make_pair(739, FONT_STYLE_BOLD)); - fontStyles.insert(make_pair(740, FONT_STYLE_ITALICS)); - fontStyles.insert(make_pair(741, FONT_STYLE_BOLD | FONT_STYLE_ITALICS)); - - AddInt(sub, "subtitles.style", 736, FONT_STYLE_BOLD, fontStyles, SPIN_CONTROL_TEXT); - AddInt(sub, "subtitles.color", 737, SUBTITLE_COLOR_START + 1, SUBTITLE_COLOR_START, 1, SUBTITLE_COLOR_END, SPIN_CONTROL_TEXT); - AddString(sub, "subtitles.charset", 735, "DEFAULT", SPIN_CONTROL_TEXT); - AddBool(sub,"subtitles.overrideassfonts", 21368, false); - AddSeparator(sub, "subtitles.sep1"); - AddPath(sub, "subtitles.custompath", 21366, "", BUTTON_CONTROL_PATH_INPUT, false, 657); - - map<int, int> subtitleAlignments; - subtitleAlignments.insert(make_pair(21461, SUBTITLE_ALIGN_MANUAL)); - subtitleAlignments.insert(make_pair(21462, SUBTITLE_ALIGN_BOTTOM_INSIDE)); - subtitleAlignments.insert(make_pair(21463, SUBTITLE_ALIGN_BOTTOM_OUTSIDE)); - subtitleAlignments.insert(make_pair(21464, SUBTITLE_ALIGN_TOP_INSIDE)); - subtitleAlignments.insert(make_pair(21465, SUBTITLE_ALIGN_TOP_OUTSIDE)); - AddInt(sub, "subtitles.align", 21460, SUBTITLE_ALIGN_MANUAL, subtitleAlignments, SPIN_CONTROL_TEXT); - - CSettingsCategory* dvd = AddCategory(SETTINGS_VIDEOS, "dvds", 14087); - AddBool(dvd, "dvds.autorun", 14088, false); - AddInt(dvd, "dvds.playerregion", 21372, 0, 0, 1, 8, SPIN_CONTROL_INT_PLUS, -1, TEXT_OFF); - AddBool(dvd, "dvds.automenu", 21882, false); - - AddDefaultAddon(NULL, "scrapers.moviesdefault", 21413, "metadata.themoviedb.org", ADDON_SCRAPER_MOVIES); - AddDefaultAddon(NULL, "scrapers.tvshowsdefault", 21414, "metadata.tvdb.com", ADDON_SCRAPER_TVSHOWS); - AddDefaultAddon(NULL, "scrapers.musicvideosdefault", 21415, "metadata.musicvideos.theaudiodb.com", ADDON_SCRAPER_MUSICVIDEOS); - - // service settings - AddGroup(SETTINGS_SERVICE, 14036); - - CSettingsCategory* srvGeneral = AddCategory(SETTINGS_SERVICE, "general", 16000); - AddString(srvGeneral,"services.devicename", 1271, "XBMC", EDIT_CONTROL_INPUT); - - CSettingsCategory* srvUpnp = AddCategory(SETTINGS_SERVICE, "upnp", 20187); - AddBool(srvUpnp, "services.upnpserver", 21360, false); - AddBool(srvUpnp, "services.upnpannounce", 20188, true); - AddBool(srvUpnp, "services.upnprenderer", 21881, false); - AddBool(srvUpnp, "services.upnpcontroller", 21361, false); - -#ifdef HAS_WEB_SERVER - CSettingsCategory* srvWeb = AddCategory(SETTINGS_SERVICE, "webserver", 33101); - AddBool(srvWeb, "services.webserver", 263, false); - AddString(srvWeb,"services.webserverport", 730, CUtil::CanBindPrivileged()?"80":"8080", EDIT_CONTROL_NUMBER_INPUT, false, 730); - AddString(srvWeb,"services.webserverusername",1048, "xbmc", EDIT_CONTROL_INPUT); - AddString(srvWeb,"services.webserverpassword",733, "", EDIT_CONTROL_HIDDEN_INPUT, true, 733); - AddDefaultAddon(srvWeb, "services.webskin",199, DEFAULT_WEB_INTERFACE, ADDON_WEB_INTERFACE); -#endif -#ifdef HAS_EVENT_SERVER - CSettingsCategory* srvEvent = AddCategory(SETTINGS_SERVICE, "remotecontrol", 790); - AddBool(srvEvent, "services.esenabled", 791, true); - AddString(NULL,"services.esport", 792, "9777", EDIT_CONTROL_NUMBER_INPUT, false, 792); - AddInt(NULL, "services.esportrange", 793, 10, 1, 1, 100, SPIN_CONTROL_INT); - AddInt(NULL, "services.esmaxclients", 797, 20, 1, 1, 100, SPIN_CONTROL_INT); - AddBool(srvEvent, "services.esallinterfaces", 794, false); - AddInt(NULL, "services.esinitialdelay", 795, 750, 5, 5, 10000, SPIN_CONTROL_INT); - AddInt(NULL, "services.escontinuousdelay", 796, 25, 5, 5, 10000, SPIN_CONTROL_INT); -#endif -#ifdef HAS_ZEROCONF - CSettingsCategory* srvZeroconf = AddCategory(SETTINGS_SERVICE, "zeroconf", 1259); -#ifdef TARGET_WINDOWS - AddBool(srvZeroconf, "services.zeroconf", 1260, false); -#else - AddBool(srvZeroconf, "services.zeroconf", 1260, true); -#endif -#endif - -#ifdef HAS_AIRPLAY - CSettingsCategory* srvAirplay = AddCategory(SETTINGS_SERVICE, "airplay", 1273); - AddBool(srvAirplay, "services.airplay", 1270, false); - AddBool(srvAirplay, "services.useairplaypassword", 1272, false); - AddString(srvAirplay, "services.airplaypassword", 733, "", EDIT_CONTROL_HIDDEN_INPUT, false, 733); -#endif - -#ifndef _WIN32 - CSettingsCategory* srvSmb = AddCategory(SETTINGS_SERVICE, "smb", 1200); - AddString(srvSmb, "smb.winsserver", 1207, "", EDIT_CONTROL_IP_INPUT); - AddString(srvSmb, "smb.workgroup", 1202, "WORKGROUP", EDIT_CONTROL_INPUT, false, 1202); -#endif - - // appearance settings - AddGroup(SETTINGS_APPEARANCE, 480); - CSettingsCategory* laf = AddCategory(SETTINGS_APPEARANCE,"lookandfeel", 166); - AddDefaultAddon(laf, "lookandfeel.skin",166,DEFAULT_SKIN, ADDON_SKIN); - AddString(laf, "lookandfeel.skinsettings", 21417, "", BUTTON_CONTROL_STANDARD); - AddString(laf, "lookandfeel.skintheme",15111,"SKINDEFAULT", SPIN_CONTROL_TEXT); - AddString(laf, "lookandfeel.skincolors",14078, "SKINDEFAULT", SPIN_CONTROL_TEXT); - AddString(laf, "lookandfeel.font",13303,"Default", SPIN_CONTROL_TEXT); - AddInt(laf, "lookandfeel.skinzoom",20109, 0, -20, 2, 20, SPIN_CONTROL_INT, MASK_PERCENT); - AddInt(laf, "lookandfeel.startupwindow",512,1, WINDOW_HOME, 1, WINDOW_PYTHON_END, SPIN_CONTROL_TEXT); - AddString(laf, "lookandfeel.soundskin",15108,"SKINDEFAULT", SPIN_CONTROL_TEXT); - AddSeparator(laf, "lookandfeel.sep2"); - AddBool(laf, "lookandfeel.enablerssfeeds",13305, true); - AddString(laf, "lookandfeel.rssedit", 21450, "", BUTTON_CONTROL_STANDARD); - - CSettingsCategory* loc = AddCategory(SETTINGS_APPEARANCE, "locale", 14090); - AddString(loc, "locale.language",248,"English", SPIN_CONTROL_TEXT); - AddString(loc, "locale.country", 20026, "USA (12h)", SPIN_CONTROL_TEXT); - AddString(loc, "locale.charset", 14091, "DEFAULT", SPIN_CONTROL_TEXT); // charset is set by the language file - - bool use_timezone = false; - -#if defined(_LINUX) -#if defined(TARGET_DARWIN) - if (g_sysinfo.IsAppleTV2() && GetIOSVersion() < 4.3) -#endif -#if !defined(TARGET_ANDROID) - use_timezone = true; -#endif - - if (use_timezone) - { - AddSeparator(loc, "locale.sep1"); - AddString(loc, "locale.timezonecountry", 14079, g_timezone.GetCountryByTimezone(g_timezone.GetOSConfiguredTimezone()), SPIN_CONTROL_TEXT); - AddString(loc, "locale.timezone", 14080, g_timezone.GetOSConfiguredTimezone(), SPIN_CONTROL_TEXT); - } -#endif - AddSeparator(loc, "locale.sep3"); - AddString(loc, "locale.audiolanguage", 285, "original", SPIN_CONTROL_TEXT); - AddString(loc, "locale.subtitlelanguage", 286, "original", SPIN_CONTROL_TEXT); - - CSettingsCategory* fl = AddCategory(SETTINGS_APPEARANCE, "filelists", 14081); - AddBool(fl, "filelists.showparentdiritems", 13306, true); - AddBool(fl, "filelists.showextensions", 497, true); - AddBool(fl, "filelists.ignorethewhensorting", 13399, true); - AddBool(fl, "filelists.allowfiledeletion", 14071, false); - AddBool(fl, "filelists.showaddsourcebuttons", 21382, true); - AddBool(fl, "filelists.showhidden", 21330, false); - - CSettingsCategory* ss = AddCategory(SETTINGS_APPEARANCE, "screensaver", 360); - AddDefaultAddon(ss, "screensaver.mode", 356, "screensaver.xbmc.builtin.dim", ADDON_SCREENSAVER); - AddString(ss, "screensaver.settings", 21417, "", BUTTON_CONTROL_STANDARD); - AddString(ss, "screensaver.preview", 1000, "", BUTTON_CONTROL_STANDARD); - AddInt(ss, "screensaver.time", 355, 3, 1, 1, 60, SPIN_CONTROL_INT_PLUS, MASK_MINS); - AddSeparator(ss, "screensaver.sep1"); - AddBool(ss, "screensaver.usemusicvisinstead", 13392, true); - AddBool(ss, "screensaver.usedimonpause", 22014, true); - - AddCategory(SETTINGS_APPEARANCE, "window", 0); - AddInt(NULL, "window.width", 0, 720, 10, 1, INT_MAX, SPIN_CONTROL_INT); - AddInt(NULL, "window.height", 0, 480, 10, 1, INT_MAX, SPIN_CONTROL_INT); - - AddPath(NULL,"system.playlistspath",20006,"set default",BUTTON_CONTROL_PATH_INPUT,false); - - AddInt(NULL, "mymusic.startwindow", 0, WINDOW_MUSIC_FILES, WINDOW_MUSIC_FILES, 1, WINDOW_MUSIC_NAV, SPIN_CONTROL_INT); - AddBool(NULL, "mymusic.songthumbinvis", 0, false); - AddString(NULL, "mymusic.defaultlibview", 0, "", BUTTON_CONTROL_STANDARD); - - AddBool(NULL, "general.addonautoupdate", 0, true); - AddBool(NULL, "general.addonnotifications", 0, true); - AddBool(NULL, "general.addonforeignfilter", 0, false); - - // tv settings (access over TV menu from home window) - AddGroup(SETTINGS_PVR, 19180); - CSettingsCategory* pvr = AddCategory(SETTINGS_PVR, "pvrmanager", 128); - AddBool(pvr, "pvrmanager.enabled", 449, false); - AddSeparator(pvr, "pvrmanager.sep1"); - AddBool(pvr, "pvrmanager.syncchannelgroups", 19221, true); - AddBool(pvr, "pvrmanager.backendchannelorder", 19231, true); - AddBool(pvr, "pvrmanager.usebackendchannelnumbers", 19234, false); - AddSeparator(pvr, "pvrmanager.sep2"); - AddString(pvr, "pvrmanager.channelmanager", 19199, "", BUTTON_CONTROL_STANDARD); - AddString(pvr, "pvrmanager.channelscan", 19117, "", BUTTON_CONTROL_STANDARD); - AddString(pvr, "pvrmanager.resetdb", 19185, "", BUTTON_CONTROL_STANDARD); - AddSeparator(pvr, "pvrmanager.sep3"); - AddBool(pvr, "pvrmanager.hideconnectionlostwarning", 19269, false); - - CSettingsCategory* pvrm = AddCategory(SETTINGS_PVR, "pvrmenu", 19181); - AddBool(pvrm, "pvrmenu.infoswitch", 19178, true); - AddBool(pvrm, "pvrmenu.infotimeout", 19179, true); - AddBool(pvrm, "pvrmenu.closechannelosdonswitch", 19229, false); - AddInt(pvrm, "pvrmenu.infotime", 19184, 5, 1, 1, 10, SPIN_CONTROL_INT_PLUS, MASK_SECS); - AddSeparator(pvrm, "pvrmenu.sep1"); - AddString(pvrm, "pvrmenu.iconpath", 19018, "", BUTTON_CONTROL_PATH_INPUT, false, 657); - AddString(pvrm, "pvrmenu.searchicons", 19167, "", BUTTON_CONTROL_STANDARD); - - CSettingsCategory* pvre = AddCategory(SETTINGS_PVR, "epg", 19069); - AddInt(pvre, "epg.defaultguideview", 19065, GUIDE_VIEW_TIMELINE, GUIDE_VIEW_CHANNEL, 1, GUIDE_VIEW_TIMELINE, SPIN_CONTROL_TEXT); - AddInt(pvre, "epg.daystodisplay", 19182, 3, 1, 1, 14, SPIN_CONTROL_INT_PLUS, MASK_DAYS); - AddSeparator(pvre, "epg.sep1"); - AddInt(pvre, "epg.epgupdate", 19071, 120, 15, 15, 2880, SPIN_CONTROL_INT_PLUS, MASK_MINS); - AddBool(pvre, "epg.preventupdateswhileplayingtv", 19230, false); - AddBool(pvre, "epg.ignoredbforclient", 19072, false); - AddBool(pvre, "epg.hidenoinfoavailable", 19268, true); - AddString(pvre, "epg.resetepg", 19187, "", BUTTON_CONTROL_STANDARD); - - CSettingsCategory* pvrp = AddCategory(SETTINGS_PVR, "pvrplayback", 19177); - AddBool(pvrp, "pvrplayback.playminimized", 19171, true); - AddInt(pvrp, "pvrplayback.startlast", 19189, START_LAST_CHANNEL_OFF, START_LAST_CHANNEL_OFF, 1, START_LAST_CHANNEL_ON, SPIN_CONTROL_TEXT); - AddBool(pvrp, "pvrplayback.signalquality", 19037, true); - AddSeparator(pvrp, "pvrplayback.sep1"); - AddInt(pvrp, "pvrplayback.scantime", 19170, 10, 1, 1, 60, SPIN_CONTROL_INT_PLUS, MASK_SECS); - AddBool(pvrp, "pvrplayback.confirmchannelswitch", 19281, false); - AddInt(pvrp, "pvrplayback.channelentrytimeout", 19073, 0, 0, 250, 10000, SPIN_CONTROL_INT_PLUS, MASK_MS); - - CSettingsCategory* pvrr = AddCategory(SETTINGS_PVR, "pvrrecord", 19043); - AddInt(pvrr, "pvrrecord.instantrecordtime", 19172, 120, 1, 1, 720, SPIN_CONTROL_INT_PLUS, MASK_MINS); - AddInt(pvrr, "pvrrecord.defaultpriority", 19173, 50, 1, 1, 100, SPIN_CONTROL_INT_PLUS); - AddInt(pvrr, "pvrrecord.defaultlifetime", 19174, 99, 1, 1, 365, SPIN_CONTROL_INT_PLUS, MASK_DAYS); - AddInt(pvrr, "pvrrecord.marginstart", 19175, 2, 0, 1, 60, SPIN_CONTROL_INT_PLUS, MASK_MINS); - AddInt(pvrr, "pvrrecord.marginend", 19176, 10, 0, 1, 60, SPIN_CONTROL_INT_PLUS, MASK_MINS); - AddSeparator(pvrr, "pvrrecord.sep1"); - AddBool(pvrr, "pvrrecord.timernotifications", 19233, true); - - CSettingsCategory* pvrpwr = AddCategory(SETTINGS_PVR, "pvrpowermanagement", 14095); - AddBool(pvrpwr, "pvrpowermanagement.enabled", 305, false); - AddSeparator(pvrpwr, "pvrpowermanagement.sep1"); - AddInt(pvrpwr, "pvrpowermanagement.backendidletime", 19244, 15, 0, 5, 360, SPIN_CONTROL_INT_PLUS, MASK_MINS, TEXT_OFF); - AddString(pvrpwr, "pvrpowermanagement.setwakeupcmd", 19245, "", EDIT_CONTROL_INPUT, true); - AddInt(pvrpwr, "pvrpowermanagement.prewakeup", 19246, 15, 0, 1, 60, SPIN_CONTROL_INT_PLUS, MASK_MINS, TEXT_OFF); - AddSeparator(pvrpwr, "pvrpowermanagement.sep2"); - AddBool(pvrpwr, "pvrpowermanagement.dailywakeup", 19247, false); - AddString(pvrpwr, "pvrpowermanagement.dailywakeuptime", 19248, "00:00:00", EDIT_CONTROL_INPUT); - - CSettingsCategory* pvrpa = AddCategory(SETTINGS_PVR, "pvrparental", 19259); - AddBool(pvrpa, "pvrparental.enabled", 449 , false); - AddSeparator(pvrpa, "pvrparental.sep1"); - AddString(pvrpa, "pvrparental.pin", 19261, "", EDIT_CONTROL_HIDDEN_NUMBER_VERIFY_NEW, true); - AddInt(pvrpa, "pvrparental.duration", 19260, 300, 5, 5, 1200, SPIN_CONTROL_INT_PLUS, MASK_SECS); - - CSettingsCategory* pvrc = AddCategory(SETTINGS_PVR, "pvrclient", 19279); - AddString(pvrc, "pvrclient.menuhook", 19280, "", BUTTON_CONTROL_STANDARD); -} - -CGUISettings::~CGUISettings(void) -{ - Clear(); -} - -void CGUISettings::AddGroup(int groupID, int labelID) -{ - CSettingsGroup *pGroup = new CSettingsGroup(groupID, labelID); - if (pGroup) - settingsGroups.push_back(pGroup); -} - -CSettingsCategory* CGUISettings::AddCategory(int groupID, const char *strSetting, int labelID) -{ - for (unsigned int i = 0; i < settingsGroups.size(); i++) - { - if (settingsGroups[i]->GetGroupID() == groupID) - return settingsGroups[i]->AddCategory(CStdString(strSetting).ToLower(), labelID); - } - return NULL; -} - -CSettingsGroup *CGUISettings::GetGroup(int groupID) -{ - for (unsigned int i = 0; i < settingsGroups.size(); i++) - { - if (settingsGroups[i]->GetGroupID() == groupID) - return settingsGroups[i]; - } - CLog::Log(LOGDEBUG, "Error: Requested setting group (%i) was not found. " - "It must be case-sensitive", - groupID); - return NULL; -} - -void CGUISettings::AddSetting(CSettingsCategory* cat, CSetting* setting) -{ - if (!setting) - return; - - if (cat) - cat->m_settings.push_back(setting); - settingsMap.insert(pair<CStdString, CSetting*>(CStdString(setting->GetSetting()).ToLower(), setting)); -} - -void CGUISettings::AddSeparator(CSettingsCategory* cat, const char *strSetting) -{ - int iOrder = cat ? cat->m_settings.size() : 0; - CSettingSeparator *pSetting = new CSettingSeparator(iOrder, CStdString(strSetting).ToLower()); - if (!pSetting) return; - AddSetting(cat, pSetting); -} - -void CGUISettings::AddBool(CSettingsCategory* cat, const char *strSetting, int iLabel, bool bData, int iControlType) -{ - int iOrder = cat ? cat->m_settings.size() : 0; - CSettingBool* pSetting = new CSettingBool(iOrder, CStdString(strSetting).ToLower(), iLabel, bData, iControlType); - if (!pSetting) return ; - AddSetting(cat, pSetting); -} - -bool CGUISettings::GetBool(const char *strSetting) const -{ - ASSERT(settingsMap.size()); - constMapIter it = settingsMap.find(strSetting); - if (it != settingsMap.end()) - { // old category - return ((CSettingBool*)(*it).second)->GetData(); - } - // Backward compatibility (skins use this setting) - if (strncmp(strSetting, "lookandfeel.enablemouse", 23) == 0) - return GetBool("input.enablemouse"); - // Assert here and write debug output - CLog::Log(LOGDEBUG,"Error: Requested setting (%s) was not found. It must be case-sensitive", strSetting); - return false; -} - -void CGUISettings::SetBool(const char *strSetting, bool bSetting) -{ - ASSERT(settingsMap.size()); - mapIter it = settingsMap.find(strSetting); - if (it != settingsMap.end()) - { // old category - ((CSettingBool*)(*it).second)->SetData(bSetting); - - SetChanged(); - - return ; - } - // Assert here and write debug output - CLog::Log(LOGDEBUG,"Error: Requested setting (%s) was not found. It must be case-sensitive", strSetting); -} - -void CGUISettings::ToggleBool(const char *strSetting) -{ - ASSERT(settingsMap.size()); - mapIter it = settingsMap.find(CStdString(strSetting).ToLower()); - if (it != settingsMap.end()) - { // old category - ((CSettingBool*)(*it).second)->SetData(!((CSettingBool *)(*it).second)->GetData()); - - SetChanged(); - - return ; - } - // Assert here and write debug output - CLog::Log(LOGDEBUG,"Error: Requested setting (%s) was not found. It must be case-sensitive", strSetting); -} - -void CGUISettings::AddFloat(CSettingsCategory* cat, const char *strSetting, int iLabel, float fData, float fMin, float fStep, float fMax, int iControlType) -{ - int iOrder = cat ? cat->m_settings.size() : 0; - CSettingFloat* pSetting = new CSettingFloat(iOrder, CStdString(strSetting).ToLower(), iLabel, fData, fMin, fStep, fMax, iControlType); - if (!pSetting) return ; - AddSetting(cat, pSetting); -} - -float CGUISettings::GetFloat(const char *strSetting) const -{ - ASSERT(settingsMap.size()); - constMapIter it = settingsMap.find(strSetting); - if (it != settingsMap.end()) - { - return ((CSettingFloat *)(*it).second)->GetData(); - } - // Assert here and write debug output - //ASSERT(false); - CLog::Log(LOGDEBUG,"Error: Requested setting (%s) was not found. It must be case-sensitive", strSetting); - return 0.0f; -} - -void CGUISettings::SetFloat(const char *strSetting, float fSetting) -{ - ASSERT(settingsMap.size()); - mapIter it = settingsMap.find(strSetting); - if (it != settingsMap.end()) - { - ((CSettingFloat *)(*it).second)->SetData(fSetting); - - SetChanged(); - - return ; - } - // Assert here and write debug output - ASSERT(false); - CLog::Log(LOGDEBUG,"Error: Requested setting (%s) was not found. It must be case-sensitive", strSetting); -} - -void CGUISettings::LoadMasterLock(TiXmlElement *pRootElement) -{ - mapIter it = settingsMap.find("masterlock.maxretries"); - if (it != settingsMap.end()) - LoadFromXML(pRootElement, it); - it = settingsMap.find("masterlock.startuplock"); - if (it != settingsMap.end()) - LoadFromXML(pRootElement, it); -} - -void CGUISettings::AddInt(CSettingsCategory* cat, const char *strSetting, int iLabel, int iData, int iMin, int iStep, int iMax, int iControlType, const char *strFormat) -{ - int iOrder = cat ? cat->m_settings.size() : 0; - CSettingInt* pSetting = new CSettingInt(iOrder, CStdString(strSetting).ToLower(), iLabel, iData, iMin, iStep, iMax, iControlType, strFormat); - if (!pSetting) return ; - AddSetting(cat, pSetting); -} - -void CGUISettings::AddInt(CSettingsCategory* cat, const char *strSetting, int iLabel, int iData, int iMin, int iStep, int iMax, int iControlType, int iFormat, int iLabelMin/*=-1*/) -{ - int iOrder = cat ? cat->m_settings.size() : 0; - CSettingInt* pSetting = new CSettingInt(iOrder, CStdString(strSetting).ToLower(), iLabel, iData, iMin, iStep, iMax, iControlType, iFormat, iLabelMin); - if (!pSetting) return ; - AddSetting(cat, pSetting); -} - -void CGUISettings::AddInt(CSettingsCategory* cat, const char *strSetting, int iLabel, int iData, const map<int,int>& entries, int iControlType) -{ - int iOrder = cat ? cat->m_settings.size() : 0; - CSettingInt* pSetting = new CSettingInt(iOrder, CStdString(strSetting).ToLower(), iLabel, iData, entries, iControlType); - if (!pSetting) return ; - AddSetting(cat, pSetting); -} - -void CGUISettings::AddHex(CSettingsCategory* cat, const char *strSetting, int iLabel, int iData, int iMin, int iStep, int iMax, int iControlType, const char *strFormat) -{ - int iOrder = cat ? cat->m_settings.size() : 0; - CSettingHex* pSetting = new CSettingHex(iOrder, CStdString(strSetting).ToLower(), iLabel, iData, iMin, iStep, iMax, iControlType, strFormat); - if (!pSetting) return ; - AddSetting(cat, pSetting); -} - -int CGUISettings::GetInt(const char *strSetting) const -{ - ASSERT(settingsMap.size()); - - constMapIter it = settingsMap.find(strSetting); - if (it != settingsMap.end()) - { - return ((CSettingInt *)(*it).second)->GetData(); - } - // Assert here and write debug output - CLog::Log(LOGERROR,"Error: Requested setting (%s) was not found. It must be case-sensitive", strSetting); - //ASSERT(false); - return 0; -} - -void CGUISettings::SetInt(const char *strSetting, int iSetting) -{ - ASSERT(settingsMap.size()); - mapIter it = settingsMap.find(strSetting); - if (it != settingsMap.end()) - { - ((CSettingInt *)(*it).second)->SetData(iSetting); - - SetChanged(); - - return ; - } - // Assert here and write debug output - ASSERT(false); -} - -void CGUISettings::AddString(CSettingsCategory* cat, const char *strSetting, int iLabel, const char *strData, int iControlType, bool bAllowEmpty, int iHeadingString) -{ - int iOrder = cat ? cat->m_settings.size() : 0; - CSettingString* pSetting = new CSettingString(iOrder, CStdString(strSetting).ToLower(), iLabel, strData, iControlType, bAllowEmpty, iHeadingString); - if (!pSetting) return ; - AddSetting(cat, pSetting); -} - -void CGUISettings::AddPath(CSettingsCategory* cat, const char *strSetting, int iLabel, const char *strData, int iControlType, bool bAllowEmpty, int iHeadingString) -{ - int iOrder = cat ? cat->m_settings.size() : 0; - CSettingPath* pSetting = new CSettingPath(iOrder, CStdString(strSetting).ToLower(), iLabel, strData, iControlType, bAllowEmpty, iHeadingString); - if (!pSetting) return ; - AddSetting(cat, pSetting); -} - -void CGUISettings::AddDefaultAddon(CSettingsCategory* cat, const char *strSetting, int iLabel, const char *strData, const TYPE type) -{ - int iOrder = cat ? cat->m_settings.size() : 0; - CSettingAddon* pSetting = new CSettingAddon(iOrder, CStdString(strSetting).ToLower(), iLabel, strData, type); - if (!pSetting) return ; - AddSetting(cat, pSetting); -} - -const CStdString &CGUISettings::GetString(const char *strSetting, bool bPrompt /* = true */) const -{ - ASSERT(settingsMap.size()); - constMapIter it = settingsMap.find(strSetting); - if (it != settingsMap.end()) - { - CSettingString* result = ((CSettingString *)(*it).second); - if (result->GetData() == "select folder" || result->GetData() == "select writable folder") - { - CStdString strData = ""; - if (bPrompt) - { - VECSOURCES shares; - g_mediaManager.GetLocalDrives(shares); - if (CGUIDialogFileBrowser::ShowAndGetDirectory(shares,g_localizeStrings.Get(result->GetLabel()),strData,result->GetData() == "select writable folder")) - { - result->SetData(strData); - g_settings.Save(); - } - else - return StringUtils::EmptyString; - } - else - return StringUtils::EmptyString; - } - return result->GetData(); - } - // Assert here and write debug output - CLog::Log(LOGDEBUG,"Error: Requested setting (%s) was not found. It must be case-sensitive", strSetting); - //ASSERT(false); - // hardcoded return value so that compiler is happy - return StringUtils::EmptyString; -} - -void CGUISettings::SetString(const char *strSetting, const char *strData) -{ - ASSERT(settingsMap.size()); - mapIter it = settingsMap.find(strSetting); - if (it != settingsMap.end()) - { - ((CSettingString *)(*it).second)->SetData(strData); - - SetChanged(); - - return ; - } - // Assert here and write debug output - ASSERT(false); - CLog::Log(LOGDEBUG,"Error: Requested setting (%s) was not found. It must be case-sensitive", strSetting); -} - -CSetting *CGUISettings::GetSetting(const char *strSetting) -{ - ASSERT(settingsMap.size()); - mapIter it = settingsMap.find(strSetting); - if (it != settingsMap.end()) - return (*it).second; - else - return NULL; -} - -// get all the settings beginning with the term "strGroup" -void CGUISettings::GetSettingsGroup(CSettingsCategory* cat, vecSettings &settings) -{ - if (!cat || cat->m_settings.size() <= 0) - return; - - vecSettings unorderedSettings; - for (unsigned int index = 0; index < cat->m_settings.size(); index++) - { - if (!cat->m_settings.at(index)->IsAdvanced()) - unorderedSettings.push_back(cat->m_settings.at(index)); - } - - // now order them... - sort(unorderedSettings.begin(), unorderedSettings.end(), sortsettings()); - - // remove any instances of 2 separators in a row - bool lastWasSeparator(false); - for (vecSettings::iterator it = unorderedSettings.begin(); it != unorderedSettings.end(); it++) - { - CSetting *setting = *it; - // only add separators if we don't have 2 in a row - if (setting->GetType() == SETTINGS_TYPE_SEPARATOR) - { - if (!lastWasSeparator) - settings.push_back(setting); - lastWasSeparator = true; - } - else - { - lastWasSeparator = false; - settings.push_back(setting); - } - } -} - -void CGUISettings::LoadXML(TiXmlElement *pRootElement, bool hideSettings /* = false */) -{ // load our stuff... - bool updated = false; - - for (mapIter it = settingsMap.begin(); it != settingsMap.end(); it++) - { - LoadFromXML(pRootElement, it, hideSettings); - } - - // check if we are updating to Frodo and need to update from - // audiooutput.channellayout to audiooutput.channels - TiXmlNode *channelNode = pRootElement->FirstChild("audiooutput"); - if (channelNode != NULL) - { - channelNode = channelNode->FirstChild("channellayout"); - CSettingInt* channels = (CSettingInt*)GetSetting("audiooutput.channels"); - if (channelNode != NULL && channelNode->FirstChild() != NULL && channels != NULL) - { - channels->FromString(channelNode->FirstChild()->ValueStr()); - if (channels->GetData() < AE_CH_LAYOUT_MAX - 1) - channels->SetData(channels->GetData() + 1); - - // let's just reset the audiodevice settings as well - std::string audiodevice = GetString("audiooutput.audiodevice"); - CAEFactory::VerifyOutputDevice(audiodevice, false); - SetString("audiooutput.audiodevice", audiodevice.c_str()); - - updated = true; - } - } - - // and fix the videoscreen.screenmode if necessary - std::string screenmode = GetString("videoscreen.screenmode"); - // in Eden there was no character ("i" or "p") indicating interlaced/progressive - // at the end so we just add a "p" and assume progressive - if (screenmode.size() == 20) - { - screenmode += "p"; - SetString("videoscreen.screenmode", screenmode.c_str()); - updated = true; - } - - // Get hardware based stuff... - CLog::Log(LOGNOTICE, "Getting hardware information now..."); - // FIXME: Check if the hardware supports it (if possible ;) - //SetBool("audiooutput.ac3passthrough", g_audioConfig.GetAC3Enabled()); - //SetBool("audiooutput.dtspassthrough", g_audioConfig.GetDTSEnabled()); - CLog::Log(LOGINFO, "Using %s output", GetInt("audiooutput.mode") == AUDIO_ANALOG ? "analog" : "digital"); - CLog::Log(LOGINFO, "AC3 pass through is %s", GetBool("audiooutput.ac3passthrough") ? "enabled" : "disabled"); - CLog::Log(LOGINFO, "DTS pass through is %s", GetBool("audiooutput.dtspassthrough") ? "enabled" : "disabled"); - CLog::Log(LOGINFO, "AAC pass through is %s", GetBool("audiooutput.passthroughaac") ? "enabled" : "disabled"); - -#if defined(TARGET_DARWIN) - // trap any previous vsync by driver setting, does not exist on OSX - if (GetInt("videoscreen.vsync") == VSYNC_DRIVER) - { - SetInt("videoscreen.vsync", VSYNC_ALWAYS); - } -#endif - - // map old vpdau color range, to now global setting - if (GetBool("videoplayer.vdpaustudiolevel")) - { - SetBool("videoscreen.limitedrange", true); - SetBool("videoplayer.vdpaustudiolevel", false); - } - // DXMERGE: This might have been useful? - // g_videoConfig.SetVSyncMode((VSYNC)GetInt("videoscreen.vsync")); - - // Move replaygain settings into our struct - ReplayGainSettings &replayGainSettings = CAudioDecoder::GetReplayGainSettings(); - replayGainSettings.iPreAmp = GetInt("musicplayer.replaygainpreamp"); - replayGainSettings.iNoGainPreAmp = GetInt("musicplayer.replaygainnogainpreamp"); - replayGainSettings.iType = GetInt("musicplayer.replaygaintype"); - replayGainSettings.bAvoidClipping = GetBool("musicplayer.replaygainavoidclipping"); - - bool use_timezone = false; - -#if defined(_LINUX) -#if defined(TARGET_DARWIN) - if (g_sysinfo.IsAppleTV2() && GetIOSVersion() < 4.3) -#endif -#if !defined(TARGET_ANDROID) - use_timezone = true; -#endif - - if (use_timezone) - { - CStdString timezone = GetString("locale.timezone"); - if(timezone == "0" || timezone.IsEmpty()) - { - timezone = g_timezone.GetOSConfiguredTimezone(); - SetString("locale.timezone", timezone); - updated = true; - } - g_timezone.SetTimezone(timezone); - } -#endif - - CStdString streamLanguage = GetString("locale.audiolanguage"); - if (!streamLanguage.Equals("original") && !streamLanguage.Equals("default")) - g_langInfo.SetAudioLanguage(streamLanguage); - else - g_langInfo.SetAudioLanguage(""); - - streamLanguage = GetString("locale.subtitlelanguage"); - if (!streamLanguage.Equals("original") && !streamLanguage.Equals("default")) - g_langInfo.SetSubtitleLanguage(streamLanguage); - else - g_langInfo.SetSubtitleLanguage(""); - - // we no longer ship the built-in slideshow screensaver, replace it if it's still in use - if (GetString("screensaver.mode") == "screensaver.xbmc.builtin.slideshow") - { - SetString("screensaver.mode", "screensaver.xbmc.builtin.dim"); - updated = true; - } - - // replace broken last.fm musicvideo scraper with theaudiodb.com if it's still in use - if (GetString("scrapers.musicvideosdefault") == "metadata.musicvideos.last.fm") - { - SetString("scrapers.musicvideosdefault", "metadata.musicvideos.theaudiodb.com"); - updated = true; - } - - if (updated) - g_settings.Save(); -} - -void CGUISettings::LoadFromXML(TiXmlElement *pRootElement, mapIter &it, bool advanced /* = false */) -{ - CStdStringArray strSplit; - StringUtils::SplitString((*it).first, ".", strSplit); - if (strSplit.size() > 1) - { - const TiXmlNode *pChild = pRootElement->FirstChild(strSplit[0].c_str()); - if (pChild) - { - const TiXmlElement *pGrandChild = pChild->FirstChildElement(strSplit[1].c_str()); - if (pGrandChild) - { - CStdString strValue = pGrandChild->FirstChild() ? pGrandChild->FirstChild()->Value() : ""; - if (strValue != "-") - { // update our item - (*it).second->FromString(strValue); - if (advanced) - (*it).second->SetAdvanced(); - } - } - } - } - - SetChanged(); -} - -void CGUISettings::SaveXML(TiXmlNode *pRootNode) -{ - for (mapIter it = settingsMap.begin(); it != settingsMap.end(); it++) - { - // don't save advanced settings - CStdString first = (*it).first; - if ((*it).second->IsAdvanced() || (*it).second->GetType() == SETTINGS_TYPE_SEPARATOR) - continue; - - CStdStringArray strSplit; - StringUtils::SplitString((*it).first, ".", strSplit); - if (strSplit.size() > 1) - { - TiXmlNode *pChild = pRootNode->FirstChild(strSplit[0].c_str()); - if (!pChild) - { // add our group tag - TiXmlElement newElement(strSplit[0].c_str()); - pChild = pRootNode->InsertEndChild(newElement); - } - - if (pChild) - { // successfully added (or found) our group - TiXmlElement newElement(strSplit[1]); - if ((*it).second->GetType() == SETTINGS_TYPE_PATH) - newElement.SetAttribute("pathversion", XMLUtils::path_version); - TiXmlNode *pNewNode = pChild->InsertEndChild(newElement); - if (pNewNode) - { - TiXmlText value((*it).second->ToString()); - pNewNode->InsertEndChild(value); - } - } - } - } - - SetChanged(); -} - -void CGUISettings::Clear() -{ - for (mapIter it = settingsMap.begin(); it != settingsMap.end(); it++) - delete (*it).second; - settingsMap.clear(); - for (unsigned int i = 0; i < settingsGroups.size(); i++) - delete settingsGroups[i]; - settingsGroups.clear(); - - SetChanged(); -} diff --git a/xbmc/settings/GUISettings.h b/xbmc/settings/GUISettings.h deleted file mode 100644 index dd71c1faa4..0000000000 --- a/xbmc/settings/GUISettings.h +++ /dev/null @@ -1,511 +0,0 @@ -#pragma once - -/* - * Copyright (C) 2005-2013 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 <vector> -#include <map> -#include "guilib/Resolution.h" -#include "addons/IAddon.h" -#include "utils/Observer.h" -#include "utils/GlobalsHandling.h" - -//FIXME - after eden - make that one nicer somehow... -#if defined(TARGET_DARWIN_IOS) && !defined(TARGET_DARWIN_IOS_ATV2) -#include "system.h" //for HAS_SKIN_TOUCHED -#endif - -#if defined(HAS_SKIN_TOUCHED) && defined(TARGET_DARWIN_IOS) && !defined(TARGET_DARWIN_IOS_ATV2) -#define DEFAULT_SKIN "skin.touched" -#else -#define DEFAULT_SKIN "skin.confluence" -#endif - -class TiXmlNode; -class TiXmlElement; - -// Render Methods -#define RENDER_METHOD_AUTO 0 -#define RENDER_METHOD_ARB 1 -#define RENDER_METHOD_GLSL 2 -#define RENDER_METHOD_SOFTWARE 3 -#define RENDER_METHOD_D3D_PS 4 -#define RENDER_METHOD_DXVA 5 -#define RENDER_OVERLAYS 99 // to retain compatibility - -// Scaling options. -#define SOFTWARE_UPSCALING_DISABLED 0 -#define SOFTWARE_UPSCALING_SD_CONTENT 1 -#define SOFTWARE_UPSCALING_ALWAYS 2 - -// Apple Remote options. -#define APPLE_REMOTE_DISABLED 0 -#define APPLE_REMOTE_STANDARD 1 -#define APPLE_REMOTE_UNIVERSAL 2 -#define APPLE_REMOTE_MULTIREMOTE 3 - -// Subtitle colours - -#define SUBTITLE_COLOR_START 0 -#define SUBTITLE_COLOR_END 7 - -// Karaoke colours - -// If you want to add more colors, it should be done the following way: -// 1. Increase KARAOKE_COLOR_END -// 2. Add a new color description in language/English/strings.xml in block -// with id 22040 + KARAOKE_COLOR_END value -// 3. Add a new color hex mask into gLyricColors structure in karaoke/karaokelyricstext.cpp -#define KARAOKE_COLOR_START 0 -#define KARAOKE_COLOR_END 4 - -// CDDA Autoaction defines -#define AUTOCD_NONE 0 -#define AUTOCD_PLAY 1 -#define AUTOCD_RIP 2 - -// CDDA ripper defines -#define CDDARIP_ENCODER_LAME 0 -#define CDDARIP_ENCODER_VORBIS 1 -#define CDDARIP_ENCODER_WAV 2 -#define CDDARIP_ENCODER_FLAC 3 - -#define CDDARIP_QUALITY_CBR 0 -#define CDDARIP_QUALITY_MEDIUM 1 -#define CDDARIP_QUALITY_STANDARD 2 -#define CDDARIP_QUALITY_EXTREME 3 - -#define AUDIO_ANALOG 0 -#define AUDIO_IEC958 1 -#define AUDIO_HDMI 2 -#define AUDIO_COUNT 3 -#define AUDIO_IS_BITSTREAM(x) ((x) == AUDIO_IEC958 || (x) == AUDIO_HDMI) - -#define VIDEO_NORMAL 0 -#define VIDEO_LETTERBOX 1 -#define VIDEO_WIDESCREEN 2 - -#define MODCHIP_SMARTXX 0 -#define MODCHIP_XENIUM 1 -#define MODCHIP_XECUTER3 2 - -// LED settings -#define LED_COLOUR_NO_CHANGE 0 -#define LED_COLOUR_GREEN 1 -#define LED_COLOUR_ORANGE 2 -#define LED_COLOUR_RED 3 -#define LED_COLOUR_CYCLE 4 -#define LED_COLOUR_OFF 5 - -#define FRAME_RATE_LEAVE_AS_IS 0 -#define FRAME_RATE_CONVERT 1 -#define FRAME_RATE_USE_PAL60 2 - -#define LED_PLAYBACK_OFF 0 -#define LED_PLAYBACK_VIDEO 1 -#define LED_PLAYBACK_MUSIC 2 -#define LED_PLAYBACK_VIDEO_MUSIC 3 - -#define SPIN_DOWN_NONE 0 -#define SPIN_DOWN_MUSIC 1 -#define SPIN_DOWN_VIDEO 2 -#define SPIN_DOWN_BOTH 3 - -#define AAM_QUIET 1 -#define AAM_FAST 0 - -#define APM_HIPOWER 0 -#define APM_LOPOWER 1 -#define APM_HIPOWER_STANDBY 2 -#define APM_LOPOWER_STANDBY 3 - -#define GUIDE_VIEW_CHANNEL 0 -#define GUIDE_VIEW_NOW 1 -#define GUIDE_VIEW_NEXT 2 -#define GUIDE_VIEW_TIMELINE 3 - -#define START_LAST_CHANNEL_OFF 0 -#define START_LAST_CHANNEL_MIN 1 -#define START_LAST_CHANNEL_ON 2 - -#define SETTINGS_TYPE_BOOL 1 -#define SETTINGS_TYPE_FLOAT 2 -#define SETTINGS_TYPE_INT 3 -#define SETTINGS_TYPE_STRING 4 -#define SETTINGS_TYPE_HEX 5 -#define SETTINGS_TYPE_SEPARATOR 6 -#define SETTINGS_TYPE_PATH 7 -#define SETTINGS_TYPE_ADDON 8 - -#define CHECKMARK_CONTROL 1 -#define SPIN_CONTROL_FLOAT 2 -#define SPIN_CONTROL_INT 3 -#define SPIN_CONTROL_INT_PLUS 4 -#define SPIN_CONTROL_TEXT 5 -#define EDIT_CONTROL_INPUT 6 -#define EDIT_CONTROL_HIDDEN_INPUT 7 -#define EDIT_CONTROL_NUMBER_INPUT 8 -#define EDIT_CONTROL_IP_INPUT 9 -#define EDIT_CONTROL_MD5_INPUT 10 -#define BUTTON_CONTROL_STANDARD 11 -#define BUTTON_CONTROL_MISC_INPUT 12 -#define BUTTON_CONTROL_PATH_INPUT 13 -#define SEPARATOR_CONTROL 14 -#define EDIT_CONTROL_HIDDEN_NUMBER_VERIFY_NEW 15 - -#define REPLAY_GAIN_NONE 0 -#define REPLAY_GAIN_ALBUM 1 -#define REPLAY_GAIN_TRACK 2 - -//AV sync options -#define SYNC_DISCON 0 -#define SYNC_SKIPDUP 1 -#define SYNC_RESAMPLE 2 - -//adjust refreshrate options -#define ADJUST_REFRESHRATE_OFF 0 -#define ADJUST_REFRESHRATE_ALWAYS 1 -#define ADJUST_REFRESHRATE_ON_STARTSTOP 2 - - -//resampler quality -#define RESAMPLE_LOW 0 -#define RESAMPLE_MID 1 -#define RESAMPLE_HIGH 2 -#define RESAMPLE_REALLYHIGH 3 - -//0.1 second increments -#define MAXREFRESHCHANGEDELAY 200 - -enum PowerState -{ - POWERSTATE_QUIT = 0, - POWERSTATE_SHUTDOWN, - POWERSTATE_HIBERNATE, - POWERSTATE_SUSPEND, - POWERSTATE_REBOOT, - POWERSTATE_MINIMIZE, - POWERSTATE_NONE, - POWERSTATE_ASK -}; - -enum VideoSelectAction -{ - SELECT_ACTION_CHOOSE = 0, - SELECT_ACTION_PLAY_OR_RESUME, - SELECT_ACTION_RESUME, - SELECT_ACTION_INFO, - SELECT_ACTION_MORE, - SELECT_ACTION_PLAY, - SELECT_ACTION_PLAYPART -}; - -enum SubtitleAlign -{ - SUBTITLE_ALIGN_MANUAL = 0, - SUBTITLE_ALIGN_BOTTOM_INSIDE, - SUBTITLE_ALIGN_BOTTOM_OUTSIDE, - SUBTITLE_ALIGN_TOP_INSIDE, - SUBTITLE_ALIGN_TOP_OUTSIDE -}; - -// base class for all settings types -class CSetting -{ -public: - CSetting(int iOrder, const char *strSetting, int iLabel, int iControlType) { - m_iOrder = iOrder; - m_strSetting = strSetting; - m_iLabel = iLabel; - m_iControlType = iControlType; - m_advanced = false; - m_visible = true; - }; - virtual ~CSetting() {}; - virtual int GetType() const { return 0; }; - int GetControlType() const { return m_iControlType; }; - virtual void FromString(const CStdString &strValue) {}; - virtual CStdString ToString() const { return ""; }; - const char *GetSetting() const { return m_strSetting.c_str(); }; - int GetLabel() const { return m_iLabel; }; - int GetOrder() const { return m_iOrder; }; - void SetOrder(int iOrder) { m_iOrder = iOrder; }; - void SetAdvanced() { m_advanced = true; }; - bool IsAdvanced() const { return m_advanced; }; - // A setting might be invisible in the current session, yet carried over - // in the config file. - void SetVisible(bool visible) { m_visible = visible; } - bool IsVisible() const { return m_visible; } -private: - int m_iControlType; - int m_iLabel; - int m_iOrder; - bool m_advanced; - bool m_visible; - CStdString m_strSetting; -}; - -class CSettingBool : public CSetting -{ -public: - CSettingBool(int iOrder, const char *strSetting, int iLabel, bool bData, int iControlType): CSetting(iOrder, strSetting, iLabel, iControlType) { m_bData = bData; }; - virtual ~CSettingBool() {}; - - virtual int GetType() const { return SETTINGS_TYPE_BOOL; }; - virtual void FromString(const CStdString &strValue); - virtual CStdString ToString() const; - - void SetData(bool bData) { m_bData = bData; }; - bool GetData() const { return m_bData; }; - -private: - bool m_bData; -}; - -class CSettingFloat : public CSetting -{ -public: - CSettingFloat(int iOrder, const char *strSetting, int iLabel, float fData, float fMin, float fStep, float fMax, int iControlType); - virtual ~CSettingFloat() {}; - - virtual int GetType() const { return SETTINGS_TYPE_FLOAT; }; - virtual void FromString(const CStdString &strValue); - virtual CStdString ToString() const; - - void SetData(float fData) { m_fData = fData; if (m_fData < m_fMin) m_fData = m_fMin; if (m_fData > m_fMax) m_fData = m_fMax;}; - float GetData() const { return m_fData; }; - - float m_fMin; - float m_fStep; - float m_fMax; - -private: - float m_fData; -}; - -class CSettingInt : public CSetting -{ -public: - CSettingInt(int iOrder, const char *strSetting, int iLabel, int iData, int iMin, int iStep, int iMax, int iControlType, const char *strFormat); - CSettingInt(int iOrder, const char *strSetting, int iLabel, int iData, int iMin, int iStep, int iMax, int iControlType, int iFormat, int iLabelMin); - CSettingInt(int iOrder, const char *strSetting, int iLabel, int iData, const std::map<int,int>& entries, int iControlType); - virtual ~CSettingInt() {}; - - virtual int GetType() const { return SETTINGS_TYPE_INT; }; - virtual void FromString(const CStdString &strValue); - virtual CStdString ToString() const; - - void SetData(int iData) - { - if (m_entries.empty()) - { - m_iData = iData; - if (m_iData < m_iMin) m_iData = m_iMin; - if (m_iData > m_iMax) m_iData = m_iMax; - } - else - { - //if the setting is an std::map, check if iData is a valid value before assigning it - for (std::map<int,int>::iterator it = m_entries.begin(); it != m_entries.end(); it++) - { - if (it->second == iData) - { - m_iData = iData; - break; - } - } - } - } - int GetData() const { return m_iData; }; - - int m_iMin; - int m_iStep; - int m_iMax; - int m_iFormat; - int m_iLabelMin; - CStdString m_strFormat; - std::map<int,int> m_entries; - -protected: - int m_iData; -}; - -class CSettingHex : public CSettingInt -{ -public: - CSettingHex(int iOrder, const char *strSetting, int iLabel, int iData, int iMin, int iStep, int iMax, int iControlType, const char *strFormat) - : CSettingInt(iOrder, strSetting, iLabel, iData, iMin, iStep, iMax, iControlType, strFormat) {}; - virtual ~CSettingHex() {}; - virtual void FromString(const CStdString &strValue); - virtual CStdString ToString() const; - virtual int GetType() const { return SETTINGS_TYPE_HEX; }; -}; - -class CSettingString : public CSetting -{ -public: - CSettingString(int iOrder, const char *strSetting, int iLabel, const char *strData, int iControlType, bool bAllowEmpty, int iHeadingString); - virtual ~CSettingString() {}; - - virtual int GetType() const { return SETTINGS_TYPE_STRING; }; - virtual void FromString(const CStdString &strValue); - virtual CStdString ToString() const; - - void SetData(const char *strData) { m_strData = strData; }; - const CStdString &GetData() const { return m_strData; }; - - bool m_bAllowEmpty; - int m_iHeadingString; -private: - CStdString m_strData; -}; - -class CSettingPath : public CSettingString -{ -public: - CSettingPath(int iOrder, const char *strSetting, int iLabel, const char *strData, int iControlType, bool bAllowEmpty, int iHeadingString); - virtual ~CSettingPath() {}; - - virtual int GetType() const { return SETTINGS_TYPE_PATH; }; -}; - -class CSettingAddon : public CSettingString -{ -public: - CSettingAddon(int iOrder, const char *strSetting, int iLabel, const char *strData, const ADDON::TYPE type); - virtual ~CSettingAddon() {}; - virtual int GetType() const { return SETTINGS_TYPE_ADDON; }; - - const ADDON::TYPE m_type; -}; - -class CSettingSeparator : public CSetting -{ -public: - CSettingSeparator(int iOrder, const char *strSetting); - virtual ~CSettingSeparator() {}; - - virtual int GetType() const { return SETTINGS_TYPE_SEPARATOR; }; -}; - -class CSettingsCategory -{ -public: - CSettingsCategory(const char *strCategory, int labelID) - { - m_strCategory = strCategory; - m_labelID = labelID; - } - ~CSettingsCategory() {}; - - CStdString m_strCategory; - int m_labelID; - std::vector<CSetting*> m_settings; -}; - -typedef std::vector<CSettingsCategory *> vecSettingsCategory; - -class CSettingsGroup -{ -public: - CSettingsGroup(int groupID, int labelID) - { - m_groupID = groupID; - m_labelID = labelID; - } - ~CSettingsGroup() - { - for (unsigned int i = 0; i < m_vecCategories.size(); i++) - delete m_vecCategories[i]; - m_vecCategories.clear(); - }; - - CSettingsCategory* AddCategory(const char *strCategory, int labelID); - void GetCategories(vecSettingsCategory &vecCategories); - int GetLabelID() { return m_labelID; }; - int GetGroupID() { return m_groupID; }; -private: - vecSettingsCategory m_vecCategories; - int m_groupID; - int m_labelID; -}; - -typedef std::vector<CSetting *> vecSettings; - -class CGUISettings : public Observable -{ -public: - CGUISettings(); - ~CGUISettings(); - - void Initialize(); - - void AddGroup(int groupID, int labelID); - CSettingsCategory* AddCategory(int groupID, const char *strCategory, int labelID); - CSettingsGroup *GetGroup(int windowID); - - void AddSetting(CSettingsCategory* cat, CSetting* setting); - void AddBool(CSettingsCategory* cat, const char *strSetting, int iLabel, bool bSetting, int iControlType = CHECKMARK_CONTROL); - bool GetBool(const char *strSetting) const; - void SetBool(const char *strSetting, bool bSetting); - void ToggleBool(const char *strSetting); - - void AddFloat(CSettingsCategory* cat, const char *strSetting, int iLabel, float fSetting, float fMin, float fStep, float fMax, int iControlType = SPIN_CONTROL_FLOAT); - float GetFloat(const char *strSetting) const; - void SetFloat(const char *strSetting, float fSetting); - - void AddInt(CSettingsCategory* cat, const char *strSetting, int iLabel, int fSetting, int iMin, int iStep, int iMax, int iControlType, const char *strFormat = NULL); - void AddInt(CSettingsCategory* cat, const char *strSetting, int iLabel, int iData, int iMin, int iStep, int iMax, int iControlType, int iFormat, int iLabelMin=-1); - void AddInt(CSettingsCategory* cat, const char *strSetting, int iLabel, int iData, const std::map<int,int>& entries, int iControlType); - void AddSpin(unsigned int id, int label, int *current, std::vector<std::pair<int, int> > &values); - int GetInt(const char *strSetting) const; - void SetInt(const char *strSetting, int fSetting); - - void AddHex(CSettingsCategory* cat, const char *strSetting, int iLabel, int fSetting, int iMin, int iStep, int iMax, int iControlType, const char *strFormat = NULL); - - void AddString(CSettingsCategory* cat, const char *strSetting, int iLabel, const char *strData, int iControlType = EDIT_CONTROL_INPUT, bool bAllowEmpty = false, int iHeadingString = -1); - void AddPath(CSettingsCategory* cat, const char *strSetting, int iLabel, const char *strData, int iControlType = EDIT_CONTROL_INPUT, bool bAllowEmpty = false, int iHeadingString = -1); - - void AddDefaultAddon(CSettingsCategory* cat, const char *strSetting, int iLabel, const char *strData, const ADDON::TYPE type); - - const CStdString &GetString(const char *strSetting, bool bPrompt=true) const; - void SetString(const char *strSetting, const char *strData); - - void AddSeparator(CSettingsCategory* cat, const char *strSetting); - - CSetting *GetSetting(const char *strSetting); - - void GetSettingsGroup(CSettingsCategory* cat, vecSettings &settings); - void LoadXML(TiXmlElement *pRootElement, bool hideSettings = false); - void SaveXML(TiXmlNode *pRootNode); - void LoadMasterLock(TiXmlElement *pRootElement); - - void Clear(); - -private: - typedef std::map<std::string, CSetting*>::iterator mapIter; - typedef std::map<std::string, CSetting*>::const_iterator constMapIter; - std::map<std::string, CSetting*> settingsMap; - std::vector<CSettingsGroup *> settingsGroups; - void LoadFromXML(TiXmlElement *pRootElement, mapIter &it, bool advanced = false); -}; - -XBMC_GLOBAL_REF(CGUISettings, g_guiSettings); -#define g_guiSettings XBMC_GLOBAL_USE(CGUISettings) diff --git a/xbmc/settings/ISetting.cpp b/xbmc/settings/ISetting.cpp new file mode 100644 index 0000000000..8f4f4fce36 --- /dev/null +++ b/xbmc/settings/ISetting.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2013 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 "ISetting.h" +#include "utils/log.h" +#include "utils/XBMCTinyXML.h" + +#define XML_VISIBLE "visible" +#define XML_CONDITION "condition" + +using namespace std; + +ISetting::ISetting(const std::string &id, CSettingsManager *settingsManager /* = NULL */) + : m_id(id), + m_settingsManager(settingsManager), + m_visible(true), + m_visibilityCondition(settingsManager) +{ } + +bool ISetting::Deserialize(const TiXmlNode *node, bool update /* = false */) +{ + if (node == NULL) + return false; + + const TiXmlNode *visibleNode = node->FirstChild(XML_VISIBLE); + if (visibleNode == NULL) + return true; + + return m_visibilityCondition.Deserialize(visibleNode); +} + +bool ISetting::DeserializeIdentification(const TiXmlNode *node, std::string &identification) +{ + if (node == NULL) + return false; + + const TiXmlElement *element = node->ToElement(); + if (element == NULL) + return false; + + const char *idAttribute = element->Attribute(XML_ATTR_ID); + if (idAttribute == NULL || strlen(idAttribute) <= 0) + return false; + + identification = idAttribute; + return true; +} + +void ISetting::CheckVisible() +{ + m_visible = m_visibilityCondition.Check(); +} diff --git a/xbmc/settings/ISetting.h b/xbmc/settings/ISetting.h new file mode 100644 index 0000000000..aaf7171c1f --- /dev/null +++ b/xbmc/settings/ISetting.h @@ -0,0 +1,105 @@ +#pragma once +/* + * Copyright (C) 2013 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 <string> +#include <vector> + +#include "SettingVisibility.h" + +#define XML_SETTING "setting" + +#define XML_ATTR_ID "id" +#define XML_ATTR_LABEL "label" +#define XML_ATTR_HELP "help" +#define XML_ATTR_TYPE "type" + +class CSettingsManager; +class TiXmlNode; + +/*! + \ingroup settings + \brief Interface defining the base of all setting objects + */ +class ISetting +{ +public: + /*! + \brief Creates a new setting object with the given identifier. + + \param id Identifier of the setting object + \param settingsManager Reference to the settings manager + */ + ISetting(const std::string &id, CSettingsManager *settingsManager = NULL); + virtual ~ISetting() { } + + /*! + \brief Deserializes the given XML node into the properties of the setting + object. + + If the update parameter is true, the checks for mandatory properties are + skipped and values are only updated. + + \param node XML node containing the properties of the setting object + \param update Whether to perform checks for mandatory properties or not + \return True if deserialization was successful, false otherwise + */ + virtual bool Deserialize(const TiXmlNode *node, bool update = false); + + /*! + \brief Gets the identifier of the setting object. + + \return Identifier of the setting object + */ + const std::string& GetId() const { return m_id; } + /*! + \brief Whether the setting object is visible or hidden. + + \return True if the setting object is visible, false otherwise + */ + bool IsVisible() const { return m_visible; } + /*! + \brief Updates the visibility state of the setting object. + */ + void CheckVisible(); + /*! + \brief Sets the visibility state of the setting object. + + \param visible Whether the setting object shall be visible or not + */ + void SetVisible(bool visible) { m_visible = visible; } + + /*! + \brief Deserializes the given XML node to retrieve a setting object's + identifier. + + \param node XML node containing a setting object's identifier + \param identification Will contain the deserialized setting object's identifier + \return True if a setting object's identifier was deserialized, false otherwise + */ + static bool DeserializeIdentification(const TiXmlNode *node, std::string &identification); + +protected: + std::string m_id; + CSettingsManager *m_settingsManager; + +private: + bool m_visible; + CSettingVisibility m_visibilityCondition; +}; diff --git a/xbmc/settings/ISettingCallback.h b/xbmc/settings/ISettingCallback.h new file mode 100644 index 0000000000..7a239d73d2 --- /dev/null +++ b/xbmc/settings/ISettingCallback.h @@ -0,0 +1,76 @@ +#pragma once +/* + * Copyright (C) 2013 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/>. + * + */ + +class CSetting; +class TiXmlNode; + +class ISettingCallback +{ +public: + virtual ~ISettingCallback() { } + + /*! + \brief The value of the given setting is being changed. + + This callback is triggered whenever the value of a setting is being + changed. The given CSetting already contains the new value and the handler + of the callback has the possibility to allow or revert changing the value + of the setting. In case of a revert OnSettingChanging() is called again to + inform all listeners that the value change has been reverted. + + \param setting The setting whose value is being changed (already containing the changed value) + \return True if the new value is acceptable otherwise false + */ + virtual bool OnSettingChanging(const CSetting *setting) { return true; } + + /*! + \brief The value of the given setting has changed. + + This callback is triggered whenever the value of a setting has been + successfully changed (i.e. none of the OnSettingChanging() handlers) + has reverted the change. + + \param setting The setting whose value has been changed + */ + virtual void OnSettingChanged(const CSetting *setting) { } + + /*! + \brief The given setting has been activated. + + This callback is triggered whenever the given setting has been activated. + This callback is only fired for CSettingAction settings. + + \param setting The setting which has been activated. + */ + virtual void OnSettingAction(const CSetting *setting) { } + + /*! + \brief The given setting needs to be updated. + + This callback is triggered when a setting needs to be updated because its + value is outdated. This only happens when initially loading the value of a + setting and will not be triggered afterwards. + + \param setting The setting which needs to be updated. + \return True if the setting has been successfully updated otherwise false + */ + virtual bool OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode) { return false; } +}; diff --git a/xbmc/settings/ISettingCreator.h b/xbmc/settings/ISettingCreator.h new file mode 100644 index 0000000000..4e393bc55f --- /dev/null +++ b/xbmc/settings/ISettingCreator.h @@ -0,0 +1,45 @@ +#pragma once +/* + * Copyright (C) 2013 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 <string> + +class CSetting; +class CSettingsManager; + +/*! + \ingroup settings + \brief Interface for creating a new setting of a custom setting type. + */ +class ISettingCreator +{ +public: + virtual ~ISettingCreator() { } + + /*! + \brief Creates a new setting of the given custom setting type. + + \param settingType string representation of the setting type + \param settingId Identifier of the setting to be created + \param settingsManager Reference to the settings manager + \return A new setting object of the given (custom) setting type or NULL if the setting type is unknown + */ + virtual CSetting* CreateSetting(const std::string &settingType, const std::string &settingId, CSettingsManager *settingsManager = NULL) const = 0; +}; diff --git a/xbmc/settings/ISettingsHandler.h b/xbmc/settings/ISettingsHandler.h index 15804377c3..70d928a8e3 100644 --- a/xbmc/settings/ISettingsHandler.h +++ b/xbmc/settings/ISettingsHandler.h @@ -19,6 +19,11 @@ * */ +/*! + \ingroup settings + \brief Interface defining methods being called by the settings system if an + action is performed on multiple/all settings + */ class ISettingsHandler { public: @@ -51,8 +56,8 @@ public: /*! \brief Settings have been cleared. - This callback can be used to trigger clearing any state variables - (e.g. before re-loading the settings). + This callback can be used to trigger clearing any state variables (e.g. + before re-loading the settings). */ virtual void OnSettingsCleared() { } }; diff --git a/xbmc/settings/ISubSettings.h b/xbmc/settings/ISubSettings.h index 3f3b316646..7632cd2274 100644 --- a/xbmc/settings/ISubSettings.h +++ b/xbmc/settings/ISubSettings.h @@ -21,6 +21,11 @@ class TiXmlNode; +/*! + \ingroup settings + \brief Interface defining methods to load additional setting values from an + XML file being loaded by the settings system. + */ class ISubSettings { public: @@ -44,4 +49,4 @@ public: \brief Clear any loaded setting values. */ virtual void Clear() { } -};
\ No newline at end of file +}; diff --git a/xbmc/settings/Makefile b/xbmc/settings/Makefile index 118e431e7a..33a08a1a09 100644 --- a/xbmc/settings/Makefile +++ b/xbmc/settings/Makefile @@ -1,9 +1,20 @@ SRCS=AdvancedSettings.cpp \ DisplaySettings.cpp \ - GUISettings.cpp \ + ISetting.cpp \ MediaSettings.cpp \ MediaSourceSettings.cpp \ + Setting.cpp \ + SettingAddon.cpp \ + SettingCategoryAccess.cpp \ + SettingConditions.cpp \ + SettingControl.cpp \ + SettingDependency.cpp \ + SettingPath.cpp \ + SettingSection.cpp \ Settings.cpp \ + SettingsManager.cpp \ + SettingUpdate.cpp \ + SettingVisibility.cpp \ SkinSettings.cpp \ VideoSettings.cpp \ diff --git a/xbmc/settings/MediaSettings.cpp b/xbmc/settings/MediaSettings.cpp index ee48085cf7..ae659a289d 100644 --- a/xbmc/settings/MediaSettings.cpp +++ b/xbmc/settings/MediaSettings.cpp @@ -21,10 +21,23 @@ #include <limits.h> #include "MediaSettings.h" +#include "Application.h" +#include "Util.h" +#include "dialogs/GUIDialogContextMenu.h" +#include "dialogs/GUIDialogFileBrowser.h" +#include "dialogs/GUIDialogYesNo.h" +#include "guilib/WindowIDs.h" +#include "interfaces/Builtins.h" +#include "music/MusicDatabase.h" +#include "profiles/ProfilesManager.h" +#include "settings/Setting.h" +#include "storage/MediaManager.h" #include "threads/SingleLock.h" #include "utils/log.h" +#include "utils/URIUtils.h" #include "utils/XBMCTinyXML.h" #include "utils/XMLUtils.h" +#include "video/VideoDatabase.h" using namespace std; @@ -237,6 +250,99 @@ bool CMediaSettings::Save(TiXmlNode *settings) const return true; } +void CMediaSettings::OnSettingAction(const CSetting *setting) +{ + if (setting == NULL) + return; + + const std::string &settingId = setting->GetId(); + if (settingId == "karaoke.export") + { + CContextButtons choices; + choices.Add(1, g_localizeStrings.Get(22034)); + choices.Add(2, g_localizeStrings.Get(22035)); + + int retVal = CGUIDialogContextMenu::ShowAndGetChoice(choices); + if ( retVal > 0 ) + { + CStdString path(CProfilesManager::Get().GetDatabaseFolder()); + VECSOURCES shares; + g_mediaManager.GetLocalDrives(shares); + if (CGUIDialogFileBrowser::ShowAndGetDirectory(shares, g_localizeStrings.Get(661), path, true)) + { + CMusicDatabase musicdatabase; + musicdatabase.Open(); + + if ( retVal == 1 ) + { + path = URIUtils::AddFileToFolder(path, "karaoke.html"); + musicdatabase.ExportKaraokeInfo( path, true ); + } + else + { + path = URIUtils::AddFileToFolder(path, "karaoke.csv"); + musicdatabase.ExportKaraokeInfo( path, false ); + } + musicdatabase.Close(); + } + } + } + else if (settingId == "karaoke.importcsv") + { + CStdString path(CProfilesManager::Get().GetDatabaseFolder()); + VECSOURCES shares; + g_mediaManager.GetLocalDrives(shares); + if (CGUIDialogFileBrowser::ShowAndGetFile(shares, "karaoke.csv", g_localizeStrings.Get(651) , path)) + { + CMusicDatabase musicdatabase; + musicdatabase.Open(); + musicdatabase.ImportKaraokeInfo(path); + musicdatabase.Close(); + } + } + else if (settingId == "musiclibrary.cleanup") + { + CMusicDatabase musicdatabase; + musicdatabase.Clean(); + CUtil::DeleteMusicDatabaseDirectoryCache(); + } + else if (settingId == "musiclibrary.export") + CBuiltins::Execute("exportlibrary(music)"); + else if (settingId == "musiclibrary.import") + { + CStdString path; + VECSOURCES shares; + g_mediaManager.GetLocalDrives(shares); + if (CGUIDialogFileBrowser::ShowAndGetFile(shares, "musicdb.xml", g_localizeStrings.Get(651) , path)) + { + CMusicDatabase musicdatabase; + musicdatabase.Open(); + musicdatabase.ImportFromXML(path); + musicdatabase.Close(); + } + } + else if (settingId == "videolibrary.cleanup") + { + if (CGUIDialogYesNo::ShowAndGetInput(313, 333, 0, 0)) + g_application.StartVideoCleanup(); + } + else if (settingId == "videolibrary.export") + CBuiltins::Execute("exportlibrary(video)"); + else if (settingId == "videolibrary.import") + { + CStdString path; + VECSOURCES shares; + g_mediaManager.GetLocalDrives(shares); + if (CGUIDialogFileBrowser::ShowAndGetDirectory(shares, g_localizeStrings.Get(651) , path)) + { + CVideoDatabase videodatabase; + videodatabase.Open(); + videodatabase.ImportFromXML(path); + videodatabase.Close(); + } + } +} + int CMediaSettings::GetWatchedMode(const std::string &content) const { CSingleLock lock(m_critical); diff --git a/xbmc/settings/MediaSettings.h b/xbmc/settings/MediaSettings.h index 9747a2567b..b2dad89a7f 100644 --- a/xbmc/settings/MediaSettings.h +++ b/xbmc/settings/MediaSettings.h @@ -22,6 +22,7 @@ #include <map> #include <string> +#include "settings/ISettingCallback.h" #include "settings/ISubSettings.h" #include "settings/VideoSettings.h" #include "threads/CriticalSection.h" @@ -37,7 +38,7 @@ typedef enum { WatchedModeWatched } WatchedMode; -class CMediaSettings : public ISubSettings +class CMediaSettings : public ISettingCallback, public ISubSettings { public: static CMediaSettings& Get(); @@ -45,6 +46,8 @@ public: virtual bool Load(const TiXmlNode *settings); virtual bool Save(TiXmlNode *settings) const; + virtual void OnSettingAction(const CSetting *setting); + const CVideoSettings& GetDefaultVideoSettings() const { return m_defaultVideoSettings; } CVideoSettings& GetDefaultVideoSettings() { return m_defaultVideoSettings; } const CVideoSettings& GetCurrentVideoSettings() const { return m_currentVideoSettings; } diff --git a/xbmc/settings/Setting.cpp b/xbmc/settings/Setting.cpp new file mode 100644 index 0000000000..dc8bb65169 --- /dev/null +++ b/xbmc/settings/Setting.cpp @@ -0,0 +1,913 @@ +/* + * Copyright (C) 2013 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 <sstream> + +#include "Setting.h" +#include "threads/SingleLock.h" +#include "utils/log.h" +#include "utils/StringUtils.h" +#include "utils/XBMCTinyXML.h" +#include "utils/XMLUtils.h" + +#define XML_ELM_LEVEL "level" +#define XML_ELM_DEFAULT "default" +#define XML_ELM_VALUE "value" + +#define XML_ELM_CONSTRAINTS "constraints" +#define XML_ELM_OPTIONS "options" +#define XML_ELM_MINIMUM "minimum" +#define XML_ELM_STEP "step" +#define XML_ELM_MAXIMUM "maximum" + +CSetting::CSetting(const std::string &id, CSettingsManager *settingsManager /* = NULL */) + : ISetting(id, settingsManager), + m_callback(NULL), + m_label(-1), m_help(-1), + m_level(SettingLevelStandard), + m_changed(false) +{ } + +CSetting::CSetting(const std::string &id, const CSetting &setting) + : ISetting(id, setting.m_settingsManager), + m_callback(NULL), + m_label(-1), m_help(-1), + m_level(SettingLevelStandard), + m_changed(false) +{ + m_id = id; + Copy(setting); +} + +bool CSetting::Deserialize(const TiXmlNode *node, bool update /* = false */) +{ + // handle <visible> conditions + if (!ISetting::Deserialize(node, update)) + return false; + + const TiXmlElement *element = node->ToElement(); + if (element == NULL) + return false; + + // get the attributes label and help + int tmp = -1; + if (element->QueryIntAttribute(XML_ATTR_LABEL, &m_label) == TIXML_SUCCESS && tmp > 0) + m_label = tmp; + if (element->QueryIntAttribute(XML_ATTR_HELP, &m_help) == TIXML_SUCCESS && tmp > 0) + m_help = tmp; + + // get the <level> + int level = -1; + if (XMLUtils::GetInt(node, XML_ELM_LEVEL, level)) + m_level = (SettingLevel)level; + + if (m_level < (int)SettingLevelBasic || m_level > (int)SettingLevelInternal) + m_level = SettingLevelStandard; + + const TiXmlElement *control = node->FirstChildElement("control"); + if (control != NULL) + { + if (!m_control.Deserialize(control, update) || + m_control.GetType() == SettingControlTypeNone) + { + CLog::Log(LOGERROR, "CSetting: error reading <control> tag of \"%s\"", m_id.c_str()); + return false; + } + + const TiXmlNode *dependencies = control->FirstChild("dependencies"); + if (dependencies != NULL) + { + const TiXmlNode *dependencyNode = dependencies->FirstChild("dependency"); + while (dependencyNode != NULL) + { + CSettingDependency dependency(m_settingsManager); + if (dependency.Deserialize(dependencyNode)) + m_dependencies.push_back(dependency); + else + CLog::Log(LOGWARNING, "CSetting: error reading <dependency> tag of \"%s\"", m_id.c_str()); + + dependencyNode = dependencyNode->NextSibling("dependency"); + } + } + } + + const TiXmlNode *updates = node->FirstChild("updates"); + if (updates != NULL) + { + const TiXmlElement *updateElem = updates->FirstChildElement("update"); + while (updateElem != NULL) + { + CSettingUpdate update; + if (update.Deserialize(updateElem)) + { + if (!m_updates.insert(update).second) + CLog::Log(LOGWARNING, "CSetting: duplicate <update> definition for \"%s\"", m_id.c_str()); + } + else + CLog::Log(LOGWARNING, "CSetting: error reading <update> tag of \"%s\"", m_id.c_str()); + + updateElem = updateElem->NextSiblingElement("update"); + } + } + + if ((m_control.GetType() == SettingControlTypeSpinner || m_control.GetType() == SettingControlTypeEdit) && + m_control.GetFormat() == SettingControlFormatNone) + { + CLog::Log(LOGERROR, "CSetting: invalid <control> tag of \"%s\"", m_id.c_str()); + return false; + } + + return true; +} + +bool CSetting::OnSettingChanging(const CSetting *setting) +{ + if (m_callback == NULL) + return true; + + return m_callback->OnSettingChanging(setting); +} + +void CSetting::OnSettingChanged(const CSetting *setting) +{ + if (m_callback == NULL) + return; + + m_callback->OnSettingChanged(setting); +} + +void CSetting::OnSettingAction(const CSetting *setting) +{ + if (m_callback == NULL) + return; + + m_callback->OnSettingAction(setting); +} + +bool CSetting::OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode) +{ + if (m_callback == NULL) + return false; + + return m_callback->OnSettingUpdate(setting, oldSettingId, oldSettingNode); +} + +void CSetting::Copy(const CSetting &setting) +{ + SetVisible(setting.IsVisible()); + m_callback = setting.m_callback; + m_label = setting.m_label; + m_help = setting.m_help; + m_level = setting.m_level; + m_control = setting.m_control; + m_dependencies = setting.m_dependencies; + m_updates = setting.m_updates; + m_changed = setting.m_changed; +} + +CSettingBool::CSettingBool(const std::string &id, CSettingsManager *settingsManager /* = NULL */) + : CSetting(id, settingsManager), + m_value(false), m_default(false) +{ + m_control.SetType(SettingControlTypeCheckmark); + m_control.SetFormat(SettingControlFormatBoolean); + m_control.SetAttributes(SettingControlAttributeNone); +} + +CSettingBool::CSettingBool(const std::string &id, const CSettingBool &setting) + : CSetting(id, setting) +{ + copy(setting); +} + +CSettingBool::CSettingBool(const std::string &id, int label, bool value, CSettingsManager *settingsManager /* = NULL */) + : CSetting(id, settingsManager), + m_value(value), m_default(value) +{ + m_label = label; + + m_control.SetType(SettingControlTypeCheckmark); + m_control.SetFormat(SettingControlFormatBoolean); + m_control.SetAttributes(SettingControlAttributeNone); +} + +bool CSettingBool::Deserialize(const TiXmlNode *node, bool update /* = false */) +{ + CSingleLock lock(m_critical); + + if (!CSetting::Deserialize(node, update)) + return false; + + if (m_control.GetType() != SettingControlTypeCheckmark || + m_control.GetFormat() != SettingControlFormatBoolean || + m_control.GetAttributes() != SettingControlAttributeNone) + { + CLog::Log(LOGERROR, "CSettingBool: invalid <control> of \"%s\"", m_id.c_str()); + return false; + } + + // get the default value + bool value; + if (XMLUtils::GetBoolean(node, XML_ELM_DEFAULT, value)) + m_value = m_default = value; + else if (!update) + { + CLog::Log(LOGERROR, "CSettingBool: error reading the default value of \"%s\"", m_id.c_str()); + return false; + } + + return true; +} + +bool CSettingBool::FromString(const std::string &value) +{ + bool bValue; + if (!fromString(value, bValue)) + return false; + + return SetValue(bValue); +} + +std::string CSettingBool::ToString() const +{ + return m_value ? "true" : "false"; +} + +bool CSettingBool::Equals(const std::string &value) const +{ + bool bValue; + return (fromString(value, bValue) && m_value == bValue); +} + +bool CSettingBool::CheckValidity(const std::string &value) const +{ + bool bValue; + return fromString(value, bValue); +} + +bool CSettingBool::SetValue(bool value) +{ + CSingleLock lock(m_critical); + + if (value == m_value) + return true; + + bool oldValue = m_value; + m_value = value; + + if (!OnSettingChanging(this)) + { + m_value = oldValue; + + // the setting couldn't be changed because one of the + // callback handlers failed the OnSettingChanging() + // callback so we need to let all the callback handlers + // know that the setting hasn't changed + OnSettingChanging(this); + return false; + } + + m_changed = m_value != m_default; + OnSettingChanged(this); + return true; +} + +void CSettingBool::SetDefault(bool value) +{ + CSingleLock lock(m_critical); + + m_default = value; + if (!m_changed) + m_value = m_default; +} + +void CSettingBool::copy(const CSettingBool &setting) +{ + CSetting::Copy(setting); + + m_value = setting.m_value; + m_default = setting.m_default; +} + +bool CSettingBool::fromString(const std::string &strValue, bool &value) const +{ + CSingleLock lock(m_critical); + + if (StringUtils::EqualsNoCase(strValue, "true")) + { + value = true; + return true; + } + if (StringUtils::EqualsNoCase(strValue, "false")) + { + value = false; + return true; + } + + return false; +} + +CSettingInt::CSettingInt(const std::string &id, CSettingsManager *settingsManager /* = NULL */) + : CSetting(id, settingsManager), + m_value(0), m_default(0), + m_min(0), m_step(1), m_max(0), + m_format(-1), m_labelMin(-1), m_strFormat("%i") +{ } + +CSettingInt::CSettingInt(const std::string &id, const CSettingInt &setting) + : CSetting(id, setting) +{ + copy(setting); +} + +CSettingInt::CSettingInt(const std::string &id, int label, int value, int minimum, int step, int maximum, int format, int minimumLabel, CSettingsManager *settingsManager /* = NULL */) + : CSetting(id, settingsManager), + m_value(value), m_default(value), + m_min(minimum), m_step(step), m_max(maximum), + m_format(format), m_labelMin(minimumLabel), m_strFormat("%i") +{ + m_label = label; + + m_control.SetType(SettingControlTypeSpinner); + if (format < 0) + m_control.SetFormat(SettingControlFormatInteger); + else + m_control.SetFormat(SettingControlFormatString); + m_control.SetAttributes(SettingControlAttributeNone); +} + +CSettingInt::CSettingInt(const std::string &id, int label, int value, int minimum, int step, int maximum, const std::string &format, CSettingsManager *settingsManager /* = NULL */) + : CSetting(id, settingsManager), + m_value(value), m_default(value), + m_min(minimum), m_step(step), m_max(maximum), + m_format(-1), m_labelMin(-1), m_strFormat(format) +{ + m_label = label; + + m_control.SetType(SettingControlTypeSpinner); + if (format.empty()) + { + m_strFormat = "%i"; + m_control.SetFormat(SettingControlFormatInteger); + } + else + m_control.SetFormat(SettingControlFormatString); + m_control.SetAttributes(SettingControlAttributeNone); +} + +CSettingInt::CSettingInt(const std::string &id, int label, int value, const SettingOptions &options, CSettingsManager *settingsManager /* = NULL */) + : CSetting(id, settingsManager), + m_value(value), m_default(value), + m_min(0), m_step(1), m_max(0), + m_format(-1), m_labelMin(-1), m_strFormat("%i"), + m_options(options) +{ + m_label = label; + + m_control.SetType(SettingControlTypeSpinner); + m_control.SetFormat(SettingControlFormatString); + m_control.SetAttributes(SettingControlAttributeNone); +} + +bool CSettingInt::Deserialize(const TiXmlNode *node, bool update /* = false */) +{ + CSingleLock lock(m_critical); + + if (!CSetting::Deserialize(node, update)) + return false; + + if (m_control.GetType() == SettingControlTypeCheckmark) + { + CLog::Log(LOGERROR, "CSettingInt: invalid <control> of \"%s\"", m_id.c_str()); + return false; + } + + // get the default value + int value; + if (XMLUtils::GetInt(node, XML_ELM_DEFAULT, value)) + m_value = m_default = value; + else if (!update) + { + CLog::Log(LOGERROR, "CSettingInt: error reading the default value of \"%s\"", m_id.c_str()); + return false; + } + + const TiXmlNode *constraints = node->FirstChild(XML_ELM_CONSTRAINTS); + if (constraints != NULL) + { + // get the entries + const TiXmlNode *options = constraints->FirstChild(XML_ELM_OPTIONS); + if (options != NULL && options->FirstChild() != NULL) + { + if (options->FirstChild()->Type() == TiXmlNode::TINYXML_TEXT) + m_optionsFiller = options->FirstChild()->ValueStr(); + else + { + m_options.clear(); + const TiXmlElement *optionElement = options->FirstChildElement("option"); + while (optionElement != NULL) + { + std::pair<int, int> entry; + if (optionElement->QueryIntAttribute("label", &entry.first) == TIXML_SUCCESS && entry.first > 0) + { + entry.second = strtol(optionElement->FirstChild()->Value(), NULL, 10); + m_options.push_back(entry); + } + + optionElement = optionElement->NextSiblingElement("option"); + } + } + } + + // get minimum + if (XMLUtils::GetInt(constraints, XML_ELM_MINIMUM, m_min) && + m_control.GetFormat() == SettingControlFormatString) + { + const TiXmlElement *minimumElement = constraints->FirstChildElement(XML_ELM_MINIMUM); + if (minimumElement->QueryIntAttribute(XML_ATTR_LABEL, &m_labelMin) != TIXML_SUCCESS) + m_labelMin = -1; + } + // get step + XMLUtils::GetInt(constraints, XML_ELM_STEP, m_step); + // get maximum + XMLUtils::GetInt(constraints, XML_ELM_MAXIMUM, m_max); + + if (m_control.GetFormat() == SettingControlFormatString) + { + XMLUtils::GetInt(constraints, "formatlabel", m_format); + + if (m_labelMin < 0) + { + CStdString strFormat; + if (XMLUtils::GetString(constraints, "format", strFormat) && !strFormat.empty()) + m_strFormat = strFormat; + } + } + } + + return true; +} + +bool CSettingInt::FromString(const std::string &value) +{ + int iValue; + if (!fromString(value, iValue)) + return false; + + return SetValue(iValue); +} + +std::string CSettingInt::ToString() const +{ + std::ostringstream oss; + oss << m_value; + + return oss.str(); +} + +bool CSettingInt::Equals(const std::string &value) const +{ + int iValue; + return (fromString(value, iValue) && m_value == iValue); +} + +bool CSettingInt::CheckValidity(const std::string &value) const +{ + int iValue; + if (!fromString(value, iValue)) + return false; + + return CheckValidity(iValue); +} + +bool CSettingInt::CheckValidity(int value) const +{ + if (!m_options.empty()) + { + //if the setting is an std::map, check if we got a valid value before assigning it + bool ok = false; + for (SettingOptions::const_iterator it = m_options.begin(); it != m_options.end(); it++) + { + if (it->second == value) + { + ok = true; + break; + } + } + + if (!ok) + return false; + } + else if (m_optionsFiller.empty() && m_min != m_max && + (value < m_min || value > m_max)) + return false; + + return true; +} + +bool CSettingInt::SetValue(int value) +{ + CSingleLock lock(m_critical); + + if (value == m_value) + return true; + + if (!CheckValidity(value)) + return false; + + int oldValue = m_value; + m_value = value; + + if (!OnSettingChanging(this)) + { + m_value = oldValue; + + // the setting couldn't be changed because one of the + // callback handlers failed the OnSettingChanging() + // callback so we need to let all the callback handlers + // know that the setting hasn't changed + OnSettingChanging(this); + return false; + } + + m_changed = m_value != m_default; + OnSettingChanged(this); + return true; +} + +void CSettingInt::SetDefault(int value) +{ + CSingleLock lock(m_critical); + + m_default = value; + if (!m_changed) + m_value = m_default; +} + +void CSettingInt::copy(const CSettingInt &setting) +{ + CSetting::Copy(setting); + + m_value = setting.m_value; + m_default = setting.m_default; + m_min = setting.m_min; + m_step = setting.m_step; + m_max = setting.m_max; + m_format = setting.m_format; + m_labelMin = setting.m_labelMin; + m_strFormat = setting.m_strFormat; + m_options = setting.m_options; + m_optionsFiller = setting.m_optionsFiller; +} + +bool CSettingInt::fromString(const std::string &strValue, int &value) const +{ + if (strValue.empty()) + return false; + + char *end = NULL; + value = (int)strtol(strValue.c_str(), &end, 10); + if (end != NULL && *end != '\0') + return false; + + return true; +} + +CSettingNumber::CSettingNumber(const std::string &id, CSettingsManager *settingsManager /* = NULL */) + : CSetting(id, settingsManager), + m_value(0.0), m_default(0.0), + m_min(0.0), m_step(1.0), m_max(0.0) +{ } + +CSettingNumber::CSettingNumber(const std::string &id, const CSettingNumber &setting) + : CSetting(id, setting) +{ + copy(setting); +} + +CSettingNumber::CSettingNumber(const std::string &id, int label, float value, float minimum, float step, float maximum, CSettingsManager *settingsManager /* = NULL */) + : CSetting(id, settingsManager), + m_value(value), m_default(value), + m_min(minimum), m_step(step), m_max(maximum) +{ + m_label = label; + + m_control.SetType(SettingControlTypeSpinner); + m_control.SetFormat(SettingControlFormatNumber); + m_control.SetAttributes(SettingControlAttributeNone); +} + +bool CSettingNumber::Deserialize(const TiXmlNode *node, bool update /* = false */) +{ + CSingleLock lock(m_critical); + + if (!CSetting::Deserialize(node, update)) + return false; + + if (m_control.GetType() == SettingControlTypeCheckmark) + { + CLog::Log(LOGERROR, "CSettingInt: invalid <control> of \"%s\"", m_id.c_str()); + return false; + } + + // get the default value + double value; + if (XMLUtils::GetDouble(node, XML_ELM_DEFAULT, value)) + m_value = m_default = value; + else if (!update) + { + CLog::Log(LOGERROR, "CSettingNumber: error reading the default value of \"%s\"", m_id.c_str()); + return false; + } + + const TiXmlNode *constraints = node->FirstChild(XML_ELM_CONSTRAINTS); + if (constraints != NULL) + { + // get the minimum value + XMLUtils::GetDouble(constraints, XML_ELM_MINIMUM, m_min); + // get the step value + XMLUtils::GetDouble(constraints, XML_ELM_STEP, m_step); + // get the maximum value + XMLUtils::GetDouble(constraints, XML_ELM_MAXIMUM, m_max); + } + + return true; +} + +bool CSettingNumber::FromString(const std::string &value) +{ + double dValue; + if (!fromString(value, dValue)) + return false; + + return SetValue(dValue); +} + +std::string CSettingNumber::ToString() const +{ + std::ostringstream oss; + oss << m_value; + + return oss.str(); +} + +bool CSettingNumber::Equals(const std::string &value) const +{ + double dValue; + return (fromString(value, dValue) && m_value == dValue); +} + +bool CSettingNumber::CheckValidity(const std::string &value) const +{ + double dValue; + if (!fromString(value, dValue)) + return false; + + return CheckValidity(dValue); +} + +bool CSettingNumber::CheckValidity(double value) const +{ + if (m_min != m_max && + (value < m_min || value > m_max)) + return false; + + return true; +} + +bool CSettingNumber::SetValue(double value) +{ + CSingleLock lock(m_critical); + + if (value == m_value) + return true; + + if (!CheckValidity(value)) + return false; + + double oldValue = m_value; + m_value = value; + + if (!OnSettingChanging(this)) + { + m_value = oldValue; + + // the setting couldn't be changed because one of the + // callback handlers failed the OnSettingChanging() + // callback so we need to let all the callback handlers + // know that the setting hasn't changed + OnSettingChanging(this); + return false; + } + + m_changed = m_value != m_default; + OnSettingChanged(this); + return true; +} + +void CSettingNumber::SetDefault(double value) +{ + CSingleLock lock(m_critical); + + m_default = value; + if (!m_changed) + m_value = m_default; +} + +void CSettingNumber::copy(const CSettingNumber &setting) +{ + CSetting::Copy(setting); + + m_value = setting.m_value; + m_default = setting.m_default; + m_min = setting.m_min; + m_step = setting.m_step; + m_max = setting.m_max; +} + +bool CSettingNumber::fromString(const std::string &strValue, double &value) const +{ + if (strValue.empty()) + return false; + + char *end = NULL; + value = (int)strtod(strValue.c_str(), &end); + if (end != NULL && *end != '\0') + return false; + + return true; +} + +CSettingString::CSettingString(const std::string &id, CSettingsManager *settingsManager /* = NULL */) + : CSetting(id, settingsManager), + m_allowEmpty(false), m_heading(-1) +{ } + +CSettingString::CSettingString(const std::string &id, const CSettingString &setting) + : CSetting(id, setting) +{ + copy(setting); +} + +CSettingString::CSettingString(const std::string &id, int label, const std::string &value, CSettingsManager *settingsManager /* = NULL */) + : CSetting(id, settingsManager), + m_value(value), m_default(value), + m_allowEmpty(false), m_heading(-1) +{ + m_label = label; + + m_control.SetType(SettingControlTypeEdit); + m_control.SetFormat(SettingControlFormatString); + m_control.SetAttributes(SettingControlAttributeNone); +} + +bool CSettingString::Deserialize(const TiXmlNode *node, bool update /* = false */) +{ + CSingleLock lock(m_critical); + + if (!CSetting::Deserialize(node, update)) + return false; + + if (m_control.GetType() == SettingControlTypeCheckmark || + (m_control.GetType() == SettingControlTypeSpinner && (m_control.GetFormat() == SettingControlFormatInteger || m_control.GetFormat() == SettingControlFormatNumber)) || + (m_control.GetType() == SettingControlTypeEdit && m_control.GetFormat() == SettingControlFormatNumber)) + { + CLog::Log(LOGERROR, "CSettingString: invalid <control> of \"%s\"", m_id.c_str()); + return false; + } + + // get allowempty (needs to be parsed before parsing the default value) + XMLUtils::GetBoolean(node, "allowempty", m_allowEmpty); + // get heading + XMLUtils::GetInt(node, "heading", m_heading); + + // get the default value + CStdString value; + if (XMLUtils::GetString(node, XML_ELM_DEFAULT, value)) + m_value = m_default = value; + else if (!update && !m_allowEmpty) + { + CLog::Log(LOGERROR, "CSettingString: error reading the default value of \"%s\"", m_id.c_str()); + return false; + } + + const TiXmlNode *constraints = node->FirstChild(XML_ELM_CONSTRAINTS); + if (constraints != NULL) + { + // get the entries + const TiXmlNode *options = constraints->FirstChild(XML_ELM_OPTIONS); + if (options != NULL && options->FirstChild() != NULL && + options->FirstChild()->Type() == TiXmlNode::TINYXML_TEXT) + m_optionsFiller = options->FirstChild()->ValueStr(); + } + + return true; +} + +bool CSettingString::CheckValidity(const std::string &value) const +{ + if (!m_allowEmpty && value.empty()) + return false; + + return true; +} + +bool CSettingString::SetValue(const std::string &value) +{ + CSingleLock lock(m_critical); + + if (value == m_value) + return true; + + if (!CheckValidity(value)) + return false; + + std::string oldValue = m_value; + m_value = value; + + if (!OnSettingChanging(this)) + { + m_value = oldValue; + + // the setting couldn't be changed because one of the + // callback handlers failed the OnSettingChanging() + // callback so we need to let all the callback handlers + // know that the setting hasn't changed + OnSettingChanging(this); + return false; + } + + m_changed = m_value != m_default; + OnSettingChanged(this); + return true; +} + +void CSettingString::SetDefault(const std::string &value) +{ + CSingleLock lock(m_critical); + + m_default = value; + if (!m_changed) + m_value = m_default; +} + +void CSettingString::copy(const CSettingString &setting) +{ + CSetting::Copy(setting); + + m_value = setting.m_value; + m_default = setting.m_default; + m_allowEmpty = setting.m_allowEmpty; + m_heading = setting.m_heading; +} + +CSettingAction::CSettingAction(const std::string &id, CSettingsManager *settingsManager /* = NULL */) + : CSetting(id, settingsManager) +{ + m_control.SetType(SettingControlTypeButton); + m_control.SetFormat(SettingControlFormatAction); + m_control.SetAttributes(SettingControlAttributeNone); +} + +CSettingAction::CSettingAction(const std::string &id, const CSettingAction &setting) + : CSetting(id, setting) +{ + m_control.SetType(SettingControlTypeButton); + m_control.SetFormat(SettingControlFormatAction); + m_control.SetAttributes(SettingControlAttributeNone); +} + +bool CSettingAction::Deserialize(const TiXmlNode *node, bool update /* = false */) +{ + CSingleLock lock(m_critical); + + if (!CSetting::Deserialize(node, update)) + return false; + + if (m_control.GetType() != SettingControlTypeButton || + m_control.GetFormat() != SettingControlFormatAction || + m_control.GetAttributes() != SettingControlAttributeNone) + { + CLog::Log(LOGERROR, "CSettingAction: invalid <control> of \"%s\"", m_id.c_str()); + return false; + } + + return true; +} diff --git a/xbmc/settings/Setting.h b/xbmc/settings/Setting.h new file mode 100644 index 0000000000..deea23ee7e --- /dev/null +++ b/xbmc/settings/Setting.h @@ -0,0 +1,318 @@ +#pragma once +/* + * Copyright (C) 2013 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 <map> +#include <set> +#include <string> +#include <vector> + +#include "ISetting.h" +#include "ISettingCallback.h" +#include "SettingControl.h" +#include "SettingDependency.h" +#include "SettingUpdate.h" +#include "threads/CriticalSection.h" + +/*! + \ingroup settings + \brief Basic setting types available in the settings system. + */ +typedef enum { + SettingTypeNone = 0, + SettingTypeBool, + SettingTypeInteger, + SettingTypeNumber, + SettingTypeString, + SettingTypeAction +} SettingType; + +/*! + \ingroup settings + \brief Levels which every setting is assigned to. + */ +typedef enum { + SettingLevelBasic = 0, + SettingLevelStandard, + SettingLevelAdvanced, + SettingLevelExpert, + SettingLevelInternal +} SettingLevel; + +typedef std::pair<int, int> SettingOption; +typedef std::vector<SettingOption> SettingOptions; + +/*! + \ingroup settings + \brief Setting base class containing all the properties which are common to + all settings independent of the setting type. + */ +class CSetting : public ISetting, + protected ISettingCallback +{ +public: + CSetting(const std::string &id, CSettingsManager *settingsManager = NULL); + CSetting(const std::string &id, const CSetting &setting); + virtual ~CSetting() { } + + virtual bool Deserialize(const TiXmlNode *node, bool update = false); + + virtual int GetType() const = 0; + virtual bool FromString(const std::string &value) = 0; + virtual std::string ToString() const = 0; + virtual bool Equals(const std::string &value) const = 0; + virtual bool CheckValidity(const std::string &value) const = 0; + virtual void Reset() = 0; + + int GetLabel() const { return m_label; } + int GetHelp() const { return m_help; } + SettingLevel GetLevel() const { return m_level; } + const CSettingControl& GetControl() const { return m_control; } + const SettingDependencies& GetDependencies() const { return m_dependencies; } + const std::set<CSettingUpdate>& GetUpdates() const { return m_updates; } + +protected: + friend class CSettingsManager; + + virtual bool OnSettingChanging(const CSetting *setting); + virtual void OnSettingChanged(const CSetting *setting); + virtual void OnSettingAction(const CSetting *setting); + virtual bool OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode); + + void Copy(const CSetting &setting); + + ISettingCallback *m_callback; + int m_label; + int m_help; + SettingLevel m_level; + CSettingControl m_control; + SettingDependencies m_dependencies; + std::set<CSettingUpdate> m_updates; + bool m_changed; + CCriticalSection m_critical; +}; + +typedef std::vector<CSetting *> SettingList; + +/*! + \ingroup settings + \brief Boolean setting implementation. + \sa CSetting + */ +class CSettingBool : public CSetting +{ +public: + CSettingBool(const std::string &id, CSettingsManager *settingsManager = NULL); + CSettingBool(const std::string &id, const CSettingBool &setting); + CSettingBool(const std::string &id, int label, bool value, CSettingsManager *settingsManager = NULL); + virtual ~CSettingBool() { } + + virtual bool Deserialize(const TiXmlNode *node, bool update = false); + + virtual int GetType() const { return SettingTypeBool; } + virtual bool FromString(const std::string &value); + virtual std::string ToString() const; + virtual bool Equals(const std::string &value) const; + virtual bool CheckValidity(const std::string &value) const; + virtual void Reset() { SetValue(m_default); } + + bool GetValue() const { return m_value; } + bool SetValue(bool value); + bool GetDefault() const { return m_default; } + void SetDefault(bool value); + +private: + void copy(const CSettingBool &setting); + bool fromString(const std::string &strValue, bool &value) const; + + bool m_value; + bool m_default; +}; + +/*! + \ingroup settings + \brief Integer setting implementation + \sa CSetting + */ +class CSettingInt : public CSetting +{ +public: + CSettingInt(const std::string &id, CSettingsManager *settingsManager = NULL); + CSettingInt(const std::string &id, const CSettingInt &setting); + CSettingInt(const std::string &id, int label, int value, int minimum, int step, int maximum, int format, int minimumLabel, CSettingsManager *settingsManager = NULL); + CSettingInt(const std::string &id, int label, int value, int minimum, int step, int maximum, const std::string &format, CSettingsManager *settingsManager = NULL); + CSettingInt(const std::string &id, int label, int value, const SettingOptions &options, CSettingsManager *settingsManager = NULL); + virtual ~CSettingInt() { } + + virtual bool Deserialize(const TiXmlNode *node, bool update = false); + + virtual int GetType() const { return SettingTypeInteger; } + virtual bool FromString(const std::string &value); + virtual std::string ToString() const; + virtual bool Equals(const std::string &value) const; + virtual bool CheckValidity(const std::string &value) const; + virtual bool CheckValidity(int value) const; + virtual void Reset() { SetValue(m_default); } + + int GetValue() const { return m_value; } + bool SetValue(int value); + int GetDefault() const { return m_default; } + void SetDefault(int value); + + int GetMinimum() const { return m_min; } + int GetStep() const { return m_step; } + int GetMaximum() const { return m_max; } + + int GetFormat() const { return m_format; } + int GetMinimumLabel() const { return m_labelMin; } + const std::string& GetFormatString() const { return m_strFormat; } + const SettingOptions& GetOptions() const { return m_options; } + const std::string& GetOptionsFiller() const { return m_optionsFiller; } + +private: + void copy(const CSettingInt &setting); + bool fromString(const std::string &strValue, int &value) const; + + int m_value; + int m_default; + int m_min; + int m_step; + int m_max; + int m_format; + int m_labelMin; + std::string m_strFormat; + SettingOptions m_options; + std::string m_optionsFiller; +}; + +/*! + \ingroup settings + \brief Real number setting implementation. + \sa CSetting + */ +class CSettingNumber : public CSetting +{ +public: + CSettingNumber(const std::string &id, CSettingsManager *settingsManager = NULL); + CSettingNumber(const std::string &id, const CSettingNumber &setting); + CSettingNumber(const std::string &id, int label, float value, float minimum, float step, float maximum, CSettingsManager *settingsManager = NULL); + virtual ~CSettingNumber() { } + + virtual bool Deserialize(const TiXmlNode *node, bool update = false); + + virtual int GetType() const { return SettingTypeNumber; } + virtual bool FromString(const std::string &value); + virtual std::string ToString() const; + virtual bool Equals(const std::string &value) const; + virtual bool CheckValidity(const std::string &value) const; + virtual bool CheckValidity(double value) const; + virtual void Reset() { SetValue(m_default); } + + double GetValue() const { return m_value; } + bool SetValue(double value); + double GetDefault() const { return m_default; } + void SetDefault(double value); + + double GetMinimum() const { return m_min; } + double GetStep() const { return m_step; } + double GetMaximum() const { return m_max; } + +private: + virtual void copy(const CSettingNumber &setting); + bool fromString(const std::string &strValue, double &value) const; + + double m_value; + double m_default; + double m_min; + double m_step; + double m_max; +}; + +/*! + \ingroup settings + \brief String setting implementation. + \sa CSetting + */ +class CSettingString : public CSetting +{ +public: + CSettingString(const std::string &id, CSettingsManager *settingsManager = NULL); + CSettingString(const std::string &id, const CSettingString &setting); + CSettingString(const std::string &id, int label, const std::string &value, CSettingsManager *settingsManager = NULL); + virtual ~CSettingString() { } + + virtual bool Deserialize(const TiXmlNode *node, bool update = false); + + virtual int GetType() const { return SettingTypeString; } + virtual bool FromString(const std::string &value) { return SetValue(value); } + virtual std::string ToString() const { return m_value; } + virtual bool Equals(const std::string &value) const { return m_value == value; } + virtual bool CheckValidity(const std::string &value) const; + virtual void Reset() { SetValue(m_default); } + + virtual const std::string& GetValue() const { return m_value; } + virtual bool SetValue(const std::string &value); + virtual const std::string& GetDefault() const { return m_default; } + virtual void SetDefault(const std::string &value); + + virtual bool AllowEmpty() const { return m_allowEmpty; } + virtual int GetHeading() const { return m_heading; } + + const std::string& GetOptionsFiller() const { return m_optionsFiller; } + +protected: + virtual void copy(const CSettingString &setting); + + std::string m_value; + std::string m_default; + bool m_allowEmpty; + int m_heading; + std::string m_optionsFiller; +}; + +/*! + \ingroup settings + \brief Action setting implementation. + + A setting action will trigger a call to the OnSettingAction() callback method + when activated. + + \sa CSetting + */ +class CSettingAction : public CSetting +{ +public: + CSettingAction(const std::string &id, CSettingsManager *settingsManager = NULL); + CSettingAction(const std::string &id, const CSettingAction &setting); + virtual ~CSettingAction() { } + + virtual bool Deserialize(const TiXmlNode *node, bool update = false); + + virtual int GetType() const { return SettingTypeAction; } + virtual bool FromString(const std::string &value) { return false; } + virtual std::string ToString() const { return ""; } + virtual bool Equals(const std::string &value) const { return false; } + virtual bool CheckValidity(const std::string &value) const { return false; } + virtual void Reset() { } + + // this needs to be public so it can be triggered when activated + // by the user in the GUI. + virtual void OnSettingAction(const CSetting *setting) { return CSetting::OnSettingAction(this); } +}; diff --git a/xbmc/settings/SettingAddon.cpp b/xbmc/settings/SettingAddon.cpp new file mode 100644 index 0000000000..bcf6dd38d6 --- /dev/null +++ b/xbmc/settings/SettingAddon.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2013 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 "SettingAddon.h" +#include "addons/Addon.h" +#include "settings/SettingsManager.h" +#include "threads/SingleLock.h" +#include "utils/log.h" +#include "utils/XBMCTinyXML.h" +#include "utils/XMLUtils.h" + +#define XML_ELM_DEFAULT "default" + +CSettingAddon::CSettingAddon(const std::string &id, CSettingsManager *settingsManager /* = NULL */) + : CSettingString(id, settingsManager), + m_addonType(ADDON::ADDON_UNKNOWN) +{ + m_control.SetType(SettingControlTypeButton); + m_control.SetFormat(SettingControlFormatAddon); + m_control.SetAttributes(SettingControlAttributeNone); +} + +CSettingAddon::CSettingAddon(const std::string &id, const CSettingAddon &setting) + : CSettingString(id, setting) +{ + copy(setting); +} + +bool CSettingAddon::Deserialize(const TiXmlNode *node, bool update /* = false */) +{ + CSingleLock lock(m_critical); + + if (!CSettingString::Deserialize(node, update)) + return false; + + if (m_control.GetType() != SettingControlTypeButton || + m_control.GetFormat() != SettingControlFormatAddon || + m_control.GetAttributes() != SettingControlAttributeNone) + { + CLog::Log(LOGERROR, "CSettingAddon: invalid <control> of \"%s\"", m_id.c_str()); + return false; + } + + // get the default value by abusing the FromString + // implementation to parse the default value + CStdString value; + if (XMLUtils::GetString(node, XML_ELM_DEFAULT, value)) + m_value = m_default = value; + else if (!update) + { + CLog::Log(LOGERROR, "CSettingAddon: error reading the default value of \"%s\"", m_id.c_str()); + return false; + } + + // get the addon type + CStdString strAddonType; + bool ok = XMLUtils::GetString(node, "addontype", strAddonType); + if (ok) + { + m_addonType = ADDON::TranslateType(strAddonType); + if (m_addonType == ADDON::ADDON_UNKNOWN) + ok = false; + } + + if (!ok && !update) + { + CLog::Log(LOGERROR, "CSettingAddon: error reading the addontype value \"%s\" of \"%s\"", strAddonType.c_str(), m_id.c_str()); + return false; + } + + return true; +} + +void CSettingAddon::copy(const CSettingAddon &setting) +{ + CSettingString::Copy(setting); + + m_addonType = setting.m_addonType; +} diff --git a/xbmc/cores/paplayer/CDDAcodec.h b/xbmc/settings/SettingAddon.h index 487e9a5988..644c325652 100644 --- a/xbmc/cores/paplayer/CDDAcodec.h +++ b/xbmc/settings/SettingAddon.h @@ -1,7 +1,6 @@ #pragma once - /* - * Copyright (C) 2005-2013 Team XBMC + * Copyright (C) 2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify @@ -20,24 +19,22 @@ * */ -#include "CachingCodec.h" +#include "Setting.h" +#include "addons/IAddon.h" -class CDDACodec : public CachingCodec +class CSettingAddon : public CSettingString { public: - CDDACodec(); - virtual ~CDDACodec(); + CSettingAddon(const std::string &id, CSettingsManager *settingsManager = NULL); + CSettingAddon(const std::string &id, const CSettingAddon &setting); + virtual ~CSettingAddon() { } + + virtual bool Deserialize(const TiXmlNode *node, bool update = false); - virtual bool Init(const CStdString &strFile, unsigned int filecache); - virtual void DeInit(); - virtual int64_t Seek(int64_t iSeekTime); - virtual int ReadPCM(BYTE *pBuffer, int size, int *actualsize); - virtual bool CanInit(); - virtual CAEChannelInfo GetChannelInfo(); + ADDON::TYPE GetAddonType() const { return m_addonType; } private: - // Input buffer to read our cdda data into - BYTE* m_Buffer; - int m_BufferSize; - int m_BufferPos; + void copy(const CSettingAddon &setting); + + ADDON::TYPE m_addonType; }; diff --git a/xbmc/settings/SettingCategoryAccess.cpp b/xbmc/settings/SettingCategoryAccess.cpp new file mode 100644 index 0000000000..609eb853da --- /dev/null +++ b/xbmc/settings/SettingCategoryAccess.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2013 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 "SettingCategoryAccess.h" +#include "SettingConditions.h" +#include "SettingsManager.h" +#include "utils/log.h" + +bool CSettingCategoryAccessCondition::Check() const +{ + if (m_value.empty()) + return true; + + if (m_settingsManager == NULL) + return false; + + bool found = m_settingsManager->GetConditions().Check(m_value, "true"); + if (m_negated) + return !found; + + return found; +} + +bool CSettingCategoryAccessConditionCombination::Check() const +{ + if (m_operations.empty() && m_values.empty()) + return true; + + return CSettingConditionCombination::Check(); +} + +CSettingCategoryAccess::CSettingCategoryAccess(CSettingsManager *settingsManager /* = NULL */) + : CSettingCondition(settingsManager) +{ + m_operation = CBooleanLogicOperationPtr(new CSettingCategoryAccessConditionCombination(m_settingsManager)); +} diff --git a/xbmc/settings/SettingCategoryAccess.h b/xbmc/settings/SettingCategoryAccess.h new file mode 100644 index 0000000000..bc1cc3a173 --- /dev/null +++ b/xbmc/settings/SettingCategoryAccess.h @@ -0,0 +1,58 @@ +#pragma once +/* + * Copyright (C) 2013 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 <set> +#include <string> + +#include "SettingConditions.h" + +class CSettingCategoryAccessCondition : public CSettingConditionItem +{ +public: + CSettingCategoryAccessCondition(CSettingsManager *settingsManager = NULL) + : CSettingConditionItem(settingsManager) + { } + virtual ~CSettingCategoryAccessCondition() { } + + virtual bool Check() const; +}; + +class CSettingCategoryAccessConditionCombination : public CSettingConditionCombination +{ +public: + CSettingCategoryAccessConditionCombination(CSettingsManager *settingsManager = NULL) + : CSettingConditionCombination(settingsManager) + { } + virtual ~CSettingCategoryAccessConditionCombination() { } + + virtual bool Check() const; + +private: + virtual CBooleanLogicOperation* newOperation() { return new CSettingCategoryAccessConditionCombination(m_settingsManager); } + virtual CBooleanLogicValue* newValue() { return new CSettingCategoryAccessCondition(m_settingsManager); } +}; + +class CSettingCategoryAccess : public CSettingCondition +{ +public: + CSettingCategoryAccess(CSettingsManager *settingsManager = NULL); + virtual ~CSettingCategoryAccess() { } +}; diff --git a/xbmc/settings/SettingConditions.cpp b/xbmc/settings/SettingConditions.cpp new file mode 100644 index 0000000000..d06aac99d9 --- /dev/null +++ b/xbmc/settings/SettingConditions.cpp @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2013 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 "SettingConditions.h" +#include "SettingsManager.h" +#include "utils/StringUtils.h" +#include "utils/XBMCTinyXML.h" + +bool CSettingConditionItem::Deserialize(const TiXmlNode *node) +{ + if (!CBooleanLogicValue::Deserialize(node)) + return false; + + const TiXmlElement *elem = node->ToElement(); + if (elem == NULL) + return false; + + // get the "name" attribute + const char *strAttribute = elem->Attribute("name"); + if (strAttribute != NULL) + m_name = strAttribute; + + // get the "setting" attribute + strAttribute = elem->Attribute("setting"); + if (strAttribute != NULL) + m_setting = strAttribute; + + return true; +} + +bool CSettingConditionItem::Check() const +{ + if (m_settingsManager == NULL) + return false; + + return m_settingsManager->GetConditions().Check(m_name, m_value, m_setting) == !m_negated; +} + +bool CSettingConditionCombination::Check() const +{ + bool ok = false; + for (CBooleanLogicOperations::const_iterator operation = m_operations.begin(); + operation != m_operations.end(); operation++) + { + if (*operation == NULL) + continue; + + CSettingConditionCombination *combination = static_cast<CSettingConditionCombination*>((*operation).get()); + if (combination == NULL) + continue; + + if (combination->Check()) + ok = true; + else if (m_operation == BooleanLogicOperationAnd) + return false; + } + + for (CBooleanLogicValues::const_iterator value = m_values.begin(); + value != m_values.end(); value++) + { + if (*value == NULL) + continue; + + CSettingConditionItem *condition = static_cast<CSettingConditionItem*>((*value).get()); + if (condition == NULL) + continue; + + if (condition->Check()) + ok = true; + else if (m_operation == BooleanLogicOperationAnd) + return false; + } + + return ok; +} + +CSettingCondition::CSettingCondition(CSettingsManager *settingsManager /* = NULL */) + : ISettingCondition(settingsManager) +{ + m_operation = CBooleanLogicOperationPtr(new CSettingConditionCombination(settingsManager)); +} + +bool CSettingCondition::Check() const +{ + CSettingConditionCombination *combination = static_cast<CSettingConditionCombination*>(m_operation.get()); + if (combination == NULL) + return false; + + return combination->Check(); +} + +void CSettingConditionsManager::AddCondition(const std::string &condition) +{ + if (condition.empty()) + return; + + m_defines.insert(condition); +} + +void CSettingConditionsManager::AddCondition(const std::string &identifier, SettingConditionCheck condition) +{ + if (identifier.empty() || condition == NULL) + return; + + m_conditions.insert(SettingConditionPair(identifier, condition)); +} + +bool CSettingConditionsManager::Check(const std::string &condition, const std::string &value /* = "" */, const std::string settingId /* = "" */) const +{ + if (condition.empty()) + return false; + + std::string tmpCondition = condition; + StringUtils::ToLower(tmpCondition); + + // special handling of "isdefined" conditions + if (tmpCondition == "isdefined") + { + std::string tmpValue = value; + StringUtils::ToLower(tmpValue); + + return m_defines.find(tmpValue) != m_defines.end(); + } + + SettingConditionMap::const_iterator conditionIt = m_conditions.find(tmpCondition); + if (conditionIt == m_conditions.end()) + return false; + + return conditionIt->second(tmpCondition, value, settingId); +} + +CSettingConditionsManager::CSettingConditionsManager() +{ } + +CSettingConditionsManager::~CSettingConditionsManager() +{ + m_conditions.clear(); + m_defines.clear(); +} diff --git a/xbmc/settings/SettingConditions.h b/xbmc/settings/SettingConditions.h new file mode 100644 index 0000000000..4b2fe7726a --- /dev/null +++ b/xbmc/settings/SettingConditions.h @@ -0,0 +1,107 @@ +#pragma once +/* + * Copyright (C) 2013 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 <map> +#include <set> +#include <string> + +#include "utils/BooleanLogic.h" + +class CSettingsManager; + +typedef bool (*SettingConditionCheck)(const std::string &condition, const std::string &value, const std::string &settingId); + +class ISettingCondition +{ +public: + ISettingCondition(CSettingsManager *settingsManager) + : m_settingsManager(settingsManager) + { } + virtual ~ISettingCondition() { } + + virtual bool Check() const = 0; + +protected: + CSettingsManager *m_settingsManager; +}; + +class CSettingConditionItem : public CBooleanLogicValue, public ISettingCondition +{ +public: + CSettingConditionItem(CSettingsManager *settingsManager = NULL) + : ISettingCondition(settingsManager) + { } + virtual ~CSettingConditionItem() { } + + virtual bool Deserialize(const TiXmlNode *node); + virtual const char* GetTag() const { return "condition"; } + virtual bool Check() const; + +protected: + std::string m_name; + std::string m_setting; +}; + +class CSettingConditionCombination : public CBooleanLogicOperation, public ISettingCondition +{ +public: + CSettingConditionCombination(CSettingsManager *settingsManager = NULL) + : ISettingCondition(settingsManager) + { } + virtual ~CSettingConditionCombination() { } + + virtual bool Check() const; + +private: + virtual CBooleanLogicOperation* newOperation() { return new CSettingConditionCombination(m_settingsManager); } + virtual CBooleanLogicValue* newValue() { return new CSettingConditionItem(m_settingsManager); } +}; + +class CSettingCondition : public CBooleanLogic, public ISettingCondition +{ +public: + CSettingCondition(CSettingsManager *settingsManager = NULL); + virtual ~CSettingCondition() { } + + virtual bool Check() const; +}; + +class CSettingConditionsManager +{ +public: + CSettingConditionsManager(); + virtual ~CSettingConditionsManager(); + + void AddCondition(const std::string &condition); + void AddCondition(const std::string &identifier, SettingConditionCheck condition); + + bool Check(const std::string &condition, const std::string &value = "", const std::string settingId = "") const; + +private: + CSettingConditionsManager(const CSettingConditionsManager&); + CSettingConditionsManager const& operator=(CSettingConditionsManager const&); + + typedef std::pair<std::string, SettingConditionCheck> SettingConditionPair; + typedef std::map<std::string, SettingConditionCheck> SettingConditionMap; + + SettingConditionMap m_conditions; + std::set<std::string> m_defines; +}; diff --git a/xbmc/settings/SettingControl.cpp b/xbmc/settings/SettingControl.cpp new file mode 100644 index 0000000000..a8c6212566 --- /dev/null +++ b/xbmc/settings/SettingControl.cpp @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2013 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 <vector> + +#include "SettingControl.h" +#include "utils/log.h" +#include "utils/StringUtils.h" +#include "utils/XBMCTinyXML.h" + +bool CSettingControl::Deserialize(const TiXmlNode *node, bool update /* = false */) +{ + if (node == NULL) + return false; + + const TiXmlElement *elem = node->ToElement(); + if (elem == NULL) + return false; + + const char *strTmp = elem->Attribute("type"); + if ((strTmp == NULL && !update && m_type == SettingControlTypeNone) || (strTmp != NULL && !setType(strTmp))) + { + CLog::Log(LOGERROR, "CSetting: error reading \"type\" attribute of <control>"); + return false; + } + + strTmp = elem->Attribute("format"); + if ((strTmp == NULL && !update && m_format == SettingControlFormatNone) || (strTmp != NULL && !setFormat(strTmp))) + { + CLog::Log(LOGERROR, "CSetting: error reading \"format\" attribute of <control>"); + return false; + } + + if ((strTmp = elem->Attribute("attributes")) != NULL && !setAttributes(strTmp)) + { + CLog::Log(LOGERROR, "CSetting: error reading \"attributes\" attribute of <control>"); + return false; + } + + if ((strTmp = elem->Attribute("delayed")) != NULL) + { + if (!StringUtils::EqualsNoCase(strTmp, "false") && !StringUtils::EqualsNoCase(strTmp, "true")) + { + CLog::Log(LOGERROR, "CSetting: error reading \"delayed\" attribute of <control>"); + return false; + } + else + m_delayed = StringUtils::EqualsNoCase(strTmp, "true"); + } + + return true; +} + +bool CSettingControl::setType(const std::string &strType) +{ + if (StringUtils::EqualsNoCase(strType, "toggle")) + m_type = SettingControlTypeCheckmark; + else if (StringUtils::EqualsNoCase(strType, "spinner")) + m_type = SettingControlTypeSpinner; + else if (StringUtils::EqualsNoCase(strType, "edit")) + { + m_type = SettingControlTypeEdit; + m_delayed = true; + } + else if (StringUtils::EqualsNoCase(strType, "button")) + m_type = SettingControlTypeButton; + else + return false; + + return true; +} + +bool CSettingControl::setFormat(const std::string &strFormat) +{ + if (StringUtils::EqualsNoCase(strFormat, "boolean")) + m_format = SettingControlFormatBoolean; + else if (StringUtils::EqualsNoCase(strFormat, "string")) + m_format = SettingControlFormatString; + else if (StringUtils::EqualsNoCase(strFormat, "integer")) + m_format = SettingControlFormatInteger; + else if (StringUtils::EqualsNoCase(strFormat, "number")) + m_format = SettingControlFormatNumber; + else if (StringUtils::EqualsNoCase(strFormat, "ip")) + m_format = SettingControlFormatIP; + else if (StringUtils::EqualsNoCase(strFormat, "md5")) + m_format = SettingControlFormatMD5; + else if (StringUtils::EqualsNoCase(strFormat, "path")) + m_format = SettingControlFormatPath; + else if (StringUtils::EqualsNoCase(strFormat, "addon")) + m_format = SettingControlFormatAddon; + else if (StringUtils::EqualsNoCase(strFormat, "action")) + m_format = SettingControlFormatAction; + else + return false; + + return true; +} + +bool CSettingControl::setAttributes(const std::string &strAttributes) +{ + std::vector<std::string> attributeList = StringUtils::Split(strAttributes, ","); + + int controlAttributes = SettingControlAttributeNone; + for (std::vector<std::string>::const_iterator attribute = attributeList.begin(); attribute != attributeList.end(); attribute++) + { + if (StringUtils::EqualsNoCase(*attribute, "hidden")) + controlAttributes |= (int)SettingControlAttributeHidden; + else if (StringUtils::EqualsNoCase(*attribute, "new")) + controlAttributes |= (int)SettingControlAttributeVerifyNew; + else + return false; + } + + m_attributes = (SettingControlAttribute)controlAttributes; + return true; +}
\ No newline at end of file diff --git a/xbmc/settings/SettingControl.h b/xbmc/settings/SettingControl.h new file mode 100644 index 0000000000..816108f223 --- /dev/null +++ b/xbmc/settings/SettingControl.h @@ -0,0 +1,84 @@ +#pragma once +/* + * Copyright (C) 2013 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 <string> + +class TiXmlNode; + +typedef enum { + SettingControlTypeNone = 0, + SettingControlTypeCheckmark, + SettingControlTypeSpinner, + SettingControlTypeEdit, + SettingControlTypeButton +} SettingControlType; + +typedef enum { + SettingControlFormatNone = 0, + SettingControlFormatBoolean, + SettingControlFormatString, + SettingControlFormatInteger, + SettingControlFormatNumber, + SettingControlFormatIP, + SettingControlFormatMD5, + SettingControlFormatPath, + SettingControlFormatAddon, + SettingControlFormatAction +} SettingControlFormat; + +typedef enum { + SettingControlAttributeNone = 0x0, + SettingControlAttributeHidden = 0x1, + SettingControlAttributeVerifyNew = 0x2 +} SettingControlAttribute; + +class CSettingControl +{ +public: + CSettingControl(SettingControlType type = SettingControlTypeNone, + SettingControlFormat format = SettingControlFormatNone, + SettingControlAttribute attribute = SettingControlAttributeNone) + : m_type(type), m_format(format), m_attributes(attribute), + m_delayed(false) + { } + virtual ~CSettingControl() { } + + bool Deserialize(const TiXmlNode *node, bool update = false); + + SettingControlType GetType() const { return m_type; } + SettingControlFormat GetFormat() const { return m_format; } + SettingControlAttribute GetAttributes() const { return m_attributes; } + bool GetDelayed() const { return m_delayed; } + + void SetType(SettingControlType type) { m_type = type; } + void SetFormat(SettingControlFormat format) { m_format = format; } + void SetAttributes(SettingControlAttribute attributes) { m_attributes = attributes; } + +protected: + bool setType(const std::string &strType); + bool setFormat(const std::string &strFormat); + bool setAttributes(const std::string &strAttributes); + + SettingControlType m_type; + SettingControlFormat m_format; + SettingControlAttribute m_attributes; + bool m_delayed; +}; diff --git a/xbmc/settings/SettingDependency.cpp b/xbmc/settings/SettingDependency.cpp new file mode 100644 index 0000000000..03772f9cb2 --- /dev/null +++ b/xbmc/settings/SettingDependency.cpp @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2013 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 <stdlib.h> + +#include "SettingDependency.h" +#include "Setting.h" +#include "SettingsManager.h" +#include "utils/log.h" +#include "utils/StringUtils.h" +#include "utils/XBMCTinyXML.h" + +bool CSettingDependencyCondition::Deserialize(const TiXmlNode *node) +{ + if (!CSettingConditionItem::Deserialize(node)) + return false; + + const TiXmlElement *elem = node->ToElement(); + if (elem == NULL) + return false; + + m_target = SettingDependencyTargetSetting; + const char *strTarget = elem->Attribute("on"); + if (strTarget != NULL && !setTarget(strTarget)) + { + CLog::Log(LOGWARNING, "CSettingDependencyCondition: unknown target \"%s\"", strTarget); + return false; + } + + if (m_target != SettingDependencyTargetSetting && m_name.empty()) + { + CLog::Log(LOGWARNING, "CSettingDependencyCondition: missing name for dependency"); + return false; + } + + if (m_target == SettingDependencyTargetSetting) + { + if (m_setting.empty()) + { + CLog::Log(LOGWARNING, "CSettingDependencyCondition: missing setting for dependency"); + return false; + } + + m_name = m_setting; + } + + m_operator = SettingDependencyOperatorEquals; + const char *strOperator = elem->Attribute("operator"); + if (strOperator != NULL && !setOperator(strOperator)) + { + CLog::Log(LOGWARNING, "CSettingDependencyCondition: unknown operator \"%s\"", strOperator); + return false; + } + + return true; +} + +bool CSettingDependencyCondition::Check() const +{ + if (m_name.empty() || + m_target == SettingDependencyTargetNone || + m_operator == SettingDependencyOperatorNone || + m_settingsManager == NULL) + return false; + + bool result = false; + switch (m_target) + { + case SettingDependencyTargetSetting: + { + if (m_setting.empty()) + return false; + + const CSetting *setting = m_settingsManager->GetSetting(m_setting); + if (setting == NULL) + { + CLog::Log(LOGWARNING, "CSettingDependencyCondition: unable to check condition on unknown setting \"%s\"", m_setting.c_str()); + return false; + } + + if (m_operator == SettingDependencyOperatorEquals) + result = setting->Equals(m_value); + else if (m_operator == SettingDependencyOperatorContains) + result = (setting->ToString().find(m_value) != std::string::npos); + + break; + } + + case SettingDependencyTargetProperty: + { + result = m_settingsManager->GetConditions().Check(m_name, m_value, m_setting); + break; + } + + default: + return false; + } + + return result == !m_negated; +} + +bool CSettingDependencyCondition::setTarget(const std::string &target) +{ + if (StringUtils::EqualsNoCase(target, "setting")) + m_target = SettingDependencyTargetSetting; + else if (StringUtils::EqualsNoCase(target, "property")) + m_target = SettingDependencyTargetProperty; + else + return false; + + return true; +} + +bool CSettingDependencyCondition::setOperator(const std::string &op) +{ + size_t length = 0; + if (StringUtils::EndsWith(op, "is")) + { + m_operator = SettingDependencyOperatorEquals; + length = 2; + } + else if (StringUtils::EndsWith(op, "contains")) + { + m_operator = SettingDependencyOperatorContains; + length = 8; + } + + if (op.size() > length + 1) + return false; + if (op.size() == length + 1) + { + if (!StringUtils::StartsWith(op, "!")) + return false; + m_negated = true; + } + + return true; +} + +bool CSettingDependencyConditionCombination::Deserialize(const TiXmlNode *node) +{ + if (node == NULL) + return false; + + size_t numOperations = m_operations.size(); + size_t numValues = m_values.size(); + + if (!CSettingConditionCombination::Deserialize(node)) + return false; + + if (numOperations < m_operations.size()) + { + for (size_t i = numOperations; i < m_operations.size(); i++) + { + if (m_operations[i] == NULL) + continue; + + CSettingDependencyConditionCombination *combination = static_cast<CSettingDependencyConditionCombination*>(m_operations[i].get()); + if (combination == NULL) + continue; + + const std::set<std::string>& settings = combination->GetSettings(); + m_settings.insert(settings.begin(), settings.end()); + } + } + + if (numValues < m_values.size()) + { + for (size_t i = numValues; i < m_values.size(); i++) + { + if (m_values[i] == NULL) + continue; + + CSettingDependencyCondition *condition = static_cast<CSettingDependencyCondition*>(m_values[i].get()); + if (condition == NULL) + continue; + + std::string settingId = condition->GetSetting(); + if (!settingId.empty()) + m_settings.insert(settingId); + } + } + + return true; +} + +CSettingDependency::CSettingDependency(CSettingsManager *settingsManager /* = NULL */) + : CSettingCondition(settingsManager), + m_type(SettingDependencyTypeNone) +{ + m_operation = CBooleanLogicOperationPtr(new CSettingDependencyConditionCombination(m_settingsManager)); +} + +bool CSettingDependency::Deserialize(const TiXmlNode *node) +{ + if (node == NULL) + return false; + + const TiXmlElement *elem = node->ToElement(); + if (elem == NULL) + return false; + + const char *strType = elem->Attribute("type"); + if (strType == NULL || strlen(strType) <= 0 || !setType(strType)) + { + CLog::Log(LOGWARNING, "CSettingDependency: missing or unknown dependency type definition"); + return false; + } + + return CSettingCondition::Deserialize(node); +} + +std::set<std::string> CSettingDependency::GetSettings() const +{ + if (m_operation == NULL) + return std::set<std::string>(); + + CSettingDependencyConditionCombination *combination = static_cast<CSettingDependencyConditionCombination*>(m_operation.get()); + if (combination == NULL) + return std::set<std::string>(); + + return combination->GetSettings(); +} + +bool CSettingDependency::setType(const std::string &type) +{ + if (StringUtils::EqualsNoCase(type, "enable")) + m_type = SettingDependencyTypeEnable; + else if (StringUtils::EqualsNoCase(type, "update")) + m_type = SettingDependencyTypeUpdate; + else + return false; + + return true; +} diff --git a/xbmc/settings/SettingDependency.h b/xbmc/settings/SettingDependency.h new file mode 100644 index 0000000000..fb2e0964a1 --- /dev/null +++ b/xbmc/settings/SettingDependency.h @@ -0,0 +1,109 @@ +#pragma once +/* + * Copyright (C) 2013 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 <list> +#include <set> +#include <string> + +#include "SettingConditions.h" +#include "utils/BooleanLogic.h" + +typedef enum { + SettingDependencyTypeNone = 0, + SettingDependencyTypeEnable, + SettingDependencyTypeUpdate +} SettingDependencyType; + +typedef enum { + SettingDependencyOperatorNone = 0, + SettingDependencyOperatorEquals, + SettingDependencyOperatorContains +} SettingDependencyOperator; + +typedef enum { + SettingDependencyTargetNone = 0, + SettingDependencyTargetSetting, + SettingDependencyTargetProperty +} SettingDependencyTarget; + +class CSettingDependencyCondition : public CSettingConditionItem +{ +public: + CSettingDependencyCondition(CSettingsManager *settingsManager = NULL) + : CSettingConditionItem(settingsManager), + m_operator(SettingDependencyOperatorEquals) + { } + virtual ~CSettingDependencyCondition() { } + + virtual bool Deserialize(const TiXmlNode *node); + virtual bool Check() const; + + const std::string& GetName() const { return m_name; } + const std::string& GetSetting() const { return m_setting; } + const SettingDependencyTarget GetTarget() const { return m_target; } + const SettingDependencyOperator GetOperator() const { return m_operator; } + +private: + bool setTarget(const std::string &target); + bool setOperator(const std::string &op); + + SettingDependencyTarget m_target; + SettingDependencyOperator m_operator; +}; + +class CSettingDependencyConditionCombination : public CSettingConditionCombination +{ +public: + CSettingDependencyConditionCombination(CSettingsManager *settingsManager = NULL) + : CSettingConditionCombination(settingsManager) + { } + virtual ~CSettingDependencyConditionCombination() { } + + virtual bool Deserialize(const TiXmlNode *node); + + const std::set<std::string>& GetSettings() const { return m_settings; } + +private: + virtual CBooleanLogicOperation* newOperation() { return new CSettingDependencyConditionCombination(m_settingsManager); } + virtual CBooleanLogicValue* newValue() { return new CSettingDependencyCondition(m_settingsManager); } + + std::set<std::string> m_settings; +}; + +class CSettingDependency : public CSettingCondition +{ +public: + CSettingDependency(CSettingsManager *settingsManager = NULL); + virtual ~CSettingDependency() { } + + virtual bool Deserialize(const TiXmlNode *node); + + SettingDependencyType GetType() const { return m_type; } + std::set<std::string> GetSettings() const; + +private: + bool setType(const std::string &type); + + SettingDependencyType m_type; +}; + +typedef std::list<CSettingDependency> SettingDependencies; +typedef std::map<std::string, SettingDependencies> SettingDependencyMap; diff --git a/xbmc/settings/SettingPath.cpp b/xbmc/settings/SettingPath.cpp new file mode 100644 index 0000000000..26b331a654 --- /dev/null +++ b/xbmc/settings/SettingPath.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2013 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 "SettingPath.h" +#include "settings/SettingsManager.h" +#include "threads/SingleLock.h" +#include "utils/log.h" +#include "utils/StringUtils.h" +#include "utils/XBMCTinyXML.h" +#include "utils/XMLUtils.h" + +#define XML_ELM_DEFAULT "default" +#define XML_ELM_CONSTRAINTS "constraints" + +CSettingPath::CSettingPath(const std::string &id, CSettingsManager *settingsManager /* = NULL */) + : CSettingString(id, settingsManager), + m_writable(true) +{ + m_control.SetType(SettingControlTypeButton); + m_control.SetFormat(SettingControlFormatPath); + m_control.SetAttributes(SettingControlAttributeNone); +} + +CSettingPath::CSettingPath(const std::string &id, const CSettingPath &setting) + : CSettingString(id, setting) +{ + copy(setting); +} + +bool CSettingPath::Deserialize(const TiXmlNode *node, bool update /* = false */) +{ + CSingleLock lock(m_critical); + + if (!CSettingString::Deserialize(node, update)) + return false; + + if (m_control.GetType() != SettingControlTypeButton || + m_control.GetFormat() != SettingControlFormatPath || + m_control.GetAttributes() != SettingControlAttributeNone) + { + CLog::Log(LOGERROR, "CSettingPath: invalid <control> of \"%s\"", m_id.c_str()); + return false; + } + + // get the default value by abusing the FromString + // implementation to parse the default value + CStdString value; + if (XMLUtils::GetString(node, XML_ELM_DEFAULT, value)) + m_value = m_default = value; + else if (!update && !m_allowEmpty) + { + CLog::Log(LOGERROR, "CSettingPath: error reading the default value of \"%s\"", m_id.c_str()); + return false; + } + + const TiXmlNode *constraints = node->FirstChild(XML_ELM_CONSTRAINTS); + if (constraints != NULL) + { + // get writable + XMLUtils::GetBoolean(constraints, "writable", m_writable); + + // get sources + const TiXmlNode *sources = constraints->FirstChild("sources"); + if (sources != NULL) + { + m_sources.clear(); + const TiXmlNode *source = sources->FirstChild("source"); + while (source != NULL) + { + std::string strSource = source->FirstChild()->ValueStr(); + if (!strSource.empty()) + m_sources.push_back(strSource); + + source = source->NextSibling("source"); + } + } + } + + return true; +} + +bool CSettingPath::SetValue(const std::string &value) +{ + // for backwards compatibility to Frodo + if (StringUtils::EqualsNoCase(value, "select folder") || + StringUtils::EqualsNoCase(value, "select writable folder")) + return CSettingString::SetValue(""); + + return CSettingString::SetValue(value); +} + +void CSettingPath::copy(const CSettingPath &setting) +{ + CSettingString::Copy(setting); + + m_writable = setting.m_writable; + m_sources = setting.m_sources; +} diff --git a/xbmc/settings/SettingPath.h b/xbmc/settings/SettingPath.h new file mode 100644 index 0000000000..714913244c --- /dev/null +++ b/xbmc/settings/SettingPath.h @@ -0,0 +1,44 @@ +#pragma once +/* + * Copyright (C) 2013 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 <vector> + +#include "Setting.h" + +class CSettingPath : public CSettingString +{ +public: + CSettingPath(const std::string &id, CSettingsManager *settingsManager = NULL); + CSettingPath(const std::string &id, const CSettingPath &setting); + virtual ~CSettingPath() { } + + virtual bool Deserialize(const TiXmlNode *node, bool update = false); + virtual bool SetValue(const std::string &value); + + bool Writable() const { return m_writable; } + const std::vector<std::string>& GetSources() const { return m_sources; } + +private: + void copy(const CSettingPath &setting); + + bool m_writable; + std::vector<std::string> m_sources; +}; diff --git a/xbmc/settings/SettingSection.cpp b/xbmc/settings/SettingSection.cpp new file mode 100644 index 0000000000..fa8ed07ad5 --- /dev/null +++ b/xbmc/settings/SettingSection.cpp @@ -0,0 +1,315 @@ +/* + * Copyright (C) 2013 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 "SettingSection.h" +#include "SettingsManager.h" +#include "utils/log.h" +#include "utils/StringUtils.h" +#include "utils/XBMCTinyXML.h" + +#define XML_CATEGORY "category" +#define XML_GROUP "group" + +template<class T> void addISetting(const TiXmlNode *node, const T &item, std::vector<T> &items) +{ + if (node == NULL) + return; + + const TiXmlElement *element = node->ToElement(); + if (element == NULL) + return; + + // check if there is a "before" or "after" attribute to place the setting at a specific position + int position = -1; // -1 => end, 0 => before, 1 => after + const char *positionId = element->Attribute("before"); + if (positionId != NULL && strlen(positionId) > 0) + position = 0; + else if ((positionId = element->Attribute("after")) != NULL && strlen(positionId) > 0) + position = 1; + + if (positionId != NULL && strlen(positionId) > 0 && position >= 0) + { + for (typename std::vector<T>::iterator it = items.begin(); it != items.end(); it++) + { + if (!StringUtils::EqualsNoCase((*it)->GetId(), positionId)) + continue; + + typename std::vector<T>::iterator positionIt = it; + if (position == 1) + positionIt++; + + items.insert(positionIt, item); + return; + } + } + + items.push_back(item); +} + +CSettingGroup::CSettingGroup(const std::string &id, CSettingsManager *settingsManager /* = NULL */) + : ISetting(id, settingsManager) +{ } + +CSettingGroup::~CSettingGroup() +{ + for (SettingList::const_iterator setting = m_settings.begin(); setting != m_settings.end(); setting++) + delete *setting; + m_settings.clear(); +} + +bool CSettingGroup::Deserialize(const TiXmlNode *node, bool update /* = false */) +{ + // handle <visible> conditions + if (!ISetting::Deserialize(node, update)) + return false; + + const TiXmlElement *settingElement = node->FirstChildElement(XML_SETTING); + while (settingElement != NULL) + { + std::string settingId; + if (CSettingCategory::DeserializeIdentification(settingElement, settingId)) + { + CSetting *setting = NULL; + for (SettingList::iterator itSetting = m_settings.begin(); itSetting != m_settings.end(); itSetting++) + { + if ((*itSetting)->GetId() == settingId) + { + setting = *itSetting; + break; + } + } + + update = (setting != NULL); + if (!update) + { + const char* settingType = settingElement->Attribute(XML_ATTR_TYPE); + if (settingType == NULL || strlen(settingType) <= 0) + { + CLog::Log(LOGERROR, "CSettingGroup: unable to read setting type of \"%s\"", settingId.c_str()); + return false; + } + + setting = m_settingsManager->CreateSetting(settingType, settingId, m_settingsManager); + if (setting == NULL) + CLog::Log(LOGERROR, "CSettingGroup: unknown setting type \"%s\" of \"%s\"", settingType, settingId.c_str()); + } + + if (setting == NULL) + CLog::Log(LOGERROR, "CSettingGroup: unable to create new setting \"%s\"", settingId.c_str()); + else if (!setting->Deserialize(settingElement, update)) + { + CLog::Log(LOGWARNING, "CSettingGroup: unable to read setting \"%s\"", settingId.c_str()); + if (!update) + delete setting; + } + else if (!update) + addISetting(settingElement, setting, m_settings); + } + + settingElement = settingElement->NextSiblingElement(XML_SETTING); + } + + return true; +} + +SettingList CSettingGroup::GetSettings(SettingLevel level) const +{ + SettingList settings; + + for (SettingList::const_iterator it = m_settings.begin(); it != m_settings.end(); it++) + { + if ((*it)->GetLevel() <= level && (*it)->IsVisible()) + settings.push_back(*it); + } + + return settings; +} + +CSettingCategory::CSettingCategory(const std::string &id, CSettingsManager *settingsManager /* = NULL */) + : ISetting(id, settingsManager), + m_label(-1), m_help(-1), + m_accessCondition(settingsManager) +{ } + +CSettingCategory::~CSettingCategory() +{ + for (SettingGroupList::const_iterator it = m_groups.begin(); it != m_groups.end(); it++) + delete *it; + + m_groups.clear(); +} + +bool CSettingCategory::Deserialize(const TiXmlNode *node, bool update /* = false */) +{ + // handle <visible> conditions + if (!ISetting::Deserialize(node, update)) + return false; + + const TiXmlElement *element = node->ToElement(); + if (element == NULL) + return false; + + int tmp = -1; + if (element->QueryIntAttribute(XML_ATTR_LABEL, &tmp) == TIXML_SUCCESS && tmp > 0) + m_label = tmp; + if (element->QueryIntAttribute(XML_ATTR_HELP, &m_help) == TIXML_SUCCESS && m_help > 0) + m_help = tmp; + + const TiXmlNode *accessNode = node->FirstChild("access"); + if (accessNode != NULL && !m_accessCondition.Deserialize(accessNode)) + return false; + + const TiXmlNode *groupNode = node->FirstChildElement(XML_GROUP); + while (groupNode != NULL) + { + std::string groupId; + if (CSettingGroup::DeserializeIdentification(groupNode, groupId)) + { + CSettingGroup *group = NULL; + for (SettingGroupList::iterator itGroup = m_groups.begin(); itGroup != m_groups.end(); itGroup++) + { + if ((*itGroup)->GetId() == groupId) + { + group = *itGroup; + break; + } + } + + update = (group != NULL); + if (!update) + group = new CSettingGroup(groupId, m_settingsManager); + + if (group->Deserialize(groupNode, update)) + { + if (!update) + addISetting(groupNode, group, m_groups); + } + else + { + CLog::Log(LOGWARNING, "CSettingCategory: unable to read group \"%s\"", groupId.c_str()); + if (!update) + delete group; + } + } + + groupNode = groupNode->NextSibling(XML_GROUP); + } + + return true; +} + +SettingGroupList CSettingCategory::GetGroups(SettingLevel level) const +{ + SettingGroupList groups; + + for (SettingGroupList::const_iterator it = m_groups.begin(); it != m_groups.end(); it++) + { + if ((*it)->IsVisible() && (*it)->GetSettings(level).size() > 0) + groups.push_back(*it); + } + + return groups; +} + +bool CSettingCategory::CanAccess() const +{ + return m_accessCondition.Check(); +} + +CSettingSection::CSettingSection(const std::string &id, CSettingsManager *settingsManager /* = NULL */) + : ISetting(id, settingsManager), + m_label(-1), m_help(-1) +{ } + +CSettingSection::~CSettingSection() +{ + for (SettingCategoryList::const_iterator it = m_categories.begin(); it != m_categories.end(); it++) + delete *it; + + m_categories.clear(); +} + +bool CSettingSection::Deserialize(const TiXmlNode *node, bool update /* = false */) +{ + // handle <visible> conditions + if (!ISetting::Deserialize(node, update)) + return false; + + const TiXmlElement *element = node->ToElement(); + if (element == NULL) + return false; + + int tmp = -1; + if (element->QueryIntAttribute(XML_ATTR_LABEL, &tmp) == TIXML_SUCCESS && tmp > 0) + m_label = tmp; + if (element->QueryIntAttribute(XML_ATTR_HELP, &tmp) == TIXML_SUCCESS && tmp > 0) + m_help = tmp; + + const TiXmlNode *categoryNode = node->FirstChild(XML_CATEGORY); + while (categoryNode != NULL) + { + std::string categoryId; + if (CSettingCategory::DeserializeIdentification(categoryNode, categoryId)) + { + CSettingCategory *category = NULL; + for (SettingCategoryList::iterator itCategory = m_categories.begin(); itCategory != m_categories.end(); itCategory++) + { + if ((*itCategory)->GetId() == categoryId) + { + category = *itCategory; + break; + } + } + + update = (category != NULL); + if (!update) + category = new CSettingCategory(categoryId, m_settingsManager); + + if (category->Deserialize(categoryNode, update)) + { + if (!update) + addISetting(categoryNode, category, m_categories); + } + else + { + CLog::Log(LOGWARNING, "CSettingSection: unable to read category \"%s\"", categoryId.c_str()); + if (!update) + delete category; + } + } + + categoryNode = categoryNode->NextSibling(XML_CATEGORY); + } + + return true; +} + +SettingCategoryList CSettingSection::GetCategories(SettingLevel level) const +{ + SettingCategoryList categories; + + for (SettingCategoryList::const_iterator it = m_categories.begin(); it != m_categories.end(); it++) + { + if ((*it)->IsVisible() && (*it)->GetGroups(level).size() > 0) + categories.push_back(*it); + } + + return categories; +} diff --git a/xbmc/settings/SettingSection.h b/xbmc/settings/SettingSection.h new file mode 100644 index 0000000000..7c0553a7e1 --- /dev/null +++ b/xbmc/settings/SettingSection.h @@ -0,0 +1,191 @@ +#pragma once +/* + * Copyright (C) 2013 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 <string> +#include <vector> + +#include "ISetting.h" +#include "Setting.h" +#include "SettingCategoryAccess.h" + +class CSettingsManager; + +/*! + \ingroup settings + \brief Group of settings being part of a category + \sa CSettingCategory + \sa CSetting + */ +class CSettingGroup : public ISetting +{ +public: + /*! + \brief Creates a new setting group with the given identifier. + + \param id Identifier of the setting group + \param settingsManager Reference to the settings manager + */ + CSettingGroup(const std::string &id, CSettingsManager *settingsManager = NULL); + ~CSettingGroup(); + + // implementation of ISetting + virtual bool Deserialize(const TiXmlNode *node, bool update = false); + + /*! + \brief Gets the full list of settings belonging to the setting group. + + \return Full list of settings belonging to the setting group + */ + const SettingList& GetSettings() const { return m_settings; } + /*! + \brief Gets the list of settings assigned to the given setting level (or + below) belonging to the setting group. + + \param level Level the settings should be assigned to + \return List of settings belonging to the setting group + */ + SettingList GetSettings(SettingLevel level) const; + +private: + SettingList m_settings; +}; + +typedef std::vector<CSettingGroup *> SettingGroupList; + +/*! + \ingroup settings + \brief Category of groups of settings being part of a section + \sa CSettingSection + \sa CSettingGroup + */ +class CSettingCategory : public ISetting +{ +public: + /*! + \brief Creates a new setting category with the given identifier. + + \param id Identifier of the setting category + \param settingsManager Reference to the settings manager + */ + CSettingCategory(const std::string &id, CSettingsManager *settingsManager = NULL); + ~CSettingCategory(); + + // implementation of ISetting + virtual bool Deserialize(const TiXmlNode *node, bool update = false); + + /*! + \brief Gets the localizeable label ID of the setting category. + + \return Localizeable label ID of the setting category + */ + const int GetLabel() const { return m_label; } + /*! + \brief Gets the localizeable help ID of the setting category. + + \return Localizeable help ID of the setting category + */ + const int GetHelp() const { return m_help; } + /*! + \brief Gets the full list of setting groups belonging to the setting + category. + + \return Full list of setting groups belonging to the setting category + */ + const SettingGroupList& GetGroups() const { return m_groups; } + /*! + \brief Gets the list of setting groups belonging to the setting category + that contain settings assigned to the given setting level (or below). + + \param level Level the settings should be assigned to + \return List of setting groups belonging to the setting category + */ + SettingGroupList GetGroups(SettingLevel level) const; + + /*! + \brief Whether the setting category can be accessed or not. + + \return True if the setting category can be accessed, false otherwise + */ + bool CanAccess() const; + +private: + int m_label; + int m_help; + SettingGroupList m_groups; + CSettingCategoryAccess m_accessCondition; +}; + +typedef std::vector<CSettingCategory *> SettingCategoryList; + +/*! + \ingroup settings + \brief Section of setting categories + \sa CSettings + \sa CSettingCategory + */ +class CSettingSection : public ISetting +{ +public: + /*! + \brief Creates a new setting section with the given identifier. + + \param id Identifier of the setting section + \param settingsManager Reference to the settings manager + */ + CSettingSection(const std::string &id, CSettingsManager *settingsManager = NULL); + ~CSettingSection(); + + // implementation of ISetting + virtual bool Deserialize(const TiXmlNode *node, bool update = false); + + /*! + \brief Gets the localizeable label ID of the setting section. + + \return Localizeable label ID of the setting section + */ + const int GetLabel() const { return m_label; } + /*! + \brief Gets the localizeable help ID of the setting section. + + \return Localizeable help ID of the setting section + */ + const int GetHelp() const { return m_help; } + /*! + \brief Gets the full list of setting categories belonging to the setting + section. + + \return Full list of setting categories belonging to the setting section + */ + const SettingCategoryList& GetCategories() const { return m_categories; } + /*! + \brief Gets the list of setting categories belonging to the setting section + that contain settings assigned to the given setting level (or below). + + \param level Level the settings should be assigned to + \return List of setting categories belonging to the setting section + */ + SettingCategoryList GetCategories(SettingLevel level) const; + +private: + int m_label; + int m_help; + SettingCategoryList m_categories; +}; diff --git a/xbmc/settings/SettingUpdate.cpp b/xbmc/settings/SettingUpdate.cpp new file mode 100644 index 0000000000..43ce87e9d8 --- /dev/null +++ b/xbmc/settings/SettingUpdate.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2013 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 "SettingUpdate.h" +#include "utils/log.h" +#include "utils/StringUtils.h" +#include "utils/XBMCTinyXML.h" + +CSettingUpdate::CSettingUpdate() + : m_type(SettingUpdateTypeNone) +{ } + +bool CSettingUpdate::operator<(const CSettingUpdate& rhs) const +{ + return m_type < rhs.m_type && m_value < rhs.m_value; +} + +bool CSettingUpdate::Deserialize(const TiXmlNode *node) +{ + if (node == NULL) + return false; + + const TiXmlElement *elem = node->ToElement(); + if (elem == NULL) + return false; + + const char *strType = elem->Attribute("type"); + if (strType == NULL || strlen(strType) <= 0 || !setType(strType)) + { + CLog::Log(LOGWARNING, "CSettingUpdate: missing or unknown update type definition"); + return false; + } + + if (m_type == SettingUpdateTypeRename) + { + if (node->FirstChild() == NULL || node->FirstChild()->Type() != TiXmlNode::TINYXML_TEXT) + { + CLog::Log(LOGWARNING, "CSettingUpdate: missing or invalid setting id for rename update definition"); + return false; + } + + m_value = node->FirstChild()->ValueStr(); + } + + return true; +} + +bool CSettingUpdate::setType(const std::string &type) +{ + if (StringUtils::EqualsNoCase(type, "change")) + m_type = SettingUpdateTypeChange; + else if (StringUtils::EqualsNoCase(type, "rename")) + m_type = SettingUpdateTypeRename; + else + return false; + + return true; +} diff --git a/xbmc/settings/SettingUpdate.h b/xbmc/settings/SettingUpdate.h new file mode 100644 index 0000000000..e8ad966b58 --- /dev/null +++ b/xbmc/settings/SettingUpdate.h @@ -0,0 +1,50 @@ +#pragma once +/* + * Copyright (C) 2013 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 <string> + +class TiXmlNode; + +typedef enum { + SettingUpdateTypeNone = 0, + SettingUpdateTypeRename, + SettingUpdateTypeChange +} SettingUpdateType; + +class CSettingUpdate +{ +public: + CSettingUpdate(); + virtual ~CSettingUpdate() { } + + bool operator<(const CSettingUpdate& rhs) const; + + virtual bool Deserialize(const TiXmlNode *node); + + SettingUpdateType GetType() const { return m_type; } + const std::string& GetValue() const { return m_value; } + +private: + bool setType(const std::string &type); + + SettingUpdateType m_type; + std::string m_value; +}; diff --git a/xbmc/settings/SettingVisibility.cpp b/xbmc/settings/SettingVisibility.cpp new file mode 100644 index 0000000000..a702a6d14f --- /dev/null +++ b/xbmc/settings/SettingVisibility.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2013 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 "SettingVisibility.h" +#include "SettingsManager.h" + +bool CSettingVisibilityCondition::Check() const +{ + if (m_settingsManager == NULL) + return false; + + bool found = m_settingsManager->GetConditions().Check("IsDefined", m_value); + if (m_negated) + return !found; + + return found; +} + +bool CSettingVisibilityConditionCombination::Check() const +{ + if (m_operations.empty() && m_values.empty()) + return true; + + return CSettingConditionCombination::Check(); +} + +CSettingVisibility::CSettingVisibility(CSettingsManager *settingsManager /* = NULL */) + : CSettingCondition(settingsManager) +{ + m_operation = CBooleanLogicOperationPtr(new CSettingVisibilityConditionCombination(m_settingsManager)); +} diff --git a/xbmc/settings/SettingVisibility.h b/xbmc/settings/SettingVisibility.h new file mode 100644 index 0000000000..6f48e9998b --- /dev/null +++ b/xbmc/settings/SettingVisibility.h @@ -0,0 +1,58 @@ +#pragma once +/* + * Copyright (C) 2013 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 <set> +#include <string> + +#include "SettingConditions.h" + +class CSettingVisibilityCondition : public CSettingConditionItem +{ +public: + CSettingVisibilityCondition(CSettingsManager *settingsManager = NULL) + : CSettingConditionItem(settingsManager) + { } + virtual ~CSettingVisibilityCondition() { } + + virtual bool Check() const; +}; + +class CSettingVisibilityConditionCombination : public CSettingConditionCombination +{ +public: + CSettingVisibilityConditionCombination(CSettingsManager *settingsManager = NULL) + : CSettingConditionCombination(settingsManager) + { } + virtual ~CSettingVisibilityConditionCombination() { } + + virtual bool Check() const; + +private: + virtual CBooleanLogicOperation* newOperation() { return new CSettingVisibilityConditionCombination(m_settingsManager); } + virtual CBooleanLogicValue* newValue() { return new CSettingVisibilityCondition(m_settingsManager); } +}; + +class CSettingVisibility : public CSettingCondition +{ +public: + CSettingVisibility(CSettingsManager *settingsManager = NULL); + virtual ~CSettingVisibility() { } +}; diff --git a/xbmc/settings/Settings.cpp b/xbmc/settings/Settings.cpp index 1083e236a5..0f2b1b2f69 100644 --- a/xbmc/settings/Settings.cpp +++ b/xbmc/settings/Settings.cpp @@ -18,216 +18,961 @@ * */ +#include "system.h" + #include "Settings.h" +#include "Application.h" +#include "Autorun.h" +#include "GUIPassword.h" +#include "LangInfo.h" +#include "Util.h" +#include "addons/AddonManager.h" +#include "addons/Skin.h" +#include "cores/AudioEngine/AEFactory.h" +#if defined(HAVE_LIBCRYSTALHD) +#include "cores/dvdplayer/DVDCodecs/Video/CrystalHD.h" +#endif // defined(HAVE_LIBCRYSTALHD) +#include "cores/playercorefactory/PlayerCoreFactory.h" +#include "cores/VideoRenderers/BaseRenderer.h" #include "filesystem/File.h" +#include "guilib/GraphicContext.h" +#include "guilib/GUIAudioManager.h" +#include "guilib/GUIFontManager.h" +#include "guilib/LocalizeStrings.h" +#include "input/MouseStat.h" +#if defined(TARGET_WINDOWS) +#include "input/windows/WINJoystick.h" +#elif defined(HAS_SDL_JOYSTICK) +#include "input/SDLJoystick.h" +#endif // defined(HAS_SDL_JOYSTICK) +#if defined(TARGET_LINUX) +#include "linux/LinuxTimezone.h" +#endif // defined(TARGET_LINUX) +#include "network/NetworkServices.h" +#include "network/upnp/UPnPSettings.h" +#if defined(TARGET_DARWIN_OSX) +#include "osx/XBMCHelper.h" +#include "cores/AudioEngine/Engines/CoreAudio/CoreAudioHardware.h" +#endif // defined(TARGET_DARWIN_OSX) +#if defined(TARGET_DARWIN) +#include "osx/DarwinUtils.h" +#endif +#include "peripherals/Peripherals.h" +#include "powermanagement/PowerManager.h" #include "profiles/ProfilesManager.h" -#include "settings/GUISettings.h" +#include "pvr/PVRManager.h" +#include "pvr/windows/GUIWindowPVRGuide.h" +#include "settings/AdvancedSettings.h" +#include "settings/DisplaySettings.h" +#include "settings/MediaSettings.h" +#include "settings/MediaSourceSettings.h" +#include "settings/SettingAddon.h" +#include "settings/SettingsManager.h" +#include "settings/SettingPath.h" +#include "settings/SkinSettings.h" #include "threads/SingleLock.h" +#include "utils/CharsetConverter.h" #include "utils/log.h" +#include "utils/RssManager.h" +#include "utils/StringUtils.h" +#include "utils/SystemInfo.h" +#include "utils/Weather.h" #include "utils/XBMCTinyXML.h" +#include "view/ViewStateSettings.h" +#include "windowing/WindowingFactory.h" + +#define SETTINGS_XML_FOLDER "special://xbmc/system/settings/" +#define SETTINGS_XML_ROOT "settings" -using namespace std; using namespace XFILE; -CSettings::CSettings(void) +bool AddonHasSettings(const std::string &condition, const std::string &value, const std::string &settingId) { + if (settingId.empty()) + return false; + + CSettingAddon *setting = (CSettingAddon*)CSettings::Get().GetSetting(settingId); + if (setting == NULL) + return false; + + ADDON::AddonPtr addon; + if (!ADDON::CAddonMgr::Get().GetAddon(setting->GetValue(), addon, setting->GetAddonType()) || addon == NULL) + return false; + + return addon->HasSettings(); } -void CSettings::RegisterSettingsHandler(ISettingsHandler *settingsHandler) +bool CheckMasterLock(const std::string &condition, const std::string &value, const std::string &settingId) { - if (settingsHandler == NULL) - return; + return g_passwordManager.IsMasterLockUnlocked(StringUtils::EqualsNoCase(value, "true")); +} - CSingleLock lock(m_critical); - m_settingsHandlers.insert(settingsHandler); +bool CheckPVRParentalPin(const std::string &condition, const std::string &value, const std::string &settingId) +{ + return PVR::g_PVRManager.CheckParentalPIN(g_localizeStrings.Get(19262).c_str()); } -void CSettings::UnregisterSettingsHandler(ISettingsHandler *settingsHandler) +bool HasPeripherals(const std::string &condition, const std::string &value, const std::string &settingId) { - if (settingsHandler == NULL) - return; + return PERIPHERALS::g_peripherals.GetNumberOfPeripherals() > 0; +} - CSingleLock lock(m_critical); - m_settingsHandlers.erase(settingsHandler); +bool IsFullscreen(const std::string &condition, const std::string &value, const std::string &settingId) +{ + return g_Windowing.IsFullScreen(); } -void CSettings::RegisterSubSettings(ISubSettings *subSettings) +bool IsMasterUser(const std::string &condition, const std::string &value, const std::string &settingId) { - if (subSettings == NULL) - return; + return g_passwordManager.bMasterUser; +} - CSingleLock lock(m_critical); - m_subSettings.insert(subSettings); +bool IsUsingTTFSubtitles(const std::string &condition, const std::string &value, const std::string &settingId) +{ + return CUtil::IsUsingTTFSubtitles(); } -void CSettings::UnregisterSubSettings(ISubSettings *subSettings) +bool ProfileCanWriteDatabase(const std::string &condition, const std::string &value, const std::string &settingId) { - if (subSettings == NULL) - return; + return CProfilesManager::Get().GetCurrentProfile().canWriteDatabases(); +} - CSingleLock lock(m_critical); - m_subSettings.erase(subSettings); +bool ProfileCanWriteSources(const std::string &condition, const std::string &value, const std::string &settingId) +{ + return CProfilesManager::Get().GetCurrentProfile().canWriteSources(); } -CSettings::~CSettings(void) +bool ProfileHasAddons(const std::string &condition, const std::string &value, const std::string &settingId) { - // first clear all registered settings handler and subsettings - // implementations because we can't be sure that they are still valid - m_settingsHandlers.clear(); - m_subSettings.clear(); + return CProfilesManager::Get().GetCurrentProfile().hasAddons(); +} - Clear(); +bool ProfileHasDatabase(const std::string &condition, const std::string &value, const std::string &settingId) +{ + return CProfilesManager::Get().GetCurrentProfile().hasDatabases(); } -void CSettings::Save() const +bool ProfileHasSources(const std::string &condition, const std::string &value, const std::string &settingId) { - if (!SaveSettings(CProfilesManager::Get().GetSettingsFile())) - CLog::Log(LOGERROR, "Unable to save settings to %s", CProfilesManager::Get().GetSettingsFile().c_str()); + return CProfilesManager::Get().GetCurrentProfile().hasSources(); } -bool CSettings::Reset() +bool ProfileHasAddonManagerLocked(const std::string &condition, const std::string &value, const std::string &settingId) { - CLog::Log(LOGINFO, "Resetting settings"); - CFile::Delete(CProfilesManager::Get().GetSettingsFile()); - Save(); - return LoadSettings(CProfilesManager::Get().GetSettingsFile()); + return CProfilesManager::Get().GetCurrentProfile().addonmanagerLocked(); } -bool CSettings::Load() +bool ProfileHasFilesLocked(const std::string &condition, const std::string &value, const std::string &settingId) +{ + return CProfilesManager::Get().GetCurrentProfile().filesLocked(); +} + +bool ProfileHasMusicLocked(const std::string &condition, const std::string &value, const std::string &settingId) +{ + return CProfilesManager::Get().GetCurrentProfile().musicLocked(); +} + +bool ProfileHasPicturesLocked(const std::string &condition, const std::string &value, const std::string &settingId) +{ + return CProfilesManager::Get().GetCurrentProfile().picturesLocked(); +} + +bool ProfileHasProgramsLocked(const std::string &condition, const std::string &value, const std::string &settingId) +{ + return CProfilesManager::Get().GetCurrentProfile().programsLocked(); +} + +bool ProfileHasSettingsLocked(const std::string &condition, const std::string &value, const std::string &settingId) +{ + return CProfilesManager::Get().GetCurrentProfile().settingsLocked(); +} + +bool ProfileHasVideosLocked(const std::string &condition, const std::string &value, const std::string &settingId) +{ + return CProfilesManager::Get().GetCurrentProfile().videoLocked(); +} + +bool ProfileLockMode(const std::string &condition, const std::string &value, const std::string &settingId) +{ + char *tmp = NULL; + LockType lock = (LockType)strtol(value.c_str(), &tmp, 0); + if (tmp != NULL && *tmp != '\0') + return false; + + return CProfilesManager::Get().GetCurrentProfile().getLockMode() == lock; +} + +CSettings::CSettings() + : m_initialized(false) +{ + m_settingsManager = new CSettingsManager(); +} + +CSettings::~CSettings() +{ + Uninitialize(); + + delete m_settingsManager; +} + +CSettings& CSettings::Get() +{ + static CSettings sSettings; + return sSettings; +} + +CSetting* CSettings::CreateSetting(const std::string &settingType, const std::string &settingId, CSettingsManager *settingsManager /* = NULL */) const +{ + if (StringUtils::EqualsNoCase(settingType, "addon")) + return new CSettingAddon(settingId, settingsManager); + else if (StringUtils::EqualsNoCase(settingType, "path")) + return new CSettingPath(settingId, settingsManager); + + return NULL; +} + +bool CSettings::Initialize() { - if (!OnSettingsLoading()) + CSingleLock lock(m_critical); + if (m_initialized) return false; - CLog::Log(LOGNOTICE, "loading %s", CProfilesManager::Get().GetSettingsFile().c_str()); - if (!LoadSettings(CProfilesManager::Get().GetSettingsFile())) + // register custom setting types + InitializeSettingTypes(); + + // option fillers and conditions need to be + // initialized before the setting definitions + InitializeOptionFillers(); + InitializeConditions(); + + // load the settings definitions + if (!InitializeDefinitions()) + return false; + + InitializeVisibility(); + InitializeDefaults(); + m_settingsManager->SetInitialized(); + + InitializeISettingsHandlers(); + InitializeISubSettings(); + InitializeISettingCallbacks(); + + m_initialized = true; + + return true; +} + +bool CSettings::Load() +{ + return Load(CProfilesManager::Get().GetSettingsFile()); +} + +bool CSettings::Load(const std::string &file) +{ + CXBMCTinyXML xmlDoc; + bool updated = false; + if (!XFILE::CFile::Exists(file) || !xmlDoc.LoadFile(file) || + !m_settingsManager->Load(xmlDoc.RootElement(), updated)) { - CLog::Log(LOGERROR, "Unable to load %s, creating new %s with default values", CProfilesManager::Get().GetSettingsFile().c_str(), CProfilesManager::Get().GetSettingsFile().c_str()); + CLog::Log(LOGERROR, "CSettingsManager: unable to load settings from %s, creating new default settings", file.c_str()); if (!Reset()) return false; - } - OnSettingsLoaded(); + if (!Load(file)) + return false; + } + // if the settings had to be updated, we need to save the changes + else if (updated) + return Save(file); return true; } -bool CSettings::LoadSettings(const CStdString& strSettingsFile) +bool CSettings::Load(const TiXmlElement *root, bool hide /* = false */) { - // load the xml file - CXBMCTinyXML xmlDoc; - if (!xmlDoc.LoadFile(strSettingsFile)) - { - CLog::Log(LOGERROR, "%s, Line %d\n%s", strSettingsFile.c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc()); + if (root == NULL) return false; - } - TiXmlElement *pRootElement = xmlDoc.RootElement(); - if (strcmpi(pRootElement->Value(), "settings") != 0) + std::map<std::string, CSetting*> *loadedSettings = NULL; + if (hide) + loadedSettings = new std::map<std::string, CSetting*>(); + + bool updated; + // only trigger settings events if hiding is disabled + bool success = m_settingsManager->Load(root, updated, !hide, loadedSettings); + // if necessary hide all the loaded settings + if (success && hide && loadedSettings != NULL) { - CLog::Log(LOGERROR, "%s\nDoesn't contain <settings>", strSettingsFile.c_str()); - return false; + for(std::map<std::string, CSetting*>::const_iterator setting = loadedSettings->begin(); setting != loadedSettings->end(); setting++) + setting->second->SetVisible(false); + + delete loadedSettings; } - g_guiSettings.LoadXML(pRootElement); - - // load any ISubSettings implementations - return Load(pRootElement); + return success; +} + +void CSettings::SetLoaded() +{ + m_settingsManager->SetLoaded(); +} + +bool CSettings::Save() +{ + return Save(CProfilesManager::Get().GetSettingsFile()); } -bool CSettings::SaveSettings(const CStdString& strSettingsFile, CGUISettings *localSettings /* = NULL */) const +bool CSettings::Save(const std::string &file) { CXBMCTinyXML xmlDoc; - TiXmlElement xmlRootElement("settings"); - TiXmlNode *pRoot = xmlDoc.InsertEndChild(xmlRootElement); - if (!pRoot) return false; - // write our tags one by one - just a big list for now (can be flashed up later) + TiXmlElement rootElement(SETTINGS_XML_ROOT); + TiXmlNode *root = xmlDoc.InsertEndChild(rootElement); + if (root == NULL) + return false; - if (!OnSettingsSaving()) + if (!m_settingsManager->Save(root)) return false; - if (localSettings) // local settings to save - localSettings->SaveXML(pRoot); - else // save the global settings - g_guiSettings.SaveXML(pRoot); + return xmlDoc.SaveFile(file); +} - OnSettingsSaved(); - - if (!Save(pRoot)) - return false; +void CSettings::Unload() +{ + CSingleLock lock(m_critical); + m_settingsManager->Unload(); +} + +void CSettings::Uninitialize() +{ + CSingleLock lock(m_critical); + if (!m_initialized) + return; + + // unregister setting option fillers + m_settingsManager->UnregisterSettingOptionsFiller("audiocdactions"); + m_settingsManager->UnregisterSettingOptionsFiller("audiocdencoders"); + m_settingsManager->UnregisterSettingOptionsFiller("audiodevices"); + m_settingsManager->UnregisterSettingOptionsFiller("audiodevicespassthrough"); + m_settingsManager->UnregisterSettingOptionsFiller("audiooutputmodes"); + m_settingsManager->UnregisterSettingOptionsFiller("charsets"); + m_settingsManager->UnregisterSettingOptionsFiller("epgguideviews"); + m_settingsManager->UnregisterSettingOptionsFiller("fontheights"); + m_settingsManager->UnregisterSettingOptionsFiller("fonts"); + m_settingsManager->UnregisterSettingOptionsFiller("languages"); + m_settingsManager->UnregisterSettingOptionsFiller("pvrstartlastchannel"); + m_settingsManager->UnregisterSettingOptionsFiller("refreshchangedelays"); + m_settingsManager->UnregisterSettingOptionsFiller("refreshrates"); + m_settingsManager->UnregisterSettingOptionsFiller("regions"); + m_settingsManager->UnregisterSettingOptionsFiller("rendermethods"); + m_settingsManager->UnregisterSettingOptionsFiller("resolutions"); + m_settingsManager->UnregisterSettingOptionsFiller("screens"); + m_settingsManager->UnregisterSettingOptionsFiller("shutdownstates"); + m_settingsManager->UnregisterSettingOptionsFiller("startupwindows"); + m_settingsManager->UnregisterSettingOptionsFiller("streamlanguages"); + m_settingsManager->UnregisterSettingOptionsFiller("skincolors"); + m_settingsManager->UnregisterSettingOptionsFiller("skinfonts"); + m_settingsManager->UnregisterSettingOptionsFiller("skinsounds"); + m_settingsManager->UnregisterSettingOptionsFiller("skinthemes"); +#if defined(TARGET_LINUX) + m_settingsManager->UnregisterSettingOptionsFiller("timezonecountries"); + m_settingsManager->UnregisterSettingOptionsFiller("timezones"); +#endif // defined(TARGET_LINUX) + m_settingsManager->UnregisterSettingOptionsFiller("verticalsyncs"); + + // unregister ISettingCallback implementations + m_settingsManager->UnregisterCallback(&g_advancedSettings); + m_settingsManager->UnregisterCallback(&CMediaSettings::Get()); + m_settingsManager->UnregisterCallback(&CDisplaySettings::Get()); + m_settingsManager->UnregisterCallback(&g_application); + m_settingsManager->UnregisterCallback(&g_audioManager); + m_settingsManager->UnregisterCallback(&g_charsetConverter); + m_settingsManager->UnregisterCallback(&g_graphicsContext); + m_settingsManager->UnregisterCallback(&g_langInfo); +#if defined(TARGET_WINDOWS) || defined(HAS_SDL_JOYSTICK) + m_settingsManager->UnregisterCallback(&g_Joystick); +#endif + m_settingsManager->UnregisterCallback(&g_Mouse); + m_settingsManager->UnregisterCallback(&CNetworkServices::Get()); + m_settingsManager->UnregisterCallback(&g_passwordManager); + m_settingsManager->UnregisterCallback(&PVR::g_PVRManager); + m_settingsManager->UnregisterCallback(&CRssManager::Get()); +#if defined(TARGET_LINUX) + m_settingsManager->UnregisterCallback(&g_timezone); +#endif // defined(TARGET_LINUX) + m_settingsManager->UnregisterCallback(&g_weatherManager); + m_settingsManager->UnregisterCallback(&PERIPHERALS::CPeripherals::Get()); + + // unregister ISubSettings implementations + m_settingsManager->UnregisterSubSettings(&g_application); + m_settingsManager->UnregisterSubSettings(&CDisplaySettings::Get()); + m_settingsManager->UnregisterSubSettings(&CMediaSettings::Get()); + m_settingsManager->UnregisterSubSettings(&CSkinSettings::Get()); + m_settingsManager->UnregisterSubSettings(&g_sysinfo); + m_settingsManager->UnregisterSubSettings(&CViewStateSettings::Get()); + + // unregister ISettingsHandler implementations + m_settingsManager->UnregisterSettingsHandler(&g_advancedSettings); + m_settingsManager->UnregisterSettingsHandler(&CMediaSourceSettings::Get()); + m_settingsManager->UnregisterSettingsHandler(&CPlayerCoreFactory::Get()); + m_settingsManager->UnregisterSettingsHandler(&CRssManager::Get()); +#ifdef HAS_UPNP + m_settingsManager->UnregisterSettingsHandler(&CUPnPSettings::Get()); +#endif + m_settingsManager->UnregisterSettingsHandler(&CProfilesManager::Get()); + m_settingsManager->UnregisterSettingsHandler(&g_application); + + // cleanup the settings manager + m_settingsManager->Clear(); + + m_initialized = false; +} + +void CSettings::RegisterCallback(ISettingCallback *callback, const std::set<std::string> &settingList) +{ + m_settingsManager->RegisterCallback(callback, settingList); +} - // save the file - return xmlDoc.SaveFile(strSettingsFile); +void CSettings::UnregisterCallback(ISettingCallback *callback) +{ + m_settingsManager->UnregisterCallback(callback); } -void CSettings::Clear() +CSetting* CSettings::GetSetting(const std::string &id) const { - OnSettingsCleared(); + CSingleLock lock(m_critical); + if (id.empty()) + return NULL; - for (SubSettings::const_iterator it = m_subSettings.begin(); it != m_subSettings.end(); it++) - (*it)->Clear(); + return m_settingsManager->GetSetting(id); } -bool CSettings::OnSettingsLoading() +CSettingSection* CSettings::GetSection(const std::string §ion) const { CSingleLock lock(m_critical); - for (SettingsHandlers::const_iterator it = m_settingsHandlers.begin(); it != m_settingsHandlers.end(); it++) + if (section.empty()) + return NULL; + + return m_settingsManager->GetSection(section); +} + +SettingDependencyMap CSettings::GetDependencies(const std::string &id) const +{ + return m_settingsManager->GetDependencies(id); +} + +SettingDependencyMap CSettings::GetDependencies(const CSetting *setting) const +{ + return m_settingsManager->GetDependencies(setting); +} + +void* CSettings::GetSettingOptionsFiller(const CSetting *setting) +{ + return m_settingsManager->GetSettingOptionsFiller(setting); +} + +bool CSettings::GetBool(const std::string &id) const +{ + return m_settingsManager->GetBool(id); +} + +bool CSettings::SetBool(const std::string &id, bool value) +{ + return m_settingsManager->SetBool(id, value); +} + +bool CSettings::ToggleBool(const std::string &id) +{ + return m_settingsManager->ToggleBool(id); +} + +int CSettings::GetInt(const std::string &id) const +{ + return m_settingsManager->GetInt(id); +} + +bool CSettings::SetInt(const std::string &id, int value) +{ + return m_settingsManager->SetInt(id, value); +} + +double CSettings::GetNumber(const std::string &id) const +{ + return m_settingsManager->GetNumber(id); +} + +bool CSettings::SetNumber(const std::string &id, double value) +{ + return m_settingsManager->SetNumber(id, value); +} + +std::string CSettings::GetString(const std::string &id) const +{ + return m_settingsManager->GetString(id); +} + +bool CSettings::SetString(const std::string &id, const std::string &value) +{ + return m_settingsManager->SetString(id, value); +} + +bool CSettings::LoadSetting(const TiXmlNode *node, const std::string &settingId) +{ + return m_settingsManager->LoadSetting(node, settingId); +} + +bool CSettings::Initialize(const std::string &file) +{ + CXBMCTinyXML xmlDoc; + if (!xmlDoc.LoadFile(file.c_str())) { - if (!(*it)->OnSettingsLoading()) - return false; + CLog::Log(LOGERROR, "CSettings: error loading settings definition from %s, Line %d\n%s", file.c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc()); + return false; + } + + CLog::Log(LOGDEBUG, "CSettings: loaded settings definition from %s", file.c_str()); + + TiXmlElement *root = xmlDoc.RootElement(); + if (root == NULL) + return false; + + return m_settingsManager->Initialize(root); +} + +bool CSettings::InitializeDefinitions() +{ + if (!Initialize(SETTINGS_XML_FOLDER "settings.xml")) + { + CLog::Log(LOGFATAL, "Unable to load settings definitions"); + return false; } +#if defined(TARGET_WINDOWS) + if (CFile::Exists(SETTINGS_XML_FOLDER "win32.xml") && !Initialize(SETTINGS_XML_FOLDER "win32.xml")) + CLog::Log(LOGFATAL, "Unable to load win32-specific settings definitions"); +#elif defined(TARGET_LINUX) + if (CFile::Exists(SETTINGS_XML_FOLDER "linux.xml") && !Initialize(SETTINGS_XML_FOLDER "linux.xml")) + CLog::Log(LOGFATAL, "Unable to load linux-specific settings definitions"); +#elif defined(TARGET_ANDROID) + if (CFile::Exists(SETTINGS_XML_FOLDER "android.xml") && !Initialize(SETTINGS_XML_FOLDER "android.xml")) + CLog::Log(LOGFATAL, "Unable to load android-specific settings definitions"); +#elif defined(TARGET_RASPBERRY_PI) + if (CFile::Exists(SETTINGS_XML_FOLDER "rbp.xml") && !Initialize(SETTINGS_XML_FOLDER "rbp.xml")) + CLog::Log(LOGFATAL, "Unable to load rbp-specific settings definitions"); +#elif defined(TARGET_FREEBSD) + if (CFile::Exists(SETTINGS_XML_FOLDER "freebsd.xml") && !Initialize(SETTINGS_XML_FOLDER "freebsd.xml")) + CLog::Log(LOGFATAL, "Unable to load freebsd-specific settings definitions"); +#elif defined(TARGET_DARWIN) + if (CFile::Exists(SETTINGS_XML_FOLDER "darwin.xml") && !Initialize(SETTINGS_XML_FOLDER "darwin.xml")) + CLog::Log(LOGFATAL, "Unable to load darwin-specific settings definitions"); +#if defined(TARGET_DARWIN_OSX) + if (CFile::Exists(SETTINGS_XML_FOLDER "darwin_osx.xml") && !Initialize(SETTINGS_XML_FOLDER "darwin_osx.xml")) + CLog::Log(LOGFATAL, "Unable to load osx-specific settings definitions"); +#elif defined(TARGET_DARWIN_IOS) + if (CFile::Exists(SETTINGS_XML_FOLDER "darwin_ios.xml") && !Initialize(SETTINGS_XML_FOLDER "darwin_ios.xml")) + CLog::Log(LOGFATAL, "Unable to load ios-specific settings definitions"); +#if defined(TARGET_DARWIN_IOS_ATV2) + if (CFile::Exists(SETTINGS_XML_FOLDER "darwin_ios_atv2.xml") && !Initialize(SETTINGS_XML_FOLDER "darwin_ios_atv2.xml")) + CLog::Log(LOGFATAL, "Unable to load atv2-specific settings definitions"); +#endif +#endif +#endif + if (CFile::Exists(SETTINGS_XML_FOLDER "appliance.xml") && !Initialize(SETTINGS_XML_FOLDER "appliance.xml")) + CLog::Log(LOGFATAL, "Unable to load appliance-specific settings definitions"); return true; } -void CSettings::OnSettingsLoaded() +void CSettings::InitializeSettingTypes() { - CSingleLock lock(m_critical); - for (SettingsHandlers::const_iterator it = m_settingsHandlers.begin(); it != m_settingsHandlers.end(); it++) - (*it)->OnSettingsLoaded(); + // register "addon" and "path" setting types implemented by CSettingAddon + m_settingsManager->RegisterSettingType("addon", this); + m_settingsManager->RegisterSettingType("path", this); } -bool CSettings::OnSettingsSaving() const +void CSettings::InitializeVisibility() { - CSingleLock lock(m_critical); - for (SettingsHandlers::const_iterator it = m_settingsHandlers.begin(); it != m_settingsHandlers.end(); it++) + // hide some settings if necessary +#if defined(TARGET_LINUX) || defined(TARGET_DARWIN) + CSettingString* timezonecountry = (CSettingString*)m_settingsManager->GetSetting("locale.timezonecountry"); + CSettingString* timezone = (CSettingString*)m_settingsManager->GetSetting("locale.timezone"); + +#if defined(TARGET_DARWIN) + if (!g_sysinfo.IsAppleTV2() || GetIOSVersion() >= 4.3) { - if (!(*it)->OnSettingsSaving()) - return false; + timezonecountry->SetVisible(false); + timezone->SetVisible(false); } +#endif + +#if defined(TARGET_LINUX) + if (timezonecountry->IsVisible()) + timezonecountry->SetDefault(g_timezone.GetCountryByTimezone(g_timezone.GetOSConfiguredTimezone())); + if (timezone->IsVisible()) + timezone->SetDefault(g_timezone.GetOSConfiguredTimezone()); +#endif +#endif +} - return true; +void CSettings::InitializeDefaults() +{ + // set some default values if necessary +#if defined(HAS_SKIN_TOUCHED) && defined(TARGET_DARWIN_IOS) && !defined(TARGET_DARWIN_IOS_ATV2) + ((CSettingAddon*)m_settingsManager->GetSetting("lookandfeel.skin"))->SetDefault("skin.touched"); +#endif + +#if defined(TARGET_WINDOWS) + #if defined(HAS_DX) + ((CSettingString*)m_settingsManager->GetSetting("musicplayer.visualisation"))->SetDefault("visualization.milkdrop"); + #endif + + #if !defined(HAS_GL) + // We prefer a fake fullscreen mode (window covering the screen rather than dedicated fullscreen) + // as it works nicer with switching to other applications. However on some systems vsync is broken + // when we do this (eg non-Aero on ATI in particular) and on others (AppleTV) we can't get XBMC to + // the front + if (g_sysinfo.IsAeroDisabled()) + ((CSettingBool*)m_settingsManager->GetSetting("videoscreen.fakefullscreen"))->SetDefault(false); + #endif +#endif + +#if defined(TARGET_DARWIN) + #if !defined(TARGET_DARWIN_IOS) + CStdString defaultAudioDeviceName; + CCoreAudioHardware::GetOutputDeviceName(defaultAudioDeviceName); + ((CSettingString*)m_settingsManager->GetSetting("audiooutput.audiodevice"))->SetDefault(defaultAudioDeviceName); + ((CSettingString*)m_settingsManager->GetSetting("audiooutput.passthroughdevice"))->SetDefault(defaultAudioDeviceName); + #endif +#else + ((CSettingString*)m_settingsManager->GetSetting("audiooutput.audiodevice"))->SetDefault(CAEFactory::GetDefaultDevice(false)); + ((CSettingString*)m_settingsManager->GetSetting("audiooutput.passthroughdevice"))->SetDefault(CAEFactory::GetDefaultDevice(true)); +#endif + + if (g_application.IsStandAlone()) + ((CSettingInt*)m_settingsManager->GetSetting("powermanagement.shutdownstate"))->SetDefault(POWERSTATE_SHUTDOWN); + +#if defined(HAS_WEB_SERVER) + if (CUtil::CanBindPrivileged()) + ((CSettingInt*)m_settingsManager->GetSetting("services.webserverport"))->SetDefault(80); +#endif } -void CSettings::OnSettingsSaved() const +void CSettings::InitializeOptionFillers() { - CSingleLock lock(m_critical); - for (SettingsHandlers::const_iterator it = m_settingsHandlers.begin(); it != m_settingsHandlers.end(); it++) - (*it)->OnSettingsSaved(); + // register setting option fillers +#ifdef HAS_DVD_DRIVE + m_settingsManager->RegisterSettingOptionsFiller("audiocdactions", MEDIA_DETECT::CAutorun::SettingOptionAudioCdActionsFiller); + m_settingsManager->RegisterSettingOptionsFiller("audiocdencoders", MEDIA_DETECT::CAutorun::SettingOptionAudioCdEncodersFiller); +#endif + m_settingsManager->RegisterSettingOptionsFiller("audiodevices", CAEFactory::SettingOptionsAudioDevicesFiller); + m_settingsManager->RegisterSettingOptionsFiller("audiodevicespassthrough", CAEFactory::SettingOptionsAudioDevicesPassthroughFiller); + m_settingsManager->RegisterSettingOptionsFiller("audiooutputmodes", CAEFactory::SettingOptionsAudioOutputModesFiller); + m_settingsManager->RegisterSettingOptionsFiller("charsets", CCharsetConverter::SettingOptionsCharsetsFiller); + m_settingsManager->RegisterSettingOptionsFiller("epgguideviews", PVR::CGUIWindowPVRGuide::SettingOptionsEpgGuideViewFiller); + m_settingsManager->RegisterSettingOptionsFiller("fonts", GUIFontManager::SettingOptionsFontsFiller); + m_settingsManager->RegisterSettingOptionsFiller("languages", CLangInfo::SettingOptionsLanguagesFiller); + m_settingsManager->RegisterSettingOptionsFiller("pvrstartlastchannel", PVR::CPVRManager::SettingOptionsPvrStartLastChannelFiller); + m_settingsManager->RegisterSettingOptionsFiller("refreshchangedelays", CDisplaySettings::SettingOptionsRefreshChangeDelaysFiller); + m_settingsManager->RegisterSettingOptionsFiller("refreshrates", CDisplaySettings::SettingOptionsRefreshRatesFiller); + m_settingsManager->RegisterSettingOptionsFiller("regions", CLangInfo::SettingOptionsRegionsFiller); + m_settingsManager->RegisterSettingOptionsFiller("rendermethods", CBaseRenderer::SettingOptionsRenderMethodsFiller); + m_settingsManager->RegisterSettingOptionsFiller("resolutions", CDisplaySettings::SettingOptionsResolutionsFiller); + m_settingsManager->RegisterSettingOptionsFiller("screens", CDisplaySettings::SettingOptionsScreensFiller); + m_settingsManager->RegisterSettingOptionsFiller("shutdownstates", CPowerManager::SettingOptionsShutdownStatesFiller); + m_settingsManager->RegisterSettingOptionsFiller("startupwindows", ADDON::CSkinInfo::SettingOptionsStartupWindowsFiller); + m_settingsManager->RegisterSettingOptionsFiller("streamlanguages", CLangInfo::SettingOptionsStreamLanguagesFiller); + m_settingsManager->RegisterSettingOptionsFiller("skincolors", ADDON::CSkinInfo::SettingOptionsSkinColorsFiller); + m_settingsManager->RegisterSettingOptionsFiller("skinfonts", ADDON::CSkinInfo::SettingOptionsSkinFontsFiller); + m_settingsManager->RegisterSettingOptionsFiller("skinsounds", ADDON::CSkinInfo::SettingOptionsSkinSoundFiller); + m_settingsManager->RegisterSettingOptionsFiller("skinthemes", ADDON::CSkinInfo::SettingOptionsSkinThemesFiller); +#ifdef TARGET_LINUX + m_settingsManager->RegisterSettingOptionsFiller("timezonecountries", CLinuxTimezone::SettingOptionsTimezoneCountriesFiller); + m_settingsManager->RegisterSettingOptionsFiller("timezones", CLinuxTimezone::SettingOptionsTimezonesFiller); +#endif + m_settingsManager->RegisterSettingOptionsFiller("verticalsyncs", CDisplaySettings::SettingOptionsVerticalSyncsFiller); } -void CSettings::OnSettingsCleared() +void CSettings::InitializeConditions() { - CSingleLock lock(m_critical); - for (SettingsHandlers::const_iterator it = m_settingsHandlers.begin(); it != m_settingsHandlers.end(); it++) - (*it)->OnSettingsCleared(); + // add basic conditions + m_settingsManager->AddCondition("true"); +#ifdef HAS_AIRPLAY + m_settingsManager->AddCondition("has_airplay"); +#endif +#ifdef HAS_EVENT_SERVER + m_settingsManager->AddCondition("has_event_server"); +#endif +#ifdef HAS_GL + m_settingsManager->AddCondition("has_gl"); +#endif +#ifdef HAS_GLES + m_settingsManager->AddCondition("has_gles"); +#endif +#if HAS_GLES == 2 + m_settingsManager->AddCondition("has_glesv2"); +#endif +#ifdef HAS_KARAOKE + m_settingsManager->AddCondition("has_karaoke"); +#endif +#ifdef HAS_SDL_JOYSTICK + m_settingsManager->AddCondition("has_sdl_joystick"); +#endif +#ifdef HAS_SKIN_TOUCHED + m_settingsManager->AddCondition("has_skin_touched"); +#endif +#ifdef HAS_TIME_SERVER + m_settingsManager->AddCondition("has_time_server"); +#endif +#ifdef HAS_WEB_SERVER + m_settingsManager->AddCondition("has_web_server"); +#endif +#ifdef HAS_ZEROCONF + m_settingsManager->AddCondition("has_zeroconf"); +#endif +#ifdef HAVE_LIBCRYSTALHD + m_settingsManager->AddCondition("have_libcrystalhd"); + if (CCrystalHD::GetInstance()->DevicePresent()) + m_settingsManager->AddCondition("hascrystalhddevice"); +#endif +#ifdef HAVE_LIBOPENMAX + m_settingsManager->AddCondition("have_libopenmax"); +#endif +#ifdef HAVE_LIBVA + m_settingsManager->AddCondition("have_libva"); +#endif +#ifdef HAVE_LIBVDADECODER + m_settingsManager->AddCondition("have_libvdadecoder"); + if (g_sysinfo.HasVDADecoder()) + m_settingsManager->AddCondition("hasvdadecoder"); +#endif +#ifdef HAVE_LIBVDPAU + m_settingsManager->AddCondition("have_libvdpau"); +#endif +#ifdef HAVE_VIDEOTOOLBOXDECODER + m_settingsManager->AddCondition("have_videotoolboxdecoder"); + if (g_sysinfo.HasVideoToolBoxDecoder()) + m_settingsManager->AddCondition("hasvideotoolboxdecoder"); +#endif +#ifdef TARGET_DARWIN_IOS_ATV2 + if (g_sysinfo.IsAppleTV2()) + m_settingsManager->AddCondition("isappletv2"); +#endif +#if defined(TARGET_WINDOWS) && defined(HAS_DX) + m_settingsManager->AddCondition("has_dx"); + if (g_sysinfo.IsVistaOrHigher()) + m_settingsManager->AddCondition("hasdxva2"); +#endif + + if (g_application.IsStandAlone()) + m_settingsManager->AddCondition("isstandalone"); + + // add more complex conditions + m_settingsManager->AddCondition("addonhassettings", AddonHasSettings); + m_settingsManager->AddCondition("checkmasterlock", CheckMasterLock); + m_settingsManager->AddCondition("checkpvrparentalpin", CheckPVRParentalPin); + m_settingsManager->AddCondition("hasperipherals", HasPeripherals); + m_settingsManager->AddCondition("isfullscreen", IsFullscreen); + m_settingsManager->AddCondition("ismasteruser", IsMasterUser); + m_settingsManager->AddCondition("isusingttfsubtitles", IsUsingTTFSubtitles); + m_settingsManager->AddCondition("profilecanwritedatabase", ProfileCanWriteDatabase); + m_settingsManager->AddCondition("profilecanwritesources", ProfileCanWriteSources); + m_settingsManager->AddCondition("profilehasaddons", ProfileHasAddons); + m_settingsManager->AddCondition("profilehasdatabase", ProfileHasDatabase); + m_settingsManager->AddCondition("profilehassources", ProfileHasSources); + m_settingsManager->AddCondition("profilehasaddonmanagerlocked", ProfileHasAddonManagerLocked); + m_settingsManager->AddCondition("profilehasfileslocked", ProfileHasFilesLocked); + m_settingsManager->AddCondition("profilehasmusiclocked", ProfileHasMusicLocked); + m_settingsManager->AddCondition("profilehaspictureslocked", ProfileHasPicturesLocked); + m_settingsManager->AddCondition("profilehasprogramslocked", ProfileHasProgramsLocked); + m_settingsManager->AddCondition("profilehassettingslocked", ProfileHasSettingsLocked); + m_settingsManager->AddCondition("profilehasvideoslocked", ProfileHasVideosLocked); + m_settingsManager->AddCondition("profilelockmode", ProfileLockMode); } -bool CSettings::Load(const TiXmlNode *settings) +void CSettings::InitializeISettingsHandlers() { - bool ok = true; - for (SubSettings::const_iterator it = m_subSettings.begin(); it != m_subSettings.end(); it++) - ok &= (*it)->Load(settings); + // register ISettingsHandler implementations + m_settingsManager->RegisterSettingsHandler(&g_application); + m_settingsManager->RegisterSettingsHandler(&CProfilesManager::Get()); + m_settingsManager->RegisterSettingsHandler(&g_advancedSettings); + m_settingsManager->RegisterSettingsHandler(&CMediaSourceSettings::Get()); + m_settingsManager->RegisterSettingsHandler(&CPlayerCoreFactory::Get()); + m_settingsManager->RegisterSettingsHandler(&CRssManager::Get()); +#ifdef HAS_UPNP + m_settingsManager->RegisterSettingsHandler(&CUPnPSettings::Get()); +#endif +} - return ok; +void CSettings::InitializeISubSettings() +{ + // register ISubSettings implementations + m_settingsManager->RegisterSubSettings(&g_application); + m_settingsManager->RegisterSubSettings(&CDisplaySettings::Get()); + m_settingsManager->RegisterSubSettings(&CMediaSettings::Get()); + m_settingsManager->RegisterSubSettings(&CSkinSettings::Get()); + m_settingsManager->RegisterSubSettings(&g_sysinfo); + m_settingsManager->RegisterSubSettings(&CViewStateSettings::Get()); } -bool CSettings::Save(TiXmlNode *settings) const +void CSettings::InitializeISettingCallbacks() { - CSingleLock lock(m_critical); - for (SubSettings::const_iterator it = m_subSettings.begin(); it != m_subSettings.end(); it++) + // register any ISettingCallback implementations + std::set<std::string> settingSet; + settingSet.insert("debug.showloginfo"); + settingSet.insert("debug.setextraloglevel"); + m_settingsManager->RegisterCallback(&g_advancedSettings, settingSet); + + settingSet.clear(); + settingSet.insert("karaoke.export"); + settingSet.insert("karaoke.importcsv"); + settingSet.insert("musiclibrary.cleanup"); + settingSet.insert("musiclibrary.export"); + settingSet.insert("musiclibrary.import"); + settingSet.insert("musicfiles.trackformat"); + settingSet.insert("musicfiles.trackformatright"); + settingSet.insert("videolibrary.flattentvshows"); + settingSet.insert("videolibrary.removeduplicates"); + settingSet.insert("videolibrary.groupmoviesets"); + settingSet.insert("videolibrary.cleanup"); + settingSet.insert("videolibrary.import"); + settingSet.insert("videolibrary.export"); + m_settingsManager->RegisterCallback(&CMediaSettings::Get(), settingSet); + + settingSet.clear(); + settingSet.insert("videoscreen.screen"); + settingSet.insert("videoscreen.resolution"); + settingSet.insert("videoscreen.screenmode"); + m_settingsManager->RegisterCallback(&CDisplaySettings::Get(), settingSet); + + settingSet.clear(); + settingSet.insert("audiooutput.channels"); + settingSet.insert("audiooutput.guisoundmode"); + settingSet.insert("lookandfeel.skin"); + settingSet.insert("lookandfeel.skinsettings"); + settingSet.insert("lookandfeel.font"); + settingSet.insert("lookandfeel.skintheme"); + settingSet.insert("lookandfeel.skincolors"); + settingSet.insert("lookandfeel.skinzoom"); + settingSet.insert("musicplayer.replaygainpreamp"); + settingSet.insert("musicplayer.replaygainnogainpreamp"); + settingSet.insert("musicplayer.replaygaintype"); + settingSet.insert("musicplayer.replaygainavoidclipping"); + settingSet.insert("scrapers.musicvideosdefault"); + settingSet.insert("screensaver.mode"); + settingSet.insert("screensaver.preview"); + settingSet.insert("screensaver.settings"); + settingSet.insert("videoscreen.guicalibration"); + settingSet.insert("videoscreen.testpattern"); + m_settingsManager->RegisterCallback(&g_application, settingSet); + + settingSet.clear(); + settingSet.insert("lookandfeel.soundskin"); + m_settingsManager->RegisterCallback(&g_audioManager, settingSet); + + settingSet.clear(); + settingSet.insert("subtitles.charset"); + settingSet.insert("karaoke.charset"); + settingSet.insert("locale.charset"); + m_settingsManager->RegisterCallback(&g_charsetConverter, settingSet); + + settingSet.clear(); + settingSet.insert("videoscreen.fakefullscreen"); + m_settingsManager->RegisterCallback(&g_graphicsContext, settingSet); + + settingSet.clear(); + settingSet.insert("locale.audiolanguage"); + settingSet.insert("locale.subtitlelanguage"); + settingSet.insert("locale.language"); + settingSet.insert("locale.country"); + m_settingsManager->RegisterCallback(&g_langInfo, settingSet); + +#if defined(HAS_SDL_JOYSTICK) + settingSet.clear(); + settingSet.insert("input.enablejoystick"); + m_settingsManager->RegisterCallback(&g_Joystick, settingSet); +#endif + + settingSet.clear(); + settingSet.insert("input.enablemouse"); + m_settingsManager->RegisterCallback(&g_Mouse, settingSet); + + settingSet.clear(); + settingSet.insert("services.webserver"); + settingSet.insert("services.webserverport"); + settingSet.insert("services.webserverusername"); + settingSet.insert("services.webserverpassword"); + settingSet.insert("services.zeroconf"); + settingSet.insert("services.airplay"); + settingSet.insert("services.useairplaypassword"); + settingSet.insert("services.airplaypassword"); + settingSet.insert("services.upnpserver"); + settingSet.insert("services.upnprenderer"); + settingSet.insert("services.upnpcontroller"); + settingSet.insert("services.esenabled"); + settingSet.insert("services.esport"); + settingSet.insert("services.esallinterfaces"); + settingSet.insert("services.esinitialdelay"); + settingSet.insert("services.escontinuousdelay"); + settingSet.insert("smb.winsserver"); + settingSet.insert("smb.workgroup"); + m_settingsManager->RegisterCallback(&CNetworkServices::Get(), settingSet); + + settingSet.clear(); + settingSet.insert("masterlock.lockcode"); + m_settingsManager->RegisterCallback(&g_passwordManager, settingSet); + + settingSet.clear(); + settingSet.insert("pvrmanager.enabled"); + settingSet.insert("pvrmanager.channelmanager"); + settingSet.insert("pvrmanager.channelscan"); + settingSet.insert("pvrmanager.resetdb"); + settingSet.insert("pvrclient.menuhook"); + settingSet.insert("pvrmenu.searchicons"); + settingSet.insert("epg.resetepg"); + settingSet.insert("pvrparental.enabled"); + m_settingsManager->RegisterCallback(&PVR::g_PVRManager, settingSet); + + settingSet.clear(); + settingSet.insert("lookandfeel.rssedit"); + m_settingsManager->RegisterCallback(&CRssManager::Get(), settingSet); + +#if defined(TARGET_LINUX) + settingSet.clear(); + settingSet.insert("locale.timezone"); + settingSet.insert("locale.timezonecountry"); + m_settingsManager->RegisterCallback(&g_timezone, settingSet); +#endif + + settingSet.clear(); + settingSet.insert("weather.addon"); + settingSet.insert("weather.addonsettings"); + m_settingsManager->RegisterCallback(&g_weatherManager, settingSet); + + settingSet.clear(); + settingSet.insert("input.peripherals"); + settingSet.insert("locale.language"); + m_settingsManager->RegisterCallback(&PERIPHERALS::CPeripherals::Get(), settingSet); + +#if defined(TARGET_DARWIN_OSX) + settingSet.clear(); + settingSet.insert("input.appleremotemode"); + m_settingsManager->RegisterCallback(&XBMCHelper::GetInstance(), settingSet); +#endif +} + +bool CSettings::Reset() +{ + std::string settingsFile = CProfilesManager::Get().GetSettingsFile(); + // try to delete the settings file + if (XFILE::CFile::Exists(settingsFile, false) && !XFILE::CFile::Delete(settingsFile)) + CLog::Log(LOGWARNING, "Unable to delete old settings file at %s", settingsFile.c_str()); + + // unload any loaded settings + Unload(); + + // try to save the default settings + if (!Save()) { - if (!(*it)->Save(settings)) - return false; + CLog::Log(LOGWARNING, "Failed to save the default settings to %s", settingsFile.c_str()); + return false; } return true; diff --git a/xbmc/settings/Settings.h b/xbmc/settings/Settings.h index c525914f24..96f334c46a 100644 --- a/xbmc/settings/Settings.h +++ b/xbmc/settings/Settings.h @@ -20,56 +20,268 @@ */ #include <set> +#include <string> -#define PRE_SKIN_VERSION_9_10_COMPATIBILITY 1 -#define PRE_SKIN_VERSION_11_COMPATIBILITY 1 - -#include "settings/ISettingsHandler.h" -#include "settings/ISubSettings.h" +#include "settings/ISettingCallback.h" +#include "settings/ISettingCreator.h" +#include "settings/Setting.h" #include "threads/CriticalSection.h" -#include "utils/StdString.h" -class CGUISettings; +class CSettingSection; +class CSettingsManager; class TiXmlElement; class TiXmlNode; -class CSettings : private ISettingsHandler, ISubSettings +/*! + \brief Wrapper around CSettingsManager responsible for properly setting up + the settings manager and registering all the callbacks, handlers and custom + setting types. + \sa CSettingsManager + */ +class CSettings : public ISettingCreator { public: - CSettings(void); - virtual ~CSettings(void); + /*! + \brief Creates a new settings wrapper around a new settings manager. + + For access to the "global" settings wrapper the static Get() method should + be used. + */ + CSettings(); + virtual ~CSettings(); + + /*! + \brief Returns a "global" settings wrapper which can be used from anywhere. + + \return "global" settings wrapper + */ + static CSettings& Get(); - void RegisterSettingsHandler(ISettingsHandler *settingsHandler); - void UnregisterSettingsHandler(ISettingsHandler *settingsHandler); - void RegisterSubSettings(ISubSettings *subSettings); - void UnregisterSubSettings(ISubSettings *subSettings); + // implementation of ISettingCreator + virtual CSetting* CreateSetting(const std::string &settingType, const std::string &settingId, CSettingsManager *settingsManager = NULL) const; + /*! + \brief Initializes the setting system with the generic + settings definition and platform specific setting definitions. + + \return True if the initialization was successful, false otherwise + */ + bool Initialize(); + /*! + \brief Loads the setting values. + + \return True if the setting values are successfully loaded, false otherwise + */ bool Load(); - void Save() const; - bool SaveSettings(const CStdString& strSettingsFile, CGUISettings *localSettings = NULL) const; - bool Reset(); - void Clear(); + /*! + \brief Loads setting values from the given (XML) file. + + \param file Path to an XML file containing setting values + \return True if the setting values were successfully loaded, false otherwise + */ + bool Load(const std::string &file); + /*! + \brief Loads setting values from the given XML element. + + \param root XML element containing setting values + \param hide Whether to hide the loaded settings or not + \return True if the setting values were successfully loaded, false otherwise + */ + bool Load(const TiXmlElement *root, bool hide = false); + /*! + \brief Tells the settings system that all setting values + have been loaded. + + This manual trigger is necessary to enable the ISettingCallback methods + being executed. + */ + void SetLoaded(); + /*! + \brief Saves the setting values. + + \return True if the setting values were successfully saved, false otherwise + */ + bool Save(); + /*! + \brief Saves the setting values to the given (XML) file. + + \param file Path to an XML file + \return True if the setting values were successfully saved, false otherwise + */ + bool Save(const std::string &file); + /*! + \brief Unloads the previously loaded setting values. + + The values of all the settings are reset to their default values. + */ + void Unload(); + /*! + \brief Uninitializes the settings system. + + Unregisters all previously registered callbacks and destroys all setting + objects. + */ + void Uninitialize(); + + /*! + \brief Registers the given ISettingCallback implementation for the given + set of settings. + + \param callback ISettingCallback implementation + \param settingList List of setting identifiers for which the given callback shall be triggered + */ + void RegisterCallback(ISettingCallback *callback, const std::set<std::string> &settingList); + /*! + \brief Unregisters the given ISettingCallback implementation. + + \param callback ISettingCallback implementation + */ + void UnregisterCallback(ISettingCallback *callback); + + /*! + \brief Gets the setting with the given identifier. + + \param id Setting identifier + \return Setting object with the given identifier or NULL if the identifier is unknown + */ + CSetting* GetSetting(const std::string &id) const; + /*! + \brief Gets the setting section with the given identifier. -protected: - bool LoadSettings(const CStdString& strSettingsFile); + \param section Setting section identifier + \return Setting section with the given identifier or NULL if the identifier is unknown + */ + CSettingSection* GetSection(const std::string §ion) const; + /*! + \brief Gets a map of settings (and their dependencies) which depend on + the setting with the given identifier. + + It is important to note that the returned dependencies are not the + dependencies of the setting with the given identifier but the settings + (and their dependencies) which depend on the setting with the given + identifier. + + \param id Setting identifier + \return Map of settings (and their dependencies) which depend on the setting with the given identifier + */ + SettingDependencyMap GetDependencies(const std::string &id) const; + /*! + \brief Gets a map of settings (and their dependencies) which depend on + the given setting. + + It is important to note that the returned dependencies are not the + dependencies of the given setting but the settings (and their dependencies) + which depend on the given setting. + + \param setting Setting object + \return Map of settings (and their dependencies) which depend on the given setting + */ + SettingDependencyMap GetDependencies(const CSetting *setting) const; + /*! + \brief Gets the implementation of the setting options filler used by the + given setting. + + \param setting Setting object + \return Implementation of the setting options filler (either IntegerSettingOptionsFiller or StringSettingOptionsFiller) + */ + void* GetSettingOptionsFiller(const CSetting *setting); + + /*! + \brief Gets the boolean value of the setting with the given identifier. + + \param id Setting identifier + \return Boolean value of the setting with the given identifier + */ + bool GetBool(const std::string &id) const; + /*! + \brief Gets the integer value of the setting with the given identifier. + + \param id Setting identifier + \return Integer value of the setting with the given identifier + */ + int GetInt(const std::string &id) const; + /*! + \brief Gets the real number value of the setting with the given identifier. + + \param id Setting identifier + \return Real number value of the setting with the given identifier + */ + double GetNumber(const std::string &id) const; + /*! + \brief Gets the string value of the setting with the given identifier. + + \param id Setting identifier + \return String value of the setting with the given identifier + */ + std::string GetString(const std::string &id) const; + + /*! + \brief Sets the boolean value of the setting with the given identifier. + + \param id Setting identifier + \param value Boolean value to set + \return True if setting the value was successful, false otherwise + */ + bool SetBool(const std::string &id, bool value); + /*! + \brief Toggles the boolean value of the setting with the given identifier. + + \param id Setting identifier + \return True if toggling the boolean value was successful, false otherwise + */ + bool ToggleBool(const std::string &id); + /*! + \brief Sets the integer value of the setting with the given identifier. + + \param id Setting identifier + \param value Integer value to set + \return True if setting the value was successful, false otherwise + */ + bool SetInt(const std::string &id, int value); + /*! + \brief Sets the real number value of the setting with the given identifier. + + \param id Setting identifier + \param value Real number value to set + \return True if setting the value was successful, false otherwise + */ + bool SetNumber(const std::string &id, double value); + /*! + \brief Sets the string value of the setting with the given identifier. + + \param id Setting identifier + \param value String value to set + \return True if setting the value was successful, false otherwise + */ + bool SetString(const std::string &id, const std::string &value); + + /*! + \brief Loads the setting being represented by the given XML node with the + given identifier. + + \param node XML node representing the setting to load + \param settingId Setting identifier + \return True if the setting was successfully loaded from the given XML node, false otherwise + */ + bool LoadSetting(const TiXmlNode *node, const std::string &settingId); private: - // implementation of ISettingsHandler - virtual bool OnSettingsLoading(); - virtual void OnSettingsLoaded(); - virtual bool OnSettingsSaving() const; - virtual void OnSettingsSaved() const; - virtual void OnSettingsCleared(); + CSettings(const CSettings&); + CSettings const& operator=(CSettings const&); - // implementation of ISubSettings - virtual bool Load(const TiXmlNode *settings); - virtual bool Save(TiXmlNode *settings) const; + bool Initialize(const std::string &file); + bool InitializeDefinitions(); + void InitializeSettingTypes(); + void InitializeVisibility(); + void InitializeDefaults(); + void InitializeOptionFillers(); + void InitializeConditions(); + void InitializeISettingsHandlers(); + void InitializeISubSettings(); + void InitializeISettingCallbacks(); + bool Reset(); + bool m_initialized; + CSettingsManager *m_settingsManager; CCriticalSection m_critical; - typedef std::set<ISettingsHandler*> SettingsHandlers; - SettingsHandlers m_settingsHandlers; - typedef std::set<ISubSettings*> SubSettings; - SubSettings m_subSettings; }; - -extern class CSettings g_settings; diff --git a/xbmc/settings/SettingsManager.cpp b/xbmc/settings/SettingsManager.cpp new file mode 100644 index 0000000000..3bb1e39946 --- /dev/null +++ b/xbmc/settings/SettingsManager.cpp @@ -0,0 +1,882 @@ +/* + * Copyright (C) 2013 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 "SettingsManager.h" +#include "SettingSection.h" +#include "Setting.h" +#include "threads/SingleLock.h" +#include "utils/log.h" +#include "utils/StringUtils.h" +#include "utils/XBMCTinyXML.h" + +#define XML_ROOT "settings" +#define XML_SECTION "section" + + +CSettingsManager::CSettingsManager() + : m_initialized(false), m_loaded(false) +{ } + +CSettingsManager::~CSettingsManager() +{ + // first clear all registered settings handler and subsettings + // implementations because we can't be sure that they are still valid + m_settingsHandlers.clear(); + m_subSettings.clear(); + m_settingCreators.clear(); + + Clear(); +} + +bool CSettingsManager::Initialize(const TiXmlElement *root) +{ + CSingleLock lock(m_critical); + if (m_initialized || root == NULL) + return false; + + if (!StringUtils::EqualsNoCase(root->ValueStr(), XML_ROOT)) + { + CLog::Log(LOGERROR, "CSettingsManager: error reading settings definition: doesn't contain <settings> tag"); + return false; + } + + const TiXmlNode *sectionNode = root->FirstChild(XML_SECTION); + while (sectionNode != NULL) + { + std::string sectionId; + if (CSettingSection::DeserializeIdentification(sectionNode, sectionId)) + { + CSettingSection *section = NULL; + SettingSectionMap::iterator itSection = m_sections.find(sectionId); + bool update = (itSection != m_sections.end()); + if (!update) + section = new CSettingSection(sectionId, this); + else + section = itSection->second; + + if (section->Deserialize(sectionNode, update)) + { + section->CheckVisible(); + if (!update) + m_sections[section->GetId()] = section; + + // get all settings and add them to the settings map + for (SettingCategoryList::const_iterator categoryIt = section->GetCategories().begin(); categoryIt != section->GetCategories().end(); categoryIt++) + { + (*categoryIt)->CheckVisible(); + for (SettingGroupList::const_iterator groupIt = (*categoryIt)->GetGroups().begin(); groupIt != (*categoryIt)->GetGroups().end(); groupIt++) + { + (*groupIt)->CheckVisible(); + for (SettingList::const_iterator settingIt = (*groupIt)->GetSettings().begin(); settingIt != (*groupIt)->GetSettings().end(); settingIt++) + { + (*settingIt)->CheckVisible(); + + const std::string &settingId = (*settingIt)->GetId(); + SettingMap::iterator setting = m_settings.find(settingId); + if (setting == m_settings.end()) + { + Setting tmpSetting = { NULL }; + std::pair<SettingMap::iterator, bool> tmpIt = m_settings.insert(make_pair(settingId, tmpSetting)); + setting = tmpIt.first; + } + + if (setting->second.setting == NULL) + { + setting->second.setting = *settingIt; + (*settingIt)->m_callback = this; + } + } + } + } + } + else + { + CLog::Log(LOGWARNING, "CSettingsManager: unable to read section \"%s\"", sectionId.c_str()); + if (!update) + delete section; + } + } + + sectionNode = sectionNode->NextSibling(XML_SECTION); + } + + for (SettingMap::iterator itSettingDep = m_settings.begin(); itSettingDep != m_settings.end(); itSettingDep++) + { + if (itSettingDep->second.setting == NULL) + continue; + + const SettingDependencies& deps = itSettingDep->second.setting->GetDependencies(); + for (SettingDependencies::const_iterator depIt = deps.begin(); depIt != deps.end(); depIt++) + { + std::set<std::string> settingIds = depIt->GetSettings(); + for (std::set<std::string>::const_iterator itSettingId = settingIds.begin(); itSettingId != settingIds.end(); itSettingId++) + { + SettingMap::iterator setting = m_settings.find(*itSettingId); + if (setting == m_settings.end()) + continue; + + setting->second.dependencies[itSettingDep->first].push_back(*depIt); + } + } + } + + return true; +} + +bool CSettingsManager::Load(const TiXmlElement *root, bool &updated, bool triggerEvents /* = true */, std::map<std::string, CSetting*> *loadedSettings /* = NULL */) +{ + CSingleLock lock(m_critical); + if (m_loaded || root == NULL) + return false; + + if (triggerEvents && !OnSettingsLoading()) + return false; + + if (!Deserialize(root, loadedSettings)) + return false; + + bool ret = true; + // load any ISubSettings implementations + if (triggerEvents) + ret = Load(root); + + updated = UpdateSettings(root); + + if (triggerEvents) + OnSettingsLoaded(); + + return ret; +} + +bool CSettingsManager::Save(TiXmlNode *root) const +{ + CSingleLock lock(m_critical); + if (!m_initialized || root == NULL) + return false; + + if (!OnSettingsSaving()) + return false; + + if (!Serialize(root)) + { + CLog::Log(LOGERROR, "CSettingsManager: failed to save settings"); + return false; + } + + // save any ISubSettings implementations + for (std::set<ISubSettings*>::const_iterator it = m_subSettings.begin(); it != m_subSettings.end(); it++) + { + if (!(*it)->Save(root)) + return false; + } + + OnSettingsSaved(); + + return true; +} + +void CSettingsManager::Unload() +{ + CSingleLock lock(m_critical); + m_loaded = false; + for (SettingMap::iterator setting = m_settings.begin(); setting != m_settings.end(); setting++) + setting->second.setting->Reset(); +} + +void CSettingsManager::Clear() +{ + CSingleLock lock(m_critical); + m_settings.clear(); + for (SettingSectionMap::iterator section = m_sections.begin(); section != m_sections.end(); section++) + delete section->second; + m_sections.clear(); + + OnSettingsCleared(); + + for (std::set<ISubSettings*>::const_iterator it = m_subSettings.begin(); it != m_subSettings.end(); it++) + (*it)->Clear(); + + m_loaded = false; + m_initialized = false; +} + +bool CSettingsManager::LoadSetting(const TiXmlNode *node, const std::string &settingId) +{ + if (node == NULL) + return false; + + CSetting *setting = GetSetting(settingId); + if (setting == NULL) + return false; + + return LoadSetting(node, setting); +} + +void CSettingsManager::SetInitialized() +{ + CSingleLock lock(m_critical); + if (m_initialized) + return; + + m_initialized = true; + + for (SettingMap::iterator setting = m_settings.begin(); setting != m_settings.end(); ) + { + SettingMap::iterator tmpIterator = setting++; + if (tmpIterator->second.setting == NULL) + m_settings.erase(tmpIterator); + } +} + +void CSettingsManager::RegisterCallback(ISettingCallback *callback, const std::set<std::string> &settingList) +{ + CSingleLock lock(m_critical); + if (callback == NULL) + return; + + for (std::set<std::string>::const_iterator settingIt = settingList.begin(); settingIt != settingList.end(); settingIt++) + { + std::string id = *settingIt; + StringUtils::ToLower(id); + + SettingMap::iterator setting = m_settings.find(id); + if (setting == m_settings.end()) + { + if (m_initialized) + continue; + + Setting tmpSetting = { NULL }; + std::pair<SettingMap::iterator, bool> tmpIt = m_settings.insert(make_pair(id, tmpSetting)); + setting = tmpIt.first; + } + + setting->second.callbacks.insert(callback); + } +} + +void CSettingsManager::UnregisterCallback(ISettingCallback *callback) +{ + CSingleLock lock(m_critical); + for (SettingMap::iterator settingIt = m_settings.begin(); settingIt != m_settings.end(); settingIt++) + settingIt->second.callbacks.erase(callback); +} + +void CSettingsManager::RegisterSettingType(const std::string &settingType, ISettingCreator *settingCreator) +{ + CSingleLock lock(m_critical); + if (settingType.empty() || settingCreator == NULL) + return; + + SettingCreatorMap::const_iterator creatorIt = m_settingCreators.find(settingType); + if (creatorIt == m_settingCreators.end()) + m_settingCreators.insert(make_pair(settingType, settingCreator)); +} + +void CSettingsManager::RegisterSettingsHandler(ISettingsHandler *settingsHandler) +{ + if (settingsHandler == NULL) + return; + + CSingleLock lock(m_critical); + m_settingsHandlers.insert(settingsHandler); +} + +void CSettingsManager::UnregisterSettingsHandler(ISettingsHandler *settingsHandler) +{ + if (settingsHandler == NULL) + return; + + CSingleLock lock(m_critical); + m_settingsHandlers.erase(settingsHandler); +} + +void CSettingsManager::RegisterSubSettings(ISubSettings *subSettings) +{ + CSingleLock lock(m_critical); + if (subSettings == NULL) + return; + + m_subSettings.insert(subSettings); +} + +void CSettingsManager::UnregisterSubSettings(ISubSettings *subSettings) +{ + CSingleLock lock(m_critical); + if (subSettings == NULL) + return; + + m_subSettings.erase(subSettings); +} + +void CSettingsManager::RegisterSettingOptionsFiller(const std::string &identifier, IntegerSettingOptionsFiller optionsFiller) +{ + if (identifier.empty() || optionsFiller == NULL) + return; + + RegisterSettingOptionsFiller(identifier, (void*)optionsFiller, SettingOptionsFillerTypeInteger); +} + +void CSettingsManager::RegisterSettingOptionsFiller(const std::string &identifier, StringSettingOptionsFiller optionsFiller) +{ + if (identifier.empty() || optionsFiller == NULL) + return; + + RegisterSettingOptionsFiller(identifier, (void*)optionsFiller, SettingOptionsFillerTypeString); +} + +void CSettingsManager::UnregisterSettingOptionsFiller(const std::string &identifier) +{ + m_optionsFillers.erase(identifier); +} + +void* CSettingsManager::GetSettingOptionsFiller(const CSetting *setting) +{ + if (setting == NULL) + return NULL; + + // get the option filler's identifier + std::string filler; + if (setting->GetType() == SettingTypeInteger) + filler = ((const CSettingInt*)setting)->GetOptionsFiller(); + else if (setting->GetType() == SettingTypeString) + filler = ((const CSettingString*)setting)->GetOptionsFiller(); + + if (filler.empty()) + return NULL; + + // check if such an option filler is known + SettingOptionsFillerMap::const_iterator fillerIt = m_optionsFillers.find(filler); + if (fillerIt == m_optionsFillers.end()) + return NULL; + + if (fillerIt->second.filler == NULL) + return NULL; + + // make sure the option filler's type matches the setting's type + switch (fillerIt->second.type) + { + case SettingOptionsFillerTypeInteger: + { + if (setting->GetType() != SettingTypeInteger) + return NULL; + + break; + } + + case SettingOptionsFillerTypeString: + { + if (setting->GetType() != SettingTypeString) + return NULL; + + break; + } + + default: + return NULL; + } + + return fillerIt->second.filler; +} + +CSetting* CSettingsManager::GetSetting(const std::string &id) const +{ + CSingleLock lock(m_critical); + if (id.empty()) + return NULL; + + std::string settingId = id; + StringUtils::ToLower(settingId); + + SettingMap::const_iterator setting = m_settings.find(settingId); + if (setting != m_settings.end()) + return setting->second.setting; + + CLog::Log(LOGDEBUG, "CSettingsManager: requested setting (%s) was not found.", id.c_str()); + return NULL; +} + +CSettingSection* CSettingsManager::GetSection(const std::string §ion) const +{ + CSingleLock lock(m_critical); + if (section.empty()) + return NULL; + + std::string sectionId = section; + StringUtils::ToLower(sectionId); + + SettingSectionMap::const_iterator sectionIt = m_sections.find(sectionId); + if (sectionIt != m_sections.end()) + return sectionIt->second; + + CLog::Log(LOGDEBUG, "CSettingsManager: requested setting section (%s) was not found.", section.c_str()); + return NULL; +} + +SettingDependencyMap CSettingsManager::GetDependencies(const std::string &id) const +{ + CSingleLock lock(m_critical); + SettingMap::const_iterator setting = m_settings.find(id); + if (setting == m_settings.end()) + return SettingDependencyMap(); + + return setting->second.dependencies; +} + +SettingDependencyMap CSettingsManager::GetDependencies(const CSetting *setting) const +{ + CSingleLock lock(m_critical); + if (setting == NULL) + return SettingDependencyMap(); + + return GetDependencies(setting->GetId()); +} + +bool CSettingsManager::GetBool(const std::string &id) const +{ + CSingleLock lock(m_critical); + CSetting *setting = GetSetting(id); + if (setting == NULL || setting->GetType() != SettingTypeBool) + { + // Backward compatibility (skins use this setting) + if (setting == NULL && StringUtils::EqualsNoCase(id.c_str(), "lookandfeel.enablemouse")) + return GetBool("input.enablemouse"); + + return false; + } + + return ((CSettingBool*)setting)->GetValue(); +} + +bool CSettingsManager::SetBool(const std::string &id, bool value) +{ + CSingleLock lock(m_critical); + CSetting *setting = GetSetting(id); + if (setting == NULL || setting->GetType() != SettingTypeBool) + return false; + + return ((CSettingBool*)setting)->SetValue(value); +} + +bool CSettingsManager::ToggleBool(const std::string &id) +{ + CSingleLock lock(m_critical); + CSetting *setting = GetSetting(id); + if (setting == NULL || setting->GetType() != SettingTypeBool) + return false; + + return SetBool(id, !((CSettingBool*)setting)->GetValue()); +} + +int CSettingsManager::GetInt(const std::string &id) const +{ + CSingleLock lock(m_critical); + CSetting *setting = GetSetting(id); + if (setting == NULL || setting->GetType() != SettingTypeInteger) + return 0; + + return ((CSettingInt*)setting)->GetValue(); +} + +bool CSettingsManager::SetInt(const std::string &id, int value) +{ + CSingleLock lock(m_critical); + CSetting *setting = GetSetting(id); + if (setting == NULL || setting->GetType() != SettingTypeInteger) + return false; + + return ((CSettingInt*)setting)->SetValue(value); +} + +double CSettingsManager::GetNumber(const std::string &id) const +{ + CSingleLock lock(m_critical); + CSetting *setting = GetSetting(id); + if (setting == NULL || setting->GetType() != SettingTypeNumber) + return 0.0; + + return ((CSettingNumber*)setting)->GetValue(); +} + +bool CSettingsManager::SetNumber(const std::string &id, double value) +{ + CSingleLock lock(m_critical); + CSetting *setting = GetSetting(id); + if (setting == NULL || setting->GetType() != SettingTypeNumber) + return false; + + return ((CSettingNumber*)setting)->SetValue(value); +} + +std::string CSettingsManager::GetString(const std::string &id) const +{ + CSingleLock lock(m_critical); + CSetting *setting = GetSetting(id); + if (setting == NULL || setting->GetType() != SettingTypeString) + return ""; + + return ((CSettingString*)setting)->GetValue(); +} + +bool CSettingsManager::SetString(const std::string &id, const std::string &value) +{ + CSingleLock lock(m_critical); + CSetting *setting = GetSetting(id); + if (setting == NULL || setting->GetType() != SettingTypeString) + return false; + + return ((CSettingString*)setting)->SetValue(value); +} + +void CSettingsManager::AddCondition(const std::string &condition) +{ + if (condition.empty()) + return; + + m_conditions.AddCondition(condition); +} + +void CSettingsManager::AddCondition(const std::string &identifier, SettingConditionCheck condition) +{ + if (identifier.empty() || condition == NULL) + return; + + m_conditions.AddCondition(identifier, condition); +} + +bool CSettingsManager::Serialize(TiXmlNode *parent) const +{ + if (parent == NULL) + return false; + + for (SettingMap::const_iterator it = m_settings.begin(); it != m_settings.end(); it++) + { + if (it->second.setting->GetType() == SettingTypeAction) + continue; + + std::vector<std::string> parts = StringUtils::Split(it->first, "."); + if (parts.size() != 2 || parts.at(0).empty() || parts.at(1).empty()) + { + CLog::Log(LOGWARNING, "CSettingsManager: unable to save setting \"%s\"", it->first.c_str()); + continue; + } + + TiXmlNode *sectionNode = parent->FirstChild(parts.at(0)); + if (sectionNode == NULL) + { + TiXmlElement sectionElement(parts.at(0)); + sectionNode = parent->InsertEndChild(sectionElement); + + if (sectionNode == NULL) + { + CLog::Log(LOGWARNING, "CSettingsManager: unable to write <%s> tag", parts.at(0).c_str()); + continue; + } + } + + TiXmlElement settingElement(parts.at(1)); + TiXmlNode *settingNode = sectionNode->InsertEndChild(settingElement); + if (settingNode == NULL) + { + CLog::Log(LOGWARNING, "CSetting: unable to write <%s> tag in <%s>", parts.at(1).c_str(), parts.at(0).c_str()); + continue; + } + + TiXmlText value(it->second.setting->ToString()); + settingNode->InsertEndChild(value); + } + + return true; +} + +bool CSettingsManager::Deserialize(const TiXmlNode *node, std::map<std::string, CSetting*> *loadedSettings /* = NULL */) +{ + if (node == NULL) + return false; + + for (SettingMap::iterator it = m_settings.begin(); it != m_settings.end(); it++) + { + if (LoadSetting(node, it->second.setting) && loadedSettings != NULL) + loadedSettings->insert(make_pair(it->first, it->second.setting)); + } + + return true; +} + +bool CSettingsManager::OnSettingChanging(const CSetting *setting) +{ + CSingleLock lock(m_critical); + if (setting == NULL) + return false; + + if (!m_loaded) + return true; + + SettingMap::const_iterator settingIt = m_settings.find(setting->GetId()); + if (settingIt == m_settings.end()) + return false; + + Setting settingData = settingIt->second; + // now that we have a copy of the setting's data, we can leave the lock + lock.Leave(); + + for (CallbackSet::iterator callback = settingData.callbacks.begin(); + callback != settingData.callbacks.end(); + callback++) + { + if (!(*callback)->OnSettingChanging(setting)) + return false; + } + + return true; +} + +void CSettingsManager::OnSettingChanged(const CSetting *setting) +{ + CSingleLock lock(m_critical); + if (!m_loaded || setting == NULL) + return; + + SettingMap::const_iterator settingIt = m_settings.find(setting->GetId()); + if (settingIt == m_settings.end()) + return; + + Setting settingData = settingIt->second; + // now that we have a copy of the setting's data, we can leave the lock + lock.Leave(); + + for (CallbackSet::iterator callback = settingData.callbacks.begin(); + callback != settingData.callbacks.end(); + callback++) + (*callback)->OnSettingChanged(setting); +} + +void CSettingsManager::OnSettingAction(const CSetting *setting) +{ + CSingleLock lock(m_critical); + if (!m_loaded || setting == NULL) + return; + + SettingMap::const_iterator settingIt = m_settings.find(setting->GetId()); + if (settingIt == m_settings.end()) + return; + + Setting settingData = settingIt->second; + // now that we have a copy of the setting's data, we can leave the lock + lock.Leave(); + + for (CallbackSet::iterator callback = settingData.callbacks.begin(); + callback != settingData.callbacks.end(); + callback++) + (*callback)->OnSettingAction(setting); +} + +bool CSettingsManager::OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode) +{ + CSingleLock lock(m_critical); + if (setting == NULL) + return false; + + SettingMap::const_iterator settingIt = m_settings.find(setting->GetId()); + if (settingIt == m_settings.end()) + return false; + + Setting settingData = settingIt->second; + // now that we have a copy of the setting's data, we can leave the lock + lock.Leave(); + + bool ret = false; + for (CallbackSet::iterator callback = settingData.callbacks.begin(); + callback != settingData.callbacks.end(); + callback++) + ret |= (*callback)->OnSettingUpdate(setting, oldSettingId, oldSettingNode); + + return ret; +} + +CSetting* CSettingsManager::CreateSetting(const std::string &settingType, const std::string &settingId, CSettingsManager *settingsManager /* = NULL */) const +{ + if (StringUtils::EqualsNoCase(settingType, "boolean")) + return new CSettingBool(settingId, (CSettingsManager*)this); + else if (StringUtils::EqualsNoCase(settingType, "integer")) + return new CSettingInt(settingId, (CSettingsManager*)this); + else if (StringUtils::EqualsNoCase(settingType, "number")) + return new CSettingNumber(settingId, (CSettingsManager*)this); + else if (StringUtils::EqualsNoCase(settingType, "string")) + return new CSettingString(settingId, (CSettingsManager*)this); + else if (StringUtils::EqualsNoCase(settingType, "action")) + return new CSettingAction(settingId, (CSettingsManager*)this); + + SettingCreatorMap::const_iterator creator = m_settingCreators.find(settingType); + if (creator != m_settingCreators.end()) + return creator->second->CreateSetting(settingType, settingId, (CSettingsManager*)this); + + return NULL; +} + +bool CSettingsManager::OnSettingsLoading() +{ + CSingleLock lock(m_critical); + for (SettingsHandlers::const_iterator it = m_settingsHandlers.begin(); it != m_settingsHandlers.end(); it++) + { + if (!(*it)->OnSettingsLoading()) + return false; + } + + return true; +} + +void CSettingsManager::OnSettingsLoaded() +{ + CSingleLock lock(m_critical); + for (SettingsHandlers::const_iterator it = m_settingsHandlers.begin(); it != m_settingsHandlers.end(); it++) + (*it)->OnSettingsLoaded(); +} + +bool CSettingsManager::OnSettingsSaving() const +{ + CSingleLock lock(m_critical); + for (SettingsHandlers::const_iterator it = m_settingsHandlers.begin(); it != m_settingsHandlers.end(); it++) + { + if (!(*it)->OnSettingsSaving()) + return false; + } + + return true; +} + +void CSettingsManager::OnSettingsSaved() const +{ + CSingleLock lock(m_critical); + for (SettingsHandlers::const_iterator it = m_settingsHandlers.begin(); it != m_settingsHandlers.end(); it++) + (*it)->OnSettingsSaved(); +} + +void CSettingsManager::OnSettingsCleared() +{ + CSingleLock lock(m_critical); + for (SettingsHandlers::const_iterator it = m_settingsHandlers.begin(); it != m_settingsHandlers.end(); it++) + (*it)->OnSettingsCleared(); +} + +bool CSettingsManager::Load(const TiXmlNode *settings) +{ + bool ok = true; + for (std::set<ISubSettings*>::const_iterator it = m_subSettings.begin(); it != m_subSettings.end(); it++) + ok &= (*it)->Load(settings); + + return ok; +} + +bool CSettingsManager::LoadSetting(const TiXmlNode *node, CSetting *setting) +{ + if (node == NULL || setting == NULL) + return false; + + if (setting->GetType() == SettingTypeAction) + return false; + + const std::string &settingId = setting->GetId(); + + std::vector<std::string> parts = StringUtils::Split(settingId, "."); + if (parts.size() != 2 || parts.at(0).empty() || parts.at(1).empty()) + { + CLog::Log(LOGWARNING, "CSettingsManager: unable to load setting \"%s\"", settingId.c_str()); + return false; + } + + const TiXmlNode *sectionNode = node->FirstChild(parts.at(0)); + if (sectionNode == NULL) + return false; + + const TiXmlNode *settingNode = sectionNode->FirstChild(parts.at(1)); + if (settingNode == NULL) + return false; + + if (!setting->FromString(settingNode->FirstChild() != NULL ? settingNode->FirstChild()->ValueStr() : StringUtils::Empty)) + { + CLog::Log(LOGWARNING, "CSettingsManager: unable to read value of setting \"%s\"", settingId.c_str()); + return false; + } + + return true; +} + +bool CSettingsManager::UpdateSettings(const TiXmlNode *root) +{ + bool updated = false; + + for (SettingMap::iterator setting = m_settings.begin(); setting != m_settings.end(); setting++) + { + const std::set<CSettingUpdate>& updates = setting->second.setting->GetUpdates(); + if (updates.empty()) + continue; + + for (std::set<CSettingUpdate>::const_iterator update = updates.begin(); update != updates.end(); update++) + updated |= UpdateSetting(root, setting->second.setting, *update); + } + + return updated; +} + +bool CSettingsManager::UpdateSetting(const TiXmlNode *node, CSetting *setting, const CSettingUpdate& update) +{ + if (node == NULL || setting == NULL || update.GetType() == SettingUpdateTypeNone) + return false; + + bool updated = false; + const char *oldSetting = NULL; + const TiXmlNode *oldSettingNode = NULL; + if (update.GetType() == SettingUpdateTypeRename) + { + if (update.GetValue().empty()) + return false; + + oldSetting = update.GetValue().c_str(); + std::vector<std::string> parts = StringUtils::Split(oldSetting, "."); + if (parts.size() != 2 || parts.at(0).empty() || parts.at(1).empty()) + return false; + + const TiXmlNode *sectionNode = node->FirstChild(parts.at(0)); + if (sectionNode == NULL) + return false; + + oldSettingNode = sectionNode->FirstChild(parts.at(1)); + if (oldSettingNode == NULL) + return false; + + if (setting->FromString(oldSettingNode->FirstChild() != NULL ? oldSettingNode->FirstChild()->ValueStr() : StringUtils::Empty)) + updated = true; + else + CLog::Log(LOGWARNING, "CSetting: unable to update \"%s\" through automatically renaming from \"%s\"", setting->GetId().c_str(), oldSetting); + } + + updated |= OnSettingUpdate(setting, oldSetting, oldSettingNode); + return updated; +} + +void CSettingsManager::RegisterSettingOptionsFiller(const std::string &identifier, void *filler, SettingOptionsFillerType type) +{ + SettingOptionsFillerMap::const_iterator it = m_optionsFillers.find(identifier); + if (it != m_optionsFillers.end()) + return; + + SettingOptionsFiller optionsFiller = { filler, type }; + m_optionsFillers.insert(make_pair(identifier, optionsFiller)); +} diff --git a/xbmc/settings/SettingsManager.h b/xbmc/settings/SettingsManager.h new file mode 100644 index 0000000000..54f9fa2d26 --- /dev/null +++ b/xbmc/settings/SettingsManager.h @@ -0,0 +1,414 @@ +#pragma once +/* + * Copyright (C) 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/>. + * + */ + +#include <map> +#include <set> +#include <vector> + +#include "ISetting.h" +#include "ISettingCallback.h" +#include "ISettingCreator.h" +#include "ISettingsHandler.h" +#include "ISubSettings.h" +#include "SettingConditions.h" +#include "SettingDependency.h" +#include "threads/CriticalSection.h" + +class CSettingSection; +class CSettingUpdate; + +class TiXmlElement; +class TiXmlNode; + +typedef std::pair<std::string, int> IntegerSettingOption; +typedef std::pair<std::string, std::string> StringSettingOption; +typedef std::vector<IntegerSettingOption> IntegerSettingOptions; +typedef std::vector<StringSettingOption> StringSettingOptions; +typedef void (*IntegerSettingOptionsFiller)(const CSetting *setting, IntegerSettingOptions &list, int ¤t); +typedef void (*StringSettingOptionsFiller)(const CSetting *setting, StringSettingOptions &list, std::string ¤t); + +/*! + \ingroup settings + \brief Settings manager responsible for initializing, loading and handling + all settings. + */ +class CSettingsManager : public ISettingCreator, private ISettingCallback, + private ISettingsHandler, private ISubSettings +{ +public: + /*! + \brief Creates a new (uninitialized) settings manager. + */ + CSettingsManager(); + virtual ~CSettingsManager(); + + // implementation of ISettingCreator + virtual CSetting* CreateSetting(const std::string &settingType, const std::string &settingId, CSettingsManager *settingsManager = NULL) const; + + /*! + \brief Initializes the settings manager using the setting definitions + represented by the given XML element. + + \param root XML element representing setting definitions + \return True if the XML element was successfully deserialized into setting definitions, false otherwise + */ + bool Initialize(const TiXmlElement *root); + /*! + \brief Loads setting values from the given XML element. + + \param root XML element containing setting values + \param updated Whether some settings were automatically updated + \param triggerEvents Whether to trigger ISettingCallback methods + \param loadedSettings A list to fill with all the successfully loaded settings + \return True if the setting values were successfully loaded, false otherwise + */ + bool Load(const TiXmlElement *root, bool &updated, bool triggerEvents = true, std::map<std::string, CSetting*> *loadedSettings = NULL); + /*! + \brief Saves the setting values to the given XML node. + + \param root XML node + \return True if the setting values were successfully saved, false otherwise + */ + virtual bool Save(TiXmlNode *root) const; + /*! + \brief Unloads the previously loaded setting values. + + The values of all the settings are reset to their default values. + */ + void Unload(); + /*! + \brief Clears the complete settings manager. + + This removes all initialized settings, groups, categories and sections and + returns to the uninitialized state. Any registered callbacks or + implementations stay registered. + */ + void Clear(); + + /*! + \brief Loads the setting being represented by the given XML node with the + given identifier. + + \param node XML node representing the setting to load + \param settingId Setting identifier + \return True if the setting was successfully loaded from the given XML node, false otherwise + */ + bool LoadSetting(const TiXmlNode *node, const std::string &settingId); + + /*! + \brief Tells the settings system that the initialization is complete. + + Setting values can only be loaded after a complete and successful + initialization of the settings system. + */ + void SetInitialized(); + /*! + \brief Tells the settings system that all setting values + have been loaded. + + This manual trigger is necessary to enable the ISettingCallback methods + being executed. + */ + void SetLoaded() { m_loaded = true; } + + /*! + \brief Registers the given ISettingCallback implementation to be triggered + for the given list of settings. + + \param settingsHandler ISettingsHandler implementation + \param settingList List of settings to trigger the given ISettingCallback implementation + */ + void RegisterCallback(ISettingCallback *callback, const std::set<std::string> &settingList); + /*! + \brief Unregisters the given ISettingCallback implementation. + + \param callback ISettingCallback implementation + */ + void UnregisterCallback(ISettingCallback *callback); + + /*! + \brief Registers a custom setting type and its ISettingCreator + implementation. + + When a setting definition for a registered custom setting type is found its + ISettingCreator implementation is called to create and deserialize the + setting definition. + + \param settingType String representation of the custom setting type + \param settingCreator ISettingCreator implementation + */ + void RegisterSettingType(const std::string &settingType, ISettingCreator *settingCreator); + + /*! + \brief Registers the given ISettingsHandler implementation. + + \param settingsHandler ISettingsHandler implementation + */ + void RegisterSettingsHandler(ISettingsHandler *settingsHandler); + /*! + \brief Unregisters the given ISettingsHandler implementation. + + \param settingsHandler ISettingsHandler implementation + */ + void UnregisterSettingsHandler(ISettingsHandler *settingsHandler); + + /*! + \brief Registers the given ISubSettings implementation. + + \param subSettings ISubSettings implementation + */ + void RegisterSubSettings(ISubSettings *subSettings); + /*! + \brief Unregisters the given ISubSettings implementation. + + \param subSettings ISubSettings implementation + */ + void UnregisterSubSettings(ISubSettings *subSettings); + + /*! + \brief Registers the given integer setting options filler under the given identifier. + + \param identifier Setting options filler identifier + \param optionsFiller Integer setting options filler implementation + */ + void RegisterSettingOptionsFiller(const std::string &identifier, IntegerSettingOptionsFiller optionsFiller); + /*! + \brief Registers the given string setting options filler under the given identifier. + + \param identifier Setting options filler identifier + \param optionsFiller String setting options filler implementation + */ + void RegisterSettingOptionsFiller(const std::string &identifier, StringSettingOptionsFiller optionsFiller); + /*! + \brief Unregisters the setting options filler registered under the given identifier. + + \param identifier Setting options filler identifier + */ + void UnregisterSettingOptionsFiller(const std::string &identifier); + /*! + \brief Gets the implementation of the setting options filler used by the + given setting. + + \param setting Setting object + \return Implementation of the setting options filler (either IntegerSettingOptionsFiller or StringSettingOptionsFiller) + */ + void* GetSettingOptionsFiller(const CSetting *setting); + + /*! + \brief Gets the setting with the given identifier. + + \param id Setting identifier + \return Setting object with the given identifier or NULL if the identifier is unknown + */ + CSetting* GetSetting(const std::string &id) const; + /*! + \brief Gets the setting section with the given identifier. + + \param section Setting section identifier + \return Setting section with the given identifier or NULL if the identifier is unknown + */ + CSettingSection* GetSection(const std::string §ion) const; + /*! + \brief Gets a map of settings (and their dependencies) which depend on + the setting with the given identifier. + + It is important to note that the returned dependencies are not the + dependencies of the setting with the given identifier but the settings + (and their dependencies) which depend on the setting with the given + identifier. + + \param id Setting identifier + \return Map of settings (and their dependencies) which depend on the setting with the given identifier + */ + SettingDependencyMap GetDependencies(const std::string &id) const; + /*! + \brief Gets a map of settings (and their dependencies) which depend on + the given setting. + + It is important to note that the returned dependencies are not the + dependencies of the given setting but the settings (and their dependencies) + which depend on the given setting. + + \param setting Setting object + \return Map of settings (and their dependencies) which depend on the given setting + */ + SettingDependencyMap GetDependencies(const CSetting *setting) const; + + /*! + \brief Gets the boolean value of the setting with the given identifier. + + \param id Setting identifier + \return Boolean value of the setting with the given identifier + */ + bool GetBool(const std::string &id) const; + /*! + \brief Gets the integer value of the setting with the given identifier. + + \param id Setting identifier + \return Integer value of the setting with the given identifier + */ + int GetInt(const std::string &id) const; + /*! + \brief Gets the real number value of the setting with the given identifier. + + \param id Setting identifier + \return Real number value of the setting with the given identifier + */ + double GetNumber(const std::string &id) const; + /*! + \brief Gets the string value of the setting with the given identifier. + + \param id Setting identifier + \return String value of the setting with the given identifier + */ + std::string GetString(const std::string &id) const; + + /*! + \brief Sets the boolean value of the setting with the given identifier. + + \param id Setting identifier + \param value Boolean value to set + \return True if setting the value was successful, false otherwise + */ + bool SetBool(const std::string &id, bool value); + /*! + \brief Toggles the boolean value of the setting with the given identifier. + + \param id Setting identifier + \return True if toggling the boolean value was successful, false otherwise + */ + bool ToggleBool(const std::string &id); + /*! + \brief Sets the integer value of the setting with the given identifier. + + \param id Setting identifier + \param value Integer value to set + \return True if setting the value was successful, false otherwise + */ + bool SetInt(const std::string &id, int value); + /*! + \brief Sets the real number value of the setting with the given identifier. + + \param id Setting identifier + \param value Real number value to set + \return True if setting the value was successful, false otherwise + */ + bool SetNumber(const std::string &id, double value); + /*! + \brief Sets the string value of the setting with the given identifier. + + \param id Setting identifier + \param value String value to set + \return True if setting the value was successful, false otherwise + */ + bool SetString(const std::string &id, const std::string &value); + + /*! + \brief Gets the setting conditions manager used by the settings manager. + + \return Setting conditions manager used by the settings manager. + */ + const CSettingConditionsManager& GetConditions() const { return m_conditions; } + /*! + \brief Adds the given static condition. + + A static condition is just a string. If a static condition is evaluated, + the result depends on whether the condition's value is defined or not. + + \param condition Static condition string/value + */ + void AddCondition(const std::string &condition); + /*! + \brief Adds the given dynamic condition. + + A dynamic condition has an identifier and an implementation which is + triggered when the condition is evaluated. + + \param identifier Identifier of the dynamic condition + \param condition Implementation of the dynamic condition + */ + void AddCondition(const std::string &identifier, SettingConditionCheck condition); + +private: + // implementation of ISettingCallback + virtual bool OnSettingChanging(const CSetting *setting); + virtual void OnSettingChanged(const CSetting *setting); + virtual void OnSettingAction(const CSetting *setting); + virtual bool OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode); + + // implementation of ISettingsHandler + virtual bool OnSettingsLoading(); + virtual void OnSettingsLoaded(); + virtual bool OnSettingsSaving() const; + virtual void OnSettingsSaved() const; + virtual void OnSettingsCleared(); + + // implementation of ISubSettings + virtual bool Load(const TiXmlNode *settings); + + bool Serialize(TiXmlNode *parent) const; + bool Deserialize(const TiXmlNode *node, std::map<std::string, CSetting*> *loadedSettings = NULL); + + bool LoadSetting(const TiXmlNode *node, CSetting *setting); + bool UpdateSettings(const TiXmlNode *root); + bool UpdateSetting(const TiXmlNode *node, CSetting *setting, const CSettingUpdate& update); + + typedef enum { + SettingOptionsFillerTypeNone = 0, + SettingOptionsFillerTypeInteger, + SettingOptionsFillerTypeString + } SettingOptionsFillerType; + + void RegisterSettingOptionsFiller(const std::string &identifier, void *filler, SettingOptionsFillerType type); + + typedef std::set<ISettingCallback *> CallbackSet; + typedef struct { + CSetting *setting; + SettingDependencyMap dependencies; + CallbackSet callbacks; + } Setting; + + bool m_initialized; + bool m_loaded; + + typedef std::map<std::string, Setting> SettingMap; + SettingMap m_settings; + typedef std::map<std::string, CSettingSection*> SettingSectionMap; + SettingSectionMap m_sections; + + typedef std::map<std::string, ISettingCreator*> SettingCreatorMap; + SettingCreatorMap m_settingCreators; + + std::set<ISubSettings*> m_subSettings; + typedef std::set<ISettingsHandler*> SettingsHandlers; + SettingsHandlers m_settingsHandlers; + + CSettingConditionsManager m_conditions; + + typedef struct { + void *filler; + SettingOptionsFillerType type; + } SettingOptionsFiller; + typedef std::map<std::string, SettingOptionsFiller> SettingOptionsFillerMap; + SettingOptionsFillerMap m_optionsFillers; + + CCriticalSection m_critical; +}; diff --git a/xbmc/settings/SkinSettings.cpp b/xbmc/settings/SkinSettings.cpp index 0d9044eabf..bc665edc73 100644 --- a/xbmc/settings/SkinSettings.cpp +++ b/xbmc/settings/SkinSettings.cpp @@ -22,7 +22,7 @@ #include "SkinSettings.h" #include "GUIInfoManager.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "threads/SingleLock.h" #include "utils/log.h" #include "utils/StringUtils.h" @@ -277,5 +277,5 @@ void CSkinSettings::Clear() std::string CSkinSettings::GetCurrentSkin() const { - return g_guiSettings.GetString("lookandfeel.skin"); + return CSettings::Get().GetString("lookandfeel.skin"); }
\ No newline at end of file diff --git a/xbmc/settings/dialogs/GUIDialogContentSettings.cpp b/xbmc/settings/dialogs/GUIDialogContentSettings.cpp index d68d25e7d5..fd5a86fcd0 100644 --- a/xbmc/settings/dialogs/GUIDialogContentSettings.cpp +++ b/xbmc/settings/dialogs/GUIDialogContentSettings.cpp @@ -20,7 +20,6 @@ #include "GUIDialogContentSettings.h" #include "addons/GUIDialogAddonSettings.h" -#include "settings/GUISettings.h" #include "guilib/GUIWindowManager.h" #include "guilib/Key.h" #include "addons/IAddon.h" diff --git a/xbmc/settings/dialogs/GUIDialogSettings.cpp b/xbmc/settings/dialogs/GUIDialogSettings.cpp index ce737e5e46..708de2417e 100644 --- a/xbmc/settings/dialogs/GUIDialogSettings.cpp +++ b/xbmc/settings/dialogs/GUIDialogSettings.cpp @@ -26,7 +26,6 @@ #include "guilib/GUIImage.h" #include "guilib/GUIControlGroupList.h" #include "guilib/LocalizeStrings.h" -#include "settings/GUISettings.h" #include "utils/log.h" #include "guilib/GUIKeyboardFactory.h" diff --git a/xbmc/settings/windows/GUIControlSettings.cpp b/xbmc/settings/windows/GUIControlSettings.cpp new file mode 100644 index 0000000000..7313b49cd4 --- /dev/null +++ b/xbmc/settings/windows/GUIControlSettings.cpp @@ -0,0 +1,396 @@ +/* + * Copyright (C) 2005-2012 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 "GUIControlSettings.h" +#include "Util.h" +#include "addons/AddonManager.h" +#include "addons/GUIWindowAddonBrowser.h" +#include "dialogs/GUIDialogFileBrowser.h" +#include "dialogs/GUIDialogOK.h" +#include "guilib/GUIEditControl.h" +#include "guilib/GUIImage.h" +#include "guilib/GUIRadioButtonControl.h" +#include "guilib/GUISpinControlEx.h" +#include "guilib/LocalizeStrings.h" +#include "settings/SettingAddon.h" +#include "settings/SettingPath.h" +#include "settings/Settings.h" +#include "settings/MediaSourceSettings.h" +#include "settings/Setting.h" +#include "storage/MediaManager.h" +#include "utils/StringUtils.h" + +using namespace ADDON; + +CGUIControlBaseSetting::CGUIControlBaseSetting(int id, CSetting *pSetting) +{ + m_id = id; + m_pSetting = pSetting; + m_delayed = false; + m_enabled = true; +} + +void CGUIControlBaseSetting::Update() +{ + CGUIControl *control = GetControl(); + if (control != NULL) + control->SetEnabled(IsEnabled()); +} + +CGUIControlRadioButtonSetting::CGUIControlRadioButtonSetting(CGUIRadioButtonControl *pRadioButton, int id, CSetting *pSetting) + : CGUIControlBaseSetting(id, pSetting) +{ + m_pRadioButton = pRadioButton; + m_pRadioButton->SetID(id); + Update(); +} + +CGUIControlRadioButtonSetting::~CGUIControlRadioButtonSetting() +{ } + +bool CGUIControlRadioButtonSetting::OnClick() +{ + return ((CSettingBool *)m_pSetting)->SetValue(!((CSettingBool *)m_pSetting)->GetValue()); +} + +void CGUIControlRadioButtonSetting::Update() +{ + if (m_pRadioButton == NULL) + return; + + CGUIControlBaseSetting::Update(); + + m_pRadioButton->SetSelected(((CSettingBool *)m_pSetting)->GetValue()); +} + +CGUIControlSpinExSetting::CGUIControlSpinExSetting(CGUISpinControlEx *pSpin, int id, CSetting *pSetting) + : CGUIControlBaseSetting(id, pSetting) +{ + m_pSpin = pSpin; + m_pSpin->SetID(id); + + switch (pSetting->GetControl().GetFormat()) + { + case SettingControlFormatNumber: + { + CSettingNumber *pSettingNumber = (CSettingNumber *)pSetting; + m_pSpin->SetType(SPIN_CONTROL_TYPE_FLOAT); + m_pSpin->SetFloatRange((float)pSettingNumber->GetMinimum(), (float)pSettingNumber->GetMaximum()); + m_pSpin->SetFloatInterval((float)pSettingNumber->GetStep()); + break; + } + + case SettingControlFormatInteger: + case SettingControlFormatString: + { + m_pSpin->SetType(SPIN_CONTROL_TYPE_TEXT); + m_pSpin->Clear(); + + if (pSetting->GetType() == SettingTypeInteger) + { + CSettingInt *pSettingInt = (CSettingInt *)pSetting; + + const SettingOptions& options = pSettingInt->GetOptions(); + if (!options.empty()) + { + for (SettingOptions::const_iterator it = options.begin(); it != options.end(); it++) + m_pSpin->AddLabel(g_localizeStrings.Get(it->first), it->second); + m_pSpin->SetValue(pSettingInt->GetValue()); + } + else + { + std::string strLabel; + int i = pSettingInt->GetMinimum(); + if (pSettingInt->GetMinimumLabel() > -1) + { + strLabel = g_localizeStrings.Get(pSettingInt->GetMinimumLabel()); + m_pSpin->AddLabel(strLabel, pSettingInt->GetMinimum()); + i += pSettingInt->GetStep(); + } + for (; i <= pSettingInt->GetMaximum(); i += pSettingInt->GetStep()) + { + if (pSettingInt->GetFormat() > -1) + strLabel = StringUtils::Format(g_localizeStrings.Get(pSettingInt->GetFormat()).c_str(), i); + else + strLabel = StringUtils::Format(pSettingInt->GetFormatString().c_str(), i); + m_pSpin->AddLabel(strLabel, i); + } + } + } + break; + } + + default: + break; + } +} + +CGUIControlSpinExSetting::~CGUIControlSpinExSetting() +{ } + +bool CGUIControlSpinExSetting::OnClick() +{ + if (m_pSpin == NULL) + return false; + + switch (m_pSetting->GetType()) + { + case SettingTypeInteger: + return ((CSettingInt *)m_pSetting)->SetValue(m_pSpin->GetValue()); + break; + + case SettingTypeNumber: + return ((CSettingNumber *)m_pSetting)->SetValue(m_pSpin->GetFloatValue()); + + case SettingTypeString: + return ((CSettingString *)m_pSetting)->SetValue(m_pSpin->GetStringValue()); + + default: + break; + } + + return false; +} + +void CGUIControlSpinExSetting::Update() +{ + if (m_pSpin == NULL) + return; + + CGUIControlBaseSetting::Update(); + + switch (m_pSetting->GetType()) + { + case SettingTypeInteger: + m_pSpin->SetValue(((CSettingInt *)m_pSetting)->GetValue()); + break; + + case SettingTypeNumber: + m_pSpin->SetFloatValue((float)((CSettingNumber *)m_pSetting)->GetValue()); + break; + + case SettingTypeString: + m_pSpin->SetStringValue(((CSettingString *)m_pSetting)->GetValue()); + break; + + default: + break; + } + + // disable the spinner if it has less than two items + if (!m_pSpin->IsDisabled() && (m_pSpin->GetMaximum() - m_pSpin->GetMinimum()) == 0) + m_pSpin->SetEnabled(false); +} + +CGUIControlButtonSetting::CGUIControlButtonSetting(CGUIButtonControl *pButton, int id, CSetting *pSetting) + : CGUIControlBaseSetting(id, pSetting) +{ + m_pButton = pButton; + m_pButton->SetID(id); + Update(); +} + +CGUIControlButtonSetting::~CGUIControlButtonSetting() +{ } + +bool CGUIControlButtonSetting::OnClick() +{ + if (m_pButton == NULL) + return false; + + bool success = false; + switch (m_pSetting->GetControl().GetFormat()) + { + case SettingControlFormatAddon: + { + // prompt for the addon + CSettingAddon *setting = (CSettingAddon *)m_pSetting; + CStdString addonID = setting->GetValue(); + if (!CGUIWindowAddonBrowser::SelectAddonID(setting->GetAddonType(), addonID, setting->AllowEmpty()) == 1) + return false; + + success = setting->SetValue(addonID); + break; + } + + case SettingControlFormatPath: + { + success = GetPath((CSettingPath *)m_pSetting); + break; + } + + case SettingControlFormatAction: + { + // simply call the OnSettingAction callback and whoever knows what to + // do can do so (based on the setting's identification + CSettingAction *pSettingAction = (CSettingAction *)m_pSetting; + pSettingAction->OnSettingAction(pSettingAction); + success = true; + break; + } + + default: + return false; + } + + return success; +} + +void CGUIControlButtonSetting::Update() +{ + if (m_pButton == NULL) + return; + + CGUIControlBaseSetting::Update(); + + if (m_pSetting->GetType() == SettingTypeString) + { + std::string strText = ((CSettingString *)m_pSetting)->GetValue(); + switch (m_pSetting->GetControl().GetFormat()) + { + case SettingControlFormatAddon: + { + ADDON::AddonPtr addon; + if (ADDON::CAddonMgr::Get().GetAddon(strText, addon)) + strText = addon->Name(); + if (strText.empty()) + strText = g_localizeStrings.Get(231); // None + break; + } + + case SettingControlFormatPath: + { + CStdString shortPath; + if (CUtil::MakeShortenPath(strText, shortPath, 30)) + strText = shortPath; + break; + } + + default: + return; + } + + m_pButton->SetLabel2(strText); + } +} + +bool CGUIControlButtonSetting::GetPath(CSettingPath *pathSetting) +{ + if (pathSetting == NULL) + return false; + + CStdString path = pathSetting->GetValue(); + + VECSOURCES shares; + const std::vector<std::string>& sources = pathSetting->GetSources(); + for (std::vector<std::string>::const_iterator source = sources.begin(); source != sources.end(); source++) + { + VECSOURCES *sources = CMediaSourceSettings::Get().GetSources(*source); + if (sources != NULL) + shares.insert(shares.end(), sources->begin(), sources->end()); + } + + g_mediaManager.GetNetworkLocations(shares); + g_mediaManager.GetLocalDrives(shares); + + if (!CGUIDialogFileBrowser::ShowAndGetDirectory(shares, g_localizeStrings.Get(pathSetting->GetHeading()), path, pathSetting->Writable())) + return false; + + return pathSetting->SetValue(path); +} + +CGUIControlEditSetting::CGUIControlEditSetting(CGUIEditControl *pEdit, int id, CSetting *pSetting) + : CGUIControlBaseSetting(id, pSetting) +{ + m_pEdit = pEdit; + m_pEdit->SetID(id); + int heading = m_pSetting->GetLabel(); + if (m_pSetting->GetType() == SettingTypeString) + { + CSettingString *pSettingString = (CSettingString *)m_pSetting; + if (pSettingString->GetHeading() > 0) + heading = pSettingString->GetHeading(); + } + if (heading < 0) + heading = 0; + + CGUIEditControl::INPUT_TYPE inputType = CGUIEditControl::INPUT_TYPE_TEXT; + const CSettingControl& control = pSetting->GetControl(); + switch (control.GetFormat()) + { + case SettingControlFormatString: + if (control.GetAttributes() & SettingControlAttributeHidden) + inputType = CGUIEditControl::INPUT_TYPE_PASSWORD; + break; + + case SettingControlFormatInteger: + if (control.GetAttributes() & SettingControlAttributeVerifyNew) + inputType = CGUIEditControl::INPUT_TYPE_PASSWORD_NUMBER_VERIFY_NEW; + else + inputType = CGUIEditControl::INPUT_TYPE_NUMBER; + break; + + case SettingControlFormatIP: + inputType = CGUIEditControl::INPUT_TYPE_IPADDRESS; + break; + + case SettingControlFormatMD5: + inputType = CGUIEditControl::INPUT_TYPE_PASSWORD_MD5; + break; + + default: + break; + } + m_pEdit->SetInputType(inputType, heading); + + Update(); +} + +CGUIControlEditSetting::~CGUIControlEditSetting() +{ } + +bool CGUIControlEditSetting::OnClick() +{ + if (m_pEdit == NULL) + return false; + + // update our string + return m_pSetting->FromString(m_pEdit->GetLabel2()); +} + +void CGUIControlEditSetting::Update() +{ + if (m_pEdit == NULL) + return; + + CGUIControlBaseSetting::Update(); + + m_pEdit->SetLabel2(m_pSetting->ToString()); +} + +CGUIControlSeparatorSetting::CGUIControlSeparatorSetting(CGUIImage *pImage, int id) + : CGUIControlBaseSetting(id, NULL) +{ + m_pImage = pImage; + m_pImage->SetID(id); +} + +CGUIControlSeparatorSetting::~CGUIControlSeparatorSetting() +{ } diff --git a/xbmc/settings/windows/GUIControlSettings.h b/xbmc/settings/windows/GUIControlSettings.h new file mode 100644 index 0000000000..c95195a73e --- /dev/null +++ b/xbmc/settings/windows/GUIControlSettings.h @@ -0,0 +1,164 @@ +#pragma once +/* + * Copyright (C) 2005-2012 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 "utils/StdString.h" + +class CGUIControl; +class CGUIImage; +class CGUISpinControlEx; +class CGUIEditControl; +class CGUIButtonControl; +class CGUIRadioButtonControl; + +class CSetting; +class CSettingPath; + +class CGUIControlBaseSetting +{ +public: + CGUIControlBaseSetting(int id, CSetting *pSetting); + virtual ~CGUIControlBaseSetting() {} + + int GetID() { return m_id; } + CSetting* GetSetting() { return m_pSetting; } + + /*! + \brief Specifies that this setting should update after a delay + Useful for settings that have options to navigate through + and may take a while, or require additional input to update + once the final setting is chosen. Settings default to updating + instantly. + \sa IsDelayed() + */ + void SetDelayed() { m_delayed = true; } + + /*! + \brief Returns whether this setting should have delayed update + \return true if the setting's update should be delayed + \sa SetDelayed() + */ + bool IsDelayed() const { return m_delayed; } + + /*! + \brief Specifies that this setting is enabled or disabled + This is used for settings which are enabled/disabled based + on conditions involving other settings and their values. + It must not be confused with a setting spin control being + disabled because it contains less than two items. + \param enabled Whether the setting is enabled or disabled + \sa IsEnabled() + */ + void SetEnabled(bool enabled) { m_enabled = enabled; } + + /*! + \brief Returns whether this setting is enabled or disabled + This state is independent of the real enabled state of a + setting control but represents the enabled state of the + setting itself based on specific conditions. + \return true if the setting is enabled otherwise false + \sa SetEnabled() + */ + bool IsEnabled() const { return m_enabled; } + + virtual CGUIControl* GetControl() { return NULL; } + virtual bool OnClick() { return false; } + virtual void Update(); + virtual void Clear() = 0; ///< Clears the attached control +protected: + int m_id; + CSetting* m_pSetting; + bool m_delayed; + bool m_enabled; +}; + +class CGUIControlRadioButtonSetting : public CGUIControlBaseSetting +{ +public: + CGUIControlRadioButtonSetting(CGUIRadioButtonControl* pRadioButton, int id, CSetting *pSetting); + virtual ~CGUIControlRadioButtonSetting(); + + void Select(bool bSelect); + + virtual CGUIControl* GetControl() { return (CGUIControl*)m_pRadioButton; } + virtual bool OnClick(); + virtual void Update(); + virtual void Clear() { m_pRadioButton = NULL; } +private: + CGUIRadioButtonControl *m_pRadioButton; +}; + +class CGUIControlSpinExSetting : public CGUIControlBaseSetting +{ +public: + CGUIControlSpinExSetting(CGUISpinControlEx* pSpin, int id, CSetting *pSetting); + virtual ~CGUIControlSpinExSetting(); + + virtual CGUIControl* GetControl() { return (CGUIControl*)m_pSpin; } + virtual bool OnClick(); + virtual void Update(); + virtual void Clear() { m_pSpin = NULL; } +private: + CGUISpinControlEx *m_pSpin; +}; + +class CGUIControlButtonSetting : public CGUIControlBaseSetting +{ +public: + CGUIControlButtonSetting(CGUIButtonControl* pButton, int id, CSetting *pSetting); + virtual ~CGUIControlButtonSetting(); + + virtual CGUIControl* GetControl() { return (CGUIControl*)m_pButton; } + virtual bool OnClick(); + virtual void Update(); + virtual void Clear() { m_pButton = NULL; } + + static bool GetPath(CSettingPath *pathSetting); +private: + CGUIButtonControl *m_pButton; +}; + +class CGUIControlEditSetting : public CGUIControlBaseSetting +{ +public: + CGUIControlEditSetting(CGUIEditControl* pButton, int id, CSetting *pSetting); + virtual ~CGUIControlEditSetting(); + + virtual CGUIControl* GetControl() { return (CGUIControl*)m_pEdit; } + virtual bool OnClick(); + virtual void Update(); + virtual void Clear() { m_pEdit = NULL; } +private: + CGUIEditControl *m_pEdit; +}; + +class CGUIControlSeparatorSetting : public CGUIControlBaseSetting +{ +public: + CGUIControlSeparatorSetting(CGUIImage* pImage, int id); + virtual ~CGUIControlSeparatorSetting(); + + virtual CGUIControl* GetControl() { return (CGUIControl*)m_pImage; } + virtual bool OnClick() { return false; } + virtual void Update() {} + virtual void Clear() { m_pImage = NULL; } +private: + CGUIImage *m_pImage; +}; diff --git a/xbmc/settings/windows/GUISettingControls.cpp b/xbmc/settings/windows/GUISettingControls.cpp deleted file mode 100644 index 40a6df2eb4..0000000000 --- a/xbmc/settings/windows/GUISettingControls.cpp +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright (C) 2005-2013 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 "GUISettingControls.h" -#include "guilib/GUIRadioButtonControl.h" -#include "guilib/GUISpinControlEx.h" -#include "guilib/GUIEditControl.h" -#include "Util.h" -#include "dialogs/GUIDialogOK.h" -#include "settings/GUISettings.h" -#include "guilib/GUIImage.h" -#include "guilib/LocalizeStrings.h" -#include "addons/AddonManager.h" - -CGUIBaseSettingControl::CGUIBaseSettingControl(int id, CSetting *pSetting) -{ - m_id = id; - m_pSetting = pSetting; - m_delayed = false; -} - -CGUIRadioButtonSettingControl::CGUIRadioButtonSettingControl(CGUIRadioButtonControl *pRadioButton, int id, CSetting *pSetting) - : CGUIBaseSettingControl(id, pSetting) -{ - m_pRadioButton = pRadioButton; - m_pRadioButton->SetID(id); - Update(); -} - -CGUIRadioButtonSettingControl::~CGUIRadioButtonSettingControl() -{} - -bool CGUIRadioButtonSettingControl::OnClick() -{ - ((CSettingBool *)m_pSetting)->SetData(!((CSettingBool *)m_pSetting)->GetData()); - return true; -} - -void CGUIRadioButtonSettingControl::Update() -{ - if (m_pRadioButton) - m_pRadioButton->SetSelected(((CSettingBool *)m_pSetting)->GetData()); -} - -CGUISpinExSettingControl::CGUISpinExSettingControl(CGUISpinControlEx *pSpin, int id, CSetting *pSetting) - : CGUIBaseSettingControl(id, pSetting) -{ - m_pSpin = pSpin; - m_pSpin->SetID(id); - if (pSetting->GetControlType() == SPIN_CONTROL_FLOAT) - { - CSettingFloat *pSettingFloat = (CSettingFloat *)pSetting; - m_pSpin->SetType(SPIN_CONTROL_TYPE_FLOAT); - m_pSpin->SetFloatRange(pSettingFloat->m_fMin, pSettingFloat->m_fMax); - m_pSpin->SetFloatInterval(pSettingFloat->m_fStep); - } - else if (pSetting->GetControlType() == SPIN_CONTROL_INT_PLUS || pSetting->GetControlType() == SPIN_CONTROL_INT) - { - CSettingInt *pSettingInt = (CSettingInt *)pSetting; - m_pSpin->SetType(SPIN_CONTROL_TYPE_TEXT); - m_pSpin->Clear(); - CStdString strLabel; - int i = pSettingInt->m_iMin; - if (pSettingInt->m_iLabelMin>-1) - { - strLabel=g_localizeStrings.Get(pSettingInt->m_iLabelMin); - m_pSpin->AddLabel(strLabel, pSettingInt->m_iMin); - i += pSettingInt->m_iStep; - } - for (; i <= pSettingInt->m_iMax; i += pSettingInt->m_iStep) - { - if (pSettingInt->m_iFormat > -1) - { - CStdString strFormat = g_localizeStrings.Get(pSettingInt->m_iFormat); - strLabel.Format(strFormat, i); - } - else - strLabel.Format(pSettingInt->m_strFormat, i); - m_pSpin->AddLabel(strLabel, i); - } - } - else // if (pSetting->GetControlType() == SPIN_CONTROL_TEXT) - { - m_pSpin->SetType(SPIN_CONTROL_TYPE_TEXT); - m_pSpin->Clear(); - } - Update(); -} - -CGUISpinExSettingControl::~CGUISpinExSettingControl() -{} - -bool CGUISpinExSettingControl::OnClick() -{ - // TODO: Should really check for a change here (as end of spincontrols may - // cause no change) - if (m_pSetting->GetControlType() == SPIN_CONTROL_FLOAT) - ((CSettingFloat *)m_pSetting)->SetData(m_pSpin->GetFloatValue()); - else - { - if (m_pSetting->GetType() == SETTINGS_TYPE_INT) - { - CSettingInt *pSettingInt = (CSettingInt *)m_pSetting; - pSettingInt->SetData(m_pSpin->GetValue()); - } - } - return true; -} - -void CGUISpinExSettingControl::Update() -{ - if (!m_pSpin) - return; - if (m_pSetting->GetControlType() == SPIN_CONTROL_FLOAT) - { - CSettingFloat *pSettingFloat = (CSettingFloat *)m_pSetting; - m_pSpin->SetFloatValue(pSettingFloat->GetData()); - } - else if (m_pSetting->GetControlType() == SPIN_CONTROL_INT_PLUS || m_pSetting->GetControlType() == SPIN_CONTROL_INT) - { - CSettingInt *pSettingInt = (CSettingInt *)m_pSetting; - m_pSpin->SetValue(pSettingInt->GetData()); - } -} - -CGUIButtonSettingControl::CGUIButtonSettingControl(CGUIButtonControl *pButton, int id, CSetting *pSetting) - : CGUIBaseSettingControl(id, pSetting) -{ - m_pButton = pButton; - m_pButton->SetID(id); - Update(); -} - -CGUIButtonSettingControl::~CGUIButtonSettingControl() -{} - -bool CGUIButtonSettingControl::OnClick() -{ - // this is pretty much a no-op as all click action is done in the calling class - Update(); - return true; -} - -void CGUIButtonSettingControl::Update() -{ - CStdString strText = ((CSettingString *)m_pSetting)->GetData(); - if (m_pSetting->GetType() == SETTINGS_TYPE_ADDON) - { - ADDON::AddonPtr addon; - if (ADDON::CAddonMgr::Get().GetAddon(strText, addon)) - strText = addon->Name(); - if (strText.IsEmpty()) - strText = g_localizeStrings.Get(231); // None - } - else if (m_pSetting->GetControlType() == BUTTON_CONTROL_PATH_INPUT) - { - CStdString shortPath; - if (CUtil::MakeShortenPath(strText, shortPath, 30 )) - strText = shortPath; - } - else if (m_pSetting->GetControlType() == BUTTON_CONTROL_STANDARD) - return; - if (m_pButton) - m_pButton->SetLabel2(strText); -} - -CGUIEditSettingControl::CGUIEditSettingControl(CGUIEditControl *pEdit, int id, CSetting *pSetting) - : CGUIBaseSettingControl(id, pSetting) -{ - m_needsUpdate = false; - m_pEdit = pEdit; - m_pEdit->SetID(id); - int heading = ((CSettingString *)m_pSetting)->m_iHeadingString; - if (heading < 0) heading = 0; - if (pSetting->GetControlType() == EDIT_CONTROL_HIDDEN_INPUT) - m_pEdit->SetInputType(CGUIEditControl::INPUT_TYPE_PASSWORD, heading); - else if (pSetting->GetControlType() == EDIT_CONTROL_MD5_INPUT) - m_pEdit->SetInputType(CGUIEditControl::INPUT_TYPE_PASSWORD_MD5, heading); - else if (pSetting->GetControlType() == EDIT_CONTROL_IP_INPUT) - m_pEdit->SetInputType(CGUIEditControl::INPUT_TYPE_IPADDRESS, heading); - else if (pSetting->GetControlType() == EDIT_CONTROL_NUMBER_INPUT) - m_pEdit->SetInputType(CGUIEditControl::INPUT_TYPE_NUMBER, heading); - else if (pSetting->GetControlType() == EDIT_CONTROL_HIDDEN_NUMBER_VERIFY_NEW) - m_pEdit->SetInputType(CGUIEditControl::INPUT_TYPE_PASSWORD_NUMBER_VERIFY_NEW, heading); - else - m_pEdit->SetInputType(CGUIEditControl::INPUT_TYPE_TEXT, heading); - Update(); -} - -CGUIEditSettingControl::~CGUIEditSettingControl() -{ -} - -bool CGUIEditSettingControl::OnClick() -{ - // update our string - ((CSettingString *)m_pSetting)->SetData(m_pEdit->GetLabel2()); - // we update on exit only - m_needsUpdate = true; - return false; -} - -void CGUIEditSettingControl::Update() -{ - if (!m_needsUpdate && m_pEdit) - m_pEdit->SetLabel2(((CSettingString *)m_pSetting)->GetData()); -} - -bool CGUIEditSettingControl::IsValidIPAddress(const CStdString &strIP) -{ - const char* s = strIP.c_str(); - bool legalFormat = true; - bool numSet = false; - int num = 0; - int dots = 0; - - while (*s != '\0') - { - if (*s == '.') - { - ++dots; - - // There must be a number before a . - if (!numSet) - { - legalFormat = false; - break; - } - - if (num > 255) - { - legalFormat = false; - break; - } - - num = 0; - numSet = false; - } - else if (*s >= '0' && *s <= '9') - { - num = (num * 10) + (*s - '0'); - numSet = true; - } - else - { - legalFormat = false; - break; - } - - ++s; - } - - if (legalFormat) - { - if (!numSet) - { - legalFormat = false; - } - - if (num > 255 || dots != 3) - { - legalFormat = false; - } - } - - if (!legalFormat) - CGUIDialogOK::ShowAndGetInput(257, 724, 725, 0); - - return legalFormat; -} - -CGUISeparatorSettingControl::CGUISeparatorSettingControl(CGUIImage *pImage, int id, CSetting *pSetting) - : CGUIBaseSettingControl(id, pSetting) -{ - m_pImage = pImage; - m_pImage->SetID(id); -} - -CGUISeparatorSettingControl::~CGUISeparatorSettingControl() -{} - diff --git a/xbmc/settings/windows/GUISettingControls.h b/xbmc/settings/windows/GUISettingControls.h deleted file mode 100644 index 576cc55b80..0000000000 --- a/xbmc/settings/windows/GUISettingControls.h +++ /dev/null @@ -1,130 +0,0 @@ -#pragma once -/* - * Copyright (C) 2005-2013 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 "utils/StdString.h" - -class CGUIImage; -class CGUISpinControlEx; -class CGUIEditControl; -class CGUIButtonControl; -class CGUIRadioButtonControl; - -class CSetting; - -class CGUIBaseSettingControl -{ -public: - CGUIBaseSettingControl(int id, CSetting *pSetting); - virtual ~CGUIBaseSettingControl() {} - virtual bool OnClick() { return false; }; - virtual void Update() {}; - int GetID() { return m_id; }; - CSetting* GetSetting() { return m_pSetting; }; - virtual bool NeedsUpdate() { return false; }; ///< Returns true if the control needs an update - virtual void Reset() {}; ///< Resets the NeedsUpdate() state - virtual void Clear()=0; ///< Clears the attached control - - /*! - \brief Specifies that this setting should update after a delay - Useful for settings that have options to navigate through - and may take a while, or require additional input to update - once the final setting is chosen. Settings default to updating - instantly. - \sa IsDelayed() - */ - void SetDelayed() { m_delayed = true; }; - - /*! - \brief Returns whether this setting should have delayed update - \return true if the setting's update should be delayed - \sa SetDelayed() - */ - bool IsDelayed() const { return m_delayed; }; -protected: - int m_id; - CSetting* m_pSetting; - bool m_delayed; -}; - -class CGUIRadioButtonSettingControl : public CGUIBaseSettingControl -{ -public: - CGUIRadioButtonSettingControl(CGUIRadioButtonControl* pRadioButton, int id, CSetting *pSetting); - virtual ~CGUIRadioButtonSettingControl(); - virtual bool OnClick(); - virtual void Update(); - virtual void Clear() { m_pRadioButton = NULL; } - void Select(bool bSelect); -private: - CGUIRadioButtonControl *m_pRadioButton; -}; - -class CGUISpinExSettingControl : public CGUIBaseSettingControl -{ -public: - CGUISpinExSettingControl(CGUISpinControlEx* pSpin, int id, CSetting *pSetting); - virtual ~CGUISpinExSettingControl(); - virtual bool OnClick(); - virtual void Update(); - virtual void Clear() { m_pSpin = NULL; } -private: - CGUISpinControlEx *m_pSpin; -}; - -class CGUIButtonSettingControl : public CGUIBaseSettingControl -{ -public: - CGUIButtonSettingControl(CGUIButtonControl* pButton, int id, CSetting *pSetting); - virtual ~CGUIButtonSettingControl(); - virtual bool OnClick(); - virtual void Update(); - virtual void Clear() { m_pButton = NULL; } -private: - CGUIButtonControl *m_pButton; -}; - -class CGUIEditSettingControl : public CGUIBaseSettingControl -{ -public: - CGUIEditSettingControl(CGUIEditControl* pButton, int id, CSetting *pSetting); - virtual ~CGUIEditSettingControl(); - virtual bool OnClick(); - virtual void Update(); - virtual bool NeedsUpdate() { return m_needsUpdate; }; - virtual void Reset() { m_needsUpdate = false; }; - virtual void Clear() { m_pEdit = NULL; } -private: - bool IsValidIPAddress(const CStdString &strIP); - CGUIEditControl *m_pEdit; - bool m_needsUpdate; -}; - -class CGUISeparatorSettingControl : public CGUIBaseSettingControl -{ -public: - CGUISeparatorSettingControl(CGUIImage* pImage, int id, CSetting *pSetting); - virtual ~CGUISeparatorSettingControl(); - virtual bool OnClick() { return false; }; - virtual void Update() {}; - virtual void Clear() { m_pImage = NULL; } -private: - CGUIImage *m_pImage; -}; diff --git a/xbmc/settings/windows/GUIWindowSettingsCategory.cpp b/xbmc/settings/windows/GUIWindowSettingsCategory.cpp index 6f57416600..32da9b2a85 100644 --- a/xbmc/settings/windows/GUIWindowSettingsCategory.cpp +++ b/xbmc/settings/windows/GUIWindowSettingsCategory.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2013 Team XBMC + * Copyright (C) 2005-2012 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify @@ -18,117 +18,39 @@ * */ -#include "system.h" -#include "GUIUserMessages.h" #include "GUIWindowSettingsCategory.h" -#include "Application.h" -#include "ApplicationMessenger.h" -#include "interfaces/Builtins.h" -#include "input/KeyboardLayoutConfiguration.h" -#include "filesystem/Directory.h" -#include "Util.h" -#include "guilib/GUISpinControlEx.h" -#include "guilib/GUIRadioButtonControl.h" -#include "guilib/GUIEditControl.h" -#include "guilib/GUIImage.h" -#include "utils/Weather.h" -#include "music/MusicDatabase.h" -#include "profiles/ProfilesManager.h" -#include "video/VideoDatabase.h" -#include "view/ViewDatabase.h" -#include "view/ViewState.h" -#include "PlayListPlayer.h" -#include "addons/Skin.h" -#include "guilib/GUIAudioManager.h" -#include "GUIPassword.h" -#include "GUIInfoManager.h" -#include "dialogs/GUIDialogGamepad.h" -#include "dialogs/GUIDialogNumeric.h" -#include "dialogs/GUIDialogFileBrowser.h" -#include "addons/GUIDialogAddonSettings.h" -#include "addons/GUIWindowAddonBrowser.h" -#include "dialogs/GUIDialogContextMenu.h" -#include "dialogs/GUIDialogYesNo.h" -#include "dialogs/GUIDialogOK.h" -#include "dialogs/GUIDialogProgress.h" +#include "GUIUserMessages.h" #include "dialogs/GUIDialogKaiToast.h" -#include "addons/Visualisation.h" -#include "addons/AddonManager.h" -#include "addons/AddonInstaller.h" -#include "storage/MediaManager.h" -#include "network/Network.h" +#include "dialogs/GUIDialogTextViewer.h" +#include "dialogs/GUIDialogYesNo.h" #include "guilib/GUIControlGroupList.h" -#include "guilib/GUIWindowManager.h" -#include "guilib/GUIFontManager.h" -#include "cores/AudioEngine/AEFactory.h" -#include "cores/paplayer/AudioDecoder.h" -#ifdef _LINUX -#include "LinuxTimezone.h" -#include <dlfcn.h> -#ifdef HAS_HAL -#include "HALManager.h" -#endif -#endif -#if defined(TARGET_DARWIN_OSX) -#include "osx/XBMCHelper.h" -#endif -#include "network/GUIDialogAccessPoints.h" -#include "filesystem/Directory.h" - -#include "FileItem.h" +#include "guilib/GUIEditControl.h" +#include "guilib/GUIImage.h" +#include "guilib/GUIRadioButtonControl.h" +#include "guilib/GUISpinControlEx.h" #include "guilib/GUIToggleButtonControl.h" -#include "filesystem/SpecialProtocol.h" - -#include "network/Zeroconf.h" -#include "peripherals/Peripherals.h" -#include "peripherals/dialogs/GUIDialogPeripheralManager.h" -#include "peripherals/devices/PeripheralImon.h" - -#ifdef _WIN32 -#include "WIN32Util.h" -#endif -#include <map> -#include "settings/Settings.h" -#include "settings/AdvancedSettings.h" -#include "settings/DisplaySettings.h" -#include "settings/MediaSourceSettings.h" -#include "input/MouseStat.h" -#if defined(TARGET_WINDOWS) -#include "input/windows/WINJoystick.h" -#elif defined(HAS_SDL_JOYSTICK) -#include "input/SDLJoystick.h" -#endif +#include "guilib/GUIWindowManager.h" +#include "guilib/Key.h" #include "guilib/LocalizeStrings.h" -#include "LangInfo.h" -#include "utils/CharsetConverter.h" -#include "utils/StringUtils.h" -#include "utils/URIUtils.h" -#include "utils/SystemInfo.h" -#include "windowing/WindowingFactory.h" -#include "pvr/dialogs/GUIDialogPVRChannelManager.h" -#include "pvr/PVRManager.h" -#include "pvr/addons/PVRClients.h" - -#if defined(HAVE_LIBCRYSTALHD) -#include "cores/dvdplayer/DVDCodecs/Video/CrystalHD.h" -#endif - -#if defined(HAS_AIRPLAY) -#include "network/AirPlayServer.h" -#endif - -#if defined(HAS_WEB_SERVER) -#include "network/WebServer.h" -#endif +#include "settings/DisplaySettings.h" +#include "settings/Settings.h" +#include "utils/log.h" +#include "view/ViewStateSettings.h" using namespace std; -using namespace XFILE; -using namespace ADDON; -using namespace PVR; -using namespace PERIPHERALS; -#define CONTROL_GROUP_BUTTONS 0 -#define CONTROL_GROUP_SETTINGS 1 +#define SETTINGS_PICTURES WINDOW_SETTINGS_MYPICTURES - WINDOW_SETTINGS_START +#define SETTINGS_PROGRAMS WINDOW_SETTINGS_MYPROGRAMS - WINDOW_SETTINGS_START +#define SETTINGS_WEATHER WINDOW_SETTINGS_MYWEATHER - WINDOW_SETTINGS_START +#define SETTINGS_MUSIC WINDOW_SETTINGS_MYMUSIC - WINDOW_SETTINGS_START +#define SETTINGS_SYSTEM WINDOW_SETTINGS_SYSTEM - WINDOW_SETTINGS_START +#define SETTINGS_VIDEOS WINDOW_SETTINGS_MYVIDEOS - WINDOW_SETTINGS_START +#define SETTINGS_SERVICE WINDOW_SETTINGS_SERVICE - WINDOW_SETTINGS_START +#define SETTINGS_APPEARANCE WINDOW_SETTINGS_APPEARANCE - WINDOW_SETTINGS_START +#define SETTINGS_PVR WINDOW_SETTINGS_MYPVR - WINDOW_SETTINGS_START + +#define SETTING_DELAY 1500 + #define CONTROL_SETTINGS_LABEL 2 #define CATEGORY_GROUP_ID 3 #define SETTINGS_GROUP_ID 5 @@ -140,17 +62,36 @@ using namespace PERIPHERALS; #define CONTROL_DEFAULT_EDIT 12 #define CONTROL_START_BUTTONS -100 #define CONTROL_START_CONTROL -80 +#define CONTRL_BTN_LEVELS 20 + +typedef struct { + int id; + string name; +} SettingGroup; + +static const SettingGroup s_settingGroupMap[] = { { SETTINGS_PICTURES, "pictures" }, + { SETTINGS_PROGRAMS, "programs" }, + { SETTINGS_WEATHER, "weather" }, + { SETTINGS_MUSIC, "music" }, + { SETTINGS_SYSTEM, "system" }, + { SETTINGS_VIDEOS, "videos" }, + { SETTINGS_SERVICE, "services" }, + { SETTINGS_APPEARANCE, "appearance" }, + { SETTINGS_PVR, "pvr" } }; + +#define SettingGroupSize sizeof(s_settingGroupMap) / sizeof(SettingGroup) CGUIWindowSettingsCategory::CGUIWindowSettingsCategory(void) - : CGUIWindow(WINDOW_SETTINGS_MYPICTURES, "SettingsCategory.xml") + : CGUIWindow(WINDOW_SETTINGS_MYPICTURES, "SettingsCategory.xml"), + m_settings(CSettings::Get()), + m_iCategory(0), m_iSection(0), + m_delayedTimer(this), + m_returningFromSkinLoad(false) { m_loadType = KEEP_IN_MEMORY; - m_pOriginalSpin = NULL; - m_pOriginalRadioButton = NULL; - m_pOriginalButton = NULL; - m_pOriginalCategoryButton = NULL; - m_pOriginalImage = NULL; - m_pOriginalEdit = NULL; + + newOriginalEdit = false; + // set the correct ID range... m_idRange.clear(); m_idRange.push_back(WINDOW_SETTINGS_MYPICTURES); @@ -162,1918 +103,258 @@ CGUIWindowSettingsCategory::CGUIWindowSettingsCategory(void) m_idRange.push_back(WINDOW_SETTINGS_SERVICE); m_idRange.push_back(WINDOW_SETTINGS_APPEARANCE); m_idRange.push_back(WINDOW_SETTINGS_MYPVR); - - m_iScreen = 0; - m_strOldTrackFormat = ""; - m_strOldTrackFormatRight = ""; - m_returningFromSkinLoad = false; - m_delayedSetting.reset(); } CGUIWindowSettingsCategory::~CGUIWindowSettingsCategory(void) { FreeControls(); - delete m_pOriginalEdit; -} - -bool CGUIWindowSettingsCategory::OnBack(int actionID) -{ - g_settings.Save(); - m_lastControlID = 0; // don't save the control as we go to a different window each time - return CGUIWindow::OnBack(actionID); + if (newOriginalEdit) + { + delete m_pOriginalEdit; + m_pOriginalEdit = NULL; + } } bool CGUIWindowSettingsCategory::OnMessage(CGUIMessage &message) { switch (message.GetMessage()) { - case GUI_MSG_CLICKED: - { - unsigned int iControl = message.GetSenderId(); - for (unsigned int i = 0; i < m_vecSettings.size(); i++) - { - if (m_vecSettings[i]->GetID() == (int)iControl) - OnClick(m_vecSettings[i]); - } - } - break; - case GUI_MSG_FOCUSED: - { - CGUIWindow::OnMessage(message); - int focusedControl = GetFocusedControlID(); - if (focusedControl >= CONTROL_START_BUTTONS && focusedControl < (int)(CONTROL_START_BUTTONS + m_vecSections.size()) && - focusedControl - CONTROL_START_BUTTONS != m_iSection && !m_returningFromSkinLoad) - { - // changing section, check for updates and cancel any delayed changes - m_delayedSetting.reset(); - CheckForUpdates(); - - if (m_vecSections[focusedControl-CONTROL_START_BUTTONS]->m_strCategory == "masterlock") - { - if (!g_passwordManager.IsMasterLockUnlocked(true)) - { // unable to go to this category - focus the previous one - SET_CONTROL_FOCUS(CONTROL_START_BUTTONS + m_iSection, 0); - return false; - } - } - if (m_vecSections[focusedControl-CONTROL_START_BUTTONS]->m_strCategory == "pvrparental") - { - if (!g_PVRManager.CheckParentalPIN(g_localizeStrings.Get(19262).c_str())) - { // unable to go to this category - focus the previous one - SET_CONTROL_FOCUS(CONTROL_START_BUTTONS + m_iSection, 0); - return false; - } - } - - m_iSection = focusedControl - CONTROL_START_BUTTONS; - - CreateSettings(); - } - return true; - } - break; - case GUI_MSG_LOAD_SKIN: - { - if (IsActive()) - m_returningFromSkinLoad = true; - } - break; - case GUI_MSG_WINDOW_INIT: + case GUI_MSG_WINDOW_INIT: { m_delayedSetting.reset(); + m_currentSetting.reset(); if (message.GetParam1() != WINDOW_INVALID && !m_returningFromSkinLoad) { // coming to this window first time (ie not returning back from some other window) // so we reset our section and control states - m_iSection = 0; + m_iCategory = 0; ResetControlStates(); } - m_iScreen = (int)message.GetParam2() - (int)CGUIWindow::GetID(); + + m_iSection = (int)message.GetParam2() - (int)CGUIWindow::GetID(); CGUIWindow::OnMessage(message); m_returningFromSkinLoad = false; return true; } - break; - case GUI_MSG_UPDATE_ITEM: - if (m_delayedSetting) - { - OnSettingChanged(m_delayedSetting); - m_delayedSetting.reset(); - return true; - } - break; - case GUI_MSG_UPDATE: - if (HasID(message.GetSenderId())) - { - int focusedControl = GetFocusedControlID(); - CreateSettings(); - SET_CONTROL_FOCUS(focusedControl, 0); - } - break; - case GUI_MSG_NOTIFY_ALL: + + case GUI_MSG_WINDOW_DEINIT: { - if (message.GetParam1() == GUI_MSG_WINDOW_RESIZE) + // cancel any delayed changes + if (m_delayedSetting != NULL) { - // Cancel delayed setting - it's only used for res changing anyway - m_delayedSetting.reset(); - if (IsActive() && CDisplaySettings::Get().GetDisplayResolution() != g_graphicsContext.GetVideoResolution()) - { - CDisplaySettings::Get().SetCurrentResolution(g_graphicsContext.GetVideoResolution(), true); - CreateSettings(); - } + m_delayedTimer.Stop(); + CGUIMessage message(GUI_MSG_UPDATE_ITEM, GetID(), GetID()); + OnMessage(message); } - } - break; - case GUI_MSG_WINDOW_DEINIT: - { - m_delayedSetting.reset(); - - CheckForUpdates(); + CGUIWindow::OnMessage(message); FreeControls(); return true; } - break; - } - return CGUIWindow::OnMessage(message); -} - -void CGUIWindowSettingsCategory::SetupControls() -{ - // cleanup first, if necessary - FreeControls(); - m_pOriginalSpin = (CGUISpinControlEx*)GetControl(CONTROL_DEFAULT_SPIN); - m_pOriginalRadioButton = (CGUIRadioButtonControl *)GetControl(CONTROL_DEFAULT_RADIOBUTTON); - m_pOriginalCategoryButton = (CGUIButtonControl *)GetControl(CONTROL_DEFAULT_CATEGORY_BUTTON); - m_pOriginalButton = (CGUIButtonControl *)GetControl(CONTROL_DEFAULT_BUTTON); - m_pOriginalImage = (CGUIImage *)GetControl(CONTROL_DEFAULT_SEPARATOR); - if (!m_pOriginalCategoryButton || !m_pOriginalSpin || !m_pOriginalRadioButton || !m_pOriginalButton) - return ; - m_pOriginalEdit = (CGUIEditControl *)GetControl(CONTROL_DEFAULT_EDIT); - if (!m_pOriginalEdit || m_pOriginalEdit->GetControlType() != CGUIControl::GUICONTROL_EDIT) - { - delete m_pOriginalEdit; - m_pOriginalEdit = new CGUIEditControl(*m_pOriginalButton); - } - m_pOriginalSpin->SetVisible(false); - m_pOriginalRadioButton->SetVisible(false); - m_pOriginalButton->SetVisible(false); - m_pOriginalCategoryButton->SetVisible(false); - m_pOriginalEdit->SetVisible(false); - if (m_pOriginalImage) m_pOriginalImage->SetVisible(false); - // setup our control groups... - CGUIControlGroupList *group = (CGUIControlGroupList *)GetControl(CATEGORY_GROUP_ID); - if (!group) - return; - // get a list of different sections - CSettingsGroup *pSettingsGroup = g_guiSettings.GetGroup(m_iScreen); - if (!pSettingsGroup) return ; - // update the screen string - SET_CONTROL_LABEL(CONTROL_SETTINGS_LABEL, pSettingsGroup->GetLabelID()); - // get the categories we need - pSettingsGroup->GetCategories(m_vecSections); - // run through and create our buttons... - int j=0; - for (unsigned int i = 0; i < m_vecSections.size(); i++) - { - if (m_vecSections[i]->m_labelID == 12360 && !CProfilesManager::Get().IsMasterProfile()) - continue; - CGUIButtonControl *pButton = NULL; - if (m_pOriginalCategoryButton->GetControlType() == CGUIControl::GUICONTROL_TOGGLEBUTTON) - pButton = new CGUIToggleButtonControl(*(CGUIToggleButtonControl *)m_pOriginalCategoryButton); - else - pButton = new CGUIButtonControl(*m_pOriginalCategoryButton); - pButton->SetLabel(g_localizeStrings.Get(m_vecSections[i]->m_labelID)); - pButton->SetID(CONTROL_START_BUTTONS + j); - pButton->SetVisible(true); - pButton->AllocResources(); - group->AddControl(pButton); - j++; - } - if (m_iSection < 0 || m_iSection >= (int)m_vecSections.size()) - m_iSection = 0; - CreateSettings(); - // set focus correctly - m_defaultControl = CONTROL_START_BUTTONS; -} - -CGUIControl* CGUIWindowSettingsCategory::AddIntBasedSpinControl(CSetting *pSetting, float groupWidth, int &iControlID) -{ - CSettingInt *pSettingInt = (CSettingInt*)pSetting; - CGUISpinControlEx *pControl = (CGUISpinControlEx *)AddSetting(pSetting, groupWidth, iControlID); - if (!pSettingInt->m_entries.empty()) - { - for (map<int,int>::iterator it=pSettingInt->m_entries.begin(); it != pSettingInt->m_entries.end();++it) - pControl->AddLabel(g_localizeStrings.Get(it->first), it->second); - pControl->SetValue(pSettingInt->GetData()); - } - return pControl; -} - -void CGUIWindowSettingsCategory::CreateSettings() -{ - FreeSettingsControls(); - - CGUIControlGroupList *group = (CGUIControlGroupList *)GetControl(SETTINGS_GROUP_ID); - if (!group) - return; - vecSettings settings; - g_guiSettings.GetSettingsGroup(m_vecSections[m_iSection], settings); - int iControlID = CONTROL_START_CONTROL; - for (unsigned int i = 0; i < settings.size(); i++) - { - CSetting *pSetting = settings[i]; - CStdString strSetting = pSetting->GetSetting(); - if (pSetting->GetType() == SETTINGS_TYPE_INT) + + case GUI_MSG_FOCUSED: { - CGUISpinControlEx *pControl = (CGUISpinControlEx *)AddIntBasedSpinControl(pSetting, group->GetWidth(), iControlID); - CSettingInt *pSettingInt = (CSettingInt*)pSetting; - if (strSetting.Equals("videoplayer.pauseafterrefreshchange")) + CGUIWindow::OnMessage(message); + if (!m_returningFromSkinLoad) { - pControl->AddLabel(g_localizeStrings.Get(13551), 0); - - for (int i = 1; i <= MAXREFRESHCHANGEDELAY; i++) + // cancel any delayed changes + if (m_delayedSetting != NULL) { - CStdString delayText; - delayText.Format(g_localizeStrings.Get(13553).c_str(), (double)i / 10.0); - pControl->AddLabel(delayText, i); + m_delayedTimer.Stop(); + CGUIMessage message(GUI_MSG_UPDATE_ITEM, GetID(), GetID(), 1); // param1 = 1 for "reset the control if it's invalid" + OnMessage(message); } - pControl->SetValue(pSettingInt->GetData()); - } - else if (strSetting.Equals("subtitles.color")) - { - for (int i = SUBTITLE_COLOR_START; i <= SUBTITLE_COLOR_END; i++) - pControl->AddLabel(g_localizeStrings.Get(760 + i), i); - pControl->SetValue(pSettingInt->GetData()); - } - else if (strSetting.Equals("lookandfeel.startupwindow")) - FillInStartupWindow(pSetting); - else if (strSetting.Equals("subtitles.height") || strSetting.Equals("karaoke.fontheight") ) - FillInSubtitleHeights(pSetting, pControl); - else if (strSetting.Equals("videoscreen.screen")) - FillInScreens(strSetting, CDisplaySettings::Get().GetDisplayResolution()); - else if (strSetting.Equals("videoscreen.resolution")) - FillInResolutions(strSetting, g_guiSettings.GetInt("videoscreen.screen"), CDisplaySettings::Get().GetDisplayResolution(), false); - else if (strSetting.Equals("epg.defaultguideview")) - FillInEpgGuideView(pSetting); - else if (strSetting.Equals("pvrplayback.startlast")) - FillInPvrStartLastChannel(pSetting); - continue; - } -#ifdef HAS_WEB_SERVER - else if (strSetting.Equals("services.webserverport")) - { - AddSetting(pSetting, group->GetWidth(), iControlID); - BaseSettingControlPtr control = GetSetting(pSetting->GetSetting()); - control->SetDelayed(); - continue; - } -#endif - else if (strSetting.Equals("services.esport")) - { -#ifdef HAS_EVENT_SERVER - AddSetting(pSetting, group->GetWidth(), iControlID); - BaseSettingControlPtr control = GetSetting(pSetting->GetSetting()); - control->SetDelayed(); - continue; -#endif - } - else if (strSetting.Equals("network.httpproxyport")) - { - AddSetting(pSetting, group->GetWidth(), iControlID); - BaseSettingControlPtr control = GetSetting(pSetting->GetSetting()); - control->SetDelayed(); - continue; - } - else if (strSetting.Equals("subtitles.font") || strSetting.Equals("karaoke.font") ) - { - AddSetting(pSetting, group->GetWidth(), iControlID); - FillInSubtitleFonts(pSetting); - continue; - } - else if (strSetting.Equals("subtitles.charset") || strSetting.Equals("locale.charset") || strSetting.Equals("karaoke.charset")) - { - AddSetting(pSetting, group->GetWidth(), iControlID); - FillInCharSets(pSetting); - continue; - } - else if (strSetting.Equals("lookandfeel.font")) - { - AddSetting(pSetting, group->GetWidth(), iControlID); - FillInSkinFonts(pSetting); - continue; - } - else if (strSetting.Equals("lookandfeel.soundskin")) - { - AddSetting(pSetting, group->GetWidth(), iControlID); - FillInSoundSkins(pSetting); - continue; - } - else if (strSetting.Equals("locale.language")) - { - AddSetting(pSetting, group->GetWidth(), iControlID); - GetSetting(pSetting->GetSetting())->SetDelayed(); - FillInLanguages(pSetting); - continue; - } - else if (strSetting.Equals("locale.audiolanguage") || strSetting.Equals("locale.subtitlelanguage")) - { - AddSetting(pSetting, group->GetWidth(), iControlID); - vector<CStdString> languages; - languages.push_back(g_localizeStrings.Get(308)); - languages.push_back(g_localizeStrings.Get(309)); - vector<CStdString> languageKeys; - languageKeys.push_back("original"); - languageKeys.push_back("default"); - FillInLanguages(pSetting, languages, languageKeys); - continue; - } -#ifdef _LINUX - else if (strSetting.Equals("locale.timezonecountry")) - { - CStdString myTimezoneCountry = g_guiSettings.GetString("locale.timezonecountry"); - int myTimezeoneCountryIndex = 0; - - CGUISpinControlEx *pControl = (CGUISpinControlEx *)AddSetting(pSetting, group->GetWidth(), iControlID); - vector<CStdString> countries = g_timezone.GetCounties(); - for (unsigned int i=0; i < countries.size(); i++) - { - if (countries[i] == myTimezoneCountry) - myTimezeoneCountryIndex = i; - pControl->AddLabel(countries[i], i); - } - pControl->SetValue(myTimezeoneCountryIndex); - continue; - } - else if (strSetting.Equals("locale.timezone")) - { - CStdString myTimezoneCountry = g_guiSettings.GetString("locale.timezonecountry"); - CStdString myTimezone = g_guiSettings.GetString("locale.timezone"); - int myTimezoneIndex = 0; - - CGUISpinControlEx *pControl = (CGUISpinControlEx *)AddSetting(pSetting, group->GetWidth(), iControlID); - pControl->Clear(); - vector<CStdString> timezones = g_timezone.GetTimezonesByCountry(myTimezoneCountry); - for (unsigned int i=0; i < timezones.size(); i++) - { - if (timezones[i] == myTimezone) - myTimezoneIndex = i; - pControl->AddLabel(timezones[i], i); - } - pControl->SetValue(myTimezoneIndex); - continue; - } -#endif - else if (strSetting.Equals("videoscreen.screenmode")) - { - AddSetting(pSetting, group->GetWidth(), iControlID); - FillInRefreshRates(strSetting, CDisplaySettings::Get().GetDisplayResolution(), false); - continue; - } - else if (strSetting.Equals("lookandfeel.skintheme")) - { - AddSetting(pSetting, group->GetWidth(), iControlID); - FillInSkinThemes(pSetting); - continue; - } - else if (strSetting.Equals("lookandfeel.skincolors")) - { - AddSetting(pSetting, group->GetWidth(), iControlID); - FillInSkinColors(pSetting); - continue; - } - /* - FIXME: setting is hidden in GUI because not supported properly. - else if (strSetting.Equals("videoplayer.displayresolution") || strSetting.Equals("pictures.displayresolution")) - { - FillInResolutions(pSetting); - } - */ - else if (strSetting.Equals("locale.country")) - { - AddSetting(pSetting, group->GetWidth(), iControlID); - FillInRegions(pSetting); - continue; - } - else if (strSetting.Equals("network.interface")) - { - FillInNetworkInterfaces(pSetting, group->GetWidth(), iControlID); - continue; - } - else if (strSetting.Equals("audiooutput.audiodevice")) - { - AddSetting(pSetting, group->GetWidth(), iControlID); - FillInAudioDevices(pSetting); - continue; - } - else if (strSetting.Equals("audiooutput.passthroughdevice")) - { - AddSetting(pSetting, group->GetWidth(), iControlID); - FillInAudioDevices(pSetting,true); - continue; - } - AddSetting(pSetting, group->GetWidth(), iControlID); - } - if (m_vecSections[m_iSection]->m_strCategory == "network") - NetworkInterfaceChanged(); - - // update our settings (turns controls on/off as appropriate) - UpdateSettings(); -} - -void CGUIWindowSettingsCategory::UpdateSettings() -{ - for (unsigned int i = 0; i < m_vecSettings.size(); i++) - { - BaseSettingControlPtr pSettingControl = m_vecSettings[i]; - pSettingControl->Update(); - CStdString strSetting = pSettingControl->GetSetting()->GetSetting(); -#ifdef HAVE_LIBVDPAU - if (strSetting.Equals("videoplayer.vdpauUpscalingLevel")) - { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) - { - pControl->SetEnabled(true); - } - } - else -#endif - if (strSetting.Equals("videoscreen.resolution")) - { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) - pControl->SetEnabled(g_guiSettings.GetInt("videoscreen.screen") != DM_WINDOWED); - } - else if (strSetting.Equals("videoscreen.screenmode")) - { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) - pControl->SetEnabled(g_guiSettings.GetInt("videoscreen.screen") != DM_WINDOWED); - } - else if (strSetting.Equals("videoscreen.fakefullscreen")) - { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) - pControl->SetEnabled(g_guiSettings.GetInt("videoscreen.screen") != DM_WINDOWED); - } -#if defined(TARGET_DARWIN_OSX) || defined(_WIN32) - else if (strSetting.Equals("videoscreen.blankdisplays")) - { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) - { - if (g_Windowing.IsFullScreen()) - pControl->SetEnabled(true); - else - pControl->SetEnabled(false); - } - } -#endif -#if defined(TARGET_DARWIN_OSX) - else if (strSetting.Equals("input.appleremotemode")) - { - int remoteMode = g_guiSettings.GetInt("input.appleremotemode"); - - // if it's not disabled, start the event server or else apple remote won't work - if ( remoteMode != APPLE_REMOTE_DISABLED ) - { - g_guiSettings.SetBool("services.esenabled", true); - if (!g_application.StartEventServer()) - CGUIDialogKaiToast::QueueNotification("DefaultIconWarning.png", g_localizeStrings.Get(33102), g_localizeStrings.Get(33100)); - } - - // if XBMC helper is running, prompt user before effecting change - if ( XBMCHelper::GetInstance().IsRunning() && XBMCHelper::GetInstance().GetMode()!=remoteMode ) - { - bool cancelled; - if (!CGUIDialogYesNo::ShowAndGetInput(13144, 13145, 13146, 13147, -1, -1, cancelled, 10000)) + int focusedControl = GetFocusedControlID(); + // check if we have changed the category and need to create new setting controls + if (focusedControl >= CONTROL_START_BUTTONS && focusedControl < (int)(CONTROL_START_BUTTONS + m_categories.size()) && + focusedControl - CONTROL_START_BUTTONS != m_iCategory) { - // user declined, restore previous spinner state and appleremote mode - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID()); - g_guiSettings.SetInt("input.appleremotemode", XBMCHelper::GetInstance().GetMode()); - pControl->SetValue(XBMCHelper::GetInstance().GetMode()); - } - else - { - // reload configuration - XBMCHelper::GetInstance().Configure(); - } - } - else - { - // set new configuration. - XBMCHelper::GetInstance().Configure(); - } - - if (XBMCHelper::GetInstance().ErrorStarting() == true) - { - // inform user about error - CGUIDialogOK::ShowAndGetInput(13620, 13621, 20022, 20022); + if (!m_categories[focusedControl - CONTROL_START_BUTTONS]->CanAccess()) + { + // unable to go to this category - focus the previous one + SET_CONTROL_FOCUS(CONTROL_START_BUTTONS + m_iCategory, 0); + return false; + } - // reset spinner to disabled state - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID()); - pControl->SetValue(APPLE_REMOTE_DISABLED); - } - } - else if (strSetting.Equals("input.appleremotealwayson")) - { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) - { - int value = g_guiSettings.GetInt("input.appleremotemode"); - if (value != APPLE_REMOTE_DISABLED) - pControl->SetEnabled(true); - else - pControl->SetEnabled(false); - } - } - else if (strSetting.Equals("input.appleremotesequencetime")) - { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) - { - int value = g_guiSettings.GetInt("input.appleremotemode"); - if (value == APPLE_REMOTE_UNIVERSAL) - pControl->SetEnabled(true); - else - pControl->SetEnabled(false); - } - } -#endif - else if (strSetting.Equals("filelists.allowfiledeletion")) - { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) pControl->SetEnabled(!CProfilesManager::Get().GetCurrentProfile().filesLocked() || g_passwordManager.bMasterUser); - } - else if (strSetting.Equals("filelists.showaddsourcebuttons")) - { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) pControl->SetEnabled(CProfilesManager::Get().GetCurrentProfile().canWriteSources() || g_passwordManager.bMasterUser); - } - else if (strSetting.Equals("masterlock.startuplock")) - { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) pControl->SetEnabled(CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE); - } - else if (strSetting.Equals("pvrmanager.channelscan")) - { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) pControl->SetEnabled(g_guiSettings.GetBool("pvrmanager.enabled") && g_PVRClients && g_PVRClients->GetClientsSupportingChannelScan().size() > 0); - } - else if (strSetting.Equals("pvrmanager.channelmanager") || strSetting.Equals("pvrmenu.searchicons")) - { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) pControl->SetEnabled(g_guiSettings.GetBool("pvrmanager.enabled")); - } - else if (!strSetting.Equals("pvrparental.enabled") && - (strSetting.Equals("pvrparental.pin") || strSetting.Equals("pvrparental.duration"))) - { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) pControl->SetEnabled(g_guiSettings.GetBool("pvrparental.enabled")); - } - else if (!strSetting.Equals("services.esenabled") - && strSetting.Left(11).Equals("services.es")) - { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) pControl->SetEnabled(g_guiSettings.GetBool("services.esenabled")); - } - else if (strSetting.Equals("services.upnpannounce")) - { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - pControl->SetEnabled(g_guiSettings.GetBool("services.upnpserver")); - } - else if (strSetting.Equals("audiocds.quality")) - { // only visible if we are doing non-WAV ripping - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) pControl->SetEnabled(g_guiSettings.GetInt("audiocds.encoder") != CDDARIP_ENCODER_WAV && - g_guiSettings.GetInt("audiocds.encoder") != CDDARIP_ENCODER_FLAC); - } - else if (strSetting.Equals("audiocds.bitrate")) - { // only visible if we are ripping to CBR - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) pControl->SetEnabled(g_guiSettings.GetInt("audiocds.encoder") != CDDARIP_ENCODER_WAV && - g_guiSettings.GetInt("audiocds.encoder") != CDDARIP_ENCODER_FLAC && - g_guiSettings.GetInt("audiocds.quality") == CDDARIP_QUALITY_CBR); - } - else if (strSetting.Equals("audiocds.compressionlevel")) - { // only visible if we are doing FLAC ripping - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) pControl->SetEnabled(g_guiSettings.GetInt("audiocds.encoder") == CDDARIP_ENCODER_FLAC); - } - else if ( - strSetting.Equals("audiooutput.passthroughdevice") || - strSetting.Equals("audiooutput.ac3passthrough") || - strSetting.Equals("audiooutput.dtspassthrough") || - strSetting.Equals("audiooutput.passthroughaac")) - { // only visible if we are in digital mode - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) pControl->SetEnabled(AUDIO_IS_BITSTREAM(g_guiSettings.GetInt("audiooutput.mode"))); - } - else if ( - strSetting.Equals("audiooutput.multichannellpcm" ) || - strSetting.Equals("audiooutput.truehdpassthrough") || - strSetting.Equals("audiooutput.dtshdpassthrough" )) - { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) - { - if (strSetting.Equals("audiooutput.dtshdpassthrough") && !g_guiSettings.GetBool("audiooutput.dtspassthrough")) - pControl->SetEnabled(false); - else - pControl->SetEnabled(g_guiSettings.GetInt("audiooutput.mode") == AUDIO_HDMI); + m_iCategory = focusedControl - CONTROL_START_BUTTONS; + CreateSettings(); + } + else if (focusedControl >= CONTROL_START_CONTROL && focusedControl < (int)(CONTROL_START_CONTROL + m_settingControls.size())) + m_currentSetting = GetSettingControl(focusedControl); } + return true; } - else if (strSetting.Equals("musicplayer.crossfadealbumtracks")) - { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) pControl->SetEnabled(g_guiSettings.GetInt("musicplayer.crossfade") > 0); - } -#ifdef HAS_WEB_SERVER - else if (strSetting.Equals("services.webserverusername") || - strSetting.Equals("services.webserverpassword")) - { - CGUIEditControl *pControl = (CGUIEditControl *)GetControl(pSettingControl->GetID()); - if (pControl) - pControl->SetEnabled(g_guiSettings.GetBool("services.webserver")); - } -#endif -#ifdef HAS_AIRPLAY - else if ( strSetting.Equals("services.airplaypassword") || - strSetting.Equals("services.useairplaypassword")) - { - if (strSetting.Equals("services.airplaypassword")) - { - CGUIEditControl *pControl = (CGUIEditControl *)GetControl(pSettingControl->GetID()); - if (pControl) - pControl->SetEnabled(g_guiSettings.GetBool("services.useairplaypassword")); - } - else//useairplaypassword - { - CGUIRadioButtonControl *pControl = (CGUIRadioButtonControl *)GetControl(pSettingControl->GetID()); - if (pControl) - pControl->SetEnabled(g_guiSettings.GetBool("services.airplay")); - } - //set credentials to airplay server - if (g_guiSettings.GetBool("services.airplay")) - { - CStdString password = g_guiSettings.GetString("services.airplaypassword"); - CAirPlayServer::SetCredentials(g_guiSettings.GetBool("services.useairplaypassword"), - password); - } - } -#endif//HAS_AIRPLAY - else if (strSetting.Equals("network.ipaddress") || strSetting.Equals("network.subnet") || strSetting.Equals("network.gateway") || strSetting.Equals("network.dns")) - { -#ifdef _LINUX - bool enabled = (geteuid() == 0); -#else - bool enabled = false; -#endif - CGUISpinControlEx* pControl1 = (CGUISpinControlEx *)GetControl(GetSetting("network.assignment")->GetID()); - if (pControl1) - enabled = (pControl1->GetValue() == NETWORK_STATIC); - - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) pControl->SetEnabled(enabled); - } - else if (strSetting.Equals("network.assignment")) - { - CGUISpinControlEx* pControl1 = (CGUISpinControlEx *)GetControl(GetSetting("network.assignment")->GetID()); -#ifdef HAS_LINUX_NETWORK - if (pControl1) - pControl1->SetEnabled(geteuid() == 0); -#endif - } - else if (strSetting.Equals("network.essid") || strSetting.Equals("network.enc") || strSetting.Equals("network.key")) + case GUI_MSG_CLICKED: { - // Get network information - CGUISpinControlEx *ifaceControl = (CGUISpinControlEx *)GetControl(GetSetting("network.interface")->GetID()); - CStdString ifaceName = ifaceControl->GetLabel(); - CNetworkInterface* iface = g_application.getNetwork().GetInterfaceByName(ifaceName); - bool bIsWireless = iface->IsWireless(); - -#ifdef HAS_LINUX_NETWORK - bool enabled = bIsWireless && (geteuid() == 0); -#else - bool enabled = bIsWireless; -#endif - CGUISpinControlEx* pControl1 = (CGUISpinControlEx *)GetControl(GetSetting("network.assignment")->GetID()); - if (pControl1) - enabled &= (pControl1->GetValue() != NETWORK_DISABLED); - - if (strSetting.Equals("network.key")) - { - pControl1 = (CGUISpinControlEx *)GetControl(GetSetting("network.enc")->GetID()); - if (pControl1) enabled &= (pControl1->GetValue() != ENC_NONE); - } + BaseSettingControlPtr control = GetSettingControl(message.GetSenderId()); + if (control != NULL) + OnClick(control); - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) pControl->SetEnabled(enabled); - } - else if (strSetting.Equals("network.httpproxyserver") || strSetting.Equals("network.httpproxyport") || - strSetting.Equals("network.httpproxyusername") || strSetting.Equals("network.httpproxypassword") || - strSetting.Equals("network.httpproxytype")) - { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) pControl->SetEnabled(g_guiSettings.GetBool("network.usehttpproxy")); - } -#ifdef HAS_LINUX_NETWORK - else if (strSetting.Equals("network.key")) - { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - CGUISpinControlEx* pControl1 = (CGUISpinControlEx *)GetControl(GetSetting("network.enc")->GetID()); - if (pControl && pControl1) - pControl->SetEnabled(!pControl1->IsDisabled() && pControl1->GetValue() > 0); - } - else if (strSetting.Equals("network.save")) - { - CGUIButtonControl *pControl = (CGUIButtonControl *)GetControl(pSettingControl->GetID()); - pControl->SetEnabled(geteuid() == 0); - } -#endif - else if (strSetting.Equals("subtitles.color") || strSetting.Equals("subtitles.style") || strSetting.Equals("subtitles.charset")) - { - CGUIControl *pControl = (CGUIControl *)GetControl(GetSetting(strSetting)->GetID()); - pControl->SetEnabled(CUtil::IsUsingTTFSubtitles()); + break; } - else if (strSetting.Equals("locale.charset")) - { // TODO: Determine whether we are using a TTF font or not. - // CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - // if (pControl) pControl->SetEnabled(g_guiSettings.GetString("lookandfeel.font").Right(4) == ".ttf"); - } - else if (strSetting.Equals("screensaver.settings")) - { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - AddonPtr addon; - if (CAddonMgr::Get().GetAddon(g_guiSettings.GetString("screensaver.mode"), addon, ADDON_SCREENSAVER)) - pControl->SetEnabled(addon->HasSettings()); - else - pControl->SetEnabled(false); - } - else if (strSetting.Equals("screensaver.preview") || - strSetting.Equals("screensaver.time") || - strSetting.Equals("screensaver.usedimonpause") || - strSetting.Equals("screensaver.usemusicvisinstead")) - { - CGUIControl *pControl = (CGUIControl *)GetControl(GetSetting(strSetting)->GetID()); - pControl->SetEnabled(!g_guiSettings.GetString("screensaver.mode").IsEmpty()); - if (strSetting.Equals("screensaver.usedimonpause") && g_guiSettings.GetString("screensaver.mode").Equals("screensaver.xbmc.builtin.dim")) - pControl->SetEnabled(false); - } - else if (strSetting.Equals("musicfiles.trackformat")) - { - if (m_strOldTrackFormat != g_guiSettings.GetString("musicfiles.trackformat")) - { - CUtil::DeleteMusicDatabaseDirectoryCache(); - m_strOldTrackFormat = g_guiSettings.GetString("musicfiles.trackformat"); - } - } - else if (strSetting.Equals("musicfiles.trackformatright")) - { - if (m_strOldTrackFormatRight != g_guiSettings.GetString("musicfiles.trackformatright")) - { - CUtil::DeleteMusicDatabaseDirectoryCache(); - m_strOldTrackFormatRight = g_guiSettings.GetString("musicfiles.trackformatright"); - } - } - else if (strSetting.Equals("audiocds.recordingpath") || strSetting.Equals("debug.screenshotpath")) - { - CGUIButtonControl *pControl = (CGUIButtonControl *)GetControl(pSettingControl->GetID()); - if (pControl && g_guiSettings.GetString(strSetting, false).IsEmpty()) - pControl->SetLabel2(""); - } - else if (strSetting.Equals("lookandfeel.rssedit")) - { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - pControl->SetEnabled(g_guiSettings.GetBool("lookandfeel.enablerssfeeds")); - } - else if (strSetting.Equals("lookandfeel.skinsettings")) - { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - pControl->SetEnabled(g_SkinInfo->HasSkinFile("SkinSettings.xml")); - } - else if (strSetting.Equals("videoplayer.pauseafterrefreshchange")) - { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) pControl->SetEnabled(g_guiSettings.GetInt("videoplayer.adjustrefreshrate") != ADJUST_REFRESHRATE_OFF); - } - else if (strSetting.Equals("videoplayer.synctype")) + + case GUI_MSG_LOAD_SKIN: { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) pControl->SetEnabled(g_guiSettings.GetBool("videoplayer.usedisplayasclock")); + if (IsActive()) + m_returningFromSkinLoad = true; + break; } - else if (strSetting.Equals("videoplayer.maxspeedadjust")) + + case GUI_MSG_UPDATE_ITEM: { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) + if (m_delayedSetting != NULL) { - bool enabled = (g_guiSettings.GetBool("videoplayer.usedisplayasclock")) && - (g_guiSettings.GetInt("videoplayer.synctype") == SYNC_RESAMPLE); - pControl->SetEnabled(enabled); + // if updating the setting fails and param1 has been specifically set + // we need to call OnSettingChanged() to restore a valid value in the + // setting control + if (!m_delayedSetting->OnClick() && message.GetParam1() != 0) + OnSettingChanged(m_delayedSetting->GetSetting()); + m_delayedSetting.reset(); + return true; } + break; } - else if (strSetting.Equals("videoplayer.resamplequality")) + + case GUI_MSG_UPDATE: { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) + if (IsActive() && HasID(message.GetSenderId())) { - bool enabled = (g_guiSettings.GetBool("videoplayer.usedisplayasclock")) && - (g_guiSettings.GetInt("videoplayer.synctype") == SYNC_RESAMPLE); - pControl->SetEnabled(enabled); + int focusedControl = GetFocusedControlID(); + CreateSettings(); + SET_CONTROL_FOCUS(focusedControl, 0); } + break; } - else if (strSetting.Equals("weather.addonsettings")) + + case GUI_MSG_NOTIFY_ALL: { - AddonPtr addon; - if (CAddonMgr::Get().GetAddon(g_guiSettings.GetString("weather.addon"), addon, ADDON_SCRIPT_WEATHER)) + if (message.GetParam1() == GUI_MSG_WINDOW_RESIZE) { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) - pControl->SetEnabled(addon->HasSettings()); + if (IsActive() && CDisplaySettings::Get().GetCurrentResolution() != g_graphicsContext.GetVideoResolution()) + { + CDisplaySettings::Get().SetCurrentResolution(g_graphicsContext.GetVideoResolution(), true); + CreateSettings(); + } } + break; } - else if (strSetting.Equals("input.peripherals")) - { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) - pControl->SetEnabled(g_peripherals.GetNumberOfPeripherals() > 0); - } - else if (strSetting.Equals("input.enablejoystick")) - { - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) - pControl->SetEnabled(CPeripheralImon::GetCountOfImonsConflictWithDInput() == 0); - } - } - - g_guiSettings.SetChanged(); - g_guiSettings.NotifyObservers(ObservableMessageGuiSettings); -} - -void CGUIWindowSettingsCategory::OnClick(BaseSettingControlPtr pSettingControl) -{ - CStdString strSetting = pSettingControl->GetSetting()->GetSetting(); - if (strSetting.Equals("weather.addonsettings")) - { - CStdString name = g_guiSettings.GetString("weather.addon"); - AddonPtr addon; - if (CAddonMgr::Get().GetAddon(name, addon, ADDON_SCRIPT_WEATHER)) - { // TODO: maybe have ShowAndGetInput return a bool if settings changed, then only reset weather if true. - CGUIDialogAddonSettings::ShowAndGetInput(addon); - g_weatherManager.Refresh(); - } - } - else if (strSetting.Equals("lookandfeel.rssedit")) - { - AddonPtr addon; - CAddonMgr::Get().GetAddon("script.rss.editor",addon); - if (!addon) - { - if (!CGUIDialogYesNo::ShowAndGetInput(g_localizeStrings.Get(24076), g_localizeStrings.Get(24100),"RSS Editor",g_localizeStrings.Get(24101))) - return; - CAddonInstaller::Get().Install("script.rss.editor", true, "", false); - } - CBuiltins::Execute("RunScript(script.rss.editor)"); - } - else if (pSettingControl->GetSetting()->GetType() == SETTINGS_TYPE_ADDON) - { // prompt for the addon - CSettingAddon *setting = (CSettingAddon *)pSettingControl->GetSetting(); - CStdString addonID = setting->GetData(); - if (CGUIWindowAddonBrowser::SelectAddonID(setting->m_type, addonID, setting->m_type == ADDON_SCREENSAVER || setting->m_type == ADDON_VIZ || setting->m_type == ADDON_SCRIPT_WEATHER) == 1) - setting->SetData(addonID); - else - return; - } - else if (strSetting.Equals("input.peripherals")) - { - CGUIDialogPeripheralManager *dialog = (CGUIDialogPeripheralManager *)g_windowManager.GetWindow(WINDOW_DIALOG_PERIPHERAL_MANAGER); - if (dialog) - dialog->DoModal(); - // refresh settings - UpdateSettings(); - return; } - // if OnClick() returns false, the setting hasn't changed or doesn't - // require immediate update - if (!pSettingControl->OnClick()) - { - UpdateSettings(); - if (!pSettingControl->IsDelayed()) - return; - } - - if (pSettingControl->IsDelayed()) - { // delayed setting - m_delayedSetting = pSettingControl; - m_delayedTimer.StartZero(); - } - else - OnSettingChanged(pSettingControl); -} - -void CGUIWindowSettingsCategory::CheckForUpdates() -{ - for (unsigned int i = 0; i < m_vecSettings.size(); i++) - { - BaseSettingControlPtr pSettingControl = m_vecSettings[i]; - if (pSettingControl->NeedsUpdate()) - { - OnSettingChanged(pSettingControl); - pSettingControl->Reset(); - } - } + return CGUIWindow::OnMessage(message); } -void CGUIWindowSettingsCategory::OnSettingChanged(BaseSettingControlPtr pSettingControl) +bool CGUIWindowSettingsCategory::OnAction(const CAction &action) { - CStdString strSetting = pSettingControl->GetSetting()->GetSetting(); - - // ok, now check the various special things we need to do - if (pSettingControl->GetSetting()->GetType() == SETTINGS_TYPE_ADDON) + switch (action.GetID()) { - CSettingAddon *pSettingAddon = (CSettingAddon*)pSettingControl->GetSetting(); - if (pSettingAddon->m_type == ADDON_SKIN) - { - g_application.ReloadSkin(); - } - else if (pSettingAddon->m_type == ADDON_SCRIPT_WEATHER) + case ACTION_SETTINGS_RESET: { - g_weatherManager.Refresh(); - } - } - else if (strSetting.Equals("musicplayer.visualisation")) - { // new visualisation choosen... - CSettingString *pSettingString = (CSettingString *)pSettingControl->GetSetting(); - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID()); - if (pControl->GetValue() == 0) - pSettingString->SetData("None"); - else - pSettingString->SetData(pControl->GetCurrentLabel()); - } - else if (strSetting.Equals("debug.showloginfo")) - { - g_advancedSettings.SetDebugMode(g_guiSettings.GetBool("debug.showloginfo")); - } - /*else if (strSetting.Equals("musicfiles.repeat")) - { - g_playlistPlayer.SetRepeat(PLAYLIST_MUSIC_TEMP, g_guiSettings.GetBool("musicfiles.repeat") ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE); - }*/ - else if (strSetting.Equals("musiclibrary.cleanup")) - { - CMusicDatabase musicdatabase; - musicdatabase.Clean(); - CUtil::DeleteMusicDatabaseDirectoryCache(); - } - else if (strSetting.Equals("videolibrary.cleanup")) - { - if (CGUIDialogYesNo::ShowAndGetInput(313, 333, 0, 0)) - g_application.StartVideoCleanup(); - } - else if (strSetting.Equals("videolibrary.export")) - CBuiltins::Execute("exportlibrary(video)"); - else if (strSetting.Equals("musiclibrary.export")) - CBuiltins::Execute("exportlibrary(music)"); - else if (strSetting.Equals("karaoke.export") ) - { - CContextButtons choices; - choices.Add(1, g_localizeStrings.Get(22034)); - choices.Add(2, g_localizeStrings.Get(22035)); - - int retVal = CGUIDialogContextMenu::ShowAndGetChoice(choices); - if ( retVal > 0 ) - { - CStdString path(CProfilesManager::Get().GetDatabaseFolder()); - VECSOURCES shares; - g_mediaManager.GetLocalDrives(shares); - if (CGUIDialogFileBrowser::ShowAndGetDirectory(shares, g_localizeStrings.Get(661), path, true)) + if (CGUIDialogYesNo::ShowAndGetInput(10041, 0, 10042, 0)) { - CMusicDatabase musicdatabase; - musicdatabase.Open(); - - if ( retVal == 1 ) - { - URIUtils::AddFileToFolder(path, "karaoke.html", path); - musicdatabase.ExportKaraokeInfo( path, true ); - } - else + for(vector<BaseSettingControlPtr>::iterator it = m_settingControls.begin(); it != m_settingControls.end(); it++) { - URIUtils::AddFileToFolder(path, "karaoke.csv", path); - musicdatabase.ExportKaraokeInfo( path, false ); + CSetting *setting = (*it)->GetSetting(); + if (setting != NULL) + setting->Reset(); } - musicdatabase.Close(); } + return true; } - } - else if (strSetting.Equals("videolibrary.import")) - { - CStdString path; - VECSOURCES shares; - g_mediaManager.GetLocalDrives(shares); - if (CGUIDialogFileBrowser::ShowAndGetDirectory(shares, g_localizeStrings.Get(651) , path)) - { - CVideoDatabase videodatabase; - videodatabase.Open(); - videodatabase.ImportFromXML(path); - videodatabase.Close(); - } - } - else if (strSetting.Equals("musiclibrary.import")) - { - CStdString path; - VECSOURCES shares; - g_mediaManager.GetLocalDrives(shares); - if (CGUIDialogFileBrowser::ShowAndGetFile(shares, "musicdb.xml", g_localizeStrings.Get(651) , path)) - { - CMusicDatabase musicdatabase; - musicdatabase.Open(); - musicdatabase.ImportFromXML(path); - musicdatabase.Close(); - } - } - else if (strSetting.Equals("karaoke.importcsv")) - { - CStdString path(CProfilesManager::Get().GetDatabaseFolder()); - VECSOURCES shares; - g_mediaManager.GetLocalDrives(shares); - if (CGUIDialogFileBrowser::ShowAndGetFile(shares, "karaoke.csv", g_localizeStrings.Get(651) , path)) - { - CMusicDatabase musicdatabase; - musicdatabase.Open(); - musicdatabase.ImportKaraokeInfo(path); - musicdatabase.Close(); - } - } - else if (strSetting.Left(22).Equals("MusicPlayer.ReplayGain")) - { // Update our replaygain settings - ReplayGainSettings &replayGainSettings = CAudioDecoder::GetReplayGainSettings(); - replayGainSettings.iType = g_guiSettings.GetInt("musicplayer.replaygaintype"); - replayGainSettings.iPreAmp = g_guiSettings.GetInt("musicplayer.replaygainpreamp"); - replayGainSettings.iNoGainPreAmp = g_guiSettings.GetInt("musicplayer.replaygainnogainpreamp"); - replayGainSettings.bAvoidClipping = g_guiSettings.GetBool("musicplayer.replaygainavoidclipping"); - } -#ifdef HAS_WEB_SERVER - else if ( strSetting.Equals("services.webserver") || strSetting.Equals("services.webserverport")) - { - if (strSetting.Equals("services.webserverport")) - ValidatePortNumber(pSettingControl, "8080", "80"); - g_application.StopWebServer(); - if (g_guiSettings.GetBool("services.webserver")) - if (!g_application.StartWebServer()) - { - CGUIDialogOK::ShowAndGetInput(g_localizeStrings.Get(33101), "", g_localizeStrings.Get(33100), ""); - g_guiSettings.SetBool("services.webserver", false); - } - } - else if (strSetting.Equals("services.webserverusername") || strSetting.Equals("services.webserverpassword")) - { - g_application.m_WebServer.SetCredentials(g_guiSettings.GetString("services.webserverusername"), g_guiSettings.GetString("services.webserverpassword")); - } -#endif - else if (strSetting.Equals("services.zeroconf")) - { -#ifdef HAS_ZEROCONF - //ifdef zeroconf here because it's only found in guisettings if defined - if(g_guiSettings.GetBool("services.zeroconf")) - { - CZeroconf::GetInstance()->Stop(); - CZeroconf::GetInstance()->Start(); - } -#ifdef HAS_AIRPLAY - else - { - g_application.StopAirplayServer(true); - g_guiSettings.SetBool("services.airplay", false); - CZeroconf::GetInstance()->Stop(); - } -#endif -#endif - } - else if (strSetting.Equals("services.airplay")) - { -#ifdef HAS_AIRPLAY - if (g_guiSettings.GetBool("services.airplay")) - { -#ifdef HAS_ZEROCONF - // AirPlay needs zeroconf - if(!g_guiSettings.GetBool("services.zeroconf")) - { - g_guiSettings.SetBool("services.zeroconf", true); - CZeroconf::GetInstance()->Stop(); - CZeroconf::GetInstance()->Start(); - } -#endif //HAS_ZEROCONF - g_application.StartAirplayServer();//will stop the server before internal - } - else - g_application.StopAirplayServer(true);//will stop the server before internal -#endif//HAS_AIRPLAY - } - else if (strSetting.Equals("network.ipaddress")) - { - if (g_guiSettings.GetInt("network.assignment") == NETWORK_STATIC) - { - CStdString strDefault = g_guiSettings.GetString("network.ipaddress").Left(g_guiSettings.GetString("network.ipaddress").ReverseFind('.'))+".1"; - if (g_guiSettings.GetString("network.gateway").Equals("0.0.0.0")) - g_guiSettings.SetString("network.gateway",strDefault); - if (g_guiSettings.GetString("network.dns").Equals("0.0.0.0")) - g_guiSettings.SetString("network.dns",strDefault); - - } - } - else if (strSetting.Equals("network.httpproxyport")) - { - ValidatePortNumber(pSettingControl, "8080", "8080", false); - } - else if (strSetting.Equals("videoplayer.calibrate") || strSetting.Equals("videoscreen.guicalibration")) - { // activate the video calibration screen - g_windowManager.ActivateWindow(WINDOW_SCREEN_CALIBRATION); - } - else if (strSetting.Equals("videoscreen.testpattern")) - { // activate the test pattern - g_windowManager.ActivateWindow(WINDOW_TEST_PATTERN); - } - else if (strSetting.Equals("subtitles.height")) - { - if (!CUtil::IsUsingTTFSubtitles()) + case ACTION_SETTINGS_LEVEL_CHANGE: { - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID()); - ((CSettingInt *)pSettingControl->GetSetting())->FromString(pControl->GetCurrentLabel()); - } - } - else if (strSetting.Equals("subtitles.font")) - { - CSettingString *pSettingString = (CSettingString *)pSettingControl->GetSetting(); - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID()); - pSettingString->SetData(pControl->GetCurrentLabel()); - CSetting *pSetting = (CSetting *)g_guiSettings.GetSetting("subtitles.height"); - FillInSubtitleHeights(pSetting, (CGUISpinControlEx *)GetControl(GetSetting(pSetting->GetSetting())->GetID())); - } - else if (strSetting.Equals("subtitles.charset")) - { - CSettingString *pSettingString = (CSettingString *)pSettingControl->GetSetting(); - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID()); - CStdString newCharset="DEFAULT"; - if (pControl->GetValue()!=0) - newCharset = g_charsetConverter.getCharsetNameByLabel(pControl->GetCurrentLabel()); - if (newCharset != "" && (newCharset != pSettingString->GetData() || newCharset=="DEFAULT")) - { - pSettingString->SetData(newCharset); - g_charsetConverter.reset(); - } - } - else if (strSetting.Equals("karaoke.fontheight")) - { - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID()); - ((CSettingInt *)pSettingControl->GetSetting())->FromString(pControl->GetCurrentLabel()); - } - else if (strSetting.Equals("karaoke.font")) - { - CSettingString *pSettingString = (CSettingString *)pSettingControl->GetSetting(); - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID()); - pSettingString->SetData(pControl->GetCurrentLabel()); - CSetting *pSetting = (CSetting *)g_guiSettings.GetSetting("karaoke.fontheight"); - FillInSubtitleHeights(pSetting, (CGUISpinControlEx *)GetControl(GetSetting(pSetting->GetSetting())->GetID())); - } - else if (strSetting.Equals("karaoke.charset")) - { - CSettingString *pSettingString = (CSettingString *)pSettingControl->GetSetting(); - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID()); - CStdString newCharset="DEFAULT"; - if (pControl->GetValue()!=0) - newCharset = g_charsetConverter.getCharsetNameByLabel(pControl->GetCurrentLabel()); - if (newCharset != "" && (newCharset != pSettingString->GetData() || newCharset=="DEFAULT")) - { - pSettingString->SetData(newCharset); - g_charsetConverter.reset(); - } - } - else if (strSetting.Equals("locale.charset")) - { - CSettingString *pSettingString = (CSettingString *)pSettingControl->GetSetting(); - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID()); - CStdString newCharset="DEFAULT"; - if (pControl->GetValue()!=0) - newCharset = g_charsetConverter.getCharsetNameByLabel(pControl->GetCurrentLabel()); - if (newCharset != "" && (newCharset != pSettingString->GetData() || newCharset=="DEFAULT")) - { - pSettingString->SetData(newCharset); - g_charsetConverter.reset(); - } - } - else if (strSetting.Equals("lookandfeel.font")) - { // new font choosen... - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID()); - CStdString strSkinFontSet = m_SkinFontSetIDs[pControl->GetCurrentLabel()]; - if (strSkinFontSet != ".svn" && strSkinFontSet != g_guiSettings.GetString("lookandfeel.font")) - { - g_guiSettings.SetString("lookandfeel.font", strSkinFontSet); - g_application.ReloadSkin(); - } - } - else if (strSetting.Equals("lookandfeel.soundskin")) - { // new sound skin choosen... - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID()); - if (pControl->GetValue()==0) - g_guiSettings.SetString("lookandfeel.soundskin", "OFF"); - else if (pControl->GetValue()==1) - g_guiSettings.SetString("lookandfeel.soundskin", "SKINDEFAULT"); - else - g_guiSettings.SetString("lookandfeel.soundskin", pControl->GetCurrentLabel()); + CViewStateSettings::Get().CycleSettingLevel(); + CSettings::Get().Save(); - g_audioManager.Enable(true); - g_audioManager.Load(); - } - else if (strSetting.Equals("lookandfeel.skinsettings")) - { - g_windowManager.ActivateWindow(WINDOW_SKIN_SETTINGS); - } - else if (strSetting.Equals("input.enablemouse")) - { - g_Mouse.SetEnabled(g_guiSettings.GetBool("input.enablemouse")); - } - else if (strSetting.Equals("input.enablejoystick")) - { -#if defined(HAS_SDL_JOYSTICK) - g_Joystick.SetEnabled(g_guiSettings.GetBool("input.enablejoystick") - && CPeripheralImon::GetCountOfImonsConflictWithDInput() == 0); -#endif - } - else if (strSetting.Equals("videoscreen.screen")) - { - DisplayMode mode = g_guiSettings.GetInt("videoscreen.screen"); - // Cascade - FillInResolutions("videoscreen.resolution", mode, RES_DESKTOP, true); - } - else if (strSetting.Equals("videoscreen.resolution")) - { - RESOLUTION nextRes = (RESOLUTION) g_guiSettings.GetInt("videoscreen.resolution"); - // Cascade - FillInRefreshRates("videoscreen.screenmode", nextRes, true); - } - else if (strSetting.Equals("videoscreen.screenmode")) - { - int iControlID = pSettingControl->GetID(); - CGUIMessage msg(GUI_MSG_ITEM_SELECTED, GetID(), iControlID); - g_windowManager.SendMessage(msg); - RESOLUTION nextRes = (RESOLUTION)msg.GetParam1(); + // try to keep the current position + std::string oldCategory; + if (m_iCategory >= 0 && m_iCategory < (int)m_categories.size()) + oldCategory = m_categories[m_iCategory]->GetId(); - OnRefreshRateChanged(nextRes); - } - else if (strSetting.Equals("videoscreen.vsync")) - { - int iControlID = pSettingControl->GetID(); - CGUIMessage msg(GUI_MSG_ITEM_SELECTED, GetID(), iControlID); - g_windowManager.SendMessage(msg); -// DXMERGE: This may be useful -// g_videoConfig.SetVSyncMode((VSYNC)msg.GetParam1()); - } - else if (strSetting.Equals("videoscreen.fakefullscreen")) - { - if (g_graphicsContext.IsFullScreenRoot()) - g_graphicsContext.SetVideoResolution(g_graphicsContext.GetVideoResolution(), true); - } - else if (strSetting.Equals("locale.audiolanguage")) - { // new audio language chosen... - CSettingString *pSettingString = (CSettingString *)pSettingControl->GetSetting(); - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID()); - int iLanguage = pControl->GetValue(); - if (iLanguage < 2) - { - if (iLanguage < 1) - g_guiSettings.SetString(strSetting, "original"); - else - g_guiSettings.SetString(strSetting, "default"); - g_langInfo.SetAudioLanguage(""); - } - else - { - CStdString strLanguage = pControl->GetCurrentLabel(); - if (strLanguage != pSettingString->GetData()) - { - g_guiSettings.SetString(strSetting, strLanguage); - g_langInfo.SetAudioLanguage(strLanguage); - } - } - } - else if (strSetting.Equals("locale.subtitlelanguage")) - { // new subtitle language chosen... - CSettingString *pSettingString = (CSettingString *)pSettingControl->GetSetting(); - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID()); - int iLanguage = pControl->GetValue(); - if (iLanguage < 2) - { - if (iLanguage < 1) - g_guiSettings.SetString(strSetting, "original"); - else - g_guiSettings.SetString(strSetting, "default"); - g_langInfo.SetSubtitleLanguage(""); - } - else - { - CStdString strLanguage = pControl->GetCurrentLabel(); - if (strLanguage != pSettingString->GetData()) + SET_CONTROL_LABEL(CONTRL_BTN_LEVELS, 10036 + (int)CViewStateSettings::Get().GetSettingLevel()); + // only re-create the categories, the settings will be created later + SetupControls(false); + + m_iCategory = 0; + // try to find the category that was previously selected + if (!oldCategory.empty()) { - g_guiSettings.SetString(strSetting, strLanguage); - g_langInfo.SetSubtitleLanguage(strLanguage); + for (int i = 0; i < (int)m_categories.size(); i++) + { + if (m_categories[i]->GetId() == oldCategory) + { + m_iCategory = i; + break; + } + } } - } - } - else if (strSetting.Equals("locale.language")) - { // new language chosen... - CSettingString *pSettingString = (CSettingString *)pSettingControl->GetSetting(); - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID()); - CStdString strLanguage = pControl->GetCurrentLabel(); - if (strLanguage != ".svn" && strLanguage != pSettingString->GetData()) - g_application.SetLanguage(strLanguage); - - // user set language, no longer use the TV's language - vector<CPeripheral *> cecDevices; - if (g_peripherals.GetPeripheralsWithFeature(cecDevices, FEATURE_CEC) > 0) - { - for (vector<CPeripheral *>::iterator it = cecDevices.begin(); it != cecDevices.end(); it++) - (*it)->SetSetting("use_tv_menu_language", false); - } - } - else if (strSetting.Equals("lookandfeel.skintheme")) - { //a new Theme was chosen - CSettingString *pSettingString = (CSettingString *)pSettingControl->GetSetting(); - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID()); - - CStdString strSkinTheme; - - if (pControl->GetValue() == 0) // Use default theme - strSkinTheme = "SKINDEFAULT"; - else - strSkinTheme = pControl->GetCurrentLabel(); - - if (strSkinTheme != pSettingString->GetData()) - { - g_guiSettings.SetString("lookandfeel.skintheme", strSkinTheme); - // also set the default color theme - CStdString colorTheme(URIUtils::ReplaceExtension(strSkinTheme, ".xml")); - if (colorTheme.Equals("Textures.xml")) - colorTheme = "defaults.xml"; - g_guiSettings.SetString("lookandfeel.skincolors", colorTheme); - g_application.ReloadSkin(); - } - } - else if (strSetting.Equals("lookandfeel.skincolors")) - { //a new color was chosen - CSettingString *pSettingString = (CSettingString *)pSettingControl->GetSetting(); - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID()); - - CStdString strSkinColor; - - if (pControl->GetValue() == 0) // Use default colors - strSkinColor = "SKINDEFAULT"; - else - strSkinColor = pControl->GetCurrentLabel() + ".xml"; - - if (strSkinColor != pSettingString->GetData()) - { - g_guiSettings.SetString("lookandfeel.skincolors", strSkinColor); - g_application.ReloadSkin(); - } - } - else if (strSetting.Equals("videoplayer.displayresolution")) - { - CSettingInt *pSettingInt = (CSettingInt *)pSettingControl->GetSetting(); - int iControlID = pSettingControl->GetID(); - CGUIMessage msg(GUI_MSG_ITEM_SELECTED, GetID(), iControlID); - g_windowManager.SendMessage(msg); - pSettingInt->SetData(msg.GetParam1()); - } - else if (strSetting.Equals("videoscreen.flickerfilter") || strSetting.Equals("videoscreen.soften")) - { // reset display - g_graphicsContext.SetVideoResolution(CDisplaySettings::Get().GetCurrentResolution()); - } - else if (strSetting.Equals("screensaver.preview")) - { - g_application.ActivateScreenSaver(true); - } - else if (strSetting.Equals("screensaver.settings")) - { - AddonPtr addon; - if (CAddonMgr::Get().GetAddon(g_guiSettings.GetString("screensaver.mode"), addon, ADDON_SCREENSAVER)) - CGUIDialogAddonSettings::ShowAndGetInput(addon); - } - else if (strSetting.Equals("debug.screenshotpath") || strSetting.Equals("audiocds.recordingpath") || strSetting.Equals("subtitles.custompath") || strSetting.Equals("pvrmenu.iconpath")) - { - CSettingString *pSettingString = (CSettingString *)pSettingControl->GetSetting(); - CStdString path = g_guiSettings.GetString(strSetting,false); - VECSOURCES shares; - - bool bWriteOnly = true; - if (strSetting.Equals("pvrmenu.iconpath")) - { - bWriteOnly = false; - } - else if (strSetting.Equals("subtitles.custompath")) - { - bWriteOnly = false; - shares = *CMediaSourceSettings::Get().GetSources("video"); - } - - g_mediaManager.GetNetworkLocations(shares); - g_mediaManager.GetLocalDrives(shares); - - UpdateSettings(); - - if (CGUIDialogFileBrowser::ShowAndGetDirectory(shares, g_localizeStrings.Get(pSettingString->m_iHeadingString), path, bWriteOnly)) - { - pSettingString->SetData(path); + CreateSettings(); + return true; } - } - else if (strSetting.Left(22).Equals("MusicPlayer.ReplayGain")) - { // Update our replaygain settings - ReplayGainSettings &replayGainSettings = CAudioDecoder::GetReplayGainSettings(); - replayGainSettings.iType = g_guiSettings.GetInt("musicplayer.replaygaintype"); - replayGainSettings.iPreAmp = g_guiSettings.GetInt("musicplayer.replaygainpreamp"); - replayGainSettings.iNoGainPreAmp = g_guiSettings.GetInt("musicplayer.replaygainnogainpreamp"); - replayGainSettings.bAvoidClipping = g_guiSettings.GetBool("musicplayer.replaygainavoidclipping"); - } - else if (strSetting.Equals("locale.country")) - { - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID()); - - const CStdString& strRegion=pControl->GetCurrentLabel(); - g_langInfo.SetCurrentRegion(strRegion); - g_guiSettings.SetString("locale.country", strRegion); - g_weatherManager.Refresh(); // need to reset our weather, as temperatures need re-translating. - } - else if (strSetting.Equals("smb.winsserver") || strSetting.Equals("smb.workgroup") ) - { - if (g_guiSettings.GetString("smb.winsserver") == "0.0.0.0") - g_guiSettings.SetString("smb.winsserver", ""); - /* okey we really don't need to restarat, 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(14038, 14039, 14040, -1, -1)) + case ACTION_SHOW_INFO: { - g_settings.Save(); - CApplicationMessenger::Get().RestartApp(); - } - } - else if (strSetting.Equals("services.upnpserver")) - { -#ifdef HAS_UPNP - if (g_guiSettings.GetBool("services.upnpserver")) - g_application.StartUPnPServer(); - else - g_application.StopUPnPServer(); -#endif - } - else if (strSetting.Equals("services.upnprenderer")) - { -#ifdef HAS_UPNP - if (g_guiSettings.GetBool("services.upnprenderer")) - g_application.StartUPnPRenderer(); - else - g_application.StopUPnPRenderer(); -#endif - } - else if (strSetting.Equals("services.upnpcontroller")) - { -#ifdef HAS_UPNP - g_application.StopUPnPClient(); /* always stop and restart */ - if (g_guiSettings.GetBool("services.upnpcontroller")) - g_application.StartUPnPClient(); -#endif - } - else if (strSetting.Equals("services.esenabled")) - { -#ifdef HAS_EVENT_SERVER - if (g_guiSettings.GetBool("services.esenabled")) - { - if (!g_application.StartEventServer()) + int label = -1; + int help = -1; + int focusedControl = GetFocusedControlID(); + // check if we are focusing a category + if (focusedControl >= CONTROL_START_BUTTONS && focusedControl < (int)(CONTROL_START_BUTTONS + m_categories.size())) { - CGUIDialogOK::ShowAndGetInput(g_localizeStrings.Get(33102), "", g_localizeStrings.Get(33100), ""); - g_guiSettings.SetBool("services.esenabled", false); - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) pControl->SetEnabled(false); + CSettingCategory *category = m_categories[focusedControl - CONTROL_START_BUTTONS]; + label = category->GetLabel(); + help = category->GetHelp(); } - } - else - { - if (!g_application.StopEventServer(true, true)) + else if (focusedControl >= CONTROL_START_CONTROL && focusedControl < (int)(CONTROL_START_CONTROL + m_settingControls.size())) { - g_guiSettings.SetBool("services.esenabled", true); - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) pControl->SetEnabled(true); - } - } -#endif -#ifdef HAS_JSONRPC - if (g_guiSettings.GetBool("services.esenabled")) - { - if (!g_application.StartJSONRPCServer()) - CGUIDialogOK::ShowAndGetInput(g_localizeStrings.Get(33103), "", g_localizeStrings.Get(33100), ""); - } - else - g_application.StopJSONRPCServer(false); -#endif - } - else if (strSetting.Equals("services.esport")) - { -#ifdef HAS_EVENT_SERVER - ValidatePortNumber(pSettingControl, "9777", "9777"); - //restart eventserver without asking user - if (g_application.StopEventServer(true, false)) - { - if (!g_application.StartEventServer()) - CGUIDialogOK::ShowAndGetInput(g_localizeStrings.Get(33102), "", g_localizeStrings.Get(33100), ""); - } -#if defined(TARGET_DARWIN_OSX) - //reconfigure XBMCHelper for port changes - XBMCHelper::GetInstance().Configure(); -#endif -#endif - } - else if (strSetting.Equals("services.esallinterfaces")) - { -#ifdef HAS_EVENT_SERVER - if (g_guiSettings.GetBool("services.esenabled")) - { - if (g_application.StopEventServer(true, true)) - { - if (!g_application.StartEventServer()) - CGUIDialogOK::ShowAndGetInput(g_localizeStrings.Get(33102), "", g_localizeStrings.Get(33100), ""); + CSetting *setting = GetSettingControl(focusedControl)->GetSetting(); + if (setting != NULL) + { + label = setting->GetLabel(); + help = setting->GetHelp(); + } } else - { - g_guiSettings.SetBool("services.esenabled", true); - CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID()); - if (pControl) pControl->SetEnabled(true); - } - } -#endif -#ifdef HAS_JSONRPC - if (g_guiSettings.GetBool("services.esenabled")) - { - if (!g_application.StartJSONRPCServer()) - CGUIDialogOK::ShowAndGetInput(g_localizeStrings.Get(33103), "", g_localizeStrings.Get(33100), ""); - } - else - g_application.StopJSONRPCServer(false); -#endif - } - else if (strSetting.Equals("services.esinitialdelay") || - strSetting.Equals("services.escontinuousdelay")) - { -#ifdef HAS_EVENT_SERVER - if (g_guiSettings.GetBool("services.esenabled")) - { - g_application.RefreshEventServer(); - } -#endif - } - else if (strSetting.Equals("pvrmanager.enabled")) - { - if (g_guiSettings.GetBool("pvrmanager.enabled")) - CApplicationMessenger::Get().ExecBuiltIn("XBMC.StartPVRManager", false); - else - CApplicationMessenger::Get().ExecBuiltIn("XBMC.StopPVRManager", false); - } - else if (strSetting.Equals("masterlock.lockcode")) - { - // Now Prompt User to enter the old and then the new MasterCode! - if(g_passwordManager.SetMasterLockMode()) - { - // We asked for the master password and saved the new one! - // Nothing todo here - } - } - else if (strSetting.Equals("network.interface")) - { - NetworkInterfaceChanged(); - } -#ifdef HAS_LINUX_NETWORK - else if (strSetting.Equals("network.save")) - { - NetworkAssignment iAssignment; - CStdString sIPAddress; - CStdString sNetworkMask; - CStdString sDefaultGateway; - CStdString sWirelessNetwork; - CStdString sWirelessKey; - CStdString sDns; - EncMode iWirelessEnc; - CStdString ifaceName; - - CGUISpinControlEx *ifaceControl = (CGUISpinControlEx *)GetControl(GetSetting("network.interface")->GetID()); - ifaceName = ifaceControl->GetLabel(); - CNetworkInterface* iface = g_application.getNetwork().GetInterfaceByName(ifaceName); - - // Update controls with information - CGUISpinControlEx* pControl1 = (CGUISpinControlEx *)GetControl(GetSetting("network.assignment")->GetID()); - if (pControl1) iAssignment = (NetworkAssignment) pControl1->GetValue(); - CGUIButtonControl* pControl2 = (CGUIButtonControl *)GetControl(GetSetting("network.ipaddress")->GetID()); - if (pControl2) sIPAddress = pControl2->GetLabel2(); - pControl2 = (CGUIButtonControl *)GetControl(GetSetting("network.subnet")->GetID()); - if (pControl2) sNetworkMask = pControl2->GetLabel2(); - pControl2 = (CGUIButtonControl *)GetControl(GetSetting("network.gateway")->GetID()); - if (pControl2) sDefaultGateway = pControl2->GetLabel2(); - pControl2 = (CGUIButtonControl *)GetControl(GetSetting("network.dns")->GetID()); - if (pControl2) sDns = pControl2->GetLabel2(); - pControl1 = (CGUISpinControlEx *)GetControl(GetSetting("network.enc")->GetID()); - if (pControl1) iWirelessEnc = (EncMode) pControl1->GetValue(); - pControl2 = (CGUIButtonControl *)GetControl(GetSetting("network.essid")->GetID()); - if (pControl2) sWirelessNetwork = pControl2->GetLabel2(); - pControl2 = (CGUIButtonControl *)GetControl(GetSetting("network.key")->GetID()); - if (pControl2) sWirelessKey = pControl2->GetLabel2(); - - CGUIDialogProgress* pDlgProgress = (CGUIDialogProgress*)g_windowManager.GetWindow(WINDOW_DIALOG_PROGRESS); - pDlgProgress->SetLine(0, ""); - pDlgProgress->SetLine(1, g_localizeStrings.Get(784)); - pDlgProgress->SetLine(2, ""); - pDlgProgress->StartModal(); - pDlgProgress->Progress(); - - std::vector<CStdString> nameServers; - nameServers.push_back(sDns); - g_application.getNetwork().SetNameServers(nameServers); - iface->SetSettings(iAssignment, sIPAddress, sNetworkMask, sDefaultGateway, sWirelessNetwork, sWirelessKey, iWirelessEnc); - - pDlgProgress->Close(); - - if (iAssignment == NETWORK_DISABLED) - CGUIDialogOK::ShowAndGetInput(0, 788, 0, 0); - else if (iface->IsConnected()) - CGUIDialogOK::ShowAndGetInput(0, 785, 0, 0); - else - CGUIDialogOK::ShowAndGetInput(0, 786, 0, 0); - } - else if (strSetting.Equals("network.essid")) - { - CGUIDialogAccessPoints *dialog = (CGUIDialogAccessPoints *)g_windowManager.GetWindow(WINDOW_DIALOG_ACCESS_POINTS); - if (dialog) - { - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(GetSetting("network.interface")->GetID()); - dialog->SetInterfaceName(pControl->GetLabel()); - dialog->DoModal(); - - if (dialog->WasItemSelected()) - { - CGUIButtonControl* pControl2 = (CGUIButtonControl *)GetControl(GetSetting("network.essid")->GetID()); - if (pControl2) pControl2->SetLabel2(dialog->GetSelectedAccessPointEssId()); - pControl = (CGUISpinControlEx *)GetControl(GetSetting("network.enc")->GetID()); - if (pControl) pControl->SetValue(dialog->GetSelectedAccessPointEncMode()); - } - } - } -#endif -#ifdef _LINUX - else if (strSetting.Equals("locale.timezonecountry")) - { - CGUISpinControlEx *pControlCountry = (CGUISpinControlEx *)GetControl(pSettingControl->GetID()); - CStdString country = pControlCountry->GetCurrentLabel(); - - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(GetSetting("locale.timezone")->GetID()); - pControl->Clear(); - vector<CStdString> timezones = g_timezone.GetTimezonesByCountry(country); - for (unsigned int i=0; i < timezones.size(); i++) - { - pControl->AddLabel(timezones[i], i); - } - - g_timezone.SetTimezone(pControl->GetLabel()); - g_guiSettings.SetString("locale.timezonecountry",pControlCountry->GetLabel().c_str()); - - CGUISpinControlEx *tzControl = (CGUISpinControlEx *)GetControl(GetSetting("locale.timezone")->GetID()); - g_guiSettings.SetString("locale.timezone", tzControl->GetLabel().c_str()); - - CDateTime::ResetTimezoneBias(); - } - else if (strSetting.Equals("locale.timezone")) - { - CGUISpinControlEx *tzControl = (CGUISpinControlEx *)GetControl(GetSetting("locale.timezone")->GetID()); - g_timezone.SetTimezone(tzControl->GetLabel()); - g_guiSettings.SetString("locale.timezone", tzControl->GetLabel().c_str()); - - tzControl = (CGUISpinControlEx *)GetControl(GetSetting("locale.timezonecountry")->GetID()); - g_guiSettings.SetString("locale.timezonecountry", tzControl->GetLabel().c_str()); + break; - CDateTime::ResetTimezoneBias(); - } -#endif - else if (strSetting.Equals("lookandfeel.skinzoom")) - { - g_windowManager.SendMessage(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_WINDOW_RESIZE); - } - else if (strSetting.Equals("videolibrary.flattentvshows") || - strSetting.Equals("videolibrary.removeduplicates") || - strSetting.Equals("videolibrary.groupmoviesets")) - { - CUtil::DeleteVideoDatabaseDirectoryCache(); - } - else if (strSetting.Equals("pvrmenu.searchicons") && g_PVRManager.IsStarted()) - { - g_PVRManager.SearchMissingChannelIcons(); - } - else if (strSetting.Equals("pvrmanager.resetdb")) - { - if (g_PVRManager.CheckParentalPIN(g_localizeStrings.Get(19262).c_str()) && - CGUIDialogYesNo::ShowAndGetInput(19098, 19186, 750, 0)) - { - CDateTime::ResetTimezoneBias(); - g_PVRManager.ResetDatabase(false); - } - } - else if (strSetting.Equals("epg.resetepg")) - { - if (CGUIDialogYesNo::ShowAndGetInput(19098, 19188, 750, 0)) - { - CDateTime::ResetTimezoneBias(); - g_PVRManager.ResetDatabase(true); - } - } - else if (strSetting.Equals("pvrmanager.channelscan") && g_PVRManager.IsStarted()) - { - if (CGUIDialogYesNo::ShowAndGetInput(19098, 19118, 19194, 0)) - g_PVRManager.StartChannelScan(); - } - else if (strSetting.Equals("pvrmanager.channelmanager") && g_PVRManager.IsStarted()) - { - CGUIDialogPVRChannelManager *dialog = (CGUIDialogPVRChannelManager *)g_windowManager.GetWindow(WINDOW_DIALOG_PVR_CHANNEL_MANAGER); - if (dialog) - { - dialog->DoModal(); - } - } - else if (strSetting.Equals("pvrclient.menuhook") && g_PVRManager.IsStarted()) - { - g_PVRManager.Get().Clients()->ProcessMenuHooks(-1, PVR_MENUHOOK_SETTING); - } - else if (strSetting.compare(0, 12, "audiooutput.") == 0) - { - if (strSetting.Equals("audiooutput.audiodevice")) - { - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID()); -#if defined(TARGET_DARWIN) - // save the sinkname - since we don't have sinks on osx - // we need to get the fitting sinkname for the device label from the - // factory - std::string label2sink = pControl->GetCurrentLabel(); - CAEFactory::VerifyOutputDevice(label2sink, false); - g_guiSettings.SetString("audiooutput.audiodevice", label2sink.c_str()); -#else - g_guiSettings.SetString("audiooutput.audiodevice", m_AnalogAudioSinkMap[pControl->GetCurrentLabel()]); -#endif - } -#if !defined(TARGET_DARWIN) - else if (strSetting.Equals("audiooutput.passthroughdevice")) - { - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID()); - g_guiSettings.SetString("audiooutput.passthroughdevice", m_DigitalAudioSinkMap[pControl->GetCurrentLabel()]); - } -#endif - else if (strSetting.Equals("audiooutput.guisoundmode")) - { - CAEFactory::SetSoundMode(g_guiSettings.GetInt("audiooutput.guisoundmode")); - } - - CAEFactory::OnSettingsChange(strSetting); - } - else if (strSetting.Equals("pvrparental.enabled")) - { - if (g_guiSettings.GetBool("pvrparental.enabled") && g_guiSettings.GetString("pvrparental.pin").GetLength() == 0) - { - CStdString newPassword = ""; - bool bNewPassword = CGUIDialogNumeric::ShowAndVerifyNewPassword(newPassword); - if (bNewPassword) + if (help >= 0) { - // password set... save it - g_guiSettings.SetString("pvrparental.pin", newPassword); + CGUIDialogTextViewer *dialog = (CGUIDialogTextViewer*)g_windowManager.GetWindow(WINDOW_DIALOG_TEXT_VIEWER); + if (dialog != NULL) + { + if (label < 0) + label = 10043; // "Help" + dialog->SetHeading(g_localizeStrings.Get(label)); + dialog->SetText(g_localizeStrings.Get(help)); + dialog->DoModal(); + } } else - { - // password not set... disable parental - g_guiSettings.SetBool("pvrparental.enabled", false); - } + CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(10043), g_localizeStrings.Get(10044), 2000U); + return true; } - } - - UpdateSettings(); -} - -void CGUIWindowSettingsCategory::FreeControls() -{ - // clear the category group - CGUIControlGroupList *control = (CGUIControlGroupList *)GetControl(CATEGORY_GROUP_ID); - if (control) - { - control->FreeResources(); - control->ClearAll(); - } - m_vecSections.clear(); - FreeSettingsControls(); -} -void CGUIWindowSettingsCategory::FreeSettingsControls() -{ - // clear the settings group - CGUIControlGroupList *control = (CGUIControlGroupList *)GetControl(SETTINGS_GROUP_ID); - if (control) - { - control->FreeResources(); - control->ClearAll(); + default: + break; } - for (int i = 0; (size_t)i < m_vecSettings.size(); i++) - m_vecSettings[i]->Clear(); - - m_vecSettings.clear(); -} - -CGUIControl* CGUIWindowSettingsCategory::AddSetting(CSetting *pSetting, float width, int &iControlID) -{ - if (!pSetting->IsVisible()) return NULL; // not displayed in current session - BaseSettingControlPtr pSettingControl; - CGUIControl *pControl = NULL; - if (pSetting->GetControlType() == CHECKMARK_CONTROL) - { - pControl = new CGUIRadioButtonControl(*m_pOriginalRadioButton); - if (!pControl) return NULL; - ((CGUIRadioButtonControl *)pControl)->SetLabel(g_localizeStrings.Get(pSetting->GetLabel())); - pControl->SetWidth(width); - pSettingControl.reset(new CGUIRadioButtonSettingControl((CGUIRadioButtonControl *)pControl, iControlID, pSetting)); - } - else if (pSetting->GetControlType() == SPIN_CONTROL_FLOAT || pSetting->GetControlType() == SPIN_CONTROL_INT_PLUS || pSetting->GetControlType() == SPIN_CONTROL_TEXT || pSetting->GetControlType() == SPIN_CONTROL_INT) - { - pControl = new CGUISpinControlEx(*m_pOriginalSpin); - if (!pControl) return NULL; - pControl->SetWidth(width); - ((CGUISpinControlEx *)pControl)->SetText(g_localizeStrings.Get(pSetting->GetLabel())); - pSettingControl.reset(new CGUISpinExSettingControl((CGUISpinControlEx *)pControl, iControlID, pSetting)); - } - else if (pSetting->GetControlType() == SEPARATOR_CONTROL && m_pOriginalImage) - { - pControl = new CGUIImage(*m_pOriginalImage); - if (!pControl) return NULL; - pControl->SetWidth(width); - pSettingControl.reset(new CGUISeparatorSettingControl((CGUIImage *)pControl, iControlID, pSetting)); - } - else if (pSetting->GetControlType() == EDIT_CONTROL_INPUT || - pSetting->GetControlType() == EDIT_CONTROL_HIDDEN_INPUT || - pSetting->GetControlType() == EDIT_CONTROL_MD5_INPUT || - pSetting->GetControlType() == EDIT_CONTROL_NUMBER_INPUT || - pSetting->GetControlType() == EDIT_CONTROL_IP_INPUT || - pSetting->GetControlType() == EDIT_CONTROL_HIDDEN_NUMBER_VERIFY_NEW ) - { - pControl = new CGUIEditControl(*m_pOriginalEdit); - if (!pControl) return NULL; - ((CGUIEditControl *)pControl)->SetLabel(g_localizeStrings.Get(pSetting->GetLabel())); - pControl->SetWidth(width); - pSettingControl.reset(new CGUIEditSettingControl((CGUIEditControl *)pControl, iControlID, pSetting)); - } - else if (pSetting->GetControlType() != SEPARATOR_CONTROL) // button control - { - pControl = new CGUIButtonControl(*m_pOriginalButton); - if (!pControl) return NULL; - ((CGUIButtonControl *)pControl)->SetLabel(g_localizeStrings.Get(pSetting->GetLabel())); - pControl->SetWidth(width); - pSettingControl.reset(new CGUIButtonSettingControl((CGUIButtonControl *)pControl, iControlID, pSetting)); - } - if (!pControl) - { - pSettingControl.reset(); - return NULL; - } - pControl->SetID(iControlID++); - pControl->SetVisible(true); - CGUIControlGroupList *group = (CGUIControlGroupList *)GetControl(SETTINGS_GROUP_ID); - if (group) - { - pControl->AllocResources(); - group->AddControl(pControl); - } - m_vecSettings.push_back(pSettingControl); - return pControl; + return CGUIWindow::OnAction(action); } -void CGUIWindowSettingsCategory::FrameMove() +bool CGUIWindowSettingsCategory::OnBack(int actionID) { - if (m_delayedSetting && m_delayedTimer.GetElapsedMilliseconds() > 3000) - { // we send a thread message so that it's processed the following frame (some settings won't - // like being changed during Render()) - CGUIMessage message(GUI_MSG_UPDATE_ITEM, GetID(), GetID()); - g_windowManager.SendThreadMessage(message, GetID()); - m_delayedTimer.Stop(); - } - CGUIWindow::FrameMove(); + m_settings.Save(); + m_lastControlID = 0; // don't save the control as we go to a different window each time + + return CGUIWindow::OnBack(actionID); } void CGUIWindowSettingsCategory::DoProcess(unsigned int currentTime, CDirtyRegionList &dirtyregions) { // update alpha status of current button bool bAlphaFaded = false; - CGUIControl *control = GetFirstFocusableControl(CONTROL_START_BUTTONS + m_iSection); + CGUIControl *control = GetFirstFocusableControl(CONTROL_START_BUTTONS + m_iCategory); if (control && !control->HasFocus()) { if (control->GetControlType() == CGUIControl::GUICONTROL_BUTTON) @@ -2100,863 +381,487 @@ void CGUIWindowSettingsCategory::DoProcess(unsigned int currentTime, CDirtyRegio } } -void CGUIWindowSettingsCategory::Render() +void CGUIWindowSettingsCategory::OnInitWindow() { - CGUIWindow::Render(); + SetupControls(); + CGUIWindow::OnInitWindow(); } -void CGUIWindowSettingsCategory::FillInSubtitleHeights(CSetting *pSetting, CGUISpinControlEx *pControl) +void CGUIWindowSettingsCategory::OnWindowLoaded() { - CSettingInt *pSettingInt = (CSettingInt*)pSetting; - pControl->SetType(SPIN_CONTROL_TYPE_TEXT); - pControl->Clear(); - if (CUtil::IsUsingTTFSubtitles()) - { // easy - just fill as per usual - CStdString strLabel; - for (int i = pSettingInt->m_iMin; i <= pSettingInt->m_iMax; i += pSettingInt->m_iStep) - { - if (pSettingInt->m_iFormat > -1) - { - CStdString strFormat = g_localizeStrings.Get(pSettingInt->m_iFormat); - strLabel.Format(strFormat, i); - } - else - strLabel.Format(pSettingInt->m_strFormat, i); - pControl->AddLabel(strLabel, i); - } - pControl->SetValue(pSettingInt->GetData()); - } + SET_CONTROL_LABEL(CONTRL_BTN_LEVELS, 10036 + (int)CViewStateSettings::Get().GetSettingLevel()); } -void CGUIWindowSettingsCategory::FillInSubtitleFonts(CSetting *pSetting) +void CGUIWindowSettingsCategory::SetupControls(bool createSettings /* = true */) { - CSettingString *pSettingString = (CSettingString*)pSetting; - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(GetSetting(pSetting->GetSetting())->GetID()); - pControl->SetType(SPIN_CONTROL_TYPE_TEXT); - pControl->Clear(); - int iCurrentFont = 0; - int iFont = 0; - - // find TTF fonts - { - CFileItemList items; - CFileItemList items2; - CDirectory::GetDirectory("special://home/media/Fonts/", items2); - - if (CDirectory::GetDirectory("special://xbmc/media/Fonts/", items)) - { - items.Append(items2); - for (int i = 0; i < items.Size(); ++i) - { - CFileItemPtr pItem = items[i]; - - if (!pItem->m_bIsFolder) - { - - if ( !URIUtils::GetExtension(pItem->GetLabel()).Equals(".ttf") ) continue; - if (pItem->GetLabel().Equals(pSettingString->GetData(), false)) - iCurrentFont = iFont; - - pControl->AddLabel(pItem->GetLabel(), iFont++); - } + // cleanup first, if necessary + FreeControls(); - } - } + m_pOriginalSpin = (CGUISpinControlEx*)GetControl(CONTROL_DEFAULT_SPIN); + m_pOriginalRadioButton = (CGUIRadioButtonControl *)GetControl(CONTROL_DEFAULT_RADIOBUTTON); + m_pOriginalCategoryButton = (CGUIButtonControl *)GetControl(CONTROL_DEFAULT_CATEGORY_BUTTON); + m_pOriginalButton = (CGUIButtonControl *)GetControl(CONTROL_DEFAULT_BUTTON); + m_pOriginalImage = (CGUIImage *)GetControl(CONTROL_DEFAULT_SEPARATOR); + if (!m_pOriginalCategoryButton || !m_pOriginalSpin || !m_pOriginalRadioButton || !m_pOriginalButton) + return ; + m_pOriginalEdit = (CGUIEditControl *)GetControl(CONTROL_DEFAULT_EDIT); + if (!m_pOriginalEdit || m_pOriginalEdit->GetControlType() != CGUIControl::GUICONTROL_EDIT) + { + delete m_pOriginalEdit; + m_pOriginalEdit = new CGUIEditControl(*m_pOriginalButton); + newOriginalEdit = true; } - pControl->SetValue(iCurrentFont); -} - -void CGUIWindowSettingsCategory::FillInSkinFonts(CSetting *pSetting) -{ - BaseSettingControlPtr setting = GetSetting(pSetting->GetSetting()); - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(setting->GetID()); - pControl->SetType(SPIN_CONTROL_TYPE_TEXT); - pControl->Clear(); - setting->SetDelayed(); - - m_SkinFontSetIDs.clear(); - int iSkinFontSet = 0; - CStdString strPath = g_SkinInfo->GetSkinPath("Font.xml"); + m_pOriginalSpin->SetVisible(false); + m_pOriginalRadioButton->SetVisible(false); + m_pOriginalButton->SetVisible(false); + m_pOriginalCategoryButton->SetVisible(false); + m_pOriginalEdit->SetVisible(false); + if (m_pOriginalImage) m_pOriginalImage->SetVisible(false); - CXBMCTinyXML xmlDoc; - if (!xmlDoc.LoadFile(strPath)) - { - CLog::Log(LOGERROR, "Couldn't load %s", strPath.c_str()); - return ; - } + // setup our control groups... + CGUIControlGroupList *group = (CGUIControlGroupList *)GetControl(CATEGORY_GROUP_ID); + if (!group) + return; - TiXmlElement* pRootElement = xmlDoc.RootElement(); + CSettingSection *section = GetSection(m_iSection); + if (section == NULL) + return; + + // update the screen string + SET_CONTROL_LABEL(CONTROL_SETTINGS_LABEL, section->GetLabel()); - CStdString strValue = pRootElement->Value(); - if (strValue != CStdString("fonts")) - { - CLog::Log(LOGERROR, "file %s doesnt start with <fonts>", strPath.c_str()); - return ; - } + // get the categories we need + m_categories = section->GetCategories(CViewStateSettings::Get().GetSettingLevel()); - const TiXmlNode *pChild = pRootElement->FirstChild(); - strValue = pChild->Value(); - if (strValue == "fontset") + // go through the categories and create the necessary buttons + int buttonIdOffset = 0; + for (SettingCategoryList::const_iterator category = m_categories.begin(); category != m_categories.end(); category++) { - while (pChild) - { - strValue = pChild->Value(); - if (strValue == "fontset") - { - const char* idAttr = ((TiXmlElement*) pChild)->Attribute("id"); - const char* idLocAttr = ((TiXmlElement*) pChild)->Attribute("idloc"); - const char* unicodeAttr = ((TiXmlElement*) pChild)->Attribute("unicode"); + CGUIButtonControl *pButton = NULL; + if (m_pOriginalCategoryButton->GetControlType() == CGUIControl::GUICONTROL_TOGGLEBUTTON) + pButton = new CGUIToggleButtonControl(*(CGUIToggleButtonControl *)m_pOriginalCategoryButton); + else + pButton = new CGUIButtonControl(*m_pOriginalCategoryButton); + pButton->SetLabel(g_localizeStrings.Get((*category)->GetLabel())); + pButton->SetID(CONTROL_START_BUTTONS + buttonIdOffset); + pButton->SetVisible(true); + pButton->AllocResources(); - bool isUnicode=(unicodeAttr && stricmp(unicodeAttr, "true") == 0); + group->AddControl(pButton); + buttonIdOffset++; + } - bool isAllowed=true; - if (g_langInfo.ForceUnicodeFont() && !isUnicode) - isAllowed=false; + if (createSettings) + CreateSettings(); - if (idAttr != NULL && isAllowed) - { - if (idLocAttr) - { - pControl->AddLabel(g_localizeStrings.Get(atoi(idLocAttr)), iSkinFontSet); - m_SkinFontSetIDs[g_localizeStrings.Get(atoi(idLocAttr))] = idAttr; - } - else - { - pControl->AddLabel(idAttr, iSkinFontSet); - m_SkinFontSetIDs[idAttr] = idAttr; - } - if (strcmpi(idAttr, g_guiSettings.GetString("lookandfeel.font").c_str()) == 0) - pControl->SetValue(iSkinFontSet); - iSkinFontSet++; - } - } - pChild = pChild->NextSibling(); - } + // set focus correctly + m_defaultControl = CONTROL_START_BUTTONS; +} - } - else +void CGUIWindowSettingsCategory::FreeControls() +{ + // clear the category group + CGUIControlGroupList *control = (CGUIControlGroupList *)GetControl(CATEGORY_GROUP_ID); + if (control) { - // Since no fontset is defined, there is no selection of a fontset, so disable the component - pControl->AddLabel(g_localizeStrings.Get(13278), 1); - pControl->SetValue(1); - pControl->SetEnabled(false); + control->FreeResources(); + control->ClearAll(); } + m_categories.clear(); + FreeSettingsControls(); } -void CGUIWindowSettingsCategory::FillInSoundSkins(CSetting *pSetting) +void CGUIWindowSettingsCategory::FreeSettingsControls() { - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(GetSetting(pSetting->GetSetting())->GetID()); - pControl->SetType(SPIN_CONTROL_TYPE_TEXT); - pControl->Clear(); - pControl->SetShowRange(true); - - //find skins... - CFileItemList items; - CDirectory::GetDirectory("special://xbmc/sounds/", items); - CDirectory::GetDirectory("special://home/sounds/", items); - - int iCurrentSoundSkin = 0; - int iSoundSkin = 0; - vector<CStdString> vecSoundSkins; - int i; - for (i = 0; i < items.Size(); ++i) + m_currentSetting.reset(); + + // clear the settings group + CGUIControlGroupList *control = (CGUIControlGroupList *)GetControl(SETTINGS_GROUP_ID); + if (control) { - CFileItemPtr pItem = items[i]; - if (pItem->m_bIsFolder) - { - if (strcmpi(pItem->GetLabel().c_str(), ".svn") == 0) continue; - if (strcmpi(pItem->GetLabel().c_str(), "fonts") == 0) continue; - if (strcmpi(pItem->GetLabel().c_str(), "media") == 0) continue; - vecSoundSkins.push_back(pItem->GetLabel()); - } + control->FreeResources(); + control->ClearAll(); } - pControl->AddLabel(g_localizeStrings.Get(474), iSoundSkin++); // Off - pControl->AddLabel(g_localizeStrings.Get(15109), iSoundSkin++); // Skin Default - - if (g_guiSettings.GetString("lookandfeel.soundskin")=="SKINDEFAULT") - iCurrentSoundSkin=1; + for (std::vector<BaseSettingControlPtr>::iterator control = m_settingControls.begin(); control != m_settingControls.end(); control++) + (*control)->Clear(); - sort(vecSoundSkins.begin(), vecSoundSkins.end(), sortstringbyname()); - for (i = 0; i < (int) vecSoundSkins.size(); ++i) - { - CStdString strSkin = vecSoundSkins[i]; - if (strcmpi(strSkin.c_str(), g_guiSettings.GetString("lookandfeel.soundskin").c_str()) == 0) - { - iCurrentSoundSkin = iSoundSkin; - } - pControl->AddLabel(strSkin, iSoundSkin++); - } - pControl->SetValue(iCurrentSoundSkin); - return ; + m_settingControls.clear(); + m_settings.UnregisterCallback(this); } -void CGUIWindowSettingsCategory::FillInCharSets(CSetting *pSetting) +void CGUIWindowSettingsCategory::OnTimeout() { - CSettingString *pSettingString = (CSettingString*)pSetting; - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(GetSetting(pSetting->GetSetting())->GetID()); - pControl->SetType(SPIN_CONTROL_TYPE_TEXT); - pControl->Clear(); - int iCurrentCharset = 0; - vector<CStdString> vecCharsets = g_charsetConverter.getCharsetLabels(); - - CStdString strCurrentCharsetLabel="DEFAULT"; - if (pSettingString->GetData()!="DEFAULT") - strCurrentCharsetLabel = g_charsetConverter.getCharsetLabelByName(pSettingString->GetData()); + if (m_delayedSetting == NULL) + return; - sort(vecCharsets.begin(), vecCharsets.end(), sortstringbyname()); + // we send a thread message so that it's processed the following frame (some settings won't + // like being changed during Render()) + CGUIMessage message(GUI_MSG_UPDATE_ITEM, GetID(), GetID(), 1); // param1 = 1 for "reset the control if it's invalid" + g_windowManager.SendThreadMessage(message, GetID()); +} - vecCharsets.insert(vecCharsets.begin(), g_localizeStrings.Get(13278)); // "Default" +void CGUIWindowSettingsCategory::OnSettingChanged(const CSetting *setting) +{ + if (setting == NULL || setting->GetType() == SettingTypeNone || + setting->GetType() == SettingTypeAction) + return; - bool bIsAuto=(pSettingString->GetData()=="DEFAULT"); + BaseSettingControlPtr pControl = GetSettingControl(setting->GetId()); + if (pControl == NULL) + return; - for (int i = 0; i < (int) vecCharsets.size(); ++i) + const SettingDependencyMap& deps = m_settings.GetDependencies(setting->GetId()); + for (SettingDependencyMap::const_iterator depsIt = deps.begin(); depsIt != deps.end(); depsIt++) { - CStdString strCharsetLabel = vecCharsets[i]; - - if (!bIsAuto && strCharsetLabel == strCurrentCharsetLabel) - iCurrentCharset = i; - - pControl->AddLabel(strCharsetLabel, i); + for (SettingDependencies::const_iterator depIt = depsIt->second.begin(); depIt != depsIt->second.end(); depIt++) + UpdateControl(depsIt->first, *depIt); } - - pControl->SetValue(iCurrentCharset); + + // update GUI of the changed setting as the change could have been triggered by something else + pControl->Update(); } -DisplayMode CGUIWindowSettingsCategory::FillInScreens(CStdString strSetting, RESOLUTION res) +void CGUIWindowSettingsCategory::UpdateControl(const std::string &dependingSetting, const CSettingDependency &dependency) { - DisplayMode mode; - if (res == RES_WINDOW) - mode = DM_WINDOWED; - else - mode = CDisplaySettings::Get().GetResolutionInfo(res).iScreen; - - // we expect "videoscreen.screen" but it might be hidden on some platforms, - // so check that we actually have a visable control. - BaseSettingControlPtr control = GetSetting(strSetting); - if (control) - { - control->SetDelayed(); - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(control->GetID()); - pControl->Clear(); + if (dependingSetting.empty()) + return; - CStdString strScreen; - if (g_advancedSettings.m_canWindowed) - pControl->AddLabel(g_localizeStrings.Get(242), -1); + BaseSettingControlPtr pControl = GetSettingControl(dependingSetting); + if (pControl == NULL) + return; - for (int idx = 0; idx < g_Windowing.GetNumScreens(); idx++) - { - strScreen.Format(g_localizeStrings.Get(241), CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP + idx).iScreen + 1); - pControl->AddLabel(strScreen, CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP + idx).iScreen); - } - pControl->SetValue(mode); - g_guiSettings.SetInt("videoscreen.screen", mode); + CSetting *pSetting = pControl->GetSetting(); + if (pSetting == NULL) + return; + + CheckDependency(pControl, dependency); + + const SettingDependencyMap& deps = m_settings.GetDependencies(pSetting->GetId()); + for (SettingDependencyMap::const_iterator depsIt = deps.begin(); depsIt != deps.end(); depsIt++) + { + for (SettingDependencies::const_iterator depIt = depsIt->second.begin(); depIt != depsIt->second.end(); depIt++) + UpdateControl(depsIt->first, *depIt); } - return mode; + // update GUI of the changed setting as the change could have been triggered by something else + pControl->Update(); } -void CGUIWindowSettingsCategory::FillInResolutions(CStdString strSetting, DisplayMode mode, RESOLUTION res, bool UserChange) +void CGUIWindowSettingsCategory::CheckDependency(BaseSettingControlPtr pSettingControl, const CSettingDependency &dependency) { - BaseSettingControlPtr control = GetSetting(strSetting); - control->SetDelayed(); - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(control->GetID()); - - pControl->Clear(); + if (pSettingControl == NULL || pSettingControl->GetControl() == NULL) + return; - RESOLUTION spinres = RES_INVALID; // index of the resolution in the spinner that has same screen/width/height as res + CSetting *pSetting = pSettingControl->GetSetting(); + if (pSetting == NULL) + return; - if (mode == DM_WINDOWED) - { - pControl->AddLabel(g_localizeStrings.Get(242), RES_WINDOW); - spinres = RES_WINDOW; - } - else + switch (dependency.GetType()) { - vector<RESOLUTION_WHR> resolutions = g_Windowing.ScreenResolutions(mode); + case SettingDependencyTypeEnable: + pSettingControl->SetEnabled(dependency.Check()); + break; - for (unsigned int idx = 0; idx < resolutions.size(); idx++) - { - CStdString strRes; - strRes.Format("%dx%d%s", resolutions[idx].width, resolutions[idx].height, - (resolutions[idx].interlaced == D3DPRESENTFLAG_INTERLACED) ? "i" : "p"); - pControl->AddLabel(strRes, resolutions[idx].ResInfo_Index); - - RESOLUTION_INFO res1 = CDisplaySettings::Get().GetResolutionInfo(res); - RESOLUTION_INFO res2 = CDisplaySettings::Get().GetResolutionInfo(resolutions[idx].ResInfo_Index); - if ( res1.iScreen == res2.iScreen - && res1.iScreenWidth == res2.iScreenWidth - && res1.iScreenHeight == res2.iScreenHeight - && (res1.dwFlags & D3DPRESENTFLAG_INTERLACED) == (res2.dwFlags & D3DPRESENTFLAG_INTERLACED)) - spinres = (RESOLUTION) resolutions[idx].ResInfo_Index; - } - } - - if (UserChange) - { - // Auto-select the windowed or desktop resolution of the screen - int autoresolution = RES_DESKTOP; - if (mode == DM_WINDOWED) - { - autoresolution = RES_WINDOW; - } - else + case SettingDependencyTypeUpdate: { - for (int idx=0; idx < g_Windowing.GetNumScreens(); idx++) - if (CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP + idx).iScreen == mode) - { - autoresolution = RES_DESKTOP + idx; - break; - } + FillControl(pSetting, pSettingControl->GetControl()); + break; } - pControl->SetValue(autoresolution); - // Cascade - FillInRefreshRates("videoscreen.screenmode", (RESOLUTION) autoresolution, true); - } - else - { - // select the entry equivalent to the resolution passed by the res parameter - pControl->SetValue(spinres); + case SettingDependencyTypeNone: + default: + break; } } -void CGUIWindowSettingsCategory::FillInRefreshRates(CStdString strSetting, RESOLUTION res, bool UserChange) +void CGUIWindowSettingsCategory::CreateSettings() { - // The only meaningful parts of res here are iScreen, iScreenWidth, iScreenHeight + FreeSettingsControls(); - vector<REFRESHRATE> refreshrates; - if (res > RES_WINDOW) - refreshrates = g_Windowing.RefreshRates(CDisplaySettings::Get().GetResolutionInfo(res).iScreen, - CDisplaySettings::Get().GetResolutionInfo(res).iScreenWidth, - CDisplaySettings::Get().GetResolutionInfo(res).iScreenHeight, - CDisplaySettings::Get().GetResolutionInfo(res).dwFlags); + if (m_categories.size() <= 0) + return; - // The control setting doesn't exist when not in standalone mode, don't manipulate it - BaseSettingControlPtr control = GetSetting(strSetting); - CGUISpinControlEx *pControl= NULL; + if (m_iCategory < 0 || m_iCategory >= (int)m_categories.size()) + m_iCategory = 0; - // Populate - if (control) - { - control->SetDelayed(); - pControl = (CGUISpinControlEx *)GetControl(control->GetID()); - pControl->Clear(); - - if (res == RES_WINDOW) - { - pControl->AddLabel(g_localizeStrings.Get(242), RES_WINDOW); - } - else - { - for (unsigned int idx = 0; idx < refreshrates.size(); idx++) - { - CStdString strRR; - strRR.Format("%.02f", refreshrates[idx].RefreshRate); - pControl->AddLabel(strRR, refreshrates[idx].ResInfo_Index); - } - } - } + CGUIControlGroupList *group = (CGUIControlGroupList *)GetControl(SETTINGS_GROUP_ID); + if (group == NULL) + return; - // Select a rate - if (UserChange) - { - RESOLUTION newresolution; - if (res == RES_WINDOW) - newresolution = RES_WINDOW; - else - newresolution = (RESOLUTION) g_Windowing.DefaultRefreshRate(CDisplaySettings::Get().GetResolutionInfo(res).iScreen, refreshrates).ResInfo_Index; + const CSettingCategory* category = m_categories.at(m_iCategory); + if (category == NULL) + return; - if (pControl) - pControl->SetValue(newresolution); + std::set<std::string> settingMap; - OnRefreshRateChanged(newresolution); - } - else + const SettingGroupList& groups = category->GetGroups(CViewStateSettings::Get().GetSettingLevel()); + int iControlID = CONTROL_START_CONTROL; + bool first = true; + for (SettingGroupList::const_iterator groupIt = groups.begin(); groupIt != groups.end(); groupIt++) { - if (pControl) - pControl->SetValue(res); - } -} + if (*groupIt == NULL) + continue; -void CGUIWindowSettingsCategory::OnRefreshRateChanged(RESOLUTION nextRes) -{ - RESOLUTION lastRes = g_graphicsContext.GetVideoResolution(); - bool cancelled = false; + const SettingList& settings = (*groupIt)->GetSettings(CViewStateSettings::Get().GetSettingLevel()); + if (settings.size() <= 0) + continue; - CDisplaySettings::Get().SetCurrentResolution(nextRes, true); - g_graphicsContext.SetVideoResolution(nextRes); + if (first) + first = false; + else + AddSeparator(group->GetWidth(), iControlID); - if (!CGUIDialogYesNo::ShowAndGetInput(13110, 13111, 20022, 20022, -1, -1, cancelled, 10000)) - { - CDisplaySettings::Get().SetCurrentResolution(lastRes, true); - g_graphicsContext.SetVideoResolution(lastRes); + for (SettingList::const_iterator settingIt = settings.begin(); settingIt != settings.end(); settingIt++) + { + CSetting *pSetting = *settingIt; + settingMap.insert(pSetting->GetId()); + CGUIControl* pControl = AddSetting(pSetting, group->GetWidth(), iControlID); - DisplayMode mode = FillInScreens("videoscreen.screen", lastRes); - FillInResolutions("videoscreen.resolution", mode, lastRes, false); - FillInRefreshRates("videoscreen.screenmode", lastRes, false); + FillControl(pSetting, pControl); + } } + + if (settingMap.size() > 0) + m_settings.RegisterCallback(this, settingMap); + + // update our settings (turns controls on/off as appropriate) + UpdateSettings(); } -void CGUIWindowSettingsCategory::FillInLanguages(CSetting *pSetting, const std::vector<CStdString> &languages /* = std::vector<CStdString>() */, const std::vector<CStdString> &languageKeys /* = std::vector<CStdString>() */) +void CGUIWindowSettingsCategory::UpdateSettings() { - CSettingString *pSettingString = (CSettingString *)pSetting; - BaseSettingControlPtr setting = GetSetting(pSetting->GetSetting()); - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(setting->GetID()); - pControl->Clear(); - - //find languages... - CFileItemList items; - CDirectory::GetDirectory("special://xbmc/language/", items); - - int iCurrentLang = 0; - vector<CStdString> vecLanguage; - for (int i = 0; i < items.Size(); ++i) + for (vector<BaseSettingControlPtr>::iterator it = m_settingControls.begin(); it != m_settingControls.end(); it++) { - CFileItemPtr pItem = items[i]; - if (pItem->m_bIsFolder) + BaseSettingControlPtr pSettingControl = *it; + CSetting *pSetting = pSettingControl->GetSetting(); + CGUIControl *pControl = pSettingControl->GetControl(); + if (pSetting == NULL || pControl == NULL) + continue; + + // update the setting's control's state (enabled/disabled etc) + const SettingDependencies &deps = pSetting->GetDependencies(); + for (SettingDependencies::const_iterator dep = deps.begin(); dep != deps.end(); dep++) { - if (strcmpi(pItem->GetLabel().c_str(), ".svn") == 0) continue; - if (strcmpi(pItem->GetLabel().c_str(), "fonts") == 0) continue; - if (strcmpi(pItem->GetLabel().c_str(), "media") == 0) continue; - vecLanguage.push_back(pItem->GetLabel()); + // don't check "update" dependencies here as all the controls are already + // setup properly based on the existing values + if (dep->GetType() == SettingDependencyTypeUpdate) + continue; + + CheckDependency(pSettingControl, *dep); } - } - sort(vecLanguage.begin(), vecLanguage.end(), sortstringbyname()); - // Add language options passed by parameter at the beginning - if (languages.size() > 0) - vecLanguage.insert(vecLanguage.begin(), languages.begin(), languages.begin() + languages.size()); - for (unsigned int i = 0; i < vecLanguage.size(); ++i) - { - CStdString strLanguage = vecLanguage[i]; - if ((i < languageKeys.size() && strcmpi(languageKeys[i].c_str(), pSettingString->GetData().c_str()) == 0) || - strcmpi(strLanguage.c_str(), pSettingString->GetData().c_str()) == 0) - iCurrentLang = i; - pControl->AddLabel(strLanguage, i); + pSettingControl->Update(); } - - pControl->SetValue(iCurrentLang); } -void CGUIWindowSettingsCategory::FillInRegions(CSetting *pSetting) +CGUIControl* CGUIWindowSettingsCategory::AddSetting(CSetting *pSetting, float width, int &iControlID) { - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(GetSetting(pSetting->GetSetting())->GetID()); - pControl->SetType(SPIN_CONTROL_TYPE_TEXT); - pControl->Clear(); - - int iCurrentRegion=0; - CStdStringArray regions; - g_langInfo.GetRegionNames(regions); - - CStdString strCurrentRegion=g_langInfo.GetCurrentRegion(); + if (pSetting == NULL) + return NULL; - sort(regions.begin(), regions.end(), sortstringbyname()); + BaseSettingControlPtr pSettingControl; + CGUIControl *pControl = NULL; - for (int i = 0; i < (int) regions.size(); ++i) + switch (pSetting->GetControl().GetType()) { - const CStdString& strRegion = regions[i]; + case SettingControlTypeCheckmark: + { + pControl = new CGUIRadioButtonControl(*m_pOriginalRadioButton); + if (pControl == NULL) + return NULL; - if (strRegion == strCurrentRegion) - iCurrentRegion = i; + ((CGUIRadioButtonControl *)pControl)->SetLabel(g_localizeStrings.Get(pSetting->GetLabel())); + pSettingControl.reset(new CGUIControlRadioButtonSetting((CGUIRadioButtonControl *)pControl, iControlID, pSetting)); + break; + } + + case SettingControlTypeSpinner: + { + pControl = new CGUISpinControlEx(*m_pOriginalSpin); + if (pControl == NULL) + return NULL; - pControl->AddLabel(strRegion, i); + ((CGUISpinControlEx *)pControl)->SetText(g_localizeStrings.Get(pSetting->GetLabel())); + pSettingControl.reset(new CGUIControlSpinExSetting((CGUISpinControlEx *)pControl, iControlID, pSetting)); + break; + } + + case SettingControlTypeEdit: + { + pControl = new CGUIEditControl(*m_pOriginalEdit); + if (pControl == NULL) + return NULL; + + ((CGUIEditControl *)pControl)->SetLabel(g_localizeStrings.Get(pSetting->GetLabel())); + pSettingControl.reset(new CGUIControlEditSetting((CGUIEditControl *)pControl, iControlID, pSetting)); + break; + } + + case SettingControlTypeButton: + { + pControl = new CGUIButtonControl(*m_pOriginalButton); + if (pControl == NULL) + return NULL; + + ((CGUIButtonControl *)pControl)->SetLabel(g_localizeStrings.Get(pSetting->GetLabel())); + pSettingControl.reset(new CGUIControlButtonSetting((CGUIButtonControl *)pControl, iControlID, pSetting)); + break; + } + + case SettingControlTypeNone: + default: + return NULL; } - pControl->SetValue(iCurrentRegion); -} + if (pSetting->GetControl().GetDelayed()) + pSettingControl->SetDelayed(); -BaseSettingControlPtr CGUIWindowSettingsCategory::GetSetting(const CStdString &strSetting) -{ - for (unsigned int i = 0; i < m_vecSettings.size(); i++) - { - if (m_vecSettings[i]->GetSetting()->GetSetting() == strSetting) - return m_vecSettings[i]; - } - return BaseSettingControlPtr(); + return AddSettingControl(pControl, pSettingControl, width, iControlID); } -void CGUIWindowSettingsCategory::FillInSkinThemes(CSetting *pSetting) +CGUIControl* CGUIWindowSettingsCategory::AddSeparator(float width, int &iControlID) { - // There is a default theme (just Textures.xpr/xbt) - // any other *.xpr|*.xbt files are additional themes on top of this one. - CSettingString *pSettingString = (CSettingString *)pSetting; - BaseSettingControlPtr setting = GetSetting(pSetting->GetSetting()); - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(setting->GetID()); - CStdString strSettingString = g_guiSettings.GetString("lookandfeel.skintheme"); - setting->SetDelayed(); - - // Clear and add. the Default Label - pControl->Clear(); - pControl->SetShowRange(true); - pControl->AddLabel(g_localizeStrings.Get(15109), 0); // "SKINDEFAULT" The standard Textures.xpr/xbt will be used - - CStdString strDefaultTheme = pSettingString->GetData(); - - // Search for Themes in the Current skin! - vector<CStdString> vecTheme; - CUtil::GetSkinThemes(vecTheme); - - // Remove the extension from the current Theme (backward compat) - URIUtils::RemoveExtension(strSettingString); - - // Sort the Themes for GUI and list them - int iCurrentTheme = 0; - for (int i = 0; i < (int) vecTheme.size(); ++i) - { - CStdString strTheme = vecTheme[i]; - // Is the Current Theme our Used Theme! If yes set the ID! - if (strTheme.CompareNoCase(strSettingString) == 0 ) - iCurrentTheme = i + 1; // 1: #of Predefined Theme [Label] - pControl->AddLabel(strTheme, i + 1); - } - // Set the Choosen Theme - pControl->SetValue(iCurrentTheme); + if (m_pOriginalImage == NULL) + return NULL; + + CGUIControl *pControl = new CGUIImage(*m_pOriginalImage); + if (pControl == NULL) + return NULL; + + return AddSettingControl(pControl, BaseSettingControlPtr(new CGUIControlSeparatorSetting((CGUIImage *)pControl, iControlID)), width, iControlID); } -void CGUIWindowSettingsCategory::FillInSkinColors(CSetting *pSetting) +CGUIControl* CGUIWindowSettingsCategory::AddSettingControl(CGUIControl *pControl, BaseSettingControlPtr pSettingControl, float width, int &iControlID) { - // There is a default theme (just defaults.xml) - // any other *.xml files are additional color themes on top of this one. - BaseSettingControlPtr setting = GetSetting(pSetting->GetSetting()); - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(setting->GetID()); - CStdString strSettingString = g_guiSettings.GetString("lookandfeel.skincolors"); - setting->SetDelayed(); - - // Clear and add. the Default Label - pControl->Clear(); - pControl->SetShowRange(true); - pControl->AddLabel(g_localizeStrings.Get(15109), 0); // "SKINDEFAULT"! The standard defaults.xml will be used! - - // Search for colors in the Current skin! - vector<CStdString> vecColors; - - CStdString strPath; - URIUtils::AddFileToFolder(g_SkinInfo->Path(),"colors",strPath); - - CFileItemList items; - CDirectory::GetDirectory(CSpecialProtocol::TranslatePathConvertCase(strPath), items, ".xml"); - // Search for Themes in the Current skin! - for (int i = 0; i < items.Size(); ++i) + if (pControl == NULL) { - CFileItemPtr pItem = items[i]; - if (!pItem->m_bIsFolder && pItem->GetLabel().CompareNoCase("defaults.xml") != 0) - { // not the default one - CStdString strLabel = pItem->GetLabel(); - vecColors.push_back(strLabel.Mid(0, strLabel.size() - 4)); - } + pSettingControl.reset(); + return NULL; } - sort(vecColors.begin(), vecColors.end(), sortstringbyname()); - - // Remove the .xml extension from the Themes - if (URIUtils::GetExtension(strSettingString) == ".xml") - URIUtils::RemoveExtension(strSettingString); - - int iCurrentColor = 0; - for (int i = 0; i < (int) vecColors.size(); ++i) + + pControl->SetID(iControlID++); + pControl->SetVisible(true); + pControl->SetWidth(width); + + CGUIControlGroupList *group = (CGUIControlGroupList *)GetControl(SETTINGS_GROUP_ID); + if (group != NULL) { - CStdString strColor = vecColors[i]; - // Is the Current Theme our Used Theme! If yes set the ID! - if (strColor.CompareNoCase(strSettingString) == 0 ) - iCurrentColor = i + 1; // 1: #of Predefined Theme [Label] - pControl->AddLabel(strColor, i + 1); + pControl->AllocResources(); + group->AddControl(pControl); } - // Set the Choosen Theme - pControl->SetValue(iCurrentColor); + m_settingControls.push_back(pSettingControl); + + return pControl; } -void CGUIWindowSettingsCategory::FillInStartupWindow(CSetting *pSetting) +void CGUIWindowSettingsCategory::OnClick(BaseSettingControlPtr pSettingControl) { - CSettingInt *pSettingInt = (CSettingInt*)pSetting; - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(GetSetting(pSetting->GetSetting())->GetID()); - pControl->Clear(); - - const vector<CSkinInfo::CStartupWindow> &startupWindows = g_SkinInfo->GetStartupWindows(); - - // TODO: How should we localize this? - // In the long run there is no way to do it really without the skin having some - // translation information built in to it, which isn't really feasible. + std::string strSetting = pSettingControl->GetSetting()->GetId(); - // Alternatively we could lookup the strings in the english strings file to get - // their id and then get the string from that - - // easier would be to have the skinner use the "name" as the label number. - - // eg <window id="0">513</window> - - bool currentSettingFound(false); - for (vector<CSkinInfo::CStartupWindow>::const_iterator it = startupWindows.begin(); it != startupWindows.end(); it++) + // we need to first set the delayed setting and then execute OnClick() + // because OnClick() triggers OnSettingChanged() and there we need to + // know if the changed setting is delayed or not + if (pSettingControl->IsDelayed()) { - CStdString windowName((*it).m_name); - if (StringUtils::IsNaturalNumber(windowName)) - windowName = g_localizeStrings.Get(atoi(windowName.c_str())); - int windowID((*it).m_id); - pControl->AddLabel(windowName, windowID); - if (pSettingInt->GetData() == windowID) - currentSettingFound = true; - } + m_delayedSetting = pSettingControl; + if (m_delayedTimer.IsRunning()) + m_delayedTimer.Restart(); + else + m_delayedTimer.Start(SETTING_DELAY); - // ok, now check whether our current option is one of these - // and set it's value - if (!currentSettingFound) - { // nope - set it to the "default" option - the first one - pSettingInt->SetData(startupWindows[0].m_id); + return; } - pControl->SetValue(pSettingInt->GetData()); -} - -void CGUIWindowSettingsCategory::OnInitWindow() -{ - m_strOldTrackFormat = g_guiSettings.GetString("musicfiles.trackformat"); - m_strOldTrackFormatRight = g_guiSettings.GetString("musicfiles.trackformatright"); - SetupControls(); - CGUIWindow::OnInitWindow(); -} -void CGUIWindowSettingsCategory::FillInViewModes(CSetting *pSetting, int windowID) -{ - CSettingInt *pSettingInt = (CSettingInt*)pSetting; - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(GetSetting(pSetting->GetSetting())->GetID()); - pControl->AddLabel("Auto", DEFAULT_VIEW_AUTO); - bool found(false); - int foundType = 0; - CGUIWindow *window = g_windowManager.GetWindow(windowID); - if (window) - { - window->Initialize(); - for (int i = 50; i < 60; i++) - { - IGUIContainer *control = (IGUIContainer *)window->GetControl(i); - if (control) - { - int type = (control->GetType() << 16) | i; - pControl->AddLabel(control->GetLabel(), type); - if (type == pSettingInt->GetData()) - found = true; - else if ((type >> 16) == (pSettingInt->GetData() >> 16)) - foundType = type; - } - } - window->ClearAll(); - } - if (!found) - pSettingInt->SetData(foundType ? foundType : (DEFAULT_VIEW_AUTO)); - pControl->SetValue(pSettingInt->GetData()); + // if changing the setting fails + // we need to restore the proper state + if (!pSettingControl->OnClick()) + pSettingControl->Update(); } -void CGUIWindowSettingsCategory::FillInSortMethods(CSetting *pSetting, int windowID) +CSettingSection* CGUIWindowSettingsCategory::GetSection(int windowID) const { - CSettingInt *pSettingInt = (CSettingInt*)pSetting; - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(GetSetting(pSetting->GetSetting())->GetID()); - CFileItemList items("C:"); - CGUIViewState *state = CGUIViewState::GetViewState(windowID, items); - if (state) + for (size_t index = 0; index < SettingGroupSize; index++) { - bool found(false); - vector< pair<int,int> > sortMethods; - state->GetSortMethods(sortMethods); - for (unsigned int i = 0; i < sortMethods.size(); i++) - { - pControl->AddLabel(g_localizeStrings.Get(sortMethods[i].second), sortMethods[i].first); - if (sortMethods[i].first == pSettingInt->GetData()) - found = true; - } - if (!found && sortMethods.size()) - pSettingInt->SetData(sortMethods[0].first); + if (s_settingGroupMap[index].id == windowID) + return m_settings.GetSection(s_settingGroupMap[index].name); } - pControl->SetValue(pSettingInt->GetData()); - delete state; + + return NULL; } -void CGUIWindowSettingsCategory::FillInNetworkInterfaces(CSetting *pSetting, float groupWidth, int &iControlID) +BaseSettingControlPtr CGUIWindowSettingsCategory::GetSettingControl(const std::string &strSetting) { - CGUISpinControlEx *pControl = (CGUISpinControlEx *)AddSetting(pSetting, groupWidth, iControlID); - pControl->Clear(); - - // query list of interfaces - vector<CStdString> vecInterfaces; - std::vector<CNetworkInterface*>& ifaces = g_application.getNetwork().GetInterfaceList(); - std::vector<CNetworkInterface*>::const_iterator iter = ifaces.begin(); - while (iter != ifaces.end()) + for (vector<BaseSettingControlPtr>::iterator control = m_settingControls.begin(); control != m_settingControls.end(); control++) { - CNetworkInterface* iface = *iter; - vecInterfaces.push_back(iface->GetName()); - ++iter; + if ((*control)->GetSetting() != NULL && (*control)->GetSetting()->GetId() == strSetting) + return *control; } - sort(vecInterfaces.begin(), vecInterfaces.end(), sortstringbyname()); - int iInterface = 0; - for (unsigned int i = 0; i < vecInterfaces.size(); ++i) - pControl->AddLabel(vecInterfaces[i], iInterface++); + return BaseSettingControlPtr(); } -void CGUIWindowSettingsCategory::FillInEpgGuideView(CSetting *pSetting) +BaseSettingControlPtr CGUIWindowSettingsCategory::GetSettingControl(int controlId) { - CSettingInt *pSettingInt = (CSettingInt*)pSetting; - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(GetSetting(pSetting->GetSetting())->GetID()); - pControl->Clear(); + if (controlId < CONTROL_START_CONTROL || controlId >= (int)(CONTROL_START_CONTROL + m_settingControls.size())) + return BaseSettingControlPtr(); - pControl->AddLabel(g_localizeStrings.Get(19029), GUIDE_VIEW_CHANNEL); - pControl->AddLabel(g_localizeStrings.Get(19030), GUIDE_VIEW_NOW); - pControl->AddLabel(g_localizeStrings.Get(19031), GUIDE_VIEW_NEXT); - pControl->AddLabel(g_localizeStrings.Get(19032), GUIDE_VIEW_TIMELINE); - - pControl->SetValue(pSettingInt->GetData()); + return m_settingControls[controlId - CONTROL_START_CONTROL]; } -void CGUIWindowSettingsCategory::FillInPvrStartLastChannel(CSetting *pSetting) +void CGUIWindowSettingsCategory::FillControl(CSetting *pSetting, CGUIControl *pSettingControl) { - CSettingInt *pSettingInt = (CSettingInt*)pSetting; - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(GetSetting(pSetting->GetSetting())->GetID()); - pControl->Clear(); + void *filler = CSettings::Get().GetSettingOptionsFiller(pSetting); + if (filler == NULL) + return; - pControl->AddLabel(g_localizeStrings.Get(106), START_LAST_CHANNEL_OFF); - pControl->AddLabel(g_localizeStrings.Get(19190), START_LAST_CHANNEL_MIN); - pControl->AddLabel(g_localizeStrings.Get(107), START_LAST_CHANNEL_ON); + if (pSetting->GetType() == SettingTypeInteger) + { + CSettingInt *pSettingInt = (CSettingInt*)pSetting; - pControl->SetValue(pSettingInt->GetData()); -} + // get the list of options and the current option + IntegerSettingOptions options; + int currentOption = pSettingInt->GetValue(); + ((IntegerSettingOptionsFiller)filler)(pSetting, options, currentOption); -void CGUIWindowSettingsCategory::FillInAudioDevices(CSetting* pSetting, bool Passthrough) -{ - CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(GetSetting(pSetting->GetSetting())->GetID()); - pControl->Clear(); + // clear the spinner control + CGUISpinControlEx *pSpinControl = (CGUISpinControlEx *)pSettingControl; + pSpinControl->Clear(); - CStdString currentDevice = Passthrough ? g_guiSettings.GetString("audiooutput.passthroughdevice") : g_guiSettings.GetString("audiooutput.audiodevice"); + // fill the spinner control + for (IntegerSettingOptions::const_iterator option = options.begin(); option != options.end(); option++) + pSpinControl->AddLabel(option->first, option->second); - if (Passthrough) - { - m_DigitalAudioSinkMap.clear(); - m_DigitalAudioSinkMap["Error - no devices found"] = "null:"; - } - else - { - m_AnalogAudioSinkMap.clear(); - m_AnalogAudioSinkMap["Error - no devices found"] = "null:"; - } + // set the current option + pSpinControl->SetValue(currentOption); - int selectedValue = -1; - AEDeviceList sinkList; - CAEFactory::EnumerateOutputDevices(sinkList, Passthrough); -#if !defined(TARGET_DARWIN) - if (sinkList.size()==0) - { - pControl->AddLabel("Error - no devices found", 0); - selectedValue = 0; + // check if the current setting has changed + if (currentOption != pSettingInt->GetValue()) + pSettingInt->SetValue(currentOption); } - else + else if (pSetting->GetType() == SettingTypeString) { -#endif - AEDeviceList::const_iterator iter = sinkList.begin(); - for (int i=0; iter != sinkList.end(); iter++) - { - CStdString label = (*iter).first; - CStdString sink = (*iter).second; - pControl->AddLabel(label.c_str(), i); + CSettingString *pSettingString = (CSettingString*)pSetting; - if (currentDevice.Equals(sink)) - selectedValue = i; + // get the list of options and the current option + StringSettingOptions options; + std::string currentOption = pSettingString->GetValue(); + ((StringSettingOptionsFiller)filler)(pSetting, options, currentOption); - if (Passthrough) - m_DigitalAudioSinkMap[label] = sink; - else - m_AnalogAudioSinkMap[label] = sink; - - i++; - } + // clear the spinner control + CGUISpinControlEx *pSpinControl = (CGUISpinControlEx *)pSettingControl; + pSpinControl->Clear(); -#if !defined(TARGET_DARWIN) - } -#endif + // fill the spinner control + for (StringSettingOptions::const_iterator option = options.begin(); option != options.end(); option++) + pSpinControl->AddLabel(option->first, option->second); - if (selectedValue < 0) - { - CLog::Log(LOGWARNING, "Failed to find previously selected audio sink"); - pControl->SetValue(0); - if (!Passthrough) - ((CSettingString*)pSetting)->SetData(m_AnalogAudioSinkMap[pControl->GetCurrentLabel()]); - else - ((CSettingString*)pSetting)->SetData(m_DigitalAudioSinkMap[pControl->GetCurrentLabel()]); - } - else - pControl->SetValue(selectedValue); -} + // set the current option + pSpinControl->SetStringValue(currentOption); -void CGUIWindowSettingsCategory::NetworkInterfaceChanged(void) -{ -#if 0 - NetworkAssignment iAssignment; - CStdString sIPAddress; - CStdString sNetworkMask; - CStdString sDefaultGateway; - CStdString sWirelessNetwork; - CStdString sWirelessKey; - EncMode iWirelessEnc; - bool bIsWireless; - CStdString ifaceName; - - // Get network information - CGUISpinControlEx *ifaceControl = (CGUISpinControlEx *)GetControl(GetSetting("network.interface")->GetID()); - ifaceName = ifaceControl->GetLabel(); - CNetworkInterface* iface = g_application.getNetwork().GetInterfaceByName(ifaceName); - iface->GetSettings(iAssignment, sIPAddress, sNetworkMask, sDefaultGateway, sWirelessNetwork, sWirelessKey, iWirelessEnc); - bIsWireless = iface->IsWireless(); - - CStdString dns; - std::vector<CStdString> dnss = g_application.getNetwork().GetNameServers(); - if (dnss.size() >= 1) - dns = dnss[0]; - - // Update controls with information - CGUISpinControlEx* pControl1 = (CGUISpinControlEx *)GetControl(GetSetting("network.assignment")->GetID()); - if (pControl1) pControl1->SetValue(iAssignment); - GetSetting("network.dns")->GetSetting()->FromString(dns); - if (iAssignment == NETWORK_STATIC || iAssignment == NETWORK_DISABLED) - { - GetSetting("network.ipaddress")->GetSetting()->FromString(sIPAddress); - GetSetting("network.subnet")->GetSetting()->FromString(sNetworkMask); - GetSetting("network.gateway")->GetSetting()->FromString(sDefaultGateway); - } - else - { - GetSetting("network.ipaddress")->GetSetting()->FromString(iface->GetCurrentIPAddress()); - GetSetting("network.subnet")->GetSetting()->FromString(iface->GetCurrentNetmask()); - GetSetting("network.gateway")->GetSetting()->FromString(iface->GetCurrentDefaultGateway()); - } - - pControl1 = (CGUISpinControlEx *)GetControl(GetSetting("network.enc")->GetID()); - if (pControl1) pControl1->SetValue(iWirelessEnc); - - if (bIsWireless) - { - GetSetting("network.essid")->GetSetting()->FromString(sWirelessNetwork); - GetSetting("network.key")->GetSetting()->FromString(sWirelessKey); - } - else - { - GetSetting("network.essid")->GetSetting()->FromString(""); - GetSetting("network.key")->GetSetting()->FromString(""); - } -#endif -} - -void CGUIWindowSettingsCategory::ValidatePortNumber(BaseSettingControlPtr pSettingControl, const CStdString& userPort, const CStdString& privPort, bool listening/*=true*/) -{ - CSettingString *pSetting = (CSettingString *)pSettingControl->GetSetting(); - // check that it's a valid port - int port = atoi(pSetting->GetData().c_str()); -#ifdef _LINUX - if (listening && !CUtil::CanBindPrivileged() && (port < 1024 || port > 65535)) - { - CGUIDialogOK::ShowAndGetInput(257, 850, 852, -1); - pSetting->SetData(userPort.c_str()); - } - else -#endif - if (port <= 0 || port > 65535) - { - CGUIDialogOK::ShowAndGetInput(257, 850, 851, -1); - pSetting->SetData(privPort.c_str()); + // check if the current setting has changed + if (currentOption.compare(pSettingString->GetValue()) != 0) + pSettingString->SetValue(currentOption); } } diff --git a/xbmc/settings/windows/GUIWindowSettingsCategory.h b/xbmc/settings/windows/GUIWindowSettingsCategory.h index 74b222ca73..434a8068ce 100644 --- a/xbmc/settings/windows/GUIWindowSettingsCategory.h +++ b/xbmc/settings/windows/GUIWindowSettingsCategory.h @@ -1,7 +1,7 @@ #pragma once /* - * Copyright (C) 2005-2013 Team XBMC + * Copyright (C) 2005-2012 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify @@ -20,92 +20,89 @@ * */ -#include "guilib/GUIWindow.h" -#include "settings/GUISettings.h" -#include "settings/windows/GUISettingControls.h" -#include "utils/Stopwatch.h" - -typedef boost::shared_ptr<CGUIBaseSettingControl> BaseSettingControlPtr; +#include <vector> -class CGUIWindowSettingsCategory : - public CGUIWindow +#include "GUIControlSettings.h" +#include "guilib/GUIWindow.h" +#include "settings/SettingDependency.h" +#include "settings/SettingSection.h" +#include "settings/Settings.h" +#include "settings/SettingsManager.h" +#include "threads/Timer.h" + +typedef boost::shared_ptr<CGUIControlBaseSetting> BaseSettingControlPtr; + +class CGUIWindowSettingsCategory + : public CGUIWindow, + protected ITimerCallback, + protected ISettingCallback { public: CGUIWindowSettingsCategory(void); virtual ~CGUIWindowSettingsCategory(void); virtual bool OnMessage(CGUIMessage &message); + virtual bool OnAction(const CAction &action); virtual bool OnBack(int actionID); - virtual void FrameMove(); - virtual void Render(); virtual void DoProcess(unsigned int currentTime, CDirtyRegionList &dirtyregions); - virtual int GetID() const { return CGUIWindow::GetID() + m_iScreen; }; + virtual int GetID() const { return CGUIWindow::GetID() + m_iSection; }; protected: virtual void OnInitWindow(); + virtual void OnWindowLoaded(); + + virtual void SetupControls(bool createSettings = true); + virtual void FreeControls(); + void FreeSettingsControls(); - void CheckNetworkSettings(); - void FillInSubtitleHeights(CSetting *pSetting, CGUISpinControlEx *pControl); - void FillInSubtitleFonts(CSetting *pSetting); - void FillInCharSets(CSetting *pSetting); - void FillInSkinFonts(CSetting *pSetting); - void FillInSoundSkins(CSetting *pSetting); - void FillInLanguages(CSetting *pSetting, const std::vector<CStdString> &languages = std::vector<CStdString>(), const std::vector<CStdString> &languageKeys = std::vector<CStdString>()); - DisplayMode FillInScreens(CStdString strSetting, RESOLUTION res); - void FillInResolutions(CStdString strSetting, DisplayMode mode, RESOLUTION res, bool UserChange); - void FillInRefreshRates(CStdString strSetting, RESOLUTION res, bool UserChange); - void OnRefreshRateChanged(RESOLUTION resolution); - void FillInRegions(CSetting *pSetting); - void FillInStartupWindow(CSetting *pSetting); - void FillInViewModes(CSetting *pSetting, int windowID); - void FillInSortMethods(CSetting *pSetting, int windowID); - void FillInEpgGuideView(CSetting *pSetting); - void FillInPvrStartLastChannel(CSetting *pSetting); - - void FillInSkinThemes(CSetting *pSetting); - void FillInSkinColors(CSetting *pSetting); - - void FillInNetworkInterfaces(CSetting *pSetting, float groupWidth, int &iControlID); - void NetworkInterfaceChanged(void); - - void FillInAudioDevices(CSetting* pSetting, bool Passthrough = false); - - virtual void SetupControls(); - CGUIControl* AddIntBasedSpinControl(CSetting *pSetting, float groupWidth, int &iControlID); + virtual void OnTimeout(); + virtual void OnSettingChanged(const CSetting *setting); + + void UpdateControl(const std::string &dependingSetting, const CSettingDependency &dependency); + void CheckDependency(BaseSettingControlPtr pSettingControl, const CSettingDependency &dependency); + void CreateSettings(); void UpdateSettings(); - void CheckForUpdates(); - void FreeSettingsControls(); - virtual void FreeControls(); - virtual void OnClick(BaseSettingControlPtr pSettingControl); - virtual void OnSettingChanged(BaseSettingControlPtr pSettingControl); CGUIControl* AddSetting(CSetting *pSetting, float width, int &iControlID); - BaseSettingControlPtr GetSetting(const CStdString &strSetting); + CGUIControl* AddSeparator(float width, int &iControlID); + CGUIControl* AddSettingControl(CGUIControl *pControl, BaseSettingControlPtr pSettingControl, float width, int &iControlID); + + /*! + \brief A setting control has been interacted with by the user + + This method is called when the user manually interacts (clicks, + edits) with a setting control. It contains handling for both + delayed and undelayed settings and either starts the delay timer + or triggers the setting change which, on success, results in a + callback to OnSettingChanged(). + + \param pSettingControl Setting control that has been interacted with + */ + virtual void OnClick(BaseSettingControlPtr pSettingControl); - void ValidatePortNumber(BaseSettingControlPtr pSettingControl, const CStdString& userPort, const CStdString& privPort, bool listening=true); + CSettingSection* GetSection(int windowID) const; + BaseSettingControlPtr GetSettingControl(const std::string &setting); + BaseSettingControlPtr GetSettingControl(int controlId); - std::vector<BaseSettingControlPtr> m_vecSettings; + void FillControl(CSetting *pSetting, CGUIControl *pSettingControl); + + CSettings& m_settings; + SettingCategoryList m_categories; + std::vector<BaseSettingControlPtr> m_settingControls; + + int m_iCategory; int m_iSection; - int m_iScreen; - vecSettingsCategory m_vecSections; + CGUISpinControlEx *m_pOriginalSpin; CGUIRadioButtonControl *m_pOriginalRadioButton; CGUIButtonControl *m_pOriginalCategoryButton; CGUIButtonControl *m_pOriginalButton; CGUIEditControl *m_pOriginalEdit; CGUIImage *m_pOriginalImage; - - CStdString m_strErrorMessage; - - CStdString m_strOldTrackFormat; - CStdString m_strOldTrackFormatRight; - - std::map<CStdString, CStdString> m_AnalogAudioSinkMap; - std::map<CStdString, CStdString> m_DigitalAudioSinkMap; - std::map<CStdString, CStdString> m_SkinFontSetIDs; + bool newOriginalEdit; + + BaseSettingControlPtr m_currentSetting; ///< Current setting control + BaseSettingControlPtr m_delayedSetting; ///< Current delayed setting \sa CBaseSettingControl::SetDelayed() + CTimer m_delayedTimer; ///< Delayed setting timer bool m_returningFromSkinLoad; // true if we are returning from loading the skin - - boost::shared_ptr<CGUIBaseSettingControl> m_delayedSetting; ///< Current delayed setting \sa CGUIBaseSettingControl::SetDelayed() - CStopWatch m_delayedTimer; ///< Delayed setting timer }; - diff --git a/xbmc/settings/windows/GUIWindowSettingsScreenCalibration.cpp b/xbmc/settings/windows/GUIWindowSettingsScreenCalibration.cpp index e286223feb..0b4264dedf 100644 --- a/xbmc/settings/windows/GUIWindowSettingsScreenCalibration.cpp +++ b/xbmc/settings/windows/GUIWindowSettingsScreenCalibration.cpp @@ -28,7 +28,6 @@ #include "Application.h" #include "settings/DisplaySettings.h" #include "settings/Settings.h" -#include "settings/GUISettings.h" #include "guilib/GUIWindowManager.h" #include "dialogs/GUIDialogYesNo.h" #include "guilib/Key.h" @@ -119,7 +118,7 @@ bool CGUIWindowSettingsScreenCalibration::OnMessage(CGUIMessage& message) case GUI_MSG_WINDOW_DEINIT: { CDisplaySettings::Get().UpdateCalibrations(); - g_settings.Save(); + CSettings::Get().Save(); g_graphicsContext.SetCalibrating(false); g_windowManager.ShowOverlay(OVERLAY_STATE_SHOWN); // reset our screen resolution to what it was initially diff --git a/xbmc/settings/windows/Makefile b/xbmc/settings/windows/Makefile index 253a73b0b4..8f9761601e 100644 --- a/xbmc/settings/windows/Makefile +++ b/xbmc/settings/windows/Makefile @@ -1,4 +1,4 @@ -SRCS=GUISettingControls.cpp \ +SRCS=GUIControlSettings.cpp \ GUIWindowSettings.cpp \ GUIWindowSettingsCategory.cpp \ GUIWindowSettingsScreenCalibration.cpp \ diff --git a/xbmc/storage/MediaManager.cpp b/xbmc/storage/MediaManager.cpp index 3a2dcb4eae..c89014d39d 100644 --- a/xbmc/storage/MediaManager.cpp +++ b/xbmc/storage/MediaManager.cpp @@ -38,13 +38,13 @@ #include "Autorun.h" #include "GUIUserMessages.h" #include "settings/MediaSourceSettings.h" +#include "settings/Settings.h" #include "utils/XBMCTinyXML.h" #include "threads/SingleLock.h" #include "utils/log.h" #include "dialogs/GUIDialogKaiToast.h" #include "utils/JobManager.h" #include "AutorunMediaJob.h" -#include "settings/GUISettings.h" #include "FileItem.h" #include "filesystem/File.h" @@ -722,13 +722,15 @@ std::vector<CStdString> CMediaManager::GetDiskUsage() void CMediaManager::OnStorageAdded(const CStdString &label, const CStdString &path) { - if (g_guiSettings.GetInt("audiocds.autoaction") != AUTOCD_NONE || g_guiSettings.GetBool("dvds.autorun")) - if (g_guiSettings.GetInt("audiocds.autoaction") == AUTOCD_RIP) +#ifdef HAS_DVD_DRIVE + if (CSettings::Get().GetInt("audiocds.autoaction") != AUTOCD_NONE || CSettings::Get().GetBool("dvds.autorun")) + if (CSettings::Get().GetInt("audiocds.autoaction") == AUTOCD_RIP) CJobManager::GetInstance().AddJob(new CAutorunMediaJob(label, path), this, CJob::PRIORITY_LOW); else CJobManager::GetInstance().AddJob(new CAutorunMediaJob(label, path), this, CJob::PRIORITY_HIGH); else CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(13021), label, TOAST_DISPLAY_TIME, false); +#endif } void CMediaManager::OnStorageSafelyRemoved(const CStdString &label) diff --git a/xbmc/storage/linux/UDisksProvider.cpp b/xbmc/storage/linux/UDisksProvider.cpp index 7b91db847f..e581e0011e 100644 --- a/xbmc/storage/linux/UDisksProvider.cpp +++ b/xbmc/storage/linux/UDisksProvider.cpp @@ -303,8 +303,7 @@ bool CUDisksProvider::HasUDisks() void CUDisksProvider::DeviceAdded(const char *object, IStorageEventsCallback *callback) { - if (g_advancedSettings.m_logLevel >= LOG_LEVEL_DEBUG_SAMBA) - CLog::Log(LOGDEBUG, "UDisks: DeviceAdded (%s)", object); + CLog::Log(LOGDEBUG|LOGDBUS, "UDisks: DeviceAdded (%s)", object); if (m_AvailableDevices[object]) { @@ -319,8 +318,7 @@ void CUDisksProvider::DeviceAdded(const char *object, IStorageEventsCallback *ca if (g_advancedSettings.m_handleMounting) device->Mount(); - if (g_advancedSettings.m_logLevel >= LOG_LEVEL_DEBUG_SAMBA) - CLog::Log(LOGDEBUG, "UDisks: DeviceAdded - %s", device->toString().c_str()); + CLog::Log(LOGDEBUG|LOGDBUS, "UDisks: DeviceAdded - %s", device->toString().c_str()); if (device->m_isMounted && device->IsApproved()) { @@ -332,8 +330,7 @@ void CUDisksProvider::DeviceAdded(const char *object, IStorageEventsCallback *ca void CUDisksProvider::DeviceRemoved(const char *object, IStorageEventsCallback *callback) { - if (g_advancedSettings.m_logLevel >= LOG_LEVEL_DEBUG_SAMBA) - CLog::Log(LOGDEBUG, "UDisks: DeviceRemoved (%s)", object); + CLog::Log(LOGDEBUG|LOGDBUS, "UDisks: DeviceRemoved (%s)", object); CUDiskDevice *device = m_AvailableDevices[object]; if (device) @@ -348,8 +345,7 @@ void CUDisksProvider::DeviceRemoved(const char *object, IStorageEventsCallback * void CUDisksProvider::DeviceChanged(const char *object, IStorageEventsCallback *callback) { - if (g_advancedSettings.m_logLevel >= LOG_LEVEL_DEBUG_SAMBA) - CLog::Log(LOGDEBUG, "UDisks: DeviceChanged (%s)", object); + CLog::Log(LOGDEBUG|LOGDBUS, "UDisks: DeviceChanged (%s)", object); CUDiskDevice *device = m_AvailableDevices[object]; if (device == NULL) @@ -371,8 +367,7 @@ void CUDisksProvider::DeviceChanged(const char *object, IStorageEventsCallback * else if (mounted && !device->m_isMounted && callback) callback->OnStorageSafelyRemoved(device->m_Label); - if (g_advancedSettings.m_logLevel >= LOG_LEVEL_DEBUG_SAMBA) - CLog::Log(LOGDEBUG, "UDisks: DeviceChanged - %s", device->toString().c_str()); + CLog::Log(LOGDEBUG|LOGDBUS, "UDisks: DeviceChanged - %s", device->toString().c_str()); } } diff --git a/xbmc/system.h b/xbmc/system.h index 8f099d314c..1bd0c98f51 100644 --- a/xbmc/system.h +++ b/xbmc/system.h @@ -25,6 +25,9 @@ #define DECLARE_UNUSED(a,b) a __attribute__((unused)) b; #endif +#define PRE_SKIN_VERSION_9_10_COMPATIBILITY 1 +#define PRE_SKIN_VERSION_11_COMPATIBILITY 1 + /***************** * All platforms *****************/ @@ -74,7 +77,7 @@ #define HAS_AIRPLAY #endif -#ifdef HAVE_LIBSHAIRPORT +#if defined(HAVE_LIBSHAIRPORT) || defined(HAVE_LIBSHAIRPLAY) #define HAS_AIRTUNES #endif @@ -121,6 +124,7 @@ #define HAS_ZEROCONF #define HAS_AIRPLAY #define HAS_AIRTUNES +#define HAVE_LIBSHAIRPLAY #define HAVE_LIBCEC #define HAVE_LIBMP3LAME #define HAVE_LIBVORBISENC @@ -269,3 +273,11 @@ #define GET_G(color) ((color >> 8) & 0xFF) #define GET_B(color) ((color >> 0) & 0xFF) +/**************** + * default skin + ****************/ +#if defined(HAS_SKIN_TOUCHED) && defined(TARGET_DARWIN_IOS) && !defined(TARGET_DARWIN_IOS_ATV2) +#define DEFAULT_SKIN "skin.touched" +#else +#define DEFAULT_SKIN "skin.confluence" +#endif diff --git a/xbmc/test/TestBasicEnvironment.cpp b/xbmc/test/TestBasicEnvironment.cpp index 521b912739..80085b8fc1 100644 --- a/xbmc/test/TestBasicEnvironment.cpp +++ b/xbmc/test/TestBasicEnvironment.cpp @@ -25,7 +25,7 @@ #include "filesystem/SpecialProtocol.h" #include "powermanagement/PowerManager.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "Util.h" #include <cstdio> @@ -59,7 +59,7 @@ void TestBasicEnvironment::SetUp() * that the initialization of these components won't be needed. */ g_powerManager.Initialize(); - g_guiSettings.Initialize(); + CSettings::Get().Initialize(); /* Create a temporary directory and set it to be used throughout the * test suite run. diff --git a/xbmc/threads/platform/win/Win32Exception.cpp b/xbmc/threads/platform/win/Win32Exception.cpp index a709244c9f..ca2b1c5ce4 100644 --- a/xbmc/threads/platform/win/Win32Exception.cpp +++ b/xbmc/threads/platform/win/Win32Exception.cpp @@ -24,6 +24,7 @@ #include "Util.h" #include "WIN32Util.h" #include "utils/StringUtils.h" +#include "utils/CharsetConverter.h" #define LOG if(logger) logger->Log @@ -115,6 +116,7 @@ bool win32_exception::write_minidump(EXCEPTION_POINTERS* pEp) // Create the dump file where the xbmc.exe resides bool returncode = false; CStdString dumpFileName; + CStdStringW dumpFileNameW; SYSTEMTIME stLocalTime; GetLocalTime(&stLocalTime); @@ -125,7 +127,8 @@ bool win32_exception::write_minidump(EXCEPTION_POINTERS* pEp) dumpFileName.Format("%s\\%s", CWIN32Util::GetProfilePath().c_str(), CUtil::MakeLegalFileName(dumpFileName)); - HANDLE hDumpFile = CreateFile(dumpFileName.c_str(), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0); + g_charsetConverter.utf8ToW(dumpFileName, dumpFileNameW, false); + HANDLE hDumpFile = CreateFileW(dumpFileNameW.c_str(), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0); if (hDumpFile == INVALID_HANDLE_VALUE) { @@ -186,6 +189,7 @@ bool win32_exception::write_stacktrace(EXCEPTION_POINTERS* pEp) #define STACKWALK_MAX_NAMELEN 1024 std::string dumpFileName, strOutput; + CStdStringW dumpFileNameW; CHAR cTemp[STACKWALK_MAX_NAMELEN]; DWORD dwBytes; SYSTEMTIME stLocalTime; @@ -223,7 +227,8 @@ bool win32_exception::write_stacktrace(EXCEPTION_POINTERS* pEp) dumpFileName = StringUtils::Format("%s\\%s", CWIN32Util::GetProfilePath().c_str(), CUtil::MakeLegalFileName(dumpFileName)); - HANDLE hDumpFile = CreateFile(dumpFileName.c_str(), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0); + g_charsetConverter.utf8ToW(dumpFileName, dumpFileNameW, false); + HANDLE hDumpFile = CreateFileW(dumpFileNameW.c_str(), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0); if (hDumpFile == INVALID_HANDLE_VALUE) { @@ -304,7 +309,7 @@ cleanup: } access_violation::access_violation(EXCEPTION_POINTERS* info) : - win32_exception(info,"access_voilation"), mAccessType(Invalid), mBadAddress(0) + win32_exception(info,"access_violation"), mAccessType(Invalid), mBadAddress(0) { switch(info->ExceptionRecord->ExceptionInformation[0]) { diff --git a/xbmc/utils/AMLUtils.cpp b/xbmc/utils/AMLUtils.cpp new file mode 100644 index 0000000000..14a421bcc5 --- /dev/null +++ b/xbmc/utils/AMLUtils.cpp @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2011-2012 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 <unistd.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <string> + +#include "utils/StringUtils.h" + +int aml_set_sysfs_str(const char *path, const char *val) +{ + int fd = open(path, O_CREAT | O_RDWR | O_TRUNC, 0644); + if (fd >= 0) + { + write(fd, val, strlen(val)); + close(fd); + return 0; + } + return -1; +} + +int aml_get_sysfs_str(const char *path, char *valstr, const int size) +{ + int fd = open(path, O_RDONLY); + if (fd >= 0) + { + read(fd, valstr, size - 1); + valstr[strlen(valstr)] = '\0'; + close(fd); + return 0; + } + + sprintf(valstr, "%s", "fail"); + return -1; +} + +int aml_set_sysfs_int(const char *path, const int val) +{ + int fd = open(path, O_CREAT | O_RDWR | O_TRUNC, 0644); + if (fd >= 0) + { + char bcmd[16]; + sprintf(bcmd, "%d", val); + write(fd, bcmd, strlen(bcmd)); + close(fd); + return 0; + } + return -1; +} + +int aml_get_sysfs_int(const char *path) +{ + int val = 0; + int fd = open(path, O_RDONLY); + if (fd >= 0) + { + char bcmd[16]; + read(fd, bcmd, sizeof(bcmd)); + val = strtol(bcmd, NULL, 16); + close(fd); + } + return val; +} + +bool aml_present() +{ + static int has_aml = -1; + if (has_aml == -1) + { + if (aml_get_sysfs_int("/sys/class/audiodsp/digital_raw") != -1) + has_aml = 1; + else + has_aml = 0; + } + return has_aml; +} + +int aml_get_cputype() +{ + static int aml_cputype = -1; + if (aml_cputype == -1) + { + // defualt to m1 SoC + aml_cputype = 1; + + FILE *cpuinfo_fd = fopen("/proc/cpuinfo", "r"); + if (cpuinfo_fd) + { + char buffer[512]; + while (fgets(buffer, sizeof(buffer), cpuinfo_fd)) + { + std::string stdbuffer(buffer); + if (stdbuffer.find("MESON-M3") != std::string::npos) + { + aml_cputype = 3; + break; + } + else if (stdbuffer.find("MESON3") != std::string::npos) + { + aml_cputype = 3; + break; + } + else if (stdbuffer.find("Meson6") != std::string::npos) + { + aml_cputype = 6; + break; + } + } + fclose(cpuinfo_fd); + } + } + + return aml_cputype; +} + +void aml_cpufreq_limit(bool limit) +{ + int cpufreq = 300000; + if (limit) + cpufreq = 600000; + + aml_set_sysfs_int("/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq", cpufreq); +} + +void aml_set_audio_passthrough(bool passthrough) +{ + if (aml_present()) + { + int raw = aml_get_cputype() < 3 ? 1:2; + aml_set_sysfs_int("/sys/class/audiodsp/digital_raw", passthrough ? raw:0); + } +} + +void aml_probe_hdmi_audio() +{ + std::vector<CStdString> audio_formats; + // Audio {format, channel, freq, cce} + // {1, 7, 7f, 7} + // {7, 5, 1e, 0} + // {2, 5, 7, 0} + // {11, 7, 7e, 1} + // {10, 7, 6, 0} + // {12, 7, 7e, 0} + + int fd = open("/sys/class/amhdmitx/amhdmitx0/edid", O_RDONLY); + if (fd >= 0) + { + char valstr[1024] = {0}; + + read(fd, valstr, sizeof(valstr) - 1); + valstr[strlen(valstr)] = '\0'; + close(fd); + + std::vector<CStdString> probe_str; + StringUtils::SplitString(valstr, "\n", probe_str); + + for (size_t i = 0; i < probe_str.size(); i++) + { + if (probe_str[i].find("Audio") == std::string::npos) + { + for (size_t j = i+1; j < probe_str.size(); j++) + { + if (probe_str[i].find("{1,") != std::string::npos) + printf(" PCM found {1,\n"); + else if (probe_str[i].find("{2,") != std::string::npos) + printf(" AC3 found {2,\n"); + else if (probe_str[i].find("{3,") != std::string::npos) + printf(" MPEG1 found {3,\n"); + else if (probe_str[i].find("{4,") != std::string::npos) + printf(" MP3 found {4,\n"); + else if (probe_str[i].find("{5,") != std::string::npos) + printf(" MPEG2 found {5,\n"); + else if (probe_str[i].find("{6,") != std::string::npos) + printf(" AAC found {6,\n"); + else if (probe_str[i].find("{7,") != std::string::npos) + printf(" DTS found {7,\n"); + else if (probe_str[i].find("{8,") != std::string::npos) + printf(" ATRAC found {8,\n"); + else if (probe_str[i].find("{9,") != std::string::npos) + printf(" One_Bit_Audio found {9,\n"); + else if (probe_str[i].find("{10,") != std::string::npos) + printf(" Dolby found {10,\n"); + else if (probe_str[i].find("{11,") != std::string::npos) + printf(" DTS_HD found {11,\n"); + else if (probe_str[i].find("{12,") != std::string::npos) + printf(" MAT found {12,\n"); + else if (probe_str[i].find("{13,") != std::string::npos) + printf(" ATRAC found {13,\n"); + else if (probe_str[i].find("{14,") != std::string::npos) + printf(" WMA found {14,\n"); + else + break; + } + break; + } + } + } +} diff --git a/xbmc/cores/amlplayer/AMLUtils.h b/xbmc/utils/AMLUtils.h index 437f4557c1..d16335b1bc 100644 --- a/xbmc/cores/amlplayer/AMLUtils.h +++ b/xbmc/utils/AMLUtils.h @@ -25,5 +25,6 @@ int aml_set_sysfs_int(const char *path, const int val); int aml_get_sysfs_int(const char *path); bool aml_present(); +int aml_get_cputype(); void aml_cpufreq_limit(bool limit); void aml_set_audio_passthrough(bool passthrough); diff --git a/xbmc/utils/BitstreamConverter.cpp b/xbmc/utils/BitstreamConverter.cpp index 5aedf76ce8..edf45a13ff 100644 --- a/xbmc/utils/BitstreamConverter.cpp +++ b/xbmc/utils/BitstreamConverter.cpp @@ -174,8 +174,129 @@ int CBitstreamConverter::nal_bs_read_ue(nal_bitstream *bs) return ((1 << i) - 1 + nal_bs_read(bs, i)); } -void CBitstreamConverter::parseh264_sps(const uint8_t *sps, const uint32_t sps_size, - bool *interlaced, int32_t *max_ref_frames) +bool CBitstreamConverter::mpeg2_sequence_header(const uint8_t *data, const uint32_t size, mpeg2_sequence *sequence) +{ + // parse nal's until a sequence_header_code is found + // and return the width, height, aspect ratio and frame rate if changed. + bool changed = false; + + if (!data) + return changed; + + const uint8_t *p = data; + const uint8_t *end = p + size; + const uint8_t *nal_start, *nal_end; + + nal_start = avc_find_startcode(p, end); + while (nal_start < end) + { + while (!*(nal_start++)); + nal_end = avc_find_startcode(nal_start, end); + if (*nal_start == 0xB3) + { + nal_bitstream bs; + nal_bs_init(&bs, nal_start, end - nal_start); + + // sequence_header_code + nal_bs_read(&bs, 8); + + // width + // nal_start + 12 bits == horizontal_size_value + uint32_t width = nal_bs_read(&bs, 12); + if (width != sequence->width) + { + changed = true; + sequence->width = width; + } + // height + // nal_start + 24 bits == vertical_size_value + uint32_t height = nal_bs_read(&bs, 12); + if (height != sequence->height) + { + changed = true; + sequence->height = height; + } + + // aspect ratio + // nal_start + 28 bits == aspect_ratio_information + float ratio = sequence->ratio; + uint32_t ratio_info = nal_bs_read(&bs, 4); + switch(ratio_info) + { + case 0x01: + ratio = 1.0; + break; + default: + case 0x02: + ratio = 4.0/3.0; + break; + case 0x03: + ratio = 16.0/9.0; + break; + case 0x04: + ratio = 2.21; + break; + } + if (ratio_info != sequence->ratio_info) + { + changed = true; + sequence->ratio = ratio; + sequence->ratio_info = ratio_info; + } + + // frame rate + // nal_start + 32 bits == frame_rate_code + float rate = sequence->rate; + uint32_t rate_info = nal_bs_read(&bs, 4); + switch(rate_info) + { + default: + case 0x01: + rate = 24000.0 / 1001.0; + break; + case 0x02: + rate = 24000.0 / 1000.0; + break; + case 0x03: + rate = 25000.0 / 1000.0; + break; + case 0x04: + rate = 30000.0 / 1001.0; + break; + case 0x05: + rate = 30000.0 / 1000.0; + break; + case 0x06: + rate = 50000.0 / 1000.0; + break; + case 0x07: + rate = 60000.0 / 1001.0; + break; + case 0x08: + rate = 60000.0 / 1000.0; + break; + } + if (rate_info != sequence->rate_info) + { + changed = true; + sequence->rate = rate; + sequence->rate_info = rate_info; + } + /* + if (changed) + { + CLog::Log(LOGDEBUG, "CBitstreamConverter::mpeg2_sequence_header: " + "width(%d), height(%d), ratio(%f), rate(%f)", width, height, ratio, rate); + } + */ + } + nal_start = nal_end; + } + + return changed; +} + +void CBitstreamConverter::parseh264_sps(const uint8_t *sps, const uint32_t sps_size, bool *interlaced, int32_t *max_ref_frames) { nal_bitstream bs; sps_info_struct sps_info; diff --git a/xbmc/utils/BitstreamConverter.h b/xbmc/utils/BitstreamConverter.h index f4c2d8f2c8..3c213146cc 100644 --- a/xbmc/utils/BitstreamConverter.h +++ b/xbmc/utils/BitstreamConverter.h @@ -69,6 +69,16 @@ typedef struct uint64_t cache; } nal_bitstream; +typedef struct mpeg2_sequence +{ + uint32_t width; + uint32_t height; + float rate; + uint32_t rate_info; + float ratio; + uint32_t ratio_info; +} mpeg2_sequence; + typedef struct { int profile_idc; @@ -122,15 +132,17 @@ public: int GetConvertSize(); uint8_t *GetExtraData(void); int GetExtraSize(); - void parseh264_sps(const uint8_t *sps, const uint32_t sps_size, bool *interlaced, int32_t *max_ref_frames); + + static void parseh264_sps(const uint8_t *sps, const uint32_t sps_size, bool *interlaced, int32_t *max_ref_frames); + static bool mpeg2_sequence_header(const uint8_t *data, const uint32_t size, mpeg2_sequence *sequence); protected: // bytestream (Annex B) to bistream conversion support. - void nal_bs_init(nal_bitstream *bs, const uint8_t *data, size_t size); - uint32_t nal_bs_read(nal_bitstream *bs, int n); - bool nal_bs_eos(nal_bitstream *bs); - int nal_bs_read_ue(nal_bitstream *bs); - const uint8_t *avc_find_startcode_internal(const uint8_t *p, const uint8_t *end); - const uint8_t *avc_find_startcode(const uint8_t *p, const uint8_t *end); + static void nal_bs_init(nal_bitstream *bs, const uint8_t *data, size_t size); + static uint32_t nal_bs_read(nal_bitstream *bs, int n); + static bool nal_bs_eos(nal_bitstream *bs); + static int nal_bs_read_ue(nal_bitstream *bs); + static const uint8_t *avc_find_startcode_internal(const uint8_t *p, const uint8_t *end); + static const uint8_t *avc_find_startcode(const uint8_t *p, const uint8_t *end); const int avc_parse_nal_units(AVIOContext *pb, const uint8_t *buf_in, int size); const int avc_parse_nal_units_buf(const uint8_t *buf_in, uint8_t **buf, int *size); const int isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len); diff --git a/xbmc/utils/BooleanLogic.cpp b/xbmc/utils/BooleanLogic.cpp new file mode 100644 index 0000000000..1a978c6741 --- /dev/null +++ b/xbmc/utils/BooleanLogic.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2012 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 "BooleanLogic.h" +#include "utils/log.h" +#include "utils/StringUtils.h" +#include "utils/XBMCTinyXML.h" + +bool CBooleanLogicValue::Deserialize(const TiXmlNode *node) +{ + if (node == NULL) + return false; + + const TiXmlElement *elem = node->ToElement(); + if (elem == NULL) + return false; + + if (node->FirstChild() != NULL && node->FirstChild()->Type() == TiXmlNode::TINYXML_TEXT) + m_value = node->FirstChild()->ValueStr(); + + m_negated = false; + const char *strNegated = elem->Attribute("negated"); + if (strNegated != NULL) + { + if (StringUtils::EqualsNoCase(strNegated, "true")) + m_negated = true; + else if (!StringUtils::EqualsNoCase(strNegated, "false")) + { + CLog::Log(LOGDEBUG, "CBooleanLogicValue: invalid negated value \"%s\"", strNegated); + return false; + } + } + + return true; +} + +CBooleanLogicOperation::~CBooleanLogicOperation() +{ + m_operations.clear(); + m_values.clear(); +} + +bool CBooleanLogicOperation::Deserialize(const TiXmlNode *node) +{ + if (node == NULL) + return false; + + // check if this is a simple operation with a single value directly expressed + // in the parent tag + if (node->FirstChild() == NULL || node->FirstChild()->Type() == TiXmlNode::TINYXML_TEXT) + { + CBooleanLogicValuePtr value = CBooleanLogicValuePtr(newValue()); + if (value == NULL || !value->Deserialize(node)) + { + CLog::Log(LOGDEBUG, "CBooleanLogicOperation: failed to deserialize implicit boolean value definition"); + return false; + } + + m_values.push_back(value); + return true; + } + + const TiXmlNode *operationNode = node->FirstChild(); + while (operationNode != NULL) + { + std::string tag = operationNode->ValueStr(); + if (StringUtils::EqualsNoCase(tag, "and") || StringUtils::EqualsNoCase(tag, "or")) + { + CBooleanLogicOperationPtr operation = CBooleanLogicOperationPtr(newOperation()); + if (operation == NULL) + return false; + + operation->SetOperation(StringUtils::EqualsNoCase(tag, "and") ? BooleanLogicOperationAnd : BooleanLogicOperationOr); + if (!operation->Deserialize(operationNode)) + { + CLog::Log(LOGDEBUG, "CBooleanLogicOperation: failed to deserialize <%s> definition", tag.c_str()); + return false; + } + + m_operations.push_back(operation); + } + else + { + CBooleanLogicValuePtr value = CBooleanLogicValuePtr(newValue()); + if (value == NULL) + return false; + + if (StringUtils::EqualsNoCase(tag, value->GetTag())) + { + if (!value->Deserialize(operationNode)) + { + CLog::Log(LOGDEBUG, "CBooleanLogicOperation: failed to deserialize <%s> definition", tag.c_str()); + return false; + } + + m_values.push_back(value); + } + else if (operationNode->Type() == TiXmlNode::TINYXML_ELEMENT) + CLog::Log(LOGDEBUG, "CBooleanLogicOperation: unknown <%s> definition encountered", tag.c_str()); + } + + operationNode = operationNode->NextSibling(); + } + + return true; +} + +bool CBooleanLogic::Deserialize(const TiXmlNode *node) +{ + if (node == NULL) + return false; + + if (m_operation == NULL) + { + m_operation = CBooleanLogicOperationPtr(new CBooleanLogicOperation()); + + if (m_operation == NULL) + return false; + } + + return m_operation->Deserialize(node); +} diff --git a/xbmc/utils/BooleanLogic.h b/xbmc/utils/BooleanLogic.h new file mode 100644 index 0000000000..b44de38795 --- /dev/null +++ b/xbmc/utils/BooleanLogic.h @@ -0,0 +1,101 @@ +#pragma once +/* + * Copyright (C) 2012 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 <string> +#include <vector> + +#include <boost/shared_ptr.hpp> + +#include "utils/IXmlDeserializable.h" + +typedef enum { + BooleanLogicOperationOr = 0, + BooleanLogicOperationAnd +} BooleanLogicOperation; + +class CBooleanLogicValue : public IXmlDeserializable +{ +public: + CBooleanLogicValue(const std::string &value = "", bool negated = false) + : m_value(value), m_negated(negated) + { } + virtual ~CBooleanLogicValue() { } + + virtual bool Deserialize(const TiXmlNode *node); + + virtual const std::string& GetValue() const { return m_value; } + virtual bool IsNegated() const { return m_negated; } + virtual const char* GetTag() const { return "value"; } + + virtual void SetValue(const std::string &value) { m_value = value; } + virtual void SetNegated(bool negated) { m_negated = negated; } + +protected: + std::string m_value; + bool m_negated; +}; + +typedef boost::shared_ptr<CBooleanLogicValue> CBooleanLogicValuePtr; +typedef std::vector<CBooleanLogicValuePtr> CBooleanLogicValues; + +class CBooleanLogicOperation; +typedef boost::shared_ptr<CBooleanLogicOperation> CBooleanLogicOperationPtr; +typedef std::vector<CBooleanLogicOperationPtr> CBooleanLogicOperations; + +class CBooleanLogicOperation : public IXmlDeserializable +{ +public: + CBooleanLogicOperation(BooleanLogicOperation op = BooleanLogicOperationAnd) + : m_operation(op) + { } + virtual ~CBooleanLogicOperation(); + + virtual bool Deserialize(const TiXmlNode *node); + + virtual BooleanLogicOperation GetOperation() const { return m_operation; } + virtual const CBooleanLogicOperations& GetOperations() const { return m_operations; } + virtual const CBooleanLogicValues& GetValues() const { return m_values; } + + virtual void SetOperation(BooleanLogicOperation op) { m_operation = op; } + +protected: + virtual CBooleanLogicOperation* newOperation() { return new CBooleanLogicOperation(); } + virtual CBooleanLogicValue* newValue() { return new CBooleanLogicValue(); } + + BooleanLogicOperation m_operation; + CBooleanLogicOperations m_operations; + CBooleanLogicValues m_values; +}; + +class CBooleanLogic : public IXmlDeserializable +{ +public: + CBooleanLogic() { } + virtual ~CBooleanLogic() { } + + virtual bool Deserialize(const TiXmlNode *node); + + virtual const CBooleanLogicOperationPtr& Get() const { return m_operation; } + virtual CBooleanLogicOperationPtr Get() { return m_operation; } + +protected: + CBooleanLogicOperationPtr m_operation; +}; diff --git a/xbmc/utils/CharsetConverter.cpp b/xbmc/utils/CharsetConverter.cpp index 4e37b7d452..f5001fff49 100644 --- a/xbmc/utils/CharsetConverter.cpp +++ b/xbmc/utils/CharsetConverter.cpp @@ -22,6 +22,8 @@ #include "Util.h" #include <fribidi/fribidi.h> #include "LangInfo.h" +#include "guilib/LocalizeStrings.h" +#include "settings/Setting.h" #include "threads/SingleLock.h" #include "log.h" @@ -339,6 +341,19 @@ CCharsetConverter::CCharsetConverter() { } +void CCharsetConverter::OnSettingChanged(const CSetting *setting) +{ + if (setting == NULL) + return; + + const std::string &settingId = setting->GetId(); + // TODO: does this make any sense at all for subtitles and karaoke? + if (settingId == "subtitles.charset" || + settingId == "karaoke.charset" || + settingId == "locale.charset") + reset(); +} + void CCharsetConverter::clear() { } @@ -700,3 +715,13 @@ void CCharsetConverter::utf8logicalToVisualBiDi(const CStdStringA& strSource, CS { logicalToVisualBiDi(strSource, strDest, FRIBIDI_UTF8, FRIBIDI_TYPE_RTL); } + +void CCharsetConverter::SettingOptionsCharsetsFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t) +{ + vector<CStdString> vecCharsets = g_charsetConverter.getCharsetLabels(); + sort(vecCharsets.begin(), vecCharsets.end(), sortstringbyname()); + + list.push_back(make_pair(g_localizeStrings.Get(13278), "DEFAULT")); // "Default" + for (int i = 0; i < (int) vecCharsets.size(); ++i) + list.push_back(make_pair(vecCharsets[i], g_charsetConverter.getCharsetNameByLabel(vecCharsets[i]))); +} diff --git a/xbmc/utils/CharsetConverter.h b/xbmc/utils/CharsetConverter.h index 62780aa2b1..36602961db 100644 --- a/xbmc/utils/CharsetConverter.h +++ b/xbmc/utils/CharsetConverter.h @@ -21,17 +21,22 @@ * */ +#include "settings/ISettingCallback.h" #include "threads/CriticalSection.h" -#include "StdString.h" #include "utils/GlobalsHandling.h" +#include "utils/StdString.h" #include <vector> -class CCharsetConverter +class CSetting; + +class CCharsetConverter : public ISettingCallback { public: CCharsetConverter(); + virtual void OnSettingChanged(const CSetting *setting); + void reset(); void clear(); @@ -78,6 +83,8 @@ public: void toW(const CStdStringA& source, CStdStringW& dest, const CStdStringA& enc); void fromW(const CStdStringW& source, CStdStringA& dest, const CStdStringA& enc); + + static void SettingOptionsCharsetsFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t); }; XBMC_GLOBAL(CCharsetConverter,g_charsetConverter); diff --git a/xbmc/utils/EdenVideoArtUpdater.cpp b/xbmc/utils/EdenVideoArtUpdater.cpp index 71b8f017a5..fd55f4f4e7 100644 --- a/xbmc/utils/EdenVideoArtUpdater.cpp +++ b/xbmc/utils/EdenVideoArtUpdater.cpp @@ -31,8 +31,8 @@ #include "TextureCacheJob.h" #include "pictures/Picture.h" #include "profiles/ProfilesManager.h" -#include "settings/GUISettings.h" #include "settings/AdvancedSettings.h" +#include "settings/Settings.h" #include "guilib/Texture.h" #include "guilib/GUIWindowManager.h" #include "guilib/LocalizeStrings.h" @@ -246,7 +246,7 @@ void CEdenVideoArtUpdater::Process() items.Clear(); // now actors - if (g_guiSettings.GetBool("videolibrary.actorthumbs")) + if (CSettings::Get().GetBool("videolibrary.actorthumbs")) { db.GetActorsNav("videodb://movies/titles/", items, VIDEODB_CONTENT_MOVIES); db.GetActorsNav("videodb://tvshows/titles/", items, VIDEODB_CONTENT_TVSHOWS); diff --git a/xbmc/utils/FileOperationJob.cpp b/xbmc/utils/FileOperationJob.cpp index 5d484ce251..2ba073746a 100644 --- a/xbmc/utils/FileOperationJob.cpp +++ b/xbmc/utils/FileOperationJob.cpp @@ -180,7 +180,7 @@ bool CFileOperationJob::DoProcess(FileAction action, CFileItemList & items, cons CStdString strnewDestFile; if(!strDestFile.IsEmpty()) // only do this if we have a destination - URIUtils::AddFileToFolder(strDestFile, strFileName, strnewDestFile); + strnewDestFile = URIUtils::AddFileToFolder(strDestFile, strFileName); if (pItem->m_bIsFolder) { diff --git a/xbmc/utils/FileUtils.cpp b/xbmc/utils/FileUtils.cpp index 74f1d81fc2..e47a87d2a9 100644 --- a/xbmc/utils/FileUtils.cpp +++ b/xbmc/utils/FileUtils.cpp @@ -71,7 +71,7 @@ bool CFileUtils::RenameFile(const CStdString &strFile) CStdString filePath(paths[i]); URIUtils::RemoveSlashAtEnd(filePath); URIUtils::GetDirectory(filePath, filePath); - URIUtils::AddFileToFolder(filePath, strFileName, filePath); + filePath = URIUtils::AddFileToFolder(filePath, strFileName); if (CFile::Rename(paths[i], filePath)) success = true; } diff --git a/xbmc/utils/IXmlDeserializable.h b/xbmc/utils/IXmlDeserializable.h new file mode 100644 index 0000000000..a7d3a27a52 --- /dev/null +++ b/xbmc/utils/IXmlDeserializable.h @@ -0,0 +1,30 @@ +#pragma once +/* + * Copyright (C) 2012 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/>. + * + */ + +class TiXmlNode; + +class IXmlDeserializable +{ +public: + virtual ~IXmlDeserializable() { } + + virtual bool Deserialize(const TiXmlNode *node) = 0; +}; diff --git a/xbmc/utils/LabelFormatter.cpp b/xbmc/utils/LabelFormatter.cpp index 957f56f2a5..906033622c 100644 --- a/xbmc/utils/LabelFormatter.cpp +++ b/xbmc/utils/LabelFormatter.cpp @@ -19,8 +19,8 @@ */ #include "LabelFormatter.h" -#include "settings/GUISettings.h" #include "settings/AdvancedSettings.h" +#include "settings/Settings.h" #include "RegExp.h" #include "Util.h" #include "video/VideoInfoTag.h" @@ -108,7 +108,7 @@ CLabelFormatter::CLabelFormatter(const CStdString &mask, const CStdString &mask2 AssembleMask(0, mask); AssembleMask(1, mask2); // save a bool for faster lookups - m_hideFileExtensions = !g_guiSettings.GetBool("filelists.showextensions"); + m_hideFileExtensions = !CSettings::Get().GetBool("filelists.showextensions"); } CStdString CLabelFormatter::GetContent(unsigned int label, const CFileItem *item) const diff --git a/xbmc/utils/LangCodeExpander.cpp b/xbmc/utils/LangCodeExpander.cpp index 0f1c58525c..6cd46c132d 100644 --- a/xbmc/utils/LangCodeExpander.cpp +++ b/xbmc/utils/LangCodeExpander.cpp @@ -32,8 +32,8 @@ typedef struct LCENTRY const char *name; } LCENTRY; -extern const struct LCENTRY g_iso639_1[143]; -extern const struct LCENTRY g_iso639_2[536]; +extern const struct LCENTRY g_iso639_1[144]; +extern const struct LCENTRY g_iso639_2[537]; struct CharCodeConvertionWithHack { @@ -202,6 +202,14 @@ bool CLangCodeExpander::ConvertToThreeCharCode(CStdString& strThreeCharCode, con return true; } } + for (unsigned int index = 0; index < sizeof(RegionCode2To3) / sizeof(RegionCode2To3[0]); ++index) + { + if (strCharCode.Equals(RegionCode2To3[index].id)) + { + strThreeCharCode = strCharCode; + return true; + } + } } else if (strCharCode.size() > 3) { @@ -261,6 +269,93 @@ bool CLangCodeExpander::ConvertWindowsToGeneralCharCode(const CStdString& strWin } #endif +bool CLangCodeExpander::ConvertToTwoCharCode(CStdString& code, const CStdString& lang) +{ + if (lang.length() == 2) + { + CStdString tmp; + if (Lookup(tmp, lang)) + { + code = lang; + return true; + } + } + else if (lang.length() == 3) + { + for (unsigned int index = 0; index < sizeof(CharCode2To3) / sizeof(CharCode2To3[0]); ++index) + { + if (lang.Equals(CharCode2To3[index].id) || (CharCode2To3[index].win_id && lang.Equals(CharCode2To3[index].win_id))) + { + code = CharCode2To3[index].old; + return true; + } + } + + for (unsigned int index = 0; index < sizeof(RegionCode2To3) / sizeof(RegionCode2To3[0]); ++index) + { + if (lang.Equals(RegionCode2To3[index].id)) + { + code = RegionCode2To3[index].old; + return true; + } + } + } + + // check if lang is full language name + CStdString tmp; + if (ReverseLookup(lang, tmp)) + { + if (tmp.length() == 2) + { + code = tmp; + return true; + } + else if (tmp.length() == 3) + return ConvertToTwoCharCode(code, tmp); + } + + // try xbmc specific language names + CStdString strLangInfoPath; + strLangInfoPath.Format("special://xbmc/language/%s/langinfo.xml", lang.c_str()); + CLangInfo langInfo; + if (!langInfo.Load(strLangInfoPath)) + return false; + + return ConvertToTwoCharCode(code, langInfo.GetLanguageCode()); +} + +bool CLangCodeExpander::ReverseLookup(const CStdString& desc, CStdString& code) +{ + CStdString descTmp(desc); + descTmp.Trim(); + STRINGLOOKUPTABLE::iterator it; + for (it = m_mapUser.begin(); it != m_mapUser.end() ; it++) + { + if (descTmp.Equals(it->second)) + { + code = it->first; + return true; + } + } + for(unsigned int i = 0; i < sizeof(g_iso639_1) / sizeof(LCENTRY); i++) + { + if (descTmp.Equals(g_iso639_1[i].name)) + { + CodeToString(g_iso639_1[i].code, code); + return true; + } + } + for(unsigned int i = 0; i < sizeof(g_iso639_2) / sizeof(LCENTRY); i++) + { + if (descTmp.Equals(g_iso639_2[i].name)) + { + CodeToString(g_iso639_2[i].code, code); + return true; + } + } + return false; +} + bool CLangCodeExpander::LookupInMap(CStdString& desc, const CStdString& code) { STRINGLOOKUPTABLE::iterator it; @@ -312,10 +407,24 @@ bool CLangCodeExpander::LookupInDb(CStdString& desc, const CStdString& code) return false; } -extern const LCENTRY g_iso639_1[143] = +void CLangCodeExpander::CodeToString(long code, CStdString& ret) +{ + ret.Empty(); + for (unsigned int j = 0 ; j < 4 ; j++) + { + char c = (char) code & 0xFF; + if (c == '\0') + return; + ret.Insert(0, c); + code >>= 8; + } +} + +extern const LCENTRY g_iso639_1[144] = { { MAKECODE('\0','\0','c','c'), "Closed Caption" }, { MAKECODE('\0','\0','a','a'), "Afar" }, + { MAKECODE('\0','\0','a','b'), "Abkhaz" }, { MAKECODE('\0','\0','a','b'), "Abkhazian" }, { MAKECODE('\0','\0','a','f'), "Afrikaans" }, { MAKECODE('\0','\0','a','m'), "Amharic" }, @@ -336,7 +445,7 @@ extern const LCENTRY g_iso639_1[143] = { MAKECODE('\0','\0','c','s'), "Czech" }, { MAKECODE('\0','\0','c','y'), "Welsh" }, { MAKECODE('\0','\0','d','a'), "Dansk" }, - { MAKECODE('\0','\0','d','e'), "Deutsch" }, + { MAKECODE('\0','\0','d','e'), "German" }, { MAKECODE('\0','\0','d','z'), "Bhutani" }, { MAKECODE('\0','\0','e','l'), "Greek" }, { MAKECODE('\0','\0','e','n'), "English" }, @@ -407,7 +516,7 @@ extern const LCENTRY g_iso639_1[143] = { MAKECODE('\0','\0','p','a'), "Punjabi" }, { MAKECODE('\0','\0','p','l'), "Polish" }, { MAKECODE('\0','\0','p','s'), "Pashto, Pushto" }, - { MAKECODE('\0','\0','p','t'), "Portugues" }, + { MAKECODE('\0','\0','p','t'), "Portuguese" }, { MAKECODE('\0','\0','q','u'), "Quechua" }, { MAKECODE('\0','\0','r','m'), "Rhaeto-Romance" }, { MAKECODE('\0','\0','r','n'), "Kirundi" }, @@ -459,9 +568,10 @@ extern const LCENTRY g_iso639_1[143] = { MAKECODE('\0','\0','z','u'), "Zulu" }, }; -extern const LCENTRY g_iso639_2[536] = +extern const LCENTRY g_iso639_2[537] = { - { MAKECODE('\0','a','b','k'), "Abkhazian" }, + { MAKECODE('\0','a','b','k'), "Abkhaz" }, + { MAKECODE('\0','a','b','k'), "Abkhazian" }, { MAKECODE('\0','a','c','e'), "Achinese" }, { MAKECODE('\0','a','c','h'), "Acoli" }, { MAKECODE('\0','a','d','a'), "Adangme" }, diff --git a/xbmc/utils/LangCodeExpander.h b/xbmc/utils/LangCodeExpander.h index bee2fe64a0..5530b70cb5 100644 --- a/xbmc/utils/LangCodeExpander.h +++ b/xbmc/utils/LangCodeExpander.h @@ -28,11 +28,27 @@ class CLangCodeExpander { public: + enum LANGFORMATS + { + ISO_639_1, + ISO_639_2, + ENGLISH_NAME + }; + CLangCodeExpander(void); ~CLangCodeExpander(void); bool Lookup(CStdString& desc, const CStdString& code); bool Lookup(CStdString& desc, const int code); + + /** \brief Converts a language given as 2-Char (ISO 639-1), + * 3-Char (ISO 639-2/T or ISO 639-2/B), + * or full english name string to a 2-Char (ISO 639-1) code. + * \param[out] code The 2-Char language code of the given language lang. + * \param[in] lang The language that should be converted. + * \return true if the conversion succeeded, false otherwise. + */ + bool ConvertToTwoCharCode(CStdString& code, const CStdString& lang); #ifdef TARGET_WINDOWS bool ConvertTwoToThreeCharCode(CStdString& strThreeCharCode, const CStdString& strTwoCharCode, bool localeHack = false); bool ConvertToThreeCharCode(CStdString& strThreeCharCode, const CStdString& strCharCode, bool localeHack = false); @@ -50,12 +66,26 @@ public: void Clear(); protected: + /** \brief Converts a language code given as a long, see #MAKECODE(a, b, c, d) + * to its string representation. + * \param[in] code The language code given as a long, see #MAKECODE(a, b, c, d). + * \param[out] ret The string representation of the given language code code. + */ + void CodeToString(long code, CStdString& ret); typedef std::map<CStdString, CStdString> STRINGLOOKUPTABLE; STRINGLOOKUPTABLE m_mapUser; bool LookupInDb(CStdString& desc, const CStdString& code); bool LookupInMap(CStdString& desc, const CStdString& code); + + /** \brief Looks up the ISO 639-1, ISO 639-2/T, or ISO 639-2/B, whichever it finds first, + * code of the given english language name. + * \param[in] desc The english language name for which a code is looked for. + * \param[out] code The ISO 639-1, ISO 639-2/T, or ISO 639-2/B code of the given language desc. + * \return true if the a code was found, false otherwise. + */ + bool ReverseLookup(const CStdString& desc, CStdString& code); }; extern CLangCodeExpander g_LangCodeExpander; diff --git a/xbmc/utils/Makefile b/xbmc/utils/Makefile deleted file mode 100644 index eec7e1f9ee..0000000000 --- a/xbmc/utils/Makefile +++ /dev/null @@ -1,76 +0,0 @@ -SRCS=AlarmClock.cpp \ - AliasShortcutUtils.cpp \ - Archive.cpp \ - AsyncFileCopy.cpp \ - AutoPtrHandle.cpp \ - Base64.cpp \ - BitstreamConverter.cpp \ - BitstreamStats.cpp \ - CharsetConverter.cpp \ - CPUInfo.cpp \ - Crc32.cpp \ - CryptThreading.cpp \ - DatabaseUtils.cpp \ - DownloadQueue.cpp \ - DownloadQueueManager.cpp \ - EndianSwap.cpp \ - EdenVideoArtUpdater.cpp \ - Fanart.cpp \ - fastmemcpy.c \ - fastmemcpy-arm.S \ - FileOperationJob.cpp \ - FileUtils.cpp \ - fstrcmp.c \ - fft.cpp \ - GLUtils.cpp \ - GroupUtils.cpp \ - HTMLTable.cpp \ - HTMLUtil.cpp \ - HttpHeader.cpp \ - HttpParser.cpp \ - HttpResponse.cpp \ - InfoLoader.cpp \ - JobManager.cpp \ - JSONVariantParser.cpp \ - JSONVariantWriter.cpp \ - LabelFormatter.cpp \ - LangCodeExpander.cpp \ - log.cpp \ - md5.cpp \ - Observer.cpp \ - Mime.cpp \ - PerformanceSample.cpp \ - PerformanceStats.cpp \ - POUtils.cpp \ - RecentlyAddedJob.cpp \ - RegExp.cpp \ - RingBuffer.cpp \ - RssManager.cpp \ - RssReader.cpp \ - ScraperParser.cpp \ - ScraperUrl.cpp \ - Screenshot.cpp \ - SeekHandler.cpp \ - SortUtils.cpp \ - Splash.cpp \ - Stopwatch.cpp \ - StreamDetails.cpp \ - StreamUtils.cpp \ - StringUtils.cpp \ - SystemInfo.cpp \ - TextSearch.cpp \ - TimeSmoother.cpp \ - TimeUtils.cpp \ - TuxBoxUtil.cpp \ - URIUtils.cpp \ - UrlOptions.cpp \ - Variant.cpp \ - Vector.cpp \ - Weather.cpp \ - XBMCTinyXML.cpp \ - XMLUtils.cpp \ - -LIB=utils.a - -include ../../Makefile.include --include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(patsubst %.S,,$(SRCS)))) diff --git a/xbmc/utils/Makefile.in b/xbmc/utils/Makefile.in new file mode 100644 index 0000000000..5b75e85626 --- /dev/null +++ b/xbmc/utils/Makefile.in @@ -0,0 +1,81 @@ +SRCS += AlarmClock.cpp +SRCS += AliasShortcutUtils.cpp +SRCS += Archive.cpp +SRCS += AsyncFileCopy.cpp +SRCS += AutoPtrHandle.cpp +SRCS += Base64.cpp +SRCS += BitstreamConverter.cpp +SRCS += BitstreamStats.cpp +SRCS += BooleanLogic.cpp +SRCS += CharsetConverter.cpp +SRCS += CPUInfo.cpp +SRCS += Crc32.cpp +SRCS += CryptThreading.cpp +SRCS += DatabaseUtils.cpp +SRCS += DownloadQueue.cpp +SRCS += DownloadQueueManager.cpp +SRCS += EndianSwap.cpp +SRCS += EdenVideoArtUpdater.cpp +SRCS += Fanart.cpp +SRCS += fastmemcpy.c +SRCS += fastmemcpy-arm.S +SRCS += FileOperationJob.cpp +SRCS += FileUtils.cpp +SRCS += fstrcmp.c +SRCS += fft.cpp +SRCS += GLUtils.cpp +SRCS += GroupUtils.cpp +SRCS += HTMLTable.cpp +SRCS += HTMLUtil.cpp +SRCS += HttpHeader.cpp +SRCS += HttpParser.cpp +SRCS += HttpResponse.cpp +SRCS += InfoLoader.cpp +SRCS += JobManager.cpp +SRCS += JSONVariantParser.cpp +SRCS += JSONVariantWriter.cpp +SRCS += LabelFormatter.cpp +SRCS += LangCodeExpander.cpp +SRCS += log.cpp +SRCS += md5.cpp +SRCS += Mime.cpp +SRCS += Observer.cpp +SRCS += PerformanceSample.cpp +SRCS += PerformanceStats.cpp +SRCS += POUtils.cpp +SRCS += RecentlyAddedJob.cpp +SRCS += RegExp.cpp +SRCS += RingBuffer.cpp +SRCS += RssManager.cpp +SRCS += RssReader.cpp +SRCS += ScraperParser.cpp +SRCS += ScraperUrl.cpp +SRCS += Screenshot.cpp +SRCS += SeekHandler.cpp +SRCS += SortUtils.cpp +SRCS += Splash.cpp +SRCS += Stopwatch.cpp +SRCS += StreamDetails.cpp +SRCS += StreamUtils.cpp +SRCS += StringUtils.cpp +SRCS += SystemInfo.cpp +SRCS += TextSearch.cpp +SRCS += TimeSmoother.cpp +SRCS += TimeUtils.cpp +SRCS += TuxBoxUtil.cpp +SRCS += URIUtils.cpp +SRCS += UrlOptions.cpp +SRCS += Variant.cpp +SRCS += Vector.cpp +SRCS += Weather.cpp +SRCS += XBMCTinyXML.cpp +SRCS += XMLUtils.cpp + +ifeq (@USE_OPENGLES@,1) +SRCS += AMLUtils.cpp +endif + +LIB = utils.a + +include @abs_top_srcdir@/Makefile.include +-include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(patsubst %.S,,$(SRCS)))) diff --git a/xbmc/utils/Mime.cpp b/xbmc/utils/Mime.cpp index 17b99d6870..daad47790c 100644 --- a/xbmc/utils/Mime.cpp +++ b/xbmc/utils/Mime.cpp @@ -59,7 +59,7 @@ map<string, string> fillMimeTypes() mimeTypes.insert(pair<string, string>("asp", "text/asp")); mimeTypes.insert(pair<string, string>("asx", "video/x-ms-asf")); mimeTypes.insert(pair<string, string>("au", "audio/basic")); - mimeTypes.insert(pair<string, string>("avi", "video/x-msvideo")); + mimeTypes.insert(pair<string, string>("avi", "video/avi")); mimeTypes.insert(pair<string, string>("avs", "video/avs-video")); mimeTypes.insert(pair<string, string>("bcpio", "application/x-bcpio")); mimeTypes.insert(pair<string, string>("bin", "application/octet-stream")); @@ -193,7 +193,8 @@ map<string, string> fillMimeTypes() mimeTypes.insert(pair<string, string>("jpeg", "image/jpeg")); mimeTypes.insert(pair<string, string>("jpg", "image/jpeg")); mimeTypes.insert(pair<string, string>("jps", "image/x-jps")); - mimeTypes.insert(pair<string, string>("js", "application/x-javascript")); + mimeTypes.insert(pair<string, string>("js", "application/javascript")); + mimeTypes.insert(pair<string, string>("json", "application/json")); mimeTypes.insert(pair<string, string>("jut", "image/jutvision")); mimeTypes.insert(pair<string, string>("kar", "music/x-karaoke")); mimeTypes.insert(pair<string, string>("ksh", "application/x-ksh")); @@ -404,6 +405,7 @@ map<string, string> fillMimeTypes() mimeTypes.insert(pair<string, string>("text", "text/plain")); mimeTypes.insert(pair<string, string>("tgz", "application/x-compressed")); mimeTypes.insert(pair<string, string>("tif", "image/tiff")); + mimeTypes.insert(pair<string, string>("tiff", "image/tiff")); mimeTypes.insert(pair<string, string>("tr", "application/x-troff")); mimeTypes.insert(pair<string, string>("ts", "video/mp2t")); mimeTypes.insert(pair<string, string>("tsi", "audio/tsp-audio")); diff --git a/xbmc/utils/Observer.h b/xbmc/utils/Observer.h index 5ebd23cd32..a54017fac8 100644 --- a/xbmc/utils/Observer.h +++ b/xbmc/utils/Observer.h @@ -29,7 +29,6 @@ typedef enum { ObservableMessageNone, ObservableMessageCurrentItem, - ObservableMessageGuiSettings, ObservableMessageAddons, ObservableMessageEpg, ObservableMessageEpgContainer, diff --git a/xbmc/utils/RssManager.cpp b/xbmc/utils/RssManager.cpp index 686c3eb226..8b71ed5271 100644 --- a/xbmc/utils/RssManager.cpp +++ b/xbmc/utils/RssManager.cpp @@ -19,8 +19,13 @@ */ #include "RssManager.h" +#include "addons/AddonInstaller.h" +#include "addons/AddonManager.h" +#include "dialogs/GUIDialogYesNo.h" #include "filesystem/File.h" +#include "interfaces/Builtins.h" #include "profiles/ProfilesManager.h" +#include "settings/Setting.h" #include "threads/SingleLock.h" #include "utils/log.h" #include "utils/RssReader.h" @@ -55,6 +60,26 @@ void CRssManager::OnSettingsCleared() Clear(); } +void CRssManager::OnSettingAction(const CSetting *setting) +{ + if (setting == NULL) + return; + + const std::string &settingId = setting->GetId(); + if (settingId == "lookandfeel.rssedit") + { + ADDON::AddonPtr addon; + ADDON::CAddonMgr::Get().GetAddon("script.rss.editor",addon); + if (!addon) + { + if (!CGUIDialogYesNo::ShowAndGetInput(g_localizeStrings.Get(24076), g_localizeStrings.Get(24100), "RSS Editor", g_localizeStrings.Get(24101))) + return; + CAddonInstaller::Get().Install("script.rss.editor", true, "", false); + } + CBuiltins::Execute("RunScript(script.rss.editor)"); + } +} + void CRssManager::Start() { m_bActive = true; diff --git a/xbmc/utils/RssManager.h b/xbmc/utils/RssManager.h index 5277876c67..8fd187d709 100644 --- a/xbmc/utils/RssManager.h +++ b/xbmc/utils/RssManager.h @@ -25,6 +25,7 @@ #include "threads/CriticalSection.h" +#include "settings/ISettingCallback.h" #include "settings/ISettingsHandler.h" class CRssReader; @@ -38,7 +39,7 @@ typedef struct } RssSet; typedef std::map<int, RssSet> RssUrls; -class CRssManager : public ISettingsHandler +class CRssManager : public ISettingCallback, public ISettingsHandler { public: static CRssManager& Get(); @@ -46,6 +47,8 @@ public: virtual void OnSettingsLoaded(); virtual void OnSettingsCleared(); + virtual void OnSettingAction(const CSetting *setting); + void Start(); void Stop(); bool Load(); diff --git a/xbmc/utils/SaveFileStateJob.h b/xbmc/utils/SaveFileStateJob.h index 3b2c727618..123bbd86bb 100644 --- a/xbmc/utils/SaveFileStateJob.h +++ b/xbmc/utils/SaveFileStateJob.h @@ -31,13 +31,14 @@ public: bool CSaveFileStateJob::DoWork() { CStdString progressTrackingFile = m_item.GetPath(); + if (m_item.HasVideoInfoTag() && m_item.GetVideoInfoTag()->m_strFileNameAndPath.Find("removable://") == 0) progressTrackingFile = m_item.GetVideoInfoTag()->m_strFileNameAndPath; // this variable contains removable:// suffixed by disc label+uniqueid or is empty if label not uniquely identified else if (m_item.HasProperty("original_listitem_url")) { - // only use original_listitem_url for Python & UPnP sources + // only use original_listitem_url for Python, UPnP and Bluray sources CStdString original = m_item.GetProperty("original_listitem_url").asString(); - if (URIUtils::IsPlugin(original) || URIUtils::IsUPnP(original)) + if (URIUtils::IsPlugin(original) || URIUtils::IsUPnP(original) || URIUtils::IsBluray(m_item.GetPath())) progressTrackingFile = original; } @@ -122,10 +123,9 @@ bool CSaveFileStateJob::DoWork() if (m_item.HasVideoInfoTag() && m_item.GetVideoInfoTag()->HasStreamDetails()) { CFileItem dbItem(m_item); - videodatabase.GetStreamDetails(dbItem); // Fetch stream details from the db (if any) // Check whether the item's db streamdetails need updating - if (!dbItem.GetVideoInfoTag()->HasStreamDetails() || dbItem.GetVideoInfoTag()->m_streamDetails != m_item.GetVideoInfoTag()->m_streamDetails) + if (!videodatabase.GetStreamDetails(dbItem) || dbItem.GetVideoInfoTag()->m_streamDetails != m_item.GetVideoInfoTag()->m_streamDetails) { videodatabase.SetStreamDetailsForFile(m_item.GetVideoInfoTag()->m_streamDetails, progressTrackingFile); updateListing = true; diff --git a/xbmc/utils/ScraperUrl.cpp b/xbmc/utils/ScraperUrl.cpp index fb7bb6cdcc..5860749062 100644 --- a/xbmc/utils/ScraperUrl.cpp +++ b/xbmc/utils/ScraperUrl.cpp @@ -207,9 +207,8 @@ bool CScraperUrl::Get(const SUrlEntry& scrURL, std::string& strHTML, XFILE::CCur if (!scrURL.m_cache.IsEmpty()) { - URIUtils::AddFileToFolder(g_advancedSettings.m_cachePath, - "scrapers/"+cacheContext+"/"+scrURL.m_cache, - strCachePath); + strCachePath = URIUtils::AddFileToFolder(g_advancedSettings.m_cachePath, + "scrapers/" + cacheContext + "/" + scrURL.m_cache); if (XFILE::CFile::Exists(strCachePath)) { XFILE::CFile file; @@ -257,10 +256,8 @@ bool CScraperUrl::Get(const SUrlEntry& scrURL, std::string& strHTML, XFILE::CCur if (!scrURL.m_cache.IsEmpty()) { - CStdString strCachePath; - URIUtils::AddFileToFolder(g_advancedSettings.m_cachePath, - "scrapers/"+cacheContext+"/"+scrURL.m_cache, - strCachePath); + CStdString strCachePath = URIUtils::AddFileToFolder(g_advancedSettings.m_cachePath, + "scrapers/" + cacheContext + "/" + scrURL.m_cache); XFILE::CFile file; if (file.OpenForWrite(strCachePath,true)) file.Write(strHTML.data(),strHTML.size()); diff --git a/xbmc/utils/Screenshot.cpp b/xbmc/utils/Screenshot.cpp index 0f5039905d..d86a240e93 100644 --- a/xbmc/utils/Screenshot.cpp +++ b/xbmc/utils/Screenshot.cpp @@ -39,7 +39,9 @@ #include "utils/JobManager.h" #include "utils/URIUtils.h" #include "utils/log.h" -#include "settings/GUISettings.h" +#include "settings/SettingPath.h" +#include "settings/Settings.h" +#include "settings/windows/GUIControlSettings.h" using namespace std; using namespace XFILE; @@ -204,10 +206,21 @@ void CScreenShot::TakeScreenshot() { static bool savingScreenshots = false; static vector<CStdString> screenShots; - bool promptUser = false; + CStdString strDir; + // check to see if we have a screenshot folder yet - CStdString strDir = g_guiSettings.GetString("debug.screenshotpath", false); + CSettingPath *screenshotSetting = (CSettingPath*)CSettings::Get().GetSetting("debug.screenshotpath"); + if (screenshotSetting != NULL) + { + strDir = screenshotSetting->GetValue(); + if (strDir.empty()) + { + if (CGUIControlButtonSetting::GetPath(screenshotSetting)) + strDir = screenshotSetting->GetValue(); + } + } + if (strDir.IsEmpty()) { strDir = "special://temp/"; @@ -231,7 +244,17 @@ void CScreenShot::TakeScreenshot() screenShots.push_back(file); if (promptUser) { // grab the real directory - CStdString newDir = g_guiSettings.GetString("debug.screenshotpath"); + CStdString newDir; + if (screenshotSetting != NULL) + { + newDir = screenshotSetting->GetValue(); + if (newDir.empty()) + { + if (CGUIControlButtonSetting::GetPath(screenshotSetting)) + newDir = screenshotSetting->GetValue(); + } + } + if (!newDir.IsEmpty()) { for (unsigned int i = 0; i < screenShots.size(); i++) diff --git a/xbmc/utils/URIUtils.cpp b/xbmc/utils/URIUtils.cpp index 3392fe9689..11e520da38 100644 --- a/xbmc/utils/URIUtils.cpp +++ b/xbmc/utils/URIUtils.cpp @@ -28,6 +28,7 @@ #include "filesystem/StackDirectory.h" #include "network/DNSNameCache.h" #include "settings/AdvancedSettings.h" +#include "settings/MediaSettings.h" #include "URL.h" #include "StringUtils.h" @@ -931,24 +932,21 @@ bool URIUtils::CompareWithoutSlashAtEnd(const CStdString& strPath1, const CStdSt return strc1.Equals(strc2); } -void URIUtils::AddFileToFolder(const CStdString& strFolder, - const CStdString& strFile, - CStdString& strResult) +CStdString URIUtils::AddFileToFolder(const CStdString& strFolder, + const CStdString& strFile) { if (IsURL(strFolder)) { CURL url(strFolder); if (url.GetFileName() != strFolder) { - AddFileToFolder(url.GetFileName(), strFile, strResult); - url.SetFileName(strResult); - strResult = url.Get(); - return; + url.SetFileName(AddFileToFolder(url.GetFileName(), strFile)); + return url.Get(); } } - strResult = strFolder; - if(!strResult.IsEmpty()) + CStdString strResult = strFolder; + if (!strResult.IsEmpty()) AddSlashAtEnd(strResult); // Remove any slash at the start of the file @@ -962,6 +960,8 @@ void URIUtils::AddFileToFolder(const CStdString& strFolder, strResult.Replace('\\', '/'); else strResult.Replace('/', '\\'); + + return strResult; } CStdString URIUtils::GetDirectory(const CStdString &filePath) diff --git a/xbmc/utils/URIUtils.h b/xbmc/utils/URIUtils.h index 9cd7a4afe6..0987aae343 100644 --- a/xbmc/utils/URIUtils.h +++ b/xbmc/utils/URIUtils.h @@ -107,15 +107,7 @@ public: const CStdString& strFilePathInArchive, const CStdString& strPwd=""); - static void AddFileToFolder(const CStdString& strFolder, - const CStdString& strFile, CStdString& strResult); - static CStdString AddFileToFolder(const CStdString &strFolder, - const CStdString &strFile) - { - CStdString result; - AddFileToFolder(strFolder, strFile, result); - return result; - } + static CStdString AddFileToFolder(const CStdString &strFolder, const CStdString &strFile); static bool ProtocolHasParentInHostname(const CStdString& prot); static bool ProtocolHasEncodedHostname(const CStdString& prot); diff --git a/xbmc/utils/Variant.cpp b/xbmc/utils/Variant.cpp index 369503f459..bf3b41cd5c 100644 --- a/xbmc/utils/Variant.cpp +++ b/xbmc/utils/Variant.cpp @@ -24,6 +24,20 @@ #include "Variant.h" +#ifndef strtoll +#ifdef TARGET_WINDOWS +#define strtoll _strtoi64 +#define strtoull _strtoui64 +#define wcstoll _wcstoi64 +#define wcstoull _wcstoui64 +#else // TARGET_WINDOWS +#define strtoll(str, endptr, base) (int64_t)strtod(str, endptr) +#define strtoull(str, endptr, base) (uint64_t)strtod(str, endptr) +#define wcstoll(str, endptr, base) (int64_t)wcstod(str, endptr) +#define wcstoull(str, endptr, base) (uint64_t)wcstod(str, endptr) +#endif // TARGET_WINDOWS +#endif // strtoll + using namespace std; string trimRight(const string &str) @@ -51,7 +65,7 @@ wstring trimRight(const wstring &str) int64_t str2int64(const string &str, int64_t fallback /* = 0 */) { char *end = NULL; - int64_t result = strtol(trimRight(str).c_str(), &end, 0); + int64_t result = strtoll(trimRight(str).c_str(), &end, 0); if (end == NULL || *end == '\0') return result; @@ -61,7 +75,7 @@ int64_t str2int64(const string &str, int64_t fallback /* = 0 */) int64_t str2int64(const wstring &str, int64_t fallback /* = 0 */) { wchar_t *end = NULL; - int64_t result = wcstol(trimRight(str).c_str(), &end, 0); + int64_t result = wcstoll(trimRight(str).c_str(), &end, 0); if (end == NULL || *end == '\0') return result; @@ -71,7 +85,7 @@ int64_t str2int64(const wstring &str, int64_t fallback /* = 0 */) uint64_t str2uint64(const string &str, uint64_t fallback /* = 0 */) { char *end = NULL; - uint64_t result = strtoul(trimRight(str).c_str(), &end, 0); + uint64_t result = strtoull(trimRight(str).c_str(), &end, 0); if (end == NULL || *end == '\0') return result; @@ -81,7 +95,7 @@ uint64_t str2uint64(const string &str, uint64_t fallback /* = 0 */) uint64_t str2uint64(const wstring &str, uint64_t fallback /* = 0 */) { wchar_t *end = NULL; - uint64_t result = wcstoul(trimRight(str).c_str(), &end, 0); + uint64_t result = wcstoull(trimRight(str).c_str(), &end, 0); if (end == NULL || *end == '\0') return result; diff --git a/xbmc/utils/Weather.cpp b/xbmc/utils/Weather.cpp index 19d0039217..a0c882d4ff 100644 --- a/xbmc/utils/Weather.cpp +++ b/xbmc/utils/Weather.cpp @@ -28,7 +28,6 @@ #include "Temperature.h" #include "network/Network.h" #include "Application.h" -#include "settings/GUISettings.h" #include "settings/Settings.h" #include "guilib/GUIWindowManager.h" #include "GUIUserMessages.h" @@ -43,6 +42,7 @@ #include "addons/AddonManager.h" #include "interfaces/python/XBPython.h" #include "CharsetConverter.h" +#include "addons/GUIDialogAddonSettings.h" using namespace std; using namespace ADDON; @@ -80,7 +80,7 @@ bool CWeatherJob::DoWork() return false; AddonPtr addon; - if (!ADDON::CAddonMgr::Get().GetAddon(g_guiSettings.GetString("weather.addon"), addon, ADDON_SCRIPT_WEATHER)) + if (!ADDON::CAddonMgr::Get().GetAddon(CSettings::Get().GetString("weather.addon"), addon, ADDON_SCRIPT_WEATHER)) return false; // initialize our sys.argv variables @@ -458,8 +458,8 @@ const day_forecast &CWeather::GetForecast(int day) const */ void CWeather::SetArea(int iLocation) { - g_guiSettings.SetInt("weather.currentlocation", iLocation); - g_settings.Save(); + CSettings::Get().SetInt("weather.currentlocation", iLocation); + CSettings::Get().Save(); } /*! @@ -468,7 +468,7 @@ void CWeather::SetArea(int iLocation) */ int CWeather::GetArea() const { - return g_guiSettings.GetInt("weather.currentlocation"); + return CSettings::Get().GetInt("weather.currentlocation"); } CJob *CWeather::GetJob() const @@ -481,3 +481,31 @@ void CWeather::OnJobComplete(unsigned int jobID, bool success, CJob *job) m_info = ((CWeatherJob *)job)->GetInfo(); CInfoLoader::OnJobComplete(jobID, success, job); } + +void CWeather::OnSettingChanged(const CSetting *setting) +{ + if (setting == NULL) + return; + + const std::string settingId = setting->GetId(); + if (settingId == "weather.addon") + Refresh(); +} + +void CWeather::OnSettingAction(const CSetting *setting) +{ + if (setting == NULL) + return; + + const std::string settingId = setting->GetId(); + if (settingId == "weather.addonsettings") + { + AddonPtr addon; + if (CAddonMgr::Get().GetAddon(CSettings::Get().GetString("weather.addon"), addon, ADDON_SCRIPT_WEATHER) && addon != NULL) + { // TODO: maybe have ShowAndGetInput return a bool if settings changed, then only reset weather if true. + CGUIDialogAddonSettings::ShowAndGetInput(addon); + Refresh(); + } + } +} + diff --git a/xbmc/utils/Weather.h b/xbmc/utils/Weather.h index 43b0472026..4043e8b082 100644 --- a/xbmc/utils/Weather.h +++ b/xbmc/utils/Weather.h @@ -22,6 +22,7 @@ #include "InfoLoader.h" #include "StdString.h" +#include "settings/ISettingCallback.h" #include "utils/GlobalsHandling.h" #include <map> @@ -138,7 +139,8 @@ private: static bool m_imagesOkay; }; -class CWeather : public CInfoLoader +class CWeather : public CInfoLoader, + public ISettingCallback { public: CWeather(void); @@ -159,6 +161,9 @@ protected: virtual CStdString BusyInfo(int info) const; virtual void OnJobComplete(unsigned int jobID, bool success, CJob *job); + virtual void OnSettingChanged(const CSetting *setting); + virtual void OnSettingAction(const CSetting *setting); + private: CWeatherInfo m_info; diff --git a/xbmc/utils/XBMCTinyXML.h b/xbmc/utils/XBMCTinyXML.h index 88726b4a0b..cf8c18a34d 100644 --- a/xbmc/utils/XBMCTinyXML.h +++ b/xbmc/utils/XBMCTinyXML.h @@ -54,7 +54,7 @@ #undef ELEMENT #undef COMMENT #undef UNKNOWN -#undef TEXT +//#undef TEXT #undef DECLARATION #undef TYPECOUNT diff --git a/xbmc/utils/log.cpp b/xbmc/utils/log.cpp index da6de6dd94..17820ac6a0 100644 --- a/xbmc/utils/log.cpp +++ b/xbmc/utils/log.cpp @@ -38,6 +38,7 @@ #define m_repeatLogLevel XBMC_GLOBAL_USE(CLog::CLogGlobals).m_repeatLogLevel #define m_repeatLine XBMC_GLOBAL_USE(CLog::CLogGlobals).m_repeatLine #define m_logLevel XBMC_GLOBAL_USE(CLog::CLogGlobals).m_logLevel +#define m_extraLogLevels XBMC_GLOBAL_USE(CLog::CLogGlobals).m_extraLogLevels static char levelNames[][8] = {"DEBUG", "INFO", "NOTICE", "WARNING", "ERROR", "SEVERE", "FATAL", "NONE"}; @@ -64,6 +65,8 @@ void CLog::Log(int loglevel, const char *format, ... ) { static const char* prefixFormat = "%02.2d:%02.2d:%02.2d T:%"PRIu64" %7s: "; CSingleLock waitLock(critSec); + int extras = (loglevel >> LOGMASKBIT) << LOGMASKBIT; + loglevel = loglevel & LOGMASK; #if !(defined(_DEBUG) || defined(PROFILE)) if (m_logLevel > LOG_LEVEL_NORMAL || (m_logLevel > LOG_LEVEL_NONE && loglevel >= LOGNOTICE)) @@ -72,6 +75,9 @@ void CLog::Log(int loglevel, const char *format, ... ) if (!m_file) return; + if (extras != 0 && (m_extraLogLevels & extras) == 0) + return; + SYSTEMTIME time; GetLocalTime(&time); @@ -139,8 +145,8 @@ bool CLog::Init(const char* path) CSingleLock waitLock(critSec); if (!m_file) { - // g_advancedSettings.m_logFolder is initialized in the CSettings constructor - // and changed in CApplication::Create() + // the log folder location is initialized in the CAdvancedSettings + // constructor and changed in CApplication::Create() CStdString strLogFile, strLogFileOld; strLogFile.Format("%sxbmc.log", path); @@ -218,6 +224,12 @@ int CLog::GetLogLevel() return m_logLevel; } +void CLog::SetExtraLogLevels(int level) +{ + CSingleLock waitLock(critSec); + m_extraLogLevels = level; +} + void CLog::OutputDebugString(const std::string& line) { #if defined(_DEBUG) || defined(PROFILE) diff --git a/xbmc/utils/log.h b/xbmc/utils/log.h index 7ce4cb70ea..eccad11a26 100644 --- a/xbmc/utils/log.h +++ b/xbmc/utils/log.h @@ -46,6 +46,7 @@ public: int m_repeatLogLevel; std::string m_repeatLine; int m_logLevel; + int m_extraLogLevels; CCriticalSection critSec; }; @@ -57,6 +58,7 @@ public: static bool Init(const char* path); static void SetLogLevel(int level); static int GetLogLevel(); + static void SetExtraLogLevels(int level); private: static void OutputDebugString(const std::string& line); }; diff --git a/xbmc/utils/test/TestCharsetConverter.cpp b/xbmc/utils/test/TestCharsetConverter.cpp index 5c21ad609a..134315fb71 100644 --- a/xbmc/utils/test/TestCharsetConverter.cpp +++ b/xbmc/utils/test/TestCharsetConverter.cpp @@ -18,7 +18,7 @@ * */ -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "utils/CharsetConverter.h" #include "gtest/gtest.h" @@ -83,19 +83,21 @@ protected: /* Add default settings for locale. * Settings here are taken from CGUISettings::Initialize() */ - CSettingsCategory *loc = g_guiSettings.AddCategory(7, "locale", 14090); - g_guiSettings.AddString(loc, "locale.language",248,"english", + /* TODO + CSettingsCategory *loc = CSettings::Get().AddCategory(7, "locale", 14090); + CSettings::Get().AddString(loc, "locale.language",248,"english", SPIN_CONTROL_TEXT); - g_guiSettings.AddString(loc, "locale.country", 20026, "USA", + CSettings::Get().AddString(loc, "locale.country", 20026, "USA", SPIN_CONTROL_TEXT); - g_guiSettings.AddString(loc, "locale.charset", 14091, "DEFAULT", + CSettings::Get().AddString(loc, "locale.charset", 14091, "DEFAULT", SPIN_CONTROL_TEXT); // charset is set by the // language file - /* Add default settings for subtitles */ - CSettingsCategory *sub = g_guiSettings.AddCategory(5, "subtitles", 287); - g_guiSettings.AddString(sub, "subtitles.charset", 735, "DEFAULT", + // Add default settings for subtitles + CSettingsCategory *sub = CSettings::Get().AddCategory(5, "subtitles", 287); + CSettings::Get().AddString(sub, "subtitles.charset", 735, "DEFAULT", SPIN_CONTROL_TEXT); + */ g_charsetConverter.reset(); g_charsetConverter.clear(); @@ -103,7 +105,7 @@ protected: ~TestCharsetConverter() { - g_guiSettings.Clear(); + CSettings::Get().Unload(); } CStdStringA refstra1, refstra2, varstra1; diff --git a/xbmc/utils/test/TestDownloadQueue.cpp b/xbmc/utils/test/TestDownloadQueue.cpp index 69387286b2..220448f588 100644 --- a/xbmc/utils/test/TestDownloadQueue.cpp +++ b/xbmc/utils/test/TestDownloadQueue.cpp @@ -20,7 +20,7 @@ #include "utils/DownloadQueue.h" #include "threads/Thread.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "test/TestUtils.h" #include "gtest/gtest.h" @@ -40,23 +40,23 @@ class TestDownloadQueue : public testing::Test protected: TestDownloadQueue() { - CSettingsCategory* net = g_guiSettings.AddCategory(4, "network", 798); - g_guiSettings.AddBool(net, "network.usehttpproxy", 708, false); - g_guiSettings.AddString(net, "network.httpproxyserver", 706, "", + CSettingsCategory* net = CSettings::Get().AddCategory(4, "network", 798); + CSettings::Get().AddBool(net, "network.usehttpproxy", 708, false); + CSettings::Get().AddString(net, "network.httpproxyserver", 706, "", EDIT_CONTROL_INPUT); - g_guiSettings.AddString(net, "network.httpproxyport", 730, "8080", + CSettings::Get().AddString(net, "network.httpproxyport", 730, "8080", EDIT_CONTROL_NUMBER_INPUT, false, 707); - g_guiSettings.AddString(net, "network.httpproxyusername", 1048, "", + CSettings::Get().AddString(net, "network.httpproxyusername", 1048, "", EDIT_CONTROL_INPUT); - g_guiSettings.AddString(net, "network.httpproxypassword", 733, "", + CSettings::Get().AddString(net, "network.httpproxypassword", 733, "", EDIT_CONTROL_HIDDEN_INPUT,true,733); - g_guiSettings.AddInt(net, "network.bandwidth", 14041, 0, 0, 512, 100*1024, + CSettings::Get().AddInt(net, "network.bandwidth", 14041, 0, 0, 512, 100*1024, SPIN_CONTROL_INT_PLUS, 14048, 351); } ~TestDownloadQueue() { - g_guiSettings.Clear(); + CSettings::Get().Clear(); } }; diff --git a/xbmc/utils/test/TestDownloadQueueManager.cpp b/xbmc/utils/test/TestDownloadQueueManager.cpp index c137c5bfc2..aa8c2e024f 100644 --- a/xbmc/utils/test/TestDownloadQueueManager.cpp +++ b/xbmc/utils/test/TestDownloadQueueManager.cpp @@ -20,7 +20,7 @@ #include "utils/DownloadQueueManager.h" #include "threads/Thread.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "test/TestUtils.h" #include "gtest/gtest.h" @@ -40,23 +40,25 @@ class TestDownloadQueueManager : public testing::Test protected: TestDownloadQueueManager() { - CSettingsCategory* net = g_guiSettings.AddCategory(4, "network", 798); - g_guiSettings.AddBool(net, "network.usehttpproxy", 708, false); - g_guiSettings.AddString(net, "network.httpproxyserver", 706, "", + /* TODO + CSettingsCategory* net = CSettings::Get().AddCategory(4, "network", 798); + CSettings::Get().AddBool(net, "network.usehttpproxy", 708, false); + CSettings::Get().AddString(net, "network.httpproxyserver", 706, "", EDIT_CONTROL_INPUT); - g_guiSettings.AddString(net, "network.httpproxyport", 730, "8080", + CSettings::Get().AddString(net, "network.httpproxyport", 730, "8080", EDIT_CONTROL_NUMBER_INPUT, false, 707); - g_guiSettings.AddString(net, "network.httpproxyusername", 1048, "", + CSettings::Get().AddString(net, "network.httpproxyusername", 1048, "", EDIT_CONTROL_INPUT); - g_guiSettings.AddString(net, "network.httpproxypassword", 733, "", + CSettings::Get().AddString(net, "network.httpproxypassword", 733, "", EDIT_CONTROL_HIDDEN_INPUT,true,733); - g_guiSettings.AddInt(net, "network.bandwidth", 14041, 0, 0, 512, 100*1024, + CSettings::Get().AddInt(net, "network.bandwidth", 14041, 0, 0, 512, 100*1024, SPIN_CONTROL_INT_PLUS, 14048, 351); + */ } ~TestDownloadQueueManager() { - g_guiSettings.Clear(); + CSettings::Get().Unload(); } }; diff --git a/xbmc/utils/test/TestJobManager.cpp b/xbmc/utils/test/TestJobManager.cpp index bf77c97175..197ad3077d 100644 --- a/xbmc/utils/test/TestJobManager.cpp +++ b/xbmc/utils/test/TestJobManager.cpp @@ -19,7 +19,7 @@ */ #include "utils/JobManager.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "utils/SystemInfo.h" #include "gtest/gtest.h" @@ -30,23 +30,25 @@ class TestJobManager : public testing::Test protected: TestJobManager() { - CSettingsCategory* net = g_guiSettings.AddCategory(4, "network", 798); - g_guiSettings.AddBool(net, "network.usehttpproxy", 708, false); - g_guiSettings.AddString(net, "network.httpproxyserver", 706, "", + /* TODO + CSettingsCategory* net = CSettings::Get().AddCategory(4, "network", 798); + CSettings::Get().AddBool(net, "network.usehttpproxy", 708, false); + CSettings::Get().AddString(net, "network.httpproxyserver", 706, "", EDIT_CONTROL_INPUT); - g_guiSettings.AddString(net, "network.httpproxyport", 730, "8080", + CSettings::Get().AddString(net, "network.httpproxyport", 730, "8080", EDIT_CONTROL_NUMBER_INPUT, false, 707); - g_guiSettings.AddString(net, "network.httpproxyusername", 1048, "", + CSettings::Get().AddString(net, "network.httpproxyusername", 1048, "", EDIT_CONTROL_INPUT); - g_guiSettings.AddString(net, "network.httpproxypassword", 733, "", + CSettings::Get().AddString(net, "network.httpproxypassword", 733, "", EDIT_CONTROL_HIDDEN_INPUT,true,733); - g_guiSettings.AddInt(net, "network.bandwidth", 14041, 0, 0, 512, 100*1024, + CSettings::Get().AddInt(net, "network.bandwidth", 14041, 0, 0, 512, 100*1024, SPIN_CONTROL_INT_PLUS, 14048, 351); + */ } ~TestJobManager() { - g_guiSettings.Clear(); + CSettings::Get().Unload(); } }; diff --git a/xbmc/utils/test/TestLabelFormatter.cpp b/xbmc/utils/test/TestLabelFormatter.cpp index e0e67b88c5..b21c2b9465 100644 --- a/xbmc/utils/test/TestLabelFormatter.cpp +++ b/xbmc/utils/test/TestLabelFormatter.cpp @@ -20,7 +20,7 @@ #include "utils/LabelFormatter.h" #include "filesystem/File.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "FileItem.h" #include "test/TestUtils.h" @@ -33,18 +33,20 @@ class TestLabelFormatter : public testing::Test protected: TestLabelFormatter() { - CSettingsCategory* fl = g_guiSettings.AddCategory(7, "filelists", 14081); - g_guiSettings.AddBool(fl, "filelists.showparentdiritems", 13306, true); - g_guiSettings.AddBool(fl, "filelists.showextensions", 497, true); - g_guiSettings.AddBool(fl, "filelists.ignorethewhensorting", 13399, true); - g_guiSettings.AddBool(fl, "filelists.allowfiledeletion", 14071, false); - g_guiSettings.AddBool(fl, "filelists.showaddsourcebuttons", 21382, true); - g_guiSettings.AddBool(fl, "filelists.showhidden", 21330, false); + /* TODO + CSettingsCategory* fl = CSettings::Get().AddCategory(7, "filelists", 14081); + CSettings::Get().AddBool(fl, "filelists.showparentdiritems", 13306, true); + CSettings::Get().AddBool(fl, "filelists.showextensions", 497, true); + CSettings::Get().AddBool(fl, "filelists.ignorethewhensorting", 13399, true); + CSettings::Get().AddBool(fl, "filelists.allowfiledeletion", 14071, false); + CSettings::Get().AddBool(fl, "filelists.showaddsourcebuttons", 21382, true); + CSettings::Get().AddBool(fl, "filelists.showhidden", 21330, false); + */ } ~TestLabelFormatter() { - g_guiSettings.Clear(); + CSettings::Get().Unload(); } }; diff --git a/xbmc/utils/test/TestSystemInfo.cpp b/xbmc/utils/test/TestSystemInfo.cpp index 628539b609..c8a92fb9cf 100644 --- a/xbmc/utils/test/TestSystemInfo.cpp +++ b/xbmc/utils/test/TestSystemInfo.cpp @@ -19,7 +19,7 @@ */ #include "utils/SystemInfo.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "GUIInfoManager.h" #include "gtest/gtest.h" @@ -29,22 +29,22 @@ class TestSystemInfo : public testing::Test protected: TestSystemInfo() { - CSettingsCategory* net = g_guiSettings.AddCategory(4, "network", 798); - g_guiSettings.AddBool(net, "network.usehttpproxy", 708, false); - g_guiSettings.AddString(net, "network.httpproxyserver", 706, "", + CSettingsCategory* net = CSettings::Get().AddCategory(4, "network", 798); + CSettings::Get().AddBool(net, "network.usehttpproxy", 708, false); + CSettings::Get().AddString(net, "network.httpproxyserver", 706, "", EDIT_CONTROL_INPUT); - g_guiSettings.AddString(net, "network.httpproxyport", 730, "8080", + CSettings::Get().AddString(net, "network.httpproxyport", 730, "8080", EDIT_CONTROL_NUMBER_INPUT, false, 707); - g_guiSettings.AddString(net, "network.httpproxyusername", 1048, "", + CSettings::Get().AddString(net, "network.httpproxyusername", 1048, "", EDIT_CONTROL_INPUT); - g_guiSettings.AddString(net, "network.httpproxypassword", 733, "", + CSettings::Get().AddString(net, "network.httpproxypassword", 733, "", EDIT_CONTROL_HIDDEN_INPUT,true,733); - g_guiSettings.AddInt(net, "network.bandwidth", 14041, 0, 0, 512, 100*1024, + CSettings::Get().AddInt(net, "network.bandwidth", 14041, 0, 0, 512, 100*1024, SPIN_CONTROL_INT_PLUS, 14048, 351); } ~TestSystemInfo() { - g_guiSettings.Clear(); + CSettings::Get().Clear(); } }; diff --git a/xbmc/utils/test/TestURIUtils.cpp b/xbmc/utils/test/TestURIUtils.cpp index 548af27503..4a551d243d 100644 --- a/xbmc/utils/test/TestURIUtils.cpp +++ b/xbmc/utils/test/TestURIUtils.cpp @@ -85,7 +85,7 @@ TEST_F(TestURIUtils, RemoveExtension) { CStdString ref, var; - /* NOTE: g_settings need to be set to find other extensions. */ + /* NOTE: CSettings need to be set to find other extensions. */ ref = "/path/to/file"; var = "/path/to/file.xml"; URIUtils::RemoveExtension(var); @@ -450,14 +450,8 @@ TEST_F(TestURIUtils, CreateArchivePath) TEST_F(TestURIUtils, AddFileToFolder) { - CStdString ref, var; - - ref = "/path/to/file"; - URIUtils::AddFileToFolder("/path/to", "file", var); - EXPECT_STREQ(ref.c_str(), var.c_str()); - - var.clear(); - var = URIUtils::AddFileToFolder("/path/to", "file"); + CStdString ref = "/path/to/file"; + CStdString var = URIUtils::AddFileToFolder("/path/to", "file"); EXPECT_STREQ(ref.c_str(), var.c_str()); } diff --git a/xbmc/video/GUIViewStateVideo.cpp b/xbmc/video/GUIViewStateVideo.cpp index 5185bda285..4c0df1ff24 100644 --- a/xbmc/video/GUIViewStateVideo.cpp +++ b/xbmc/video/GUIViewStateVideo.cpp @@ -25,10 +25,10 @@ #include "filesystem/VideoDatabaseDirectory.h" #include "filesystem/Directory.h" #include "VideoDatabase.h" -#include "settings/GUISettings.h" #include "settings/AdvancedSettings.h" #include "settings/MediaSettings.h" #include "settings/MediaSourceSettings.h" +#include "settings/Settings.h" #include "FileItem.h" #include "guilib/WindowIDs.h" #include "guilib/LocalizeStrings.h" @@ -72,15 +72,15 @@ CGUIViewStateWindowVideoFiles::CGUIViewStateWindowVideoFiles(const CFileItemList } else { - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) AddSortMethod(SORT_METHOD_LABEL_IGNORE_THE, 551, LABEL_MASKS("%L", "%I", "%L", "")); // Label, Size | Label, empty else AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS("%L", "%I", "%L", "")); // Label, Size | Label, empty AddSortMethod(SORT_METHOD_SIZE, 553, LABEL_MASKS("%L", "%I", "%L", "%I")); // Label, Size | Label, Size AddSortMethod(SORT_METHOD_DATE, 552, LABEL_MASKS("%L", "%J", "%L", "%J")); // Label, Date | Label, Date AddSortMethod(SORT_METHOD_FILE, 561, LABEL_MASKS("%L", "%I", "%L", "")); // Label, Size | Label, empty - - CViewState *viewState = CViewStateSettings::Get().Get("videofiles"); + + const CViewState *viewState = CViewStateSettings::Get().Get("videofiles"); SetSortMethod(viewState->m_sortMethod); SetViewAsControl(viewState->m_viewMode); SetSortOrder(viewState->m_sortOrder); @@ -138,8 +138,8 @@ CGUIViewStateWindowVideoNav::CGUIViewStateWindowVideoNav(const CFileItemList& it { AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS("%T", "%R", "%L", "")); // Title, Rating | Label, empty SetSortMethod(SORT_METHOD_LABEL); - - CViewState *viewState = CViewStateSettings::Get().Get("videonavactors"); + + const CViewState *viewState = CViewStateSettings::Get().Get("videonavactors"); SetViewAsControl(viewState->m_viewMode); SetSortOrder(viewState->m_sortOrder); } @@ -148,8 +148,8 @@ CGUIViewStateWindowVideoNav::CGUIViewStateWindowVideoNav(const CFileItemList& it { AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS("%T", "%R", "%L", "")); // Title, Rating | Label, empty SetSortMethod(SORT_METHOD_LABEL); - - CViewState *viewState = CViewStateSettings::Get().Get("videonavyears"); + + const CViewState *viewState = CViewStateSettings::Get().Get("videonavyears"); SetViewAsControl(viewState->m_viewMode); SetSortOrder(viewState->m_sortOrder); } @@ -158,15 +158,15 @@ CGUIViewStateWindowVideoNav::CGUIViewStateWindowVideoNav(const CFileItemList& it { AddSortMethod(SORT_METHOD_VIDEO_SORT_TITLE, 556, LABEL_MASKS("%L", "","%L","")); // Label, empty | Label, empty SetSortMethod(SORT_METHOD_VIDEO_SORT_TITLE); - - CViewState *viewState = CViewStateSettings::Get().Get("videonavseasons"); + + const CViewState *viewState = CViewStateSettings::Get().Get("videonavseasons"); SetViewAsControl(viewState->m_viewMode); SetSortOrder(viewState->m_sortOrder); } break; case NODE_TYPE_TITLE_TVSHOWS: { - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) AddSortMethod(SORT_METHOD_VIDEO_SORT_TITLE_IGNORE_THE, 556, LABEL_MASKS("%T", "%M", "%T", "%M")); // Title, #Episodes | Title, #Episodes else AddSortMethod(SORT_METHOD_VIDEO_SORT_TITLE, 556, LABEL_MASKS("%T", "%M", "%T", "%M")); // Title, #Episodes | Title, #Episodes @@ -176,8 +176,8 @@ CGUIViewStateWindowVideoNav::CGUIViewStateWindowVideoNav(const CFileItemList& it AddSortMethod(SORT_METHOD_LASTPLAYED, 568, LABEL_MASKS("%T", "%p", "%T", "%p")); // Title, #Last played | Title, #Last played AddSortMethod(SORT_METHOD_YEAR, 562, LABEL_MASKS("%L","%Y","%L","%Y")); // Label, Year | Label, Year SetSortMethod(SORT_METHOD_LABEL); - - CViewState *viewState = CViewStateSettings::Get().Get("videonavtvshows"); + + const CViewState *viewState = CViewStateSettings::Get().Get("videonavtvshows"); SetViewAsControl(viewState->m_viewMode); SetSortOrder(viewState->m_sortOrder); } @@ -189,15 +189,15 @@ CGUIViewStateWindowVideoNav::CGUIViewStateWindowVideoNav(const CFileItemList& it { AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS("%T", "%R", "%L", "")); // Title, Rating | Label, empty SetSortMethod(SORT_METHOD_LABEL); - - CViewState *viewState = CViewStateSettings::Get().Get("videonavgenres"); + + const CViewState *viewState = CViewStateSettings::Get().Get("videonavgenres"); SetViewAsControl(viewState->m_viewMode); SetSortOrder(viewState->m_sortOrder); } break; case NODE_TYPE_SETS: { - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) AddSortMethod(SORT_METHOD_LABEL_IGNORE_THE, 551, LABEL_MASKS("%T","%R", "%T","%R")); // Title, Rating | Title, Rating else AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS("%T", "%R", "%T","%R")); // Title, Rating | Title, Rating @@ -210,8 +210,8 @@ CGUIViewStateWindowVideoNav::CGUIViewStateWindowVideoNav(const CFileItemList& it AddSortMethod(SORT_METHOD_PLAYCOUNT, 567, LABEL_MASKS("%T", "%V", "%T", "%V")); // Title, Playcount | Title, Playcount SetSortMethod(SORT_METHOD_LABEL_IGNORE_THE); - - CViewState *viewState = CViewStateSettings::Get().Get("videonavgenres"); + + const CViewState *viewState = CViewStateSettings::Get().Get("videonavgenres"); SetViewAsControl(viewState->m_viewMode); SetSortOrder(viewState->m_sortOrder); } @@ -219,13 +219,13 @@ CGUIViewStateWindowVideoNav::CGUIViewStateWindowVideoNav(const CFileItemList& it case NODE_TYPE_TAGS: { SORT_METHOD method = SORT_METHOD_LABEL_IGNORE_THE; - if (!g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (!CSettings::Get().GetBool("filelists.ignorethewhensorting")) method = SORT_METHOD_LABEL; AddSortMethod(method, 551, LABEL_MASKS("%T","", "%T","")); // Title, empty | Title, empty SetSortMethod(method); - - CViewState *viewState = CViewStateSettings::Get().Get("videonavgenres"); + + const CViewState *viewState = CViewStateSettings::Get().Get("videonavgenres"); SetViewAsControl(viewState->m_viewMode); SetSortOrder(viewState->m_sortOrder); } @@ -254,12 +254,12 @@ CGUIViewStateWindowVideoNav::CGUIViewStateWindowVideoNav(const CFileItemList& it if (CMediaSettings::Get().GetWatchedMode(items.GetContent()) == WatchedModeAll) AddSortMethod(SORT_METHOD_PLAYCOUNT, 567, LABEL_MASKS("%H. %T", "%V")); // Order. Title, Playcount | empty, empty } - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) AddSortMethod(SORT_METHOD_LABEL_IGNORE_THE, 551, LABEL_MASKS("%T","%R")); // Title, Rating | empty, empty else AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS("%T", "%R")); // Title, Rating | empty, empty - - CViewState *viewState = CViewStateSettings::Get().Get("videonavepisodes"); + + const CViewState *viewState = CViewStateSettings::Get().Get("videonavepisodes"); SetSortMethod(viewState->m_sortMethod); SetViewAsControl(viewState->m_viewMode); SetSortOrder(viewState->m_sortOrder); @@ -281,14 +281,14 @@ CGUIViewStateWindowVideoNav::CGUIViewStateWindowVideoNav(const CFileItemList& it { AddSortMethod(SORT_METHOD_YEAR, 562, LABEL_MASKS("%T", "%Y")); // Title, Year | empty, empty - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) AddSortMethod(SORT_METHOD_VIDEO_SORT_TITLE_IGNORE_THE, 556, LABEL_MASKS("%T", "%R")); // Title, Rating | empty, empty else AddSortMethod(SORT_METHOD_VIDEO_SORT_TITLE, 556, LABEL_MASKS("%T", "%R")); // Title, Rating | empty, empty } else { - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) AddSortMethod(SORT_METHOD_VIDEO_SORT_TITLE_IGNORE_THE, 556, LABEL_MASKS("%T", "%R", "%T", "%R")); // Title, Rating | Title, Rating else AddSortMethod(SORT_METHOD_VIDEO_SORT_TITLE, 556, LABEL_MASKS("%T", "%R", "%T", "%R")); // Title, Rating | Title, Rating @@ -302,8 +302,8 @@ CGUIViewStateWindowVideoNav::CGUIViewStateWindowVideoNav(const CFileItemList& it if (CMediaSettings::Get().GetWatchedMode(items.GetContent()) == WatchedModeAll) AddSortMethod(SORT_METHOD_PLAYCOUNT, 567, LABEL_MASKS("%T", "%V", "%T", "%V")); // Title, Playcount | Title, Playcount - - CViewState *viewState = CViewStateSettings::Get().Get("videonavtitles"); + + const CViewState *viewState = CViewStateSettings::Get().Get("videonavtitles"); if (params.GetSetId() > -1) SetSortMethod(SORT_METHOD_YEAR); else @@ -315,13 +315,13 @@ CGUIViewStateWindowVideoNav::CGUIViewStateWindowVideoNav(const CFileItemList& it break; case NODE_TYPE_TITLE_MUSICVIDEOS: { - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) AddSortMethod(SORT_METHOD_LABEL_IGNORE_THE, 551, LABEL_MASKS("%T", "%Y")); // Title, Year | empty, empty else AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS("%T", "%Y")); // Title, Year | empty, empty AddSortMethod(SORT_METHOD_MPAA_RATING, 20074, LABEL_MASKS("%T", "%O")); AddSortMethod(SORT_METHOD_YEAR, 562, LABEL_MASKS("%T", "%Y")); // Title, Year | empty, empty - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) { AddSortMethod(SORT_METHOD_ARTIST_IGNORE_THE, 557, LABEL_MASKS("%A - %T", "%Y")); // Artist - Title, Year | empty, empty AddSortMethod(SORT_METHOD_ALBUM_IGNORE_THE, 558, LABEL_MASKS("%B - %T", "%Y")); // Album - Title, Year | empty, empty @@ -335,11 +335,11 @@ CGUIViewStateWindowVideoNav::CGUIViewStateWindowVideoNav(const CFileItemList& it if (CMediaSettings::Get().GetWatchedMode(items.GetContent()) == WatchedModeAll) AddSortMethod(SORT_METHOD_PLAYCOUNT, 567, LABEL_MASKS("%T", "%V")); // Title, Playcount | empty, empty - CStdString strTrackLeft=g_guiSettings.GetString("musicfiles.trackformat"); - CStdString strTrackRight=g_guiSettings.GetString("musicfiles.trackformatright"); + CStdString strTrackLeft=CSettings::Get().GetString("musicfiles.trackformat"); + CStdString strTrackRight=CSettings::Get().GetString("musicfiles.trackformatright"); AddSortMethod(SORT_METHOD_TRACKNUM, 554, LABEL_MASKS(strTrackLeft, strTrackRight)); // Userdefined, Userdefined | empty, empty - - CViewState *viewState = CViewStateSettings::Get().Get("videonavmusicvideos"); + + const CViewState *viewState = CViewStateSettings::Get().Get("videonavmusicvideos"); SetSortMethod(viewState->m_sortMethod); SetViewAsControl(viewState->m_viewMode); SetSortOrder(viewState->m_sortOrder); @@ -371,15 +371,15 @@ CGUIViewStateWindowVideoNav::CGUIViewStateWindowVideoNav(const CFileItemList& it } else { - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) AddSortMethod(SORT_METHOD_LABEL_IGNORE_THE, 551, LABEL_MASKS("%L", "%I", "%L", "")); // Label, Size | Label, empty else AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS("%L", "%I", "%L", "")); // Label, Size | Label, empty AddSortMethod(SORT_METHOD_SIZE, 553, LABEL_MASKS("%L", "%I", "%L", "%I")); // Label, Size | Label, Size AddSortMethod(SORT_METHOD_DATE, 552, LABEL_MASKS("%L", "%J", "%L", "%J")); // Label, Date | Label, Date AddSortMethod(SORT_METHOD_FILE, 561, LABEL_MASKS("%L", "%I", "%L", "")); // Label, Size | Label, empty - - CViewState *viewState = CViewStateSettings::Get().Get("videofiles"); + + const CViewState *viewState = CViewStateSettings::Get().Get("videofiles"); SetSortMethod(viewState->m_sortMethod); SetViewAsControl(viewState->m_viewMode); SetSortOrder(viewState->m_sortOrder); @@ -418,7 +418,7 @@ void CGUIViewStateWindowVideoNav::SaveViewState() SaveViewToDb(m_items.GetPath(), WINDOW_VIDEO_NAV, CViewStateSettings::Get().Get("videonavseasons")); break; case NODE_TYPE_TITLE_MUSICVIDEOS: - SaveViewToDb(m_items.GetPath(), WINDOW_VIDEO_NAV,CViewStateSettings::Get().Get("videonavmusicvideos")); + SaveViewToDb(m_items.GetPath(), WINDOW_VIDEO_NAV, CViewStateSettings::Get().Get("videonavmusicvideos")); break; default: SaveViewToDb(m_items.GetPath(), WINDOW_VIDEO_NAV); @@ -436,7 +436,7 @@ VECSOURCES& CGUIViewStateWindowVideoNav::GetSources() // Setup shares we want to have m_sources.clear(); CFileItemList items; - if (g_guiSettings.GetBool("myvideos.flatten")) + if (CSettings::Get().GetBool("myvideos.flatten")) CDirectory::GetDirectory("library://video_flat/", items, ""); else CDirectory::GetDirectory("library://video/", items, ""); @@ -458,9 +458,9 @@ bool CGUIViewStateWindowVideoNav::AutoPlayNextItem() CQueryParams params; CVideoDatabaseDirectory::GetQueryParams(m_items.GetPath(),params); if (params.GetContentType() == VIDEODB_CONTENT_MUSICVIDEOS || params.GetContentType() == 6) // recently added musicvideos - return g_guiSettings.GetBool("musicplayer.autoplaynextitem"); + return CSettings::Get().GetBool("musicplayer.autoplaynextitem"); - return g_guiSettings.GetBool("videoplayer.autoplaynextitem"); + return CSettings::Get().GetBool("videoplayer.autoplaynextitem"); } CGUIViewStateWindowVideoPlaylist::CGUIViewStateWindowVideoPlaylist(const CFileItemList& items) : CGUIViewStateWindowVideo(items) @@ -506,7 +506,7 @@ VECSOURCES& CGUIViewStateWindowVideoPlaylist::GetSources() CGUIViewStateVideoMovies::CGUIViewStateVideoMovies(const CFileItemList& items) : CGUIViewStateWindowVideo(items) { - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) AddSortMethod(SORT_METHOD_VIDEO_SORT_TITLE_IGNORE_THE, 556, LABEL_MASKS("%T", "%R", "%T", "%R")); // Title, Rating | Title, Rating else AddSortMethod(SORT_METHOD_VIDEO_SORT_TITLE, 556, LABEL_MASKS("%T", "%R", "%T", "%R")); // Title, Rating | Title, Rating @@ -514,7 +514,7 @@ CGUIViewStateVideoMovies::CGUIViewStateVideoMovies(const CFileItemList& items) : AddSortMethod(SORT_METHOD_MPAA_RATING, 20074, LABEL_MASKS("%T", "%O")); // Title, MPAA | empty, empty AddSortMethod(SORT_METHOD_YEAR, 562, LABEL_MASKS("%T", "%Y", "%T", "%Y")); // Title, Year | Title, Year - CViewState *viewState = CViewStateSettings::Get().Get("videonavtitles"); + const CViewState *viewState = CViewStateSettings::Get().Get("videonavtitles"); if (items.IsSmartPlayList() || items.GetProperty("library.filter").asBoolean()) AddPlaylistOrder(items, LABEL_MASKS("%T", "%R", "%T", "%R")); // Title, Rating | Title, Rating else @@ -536,13 +536,13 @@ void CGUIViewStateVideoMovies::SaveViewState() CGUIViewStateVideoMusicVideos::CGUIViewStateVideoMusicVideos(const CFileItemList& items) : CGUIViewStateWindowVideo(items) { - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) AddSortMethod(SORT_METHOD_LABEL_IGNORE_THE, 551, LABEL_MASKS("%T", "%Y")); // Title, Year | empty, empty else AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS("%T", "%Y")); // Title, Year | empty, empty AddSortMethod(SORT_METHOD_MPAA_RATING, 20074, LABEL_MASKS("%T", "%O")); AddSortMethod(SORT_METHOD_YEAR, 562, LABEL_MASKS("%T", "%Y")); // Title, Year | empty, empty - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) { AddSortMethod(SORT_METHOD_ARTIST_IGNORE_THE, 557, LABEL_MASKS("%A - %T", "%Y")); // Artist - Title, Year | empty, empty AddSortMethod(SORT_METHOD_ALBUM_IGNORE_THE, 558, LABEL_MASKS("%B - %T", "%Y")); // Album - Title, Year | empty, empty @@ -555,11 +555,11 @@ CGUIViewStateVideoMusicVideos::CGUIViewStateVideoMusicVideos(const CFileItemList AddSortMethod(SORT_METHOD_PLAYCOUNT, 567, LABEL_MASKS("%T", "%V")); // Title, Playcount | empty, empty - CStdString strTrackLeft=g_guiSettings.GetString("musicfiles.trackformat"); - CStdString strTrackRight=g_guiSettings.GetString("musicfiles.trackformatright"); + CStdString strTrackLeft=CSettings::Get().GetString("musicfiles.trackformat"); + CStdString strTrackRight=CSettings::Get().GetString("musicfiles.trackformatright"); AddSortMethod(SORT_METHOD_TRACKNUM, 554, LABEL_MASKS(strTrackLeft, strTrackRight)); // Userdefined, Userdefined | empty, empty - - CViewState *viewState = CViewStateSettings::Get().Get("videonavmusicvideos"); + + const CViewState *viewState = CViewStateSettings::Get().Get("videonavmusicvideos"); if (items.IsSmartPlayList() || items.GetProperty("library.filter").asBoolean()) AddPlaylistOrder(items, LABEL_MASKS("%A - %T", "%Y")); // Artist - Title, Year | empty, empty else @@ -580,13 +580,13 @@ void CGUIViewStateVideoMusicVideos::SaveViewState() CGUIViewStateVideoTVShows::CGUIViewStateVideoTVShows(const CFileItemList& items) : CGUIViewStateWindowVideo(items) { - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) AddSortMethod(SORT_METHOD_VIDEO_SORT_TITLE_IGNORE_THE, 556, LABEL_MASKS("%T", "%M", "%T", "%M")); // Title, #Episodes | Title, #Episodes else AddSortMethod(SORT_METHOD_VIDEO_SORT_TITLE, 556, LABEL_MASKS("%T", "%M", "%T", "%M")); // Title, #Episodes | Title, #Episodes AddSortMethod(SORT_METHOD_YEAR, 562, LABEL_MASKS("%T", "%Y", "%T", "%Y")); // Title, Year | Title, Year - - CViewState *viewState = CViewStateSettings::Get().Get("videonavtvshows"); + + const CViewState *viewState = CViewStateSettings::Get().Get("videonavtvshows"); if (items.IsSmartPlayList() || items.GetProperty("library.filter").asBoolean()) AddPlaylistOrder(items, LABEL_MASKS("%T", "%M", "%T", "%M")); // Title, #Episodes | Title, #Episodes else @@ -608,7 +608,7 @@ void CGUIViewStateVideoTVShows::SaveViewState() CGUIViewStateVideoEpisodes::CGUIViewStateVideoEpisodes(const CFileItemList& items) : CGUIViewStateWindowVideo(items) { - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) AddSortMethod(SORT_METHOD_LABEL_IGNORE_THE, 551, LABEL_MASKS("%Z - %H. %T","%R")); // TvShow - Order. Title, Rating | empty, empty else AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS("%Z - %H. %T", "%R")); // TvShow - Order. Title, Rating | empty, empty @@ -628,8 +628,8 @@ CGUIViewStateVideoEpisodes::CGUIViewStateVideoEpisodes(const CFileItemList& item AddSortMethod(SORT_METHOD_PRODUCTIONCODE, 20368, LABEL_MASKS("%Z - %H. %T","%P")); // TvShow - Order. Title, Production Code | empty, empty AddSortMethod(SORT_METHOD_DATE, 552, LABEL_MASKS("%Z - %H. %T","%J")); // TvShow - Order. Title, Date | empty, empty } - - CViewState *viewState = CViewStateSettings::Get().Get("videonavepisodes"); + + const CViewState *viewState = CViewStateSettings::Get().Get("videonavepisodes"); if (items.IsSmartPlayList() || items.GetProperty("library.filter").asBoolean()) AddPlaylistOrder(items, LABEL_MASKS("%Z - %H. %T", "%R")); // TvShow - Order. Title, Rating | empty, empty else diff --git a/xbmc/video/PlayerController.cpp b/xbmc/video/PlayerController.cpp index d4d8e47d03..87aa34ef7c 100644 --- a/xbmc/video/PlayerController.cpp +++ b/xbmc/video/PlayerController.cpp @@ -21,15 +21,16 @@ #include "PlayerController.h" #include "utils/StdString.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" -#include "settings/MediaSettings.h" #include "settings/DisplaySettings.h" +#include "settings/MediaSettings.h" +#include "settings/Settings.h" #include "cores/IPlayer.h" #include "guilib/Key.h" #include "guilib/LocalizeStrings.h" #include "guilib/GUISliderControl.h" #include "dialogs/GUIDialogKaiToast.h" #include "video/dialogs/GUIDialogAudioSubtitleSettings.h" +#include "video/windows/GUIWindowFullScreen.h" #ifdef HAS_VIDEO_PLAYBACK #include "cores/VideoRenderers/RenderManager.h" #endif @@ -103,7 +104,7 @@ bool CPlayerController::OnAction(const CAction &action) if (CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleOn) { SPlayerSubtitleStreamInfo info; - g_application.m_pPlayer->GetSubtitleStreamInfo(g_application.m_pPlayer->GetSubtitle(), info); + g_application.m_pPlayer->GetSubtitleStreamInfo(CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleStream, info); sub = info.name; if (sub != info.language) sub.Format("%s [%s]", sub.c_str(), info.language.c_str()); @@ -275,7 +276,7 @@ bool CPlayerController::OnAction(const CAction &action) case ACTION_SUBTITLE_VSHIFT_UP: { RESOLUTION_INFO& res_info = CDisplaySettings::Get().GetResolutionInfo(g_graphicsContext.GetVideoResolution()); - int subalign = g_guiSettings.GetInt("subtitles.align"); + int subalign = CSettings::Get().GetInt("subtitles.align"); if ((subalign == SUBTITLE_ALIGN_BOTTOM_OUTSIDE) || (subalign == SUBTITLE_ALIGN_TOP_INSIDE)) { res_info.iSubtitles ++; @@ -301,7 +302,7 @@ bool CPlayerController::OnAction(const CAction &action) case ACTION_SUBTITLE_VSHIFT_DOWN: { RESOLUTION_INFO& res_info = CDisplaySettings::Get().GetResolutionInfo(g_graphicsContext.GetVideoResolution()); - int subalign = g_guiSettings.GetInt("subtitles.align"); + int subalign = CSettings::Get().GetInt("subtitles.align"); if ((subalign == SUBTITLE_ALIGN_BOTTOM_OUTSIDE) || (subalign == SUBTITLE_ALIGN_TOP_INSIDE)) { res_info.iSubtitles--; @@ -327,7 +328,7 @@ bool CPlayerController::OnAction(const CAction &action) case ACTION_SUBTITLE_ALIGN: { RESOLUTION_INFO& res_info = CDisplaySettings::Get().GetResolutionInfo(g_graphicsContext.GetVideoResolution()); - int subalign = g_guiSettings.GetInt("subtitles.align"); + int subalign = CSettings::Get().GetInt("subtitles.align"); subalign++; if (subalign > SUBTITLE_ALIGN_TOP_OUTSIDE) @@ -335,7 +336,7 @@ bool CPlayerController::OnAction(const CAction &action) res_info.iSubtitles = res_info.iHeight - 1; - g_guiSettings.SetInt("subtitles.align", subalign); + CSettings::Get().SetInt("subtitles.align", subalign); CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(21460), g_localizeStrings.Get(21461 + subalign), diff --git a/xbmc/video/VideoDatabase.cpp b/xbmc/video/VideoDatabase.cpp index ad9cf64f4f..eeb9a4a8b1 100644 --- a/xbmc/video/VideoDatabase.cpp +++ b/xbmc/video/VideoDatabase.cpp @@ -41,7 +41,6 @@ #include "FileItem.h" #include "profiles/ProfilesManager.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" #include "settings/MediaSettings.h" #include "settings/MediaSourceSettings.h" #include "settings/Settings.h" @@ -4243,7 +4242,7 @@ bool CVideoDatabase::UpdateOldVersion(int iVersion) m_pDS->exec("CREATE TRIGGER delete_person AFTER DELETE ON actors FOR EACH ROW BEGIN DELETE FROM art WHERE media_id=old.idActor AND media_type IN ('actor','artist','writer','director'); END"); CMediaSettings::Get().SetVideoNeedsUpdate(63); - g_settings.Save(); + CSettings::Get().Save(); } if (iVersion < 64) { // add idShow to episode table @@ -8291,8 +8290,7 @@ void CVideoDatabase::DumpToDummyFiles(const CStdString &path) { // create a folder in this directory CStdString showName = CUtil::MakeLegalFileName(items[i]->GetVideoInfoTag()->m_strShowTitle); - CStdString TVFolder; - URIUtils::AddFileToFolder(showPath, showName, TVFolder); + CStdString TVFolder = URIUtils::AddFileToFolder(showPath, showName); if (CDirectory::Create(TVFolder)) { // right - grab the episodes and dump them as well CFileItemList episodes; @@ -8304,8 +8302,7 @@ void CVideoDatabase::DumpToDummyFiles(const CStdString &path) CStdString episode; episode.Format("%s.s%02de%02d.avi", showName.c_str(), tag->m_iSeason, tag->m_iEpisode); // and make a file - CStdString episodePath; - URIUtils::AddFileToFolder(TVFolder, episode, episodePath); + CStdString episodePath = URIUtils::AddFileToFolder(TVFolder, episode); CFile file; if (file.OpenForWrite(episodePath)) file.Close(); @@ -8656,8 +8653,7 @@ void CVideoDatabase::ExportToXML(const CStdString &path, bool singleFiles /* = f } else { - CStdString nfoFile; - URIUtils::AddFileToFolder(tvshow.m_strPath, "tvshow.nfo", nfoFile); + CStdString nfoFile = URIUtils::AddFileToFolder(tvshow.m_strPath, "tvshow.nfo"); if (overwrite || !CFile::Exists(nfoFile, false)) { @@ -9089,7 +9085,7 @@ void CVideoDatabase::ConstructPath(CStdString& strDest, const CStdString& strPat URIUtils::IsInArchive(strFileName) || URIUtils::IsPlugin(strPath)) strDest = strFileName; else - URIUtils::AddFileToFolder(strPath, strFileName, strDest); + strDest = URIUtils::AddFileToFolder(strPath, strFileName); } void CVideoDatabase::SplitPath(const CStdString& strFileNameAndPath, CStdString& strPath, CStdString& strFileName) @@ -9668,7 +9664,7 @@ bool CVideoDatabase::GetFilter(CDbUrl &videoUrl, Filter &filter, SortDescription sorting.sortBy = xsp.GetOrder(); if (xsp.GetOrderDirection() != SortOrderNone) sorting.sortOrder = xsp.GetOrderDirection(); - if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) sorting.sortAttributes = SortAttributeIgnoreArticle; } } diff --git a/xbmc/video/VideoInfoScanner.cpp b/xbmc/video/VideoInfoScanner.cpp index 592e6ae478..f5e46665f7 100644 --- a/xbmc/video/VideoInfoScanner.cpp +++ b/xbmc/video/VideoInfoScanner.cpp @@ -37,7 +37,7 @@ #include "dialogs/GUIDialogOK.h" #include "interfaces/AnnouncementManager.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "utils/StringUtils.h" #include "guilib/LocalizeStrings.h" #include "guilib/GUIWindowManager.h" @@ -81,7 +81,7 @@ namespace VIDEO m_database.Open(); - if (m_showDialog && !g_guiSettings.GetBool("videolibrary.backgroundupdate")) + if (m_showDialog && !CSettings::Get().GetBool("videolibrary.backgroundupdate")) { CGUIDialogExtendedProgressBar* dialog = (CGUIDialogExtendedProgressBar*)g_windowManager.GetWindow(WINDOW_DIALOG_EXT_PROGRESS); @@ -1260,7 +1260,7 @@ namespace VIDEO // parent folder to apply the thumb to and to search for local actor thumbs CStdString parentDir = GetParentDir(*pItem); - if (g_guiSettings.GetBool("videolibrary.actorthumbs")) + if (CSettings::Get().GetBool("videolibrary.actorthumbs")) FetchActorThumbs(movieDetails.m_cast, actorArtPath.empty() ? parentDir : actorArtPath); if (bApplyToDir) ApplyThumbToFolder(parentDir, art["thumb"]); @@ -1808,7 +1808,7 @@ namespace VIDEO || (info->Content() == CONTENT_TVSHOWS && !pItem->m_bIsFolder)) strNfoFile = GetnfoFile(pItem, bGrabAny); if (info->Content() == CONTENT_TVSHOWS && pItem->m_bIsFolder) - URIUtils::AddFileToFolder(pItem->GetPath(), "tvshow.nfo", strNfoFile); + strNfoFile = URIUtils::AddFileToFolder(pItem->GetPath(), "tvshow.nfo"); CNfoFile::NFOResult result=CNfoFile::NO_NFO; if (!strNfoFile.IsEmpty() && CFile::Exists(strNfoFile)) diff --git a/xbmc/video/VideoInfoTag.cpp b/xbmc/video/VideoInfoTag.cpp index d59205d391..636f83578a 100644 --- a/xbmc/video/VideoInfoTag.cpp +++ b/xbmc/video/VideoInfoTag.cpp @@ -21,7 +21,6 @@ #include "VideoInfoTag.h" #include "utils/XMLUtils.h" #include "guilib/LocalizeStrings.h" -#include "settings/GUISettings.h" #include "settings/AdvancedSettings.h" #include "utils/log.h" #include "utils/StringUtils.h" diff --git a/xbmc/video/VideoThumbLoader.cpp b/xbmc/video/VideoThumbLoader.cpp index 10073b51f3..a130f57a1e 100644 --- a/xbmc/video/VideoThumbLoader.cpp +++ b/xbmc/video/VideoThumbLoader.cpp @@ -25,7 +25,7 @@ #include "filesystem/File.h" #include "filesystem/DirectoryCache.h" #include "FileItem.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "GUIUserMessages.h" #include "guilib/GUIWindowManager.h" #include "TextureCache.h" @@ -83,7 +83,11 @@ bool CThumbExtractor::DoWork() return false; if (URIUtils::IsRemote(m_item.GetPath()) && !URIUtils::IsOnLAN(m_item.GetPath())) - return false; + { + // A quasi internet filesystem like webdav is generally fast enough for extracting stuff + if (!URIUtils::IsDAV(m_item.GetPath())) + return false; + } bool result=false; if (m_thumb) @@ -280,8 +284,8 @@ bool CVideoThumbLoader::LoadItem(CFileItem* pItem) m_database->SetArtForItem(info->m_iDbId, info->m_type, "thumb", thumbURL); } } - else if (g_guiSettings.GetBool("myvideos.extractthumb") && - g_guiSettings.GetBool("myvideos.extractflags")) + else if (CSettings::Get().GetBool("myvideos.extractthumb") && + CSettings::Get().GetBool("myvideos.extractflags")) { CFileItem item(*pItem); CStdString path(item.GetPath()); @@ -297,7 +301,7 @@ bool CVideoThumbLoader::LoadItem(CFileItem* pItem) } // flag extraction - if (g_guiSettings.GetBool("myvideos.extractflags") && + if (CSettings::Get().GetBool("myvideos.extractflags") && (!pItem->HasVideoInfoTag() || !pItem->GetVideoInfoTag()->HasStreamDetails() || pItem->GetVideoInfoTag()->m_streamDetails.GetVideoDuration() <= 0)) diff --git a/xbmc/video/dialogs/GUIDialogAudioSubtitleSettings.cpp b/xbmc/video/dialogs/GUIDialogAudioSubtitleSettings.cpp index 68fcc0c9c0..d08ce7027f 100644 --- a/xbmc/video/dialogs/GUIDialogAudioSubtitleSettings.cpp +++ b/xbmc/video/dialogs/GUIDialogAudioSubtitleSettings.cpp @@ -33,10 +33,9 @@ #include "addons/Skin.h" #include "profiles/ProfilesManager.h" #include "settings/AdvancedSettings.h" -#include "settings/Settings.h" -#include "settings/GUISettings.h" #include "settings/MediaSettings.h" #include "settings/MediaSourceSettings.h" +#include "settings/Settings.h" #include "guilib/LocalizeStrings.h" #include "pvr/PVRManager.h" #include "cores/AudioEngine/Utils/AEUtil.h" @@ -103,10 +102,10 @@ void CGUIDialogAudioSubtitleSettings::CreateSettings() // only show stuff available in digital mode if we have digital output if (SupportsAudioFeature(IPC_AUD_OUTPUT_STEREO)) - AddBool(AUDIO_SETTINGS_OUTPUT_TO_ALL_SPEAKERS, 252, &CMediaSettings::Get().GetCurrentVideoSettings().m_OutputToAllSpeakers, AUDIO_IS_BITSTREAM(g_guiSettings.GetInt("audiooutput.mode"))); + AddBool(AUDIO_SETTINGS_OUTPUT_TO_ALL_SPEAKERS, 252, &CMediaSettings::Get().GetCurrentVideoSettings().m_OutputToAllSpeakers, AUDIO_IS_BITSTREAM(CSettings::Get().GetInt("audiooutput.mode"))); int settings[3] = { 338, 339, 420 }; //ANALOG, IEC958, HDMI - m_outputmode = g_guiSettings.GetInt("audiooutput.mode"); + m_outputmode = CSettings::Get().GetInt("audiooutput.mode"); if (SupportsAudioFeature(IPC_AUD_SELECT_OUTPUT)) AddSpin(AUDIO_SETTINGS_DIGITAL_ANALOG, 337, &m_outputmode, 3, settings); @@ -264,7 +263,7 @@ void CGUIDialogAudioSubtitleSettings::OnSettingChanged(SettingInfo &setting) // update the screen setting... CMediaSettings::Get().GetCurrentVideoSettings().m_AudioStream = -1 - m_audioStream; // call monkeyh1's code here... - //bool bAudioOnAllSpeakers = (g_guiSettings.GetInt("audiooutput.mode") == AUDIO_IEC958) && CMediaSettings::Get().GetCurrentVideoSettings().m_OutputToAllSpeakers; + //bool bAudioOnAllSpeakers = (CSettings::Get().GetInt("audiooutput.mode") == AUDIO_IEC958) && CMediaSettings::Get().GetCurrentVideoSettings().m_OutputToAllSpeakers; return; } } @@ -286,9 +285,9 @@ void CGUIDialogAudioSubtitleSettings::OnSettingChanged(SettingInfo &setting) switch(m_outputmode) { - case 0: g_guiSettings.SetInt("audiooutput.mode", AUDIO_ANALOG ); break; - case 1: g_guiSettings.SetInt("audiooutput.mode", AUDIO_IEC958 ); bitstream = true; break; - case 2: g_guiSettings.SetInt("audiooutput.mode", AUDIO_HDMI ); bitstream = true; break; + case 0: CSettings::Get().SetInt("audiooutput.mode", AUDIO_ANALOG ); break; + case 1: CSettings::Get().SetInt("audiooutput.mode", AUDIO_IEC958 ); bitstream = true; break; + case 2: CSettings::Get().SetInt("audiooutput.mode", AUDIO_HDMI ); bitstream = true; break; } EnableSettings(AUDIO_SETTINGS_OUTPUT_TO_ALL_SPEAKERS, bitstream); @@ -324,15 +323,15 @@ void CGUIDialogAudioSubtitleSettings::OnSettingChanged(SettingInfo &setting) if (g_application.GetCurrentPlayer() == EPC_DVDPLAYER) strMask = ".srt|.rar|.zip|.ifo|.smi|.sub|.idx|.ass|.ssa|.txt"; VECSOURCES shares(*CMediaSourceSettings::Get().GetSources("video")); - if (CMediaSettings::Get().GetAdditionalSubtitleDirectoryChecked() != -1 && !g_guiSettings.GetString("subtitles.custompath").IsEmpty()) + if (CMediaSettings::Get().GetAdditionalSubtitleDirectoryChecked() != -1 && !CSettings::Get().GetString("subtitles.custompath").empty()) { CMediaSource share; std::vector<CStdString> paths; CStdString strPath1; URIUtils::GetDirectory(strPath,strPath1); paths.push_back(strPath1); - strPath1 = g_guiSettings.GetString("subtitles.custompath"); - paths.push_back(g_guiSettings.GetString("subtitles.custompath")); + strPath1 = CSettings::Get().GetString("subtitles.custompath"); + paths.push_back(CSettings::Get().GetString("subtitles.custompath")); share.FromNameAndPaths("video",g_localizeStrings.Get(21367),paths); shares.push_back(share); strPath = share.strPath; @@ -372,7 +371,7 @@ void CGUIDialogAudioSubtitleSettings::OnSettingChanged(SettingInfo &setting) CMediaSettings::Get().GetDefaultVideoSettings() = CMediaSettings::Get().GetCurrentVideoSettings(); CMediaSettings::Get().GetDefaultVideoSettings().m_SubtitleStream = -1; CMediaSettings::Get().GetDefaultVideoSettings().m_AudioStream = -1; - g_settings.Save(); + CSettings::Get().Save(); } } diff --git a/xbmc/video/dialogs/GUIDialogTeletext.cpp b/xbmc/video/dialogs/GUIDialogTeletext.cpp index a5f238aee6..bf70623c39 100644 --- a/xbmc/video/dialogs/GUIDialogTeletext.cpp +++ b/xbmc/video/dialogs/GUIDialogTeletext.cpp @@ -20,13 +20,13 @@ #include "GUIDialogTeletext.h" #include "utils/log.h" -#include "settings/GUISettings.h" #include "Application.h" #include "guilib/GUITexture.h" #include "guilib/Texture.h" #include "guilib/LocalizeStrings.h" #include "dialogs/GUIDialogKaiToast.h" #include "cores/IPlayer.h" +#include "settings/Settings.h" using namespace std; @@ -119,7 +119,7 @@ void CGUIDialogTeletext::OnInitWindow() m_windowLoaded = true; g_graphicsContext.SetScalingResolution(m_coordsRes, m_needsScaling); - if (g_guiSettings.GetBool("videoplayer.teletextscale")) + if (CSettings::Get().GetBool("videoplayer.teletextscale")) { /* Fixed aspect ratio to 4:3 for teletext */ left = g_graphicsContext.ScaleFinalXCoord((float)(m_coordsRes.iWidth-m_coordsRes.iHeight*4/3)/2, 0); diff --git a/xbmc/video/dialogs/GUIDialogVideoInfo.cpp b/xbmc/video/dialogs/GUIDialogVideoInfo.cpp index eae323e4ec..d51041c6ef 100644 --- a/xbmc/video/dialogs/GUIDialogVideoInfo.cpp +++ b/xbmc/video/dialogs/GUIDialogVideoInfo.cpp @@ -41,8 +41,8 @@ #include "utils/AsyncFileCopy.h" #include "profiles/ProfilesManager.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" #include "settings/MediaSourceSettings.h" +#include "settings/Settings.h" #include "guilib/Key.h" #include "guilib/LocalizeStrings.h" #include "GUIUserMessages.h" @@ -271,7 +271,7 @@ void CGUIDialogVideoInfo::SetMovie(const CFileItem *item) CFileItemPtr item(new CFileItem(it->strName)); if (!it->thumb.IsEmpty()) item->SetArt("thumb", it->thumb); - else if (g_guiSettings.GetBool("videolibrary.actorthumbs")) + else if (CSettings::Get().GetBool("videolibrary.actorthumbs")) { // backward compatibility CStdString thumb = CScraperUrl::GetThumbURL(it->thumbUrl.GetFirstThumb()); if (!thumb.IsEmpty()) @@ -361,7 +361,7 @@ void CGUIDialogVideoInfo::Update() // setup plot text area CStdString strTmp = m_movieItem->GetVideoInfoTag()->m_strPlot; if (!(!m_movieItem->GetVideoInfoTag()->m_strShowTitle.IsEmpty() && m_movieItem->GetVideoInfoTag()->m_iSeason == 0)) // dont apply to tvshows - if (m_movieItem->GetVideoInfoTag()->m_playCount == 0 && !g_guiSettings.GetBool("videolibrary.showunwatchedplots")) + if (m_movieItem->GetVideoInfoTag()->m_playCount == 0 && !CSettings::Get().GetBool("videolibrary.showunwatchedplots")) strTmp = g_localizeStrings.Get(20370); strTmp.Trim(); diff --git a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp index c90bf49e66..908b911754 100644 --- a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp +++ b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp @@ -23,7 +23,6 @@ #include "guilib/GUIWindowManager.h" #include "GUIPassword.h" #include "utils/MathUtils.h" -#include "settings/GUISettings.h" #ifdef HAS_VIDEO_PLAYBACK #include "cores/VideoRenderers/RenderManager.h" #endif @@ -244,7 +243,7 @@ void CGUIDialogVideoSettings::OnSettingChanged(SettingInfo &setting) CMediaSettings::Get().GetDefaultVideoSettings() = CMediaSettings::Get().GetCurrentVideoSettings(); CMediaSettings::Get().GetDefaultVideoSettings().m_SubtitleStream = -1; CMediaSettings::Get().GetDefaultVideoSettings().m_AudioStream = -1; - g_settings.Save(); + CSettings::Get().Save(); } } else if (setting.id == VIDEO_SETTINGS_DEINTERLACEMODE) diff --git a/xbmc/video/windows/GUIWindowFullScreen.cpp b/xbmc/video/windows/GUIWindowFullScreen.cpp index d3786dae34..559a04ca7d 100644 --- a/xbmc/video/windows/GUIWindowFullScreen.cpp +++ b/xbmc/video/windows/GUIWindowFullScreen.cpp @@ -39,14 +39,13 @@ #include "video/dialogs/GUIDialogFullScreenInfo.h" #include "dialogs/GUIDialogNumeric.h" #include "settings/DisplaySettings.h" -#include "settings/Settings.h" #include "settings/MediaSettings.h" +#include "settings/Settings.h" #include "guilib/GUISelectButtonControl.h" #include "FileItem.h" #include "video/VideoReferenceClock.h" #include "settings/AdvancedSettings.h" #include "utils/CPUInfo.h" -#include "settings/GUISettings.h" #include "guilib/LocalizeStrings.h" #include "threads/SingleLock.h" #include "utils/log.h" @@ -252,7 +251,7 @@ bool CGUIWindowFullScreen::OnAction(const CAction &action) } else { - int autoCloseTime = g_guiSettings.GetBool("pvrplayback.confirmchannelswitch") ? 0 : g_advancedSettings.m_iPVRNumericChannelSwitchTimeout; + int autoCloseTime = CSettings::Get().GetBool("pvrplayback.confirmchannelswitch") ? 0 : g_advancedSettings.m_iPVRNumericChannelSwitchTimeout; CStdString strChannel; strChannel.Format("%i", action.GetID() - REMOTE_0); if (CGUIDialogNumeric::ShowAndGetNumber(strChannel, g_localizeStrings.Get(19000), autoCloseTime) || autoCloseTime) @@ -406,12 +405,12 @@ bool CGUIWindowFullScreen::OnMessage(CGUIMessage& message) CSingleLock lock (m_fontLock); CStdString fontPath = "special://xbmc/media/Fonts/"; - fontPath += g_guiSettings.GetString("subtitles.font"); + fontPath += CSettings::Get().GetString("subtitles.font"); // We scale based on PAL4x3 - this at least ensures all sizing is constant across resolutions. RESOLUTION_INFO pal(720, 576, 0); - CGUIFont *subFont = g_fontManager.LoadTTF("__subtitle__", fontPath, color[g_guiSettings.GetInt("subtitles.color")], 0, g_guiSettings.GetInt("subtitles.height"), g_guiSettings.GetInt("subtitles.style"), false, 1.0f, 1.0f, &pal, true); - CGUIFont *borderFont = g_fontManager.LoadTTF("__subtitleborder__", fontPath, 0xFF000000, 0, g_guiSettings.GetInt("subtitles.height"), g_guiSettings.GetInt("subtitles.style"), true, 1.0f, 1.0f, &pal, true); + CGUIFont *subFont = g_fontManager.LoadTTF("__subtitle__", fontPath, color[CSettings::Get().GetInt("subtitles.color")], 0, CSettings::Get().GetInt("subtitles.height"), CSettings::Get().GetInt("subtitles.style"), false, 1.0f, 1.0f, &pal, true); + CGUIFont *borderFont = g_fontManager.LoadTTF("__subtitleborder__", fontPath, 0xFF000000, 0, CSettings::Get().GetInt("subtitles.height"), CSettings::Get().GetInt("subtitles.style"), true, 1.0f, 1.0f, &pal, true); if (!subFont || !borderFont) CLog::Log(LOGERROR, "CGUIWindowFullScreen::OnMessage(WINDOW_INIT) - Unable to load subtitle font"); else @@ -443,7 +442,7 @@ bool CGUIWindowFullScreen::OnMessage(CGUIMessage& message) CGUIWindow::OnMessage(message); - g_settings.Save(); + CSettings::Get().Save(); CSingleLock lock (g_graphicsContext); g_graphicsContext.SetFullScreenVideo(false); @@ -659,7 +658,7 @@ void CGUIWindowFullScreen::FrameMove() strSizing.Format(g_localizeStrings.Get(245), (int)info.SrcRect.Width(), (int)info.SrcRect.Height(), (int)(info.DestRect.Width() * xscale), (int)(info.DestRect.Height() * yscale), - CDisplaySettings::Get().GetZoomAmount(), info.videoAspectRatio*CDisplaySettings::Get().GetPixelRatio(), + CDisplaySettings::Get().GetZoomAmount(), info.videoAspectRatio*CDisplaySettings::Get().GetPixelRatio(), CDisplaySettings::Get().GetPixelRatio(), CDisplaySettings::Get().GetVerticalShift()); CGUIMessage msg(GUI_MSG_LABEL_SET, GetID(), LABEL_ROW2); msg.SetLabel(strSizing); @@ -806,7 +805,7 @@ void CGUIWindowFullScreen::RenderTTFSubtitles() float maxWidth = (float) CDisplaySettings::Get().GetResolutionInfo(res).Overscan.right - CDisplaySettings::Get().GetResolutionInfo(res).Overscan.left; m_subsLayout->Update(subtitleText, maxWidth * 0.9f, false, true); // true to force LTR reading order (most Hebrew subs are this format) - int subalign = g_guiSettings.GetInt("subtitles.align"); + int subalign = CSettings::Get().GetInt("subtitles.align"); float textWidth, textHeight; m_subsLayout->GetTextExtent(textWidth, textHeight); float x = maxWidth * 0.5f + CDisplaySettings::Get().GetResolutionInfo(res).Overscan.left; diff --git a/xbmc/video/windows/GUIWindowFullScreen.h b/xbmc/video/windows/GUIWindowFullScreen.h index c0df83491f..c42a09551c 100644 --- a/xbmc/video/windows/GUIWindowFullScreen.h +++ b/xbmc/video/windows/GUIWindowFullScreen.h @@ -23,6 +23,15 @@ #include "guilib/GUIWindow.h" #include "threads/CriticalSection.h" +enum SubtitleAlign +{ + SUBTITLE_ALIGN_MANUAL = 0, + SUBTITLE_ALIGN_BOTTOM_INSIDE, + SUBTITLE_ALIGN_BOTTOM_OUTSIDE, + SUBTITLE_ALIGN_TOP_INSIDE, + SUBTITLE_ALIGN_TOP_OUTSIDE +}; + class CGUITextLayout; // forward class CGUIWindowFullScreen : public CGUIWindow diff --git a/xbmc/video/windows/GUIWindowVideoBase.cpp b/xbmc/video/windows/GUIWindowVideoBase.cpp index 212a3b47e7..a1a0bc33a2 100644 --- a/xbmc/video/windows/GUIWindowVideoBase.cpp +++ b/xbmc/video/windows/GUIWindowVideoBase.cpp @@ -55,7 +55,6 @@ #include "profiles/ProfilesManager.h" #include "settings/Settings.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" #include "settings/MediaSettings.h" #include "settings/dialogs/GUIDialogContentSettings.h" #include "guilib/Key.h" @@ -145,10 +144,10 @@ bool CGUIWindowVideoBase::OnMessage(CGUIMessage& message) m_dlgProgress = (CGUIDialogProgress*)g_windowManager.GetWindow(WINDOW_DIALOG_PROGRESS); // save current window, unless the current window is the video playlist window - if (GetID() != WINDOW_VIDEO_PLAYLIST && g_guiSettings.GetInt("myvideos.startwindow") != GetID()) + if (GetID() != WINDOW_VIDEO_PLAYLIST && CSettings::Get().GetInt("myvideos.startwindow") != GetID()) { - g_guiSettings.SetInt("myvideos.startwindow", GetID()); - g_settings.Save(); + CSettings::Get().SetInt("myvideos.startwindow", GetID()); + CSettings::Get().Save(); } return CGUIMediaWindow::OnMessage(message); @@ -160,8 +159,8 @@ bool CGUIWindowVideoBase::OnMessage(CGUIMessage& message) int iControl = message.GetSenderId(); if (iControl == CONTROL_STACK) { - g_guiSettings.ToggleBool("myvideos.stackvideos"); - g_settings.Save(); + CSettings::Get().ToggleBool("myvideos.stackvideos"); + CSettings::Get().Save(); UpdateButtons(); Update( m_vecItems->GetPath() ); } @@ -191,8 +190,8 @@ bool CGUIWindowVideoBase::OnMessage(CGUIMessage& message) if (nNewWindow != GetID()) { - g_guiSettings.SetInt("myvideos.startwindow", nNewWindow); - g_settings.Save(); + CSettings::Get().SetInt("myvideos.startwindow", nNewWindow); + CSettings::Get().Save(); g_windowManager.ChangeActiveWindow(nNewWindow); CGUIMessage msg2(GUI_MSG_SETFOCUS, nNewWindow, CONTROL_BTNTYPE); g_windowManager.SendMessage(msg2); @@ -230,7 +229,7 @@ bool CGUIWindowVideoBase::OnMessage(CGUIMessage& message) OnDeleteItem(iItem); // or be at the files window and have file deletion enabled - else if (GetID() == WINDOW_VIDEO_FILES && g_guiSettings.GetBool("filelists.allowfiledeletion")) + else if (GetID() == WINDOW_VIDEO_FILES && CSettings::Get().GetBool("filelists.allowfiledeletion")) OnDeleteItem(iItem); // or be at the video playlists location @@ -269,13 +268,13 @@ void CGUIWindowVideoBase::UpdateButtons() g_windowManager.SendMessage(msg2); // Select the current window as default item - int nWindow = g_guiSettings.GetInt("myvideos.startwindow")-WINDOW_VIDEO_FILES; + int nWindow = CSettings::Get().GetInt("myvideos.startwindow")-WINDOW_VIDEO_FILES; CONTROL_SELECT_ITEM(CONTROL_BTNTYPE, nWindow); CONTROL_ENABLE(CONTROL_BTNSCAN); SET_CONTROL_LABEL(CONTROL_STACK, 14000); // Stack - SET_CONTROL_SELECTED(GetID(), CONTROL_STACK, g_guiSettings.GetBool("myvideos.stackvideos")); + SET_CONTROL_SELECTED(GetID(), CONTROL_STACK, CSettings::Get().GetBool("myvideos.stackvideos")); CONTROL_ENABLE_ON_CONDITION(CONTROL_STACK, m_stackingAvailable); CGUIMediaWindow::UpdateButtons(); @@ -918,7 +917,7 @@ bool CGUIWindowVideoBase::OnSelect(int iItem) CStdString path = item->GetPath(); if (!item->m_bIsFolder && path != "add" && path != "addons://more/video" && path.Left(19) != "newsmartplaylist://" && path.Left(14) != "newplaylist://" && path.Left(9) != "newtag://") - return OnFileAction(iItem, g_guiSettings.GetInt("myvideos.selectaction")); + return OnFileAction(iItem, CSettings::Get().GetInt("myvideos.selectaction")); return CGUIMediaWindow::OnSelect(iItem); } @@ -1280,7 +1279,7 @@ void CGUIWindowVideoBase::GetContextButtons(int itemNumber, CContextButtons &but //then add add either 'play from here' or 'play only this' depending on default behaviour if (!(item->m_bIsFolder || item->IsScript()) && m_vecItems->Size() > 1 && itemNumber < m_vecItems->Size()-1) { - if (!g_guiSettings.GetBool("videoplayer.autoplaynextitem")) + if (!CSettings::Get().GetBool("videoplayer.autoplaynextitem")) buttons.Add(CONTEXT_BUTTON_PLAY_AND_QUEUE, 13412); else buttons.Add(CONTEXT_BUTTON_PLAY_ONLY_THIS, 13434); @@ -1649,7 +1648,7 @@ void CGUIWindowVideoBase::OnDeleteItem(CFileItemPtr item) return; } - if ((g_guiSettings.GetBool("filelists.allowfiledeletion") || + if ((CSettings::Get().GetBool("filelists.allowfiledeletion") || m_vecItems->GetPath().Equals("special://videoplaylists/")) && CUtil::SupportsWriteFileOperations(item->GetPath())) CFileUtils::DeleteItem(item); @@ -1876,7 +1875,7 @@ bool CGUIWindowVideoBase::GetDirectory(const CStdString &strDirectory, CFileItem if (info && info->Content() == CONTENT_TVSHOWS) m_stackingAvailable = false; - if (m_stackingAvailable && !items.IsStack() && g_guiSettings.GetBool("myvideos.stackvideos")) + if (m_stackingAvailable && !items.IsStack() && CSettings::Get().GetBool("myvideos.stackvideos")) items.Stack(); return bResult; @@ -1911,7 +1910,7 @@ void CGUIWindowVideoBase::GetGroupedItems(CFileItemList &items) VIDEODATABASEDIRECTORY::NODE_TYPE nodeType = CVideoDatabaseDirectory::GetDirectoryChildType(m_strFilterPath); if (items.GetContent().Equals("movies") && params.GetSetId() <= 0 && nodeType == NODE_TYPE_TITLE_MOVIES && - (g_guiSettings.GetBool("videolibrary.groupmoviesets") || (StringUtils::EqualsNoCase(group, "sets") && mixed))) + (CSettings::Get().GetBool("videolibrary.groupmoviesets") || (StringUtils::EqualsNoCase(group, "sets") && mixed))) { CFileItemList groupedItems; if (GroupUtils::Group(GroupBySet, m_strFilterPath, items, groupedItems, GroupAttributeIgnoreSingleItems)) @@ -2073,7 +2072,7 @@ void CGUIWindowVideoBase::OnSearchItemFound(const CFileItem* pSelItem) Update(strParentPath); - if (pSelItem->IsVideoDb() && g_guiSettings.GetBool("myvideos.flatten")) + if (pSelItem->IsVideoDb() && CSettings::Get().GetBool("myvideos.flatten")) SetHistoryForPath(""); else SetHistoryForPath(strParentPath); @@ -2100,7 +2099,7 @@ void CGUIWindowVideoBase::OnSearchItemFound(const CFileItem* pSelItem) Update(strPath); - if (pSelItem->IsVideoDb() && g_guiSettings.GetBool("myvideos.flatten")) + if (pSelItem->IsVideoDb() && CSettings::Get().GetBool("myvideos.flatten")) SetHistoryForPath(""); else SetHistoryForPath(strPath); @@ -2161,7 +2160,7 @@ void CGUIWindowVideoBase::AppendAndClearSearchItems(CFileItemList &searchItems, if (!searchItems.Size()) return; - searchItems.Sort(g_guiSettings.GetBool("filelists.ignorethewhensorting") ? SORT_METHOD_LABEL_IGNORE_THE : SORT_METHOD_LABEL, SortOrderAscending); + searchItems.Sort(CSettings::Get().GetBool("filelists.ignorethewhensorting") ? SORT_METHOD_LABEL_IGNORE_THE : SORT_METHOD_LABEL, SortOrderAscending); for (int i = 0; i < searchItems.Size(); i++) searchItems[i]->SetLabel(prependLabel + searchItems[i]->GetLabel()); results.Append(searchItems); @@ -2240,7 +2239,7 @@ void CGUIWindowVideoBase::OnInitWindow() { CEdenVideoArtUpdater::Start(); CMediaSettings::Get().SetVideoNeedsUpdate(0); // once is enough - g_settings.Save(); + CSettings::Get().Save(); } } } diff --git a/xbmc/video/windows/GUIWindowVideoBase.h b/xbmc/video/windows/GUIWindowVideoBase.h index 06c75f53c5..c77a2ac574 100644 --- a/xbmc/video/windows/GUIWindowVideoBase.h +++ b/xbmc/video/windows/GUIWindowVideoBase.h @@ -25,6 +25,17 @@ #include "PlayListPlayer.h" #include "video/VideoThumbLoader.h" +enum VideoSelectAction +{ + SELECT_ACTION_CHOOSE = 0, + SELECT_ACTION_PLAY_OR_RESUME, + SELECT_ACTION_RESUME, + SELECT_ACTION_INFO, + SELECT_ACTION_MORE, + SELECT_ACTION_PLAY, + SELECT_ACTION_PLAYPART +}; + class CGUIWindowVideoBase : public CGUIMediaWindow, public IBackgroundLoaderObserver, public IStreamDetailsObserver { public: diff --git a/xbmc/video/windows/GUIWindowVideoNav.cpp b/xbmc/video/windows/GUIWindowVideoNav.cpp index edc74e9c07..a443c74be1 100644 --- a/xbmc/video/windows/GUIWindowVideoNav.cpp +++ b/xbmc/video/windows/GUIWindowVideoNav.cpp @@ -42,11 +42,10 @@ #include "Application.h" #include "ApplicationMessenger.h" #include "profiles/ProfilesManager.h" -#include "settings/Settings.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" #include "settings/MediaSettings.h" #include "settings/MediaSourceSettings.h" +#include "settings/Settings.h" #include "guilib/Key.h" #include "guilib/LocalizeStrings.h" #include "storage/MediaManager.h" @@ -121,7 +120,7 @@ bool CGUIWindowVideoNav::OnMessage(CGUIMessage& message) /* We don't want to show Autosourced items (ie removable pendrives, memorycards) in Library mode */ m_rootDir.AllowNonLocalSources(false); - SetProperty("flattened", g_guiSettings.GetBool("myvideos.flatten")); + SetProperty("flattened", CSettings::Get().GetBool("myvideos.flatten")); if (message.GetNumStringParams() && message.GetStringParam(0).Equals("Files") && CMediaSourceSettings::Get().GetSources("video")->empty()) { @@ -165,15 +164,15 @@ bool CGUIWindowVideoNav::OnMessage(CGUIMessage& message) else if (iControl == CONTROL_BTNSHOWMODE) { CMediaSettings::Get().CycleWatchedMode(m_vecItems->GetContent()); - g_settings.Save(); + CSettings::Get().Save(); OnFilterItems(GetProperty("filter").asString()); return true; } else if (iControl == CONTROL_BTNFLATTEN) { - g_guiSettings.ToggleBool("myvideos.flatten"); - g_settings.Save(); - SetProperty("flattened", g_guiSettings.GetBool("myvideos.flatten")); + CSettings::Get().ToggleBool("myvideos.flatten"); + CSettings::Get().Save(); + SetProperty("flattened", CSettings::Get().GetBool("myvideos.flatten")); CUtil::DeleteVideoDatabaseDirectoryCache(); SetupShares(); Update(""); @@ -185,7 +184,7 @@ bool CGUIWindowVideoNav::OnMessage(CGUIMessage& message) CMediaSettings::Get().SetWatchedMode(m_vecItems->GetContent(), WatchedModeUnwatched); else CMediaSettings::Get().SetWatchedMode(m_vecItems->GetContent(), WatchedModeAll); - g_settings.Save(); + CSettings::Get().Save(); OnFilterItems(GetProperty("filter").asString()); return true; } @@ -269,8 +268,6 @@ CStdString CGUIWindowVideoNav::GetQuickpathName(const CStdString& strPath) const bool CGUIWindowVideoNav::GetDirectory(const CStdString &strDirectory, CFileItemList &items) { - CFileItem directory(strDirectory, true); - if (m_thumbLoader.IsLoading()) m_thumbLoader.StopThread(); @@ -425,8 +422,8 @@ void CGUIWindowVideoNav::LoadVideoInfo(CFileItemList &items, CVideoDatabase &dat Similarly, we assign the "clean" library labels to the item only if the "Replace filenames with library titles" setting is enabled. */ - const bool stackItems = items.GetProperty("isstacked").asBoolean() || (StackingAvailable(items) && g_guiSettings.GetBool("myvideos.stackvideos")); - const bool replaceLabels = allowReplaceLabels && g_guiSettings.GetBool("myvideos.replacelabels"); + const bool stackItems = items.GetProperty("isstacked").asBoolean() || (StackingAvailable(items) && CSettings::Get().GetBool("myvideos.stackvideos")); + const bool replaceLabels = allowReplaceLabels && CSettings::Get().GetBool("myvideos.replacelabels"); CFileItemList dbItems; /* NOTE: In the future when GetItemsForPath returns all items regardless of whether they're "in the library" @@ -543,7 +540,7 @@ void CGUIWindowVideoNav::UpdateButtons() SET_CONTROL_SELECTED(GetID(),CONTROL_BTNPARTYMODE, g_partyModeManager.IsEnabled()); - SET_CONTROL_SELECTED(GetID(),CONTROL_BTNFLATTEN, g_guiSettings.GetBool("myvideos.flatten")); + SET_CONTROL_SELECTED(GetID(),CONTROL_BTNFLATTEN, CSettings::Get().GetBool("myvideos.flatten")); } bool CGUIWindowVideoNav::GetFilteredItems(const CStdString &filter, CFileItemList &items) @@ -745,7 +742,7 @@ void CGUIWindowVideoNav::OnDeleteItem(CFileItemPtr pItem) if (URIUtils::HasSlashAtEnd(strDeletePath)) pItem->m_bIsFolder=true; - if (g_guiSettings.GetBool("filelists.allowfiledeletion") && + if (CSettings::Get().GetBool("filelists.allowfiledeletion") && CUtil::SupportsWriteFileOperations(strDeletePath)) { pItem->SetPath(strDeletePath); @@ -1047,7 +1044,7 @@ void CGUIWindowVideoNav::GetContextButtons(int itemNumber, CContextButtons &butt if (!m_vecItems->IsVideoDb() && !m_vecItems->IsVirtualDirectoryRoot()) { // non-video db items, file operations are allowed - if ((g_guiSettings.GetBool("filelists.allowfiledeletion") && + if ((CSettings::Get().GetBool("filelists.allowfiledeletion") && CUtil::SupportsWriteFileOperations(item->GetPath())) || (inPlaylists && !URIUtils::GetFileName(item->GetPath()).Equals("PartyMode-Video.xsp") && (item->IsPlayList() || item->IsSmartPlayList()))) @@ -1063,8 +1060,7 @@ void CGUIWindowVideoNav::GetContextButtons(int itemNumber, CContextButtons &butt if (info && info->Content() != CONTENT_NONE) { buttons.Add(CONTEXT_BUTTON_SET_CONTENT, 20442); - if (info && g_application.IsVideoScanning()) - buttons.Add(CONTEXT_BUTTON_SCAN, 13349); + buttons.Add(CONTEXT_BUTTON_SCAN, 13349); } else buttons.Add(CONTEXT_BUTTON_SET_CONTENT, 20333); @@ -1191,8 +1187,7 @@ bool CGUIWindowVideoNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button) bool local=false; if (button == CONTEXT_BUTTON_SET_ARTIST_THUMB) { - CStdString strThumb; - URIUtils::AddFileToFolder(artistPath,"folder.jpg",strThumb); + CStdString strThumb = URIUtils::AddFileToFolder(artistPath, "folder.jpg"); if (XFILE::CFile::Exists(strThumb)) { CFileItemPtr pItem(new CFileItem(strThumb,false)); @@ -1208,8 +1203,7 @@ bool CGUIWindowVideoNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button) if (button == CONTEXT_BUTTON_SET_ACTOR_THUMB) { CStdString picturePath; - CStdString strThumb; - URIUtils::AddFileToFolder(picturePath,"folder.jpg",strThumb); + CStdString strThumb = URIUtils::AddFileToFolder(picturePath, "folder.jpg"); if (XFILE::CFile::Exists(strThumb)) { CFileItemPtr pItem(new CFileItem(strThumb,false)); @@ -1420,7 +1414,7 @@ bool CGUIWindowVideoNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button) CMusicDatabase database; database.Open(); CSong song; - if (database.GetSongById(database.GetSongByArtistAndAlbumAndTitle(StringUtils::Join(m_vecItems->Get(itemNumber)->GetVideoInfoTag()->m_artist, g_advancedSettings.m_videoItemSeparator),m_vecItems->Get(itemNumber)->GetVideoInfoTag()->m_strAlbum, + if (database.GetSong(database.GetSongByArtistAndAlbumAndTitle(StringUtils::Join(m_vecItems->Get(itemNumber)->GetVideoInfoTag()->m_artist, g_advancedSettings.m_videoItemSeparator),m_vecItems->Get(itemNumber)->GetVideoInfoTag()->m_strAlbum, m_vecItems->Get(itemNumber)->GetVideoInfoTag()->m_strTitle), song)) { @@ -1542,7 +1536,7 @@ void CGUIWindowVideoNav::OnLinkMovieToTvShow(int itemnumber, bool bRemove) int iSelectedLabel = 0; if (list.Size() > 1) { - list.Sort(g_guiSettings.GetBool("filelists.ignorethewhensorting") ? SORT_METHOD_LABEL_IGNORE_THE : SORT_METHOD_LABEL, SortOrderAscending); + list.Sort(CSettings::Get().GetBool("filelists.ignorethewhensorting") ? SORT_METHOD_LABEL_IGNORE_THE : SORT_METHOD_LABEL, SortOrderAscending); CGUIDialogSelect* pDialog = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT); pDialog->Reset(); pDialog->SetItems(&list); diff --git a/xbmc/video/windows/GUIWindowVideoPlaylist.cpp b/xbmc/video/windows/GUIWindowVideoPlaylist.cpp index 5d6e2bdd71..3c8a343a80 100644 --- a/xbmc/video/windows/GUIWindowVideoPlaylist.cpp +++ b/xbmc/video/windows/GUIWindowVideoPlaylist.cpp @@ -30,9 +30,8 @@ #include "guilib/GUIKeyboardFactory.h" #include "GUIUserMessages.h" #include "Favourites.h" -#include "settings/Settings.h" -#include "settings/GUISettings.h" #include "settings/MediaSettings.h" +#include "settings/Settings.h" #include "guilib/Key.h" #include "guilib/LocalizeStrings.h" #include "utils/log.h" @@ -129,7 +128,7 @@ bool CGUIWindowVideoPlaylist::OnMessage(CGUIMessage& message) { g_playlistPlayer.SetShuffle(PLAYLIST_VIDEO, !(g_playlistPlayer.IsShuffled(PLAYLIST_VIDEO))); CMediaSettings::Get().SetVideoPlaylistShuffled(g_playlistPlayer.IsShuffled(PLAYLIST_VIDEO)); - g_settings.Save(); + CSettings::Get().Save(); UpdateButtons(); Refresh(); } @@ -172,7 +171,7 @@ bool CGUIWindowVideoPlaylist::OnMessage(CGUIMessage& message) // save settings CMediaSettings::Get().SetVideoPlaylistRepeat(g_playlistPlayer.GetRepeat(PLAYLIST_VIDEO) == PLAYLIST::REPEAT_ALL); - g_settings.Save(); + CSettings::Get().Save(); UpdateButtons(); } @@ -376,11 +375,10 @@ void CGUIWindowVideoPlaylist::SavePlayList() if (CGUIKeyboardFactory::ShowAndGetInput(strNewFileName, g_localizeStrings.Get(16012), false)) { // need 2 rename it - CStdString strPath, strFolder; - URIUtils::AddFileToFolder(g_guiSettings.GetString("system.playlistspath"), "video", strFolder); + CStdString strFolder = URIUtils::AddFileToFolder(CSettings::Get().GetString("system.playlistspath"), "video"); strNewFileName = CUtil::MakeLegalFileName(strNewFileName); strNewFileName += ".m3u"; - URIUtils::AddFileToFolder(strFolder, strNewFileName, strPath); + CStdString strPath = URIUtils::AddFileToFolder(strFolder, strNewFileName); CPlayListM3U playlist; playlist.Add(*m_vecItems); diff --git a/xbmc/view/GUIViewControl.cpp b/xbmc/view/GUIViewControl.cpp index 91e6061030..0781ec6acc 100644 --- a/xbmc/view/GUIViewControl.cpp +++ b/xbmc/view/GUIViewControl.cpp @@ -120,7 +120,7 @@ void CGUIViewControl::SetCurrentView(int viewMode, bool bRefresh /* = false */) if (hasFocus) { CGUIMessage msg(GUI_MSG_SETFOCUS, m_parentWindow, pNewView->GetID(), 0); - g_windowManager.SendMessage(msg); + g_windowManager.SendMessage(msg, m_parentWindow); } // Update our view control only if we are not in the TV Window @@ -140,7 +140,7 @@ void CGUIViewControl::UpdateContents(const CGUIControl *control, int currentItem { if (!control || !m_fileItems) return; CGUIMessage msg(GUI_MSG_LABEL_BIND, m_parentWindow, control->GetID(), currentItem, 0, m_fileItems); - g_windowManager.SendMessage(msg); + g_windowManager.SendMessage(msg, m_parentWindow); } void CGUIViewControl::UpdateView() @@ -159,7 +159,7 @@ int CGUIViewControl::GetSelectedItem(const CGUIControl *control) const { if (!control || !m_fileItems) return -1; CGUIMessage msg(GUI_MSG_ITEM_SELECTED, m_parentWindow, control->GetID()); - g_windowManager.SendMessage(msg); + g_windowManager.SendMessage(msg, m_parentWindow); int iItem = msg.GetParam1(); if (iItem >= m_fileItems->Size()) @@ -184,7 +184,7 @@ void CGUIViewControl::SetSelectedItem(int item) return; // no valid current view! CGUIMessage msg(GUI_MSG_ITEM_SELECT, m_parentWindow, m_visibleViews[m_currentView]->GetID(), item); - g_windowManager.SendMessage(msg); + g_windowManager.SendMessage(msg, m_parentWindow); } void CGUIViewControl::SetSelectedItem(const CStdString &itemPath) @@ -215,7 +215,7 @@ void CGUIViewControl::SetFocused() return; // no valid current view! CGUIMessage msg(GUI_MSG_SETFOCUS, m_parentWindow, m_visibleViews[m_currentView]->GetID(), 0); - g_windowManager.SendMessage(msg); + g_windowManager.SendMessage(msg, m_parentWindow); } bool CGUIViewControl::HasControl(int viewControlID) const @@ -279,7 +279,7 @@ void CGUIViewControl::Clear() return; // no valid current view! CGUIMessage msg(GUI_MSG_LABEL_RESET, m_parentWindow, m_visibleViews[m_currentView]->GetID(), 0); - g_windowManager.SendMessage(msg); + g_windowManager.SendMessage(msg, m_parentWindow); } int CGUIViewControl::GetView(VIEW_TYPE type, int id) const @@ -297,7 +297,7 @@ void CGUIViewControl::UpdateViewAsControl(const CStdString &viewLabel) { // the view as control could be a select/spin/dropdown button CGUIMessage msg(GUI_MSG_LABEL_RESET, m_parentWindow, m_viewAsControl); - g_windowManager.SendMessage(msg); + g_windowManager.SendMessage(msg, m_parentWindow); for (unsigned int i = 0; i < m_visibleViews.size(); i++) { IGUIContainer *view = (IGUIContainer *)m_visibleViews[i]; @@ -305,17 +305,17 @@ void CGUIViewControl::UpdateViewAsControl(const CStdString &viewLabel) CStdString label; label.Format(g_localizeStrings.Get(534).c_str(), view->GetLabel().c_str()); // View: %s msg.SetLabel(label); - g_windowManager.SendMessage(msg); + g_windowManager.SendMessage(msg, m_parentWindow); } CGUIMessage msgSelect(GUI_MSG_ITEM_SELECT, m_parentWindow, m_viewAsControl, m_currentView); - g_windowManager.SendMessage(msgSelect); + g_windowManager.SendMessage(msgSelect, m_parentWindow); // otherwise it's just a normal button CStdString label; label.Format(g_localizeStrings.Get(534).c_str(), viewLabel.c_str()); // View: %s CGUIMessage msgSet(GUI_MSG_LABEL_SET, m_parentWindow, m_viewAsControl); msgSet.SetLabel(label); - g_windowManager.SendMessage(msgSet); + g_windowManager.SendMessage(msgSet, m_parentWindow); } void CGUIViewControl::UpdateViewVisibility() diff --git a/xbmc/view/GUIViewState.cpp b/xbmc/view/GUIViewState.cpp index 39b02db9a9..8f6e6cda03 100644 --- a/xbmc/view/GUIViewState.cpp +++ b/xbmc/view/GUIViewState.cpp @@ -37,7 +37,6 @@ #include "addons/AddonManager.h" #include "addons/PluginSource.h" #include "view/ViewState.h" -#include "settings/GUISettings.h" #include "settings/AdvancedSettings.h" #include "settings/MediaSourceSettings.h" #include "settings/Settings.h" @@ -260,7 +259,7 @@ void CGUIViewState::AddSortMethod(SORT_METHOD sortMethod, int buttonLabel, LABEL void CGUIViewState::SetCurrentSortMethod(int method) { - bool ignoreThe = g_guiSettings.GetBool("filelists.ignorethewhensorting"); + bool ignoreThe = CSettings::Get().GetBool("filelists.ignorethewhensorting"); if (method < SORT_METHOD_NONE || method >= SORT_METHOD_MAX) return; // invalid @@ -303,18 +302,18 @@ SORT_METHOD CGUIViewState::SetNextSortMethod(int direction /* = 1 */) bool CGUIViewState::HideExtensions() { - return !g_guiSettings.GetBool("filelists.showextensions"); + return !CSettings::Get().GetBool("filelists.showextensions"); } bool CGUIViewState::HideParentDirItems() { - return !g_guiSettings.GetBool("filelists.showparentdiritems"); + return !CSettings::Get().GetBool("filelists.showparentdiritems"); } bool CGUIViewState::DisableAddSourceButtons() { if (CProfilesManager::Get().GetCurrentProfile().canWriteSources() || g_passwordManager.bMasterUser) - return !g_guiSettings.GetBool("filelists.showaddsourcebuttons"); + return !CSettings::Get().GetBool("filelists.showaddsourcebuttons"); return true; } @@ -449,7 +448,7 @@ void CGUIViewState::LoadViewState(const CStdString &path, int windowID) if (db.Open()) { CViewState state; - if (db.GetViewState(path, windowID, state, g_guiSettings.GetString("lookandfeel.skin")) || + if (db.GetViewState(path, windowID, state, CSettings::Get().GetString("lookandfeel.skin")) || db.GetViewState(path, windowID, state, "")) { SetViewAsControl(state.m_viewMode); @@ -468,10 +467,10 @@ void CGUIViewState::SaveViewToDb(const CStdString &path, int windowID, CViewStat CViewState state(m_currentViewAsControl, GetSortMethod(), m_sortOrder); if (viewState) *viewState = state; - db.SetViewState(path, windowID, state, g_guiSettings.GetString("lookandfeel.skin")); + db.SetViewState(path, windowID, state, CSettings::Get().GetString("lookandfeel.skin")); db.Close(); if (viewState) - g_settings.Save(); + CSettings::Get().Save(); } } @@ -485,7 +484,7 @@ void CGUIViewState::AddPlaylistOrder(const CFileItemList &items, LABEL_MASKS lab SortBy sortBy = (SortBy)items.GetProperty(PROPERTY_SORT_ORDER).asInteger(); if (sortBy != SortByNone) { - sortMethod = SortUtils::TranslateOldSortMethod(sortBy, g_guiSettings.GetBool("filelists.ignorethewhensorting")); + sortMethod = SortUtils::TranslateOldSortMethod(sortBy, CSettings::Get().GetBool("filelists.ignorethewhensorting")); if (sortMethod == SORT_METHOD_NONE) sortMethod = SORT_METHOD_PLAYLIST_ORDER; else diff --git a/xbmc/view/ViewStateSettings.cpp b/xbmc/view/ViewStateSettings.cpp index 0df7b8c290..9e78b9c245 100644 --- a/xbmc/view/ViewStateSettings.cpp +++ b/xbmc/view/ViewStateSettings.cpp @@ -31,6 +31,8 @@ #define XML_VIEWMODE "viewmode" #define XML_SORTMETHOD "sortmethod" #define XML_SORTORDER "sortorder" +#define XML_GENERAL "general" +#define XML_SETTINGLEVEL "settinglevel" using namespace std; @@ -53,6 +55,8 @@ CViewStateSettings::CViewStateSettings() AddViewState("pictures", DEFAULT_VIEW_AUTO); AddViewState("videofiles", DEFAULT_VIEW_AUTO); AddViewState("musicfiles", DEFAULT_VIEW_AUTO); + + Clear(); } CViewStateSettings::~CViewStateSettings() @@ -98,6 +102,16 @@ bool CViewStateSettings::Load(const TiXmlNode *settings) viewState->second->m_sortOrder = (SortOrder)sortOrder; } + pElement = settings->FirstChild(XML_GENERAL); + if (pElement != NULL) + { + int settingLevel; + if (XMLUtils::GetInt(pElement, XML_SETTINGLEVEL, settingLevel, (const int)SettingLevelBasic, (const int)SettingLevelExpert)) + m_settingLevel = (SettingLevel)settingLevel; + else + m_settingLevel = SettingLevelStandard; + } + return true; } @@ -126,12 +140,27 @@ bool CViewStateSettings::Save(TiXmlNode *settings) const XMLUtils::SetInt(pNewNode, XML_VIEWMODE, viewState->second->m_viewMode); XMLUtils::SetInt(pNewNode, XML_SORTMETHOD, (int)viewState->second->m_sortMethod); XMLUtils::SetInt(pNewNode, XML_SORTORDER, (int)viewState->second->m_sortOrder); + } + TiXmlNode *generalNode = settings->FirstChild(XML_GENERAL); + if (generalNode == NULL) + { + TiXmlElement generalElement(XML_GENERAL); + generalNode = settings->InsertEndChild(generalElement); + if (generalNode == NULL) + return false; } + XMLUtils::SetInt(generalNode, XML_SETTINGLEVEL, (int)m_settingLevel); + return true; } +void CViewStateSettings::Clear() +{ + m_settingLevel = SettingLevelStandard; +} + const CViewState* CViewStateSettings::Get(const std::string &viewState) const { CSingleLock lock(m_critical); @@ -152,6 +181,23 @@ CViewState* CViewStateSettings::Get(const std::string &viewState) return NULL; } +void CViewStateSettings::SetSettingLevel(SettingLevel settingLevel) +{ + if (settingLevel < SettingLevelBasic) + m_settingLevel = SettingLevelBasic; + if (settingLevel > SettingLevelExpert) + m_settingLevel = SettingLevelExpert; + else + m_settingLevel = settingLevel; +} + +void CViewStateSettings::CycleSettingLevel() +{ + m_settingLevel = (SettingLevel)((int)m_settingLevel + 1); + if (m_settingLevel > SettingLevelExpert) + m_settingLevel = SettingLevelBasic; +} + void CViewStateSettings::AddViewState(const std::string& strTagName, int defaultView /* = DEFAULT_VIEW_LIST */, SORT_METHOD defaultSort /* = SORT_METHOD_LABEL */) { if (strTagName.empty() || m_viewStates.find(strTagName) != m_viewStates.end()) diff --git a/xbmc/view/ViewStateSettings.h b/xbmc/view/ViewStateSettings.h index b2174a571a..5014d2dbc0 100644 --- a/xbmc/view/ViewStateSettings.h +++ b/xbmc/view/ViewStateSettings.h @@ -25,6 +25,7 @@ #include "ViewState.h" #include "guilib/GraphicContext.h" #include "settings/ISubSettings.h" +#include "settings/Setting.h" #include "threads/CriticalSection.h" class TiXmlNode; @@ -36,10 +37,15 @@ public: virtual bool Load(const TiXmlNode *settings); virtual bool Save(TiXmlNode *settings) const; + virtual void Clear(); const CViewState* Get(const std::string &viewState) const; CViewState* Get(const std::string &viewState); + SettingLevel GetSettingLevel() const { return m_settingLevel; } + void SetSettingLevel(SettingLevel settingLevel); + void CycleSettingLevel(); + protected: CViewStateSettings(); CViewStateSettings(const CViewStateSettings&); @@ -48,6 +54,7 @@ protected: private: std::map<std::string, CViewState*> m_viewStates; + SettingLevel m_settingLevel; CCriticalSection m_critical; void AddViewState(const std::string& strTagName, int defaultView = DEFAULT_VIEW_LIST, SORT_METHOD defaultSort = SORT_METHOD_LABEL); diff --git a/xbmc/visualizations/Vortex/VortexVis/Core/Vortex.cpp b/xbmc/visualizations/Vortex/VortexVis/Core/Vortex.cpp index 6bc8ad6739..682724e35d 100644 --- a/xbmc/visualizations/Vortex/VortexVis/Core/Vortex.cpp +++ b/xbmc/visualizations/Vortex/VortexVis/Core/Vortex.cpp @@ -359,7 +359,7 @@ void Vortex::Init( LPDIRECT3DDEVICE9 pD3DDevice, int iPosX, int iPosY, int iWidt g_AnnouncePreset.Init(m_pScriptEngine, "ANNOUNCE"); g_AnnouncePreset.m_presetId = 3; - if ( g_Settings.PresetLocked ) + if ( CSettings::Get().PresetLocked ) { // Check that the preset locked in the settings file is still valid if ( g_currPresetId >= g_PresetFiles.NumFiles() || g_currPresetId < 0 ) @@ -367,7 +367,7 @@ void Vortex::Init( LPDIRECT3DDEVICE9 pD3DDevice, int iPosX, int iPosY, int iWidt g_currPresetId = GetRandomPreset(); } } - else if ( g_Settings.RandomPresetsEnabled ) + else if ( CSettings::Get().RandomPresetsEnabled ) { g_currPresetId = GetRandomPreset(); } @@ -379,7 +379,7 @@ void Vortex::Init( LPDIRECT3DDEVICE9 pD3DDevice, int iPosX, int iPosY, int iWidt char filename[ 256 ]; sprintf( filename, "%s%s", g_PresetPath, g_PresetFiles.GetFilename( g_currPresetId ) ); g_presets[ 0 ]->Begin( filename ); - g_mainCounter = g_Settings.TimeBetweenPresets + ((rand() % 100) / 100.0f) * g_Settings.TimeBetweenPresetsRand; + g_mainCounter = CSettings::Get().TimeBetweenPresets + ((rand() % 100) / 100.0f) * CSettings::Get().TimeBetweenPresetsRand; g_currentState = STATE_RENDER_PRESET; } @@ -809,7 +809,7 @@ void Vortex::Render() case STATE_RENDER_PRESET: { // OutputDebugString("STATE = STATE_RENDER_PRESET\n"); - if ( !g_Settings.PresetLocked ) + if ( !CSettings::Get().PresetLocked ) { g_mainCounter -= g_timePass; } @@ -821,7 +821,7 @@ void Vortex::Render() if ( g_mainCounter <= 0 ) { // Not in a transition, preset not locked and time for a new preset - if ( g_Settings.RandomPresetsEnabled ) + if ( CSettings::Get().RandomPresetsEnabled ) { int nextPreset = GetRandomPreset(); if ( nextPreset == g_currPresetId ) @@ -843,14 +843,14 @@ void Vortex::Render() } g_finished = true; - g_mainCounter = g_Settings.TimeBetweenPresets + ((rand() % 100) / 100.0f) * g_Settings.TimeBetweenPresetsRand; + g_mainCounter = CSettings::Get().TimeBetweenPresets + ((rand() % 100) / 100.0f) * CSettings::Get().TimeBetweenPresetsRand; // Load preset sprintf(filename, "%s%s", g_PresetPath, g_PresetFiles.GetFilename( g_currPresetId ) ); if ( g_presets[ 1 ]->Begin( filename ) == true ) { // Load and begin transition - if ( g_Settings.TransitionsEnabled && g_TransitionFiles.NumFiles() != 0 ) + if ( CSettings::Get().TransitionsEnabled && g_TransitionFiles.NumFiles() != 0 ) { g_transitionId = ( g_transitionId + 1 ) % g_TransitionFiles.NumFiles(); sprintf( filename, "%s%s", g_TransitionPath, g_TransitionFiles.GetFilename( g_transitionId ) ); @@ -880,7 +880,7 @@ void Vortex::Render() // OutputDebugString("STATE = STATE_TRANSITION\n"); if (g_finished) { - g_mainCounter = g_Settings.TimeBetweenPresets + ((rand() % 100) / 100.0f) * g_Settings.TimeBetweenPresetsRand; + g_mainCounter = CSettings::Get().TimeBetweenPresets + ((rand() % 100) / 100.0f) * CSettings::Get().TimeBetweenPresetsRand; SwapPresets(); g_finished = false; @@ -913,7 +913,7 @@ void Vortex::Render() // Renderer::Rect( -1.0, -1.0, 1.0, 1.0, 0xff000000 ); /* - if ( g_Settings.ShowAudioAnalysis ) + if ( CSettings::Get().ShowAudioAnalysis ) { FLOAT BAR_WIDTH = 1.0f / 128; / * @@ -994,12 +994,12 @@ void Vortex::Render() } */ - if( g_Settings.ShowDebugConsole ) + if( CSettings::Get().ShowDebugConsole ) { DebugConsole::Render(); } - if( g_Settings.ShowFPS ) + if( CSettings::Get().ShowFPS ) { char FrameRate[256]; sprintf_s(FrameRate, 256, "FPS = %0.02f\n", fFPS ); diff --git a/xbmc/win32/WIN32Util.cpp b/xbmc/win32/WIN32Util.cpp index 0ca4e474ee..d0585e50c0 100644 --- a/xbmc/win32/WIN32Util.cpp +++ b/xbmc/win32/WIN32Util.cpp @@ -19,7 +19,6 @@ */ #include "WIN32Util.h" -#include "settings/GUISettings.h" #include "Util.h" #include "utils/URIUtils.h" #include "storage/cdioSupport.h" @@ -1604,4 +1603,4 @@ bool CWIN32Util::IsUsbDevice(const CStdStringW &strWdrive) CloseHandle(deviceHandle); return BusTypeUsb == busType; - }
\ No newline at end of file + } diff --git a/xbmc/win32/WIN32Util.h b/xbmc/win32/WIN32Util.h index eb7a50cd7d..40f3cc5d2a 100644 --- a/xbmc/win32/WIN32Util.h +++ b/xbmc/win32/WIN32Util.h @@ -21,13 +21,13 @@ */ #include "URL.h" -#include "settings/GUISettings.h" #if _MSC_VER > 1400 #include "Cfgmgr32.h" #endif #include "MediaSource.h" -#include "utils/Stopwatch.h" #include "guilib/Geometry.h" +#include "powermanagement/PowerManager.h" +#include "utils/Stopwatch.h" enum Drive_Types { diff --git a/xbmc/win32/XBMC_PC.cpp b/xbmc/win32/XBMC_PC.cpp index 425e3f1720..d3823c9af0 100644 --- a/xbmc/win32/XBMC_PC.cpp +++ b/xbmc/win32/XBMC_PC.cpp @@ -18,8 +18,8 @@ * */ -#include "settings/AdvancedSettings.h" #include "AppParamParser.h" +#include "settings/AdvancedSettings.h" #include "utils/CharsetConverter.h" #include "utils/log.h" #include "threads/platform/win/Win32Exception.h" diff --git a/xbmc/win32/XBMC_PC.rc b/xbmc/win32/XBMC_PC.rc index 207edd8e94..20713b9a4b 100644 --- a/xbmc/win32/XBMC_PC.rc +++ b/xbmc/win32/XBMC_PC.rc @@ -53,8 +53,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 12,9,3,0 - PRODUCTVERSION 12,9,3,0 + FILEVERSION 12,9,4,0 + PRODUCTVERSION 12,9,4,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -71,12 +71,12 @@ BEGIN BEGIN VALUE "CompanyName", "Team XBMC" VALUE "FileDescription", "XBMC" - VALUE "FileVersion", "13.0-ALPHA3" + VALUE "FileVersion", "13.0-ALPHA4" VALUE "InternalName", "XBMC.exe" VALUE "LegalCopyright", "Copyright (c) Team XBMC. All rights reserved." VALUE "OriginalFilename", "XBMC.exe" VALUE "ProductName", "XBMC for Windows" - VALUE "ProductVersion", "13.0-ALPHA3" + VALUE "ProductVersion", "13.0-ALPHA4" END END BLOCK "VarFileInfo" diff --git a/xbmc/windowing/WinSystem.cpp b/xbmc/windowing/WinSystem.cpp index 08478948e4..b60dfe3071 100644 --- a/xbmc/windowing/WinSystem.cpp +++ b/xbmc/windowing/WinSystem.cpp @@ -22,7 +22,6 @@ #include "guilib/GraphicContext.h" #include "settings/DisplaySettings.h" #include "settings/Settings.h" -#include "settings/GUISettings.h" using namespace std; @@ -207,8 +206,8 @@ REFRESHRATE CWinSystemBase::DefaultRefreshRate(int screen, vector<REFRESHRATE> r bool CWinSystemBase::UseLimitedColor() { #if defined(HAS_GL) || defined(HAS_DX) - static CSettingBool* setting = (CSettingBool*)g_guiSettings.GetSetting("videoscreen.limitedrange"); - return setting->GetData(); + static CSettingBool* setting = (CSettingBool*)CSettings::Get().GetSetting("videoscreen.limitedrange"); + return setting->GetValue(); #else return false; #endif diff --git a/xbmc/windowing/X11/WinSystemX11GLES.cpp b/xbmc/windowing/X11/WinSystemX11GLES.cpp index 7975c573c0..0660e6059a 100644 --- a/xbmc/windowing/X11/WinSystemX11GLES.cpp +++ b/xbmc/windowing/X11/WinSystemX11GLES.cpp @@ -27,6 +27,7 @@ #include "filesystem/SpecialProtocol.h" #include "settings/DisplaySettings.h" #include "settings/Settings.h" +#include "settings/DisplaySettings.h" #include "guilib/Texture.h" #include "windowing/X11/XRandR.h" #include <vector> diff --git a/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp b/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp index 360c6d9db0..5ce894b882 100644 --- a/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp +++ b/xbmc/windowing/egl/EGLNativeTypeAmlogic.cpp @@ -17,17 +17,29 @@ * <http://www.gnu.org/licenses/>. * */ -#include <EGL/egl.h> + #include "EGLNativeTypeAmlogic.h" +#include "guilib/gui3d.h" +#include "utils/AMLUtils.h" +#include "utils/StringUtils.h" + #include <stdlib.h> #include <linux/fb.h> #include <sys/ioctl.h> -#include "utils/StringUtils.h" -#include "guilib/gui3d.h" -#define m_framebuffer_name "fb0" +#include <EGL/egl.h> CEGLNativeTypeAmlogic::CEGLNativeTypeAmlogic() { + const char *env_framebuffer = getenv("FRAMEBUFFER"); + + // default to framebuffer 0 + m_framebuffer_name = "fb0"; + if (env_framebuffer) + { + std::string framebuffer(env_framebuffer); + std::string::size_type start = framebuffer.find("fb"); + m_framebuffer_name = framebuffer.substr(start); + } m_nativeWindow = NULL; } @@ -38,7 +50,9 @@ CEGLNativeTypeAmlogic::~CEGLNativeTypeAmlogic() bool CEGLNativeTypeAmlogic::CheckCompatibility() { char name[256] = {0}; - get_sysfs_str("/sys/class/graphics/fb0/device/modalias", name, 255); + std::string modalias = "/sys/class/graphics/" + m_framebuffer_name + "/device/modalias"; + + aml_get_sysfs_str(modalias.c_str(), name, 255); CStdString strName = name; strName.Trim(); if (strName == "platform:mesonfb") @@ -48,12 +62,12 @@ bool CEGLNativeTypeAmlogic::CheckCompatibility() void CEGLNativeTypeAmlogic::Initialize() { - SetCpuMinLimit(true); + aml_cpufreq_limit(true); return; } void CEGLNativeTypeAmlogic::Destroy() { - SetCpuMinLimit(false); + aml_cpufreq_limit(false); return; } @@ -111,47 +125,60 @@ bool CEGLNativeTypeAmlogic::DestroyNativeWindow() bool CEGLNativeTypeAmlogic::GetNativeResolution(RESOLUTION_INFO *res) const { char mode[256] = {0}; - get_sysfs_str("/sys/class/display/mode", mode, 255); + aml_get_sysfs_str("/sys/class/display/mode", mode, 255); return ModeToResolution(mode, res); } bool CEGLNativeTypeAmlogic::SetNativeResolution(const RESOLUTION_INFO &res) { - if (res.iScreenWidth == 1920 && res.iScreenHeight == 1080) + switch((int)(0.5 + res.fRefreshRate)) { - if (res.dwFlags & D3DPRESENTFLAG_INTERLACED) - { - if ((int)res.fRefreshRate == 60) - SetDisplayResolution("1080i"); - else - SetDisplayResolution("1080i50hz"); - } - else - { - if ((int)res.fRefreshRate == 60) - SetDisplayResolution("1080p"); - else - SetDisplayResolution("1080p50hz"); - } - } - else if (res.iScreenWidth == 1280 && res.iScreenHeight == 720) - { - if ((int)res.fRefreshRate == 60) - SetDisplayResolution("720p"); - else - SetDisplayResolution("720p50hz"); - } - else if (res.iScreenWidth == 720 && res.iScreenHeight == 480) - { - SetDisplayResolution("480p"); + default: + case 60: + switch(res.iScreenWidth) + { + default: + case 1280: + SetDisplayResolution("720p"); + break; + case 1920: + if (res.dwFlags & D3DPRESENTFLAG_INTERLACED) + SetDisplayResolution("1080i"); + else + SetDisplayResolution("1080p"); + break; + } + break; + case 50: + switch(res.iScreenWidth) + { + default: + case 1280: + SetDisplayResolution("720p50hz"); + break; + case 1920: + if (res.dwFlags & D3DPRESENTFLAG_INTERLACED) + SetDisplayResolution("1080i50hz"); + else + SetDisplayResolution("1080p50hz"); + break; + } + break; + case 30: + SetDisplayResolution("1080p30hz"); + break; + case 24: + SetDisplayResolution("1080p24hz"); + break; } + return true; } bool CEGLNativeTypeAmlogic::ProbeResolutions(std::vector<RESOLUTION_INFO> &resolutions) { char valstr[256] = {0}; - get_sysfs_str("/sys/class/amhdmitx/amhdmitx0/disp_cap", valstr, 255); + aml_get_sysfs_str("/sys/class/amhdmitx/amhdmitx0/disp_cap", valstr, 255); std::vector<CStdString> probe_str; StringUtils::SplitString(valstr, "\n", probe_str); @@ -168,92 +195,28 @@ bool CEGLNativeTypeAmlogic::ProbeResolutions(std::vector<RESOLUTION_INFO> &resol bool CEGLNativeTypeAmlogic::GetPreferredResolution(RESOLUTION_INFO *res) const { - res->iWidth = 1280; - res->iHeight= 720; - res->fRefreshRate = 60; - res->dwFlags= D3DPRESENTFLAG_PROGRESSIVE; - res->iScreen = 0; - res->bFullScreen = true; - res->iSubtitles = (int)(0.965 * res->iHeight); - res->fPixelRatio = 1.0f; - res->iScreenWidth = res->iWidth; - res->iScreenHeight = res->iHeight; - res->strMode.Format("%dx%d @ %.2f%s - Full Screen", res->iScreenWidth, res->iScreenHeight, res->fRefreshRate, - res->dwFlags & D3DPRESENTFLAG_INTERLACED ? "i" : ""); - return true; -} - -bool CEGLNativeTypeAmlogic::ShowWindow(bool show) -{ - std::string blank_framebuffer = "/sys/class/graphics/fb0/blank"; - set_sysfs_int(blank_framebuffer.c_str(), show ? 0 : 1); - return true; -} - -int CEGLNativeTypeAmlogic::get_sysfs_str(const char *path, char *valstr, const int size) const -{ - int fd = open(path, O_RDONLY); - if (fd >= 0) - { - int len = read(fd, valstr, size - 1); - if (len != -1 ) - valstr[len] = '\0'; - close(fd); - } - else - { - sprintf(valstr, "%s", "fail"); - return -1; - } - return 0; -} - -int CEGLNativeTypeAmlogic::set_sysfs_str(const char *path, const char *val) const -{ - int fd = open(path, O_CREAT | O_RDWR | O_TRUNC, 0644); - if (fd >= 0) + // check display/mode, it gets defaulted at boot + if (!GetNativeResolution(res)) { - write(fd, val, strlen(val)); - close(fd); - return 0; + // punt to 720p if we get nothing + ModeToResolution("720p", res); } - return -1; -} -int CEGLNativeTypeAmlogic::set_sysfs_int(const char *path, const int val) const -{ - char bcmd[16]; - int fd = open(path, O_CREAT | O_RDWR | O_TRUNC, 0644); - if (fd >= 0) - { - sprintf(bcmd, "%d", val); - write(fd, bcmd, strlen(bcmd)); - close(fd); - return 0; - } - return -1; + return true; } -int CEGLNativeTypeAmlogic::get_sysfs_int(const char *path) const +bool CEGLNativeTypeAmlogic::ShowWindow(bool show) { - int val = 0; - char bcmd[16]; - int fd = open(path, O_RDONLY); - if (fd >= 0) - { - read(fd, bcmd, sizeof(bcmd)); - val = strtol(bcmd, NULL, 16); - close(fd); - } - return val; + std::string blank_framebuffer = "/sys/class/graphics/" + m_framebuffer_name + "/blank"; + aml_set_sysfs_int(blank_framebuffer.c_str(), show ? 0 : 1); + return true; } bool CEGLNativeTypeAmlogic::SetDisplayResolution(const char *resolution) { CStdString modestr = resolution; // switch display resolution - set_sysfs_str("/sys/class/display/mode", modestr.c_str()); - usleep(250 * 1000); + aml_set_sysfs_str("/sys/class/display/mode", modestr.c_str()); // setup gui freescale depending on display resolution DisableFreeScale(); @@ -279,6 +242,7 @@ bool CEGLNativeTypeAmlogic::ModeToResolution(const char *mode, RESOLUTION_INFO * CStdString fromMode = mode; fromMode.Trim(); // strips, for example, 720p* to 720p + // the * indicate the 'native' mode of the display if (fromMode.Right(1) == "*") fromMode = fromMode.Left(std::max(0, (int)fromMode.size() - 1)); @@ -286,56 +250,79 @@ bool CEGLNativeTypeAmlogic::ModeToResolution(const char *mode, RESOLUTION_INFO * { res->iWidth = 1280; res->iHeight= 720; - res->iScreenWidth = res->iWidth; - res->iScreenHeight = res->iHeight; + res->iScreenWidth = 1280; + res->iScreenHeight= 720; res->fRefreshRate = 60; - res->dwFlags= D3DPRESENTFLAG_PROGRESSIVE; + res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE; } else if (fromMode.Equals("720p50hz")) { res->iWidth = 1280; res->iHeight= 720; - res->iScreenWidth = res->iWidth; - res->iScreenHeight = res->iHeight; + res->iScreenWidth = 1280; + res->iScreenHeight= 720; res->fRefreshRate = 50; - res->dwFlags= D3DPRESENTFLAG_PROGRESSIVE; + res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE; } else if (fromMode.Equals("1080p")) { res->iWidth = 1280; res->iHeight= 720; - res->iScreenWidth = 1920; - res->iScreenHeight = 1080; + res->iScreenWidth = 1920; + res->iScreenHeight= 1080; res->fRefreshRate = 60; - res->dwFlags= D3DPRESENTFLAG_PROGRESSIVE; + res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE; } - else if (fromMode.Equals("1080p50hz")) + else if (fromMode.Equals("1080p24hz")) { + res->iWidth = 1280; + res->iHeight= 720; res->iScreenWidth = 1920; res->iScreenHeight= 1080; + res->fRefreshRate = 24; + res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE; + } + else if (fromMode.Equals("1080p30hz")) + { res->iWidth = 1280; res->iHeight= 720; - res->fRefreshRate = 50; - res->dwFlags= D3DPRESENTFLAG_PROGRESSIVE; + res->iScreenWidth = 1920; + res->iScreenHeight= 1080; + res->fRefreshRate = 30; + res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE; } - else if (fromMode.Equals("1080i")) + else if (fromMode.Equals("1080p50hz")) { + res->iWidth = 1280; + res->iHeight= 720; res->iScreenWidth = 1920; res->iScreenHeight= 1080; + res->fRefreshRate = 50; + res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE; + } + else if (fromMode.Equals("1080i")) + { res->iWidth = 1280; res->iHeight= 720; + res->iScreenWidth = 1920; + res->iScreenHeight= 1080; res->fRefreshRate = 60; - res->dwFlags= D3DPRESENTFLAG_INTERLACED; + res->dwFlags = D3DPRESENTFLAG_INTERLACED; } else if (fromMode.Equals("1080i50hz")) { - res->iWidth = 1920; - res->iHeight= 1080; - res->iScreenWidth = 1280; - res->iScreenHeight= 720; + res->iWidth = 1280; + res->iHeight= 720; + res->iScreenWidth = 1920; + res->iScreenHeight= 1080; res->fRefreshRate = 50; - res->dwFlags= D3DPRESENTFLAG_INTERLACED; + res->dwFlags = D3DPRESENTFLAG_INTERLACED; } + else + { + return false; + } + res->iScreen = 0; res->bFullScreen = true; @@ -349,68 +336,50 @@ bool CEGLNativeTypeAmlogic::ModeToResolution(const char *mode, RESOLUTION_INFO * void CEGLNativeTypeAmlogic::EnableFreeScale() { - // remove default OSD and video path (default_osd default) - set_sysfs_str("/sys/class/vfm/map", "rm all"); - usleep(60 * 1000); - - // add OSD path - set_sysfs_str("/sys/class/vfm/map", "add osdpath osd amvideo"); // enable OSD free scale using frame buffer size of 720p - set_sysfs_int("/sys/class/graphics/fb0/free_scale", 0); - set_sysfs_int("/sys/class/graphics/fb1/free_scale", 0); - set_sysfs_int("/sys/class/graphics/fb0/scale_width", 1280); - set_sysfs_int("/sys/class/graphics/fb0/scale_height", 720); - set_sysfs_int("/sys/class/graphics/fb1/scale_width", 1280); - set_sysfs_int("/sys/class/graphics/fb1/scale_height", 720); - set_sysfs_int("/sys/class/graphics/fb0/free_scale", 1); - set_sysfs_int("/sys/class/graphics/fb1/free_scale", 1); - usleep(60 * 1000); - // remove OSD path - set_sysfs_int("/sys/class/graphics/fb0/free_scale", 0); - set_sysfs_int("/sys/class/graphics/fb1/free_scale", 0); - set_sysfs_str("/sys/class/vfm/map", "rm osdpath"); - usleep(60 * 1000); - // add video path - set_sysfs_str("/sys/class/vfm/map", "add videopath decoder ppmgr amvideo"); + aml_set_sysfs_int("/sys/class/graphics/fb0/free_scale", 0); + aml_set_sysfs_int("/sys/class/graphics/fb1/free_scale", 0); + aml_set_sysfs_int("/sys/class/graphics/fb0/scale_width", 1280); + aml_set_sysfs_int("/sys/class/graphics/fb0/scale_height", 720); + aml_set_sysfs_int("/sys/class/graphics/fb1/scale_width", 1280); + aml_set_sysfs_int("/sys/class/graphics/fb1/scale_height", 720); + // enable video free scale (scaling to 1920x1080 with frame buffer size 1280x720) - set_sysfs_int("/sys/class/ppmgr/ppscaler", 0); - set_sysfs_int("/sys/class/video/disable_video", 1); - set_sysfs_int("/sys/class/ppmgr/ppscaler", 1); - set_sysfs_str("/sys/class/ppmgr/ppscaler_rect", "0 0 1919 1079 0"); - set_sysfs_str("/sys/class/ppmgr/disp", "1280 720"); - usleep(60 * 1000); + aml_set_sysfs_int("/sys/class/ppmgr/ppscaler", 0); + aml_set_sysfs_int("/sys/class/video/disable_video", 1); + aml_set_sysfs_int("/sys/class/ppmgr/ppscaler", 1); + aml_set_sysfs_str("/sys/class/ppmgr/ppscaler_rect", "0 0 1919 1079 0"); + aml_set_sysfs_str("/sys/class/ppmgr/disp", "1280 720"); + // + aml_set_sysfs_int("/sys/class/graphics/fb0/scale_width", 1280); + aml_set_sysfs_int("/sys/class/graphics/fb0/scale_height", 720); + aml_set_sysfs_int("/sys/class/graphics/fb1/scale_width", 1280); + aml_set_sysfs_int("/sys/class/graphics/fb1/scale_height", 720); // - set_sysfs_int("/sys/class/graphics/fb0/free_scale", 0); - set_sysfs_int("/sys/class/graphics/fb1/free_scale", 0); - set_sysfs_int("/sys/class/graphics/fb0/scale_width", 1280); - set_sysfs_int("/sys/class/graphics/fb0/scale_height", 720); - set_sysfs_int("/sys/class/graphics/fb1/scale_width", 1280); - set_sysfs_int("/sys/class/graphics/fb1/scale_height", 720); - set_sysfs_int("/sys/class/graphics/fb0/free_scale", 1); - set_sysfs_int("/sys/class/graphics/fb1/free_scale", 1); - usleep(60 * 1000); + aml_set_sysfs_int("/sys/class/video/disable_video", 2); + aml_set_sysfs_str("/sys/class/display/axis", "0 0 1279 719 0 0 0 0"); + aml_set_sysfs_str("/sys/class/ppmgr/ppscaler_rect", "0 0 1279 719 1"); // - set_sysfs_int("/sys/class/video/disable_video", 2); - set_sysfs_str("/sys/class/display/axis", "0 0 1279 719 0 0 0 0"); - set_sysfs_str("/sys/class/ppmgr/ppscaler_rect", "0 0 1279 719 1"); + aml_set_sysfs_int("/sys/class/graphics/fb0/free_scale", 1); + aml_set_sysfs_int("/sys/class/graphics/fb1/free_scale", 1); + aml_set_sysfs_str("/sys/class/graphics/fb0/free_scale_axis", "0 0 1279 719"); } void CEGLNativeTypeAmlogic::DisableFreeScale() { // turn off frame buffer freescale - set_sysfs_int("/sys/class/graphics/fb0/free_scale", 0); - set_sysfs_int("/sys/class/graphics/fb1/free_scale", 0); - // revert to default video paths - set_sysfs_str("/sys/class/vfm/map", "rm all"); - set_sysfs_str("/sys/class/vfm/map", "add default_osd osd amvideo"); - set_sysfs_str("/sys/class/vfm/map", "add default decoder ppmgr amvideo"); - // disable post processing scaler and disable_video special mode - set_sysfs_int("/sys/class/ppmgr/ppscaler", 0); - set_sysfs_int("/sys/class/video/disable_video", 0); + aml_set_sysfs_int("/sys/class/graphics/fb0/free_scale", 0); + aml_set_sysfs_int("/sys/class/graphics/fb1/free_scale", 0); + aml_set_sysfs_str("/sys/class/graphics/fb0/free_scale_axis", "0 0 1279 719"); + + aml_set_sysfs_int("/sys/class/ppmgr/ppscaler", 0); + aml_set_sysfs_int("/sys/class/video/disable_video", 0); + // now default video display to off + aml_set_sysfs_int("/sys/class/video/disable_video", 1); // revert display axis int fd0; - std::string framebuffer = "/dev/fb0"; + std::string framebuffer = "/dev/" + m_framebuffer_name; if ((fd0 = open(framebuffer.c_str(), O_RDWR)) >= 0) { @@ -418,30 +387,9 @@ void CEGLNativeTypeAmlogic::DisableFreeScale() if (ioctl(fd0, FBIOGET_VSCREENINFO, &vinfo) == 0) { char daxis_str[255] = {0}; - sprintf(daxis_str, "%d %d %d %d 0 0 0 0", 0, 0, vinfo.xres, vinfo.yres); - set_sysfs_str("/sys/class/display/axis", daxis_str); + sprintf(daxis_str, "%d %d %d %d 0 0 0 0", 0, 0, vinfo.xres-1, vinfo.yres-1); + aml_set_sysfs_str("/sys/class/display/axis", daxis_str); } close(fd0); } } - -void CEGLNativeTypeAmlogic::SetCpuMinLimit(bool limit) -{ - // when playing hw decoded audio, we cannot drop below 600MHz - // or risk hw audio issues. AML code does a 2X scaling based off - // /sys/class/audiodsp/codec_mips but tests show that this is - // seems risky so we just clamp to 600Mhz to be safe. - - // only adjust if we are running "ondemand" - char scaling_governor[256] = {0}; - get_sysfs_str("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor", scaling_governor, 255); - if (strncmp(scaling_governor, "ondemand", 255)) - return; - - int freq; - if (limit) - freq = 600000; - else - freq = get_sysfs_int("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq"); - set_sysfs_int("/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq", freq); -} diff --git a/xbmc/windowing/egl/EGLNativeTypeAmlogic.h b/xbmc/windowing/egl/EGLNativeTypeAmlogic.h index 639a09e8ca..968bf2ba28 100644 --- a/xbmc/windowing/egl/EGLNativeTypeAmlogic.h +++ b/xbmc/windowing/egl/EGLNativeTypeAmlogic.h @@ -48,14 +48,11 @@ public: virtual bool ShowWindow(bool show); protected: - int get_sysfs_str(const char *path, char *valstr, const int size) const; - int set_sysfs_str(const char *path, const char *val) const; - int set_sysfs_int(const char *path, const int val) const; - int get_sysfs_int(const char *path) const; - bool SetDisplayResolution(const char *resolution); bool ModeToResolution(const char *mode, RESOLUTION_INFO *res) const; void EnableFreeScale(); void DisableFreeScale(); - void SetCpuMinLimit(bool limit); + +private: + std::string m_framebuffer_name; }; diff --git a/xbmc/windowing/egl/WinSystemEGL.cpp b/xbmc/windowing/egl/WinSystemEGL.cpp index 85a5ef7c36..245b439227 100644 --- a/xbmc/windowing/egl/WinSystemEGL.cpp +++ b/xbmc/windowing/egl/WinSystemEGL.cpp @@ -26,7 +26,7 @@ #include "guilib/GraphicContext.h" #include "settings/DisplaySettings.h" #include "settings/Settings.h" -#include "settings/GUISettings.h" +#include "settings/DisplaySettings.h" #include "utils/log.h" #include "EGLWrapper.h" #include "EGLQuirks.h" @@ -448,7 +448,7 @@ bool CWinSystemEGL::Support3D(int width, int height, uint32_t mode) const RESOLUTION_INFO &curr = CDisplaySettings::Get().GetResolutionInfo(g_graphicsContext.GetVideoResolution()); // if we are using automatic hdmi mode switching - if (g_guiSettings.GetInt("videoplayer.adjustrefreshrate") != ADJUST_REFRESHRATE_OFF) + if (CSettings::Get().GetInt("videoplayer.adjustrefreshrate") != ADJUST_REFRESHRATE_OFF) { int searchWidth = curr.iScreenWidth; int searchHeight = curr.iScreenHeight; diff --git a/xbmc/windowing/osx/WinSystemIOS.mm b/xbmc/windowing/osx/WinSystemIOS.mm index a2a4a665c7..1002e13229 100644 --- a/xbmc/windowing/osx/WinSystemIOS.mm +++ b/xbmc/windowing/osx/WinSystemIOS.mm @@ -31,7 +31,6 @@ #include "utils/log.h" #include "filesystem/SpecialProtocol.h" #include "settings/DisplaySettings.h" -#include "settings/Settings.h" #include "guilib/GraphicContext.h" #include "guilib/Texture.h" #include <vector> diff --git a/xbmc/windowing/osx/WinSystemOSX.mm b/xbmc/windowing/osx/WinSystemOSX.mm index 1372a8c6be..cb86e0a1b9 100644 --- a/xbmc/windowing/osx/WinSystemOSX.mm +++ b/xbmc/windowing/osx/WinSystemOSX.mm @@ -30,7 +30,7 @@ #include "guilib/GUIWindowManager.h" #include "settings/DisplaySettings.h" #include "settings/Settings.h" -#include "settings/GUISettings.h" +#include "settings/DisplaySettings.h" #include "input/KeyboardStat.h" #include "threads/SingleLock.h" #include "utils/log.h" @@ -710,6 +710,7 @@ bool CWinSystemOSX::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl static NSView* last_view = NULL; static NSSize last_view_size; static NSPoint last_view_origin; + static NSInteger last_window_level = NSNormalWindowLevel; bool was_fullscreen = m_bFullScreen; static int lastDisplayNr = res.iScreen; NSOpenGLContext* cur_context; @@ -744,7 +745,7 @@ bool CWinSystemOSX::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl // send pre-configuration change now and do not // wait for switch videomode callback. This gives just // a little more advanced notice of the display pre-change. - if (g_guiSettings.GetInt("videoplayer.adjustrefreshrate") != ADJUST_REFRESHRATE_OFF) + if (CSettings::Get().GetInt("videoplayer.adjustrefreshrate") != ADJUST_REFRESHRATE_OFF) CheckDisplayChanging(kCGDisplayBeginConfigurationFlag); // switch videomode @@ -779,8 +780,9 @@ bool CWinSystemOSX::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl last_view_origin = [last_view frame].origin; last_window_screen = [[last_view window] screen]; last_window_origin = [[last_view window] frame].origin; + last_window_level = [[last_view window] level]; - if (g_guiSettings.GetBool("videoscreen.fakefullscreen")) + if (CSettings::Get().GetBool("videoscreen.fakefullscreen")) { // This is Cocca Windowed FullScreen Mode // Get the screen rect of our current display @@ -888,10 +890,10 @@ bool CWinSystemOSX::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl if (GetDisplayID(res.iScreen) == kCGDirectMainDisplay) SetMenuBarVisible(true); - if (g_guiSettings.GetBool("videoscreen.fakefullscreen")) + if (CSettings::Get().GetBool("videoscreen.fakefullscreen")) { // restore the windowed window level - [[last_view window] setLevel:NSNormalWindowLevel]; + [[last_view window] setLevel:last_window_level]; // Get rid of the new window we created. if (windowedFullScreenwindow != NULL) diff --git a/xbmc/windowing/windows/WinEventsWin32.cpp b/xbmc/windowing/windows/WinEventsWin32.cpp index 471bb9bf2a..e1d663a8c8 100644 --- a/xbmc/windowing/windows/WinEventsWin32.cpp +++ b/xbmc/windowing/windows/WinEventsWin32.cpp @@ -43,8 +43,8 @@ #include "guilib/GUIControl.h" // for EVENT_RESULT #include "powermanagement/windows/Win32PowerSyscall.h" #include "Shlobj.h" -#include "settings/Settings.h" #include "settings/AdvancedSettings.h" +#include "settings/Settings.h" #include "peripherals/Peripherals.h" #include "utils/JobManager.h" #include "network/Zeroconf.h" @@ -487,7 +487,7 @@ LRESULT CALLBACK CWinEventsWin32::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, L case SC_MONITORPOWER: if (g_application.IsPlaying() || g_application.IsPaused()) return 0; - else if(g_guiSettings.GetInt("powermanagement.displaysoff") == 0) + else if(CSettings::Get().GetInt("powermanagement.displaysoff") == 0) return 0; break; case SC_SCREENSAVE: diff --git a/xbmc/windowing/windows/WinSystemWin32.cpp b/xbmc/windowing/windows/WinSystemWin32.cpp index 9cc9b23bc0..6b27a58bba 100644 --- a/xbmc/windowing/windows/WinSystemWin32.cpp +++ b/xbmc/windowing/windows/WinSystemWin32.cpp @@ -22,9 +22,9 @@ #include "WinEventsWin32.h" #include "resource.h" #include "guilib/gui3d.h" -#include "settings/DisplaySettings.h" -#include "settings/GUISettings.h" #include "settings/AdvancedSettings.h" +#include "settings/DisplaySettings.h" +#include "settings/Settings.h" #include "utils/log.h" #ifdef _WIN32 @@ -257,7 +257,7 @@ bool CWinSystemWin32::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool { m_IsAlteringWindow = true; - CLog::Log(LOGDEBUG, "%s (%s) on screen %d with size %dx%d, refresh %f%s", __FUNCTION__, !fullScreen ? "windowed" : (g_guiSettings.GetBool("videoscreen.fakefullscreen") ? "windowed fullscreen" : "true fullscreen"), res.iScreen, res.iWidth, res.iHeight, res.fRefreshRate, (res.dwFlags & D3DPRESENTFLAG_INTERLACED) ? "i" : ""); + CLog::Log(LOGDEBUG, "%s (%s) on screen %d with size %dx%d, refresh %f%s", __FUNCTION__, !fullScreen ? "windowed" : (CSettings::Get().GetBool("videoscreen.fakefullscreen") ? "windowed fullscreen" : "true fullscreen"), res.iScreen, res.iWidth, res.iHeight, res.fRefreshRate, (res.dwFlags & D3DPRESENTFLAG_INTERLACED) ? "i" : ""); bool forceResize = false; @@ -267,7 +267,7 @@ bool CWinSystemWin32::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool RestoreDesktopResolution(m_nScreen); } - if(!m_bFullScreen && fullScreen) + if(m_hWnd && !m_bFullScreen && fullScreen) { // save position of windowed mode WINDOWINFO wi; @@ -284,7 +284,7 @@ bool CWinSystemWin32::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool m_nHeight = res.iHeight; m_bBlankOtherDisplay = blankOtherDisplays; - if (fullScreen && g_guiSettings.GetBool("videoscreen.fakefullscreen")) + if (fullScreen && CSettings::Get().GetBool("videoscreen.fakefullscreen")) ChangeResolution(res); ResizeInternal(forceResize); @@ -350,6 +350,8 @@ RECT CWinSystemWin32::ScreenRect(int screen) bool CWinSystemWin32::ResizeInternal(bool forceRefresh) { + if (m_hWnd == NULL) + return false; DWORD dwStyle = WS_CLIPCHILDREN; HWND windowAfter; RECT rc; diff --git a/xbmc/windowing/windows/WinSystemWin32DX.cpp b/xbmc/windowing/windows/WinSystemWin32DX.cpp index 4bcff0716f..f76763aeed 100644 --- a/xbmc/windowing/windows/WinSystemWin32DX.cpp +++ b/xbmc/windowing/windows/WinSystemWin32DX.cpp @@ -20,7 +20,7 @@ #include "WinSystemWin32DX.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "guilib/gui3d.h" #ifdef HAS_DX @@ -38,7 +38,7 @@ CWinSystemWin32DX::~CWinSystemWin32DX() bool CWinSystemWin32DX::UseWindowedDX(bool fullScreen) { - return (g_guiSettings.GetBool("videoscreen.fakefullscreen") || !fullScreen); + return (CSettings::Get().GetBool("videoscreen.fakefullscreen") || !fullScreen); } bool CWinSystemWin32DX::CreateNewWindow(CStdString name, bool fullScreen, RESOLUTION_INFO& res, PHANDLE_EVENT_FUNC userFunction) diff --git a/xbmc/windowing/windows/WinSystemWin32GL.cpp b/xbmc/windowing/windows/WinSystemWin32GL.cpp index d5346309a4..19028fdf25 100644 --- a/xbmc/windowing/windows/WinSystemWin32GL.cpp +++ b/xbmc/windowing/windows/WinSystemWin32GL.cpp @@ -26,7 +26,7 @@ */ #include "WinSystemWin32GL.h" #include "WIN32Util.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "guilib/gui3d.h" #ifdef HAS_GL @@ -83,7 +83,7 @@ bool CWinSystemWin32GL::InitRenderSystem() CWIN32Util::CheckGLVersion(); - g_guiSettings.SetBool("videoscreen.fakefullscreen", true); + CSettings::Get().SetBool("videoscreen.fakefullscreen", true); return true; } diff --git a/xbmc/windows/GUIMediaWindow.cpp b/xbmc/windows/GUIMediaWindow.cpp index 4fb5ef286c..2f06406df6 100644 --- a/xbmc/windows/GUIMediaWindow.cpp +++ b/xbmc/windows/GUIMediaWindow.cpp @@ -40,7 +40,7 @@ #include "dialogs/GUIDialogProgress.h" #include "profiles/ProfilesManager.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "URL.h" #include "dialogs/GUIDialogSmartPlaylistEditor.h" @@ -597,7 +597,7 @@ void CGUIMediaWindow::SortItems(CFileItemList &items) SortDescription sorting; sorting.sortBy = sortBy; sorting.sortOrder = items.GetProperty(PROPERTY_SORT_ASCENDING).asBoolean() ? SortOrderAscending : SortOrderDescending; - sorting.sortAttributes = g_guiSettings.GetBool("filelists.ignorethewhensorting") ? SortAttributeIgnoreArticle : SortAttributeNone; + sorting.sortAttributes = CSettings::Get().GetBool("filelists.ignorethewhensorting") ? SortAttributeIgnoreArticle : SortAttributeNone; // if the sort order is descending, we need to switch the original sort order, as we assume // in CGUIViewState::AddPlaylistOrder that SORT_METHOD_PLAYLIST_ORDER is ascending. @@ -980,7 +980,7 @@ bool CGUIMediaWindow::OnClick(int iItem) return true; } - if (!pItem->m_bIsFolder && pItem->IsFileFolder()) + if (!pItem->m_bIsFolder && pItem->IsFileFolder(EFILEFOLDER_MASK_ONCLICK)) { XFILE::IFileDirectory *pFileDirectory = NULL; pFileDirectory = XFILE::CFileDirectoryFactory::Create(pItem->GetPath(), pItem.get(), ""); @@ -1090,8 +1090,8 @@ bool CGUIMediaWindow::OnClick(int iItem) } // If karaoke song is being played AND popup autoselector is enabled, the playlist should not be added - bool do_not_add_karaoke = g_guiSettings.GetBool("karaoke.enabled") && - g_guiSettings.GetBool("karaoke.autopopupselector") && pItem->IsKaraoke(); + bool do_not_add_karaoke = CSettings::Get().GetBool("karaoke.enabled") && + CSettings::Get().GetBool("karaoke.autopopupselector") && pItem->IsKaraoke(); bool autoplay = m_guiState.get() && m_guiState->AutoPlayNextItem(); if (m_vecItems->IsPlugin()) @@ -1358,7 +1358,7 @@ bool CGUIMediaWindow::OnPlayMedia(int iItem) if (pItem->IsInternetStream() || pItem->IsPlayList()) bResult = g_application.PlayMedia(*pItem, m_guiState->GetPlaylist()); else - bResult = g_application.PlayFile(*pItem); + bResult = g_application.PlayFile(*pItem) == PLAYBACK_OK; if (pItem->m_lStartOffset == STARTOFFSET_RESUME) pItem->m_lStartOffset = 0; @@ -1582,6 +1582,10 @@ void CGUIMediaWindow::GetContextButtons(int itemNumber, CContextButtons &buttons else buttons.Add(CONTEXT_BUTTON_ADD_FAVOURITE, 14076); // Add To Favourites; } + + if (item->IsFileFolder(EFILEFOLDER_MASK_ONBROWSE)) + buttons.Add(CONTEXT_BUTTON_BROWSE_INTO, 37015); + } bool CGUIMediaWindow::OnContextButton(int itemNumber, CONTEXT_BUTTON button) @@ -1607,6 +1611,13 @@ bool CGUIMediaWindow::OnContextButton(int itemNumber, CONTEXT_BUTTON button) Refresh(); return true; } + case CONTEXT_BUTTON_BROWSE_INTO: + { + CFileItemPtr item = m_vecItems->Get(itemNumber); + if(Update(item->GetPath())) + return true; + return true; + } case CONTEXT_BUTTON_USER1: case CONTEXT_BUTTON_USER2: case CONTEXT_BUTTON_USER3: diff --git a/xbmc/windows/GUIWindowFileManager.cpp b/xbmc/windows/GUIWindowFileManager.cpp index b750e9ce99..9be0493168 100644 --- a/xbmc/windows/GUIWindowFileManager.cpp +++ b/xbmc/windows/GUIWindowFileManager.cpp @@ -25,6 +25,7 @@ #include "Util.h" #include "filesystem/Directory.h" #include "filesystem/ZipManager.h" +#include "filesystem/FileDirectoryFactory.h" #include "dialogs/GUIDialogContextMenu.h" #include "guilib/GUIListContainer.h" #include "dialogs/GUIDialogMediaSource.h" @@ -47,10 +48,9 @@ #include "playlists/PlayList.h" #include "utils/AsyncFileCopy.h" #include "storage/MediaManager.h" -#include "settings/Settings.h" #include "settings/AdvancedSettings.h" -#include "settings/GUISettings.h" #include "settings/MediaSourceSettings.h" +#include "settings/Settings.h" #include "input/MouseStat.h" #include "guilib/LocalizeStrings.h" #include "utils/StringUtils.h" @@ -367,37 +367,6 @@ void CGUIWindowFileManager::ClearFileItems(int iList) void CGUIWindowFileManager::UpdateButtons() { - - /* - // Update sorting control - bool bSortOrder=false; - if ( m_bViewSource ) - { - if (m_strSourceDirectory.IsEmpty()) - bSortOrder=g_settings.m_bMyFilesSourceRootSortOrder; - else - bSortOrder=g_settings.m_bMyFilesSourceSortOrder; - } - else - { - if (m_strDestDirectory.IsEmpty()) - bSortOrder=g_settings.m_bMyFilesDestRootSortOrder; - else - bSortOrder=g_settings.m_bMyFilesDestSortOrder; - } - - if (bSortOrder) - { - CGUIMessage msg(GUI_MSG_DESELECTED,GetID(), CONTROL_BTNSORTASC); - g_windowManager.SendMessage(msg); - } - else - { - CGUIMessage msg(GUI_MSG_SELECTED,GetID(), CONTROL_BTNSORTASC); - g_windowManager.SendMessage(msg); - } - - */ // update our current directory labels CStdString strDir = CURL(m_Directory[0]->GetPath()).GetWithoutUserDetails(); if (strDir.IsEmpty()) @@ -490,7 +459,7 @@ bool CGUIWindowFileManager::Update(int iList, const CStdString &strDirectory) CStdString strParentPath; URIUtils::GetParentPath(strDirectory, strParentPath); - if (strDirectory.IsEmpty() && (m_vecItems[iList]->Size() == 0 || g_guiSettings.GetBool("filelists.showaddsourcebuttons"))) + if (strDirectory.IsEmpty() && (m_vecItems[iList]->Size() == 0 || CSettings::Get().GetBool("filelists.showaddsourcebuttons"))) { // add 'add source button' CStdString strLabel = g_localizeStrings.Get(1026); CFileItemPtr pItem(new CFileItem(strLabel)); @@ -502,7 +471,7 @@ bool CGUIWindowFileManager::Update(int iList, const CStdString &strDirectory) pItem->SetSpecialSort(SortSpecialOnBottom); m_vecItems[iList]->Add(pItem); } - else if (items.IsEmpty() || g_guiSettings.GetBool("filelists.showparentdiritems")) + else if (items.IsEmpty() || CSettings::Get().GetBool("filelists.showparentdiritems")) { CFileItemPtr pItem(new CFileItem("..")); pItem->SetPath(m_rootDir.IsSource(strDirectory) ? "" : strParentPath); @@ -573,6 +542,17 @@ void CGUIWindowFileManager::OnClick(int iList, int iItem) return; } + if (!pItem->m_bIsFolder && pItem->IsFileFolder(EFILEFOLDER_MASK_ALL)) + { + XFILE::IFileDirectory *pFileDirectory = NULL; + pFileDirectory = XFILE::CFileDirectoryFactory::Create(pItem->GetPath(), pItem.get(), ""); + if(pFileDirectory) + pItem->m_bIsFolder = true; + else if(pItem->m_bIsFolder) + pItem->m_bIsFolder = false; + delete pFileDirectory; + } + if (pItem->m_bIsFolder) { // save path + drive type because of the possible refresh diff --git a/xbmc/windows/GUIWindowLoginScreen.cpp b/xbmc/windows/GUIWindowLoginScreen.cpp index 699b5959ae..d30124ba8d 100644 --- a/xbmc/windows/GUIWindowLoginScreen.cpp +++ b/xbmc/windows/GUIWindowLoginScreen.cpp @@ -42,7 +42,7 @@ #include "GUIUserMessages.h" #include "guilib/GUIWindowManager.h" #include "dialogs/GUIDialogOK.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "FileItem.h" #include "guilib/Key.h" #include "guilib/LocalizeStrings.h" @@ -234,7 +234,7 @@ bool CGUIWindowLoginScreen::OnPopupMenu(int iItem) if (choice == 3) { if (g_passwordManager.CheckLock(CProfilesManager::Get().GetMasterProfile().getLockMode(),CProfilesManager::Get().GetMasterProfile().getLockCode(),20075)) - g_passwordManager.iMasterLockRetriesLeft = g_guiSettings.GetInt("masterlock.maxretries"); + g_passwordManager.iMasterLockRetriesLeft = CSettings::Get().GetInt("masterlock.maxretries"); else // be inconvenient CApplicationMessenger::Get().Shutdown(); diff --git a/xbmc/windows/GUIWindowScreensaver.cpp b/xbmc/windows/GUIWindowScreensaver.cpp index 0e63802586..fc790e3263 100644 --- a/xbmc/windows/GUIWindowScreensaver.cpp +++ b/xbmc/windows/GUIWindowScreensaver.cpp @@ -23,7 +23,7 @@ #include "addons/AddonManager.h" #include "Application.h" #include "GUIPassword.h" -#include "settings/GUISettings.h" +#include "settings/Settings.h" #include "GUIUserMessages.h" #include "guilib/GUIWindowManager.h" #include "threads/SingleLock.h" @@ -139,7 +139,7 @@ bool CGUIWindowScreensaver::OnMessage(CGUIMessage& message) m_addon.reset(); // Setup new screensaver instance AddonPtr addon; - if (!CAddonMgr::Get().GetAddon(g_guiSettings.GetString("screensaver.mode"), addon, ADDON_SCREENSAVER)) + if (!CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), addon, ADDON_SCREENSAVER)) return false; m_addon = boost::dynamic_pointer_cast<CScreenSaver>(addon); diff --git a/xbmc/windows/GUIWindowWeather.cpp b/xbmc/windows/GUIWindowWeather.cpp index 925031e718..c67d45a5a9 100644 --- a/xbmc/windows/GUIWindowWeather.cpp +++ b/xbmc/windows/GUIWindowWeather.cpp @@ -24,7 +24,6 @@ #include "GUIWindowWeather.h" #include "guilib/GUIImage.h" #include "utils/Weather.h" -#include "settings/GUISettings.h" #include "guilib/GUIWindowManager.h" #include "utils/URIUtils.h" #ifdef HAS_PYTHON |