Merge pull request #1129 from jmarshallnz/remove_smb_auth_details_in_add_source
authorjmarshallnz <jcmarsha@gmail.com>
Wed, 11 Jul 2012 22:33:15 +0000 (15:33 -0700)
committerjmarshallnz <jcmarsha@gmail.com>
Wed, 11 Jul 2012 22:33:15 +0000 (15:33 -0700)
Remove smb auth details in add source

284 files changed:
Makefile.in
XBMC-ATV2.xcodeproj/project.pbxproj
XBMC-IOS.xcodeproj/project.pbxproj
XBMC.xcodeproj/project.pbxproj
addons/metadata.album.universal/addon.xml [new file with mode: 0644]
addons/metadata.album.universal/albumuniversal.xml [new file with mode: 0644]
addons/metadata.album.universal/changelog.txt [new file with mode: 0644]
addons/metadata.album.universal/icon.png [new file with mode: 0644]
addons/metadata.album.universal/resources/language/English/strings.xml [new file with mode: 0644]
addons/metadata.album.universal/resources/settings.xml [new file with mode: 0644]
addons/metadata.albums.allmusic.com/addon.xml [deleted file]
addons/metadata.albums.allmusic.com/allmusic.xml [deleted file]
addons/metadata.albums.allmusic.com/icon.png [deleted file]
addons/metadata.albums.allmusic.com/resources/language/Bulgarian/strings.xml [deleted file]
addons/metadata.albums.allmusic.com/resources/language/Chinese (Simple)/strings.xml [deleted file]
addons/metadata.albums.allmusic.com/resources/language/Dutch/strings.xml [deleted file]
addons/metadata.albums.allmusic.com/resources/language/English/strings.xml [deleted file]
addons/metadata.albums.allmusic.com/resources/language/Finnish/strings.xml [deleted file]
addons/metadata.albums.allmusic.com/resources/language/French/strings.xml [deleted file]
addons/metadata.albums.allmusic.com/resources/language/German/strings.xml [deleted file]
addons/metadata.albums.allmusic.com/resources/language/Hungarian/strings.xml [deleted file]
addons/metadata.albums.allmusic.com/resources/language/Korean/strings.xml [deleted file]
addons/metadata.albums.allmusic.com/resources/language/Polish/strings.xml [deleted file]
addons/metadata.albums.allmusic.com/resources/language/Portuguese/strings.xml [deleted file]
addons/metadata.albums.allmusic.com/resources/language/Russian/strings.xml [deleted file]
addons/metadata.albums.allmusic.com/resources/language/Spanish/strings.xml [deleted file]
addons/metadata.albums.allmusic.com/resources/language/Swedish/strings.xml [deleted file]
addons/metadata.albums.allmusic.com/resources/settings.xml [deleted file]
addons/metadata.artists.allmusic.com/addon.xml [deleted file]
addons/metadata.artists.allmusic.com/allmusic.xml [deleted file]
addons/metadata.artists.allmusic.com/icon.png [deleted file]
addons/metadata.artists.allmusic.com/resources/language/Bulgarian/strings.xml [deleted file]
addons/metadata.artists.allmusic.com/resources/language/Chinese (Simple)/strings.xml [deleted file]
addons/metadata.artists.allmusic.com/resources/language/Dutch/strings.xml [deleted file]
addons/metadata.artists.allmusic.com/resources/language/English/strings.xml [deleted file]
addons/metadata.artists.allmusic.com/resources/language/Finnish/strings.xml [deleted file]
addons/metadata.artists.allmusic.com/resources/language/French/strings.xml [deleted file]
addons/metadata.artists.allmusic.com/resources/language/German/strings.xml [deleted file]
addons/metadata.artists.allmusic.com/resources/language/Hungarian/strings.xml [deleted file]
addons/metadata.artists.allmusic.com/resources/language/Korean/strings.xml [deleted file]
addons/metadata.artists.allmusic.com/resources/language/Polish/strings.xml [deleted file]
addons/metadata.artists.allmusic.com/resources/language/Portuguese/strings.xml [deleted file]
addons/metadata.artists.allmusic.com/resources/language/Russian/strings.xml [deleted file]
addons/metadata.artists.allmusic.com/resources/language/Spanish/strings.xml [deleted file]
addons/metadata.artists.allmusic.com/resources/language/Swedish/strings.xml [deleted file]
addons/metadata.artists.allmusic.com/resources/settings.xml [deleted file]
addons/metadata.artists.universal/addon.xml [new file with mode: 0644]
addons/metadata.artists.universal/artistuniversal.xml [new file with mode: 0644]
addons/metadata.artists.universal/changelog.txt [new file with mode: 0644]
addons/metadata.artists.universal/icon.png [new file with mode: 0644]
addons/metadata.artists.universal/resources/language/English/strings.xml [new file with mode: 0644]
addons/metadata.artists.universal/resources/settings.xml [new file with mode: 0644]
addons/metadata.common.allmusic.com/addon.xml
addons/metadata.common.allmusic.com/allmusic.xml
addons/metadata.common.allmusic.com/icon.png [new file with mode: 0644]
addons/metadata.common.amazon.de/addon.xml [new file with mode: 0644]
addons/metadata.common.amazon.de/amazonde.xml [new file with mode: 0644]
addons/metadata.common.fanart.tv/addon.xml [new file with mode: 0644]
addons/metadata.common.fanart.tv/fanarttv.xml [new file with mode: 0644]
addons/metadata.common.htbackdrops.com/addon.xml
addons/metadata.common.htbackdrops.com/htbackdrops.xml
addons/metadata.common.htbackdrops.com/icon.png [new file with mode: 0644]
addons/metadata.common.last.fm/addon.xml
addons/metadata.common.last.fm/icon.png [new file with mode: 0644]
addons/metadata.common.last.fm/lastfm.xml
addons/metadata.common.musicbrainz.org/addon.xml [new file with mode: 0644]
addons/metadata.common.musicbrainz.org/musicbrainz.xml [new file with mode: 0644]
addons/metadata.musicvideos.last.fm/addon.xml [new file with mode: 0644]
addons/metadata.musicvideos.last.fm/icon.png [new file with mode: 0644]
addons/metadata.musicvideos.last.fm/lastfmmusicvideos.xml [new file with mode: 0644]
addons/metadata.musicvideos.last.fm/resources/language/English/strings.xml [new file with mode: 0644]
addons/metadata.musicvideos.last.fm/resources/settings.xml [new file with mode: 0644]
addons/metadata.yahoomusic.com/addon.xml [deleted file]
addons/metadata.yahoomusic.com/icon.png [deleted file]
addons/metadata.yahoomusic.com/resources/language/Dutch/strings.xml [deleted file]
addons/metadata.yahoomusic.com/resources/language/English/strings.xml [deleted file]
addons/metadata.yahoomusic.com/resources/language/Finnish/strings.xml [deleted file]
addons/metadata.yahoomusic.com/resources/language/Hungarian/strings.xml [deleted file]
addons/metadata.yahoomusic.com/resources/language/Korean/strings.xml [deleted file]
addons/metadata.yahoomusic.com/resources/language/Polish/strings.xml [deleted file]
addons/metadata.yahoomusic.com/resources/language/Portuguese/strings.xml [deleted file]
addons/metadata.yahoomusic.com/resources/language/Swedish/strings.xml [deleted file]
addons/metadata.yahoomusic.com/resources/settings.xml [deleted file]
addons/metadata.yahoomusic.com/yahoomusic.xml [deleted file]
addons/skin.confluence/720p/IncludesBackgroundBuilding.xml
configure.in
language/English/strings.po
lib/cmyth/Win32/include/mysql/mysql.h
lib/cmyth/Win32/libcmyth.def
lib/cmyth/Win32/libcmyth.vcxproj
lib/cmyth/include/cmyth/cmyth.h
lib/cmyth/include/debug.h
lib/cmyth/include/refmem/atomic.h
lib/cmyth/include/refmem/refmem.h
lib/cmyth/libcmyth/bookmark.c
lib/cmyth/libcmyth/cmyth_local.h
lib/cmyth/libcmyth/cmyth_msc.h [new file with mode: 0644]
lib/cmyth/libcmyth/commbreak.c
lib/cmyth/libcmyth/connection.c
lib/cmyth/libcmyth/debug.c
lib/cmyth/libcmyth/event.c
lib/cmyth/libcmyth/file.c
lib/cmyth/libcmyth/freespace.c
lib/cmyth/libcmyth/keyframe.c
lib/cmyth/libcmyth/livetv.c
lib/cmyth/libcmyth/mysql_query.c
lib/cmyth/libcmyth/mythtv_mysql.c
lib/cmyth/libcmyth/posmap.c
lib/cmyth/libcmyth/proginfo.c
lib/cmyth/libcmyth/proglist.c
lib/cmyth/libcmyth/rec_num.c
lib/cmyth/libcmyth/recorder.c
lib/cmyth/libcmyth/ringbuf.c
lib/cmyth/libcmyth/safe_string.h
lib/cmyth/libcmyth/socket.c
lib/cmyth/libcmyth/timestamp.c
lib/cmyth/librefmem/debug_refmem.c
lib/cpluff/libcpluff/win32/cpluff.vcxproj
lib/cximage-6.0/ImageLib.vcxproj
lib/cximage-6.0/jasper/jasper.vcxproj
lib/cximage-6.0/jbig/jbig.vcxproj
lib/cximage-6.0/jpeg/Jpeg.vcxproj
lib/cximage-6.0/mng/mng.vcxproj
lib/cximage-6.0/png/png.vcxproj
lib/cximage-6.0/raw/libdcr.vcxproj
lib/cximage-6.0/tiff/Tiff.vcxproj
lib/cximage-6.0/zlib/zlib.vcxproj
lib/libRTV/libRTV.vcxproj
lib/libXDAAP/libXDAAP_win32/libXDAAP_win32.vcxproj
lib/libapetag/libapetag.vcxproj
lib/libass/xbmc/libass_win32/libass_win32_vs2010.vcxproj
lib/libexif/libexif.vcxproj
lib/libhdhomerun/hdhomerun/hdhomerun.vcxproj
lib/libhts/Win32/libhts_2010.vcxproj
lib/libid3tag/libid3tag/msvc++/libid3tag.vcxproj
lib/liblame/include/lame.def
lib/liblame/vc_solution/vc10_libmp3lame_dll.vcxproj
lib/libmad/msvc++/libmad.vcxproj
lib/libmodplug/libmodplug_2010.vcxproj
lib/libsidplay2/libsidplay/win/VC/libsidplay.vcxproj
lib/libsquish/vs7/squish/squish_2010.vcxproj
lib/stsound/StSoundLibrary/StSoundLibrary.vcxproj
lib/win32/pcre/libpcre/libpcre.vcxproj
project/VS2010Express/UnrarXLib.vcxproj
project/VS2010Express/XBMC.vcxproj
project/VS2010Express/XBMC.vcxproj.filters
project/VS2010Express/XbmcCommons.vcxproj
project/VS2010Express/XbmcThreads.vcxproj
system/Lircmap.xml
system/library/video/movies/tags.xml [new file with mode: 0644]
xbmc-xrandr.c
xbmc/Application.cpp
xbmc/Application.h
xbmc/GUIInfoManager.cpp
xbmc/GUIInfoManager.h
xbmc/NfoFile.cpp
xbmc/NfoFile.h
xbmc/SystemGlobals.cpp
xbmc/TextureDatabase.cpp
xbmc/ThumbLoader.cpp
xbmc/addons/AddonDatabase.cpp
xbmc/addons/AddonDll.h
xbmc/cores/AudioEngine/AEFactory.h
xbmc/cores/AudioEngine/AESinkFactory.cpp
xbmc/cores/AudioEngine/AESinkFactory.h
xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHAL.cpp
xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALIOS.cpp
xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioUnit.cpp
xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp
xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h
xbmc/cores/AudioEngine/Engines/SoftAE/SoftAESound.cpp
xbmc/cores/AudioEngine/Engines/SoftAE/SoftAESound.h
xbmc/cores/AudioEngine/Engines/SoftAE/SoftAEStream.cpp
xbmc/cores/AudioEngine/Interfaces/AE.h
xbmc/cores/AudioEngine/Interfaces/AESink.h
xbmc/cores/AudioEngine/Interfaces/AESound.h
xbmc/cores/AudioEngine/Interfaces/AEStream.h
xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp
xbmc/cores/AudioEngine/Sinks/AESinkALSA.h
xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp
xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.h
xbmc/cores/AudioEngine/Sinks/AESinkNULL.cpp
xbmc/cores/AudioEngine/Sinks/AESinkNULL.h
xbmc/cores/AudioEngine/Sinks/AESinkOSS.cpp
xbmc/cores/AudioEngine/Sinks/AESinkOSS.h
xbmc/cores/AudioEngine/Sinks/AESinkProfiler.cpp
xbmc/cores/AudioEngine/Sinks/AESinkProfiler.h
xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp
xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.h
xbmc/cores/AudioEngine/Utils/AEBitstreamPacker.cpp
xbmc/cores/AudioEngine/Utils/AEBitstreamPacker.h
xbmc/cores/AudioEngine/Utils/AEConvert.h
xbmc/cores/AudioEngine/Utils/AEDeviceInfo.cpp
xbmc/cores/AudioEngine/Utils/AEDeviceInfo.h
xbmc/cores/AudioEngine/Utils/AEELDParser.cpp
xbmc/cores/AudioEngine/Utils/AEELDParser.h
xbmc/cores/AudioEngine/Utils/AEPackIEC61937.cpp
xbmc/cores/AudioEngine/Utils/AEPackIEC61937.h
xbmc/cores/AudioEngine/Utils/AEStreamInfo.cpp
xbmc/cores/AudioEngine/Utils/AEUtil.cpp
xbmc/cores/AudioEngine/Utils/AEUtil.h
xbmc/cores/dvdplayer/DVDAudio.cpp
xbmc/cores/dvdplayer/DVDAudio.h
xbmc/cores/dvdplayer/DVDPlayerTeletext.cpp
xbmc/cores/paplayer/BXAcodec.cpp
xbmc/cores/paplayer/FLACcodec.cpp
xbmc/cores/paplayer/ICodec.h
xbmc/cores/paplayer/MP3codec.cpp
xbmc/cores/paplayer/OGGcodec.cpp
xbmc/cores/paplayer/PAPlayer.cpp
xbmc/cores/paplayer/PAPlayer.h
xbmc/dbwrappers/Database.cpp
xbmc/dbwrappers/mysqldataset.cpp
xbmc/dialogs/GUIDialogContextMenu.h
xbmc/dialogs/GUIDialogKeyboard.cpp
xbmc/dialogs/GUIDialogNumeric.cpp
xbmc/dialogs/GUIDialogNumeric.h
xbmc/dialogs/GUIDialogSmartPlaylistRule.cpp
xbmc/filesystem/DllLibCMyth.h
xbmc/filesystem/MythDirectory.cpp
xbmc/filesystem/VideoDatabaseDirectory.cpp
xbmc/filesystem/VideoDatabaseDirectory/DirectoryNode.cpp
xbmc/filesystem/VideoDatabaseDirectory/DirectoryNode.h
xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeMoviesOverview.cpp
xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTags.cpp [new file with mode: 0644]
xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTags.h [new file with mode: 0644]
xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTitleMovies.cpp
xbmc/filesystem/VideoDatabaseDirectory/Makefile
xbmc/filesystem/VideoDatabaseDirectory/QueryParams.cpp
xbmc/filesystem/VideoDatabaseDirectory/QueryParams.h
xbmc/guilib/GUIEditControl.cpp
xbmc/guilib/GUIMessage.h
xbmc/input/ButtonTranslator.cpp
xbmc/input/ButtonTranslator.h
xbmc/input/SDLJoystick.cpp
xbmc/input/SDLJoystick.h
xbmc/input/windows/WINJoystick.cpp
xbmc/input/windows/WINJoystick.h
xbmc/interfaces/IAnnouncer.h
xbmc/interfaces/json-rpc/InputOperations.cpp
xbmc/interfaces/json-rpc/InputOperations.h
xbmc/interfaces/json-rpc/JSONRPC.cpp
xbmc/interfaces/json-rpc/JSONServiceDescription.cpp
xbmc/interfaces/json-rpc/Makefile
xbmc/interfaces/json-rpc/ServiceDescription.h
xbmc/interfaces/json-rpc/methods.json
xbmc/interfaces/json-rpc/notifications.json
xbmc/interfaces/python/XBPyThread.cpp
xbmc/music/MusicDatabase.cpp
xbmc/music/infoscanner/MusicInfoScanner.cpp
xbmc/music/infoscanner/MusicInfoScanner.h
xbmc/music/tags/MusicInfoTagLoaderASAP.h
xbmc/music/tags/MusicInfoTagLoaderFactory.cpp
xbmc/music/windows/GUIWindowMusicBase.cpp
xbmc/music/windows/GUIWindowMusicBase.h
xbmc/network/GUIDialogNetworkSetup.cpp
xbmc/playlists/SmartPlayList.cpp
xbmc/programs/ProgramDatabase.cpp
xbmc/settings/AdvancedSettings.cpp
xbmc/settings/AdvancedSettings.h
xbmc/settings/GUISettings.cpp
xbmc/settings/GUIWindowSettingsCategory.cpp
xbmc/system.h
xbmc/threads/Atomics.cpp
xbmc/threads/platform/win/ThreadImpl.cpp
xbmc/utils/DatabaseUtils.h
xbmc/utils/EndianSwap.cpp [new file with mode: 0644]
xbmc/utils/EndianSwap.h
xbmc/utils/Makefile
xbmc/utils/RecentlyAddedJob.cpp
xbmc/utils/XBMCTinyXML.cpp
xbmc/video/GUIViewStateVideo.cpp
xbmc/video/VideoDatabase.cpp
xbmc/video/VideoDatabase.h
xbmc/video/VideoInfoTag.cpp
xbmc/video/VideoInfoTag.h
xbmc/video/dialogs/GUIDialogVideoInfo.cpp
xbmc/video/windows/GUIWindowVideoBase.cpp
xbmc/video/windows/GUIWindowVideoNav.cpp
xbmc/video/windows/GUIWindowVideoNav.h
xbmc/visualizations/DirectXSpectrum/directx_spectrum.vcxproj
xbmc/visualizations/Milkdrop/Plugin.vcxproj
xbmc/visualizations/WaveForm/Waveform.vcxproj
xbmc/windows/GUIMediaWindow.cpp

index ae6f5d4..9ffae7e 100755 (executable)
@@ -141,13 +141,16 @@ endif
 LIB_DIRS=\
        lib/cximage-6.0 \
        lib/libexif \
-       lib/cmyth \
        lib/libhdhomerun \
        lib/libid3tag \
        lib/libapetag \
        lib/cpluff \
        lib/xbmc-dll-symbols
 
+ifeq (@USE_MYSQL@,1)
+LIB_DIRS += lib/cmyth
+endif
+
 SS_DIRS=
 ifneq (@DISABLE_RSXS@,1)
   SS_DIRS+= xbmc/screensavers/rsxs-0.9/xbmc
@@ -317,7 +320,12 @@ imagelib: dllloader
        $(MAKE) -C lib/cximage-6.0
 
 codecs: papcodecs dvdpcodecs
-libs: cmyth libhdhomerun libid3tag imagelib libexif system/libcpluff-@ARCH@.so
+
+libs: libhdhomerun libid3tag imagelib libexif system/libcpluff-@ARCH@.so
+ifeq (@USE_MYSQL@,1)
+libs += cmyth
+endif
+
 externals: codecs libs visualizations screensavers
 
 xcode_depends: \
@@ -370,7 +378,7 @@ ifneq (1,@USE_XRANDR@)
        # xbmc-xrandr.c gets picked up by the default make rules
        @echo "excluding xbmc-xrandr"
 else
-       $(SILENT_LD) $(CC) $(CFLAGS) $(LDFLAGS) -o xbmc-xrandr xbmc-xrandr.c -lXrandr -lX11
+       $(SILENT_LD) $(CC) $(CFLAGS) $(LDFLAGS) -o xbmc-xrandr xbmc-xrandr.c -lXrandr -lX11 -lm
 endif
 
 tools/XBMCTex/XBMCTex:
index 20fbc5d..d83b951 100644 (file)
@@ -21,6 +21,7 @@
                32D6D47C1423A9D8003641AC /* JpegIO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 32D6D47A1423A9D8003641AC /* JpegIO.cpp */; };
                36A9445915821F8300727135 /* DatabaseUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9445715821F8300727135 /* DatabaseUtils.cpp */; };
                36A9445D15821FAC00727135 /* SortUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9445B15821FAB00727135 /* SortUtils.cpp */; };
+               36A9465315AA269B00727135 /* DirectoryNodeTags.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9465115AA269B00727135 /* DirectoryNodeTags.cpp */; };
                4D5D2E131301753F006ABC13 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D5D2E121301753F006ABC13 /* CFNetwork.framework */; };
                7C0A7ECD13A5DBF900AFC2BD /* AppParamParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C0A7ECB13A5DBF900AFC2BD /* AppParamParser.cpp */; };
                7C0A7FC813A9E75400AFC2BD /* DirtyRegionSolvers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C0A7FC413A9E75400AFC2BD /* DirtyRegionSolvers.cpp */; };
                36A9445A15821F9100727135 /* ISortable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ISortable.h; sourceTree = "<group>"; };
                36A9445B15821FAB00727135 /* SortUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SortUtils.cpp; sourceTree = "<group>"; };
                36A9445C15821FAB00727135 /* SortUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SortUtils.h; sourceTree = "<group>"; };
+               36A9465115AA269B00727135 /* DirectoryNodeTags.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DirectoryNodeTags.cpp; sourceTree = "<group>"; };
+               36A9465215AA269B00727135 /* DirectoryNodeTags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirectoryNodeTags.h; sourceTree = "<group>"; };
                4D5D2E121301753F006ABC13 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; };
                7C0A7ECB13A5DBF900AFC2BD /* AppParamParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AppParamParser.cpp; sourceTree = "<group>"; };
                7C0A7ECC13A5DBF900AFC2BD /* AppParamParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppParamParser.h; sourceTree = "<group>"; };
                7C0A7FCB13A9E76E00AFC2BD /* GUIWindowDebugInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIWindowDebugInfo.h; sourceTree = "<group>"; };
                7C0B9908154B80200065A238 /* AEDeviceInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AEDeviceInfo.cpp; sourceTree = "<group>"; };
                7C0B9909154B80200065A238 /* AEDeviceInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AEDeviceInfo.h; sourceTree = "<group>"; };
+               7C1A494015A968D6004AF4A4 /* SaveFileStateJob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SaveFileStateJob.h; sourceTree = "<group>"; };
                7C1A89B9152671FB00C63311 /* TextureCacheJob.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextureCacheJob.cpp; sourceTree = "<group>"; };
                7C1A89BA152671FB00C63311 /* TextureCacheJob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextureCacheJob.h; sourceTree = "<group>"; };
                7C1F6F8A13ED17CC001726AB /* LibraryDirectory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LibraryDirectory.cpp; sourceTree = "<group>"; };
                                F56C7481131EC152000AD0F6 /* DirectoryNodeSets.h */,
                                F56C7482131EC152000AD0F6 /* DirectoryNodeStudio.cpp */,
                                F56C7483131EC152000AD0F6 /* DirectoryNodeStudio.h */,
+                               36A9465115AA269B00727135 /* DirectoryNodeTags.cpp */,
+                               36A9465215AA269B00727135 /* DirectoryNodeTags.h */,
                                F56C7484131EC152000AD0F6 /* DirectoryNodeTitleMovies.cpp */,
                                F56C7485131EC152000AD0F6 /* DirectoryNodeTitleMovies.h */,
                                F56C7486131EC152000AD0F6 /* DirectoryNodeTitleMusicVideos.cpp */,
                                F56C775B131EC154000AD0F6 /* RingBuffer.h */,
                                F56C775C131EC154000AD0F6 /* RssReader.cpp */,
                                F56C775D131EC154000AD0F6 /* RssReader.h */,
+                               7C1A494015A968D6004AF4A4 /* SaveFileStateJob.h */,
                                F56C775E131EC154000AD0F6 /* ScraperParser.cpp */,
                                F56C775F131EC154000AD0F6 /* ScraperParser.h */,
                                F56C7760131EC154000AD0F6 /* ScraperUrl.cpp */,
                                36A9445915821F8300727135 /* DatabaseUtils.cpp in Sources */,
                                36A9445D15821FAC00727135 /* SortUtils.cpp in Sources */,
                                DF08E84515829BA600058C77 /* Exception.cpp in Sources */,
+                               36A9465315AA269B00727135 /* DirectoryNodeTags.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 16a224d..9c82006 100644 (file)
@@ -22,6 +22,7 @@
                3291892B1423A9B700E878CD /* JpegIO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 329189291423A9B700E878CD /* JpegIO.cpp */; };
                36A9444E15821F2C00727135 /* DatabaseUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9444C15821F2C00727135 /* DatabaseUtils.cpp */; };
                36A9445215821F5300727135 /* SortUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9445015821F5300727135 /* SortUtils.cpp */; };
+               36A9465B15AA26BC00727135 /* DirectoryNodeTags.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9465915AA26BC00727135 /* DirectoryNodeTags.cpp */; };
                4D5D2E1E1301758F006ABC13 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D5D2E1D1301758F006ABC13 /* CFNetwork.framework */; };
                7C0A7EDE13A5DC2800AFC2BD /* AppParamParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C0A7EDC13A5DC2800AFC2BD /* AppParamParser.cpp */; };
                7C0A7F9D13A9E70800AFC2BD /* GUIWindowDebugInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C0A7F9B13A9E70800AFC2BD /* GUIWindowDebugInfo.cpp */; };
                36A9444F15821F3B00727135 /* ISortable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ISortable.h; sourceTree = "<group>"; };
                36A9445015821F5300727135 /* SortUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SortUtils.cpp; sourceTree = "<group>"; };
                36A9445115821F5300727135 /* SortUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SortUtils.h; sourceTree = "<group>"; };
+               36A9465915AA26BC00727135 /* DirectoryNodeTags.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DirectoryNodeTags.cpp; sourceTree = "<group>"; };
+               36A9465A15AA26BC00727135 /* DirectoryNodeTags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirectoryNodeTags.h; sourceTree = "<group>"; };
                4D5D2E1D1301758F006ABC13 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; };
                7C0A7EDC13A5DC2800AFC2BD /* AppParamParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AppParamParser.cpp; sourceTree = "<group>"; };
                7C0A7EDD13A5DC2800AFC2BD /* AppParamParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppParamParser.h; sourceTree = "<group>"; };
                7C0A7FB113A9E72E00AFC2BD /* DirtyRegionTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirtyRegionTracker.h; sourceTree = "<group>"; };
                7C0B98F7154B7FF30065A238 /* AEDeviceInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AEDeviceInfo.cpp; sourceTree = "<group>"; };
                7C0B98F8154B7FF30065A238 /* AEDeviceInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AEDeviceInfo.h; sourceTree = "<group>"; };
+               7C1A495415A96908004AF4A4 /* SaveFileStateJob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SaveFileStateJob.h; sourceTree = "<group>"; };
                7C1A89CC1526722200C63311 /* TextureCacheJob.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextureCacheJob.cpp; sourceTree = "<group>"; };
                7C1A89CD1526722200C63311 /* TextureCacheJob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextureCacheJob.h; sourceTree = "<group>"; };
                7C1F6F7813ED178F001726AB /* LibraryDirectory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LibraryDirectory.cpp; sourceTree = "<group>"; };
                                F56C8464131F42E8000AD0F6 /* DirectoryNodeSets.h */,
                                F56C8465131F42E8000AD0F6 /* DirectoryNodeStudio.cpp */,
                                F56C8466131F42E8000AD0F6 /* DirectoryNodeStudio.h */,
+                               36A9465915AA26BC00727135 /* DirectoryNodeTags.cpp */,
+                               36A9465A15AA26BC00727135 /* DirectoryNodeTags.h */,
                                F56C8467131F42E8000AD0F6 /* DirectoryNodeTitleMovies.cpp */,
                                F56C8468131F42E8000AD0F6 /* DirectoryNodeTitleMovies.h */,
                                F56C8469131F42E8000AD0F6 /* DirectoryNodeTitleMusicVideos.cpp */,
                                F56C874A131F42EC000AD0F6 /* RingBuffer.h */,
                                F56C874B131F42EC000AD0F6 /* RssReader.cpp */,
                                F56C874C131F42EC000AD0F6 /* RssReader.h */,
+                               7C1A495415A96908004AF4A4 /* SaveFileStateJob.h */,
                                F56C874D131F42EC000AD0F6 /* ScraperParser.cpp */,
                                F56C874E131F42EC000AD0F6 /* ScraperParser.h */,
                                F56C874F131F42EC000AD0F6 /* ScraperUrl.cpp */,
                                36A9444E15821F2C00727135 /* DatabaseUtils.cpp in Sources */,
                                36A9445215821F5300727135 /* SortUtils.cpp in Sources */,
                                DFC3867E158296EC008AE277 /* Exception.cpp in Sources */,
+                               36A9465B15AA26BC00727135 /* DirectoryNodeTags.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 45eadd8..e6acb2c 100644 (file)
                32C631281423A90F00F18420 /* JpegIO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 32C631261423A90F00F18420 /* JpegIO.cpp */; };
                36A9443D15821E2800727135 /* DatabaseUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9443B15821E2800727135 /* DatabaseUtils.cpp */; };
                36A9444115821E7C00727135 /* SortUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9443F15821E7C00727135 /* SortUtils.cpp */; };
+               36A9464C15AA25FD00727135 /* DirectoryNodeTags.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9464A15AA25FD00727135 /* DirectoryNodeTags.cpp */; };
                3802709A13D5A653009493DD /* SystemClock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3802709813D5A653009493DD /* SystemClock.cpp */; };
                384718D81325BA04000486D6 /* XBDateTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 384718D61325BA04000486D6 /* XBDateTime.cpp */; };
                38F4E57013CCCB3B00664821 /* Implementation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 38F4E56C13CCCB3B00664821 /* Implementation.cpp */; };
                36A9443E15821E5400727135 /* ISortable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ISortable.h; sourceTree = "<group>"; };
                36A9443F15821E7C00727135 /* SortUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SortUtils.cpp; sourceTree = "<group>"; };
                36A9444015821E7C00727135 /* SortUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SortUtils.h; sourceTree = "<group>"; };
+               36A9464A15AA25FD00727135 /* DirectoryNodeTags.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DirectoryNodeTags.cpp; sourceTree = "<group>"; };
+               36A9464B15AA25FD00727135 /* DirectoryNodeTags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirectoryNodeTags.h; sourceTree = "<group>"; };
                3802709713D5A62D009493DD /* ThreadLocal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadLocal.h; sourceTree = "<group>"; };
                3802709813D5A653009493DD /* SystemClock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SystemClock.cpp; sourceTree = "<group>"; };
                3802709913D5A653009493DD /* SystemClock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SystemClock.h; sourceTree = "<group>"; };
                7C0A7EBF13A5DBCE00AFC2BD /* AppParamParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppParamParser.h; sourceTree = "<group>"; };
                7C0B98A1154B79C30065A238 /* AEDeviceInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AEDeviceInfo.cpp; sourceTree = "<group>"; };
                7C0B98A2154B79C30065A238 /* AEDeviceInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AEDeviceInfo.h; sourceTree = "<group>"; };
+               7C1A495B15A96918004AF4A4 /* SaveFileStateJob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SaveFileStateJob.h; sourceTree = "<group>"; };
                7C1A85631520522500C63311 /* TextureCacheJob.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextureCacheJob.cpp; sourceTree = "<group>"; };
                7C1A85641520522500C63311 /* TextureCacheJob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextureCacheJob.h; sourceTree = "<group>"; };
                7C1F6EB913ECCFA7001726AB /* LibraryDirectory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LibraryDirectory.cpp; sourceTree = "<group>"; };
                                7CCF7E711067643800992676 /* DirectoryNodeSets.h */,
                                E38E177A0D25F9FA00618676 /* DirectoryNodeStudio.cpp */,
                                E38E177B0D25F9FA00618676 /* DirectoryNodeStudio.h */,
+                               36A9464A15AA25FD00727135 /* DirectoryNodeTags.cpp */,
+                               36A9464B15AA25FD00727135 /* DirectoryNodeTags.h */,
                                E38E177C0D25F9FA00618676 /* DirectoryNodeTitleMovies.cpp */,
                                E38E177D0D25F9FA00618676 /* DirectoryNodeTitleMovies.h */,
                                E38E177E0D25F9FA00618676 /* DirectoryNodeTitleMusicVideos.cpp */,
                                F5DC87E0110A287400EE1B15 /* RingBuffer.h */,
                                E38E1E750D25F9FD00618676 /* RssReader.cpp */,
                                E38E1E760D25F9FD00618676 /* RssReader.h */,
+                               7C1A495B15A96918004AF4A4 /* SaveFileStateJob.h */,
                                E38E1E770D25F9FD00618676 /* ScraperParser.cpp */,
                                E38E1E780D25F9FD00618676 /* ScraperParser.h */,
                                E36C29E70DA72486001F0C9D /* ScraperUrl.cpp */,
                                36A9443D15821E2800727135 /* DatabaseUtils.cpp in Sources */,
                                36A9444115821E7C00727135 /* SortUtils.cpp in Sources */,
                                1DE0443515828F4B005DDB4D /* Exception.cpp in Sources */,
+                               36A9464C15AA25FD00727135 /* DirectoryNodeTags.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
diff --git a/addons/metadata.album.universal/addon.xml b/addons/metadata.album.universal/addon.xml
new file mode 100644 (file)
index 0000000..e25ee4a
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<addon id="metadata.album.universal"
+       name="Universal Album Scraper"
+       version="1.2.2"
+       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="metadata.common.musicbrainz.org" version="1.2.3"/>
+    <import addon="metadata.common.fanart.tv" version="1.0.1"/>
+    <import addon="metadata.common.amazon.de" version="1.0.0"/>
+  </requires>
+  <extension point="xbmc.metadata.scraper.albums"
+             language="en"
+             library="albumuniversal.xml"/>
+  <extension point="xbmc.addon.metadata">
+    <summary lang="en">Universal Scraper for Albums</summary>
+    <description lang="en">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>
+    <platform>all</platform>
+  </extension>
+</addon>
diff --git a/addons/metadata.album.universal/albumuniversal.xml b/addons/metadata.album.universal/albumuniversal.xml
new file mode 100644 (file)
index 0000000..9a90ff0
--- /dev/null
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scraper framework="1.1" date="2012-06-09">
+       <NfoUrl dest="3">
+               <RegExp input="$$1" output="&lt;url&gt;http://musicbrainz.org/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings&lt;/url&gt;" dest="3">
+                       <expression>release/(.+)</expression>
+               </RegExp>
+       </NfoUrl>
+       <CreateAlbumSearchUrl dest="3">
+               <RegExp input="$$1" output="&lt;url&gt;http://search.musicbrainz.org/ws/2/release/?fmt=xml&amp;query=release:&quot;\1&quot;%20AND%20artist:&quot;$$2&quot;&lt;/url&gt;" dest="3">
+                       <RegExp input="$$2" output="\1" dest="4">
+                               <expression noclean="1">(.+)</expression>
+                       </RegExp>
+                       <RegExp input="$$2" output="\1" dest="6">
+                               <expression noclean="1">(.+)(?:Ft%2e|Feat%2e|Ft.|Feat.|%20and%20)</expression>
+                       </RegExp>
+                       <RegExp input="$$6" output="\1" dest="4">
+                               <expression>(.+)</expression>
+                       </RegExp>
+                       <expression/>
+               </RegExp>
+       </CreateAlbumSearchUrl>
+       <GetAlbumSearchResults dest="8">
+               <RegExp input="$$5" output="&lt;results&gt;\1&lt;/results&gt;" dest="8">
+                       <RegExp input="$$1" output="&lt;entity&gt;&lt;year&gt;\5-\4-T#\6&lt;/year&gt;&lt;artist&gt;\3&lt;/artist&gt;&lt;title&gt;\2&lt;/title&gt;&lt;url cache=&quot;mb-\1-album.xml&quot;&gt;http://musicbrainz.org/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings&lt;/url&gt;&lt;/entity&gt;" dest="5">
+                               <expression repeat="yes">id=&quot;([^&quot;]*)&quot;&gt;&lt;title&gt;([^&lt;]*)&lt;/title&gt;&lt;status&gt;Official&lt;/status&gt;&lt;text-representation&gt;&lt;language&gt;[^&lt;]*&lt;/language&gt;&lt;script&gt;[^&lt;]*&lt;/script&gt;&lt;/text-representation&gt;&lt;artist-credit&gt;&lt;name-credit(?:&gt;)*(?:\sjoinphrase=&quot;[^&quot;]*&quot;&gt;)*(?:&lt;name&gt;[^&lt;]*&lt;/name)*(?:&gt;)*&lt;artist\sid=&quot;[^&quot;]*&quot;&gt;&lt;name&gt;([^&lt;]*)&lt;/name&gt;(?:&lt;sort-name&gt;[^&lt;]*&lt;/sort-name&gt;)*(?:&lt;disambiguation&gt;[^&lt;]*&lt;/disambiguation&gt;)*(?:&lt;alias-list&gt;.*?&lt;/alias-list&gt;)*&lt;/artist&gt;&lt;/name-credit&gt;(?:&lt;name-credit(?:&gt;)*(?:\sjoinphrase=&quot;[^&quot;]*&quot;&gt;)*(?:&lt;name&gt;[^&lt;]*&lt;/name)*(?:&gt;)*&lt;artist\sid=&quot;[^&quot;]*&quot;&gt;&lt;name&gt;[^&lt;]*&lt;/name&gt;(?:&lt;sort-name&gt;[^&lt;]*&lt;/sort-name&gt;)*(?:&lt;disambiguation&gt;[^&lt;]*&lt;/disambiguation&gt;)*(?:&lt;alias-list&gt;.*?&lt;/alias-list&gt;)*&lt;/artist&gt;&lt;/name-credit&gt;)*&lt;/artist-credit&gt;&lt;release-group\stype=&quot;Album&quot;\sid=&quot;[^&quot;]*&quot;&gt;(?:&lt;primary-type&gt;[^&lt;]*&lt;/primary-type&gt;)*(?:&lt;secondary-type-list&gt;&lt;secondary-type&gt;[^&lt;]*&lt;/secondary-type&gt;&lt;/secondary-type-list&gt;)*&lt;/release-group&gt;&lt;date&gt;(\d{4})[^&lt;]*&lt;/date&gt;(?:&lt;country&gt;)*([^&lt;]*)?.*?&lt;track-list\scount=&quot;(\d+)</expression>
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;entity&gt;&lt;year&gt;\5-\4-T#\6&lt;/year&gt;&lt;artist&gt;\3&lt;/artist&gt;&lt;title&gt;\2&lt;/title&gt;&lt;url cache=&quot;mb-\1-album.xml&quot;&gt;http://musicbrainz.org/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings&lt;/url&gt;&lt;/entity&gt;" dest="5+">
+                               <expression repeat="yes">id=&quot;([^&quot;]*)&quot;&gt;&lt;title&gt;([^&lt;]*)&lt;/title&gt;&lt;status&gt;Official&lt;/status&gt;&lt;text-representation&gt;&lt;language&gt;[^&lt;]*&lt;/language&gt;&lt;script&gt;[^&lt;]*&lt;/script&gt;&lt;/text-representation&gt;&lt;artist-credit&gt;&lt;name-credit(?:&gt;)*(?:\sjoinphrase=&quot;[^&quot;]*&quot;&gt;)*(?:&lt;name&gt;[^&lt;]*&lt;/name)*(?:&gt;)*&lt;artist\sid=&quot;[^&quot;]*&quot;&gt;&lt;name&gt;([^&lt;]*)&lt;/name&gt;(?:&lt;sort-name&gt;[^&lt;]*&lt;/sort-name&gt;)*(?:&lt;disambiguation&gt;[^&lt;]*&lt;/disambiguation&gt;)*(?:&lt;alias-list&gt;.*?&lt;/alias-list&gt;)*&lt;/artist&gt;&lt;/name-credit&gt;(?:&lt;name-credit(?:&gt;)*(?:\sjoinphrase=&quot;[^&quot;]*&quot;&gt;)*(?:&lt;name&gt;[^&lt;]*&lt;/name)*(?:&gt;)*&lt;artist\sid=&quot;[^&quot;]*&quot;&gt;&lt;name&gt;[^&lt;]*&lt;/name&gt;(?:&lt;sort-name&gt;[^&lt;]*&lt;/sort-name&gt;)*(?:&lt;disambiguation&gt;[^&lt;]*&lt;/disambiguation&gt;)*(?:&lt;alias-list&gt;.*?&lt;/alias-list&gt;)*&lt;/artist&gt;&lt;/name-credit&gt;)*&lt;/artist-credit&gt;&lt;release-group(?:\stype=&quot;[^&quot;]*&quot;)*\sid=&quot;[^&quot;]*&quot;&gt;(?:&lt;primary-type&gt;[^&lt;]*&lt;/primary-type&gt;)*(?:&lt;secondary-type-list&gt;&lt;secondary-type&gt;[^&lt;]*&lt;/secondary-type&gt;&lt;/secondary-type-list&gt;)*&lt;/release-group&gt;&lt;date&gt;(\d{4})[^&lt;]*&lt;/date&gt;(?:&lt;country&gt;)*([^&lt;]*)?.*?&lt;track-list\scount=&quot;(\d+)</expression>
+                       </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </GetAlbumSearchResults>
+       <GetAlbumDetails dest="3">
+               <RegExp input="$$5" output="&lt;details&gt;\1&lt;/details&gt;" dest="3">
+                       <!--MBID - release-->
+                       <RegExp input="$$1" output="\1" dest="3">
+                               <expression>id=&quot;([^&quot;]*)</expression>
+                       </RegExp>
+                       <!--MBID - release group-->
+                       <RegExp input="$$1" output="\1" dest="4">
+                               <expression>&lt;release-group type=&quot;[^&quot;]*&quot; id=&quot;([^&quot;]*)&quot;</expression>
+                       </RegExp>
+                       <!--Album title-->
+                       <RegExp input="$$1" output="\1" dest="7">
+                               <expression trim="1">&lt;release id=&quot;[^&quot;]*&quot;&gt;&lt;title&gt;([^&lt;]*)&lt;</expression>
+                       </RegExp>
+                       <!--Artist name-->
+                       <RegExp input="$$1" output="\1" dest="8">
+                               <expression trim="1">&lt;release id=&quot;[^&quot;]*&quot;&gt;&lt;title&gt;[^&lt;]*&lt;.*?&lt;artist id=&quot;[^&quot;]*&quot;&gt;&lt;name&gt;([^&lt;]*)&lt;</expression>
+                       </RegExp>
+                       <RegExp input="$$3" output="&lt;chain function=&quot;GetMBAlbumTitleByMBID&quot;&gt;\1&lt;/chain&gt;" dest="5">
+                               <expression noclean="1">(.+)</expression>
+                       </RegExp>
+                       <RegExp input="$$3" output="&lt;chain function=&quot;GetMBAlbumArtistByMBID&quot;&gt;\1&lt;/chain&gt;" dest="5+">
+                               <expression noclean="1">(.+)</expression>
+                       </RegExp>
+                       <RegExp input="$$3" output="&lt;chain function=&quot;GetMBAlbumLabelByMBID&quot;&gt;\1&lt;/chain&gt;" dest="5+">
+                               <expression noclean="1">(.+)</expression>
+                       </RegExp>
+                       <RegExp input="$$3" output="&lt;chain function=&quot;GetMBAlbumDateByMBID&quot;&gt;\1&lt;/chain&gt;" dest="5+">
+                               <expression noclean="1">(.+)</expression>
+                       </RegExp>
+                       <RegExp input="$$3" output="&lt;chain function=&quot;GetMBAlbumTracksByMBID&quot;&gt;\1&lt;/chain&gt;" dest="5+">
+                               <expression noclean="1">(.+)</expression>
+                       </RegExp>
+                       <RegExp input="$INFO[albumreviewsource]" output="&lt;url function=&quot;GetAMGAlbumReview&quot; cache=&quot;mb-$$4-rg.xml&quot;&gt;http://musicbrainz.org/ws/2/release-group/$$4?inc=url-rels&lt;/url&gt;" dest="5+">
+                               <expression>allmusic.com</expression>
+                       </RegExp>
+                       <RegExp input="$INFO[albumreviewsource]" output="&lt;chain function=&quot;GetLastFMAlbumReviewByAlbumAndArtist&quot;&gt;$$7::$$8::$$7::$$8&lt;/chain&gt;" dest="5+">
+                               <expression>last.fm</expression>
+                       </RegExp>
+                       <RegExp input="$INFO[albumreviewsource]" output="&lt;url function=&quot;GetAmazonDEAlbumReview&quot;&gt;http://musicbrainz.org/ws/2/release-group/$$4?inc=url-rels&lt;/url&gt;" dest="5+">
+                               <expression>amazon.de</expression>
+                       </RegExp>
+                       <RegExp input="$INFO[albumratingsource]" output="&lt;chain function=&quot;GetMBAlbumRatingByMBID&quot;&gt;$$3&lt;/chain&gt;" dest="5+">
+                               <expression>MusicBrainz</expression>
+                       </RegExp>
+                       <RegExp input="$INFO[albumratingsource]" output="&lt;url function=&quot;GetAMGAlbumRating&quot; cache=&quot;mb-$$4-rg.xml&quot;&gt;http://musicbrainz.org/ws/2/release-group/$$4?inc=url-rels&lt;/url&gt;" dest="5+">
+                               <expression>allmusic.com</expression>
+                       </RegExp>
+                       <RegExp input="$INFO[albumstylessource]" output="&lt;url function=&quot;GetAMGAlbumStyles&quot; cache=&quot;mb-$$4-rg.xml&quot;&gt;http://musicbrainz.org/ws/2/release-group/$$4?inc=url-rels&lt;/url&gt;" dest="5+">
+                               <expression>allmusic.com</expression>
+                       </RegExp>
+                       <RegExp input="$INFO[albummoodssource]" output="&lt;url function=&quot;GetAMGAlbumMoods&quot; cache=&quot;mb-$$4-rg.xml&quot;&gt;http://musicbrainz.org/ws/2/release-group/$$4?inc=url-rels&lt;/url&gt;" dest="5+">
+                               <expression>allmusic.com</expression>
+                       </RegExp>
+                       <RegExp input="$INFO[albumthemessource]" output="&lt;url function=&quot;GetAMGAlbumThemes&quot; cache=&quot;mb-$$4-rg.xml&quot;&gt;http://musicbrainz.org/ws/2/release-group/$$4?inc=url-rels&lt;/url&gt;" dest="5+">
+                               <expression>allmusic.com</expression>
+                       </RegExp>
+                       <RegExp conditional="fanarttvalbumthumbs" input="$$1" output="&lt;chain function=&quot;GetFanartTvAlbumThumbsByMBID&quot;&gt;$$4&lt;/chain&gt;" dest="5+">
+                               <expression noclean="1" />
+                       </RegExp>
+                       <RegExp conditional="allmusicalbumthumbs" input="$$1" output="&lt;url function=&quot;GetAMGAlbumThumbs&quot; cache=&quot;mb-$$4-rg.xml&quot;&gt;http://musicbrainz.org/ws/2/release-group/$$4?inc=url-rels&lt;/url&gt;" dest="5+">
+                               <expression noclean="1" />
+                       </RegExp>
+                       <RegExp conditional="lastfmalbumthumbs" input="$$1" output="&lt;chain function=&quot;GetLastFMAlbumThumbs&quot;&gt;$$7::$$8::$$7::$$8&lt;/chain&gt;" dest="5+">
+                               <expression noclean="1" />
+                       </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </GetAlbumDetails>
+
+       <GetAMGAlbumReview dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$$1" output="&lt;chain function=&quot;GetAMGAlbumReviewByAMGID&quot;&gt;\1&lt;/chain&gt;" dest="2">
+                               <expression noclean="1">allmusic.com/album/([^&lt;]*)</expression>
+                       </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </GetAMGAlbumReview>
+
+       <GetAMGAlbumRating dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$$1" output="&lt;chain function=&quot;GetAMGAlbumRatingByAMGID&quot;&gt;\1&lt;/chain&gt;" dest="2">
+                               <expression noclean="1">allmusic.com/album/([^&lt;]*)</expression>
+                       </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </GetAMGAlbumRating>
+
+       <GetAMGAlbumStyles dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$$1" output="&lt;chain function=&quot;GetAMGAlbumStylesByAMGID&quot;&gt;\1&lt;/chain&gt;" dest="2">
+                               <expression noclean="1">allmusic.com/album/([^&lt;]*)</expression>
+                       </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </GetAMGAlbumStyles>
+
+       <GetAMGAlbumMoods dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$$1" output="&lt;chain function=&quot;GetAMGAlbumMoodsByAMGID&quot;&gt;\1&lt;/chain&gt;" dest="2">
+                               <expression noclean="1">allmusic.com/album/([^&lt;]*)</expression>
+                       </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </GetAMGAlbumMoods>
+
+       <GetAMGAlbumThemes dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$$1" output="&lt;chain function=&quot;GetAMGAlbumThemesByAMGID&quot;&gt;\1&lt;/chain&gt;" dest="2">
+                               <expression noclean="1">allmusic.com/album/([^&lt;]*)</expression>
+                       </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </GetAMGAlbumThemes>
+
+       <GetAMGAlbumThumbs dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$$1" output="&lt;chain function=&quot;GetAMGAlbumThumbsByAMGID&quot;&gt;\1&lt;/chain&gt;" dest="2">
+                               <expression noclean="1">allmusic.com/album/([^&lt;]*)</expression>
+                       </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </GetAMGAlbumThumbs>
+
+       <GetAmazonDEAlbumReview dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$$1" output="&lt;chain function=&quot;GetAmazonDEAlbumReviewByASIN&quot;&gt;\1&lt;/chain&gt;" dest="2">
+                               <expression noclean="1">http://www.amazon.de/gp/product/([^&lt;]*)</expression>
+                       </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </GetAmazonDEAlbumReview>
+
+</scraper>
diff --git a/addons/metadata.album.universal/changelog.txt b/addons/metadata.album.universal/changelog.txt
new file mode 100644 (file)
index 0000000..10cbfbf
--- /dev/null
@@ -0,0 +1,36 @@
+[B]1.2.2[/B]
+Fixed: accommodate new Frodo style URL encoding
+
+[B]1.2.1[/B]
+Removed: '&' sign from artist splitter
+
+[B]1.2.0[/B]
+Added: scraping album review from amazon.de (if link exist on MusicBrainz)
+
+[B]1.1.4[/B]
+Fixed: typo blocks preferring album in search result
+
+[B]1.1.3[/B]
+Fixed: won't find tracks without recording id
+
+[B]1.1.2[/B]
+Fixed: won't find tracks without duration
+
+[B]1.1.1[/B]
+Fixed: artists won't find with 'and' in their name
+
+[B]1.1.0[/B]
+Added: trying to get album info when multiple artists are credited (first artist will be used)
+Fixed: will not find some albums
+
+[B]1.0.3[/B]
+Fixed: Some Album releases were not found
+
+[B]1.0.2[/B]
+Fixed: Track Duration from MusicBrainz was wrong in certain cases. Credits to scudlee!
+
+[B]1.0.1[/B]
+Fixed: scraping moods from allmusic.com
+
+[B]1.0.0[/B]
+Initial version
\ No newline at end of file
diff --git a/addons/metadata.album.universal/icon.png b/addons/metadata.album.universal/icon.png
new file mode 100644 (file)
index 0000000..7c3d600
Binary files /dev/null and b/addons/metadata.album.universal/icon.png differ
diff --git a/addons/metadata.album.universal/resources/language/English/strings.xml b/addons/metadata.album.universal/resources/language/English/strings.xml
new file mode 100644 (file)
index 0000000..9777a09
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<strings>
+    <string id="30000">Grab Album Thumbs from fanart.tv</string>
+    <string id="30001">Grab Album Thumbs from Last.fm</string>
+    <string id="30002">Get Album Review from</string>
+    <string id="30003">     Preferred Language</string>
+    <string id="30004">Get Album Rating from</string>
+    <string id="30005">Get Album Styles from</string>
+    <string id="30006">Get Album Moods from</string>
+    <string id="30007">Get Album Themes from</string>
+    <string id="30008">Grab Album Thumbs from allmusic.com</string>
+    <string id="30009">Artwork</string>
+</strings>
diff --git a/addons/metadata.album.universal/resources/settings.xml b/addons/metadata.album.universal/resources/settings.xml
new file mode 100644 (file)
index 0000000..8b2a8a9
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<settings>
+  <category label="128">
+    <setting type="lsep" label="General Settings"/>
+      <setting label="30002" type="labelenum" values="last.fm|amazon.de|None" id="albumreviewsource" default="last.fm"/>
+      <setting label="30003" type="labelenum" values="en|de|es|fr|it|jp|pl|pt|ru|sv|tr|zh" id="lastfmlanguage" 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"/>
+      <setting label="30006" type="labelenum" values="allmusic.com|None" id="albummoodssource" default="allmusic.com"/>
+      <setting label="30007" type="labelenum" values="allmusic.com|None" id="albumthemessource" default="allmusic.com"/>
+  </category>
+
+  <category label="30009">
+    <setting type="lsep" label="Artwork Settings"/>
+      <setting label="30000" type="bool" id="fanarttvalbumthumbs" default="true"/>
+      <setting label="30001" type="bool" id="lastfmalbumthumbs" default="true"/>
+      <setting label="30008" type="bool" id="allmusicalbumthumbs" default="true"/>
+  </category>
+</settings>
diff --git a/addons/metadata.albums.allmusic.com/addon.xml b/addons/metadata.albums.allmusic.com/addon.xml
deleted file mode 100644 (file)
index dea6306..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<addon id="metadata.albums.allmusic.com"
-       name="AllMusic"
-       version="2.0.1"
-       provider-name="Team XBMC">
-  <requires>
-    <import addon="xbmc.metadata" version="1.0"/>
-    <import addon="metadata.common.last.fm" version="1.1.0"/>
-    <import addon="metadata.common.allmusic.com" version="1.8.1"/>
-    <import addon="metadata.common.htbackdrops.com" version="1.0.7"/>
-  </requires>
-  <extension point="xbmc.metadata.scraper.albums"
-             language="en"
-             library="allmusic.xml"/>
-  <extension point="xbmc.addon.metadata">
-    <summary lang="bg">Информация за албуми от AllMusic.com</summary>
-    <summary lang="en">AllMusic album information</summary>
-    <summary lang="de">Alben Scraper für AllMusic.com</summary>
-    <summary lang="es">Scraper de Álbums de AllMusic</summary>
-    <summary lang="fr">Scraper d'albums musicaux AllMusic</summary>
-    <summary lang="fi">AllMusic.com -albumitietojen lataaja</summary>
-    <summary lang="hu">AllMusic.com album információk</summary>
-    <summary lang="nl">AllMusic-albuminfo</summary>
-    <summary lang="pl">Informacje o albumach z AllMusic</summary>
-    <summary lang="pt">Scraper de músicas AllMusic</summary>
-    <summary lang="ro">Catalog AllMusic pentru informații albume</summary>
-    <summary lang="ru">Информация об альбоме из AllMusic</summary>
-    <summary lang="se">AllMusic albuminformation</summary>
-    <summary lang="zh">AllMusic音乐专辑信息</summary>
-    <description lang="bg">Попълнете метаинформацията в библиотеката си от AllMusic.com.
-Уебсайтът allmusic.com е създаден през 19995, като място за страстни музикални фенове.
-Редакторският колектив AMG заедно със стотици експерти (и малко фанатици на тема allmusic.com) са направили сайта един от най-подробните (и най-често ползваните) източници на информация на музикална тема. Всички те са се посветили на създаването и поддържането на базата от данни, на разпространяването на съдържание от AMG, което се очаква от любителите на музика и професионалисти в музикалния отрасъл.
-Засегнати са всички жанрове и стилове музика. От най-комерсиалните и популярни до най-невъзприетите. Критиката към артисти и албуми се прави в контекста на съответните им жанрове - от опера до гаражен рок. Така се осигури актуална информация за почитателите на всеки стил, за любимите им артисти и се представят нови творби.</description>
-    <description lang="en">Use AllMusic.com to fill your library metadata information.
-The allmusic website was created in 1995 as a place for music fans to indulge their passion.
-The AMG editorial staff, along with hundreds of expert contributors (all music fanatics in their own right), has made allmusic the most comprehensive music reference source on the planet. They are all dedicated to creating and maintaining the knowledgeable, spirited content that music lovers and industry professionals have come to expect from AMG.
-All genres and styles of music are covered here, ranging from the most commercially popular to the most obscure. We critique albums and artists within the context of their own genres - from opera to garage rock to traditional country. This ensures that fans of any style of music can depend on us to keep them up-to-date with their favorite artists as well as introduce them to new sounds.</description>
-     <description lang="de">Benutze den AllMusic.com-Scraper um deine Musik-Bibliothek mit Metadaten zu füllen. 
-AllMusic.com wurde 1995 gegründet, um Musikliebhabern einen Platz zu geben, Ihre Leidenschaft auszuleben.
-Die AMG Redaktion, zusammen mit hunderten Experten (alles Fachmänner auf Ihrem Gebiet) als Beitragende, machte AllMusic.com zur umfangreichsten Quelle für Musikinformationen auf dem Planeten. Sie sind alle engagiert, um den lebhaften Inhalt, welcher von Musikliebhabern und der Musikindustrie von AMG erwartet wird, zu Erstellen und Pflegen. 
-Alle Genres und Stile der Musik werden hier abgedeckt, reichend von Mainstream bis zum Underground. Wir schreiben Kritiken zu Alben, im Kontext zu dem passenden Genre - von Oper über Garagen Rock bis hin zu traditioneller Country Musik. Das garantiert Fans jeglicher Musikrichtung, dass sie sich auf uns verlassen können, weil wir sie immer up-to-date über Ihre Liblingskünstler halten und Ihnen auch neue Sounds vorstellen</description>
-    <description lang="es">Este scraper utiliza Allmusic.com para rellenar la información de la librería musical.
-La página web allmusic fue creada en el 1995 cómo un sitio donde los fans podíaan compartir su pasión por la música.
-El equipo de AMG, junto con cuentos de colaboradores expertos (todos ellos fans de la música) han hecho de allmusic uno de los sitios más extensos del planeta. Todos ellos intentan crear y mantener unos contenidos que los amantes de la música y los profesionales del sector obtienen de AMG.
-Todos los géneros y estilos musicales tienen cabida, desde los más comerciales hasta los más oscuros. En allmusic se critican los álbumes y los artistas en el entorno que les corresponde - desde opera, pasando por rock hasta country tradicional. Así se asegura que los fans de cualquier estilo de música puedan depender de nosotros para mantenerse al día de las novedades de sus artistas favoritos y descubrir nuevos sonidos.</description>
-    <description lang="fi">Käytä AllMusic.com -sivustoa täyttämään kirjastosi metatiedot.
-AllMusic.com -sivusto luotiin vuonna 1995 paikaksi, jossa musiikkifanit voivat tyydyttää intohimonsa musiikkiin.
-AMG-toimituksen henkilökunta, satojen asiansa tuntevien lahjoittajien kanssa (kaikki musiikkifanaatikot), ovat tehneet AllMusic.com -sivustosta koko planeetan kattavimman musiikkitietolähteen. He ovat kaikki sitoutuneita luomaan ja ylläpitämään asioista perillä olevaa henkevää sisältöä, jota musiikista pitävät ja musiikkialan ammattilaiset odottavat AMG:ltä.
-Kaikki musiikin lajityypit ja tyylisuunnat ovat edustettuina täällä, vaihdellen kaupallisesti suosituimmista kaikista huomaamattomimpiin. Me arvostelemme albumit ja esittäjät heidän oman lajityyppinsä sisällä - oopperasta ja autotallirokista aina perinteiseen country-musiikkiin. Tämä varmistaa, että minkä tahansa tyylisuunnan fanit voivat luottaa, että samalla kun pidämme heidät ajan tasalla heidän lempiartististansa, niin esittelemme myös heille uusia äänimaailmoita.</description>
-    <description lang="fr">Utiliser AllMusic.com pour la récupération des méta-données.
-Le site web AllMusic a été créé en 1995 afin que les fans de musique puissent assouvir leur passion.
-L'équipe rédactionnelle d'AMG, forte de ses centaines de contributeurs avisés (tous passionnés de musique à part entière), a fait de AllMusic la source de référence la plus complète de toute la planète. Chacun s'investissant dans la construction et la maintenance d'un contenu aussi passionné et judicieux que tout amoureux de musique ou tout professionnel de l'industrie serait en droit d'attendre d'AMG.
-Tous les styles et tous les genres y sont représentés, allant du plus commercial au plus confidentiel. Nous critiquons albums et artistes dans le cadre de leur propre style - de l'opéra à la country traditionnelle en passant par le rock garage. Pour les fans de chaque style musical, c'est l'assurance que nous les tenons informés sur leurs artistes préférés ou à l'apprentissage de nouvelles sonorités.</description>
-    <description lang="hu">Az AllMusic.com használata a médiatáradatok feltöltésére. Ez a webhely 1995-ben a zenerajongók szenvedélyének kiszolgálására jött létre.
-Az AMG szerkesztői csapata a szakértő közreműködőkkel együtt (mind zenei fanatikus a maga nemében), az allmusic-ot a legátfogóbb zenei információforrássá tették a világon.
-Minden létező stílus és zenei irányzat feldolgozásra kerül itt. Kezdve a legpopulárisabbtól a legismeretlenebbig. Mi kritikát mondunk a lemezekről és előadókról, az operától a garázs rock-on át a hagyományos country zenéig. Ez biztosítja, hogy bármely stílus rajongói napra készek legyenek a kedvenc előadóikkal, ugyanakkor az új hangzások is eljussanak hozzájuk.</description>
-    <description lang="nl">AllMusic.com gebruiken om de metadata van uw collectie op te halen.
-De AllMusic-website werd in 1995 opgericht om muziekfans een online thuis te bieden.
-De AMG-redactie heeft van AllMusic het meest complete muzieknaslagwerk gemaakt op deze planeet, mede dankzij de bijdragen van honderden experts. Het is hun missie om de hoogstaande inhoud te blijven aanbieden die muziekliefhebbers en professionals ondertussen van AMG verwachten.
-Alle genres en stijlen - of het nu de meest commerciële of de meest obscure zijn - krijgen hier een plaatsje. We bespreken albums en artiesten in de context van hun eigen genre, van opera over garagerock tot traditionele country. Hierdoor kunnen fans van elke muziekstijl bij ons terecht voor de laatste informatie over hun favoriete artiesten, of om nieuwe muziek te leren ontdekken.</description>
-    <description lang="pl">Używa AllMusic.com do pobierania informacji o albumach z Twojej muzycznej biblioteki.</description>
-    <description lang="pt">Use o AllMusic.com para obter a informação da sua Biblioteca de música. O site allmusic foi criado em 1995 para alimentar a paixão dos fans de música.
-O pessoal da redacção da AMG, em conjunto com centenas de especialistas (todos fanáticos por música à sua maneira), tornaram o allmusic o mais completo site de referência musical do planeta. Continuam dedicados a criar e manter o conhecimento, espírito e conteúdos que fans de música e profissionais da indústria se habituaram a obter da AMG.
-Todos os géneros e estilos de música podem ser encontrados aqui, desde o mais comercial e popular até à música mais rara. Nós revemos e criticamos álbuns e artistas dentro do contexto do seu género - the ópera a rock de garagem, de pop a música country. Isto assegura que fans de qualquer género podem depender de nós para os manter actualizados sobre os seus artistas favoritos bem como de novos sons.</description>
-     <description lang="ro">Folosiți AllMusic.com ca sursă pentru mediateca dumneavoastră.
-Site-ul allmusic a fost creat în 1995 ca un loc unde iubitorii de muzică să se răsfețe. Echipa editorială AMG, împreună cu sute de contribuitori experți (niște fanatici după muzică în felul lor), au făcut allmusic cea mai cuprinzătoare sursă de referințe muzicale de pe planetă. Toți sunt dedicați să creeze și să întrețină conținutul pe care iubitorii de muzică și profesioniștii din industrie îl așteaptă de la AMG.
-Toate genurile și stilurile de muzică sunt incluse aici, începând de la cele mai populare către cele mai obscure. Noi criticăm albumele și artiștii în contextul genurilor proprii. Toți fanii oricărui stil de muzică pot conta pe noi să îi ținem la curent cu artiștii lor favoriți, dar și să le prezentăm noi cântece.</description>
-    <description lang="ru">Используйте AllMusic.com для добавления мета-данных в вашу библиотеку.
-Сайт allmusic был создан в 1995 как место для фанатов музыки, где они могли бы удовлетворять свою страсть.
-Редакторский состав AMG, вместе с сотнями участников-экспертов (каждый по-своему фанат музыки), сделали allmusic самым полным источником информации о музыке на планете. Все они посвятили себя созданию и поддержке полезного, и познавательного, контента который любители музыки, и профессионалы индустрии, ожидают от AMG.
-Здесь представлены все стили и жанры музыки, от самых коммерчески популярных до наиболее неизвестных. Мы критикуем альбомы и исполнителей в контексте их собственного жанра - от оперы и гаражного рока до традиционного кантри. Это обеспечивает то, что фанат любого стиля музыки может полагаться на нас в поддержке актуальности своих познаний о любимом исполнителе и также расширять свои знания.</description>
-    <description lang="se">Låt AllMusic.com fylla dina mappar med metadatainformation.
-AllMusic's webbplats skapades 1995 som en plats för musikälskare där de kunde njuta av sin passion.
-AMG's redaktion har tillsammans med hundratals experter och bidragsgivare, alla musikfanatiker på sina egna sätt, gjort AllMusic till den mest omfattande källan inom musikreferens på den här planeten. De är alla kunniga och engagerade med att skapa och upprätthålla ett innehåll på webbplatsen, som musikälskare och branschfolk förväntar sig av AMG.
-Alla genrer och stilar av musik behandlas här, allt från det mest kommersiellt populära till det mest suspekta. De kritiserar album och artister inom ramen för sina egna genrer, allt från opera, garagerock till traditionell countrymusik. Detta säkerställer att alla fans oavsett musikstil kan lita på dem och hålla sig uppdaterade med sina favoritartister och bli introducerade till nya ljud.</description>
-    <description lang="zh">从AllMusic.com网站获取音乐资料。
-allmusic网站创建于1995年,它是音乐爱好者的乐园。
-AMG的编辑和许多专业撰稿人(都是音乐狂热分子)共同把allmusic建成世界上最全面的音乐资料库。他们致力于创造和维护音乐爱好者和业内专业人士期望从AMG得到的知识和精神产品。
-这里涵盖了所有的音乐流派和风格,评价从最流行到晦涩和冷门的音乐,讨论不同风格的专辑和艺术家 - 从歌剧到摇滚乐到传统的乡村音乐。力求让所有音乐爱好者都能在这里了解他所喜爱的艺术家最新动态,并为他们介绍新的音乐。</description>
-    <platform>all</platform>
-  </extension>
-</addon>
diff --git a/addons/metadata.albums.allmusic.com/allmusic.xml b/addons/metadata.albums.allmusic.com/allmusic.xml
deleted file mode 100644 (file)
index 1e86b27..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<scraper framework="1.1" date="2010-10-16">
-       <NfoUrl dest="3">
-               <RegExp input="$$1" output="&lt;url&gt;http://www.\1/review&lt;/url&gt;" dest="3">
-                       <expression>(allmusic.com/album/.*)</expression>
-               </RegExp>
-       </NfoUrl>
-       <CreateAlbumSearchUrl dest="3">
-               <RegExp input="$$1" output="&lt;url&gt;http://www.allmusic.com/search/album/\1&lt;/url&gt;" dest="3">
-                       <expression />
-               </RegExp>
-       </CreateAlbumSearchUrl>
-       <GetAlbumSearchResults dest="8">
-               <RegExp input="$$5" output="&lt;results&gt;\1&lt;/results&gt;" dest="8">
-                       <RegExp input="$$1" output="&lt;entity&gt;&lt;year&gt;\4&lt;/year&gt;&lt;artist&gt;\3&lt;/artist&gt;&lt;title&gt;\2&lt;/title&gt;&lt;url cache=&quot;am-\3-\2-album.html&quot;&gt;http://www.allmusic.com/album/\1/review&lt;/url&gt;&lt;/entity&gt;" dest="5">
-                               <expression repeat="yes" noclean="1,2,3">&lt;td class=&quot;text-center&quot;&gt;[^&lt;]*&lt;a href.*?www.allmusic.com/album/([^&quot;]*)&quot;&gt;([^&lt;]*).*?&lt;td&gt;([^&lt;]*)&lt;/td&gt;.*?&lt;td&gt;.*?&lt;td&gt;([^&lt;]*)</expression>
-                       </RegExp>
-                       <RegExp input="$$1" output="&lt;entity&gt;&lt;year&gt;\4&lt;/year&gt;&lt;artist&gt;\3&lt;/artist&gt;&lt;title&gt;\2&lt;/title&gt;&lt;url cache=&quot;am-\3-\2-album.html&quot;&gt;http://www.allmusic.com/album/\1/review&lt;/url&gt;&lt;/entity&gt;" dest="5+">
-                               <expression repeat="yes" noclean="1,2,3">&lt;td class=&quot;text-center&quot;&gt;[^&lt;]*&lt;/td&gt;.*?www.allmusic.com/album/([^&quot;]*)&quot;&gt;([^&lt;]*).*?&lt;td&gt;([^&lt;]*)&lt;/td&gt;.*?&lt;td&gt;.*?&lt;td&gt;([^&lt;]*)</expression>
-                       </RegExp>
-                       <expression noclean="1" />
-               </RegExp>
-       </GetAlbumSearchResults>
-       <GetAlbumDetails dest="3">
-               <RegExp input="$$5" output="&lt;details&gt;\1&lt;/details&gt;" dest="3">
-                       <RegExp input="$$1" output="\1" dest="2">
-                               <expression noclean="1">&lt;h1 class=&quot;title&quot;&gt;([^&lt;]*)&lt;/h1&gt;</expression>
-                       </RegExp>
-                       <RegExp input="$$1" output="\1" dest="3">
-                               <expression noclean="1">&lt;a href=&quot;http://www.allmusic.com/album/([^&quot;]*)&quot;&gt;Overview&lt;</expression>
-                       </RegExp>
-                       <RegExp conditional="lastfmalbumthumbs" input="$$1" output="&lt;chain function=&quot;GetLastFMAlbumThumbs&quot;&gt;\1::\2&lt;/chain&gt;" dest="5+">
-                               <expression trim="1,2" encode="1,2">&lt;meta name=&quot;title&quot; content=&quot;([^-]*)- ([^&lt;]*)&quot; /&gt;</expression>
-                       </RegExp>
-                       <RegExp input="$$1" output="&lt;url cache=&quot;am-$$3-$$2-album.html&quot; function=&quot;ParseAMGAlbum&quot;&gt;http://www.allmusic.com/album/\1/review&lt;/url&gt;" dest="5+">
-                               <expression noclean="1">&lt;a href=&quot;http://www.allmusic.com/album/([^&quot;]*)&quot;&gt;Overview&lt;</expression>
-                       </RegExp>
-                       <RegExp input="$$1" output="&lt;url cache=&quot;am-$$3-$$2-album.html&quot; function=&quot;GetAMGReview&quot;&gt;http://www.allmusic.com/album/\1/review&lt;/url&gt;" dest="5+">
-                               <expression noclean="1">&lt;a href=&quot;http://www.allmusic.com/album/([^&quot;]*)&quot;&gt;Overview&lt;</expression>
-                       </RegExp>
-                       <expression noclean="1" />
-               </RegExp>
-       </GetAlbumDetails>
-</scraper>
diff --git a/addons/metadata.albums.allmusic.com/icon.png b/addons/metadata.albums.allmusic.com/icon.png
deleted file mode 100644 (file)
index 9c18e20..0000000
Binary files a/addons/metadata.albums.allmusic.com/icon.png and /dev/null differ
diff --git a/addons/metadata.albums.allmusic.com/resources/language/Bulgarian/strings.xml b/addons/metadata.albums.allmusic.com/resources/language/Bulgarian/strings.xml
deleted file mode 100644 (file)
index 7b03b74..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
-    <string id="30000">Вземи снимки за албум от Allmusic.com</string>
-    <string id="30001">Вземи снимки за албум от Last.fm</string>
-</strings>
diff --git a/addons/metadata.albums.allmusic.com/resources/language/Chinese (Simple)/strings.xml b/addons/metadata.albums.allmusic.com/resources/language/Chinese (Simple)/strings.xml
deleted file mode 100644 (file)
index 6b0eca4..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
-    <string id="30000">从Allmusic.com获取专辑图片</string>
-    <string id="30001">从Last.fm获取专辑图片</string>
-</strings>
diff --git a/addons/metadata.albums.allmusic.com/resources/language/Dutch/strings.xml b/addons/metadata.albums.allmusic.com/resources/language/Dutch/strings.xml
deleted file mode 100644 (file)
index 556ea1c..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
-    <string id="30000">Allmusic.com gebruiken voor albumminiaturen</string>
-    <string id="30001">Last.fm gebruiken voor albumminiaturen</string>
-</strings>
diff --git a/addons/metadata.albums.allmusic.com/resources/language/English/strings.xml b/addons/metadata.albums.allmusic.com/resources/language/English/strings.xml
deleted file mode 100644 (file)
index 661ec19..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
-    <string id="30000">Grab album thumbs from Allmusic.com</string>
-    <string id="30001">Grab album thumbs from Last.fm</string>
-</strings>
diff --git a/addons/metadata.albums.allmusic.com/resources/language/Finnish/strings.xml b/addons/metadata.albums.allmusic.com/resources/language/Finnish/strings.xml
deleted file mode 100644 (file)
index 75d3ef6..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
-    <string id="30000">Hae albumin kuvakkeet osoitteesta Allmusic.com</string>
-    <string id="30001">Hae albumin kuvakkeet osoitteesta Last.fm</string>
-</strings>
diff --git a/addons/metadata.albums.allmusic.com/resources/language/French/strings.xml b/addons/metadata.albums.allmusic.com/resources/language/French/strings.xml
deleted file mode 100644 (file)
index 93bda6f..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
-    <string id="30000">Récupérer les pochettes album depuis Allmusic.com</string>
-    <string id="30001">Récupérer les pochettes album depuis Last.fm</string>
-</strings>
diff --git a/addons/metadata.albums.allmusic.com/resources/language/German/strings.xml b/addons/metadata.albums.allmusic.com/resources/language/German/strings.xml
deleted file mode 100644 (file)
index d418c1f..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
-    <string id="30000">Ziehe Alben Cover von Allmusic.com</string>
-    <string id="30001">Ziehe Alben Cover von Last.fm</string>
-</strings>
diff --git a/addons/metadata.albums.allmusic.com/resources/language/Hungarian/strings.xml b/addons/metadata.albums.allmusic.com/resources/language/Hungarian/strings.xml
deleted file mode 100644 (file)
index 5038141..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
-    <string id="30000">Album bélyegkép letöltése az Allmusic.com-ról</string>
-    <string id="30001">Album bélyegkép letöltése a Last.fm-ről</string>
-</strings>
diff --git a/addons/metadata.albums.allmusic.com/resources/language/Korean/strings.xml b/addons/metadata.albums.allmusic.com/resources/language/Korean/strings.xml
deleted file mode 100644 (file)
index a5202b8..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
-    <string id="30000">Allmusic.com 에서 앨범 사진 가져오기</string>
-    <string id="30001">Last.fm 에서 앨범 사진 가져오기</string>
-</strings>
diff --git a/addons/metadata.albums.allmusic.com/resources/language/Polish/strings.xml b/addons/metadata.albums.allmusic.com/resources/language/Polish/strings.xml
deleted file mode 100644 (file)
index d521f48..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
-    <string id="30000">Pobierz miniatury albumów z Allmusic.com</string>
-    <string id="30001">Pobierz miniatury albumów z Last.fm</string>
-</strings>
diff --git a/addons/metadata.albums.allmusic.com/resources/language/Portuguese/strings.xml b/addons/metadata.albums.allmusic.com/resources/language/Portuguese/strings.xml
deleted file mode 100644 (file)
index 2b2b603..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
-    <string id="30000">Descarregar miniaturas do álbum de Allmusic.com</string>
-    <string id="30001">Descarregar miniaturas do álbum de Last.fm</string>
-</strings>
diff --git a/addons/metadata.albums.allmusic.com/resources/language/Russian/strings.xml b/addons/metadata.albums.allmusic.com/resources/language/Russian/strings.xml
deleted file mode 100644 (file)
index 6f34cd6..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
-    <string id="30000">Получать миниатюры альбомов с Allmusic.com</string>
-    <string id="30001">Получать миниатюры альбомов с Last.fm</string>
-</strings>
diff --git a/addons/metadata.albums.allmusic.com/resources/language/Spanish/strings.xml b/addons/metadata.albums.allmusic.com/resources/language/Spanish/strings.xml
deleted file mode 100644 (file)
index 16b217f..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
-    <string id="30000">Descargar imágenes de Allmusic.com</string>
-    <string id="30001">Descargar imágenes de Last.fm</string>
-</strings>
diff --git a/addons/metadata.albums.allmusic.com/resources/language/Swedish/strings.xml b/addons/metadata.albums.allmusic.com/resources/language/Swedish/strings.xml
deleted file mode 100644 (file)
index 3804ab1..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<!--Language file translated with Team XBMC Translator-->
-<!--Translator: blittan-->
-<!--Email: blittan@xbmc.org-->
-<!--Date of translation: 09/11/2010-->
-<!--$Revision$-->
-<strings>
-  <string id="30000">Hämta albumminiatyr från Allmusic.com</string>
-  <string id="30001">Hämta albumminiatyr från Last.fm</string>
-</strings>
\ No newline at end of file
diff --git a/addons/metadata.albums.allmusic.com/resources/settings.xml b/addons/metadata.albums.allmusic.com/resources/settings.xml
deleted file mode 100644 (file)
index 3071c6d..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<settings>
-    <setting label="30000" type="bool" id="allmusicalbumthumbs" default="true"/>
-    <setting label="30001" type="bool" id="lastfmalbumthumbs" default="true"/>
-</settings>
diff --git a/addons/metadata.artists.allmusic.com/addon.xml b/addons/metadata.artists.allmusic.com/addon.xml
deleted file mode 100644 (file)
index 41e7af2..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<addon id="metadata.artists.allmusic.com"
-       name="AllMusic"
-       version="2.0.7"
-       provider-name="Team XBMC">
-  <requires>
-    <import addon="xbmc.metadata" version="1.0"/>
-    <import addon="metadata.common.last.fm" version="1.1.0"/>
-    <import addon="metadata.common.allmusic.com" version="1.8.2"/>
-    <import addon="metadata.common.htbackdrops.com" version="1.0.7"/>
-  </requires>
-  <extension point="xbmc.metadata.scraper.artists"
-             language="en"
-             library="allmusic.xml"/>
-  <extension point="xbmc.addon.metadata">
-    <summary lang="bg">Инф. за артисти от AllMusic + снимки на артисти от HTBackdrops</summary>
-    <summary lang="en">AllMusic artist information + HTBackdrops artist images</summary>
-    <summary lang="de">Scraper für Künstler-Informationen von AllMusic.com</summary>
-    <summary lang="es">Descarga información de Artistas de AllMusic</summary>
-    <summary lang="fi">AllMusic.com -esittäjätietojen ja HTBackdrops-esittäjäkuvien lataaja</summary>
-    <summary lang="fr">Scraper d'artistes musicaux AllMusic</summary>
-    <summary lang="hu">AllMusic előadó információk</summary>
-    <summary lang="nl">AllMusic-artiestinfo</summary>
-    <summary lang="pl">Informacje o artystach AllMusic</summary>
-    <summary lang="pt">Scraper de músicas AllMusic</summary>
-    <summary lang="ro">Catalog AllMusic pentru informații artiști</summary>
-    <summary lang="ru">Информация об исполнителе из AllMusic</summary>
-    <summary lang="se">AllMusic artistinformation + HTBackdrops artistbilder</summary>
-    <summary lang="zh">AllMusic艺术家信息</summary>
-    <description lang="bg">Попълнете метаинформацията в библиотеката си от AllMusic.com
-Уебсайтът allmusic.com е създаден през 19995, като място за страстни музикални фенове. Засегнати са всички жанрове и стилове музика. От най-комерсиалните и популярни до най-невъзприетите. Критиката към артисти и албуми се прави в контекста на съответните им жанрове - от опера до гаражен рок.
-Home Theater Backdrops (HTBackdrops.com) представлява база от данни с изображения задвижвана от общността около уебсайта. Съдържа висококачествени изображенията на артисти под формата на миниатюри и fanarts. Всички те са създадени или произхождат от общността. Моля, обмислете възможността да качите изображения за любимите ви артисти.</description>
-    <description lang="en">Use AllMusic.com to fill your libray metadata information.
-The allmusic website was created in 1995 as a place for music fans to indulge their passion. All genres and styles of music are covered here, ranging from the most commercially popular to the most obscure. We critique albums and artists within the context of their own genres - from opera to garage rock to traditional country.
-
-Home Theater Backdrops (HTBackdrops.com) is a community driven image database for high quality artist images like thumbs and fanarts. All images have been created or sourced by its members. Please consider uploading your own images of your favorite musician.</description>
-    <description lang="de">Benutze den AllMusic.com-Scraper um deine Musik-Bibliothek mit Metadaten zu füllen. 
-AllMusic.com wurde 1995 gegründet, um Musikliebhabern einen Platz zu geben, Ihre Leidenschaft auszuleben.
-Die AMG Redaktion, zusammen mit hunderten Experten (alles Fachmänner auf Ihrem Gebiet) als Beitragende, machte AllMusic.com zur umfangreichsten Quelle für Musikinformationen auf dem Planeten. Sie sind alle engagiert, um den lebhaften Inhalt, welcher von Musikliebhabern und der Musikindustrie von AMG erwartet wird, zu Erstellen und Pflegen. 
-Alle Genres und Stile der Musik werden hier abgedeckt, reichend von Mainstream bis zum Underground. Wir schreiben Kritiken zu Alben, im Kontext zu dem passenden Genre - von Oper über Garagen Rock bis hin zu traditioneller Country Musik. Das garantiert Fans jeglicher Musikrichtung, dass sie sich auf uns verlassen können, weil wir sie immer up-to-date über Ihre Liblingskünstler halten und Ihnen auch neue Sounds vorstellen</description>
-    <description lang="es">Este scraper utiliza Allmusic.com para rellenar la información de la librería musical.
-La página web allmusic fue creada en el 1995 cómo un sitio donde los fans podíaan compartir su pasión por la música.
-El equipo de AMG, junto con cuentos de colaboradores expertos (todos ellos fans de la música) han hecho de allmusic uno de los sitios más extensos del planeta. Todos ellos intentan crear y mantener unos contenidos que los amantes de la música y los profesionales del sector obtienen de AMG.
-Todos los géneros y estilos musicales tienen cabida, desde los más comerciales hasta los más oscuros. En allmusic se critican los álbumes y los artistas en el entorno que les corresponde - desde opera, pasando por rock hasta country tradicional. Así se asegura que los fans de cualquier estilo de música puedan depender de nosotros para mantenerse al día de las novedades de sus artistas favoritos y descubrir nuevos sonidos.</description>
-    <description lang="fi">Käytä AllMusic.com -sivustoa täyttämään kirjastosi metatiedot.
-AllMusic.com -sivusto luotiin vuonna 1995 paikaksi, jossa musiikkifanit voivat tyydyttää intohimonsa musiikkiin. Kaikki musiikin lajityypit ja tyylisuunnat ovat edustettuina täällä, vaihdellen kaupallisesti suosituimmista kaikkein huomaamattomimpiin. Me arvostelemme albumit ja esittäjät heidän oman lajityyppinsä sisällä - oopperasta ja autotallirokista aina perinteiseen country-musiikkiin.
-HTBackdrops.com -sivusto on yhteisön ylläpitämä tietokanta korkealaatuisille esittäjä- ja fanitaidekuville. Sivuston jäsenet ovat luoneet kaikki sivuston kuvat. Lähetä meille itse tekemäsi suosikkiartistiesi kuvat, jotta voimme lisätä ne tietokantaan.</description>
-    <description lang="fr">Utiliser AllMusic.com pour la récupération des méta-données.
-Le site web AllMusic a été créé en 1995 afin que les fans de musique puissent assouvir leur passion.
-L'équipe rédactionnelle d'AMG, forte de ses centaines de contributeurs avisés (tous passionnés de musique à part entière), a fait de AllMusic la source de référence la plus complète de toute la planète. Chacun s'investissant dans la construction et la maintenance d'un contenu aussi passionné et judicieux que tout amoureux de musique ou tout professionnel de l'industrie serait en droit d'attendre d'AMG.
-Tous les styles et tous les genres y sont représentés, allant du plus commercial au plus confidentiel. Nous critiquons albums et artistes dans le cadre de leur propre style - de l'opéra à la country traditionnelle en passant par le rock garage. Pour les fans de chaque style musical, c'est l'assurance que nous les tenons informés sur leurs artistes préférés ou à l'apprentissage de nouvelles sonorités.</description>
-    <description lang="hu">Az AllMusic.com használata a médiatáradatok feltöltésére. Ez a webhely 1995-ben a zenerajongók szenvedélyének kiszolgálására jött létre.
-Az AMG szerkesztői csapata a szakértő közreműködőkkel együtt (mind zenei fanatikus a maga nemében), az allmusic-ot a legátfogóbb zenei információforrássá tették a világon.
-Minden létező stílus és zenei irányzat feldolgozásra kerül itt. Kezdve a legpopulárisabbtól a legismeretlenebbig. Mi kritikát mondunk a lemezekről és előadókról, az operától a garázs rock-on át a hagyományos country zenéig. Ez biztosítja, hogy bármely stílus rajongói napra készek legyenek a kedvenc előadóikkal, ugyanakkor az új hangzások is eljussanak hozzájuk.</description>
-    <description lang="nl">AllMusic.com gebruiken om de metadata van uw collectie op te halen.
-De AllMusic-website werd in 1995 opgericht om muziekfans een online thuis te bieden.
-De AMG-redactie heeft van AllMusic het meest complete muzieknaslagwerk gemaakt op deze planeet, mede dankzij de bijdragen van honderden experts. Het is hun missie om de hoogstaande inhoud te blijven aanbieden die muziekliefhebbers en professionals ondertussen van AMG verwachten.
-Alle genres en stijlen - of het nu de meest commerciële of de meest obscure zijn - krijgen hier een plaatsje. We bespreken albums en artiesten in de context van hun eigen genre, van opera over garagerock tot traditionele country. Hierdoor kunnen fans van elke muziekstijl bij ons terecht voor de laatste informatie over hun favoriete artiesten, of om nieuwe muziek te leren ontdekken.</description>
-    <description lang="pl">Używa AllMusic.com do pobierania informacji o zawartości Twojej muzycznej biblioteki.</description>
-    <description lang="pt">Use o AllMusic.com para obter a informação da sua Biblioteca de música. O site allmusic foi criado em 1995 para alimentar a paixão dos fans de música.
-O pessoal da redacção da AMG, em conjunto com centenas de especialistas (todos fanáticos por música à sua maneira), tornaram o allmusic o mais completo site de referência musical do planeta. Continuam dedicados a criar e manter o conhecimento, espírito e conteúdos que fans de música e profissionais da indústria se habituaram a obter da AMG.
-Todos os géneros e estilos de música podem ser encontrados aqui, desde o mais comercial e popular até à música mais rara. Nós revemos e criticamos álbuns e artistas dentro do contexto do seu género - the ópera a rock de garagem, de pop a música country. Isto assegura que fans de qualquer género podem depender de nós para os manter actualizados sobre os seus artistas favoritos bem como de novos sons.</description>
-    <description lang="ro">Folosiți AllMusic.com ca sursă pentru mediateca dumneavoastră.
-Site-ul allmusic a fost creat în 1995 ca un loc unde iubitorii de muzică să se răsfețe. Toate genurile și stilurile de muzică sunt incluse aici, începând de la cele mai populare către cele mai obscure. Noi criticăm albumele și artiștii în contextul genurilor proprii.
-
-Home Theater Backdrops (HTBackdrops.com) este o bază de date de imagini realizată de comunitate pentru imagini de înaltă calitate ale artiștiilor, cum ar fi miniaturi și imagini realizate de fani (fanarts). Toate imaginile au fost create sau au ca sursă membrii ei. Vă rugăm să luați în considerare că puteți încărca propriile imagini cu muzicianul preferat.</description>
-    <description lang="ru">Используйте AllMusic.com для добавления мета-данных в вашу библиотеку.
-Сайт allmusic был создан в 1995 как место для фанатов музыки, где они могли бы удовлетворять свою страсть.
-Редакторский состав AMG, вместе с сотнями участников-экспертов (каждый по-своему фанат музыки), сделали allmusic самым полным источником информации о музыке на планете. Все они посвятили себя созданию и поддержке полезного, и познавательного, контента который любители музыки, и профессионалы индустрии, ожидают от AMG.
-Здесь представлены все стили и жанры музыки, от самых коммерчески популярных до наиболее неизвестных. Мы критикуем альбомы и исполнителей в контексте их собственного жанра - от оперы и гаражного рока до традиционного кантри. Это обеспечивает то, что фанат любого стиля музыки может полагаться на нас в поддержке актуальности своих познаний о любимом исполнителе и также расширять свои знания.</description>
-    <description lang="se">Låt AllMusic.com fylla dina mappar med metadatainformation.
-AllMusic's webbplats skapades 1995 som en plats för musikälskare där de kunde njuta av sin passion. Alla genrer och stilar av musik behandlas här, allt från det mest kommersiellt populära till det mest suspekta. De kritiserar album och artister inom ramen för sina egna genrer, allt från opera, garagerock till traditionell countrymusik.
-
-Home Theater Backdrops (HTBackdrops.com) är en gemenskapsdriven bilddatabas för högkvalitativa miniatyrer och fanart på artister. Alla bilder har skapats eller bidragits från medlemmarna. Överväg att ladda upp dina egna bilder av dina favoritartister.</description>
-    <description lang="zh">从AllMusic.com网站获取音乐资料。
-allmusic网站创建于1995年,它是音乐爱好者的乐园。
-AMG的编辑和许多专业撰稿人(都是音乐狂热分子)共同把allmusic建成世界上最全面的音乐资料库。他们致力于创造和维护音乐爱好者和业内专业人士期望从AMG得到的知识和精神产品。
-这里涵盖了所有的音乐流派和风格,评价从最流行到晦涩和冷门的音乐,讨论不同风格的专辑和艺术家 - 从歌剧到摇滚乐到传统的乡村音乐。力求让所有音乐爱好者都能在这里了解他所喜爱的艺术家最新动态,并为他们介绍新的音乐。</description>
-    <platform>all</platform>
-  </extension>
-</addon>
diff --git a/addons/metadata.artists.allmusic.com/allmusic.xml b/addons/metadata.artists.allmusic.com/allmusic.xml
deleted file mode 100644 (file)
index 7ea01cc..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<scraper framework="1.1" date="2010-10-16">
-       <NfoUrl dest="3">
-               <RegExp input="$$1" output="&lt;url&gt;http://www.\1&lt;/url&gt;" dest="3">
-                       <expression>(allmusic.com/artist/.*)</expression>
-               </RegExp>
-       </NfoUrl>
-       <CreateArtistSearchUrl dest="3">
-               <RegExp input="$$1" output="&lt;url&gt;http://www.allmusic.com/search/artist/\1&lt;/url&gt;" dest="3">
-                       <expression/>
-               </RegExp>
-       </CreateArtistSearchUrl>
-       <GetArtistSearchResults dest="8">
-               <RegExp input="$$5" output="&lt;results&gt;\1&lt;/results&gt;" dest="8">
-                       <RegExp input="$$1" output="&lt;entity&gt;&lt;title&gt;\1&lt;/title&gt;&lt;url cache=&quot;am-\2-artist.html&quot;&gt;http://www.allmusic.com/artist/\2&lt;/url&gt;&lt;/entity&gt;" dest="9">
-                               <expression noclean="1">&lt;meta name=&quot;title&quot; content=&quot;([^&quot;]*)&quot;.*?&lt;a href="http://www.allmusic.com/artist/([^/]*)/credits&quot;</expression>
-                       </RegExp>
-                       <RegExp input="$$9" output="\1" dest="5">
-                               <expression noclean="1">(.+)</expression>
-                       </RegExp>
-                       <RegExp input="$$1" output="&lt;entity&gt;&lt;title&gt;\1&lt;/title&gt;&lt;url cache=&quot;am-\2-artist.html&quot;&gt;http://www.allmusic.com/artist/\2&lt;/url&gt;&lt;/entity&gt;" dest="9">
-                               <expression noclean="1">&lt;meta name=&quot;title&quot; content=&quot;([^&quot;]*)&quot;.*?&lt;a href="http://www.allmusic.com/artist/([^/]*)/biography&quot;</expression>
-                       </RegExp>
-                       <RegExp input="$$9" output="\1" dest="5">
-                               <expression noclean="1">(.+)</expression>
-                       </RegExp>
-                       <RegExp input="$$1" output="&lt;entity&gt;&lt;title&gt;\1&lt;/title&gt;&lt;url cache=&quot;am-\2-artist.html&quot;&gt;http://www.allmusic.com/artist/\2&lt;/url&gt;&lt;/entity&gt;" dest="9">
-                               <expression noclean="1">&lt;meta name=&quot;title&quot; content=&quot;([^&quot;]*)&quot;.*?&lt;a href="http://www.allmusic.com/artist/([^/]*)/discography&quot;</expression>
-                       </RegExp>
-                       <RegExp input="$$9" output="\1" dest="5">
-                               <expression noclean="1">(.+)</expression>
-                       </RegExp>
-                       <RegExp input="$$1" output="&lt;entity&gt;&lt;title&gt;\2&lt;/title&gt;&lt;genre&gt;\3&lt;/genre&gt;&lt;year&gt;\4&lt;/year&gt;&lt;url cache=&quot;am-\1-artist.html&quot;&gt;http://www.allmusic.com/artist/\1&lt;/url&gt;&lt;/entity&gt;" dest="5+">
-                               <expression repeat="yes" noclean="1,2">&lt;td&gt;&lt;a href=&quot;http://www.allmusic.com/artist/([^&quot;]*)&quot;&gt;([^&lt;]*)&lt;/a&gt;&lt;/td&gt;[^&gt;]*&gt;([^&lt;]*)&lt;/td&gt;[^&gt;]*&gt;([^&lt;]*)&lt;/td&gt;</expression>
-                       </RegExp>
-                       <expression noclean="1"/>
-               </RegExp>
-       </GetArtistSearchResults>
-       <GetArtistDetails dest="3">
-               <RegExp input="$$5" output="&lt;details&gt;\1&lt;/details&gt;" dest="3">
-                       <RegExp input="$$1" output="\1" dest="7">
-                               <expression noclean="1">&lt;meta name=&quot;title&quot; content=&quot;([^&quot;]*)</expression>
-                       </RegExp>
-                       <RegExp input="$$1" output="\1" dest="8">
-                               <expression>http://www.allmusic.com/artist/([^&amp;&quot;/]*)/</expression>
-                       </RegExp>
-                       <RegExp input="$$7" conditional="htbthumbs" output="&lt;chain function=&quot;GetHTBThumbs&quot;&gt;\1&lt;/chain&gt;" dest="5">
-                               <expression/>
-                       </RegExp>
-                       <RegExp input="$$2" conditional="lastfmartistthumbs" output="&lt;chain function=&quot;GetLastFMArtistThumbsByName&quot;&gt;\1&lt;/chain&gt;" dest="5+">
-                               <expression/>
-                       </RegExp>
-                       <RegExp input="$$8" output="&lt;url cache=&quot;am-\1-artist.html&quot; function=&quot;ParseAMGArtist&quot;&gt;http://www.allmusic.com/artist/\1&lt;/url&gt;" dest="5+">
-                               <expression/>
-                       </RegExp>
-                       <RegExp input="$$7" conditional="htbfanart" output="&lt;chain function=&quot;GetHTBFanart&quot;&gt;\1&lt;/chain&gt;" dest="5+">
-                               <expression/>
-                       </RegExp>
-                       <RegExp input="$$8" output="&lt;url cache=&quot;am-\1-biog.html&quot; function=&quot;GetAMGBiography&quot;&gt;http://www.allmusic.com/artist/\1/biography&lt;/url&gt;" dest="5+">
-                               <expression/>
-                       </RegExp>
-                       <RegExp input="$$8" output="&lt;url cache=&quot;am-\1-discog.html&quot; function=&quot;GetAMGDiscography&quot;&gt;http://www.allmusic.com/artist/\1/discography&lt;/url&gt;" dest="5+">
-                               <expression/>
-                       </RegExp>
-                       <expression noclean="1"/>
-               </RegExp>
-       </GetArtistDetails>
-</scraper>
diff --git a/addons/metadata.artists.allmusic.com/icon.png b/addons/metadata.artists.allmusic.com/icon.png
deleted file mode 100644 (file)
index 9c18e20..0000000
Binary files a/addons/metadata.artists.allmusic.com/icon.png and /dev/null differ
diff --git a/addons/metadata.artists.allmusic.com/resources/language/Bulgarian/strings.xml b/addons/metadata.artists.allmusic.com/resources/language/Bulgarian/strings.xml
deleted file mode 100644 (file)
index ebedf10..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
-    <string id="30000">Включи постер</string>
-    <string id="30001">Вземи снимки за албум от Allmusic.com</string>
-    <string id="30002">Вземи снимки за албум от Last.fm</string>
-    <string id="30003">Вземи снимки за албум от HTBackdrops</string>
-</strings>
diff --git a/addons/metadata.artists.allmusic.com/resources/language/Chinese (Simple)/strings.xml b/addons/metadata.artists.allmusic.com/resources/language/Chinese (Simple)/strings.xml
deleted file mode 100644 (file)
index 0dae926..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
-    <string id="30000">启用同人画</string>
-    <string id="30001">从Allmusic.com获取艺人图片</string>
-    <string id="30002">从Last.fm获取艺人图片</string>
-    <string id="30003">从HTBackdrops获取艺人图片</string>
-</strings>
diff --git a/addons/metadata.artists.allmusic.com/resources/language/Dutch/strings.xml b/addons/metadata.artists.allmusic.com/resources/language/Dutch/strings.xml
deleted file mode 100644 (file)
index 19ece63..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
-    <string id="30000">Fanart inschakelen</string>
-    <string id="30001">Allmusic.com gebruiken voor artiestminiaturen</string>
-    <string id="30002">Last.fm gebruiken voor artiestminiaturen</string>
-    <string id="30003">HTBackdrops gebruiken voor artiestminiaturen</string>
-</strings>
diff --git a/addons/metadata.artists.allmusic.com/resources/language/English/strings.xml b/addons/metadata.artists.allmusic.com/resources/language/English/strings.xml
deleted file mode 100644 (file)
index 7534b41..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
-    <string id="30000">Download Fanarts from HTBackdrops.com</string>
-    <string id="30001">Grab artist thumbs from Allmusic.com</string>
-    <string id="30002">Grab artist thumbs from Last.fm</string>
-    <string id="30003">Grab artist thumbs from HTBackdrops.com</string>
-</strings>
diff --git a/addons/metadata.artists.allmusic.com/resources/language/Finnish/strings.xml b/addons/metadata.artists.allmusic.com/resources/language/Finnish/strings.xml
deleted file mode 100644 (file)
index ae4ff3c..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
-    <string id="30000">Fanitaide käytössä</string>
-    <string id="30001">Hae esittäjän kuvakkeet osoitteesta Allmusic.com</string>
-    <string id="30002">Hae esittäjän kuvakkeet osoitteesta Last.fm</string>
-    <string id="30003">Hae esittäjän kuvakkeet osoitteesta HTBackdrops</string>
-</strings>
diff --git a/addons/metadata.artists.allmusic.com/resources/language/French/strings.xml b/addons/metadata.artists.allmusic.com/resources/language/French/strings.xml
deleted file mode 100644 (file)
index 27f6352..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
-    <string id="30000">Activer les Fanarts</string>
-    <string id="30001">Récupérer les images artistes depuis Allmusic.com</string>
-    <string id="30002">Récupérer les images artistes depuis Last.fm</string>
-    <string id="30003">Récupérer les images artistes depuis HTBackdrops</string>
-</strings>
diff --git a/addons/metadata.artists.allmusic.com/resources/language/German/strings.xml b/addons/metadata.artists.allmusic.com/resources/language/German/strings.xml
deleted file mode 100644 (file)
index 9e44c44..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
-    <string id="30000">Aktiviere Fanart</string>
-    <string id="30001">Ziehe Bilder des Künstler von Allmusic.com</string>
-    <string id="30002">Ziehe Bilder des Künstler von Last.fm</string>
-    <string id="30003">Ziehe Bilder des Künstler von HTBackdrops</string>
-</strings>
diff --git a/addons/metadata.artists.allmusic.com/resources/language/Hungarian/strings.xml b/addons/metadata.artists.allmusic.com/resources/language/Hungarian/strings.xml
deleted file mode 100644 (file)
index 3502108..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
-    <string id="30000">Fanartképek letöltése a HTBackdrops.com-ról</string>
-    <string id="30001">Előadó bélyegkép letöltése az Allmusic.com-ról</string>
-    <string id="30002">Előadó bélyegkép letöltése a Last.fm-ről</string>
-    <string id="30003">Előadó bélyegkép letöltése a HTBackdrops.com-ról</string>
-</strings>
diff --git a/addons/metadata.artists.allmusic.com/resources/language/Korean/strings.xml b/addons/metadata.artists.allmusic.com/resources/language/Korean/strings.xml
deleted file mode 100644 (file)
index e62f7b7..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
-    <string id="30000">팬아트 가져오기</string>
-    <string id="30001">Allmusic.com 에서 음악가 사진 가져오기</string>
-    <string id="30002">Last.fm 에서 음악가 사진 가져오기</string>
-    <string id="30003">HTBackdrops 에서 음악가 사진 가져오기</string>
-</strings>
diff --git a/addons/metadata.artists.allmusic.com/resources/language/Polish/strings.xml b/addons/metadata.artists.allmusic.com/resources/language/Polish/strings.xml
deleted file mode 100644 (file)
index 5a4ab39..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
-    <string id="30000">Włącz fanart</string>
-    <string id="30001">Pobierz miniaturę artysty z Allmusic.com</string>
-    <string id="30002">Pobierz miniaturę artysty z Last.fm</string>
-    <string id="30003">Pobierz miniaturę artysty z HTBackdrops</string>
-</strings>
diff --git a/addons/metadata.artists.allmusic.com/resources/language/Portuguese/strings.xml b/addons/metadata.artists.allmusic.com/resources/language/Portuguese/strings.xml
deleted file mode 100644 (file)
index bbe7a67..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
-    <string id="30000">Ligar Fanart</string>
-    <string id="30001">Descarregar miniaturas do artista de Allmusic.com</string>
-    <string id="30002">Descarregar miniaturas do artista de Last.fm</string>
-    <string id="30003">Descarregar miniaturas do artista de HTBackdrops</string>
-</strings>
diff --git a/addons/metadata.artists.allmusic.com/resources/language/Russian/strings.xml b/addons/metadata.artists.allmusic.com/resources/language/Russian/strings.xml
deleted file mode 100644 (file)
index 7d24737..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
-    <string id="30000">Включить Фанарт</string>
-    <string id="30001">Брать миниатюры с Allmusic.com</string>
-    <string id="30002">Брать миниатюры с Last.fm</string>
-    <string id="30003">Брать миниатюры с HTBackdrops</string>
-</strings>
diff --git a/addons/metadata.artists.allmusic.com/resources/language/Spanish/strings.xml b/addons/metadata.artists.allmusic.com/resources/language/Spanish/strings.xml
deleted file mode 100644 (file)
index 7ce046c..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
-    <string id="30000">Descargar Fanart</string>
-    <string id="30001">Descargar miniaturas de artista de Allmusic.com</string>
-    <string id="30002">Descargar miniaturas de artista de Last.fm</string>
-    <string id="30003">Descargar miniaturas de artista de HTBackdrops</string>
-</strings>
diff --git a/addons/metadata.artists.allmusic.com/resources/language/Swedish/strings.xml b/addons/metadata.artists.allmusic.com/resources/language/Swedish/strings.xml
deleted file mode 100644 (file)
index a63aa7c..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<!--Language file translated with Team XBMC Translator-->
-<!--Translator: blittan-->
-<!--Email: blittan@xbmc.org-->
-<!--Date of translation: 12/26/2011-->
-<!--$Revision$-->
-<strings>
-  <string id="30000">Ladda ner fanart från HTBackdrops.com</string>
-  <string id="30001">Hämta artistminiatyr från Allmusic.com</string>
-  <string id="30002">Hämta artistminiatyr från Last.fm</string>
-  <string id="30003">Hämta artistminiatyr från HTBackdrops.com</string>
-</strings>
\ No newline at end of file
diff --git a/addons/metadata.artists.allmusic.com/resources/settings.xml b/addons/metadata.artists.allmusic.com/resources/settings.xml
deleted file mode 100644 (file)
index bbae2a6..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<settings>
-    <setting label="30000" type="bool" id="htbfanart" default="true"/>
-    <setting label="30001" type="bool" id="allmusicartistthumbs" default="true"/>
-    <setting label="30002" type="bool" id="lastfmartistthumbs" default="false"/>
-    <setting label="30003" type="bool" id="htbthumbs" default="true"/>
-</settings>
diff --git a/addons/metadata.artists.universal/addon.xml b/addons/metadata.artists.universal/addon.xml
new file mode 100644 (file)
index 0000000..2d94544
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<addon id="metadata.artists.universal"
+       name="Universal Artist Scraper"
+       version="2.0.6"
+       provider-name="Team XBMC">
+  <requires>
+    <import addon="xbmc.metadata" version="1.0"/>
+    <import addon="metadata.common.last.fm" version="1.4.1"/>
+    <import addon="metadata.common.allmusic.com" version="2.4.1"/>
+    <import addon="metadata.common.musicbrainz.org" version="1.2.1"/>
+    <import addon="metadata.common.htbackdrops.com" version="1.2.0"/>
+    <import addon="metadata.common.fanart.tv" version="1.1.0"/>
+  </requires>
+  <extension point="xbmc.metadata.scraper.artists"
+             language="en"
+             library="artistuniversal.xml"/>
+  <extension point="xbmc.addon.metadata">
+    <summary lang="en">Universal Scraper for Artists</summary>
+    <description lang="en">This scraper collects information from the following supported sites: 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>
+    <platform>all</platform>
+  </extension>
+</addon>
diff --git a/addons/metadata.artists.universal/artistuniversal.xml b/addons/metadata.artists.universal/artistuniversal.xml
new file mode 100644 (file)
index 0000000..ec474e1
--- /dev/null
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scraper framework="1.1" date="2012-05-28">
+       <NfoUrl dest="3">
+               <RegExp input="$$1" output="&lt;url&gt;http://www.musicbrainz.org/ws/2/artist/\1?inc=url-rels&lt;/url&gt;" dest="3">
+                       <expression>http://musicbrainz.org/artist/(.+)</expression>
+               </RegExp>
+       </NfoUrl>
+       <CreateArtistSearchUrl dest="3">
+               <RegExp input="$$1" output="&lt;url&gt;http://search.musicbrainz.org/ws/2/artist/?fmt=xml&amp;query=artist:&quot;$$4&quot;&amp;limit=100&lt;/url&gt;" dest="3">
+                       <RegExp input="$$1" output="\1" dest="4">
+                               <expression noclean="1">(.+)</expression>
+                       </RegExp>
+                       <RegExp input="$$1" output="\1" dest="6">
+                               <expression noclean="1">(.+)(?:Ft%2e|Feat%2e|Ft.|Feat.|%20and%20)</expression>
+                       </RegExp>
+                       <RegExp input="$$6" output="\1" dest="4">
+                               <expression>(.+)</expression>
+                       </RegExp>
+                       <expression/>
+               </RegExp>
+       </CreateArtistSearchUrl>
+       <GetArtistSearchResults dest="8">
+               <RegExp input="$$5" output="&lt;results&gt;\1&lt;/results&gt;" dest="8">
+                       <RegExp input="$$1" output="&lt;entity&gt;&lt;title&gt;\2&lt;/title&gt;&lt;genre&gt;\7&lt;/genre&gt;&lt;url cache=&quot;mb-\1-artist.xml&quot;&gt;http://www.musicbrainz.org/ws/2/artist/\1?inc=url-rels&lt;/url&gt;&lt;/entity&gt;" dest="9">
+                               <expression repeat="yes" noclean="1">artist ext:score=&quot;[^&quot;]*&quot;(?:\stype=&quot;[^&quot;]*&quot;)* id=&quot;([^&quot;]*)&quot;&gt;&lt;name&gt;([^&lt;]*)&lt;/name&gt;(&lt;sort-name&gt;[^&lt;]*&lt;/sort-name&gt;)?(&lt;gender&gt;[^&lt;]*&lt;/gender&gt;)?(&lt;country&gt;[^&lt;]*&lt;/country&gt;)?(&lt;disambiguation&gt;([^&lt;]*))?</expression>
+                       </RegExp>
+                       <RegExp input="$$9" output="\1" dest="5">
+                               <expression noclean="1">(.+)</expression>
+                       </RegExp>
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetArtistSearchResults>
+       <GetArtistDetails dest="3" clearbuffers="no">
+               <RegExp input="$$5" output="&lt;details&gt;\1&lt;/details&gt;" dest="3">
+                       <!--MBID - Artist-->
+                       <RegExp input="$$1" output="\1" dest="8">
+                               <expression noclean="1">&lt;artist(?:\stype=&quot;[^&quot;]*&quot;)* id=&quot;([^&quot;]*)&quot;&gt;&lt;name&gt;([^&lt;]*)</expression>
+                       </RegExp>
+                       <!--AMGID - Artist-->
+                       <RegExp input="$$1" output="\2" dest="9">
+                               <expression noclean="1">&gt;&lt;relation type=&quot;allmusic&quot;&gt;&lt;target&gt;http://(www.)?allmusic.com/artist/([^&lt;]*)</expression>
+                       </RegExp>
+                       <RegExp input="$$8" conditional="fanarttvthumbs" output="&lt;chain function=&quot;GetFanartTvArtistThumbsByMBID&quot;&gt;\1&lt;/chain&gt;" dest="5+">
+                               <expression/>
+                       </RegExp>
+                       <RegExp input="$$8" conditional="htbthumbs" output="&lt;chain function=&quot;GetHTBThumbsByMBID&quot;&gt;\1&lt;/chain&gt;" dest="5+">
+                               <expression/>
+                       </RegExp>
+                       <RegExp input="$$8" conditional="lastfmartistthumbs" output="&lt;chain function=&quot;GetLastFMArtistThumbsByMBID&quot;&gt;\1&lt;/chain&gt;" dest="5+">
+                               <expression/>
+                       </RegExp>
+                       <RegExp input="$$8" conditional="fanarttvfanart" output="&lt;chain function=&quot;GetFanartTvArtistFanartsByMBID&quot;&gt;\1&lt;/chain&gt;" dest="5+">
+                               <expression/>
+                       </RegExp>
+                       <RegExp input="$$8" conditional="htbfanart" output="&lt;chain function=&quot;GetHTBFanartByMBID&quot;&gt;\1&lt;/chain&gt;" dest="5+">
+                               <expression/>
+                       </RegExp>
+                       <RegExp input="$$9" output="&lt;chain function=&quot;GetAMGData&quot;&gt;\1&lt;/chain&gt;" dest="5+">
+                               <expression noclean="1">(.+)</expression>
+                       </RegExp>
+                       <RegExp input="$$9" output="&lt;chain function=&quot;AMGFallback&quot;&gt;\1&lt;/chain&gt;" dest="5+">
+                               <expression noclean="1">^$</expression>
+                       </RegExp>
+                       <RegExp input="$INFO[discogsource]" output="&lt;chain function=&quot;GetMBDiscographyByMBID&quot;&gt;$$8&lt;/chain&gt;" dest="5+">
+                               <expression>MusicBrainz</expression>
+                       </RegExp>
+                       <RegExp input="$INFO[lifespansource]" output="&lt;chain function=&quot;GetMBLafeSpanByMBID&quot;&gt;$$8&lt;/chain&gt;" dest="5+">
+                               <expression>MusicBrainz</expression>
+                       </RegExp>
+                       <RegExp input="$INFO[biogsource]" output="&lt;chain function=&quot;GetLastFMBiographyByMBID&quot;&gt;$$8&lt;/chain&gt;" dest="5+">
+                               <expression>last.fm</expression>
+                       </RegExp>
+                       <RegExp input="$INFO[discogsource]" output="&lt;chain function=&quot;GetLastFMDiscographyByMBID&quot;&gt;$$8&lt;/chain&gt;" dest="5+">
+                               <expression>last.fm</expression>
+                       </RegExp>
+                       <RegExp input="$INFO[genressource]" output="&lt;chain function=&quot;GetLastFMArtistGenresByMBID&quot;&gt;$$8&lt;/chain&gt;" dest="5+">
+                               <expression>last.fm</expression>
+                       </RegExp>
+                       <RegExp input="$INFO[stylessource]" output="&lt;chain function=&quot;GetLastFMArtistStylesByMBID&quot;&gt;$$8&lt;/chain&gt;" dest="5+">
+                               <expression>last.fm</expression>
+                       </RegExp>
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetArtistDetails>
+
+       <GetAMGData dest="5" clearbuffers="no">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$$1" output="\1" dest="9">
+                               <expression/>
+                       </RegExp>
+                       <RegExp input="" output="" dest="2">
+                               <expression />
+                       </RegExp>
+                       <RegExp input="$INFO[discogsource]" output="&lt;chain function=&quot;GetAMGDiscographyByAMGID&quot;&gt;$$9&lt;/chain&gt;" dest="2">
+                               <expression>allmusic.com</expression>
+                       </RegExp>
+                       <RegExp input="$INFO[lifespansource]" output="&lt;chain function=&quot;GetAMGArtistLifeSpanByAMGID&quot;&gt;$$9&lt;/chain&gt;" dest="2+">
+                               <expression>allmusic.com</expression>
+                       </RegExp>
+                       <RegExp input="$INFO[biogsource]" output="&lt;chain function=&quot;GetAMGBiographyByAMGID&quot;&gt;$$9&lt;/chain&gt;" dest="2+">
+                               <expression>allmusic.com</expression>
+                       </RegExp>
+                       <RegExp input="$INFO[genressource]" output="&lt;chain function=&quot;GetAMGArtistGenresByAMGID&quot;&gt;$$9&lt;/chain&gt;" dest="2+">
+                               <expression>allmusic.com</expression>
+                       </RegExp>
+                       <RegExp input="$INFO[stylessource]" output="&lt;chain function=&quot;GetAMGArtistStylesByAMGID&quot;&gt;$$9&lt;/chain&gt;" dest="2+">
+                               <expression>allmusic.com</expression>
+                       </RegExp>
+                       <RegExp input="$INFO[moodssource]" output="&lt;chain function=&quot;GetAMGArtistMoodsByAMGID&quot;&gt;$$9&lt;/chain&gt;" dest="2+">
+                               <expression>allmusic.com</expression>
+                       </RegExp>
+                       <RegExp input="$INFO[yearsasource]" output="&lt;chain function=&quot;GetAMGArtistYearsActiveByAMGID&quot;&gt;$$9&lt;/chain&gt;" dest="2+">
+                               <expression>allmusic.com</expression>
+                       </RegExp>
+                       <RegExp input="$$9" conditional="allmusicartistthumbs" output="&lt;chain function=&quot;GetAMGArtistThumbsByAMGID&quot;&gt;\1&lt;/chain&gt;" dest="2+">
+                               <expression/>
+                       </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </GetAMGData>
+
+       <AMGFallback dest="5" clearbuffers="no">
+               <RegExp input="$$11" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$INFO[biogfbsource]" output="&lt;chain function=&quot;GetLastFMBiographyByMBID&quot;&gt;$$8&lt;/chain&gt;" dest="11+">
+                               <expression>last.fm</expression>
+                       </RegExp>
+                       <RegExp input="$INFO[discogfbsource]" output="&lt;chain function=&quot;GetLastFMDiscographyByMBID&quot;&gt;$$8&lt;/chain&gt;" dest="11+">
+                               <expression>last.fm</expression>
+                       </RegExp>
+                       <RegExp input="$INFO[discogfbsource]" output="&lt;chain function=&quot;GetMBDiscographyByMBID&quot;&gt;$$8&lt;/chain&gt;" dest="11+">
+                               <expression>MusicBrainz</expression>
+                       </RegExp>
+                       <RegExp input="$INFO[genresfbsource]" output="&lt;chain function=&quot;GetLastFMArtistGenresByMBID&quot;&gt;$$8&lt;/chain&gt;" dest="11+">
+                               <expression>last.fm</expression>
+                       </RegExp>
+                       <RegExp input="$INFO[stylesfbsource]" output="&lt;chain function=&quot;GetLastFMArtistStylesByMBID&quot;&gt;$$8&lt;/chain&gt;" dest="11+">
+                               <expression>last.fm</expression>
+                       </RegExp>
+                       <RegExp input="$INFO[lifespanfbsource]" output="&lt;chain function=&quot;GetMBLafeSpanByMBID&quot;&gt;$$8&lt;/chain&gt;" dest="11+">
+                               <expression>MusicBrainz</expression>
+                       </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </AMGFallback>
+
+</scraper>
diff --git a/addons/metadata.artists.universal/changelog.txt b/addons/metadata.artists.universal/changelog.txt
new file mode 100644 (file)
index 0000000..961ee0b
--- /dev/null
@@ -0,0 +1,37 @@
+[B]2.0.6[/B]
+Fixed: accommodate new Frodo style URL encoding
+
+[B]2.0.5[/B]
+Removed: '&' sign from artist splitter
+
+[B]2.0.4[/B]
+Improved: further improve search results for artists with almost no data
+
+[B]2.0.3[/B]
+Improved: search results are now return artists with almost no data
+
+[B]2.0.2[/B]
+Fixed: artists won't find with 'and' in their name
+
+[B]2.0.1[/B]
+Fixed: potential crashes due to infinite loop
+
+[B]2.0.0[/B]
+Added: Fallback per field
+Added: scraping in case of multiple artists (feat., ft., &, and)
+Added: other improvements
+
+[B]1.2.1[/B]
+Added: Enable all source for artwork by default
+
+[B]1.2.0[/B]
+Added: extra options for Artist Biography
+
+[B]1.1.1[/B]
+Added: handling of new format of allmusic link
+
+[B]1.1.0[/B]
+Added: language setting for last.fm artist biography
+
+[B]1.0.0[/B]
+Initial version
\ No newline at end of file
diff --git a/addons/metadata.artists.universal/icon.png b/addons/metadata.artists.universal/icon.png
new file mode 100644 (file)
index 0000000..7c3d600
Binary files /dev/null and b/addons/metadata.artists.universal/icon.png differ
diff --git a/addons/metadata.artists.universal/resources/language/English/strings.xml b/addons/metadata.artists.universal/resources/language/English/strings.xml
new file mode 100644 (file)
index 0000000..ae97b79
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<strings>
+    <string id="30000">Enable Artist Fanarts from HTBackdrops.com</string>
+    <string id="30001">Enable Artist Thumbs from allmusic.com</string>
+    <string id="30002">Enable Artist Thumbs from last.fm</string>
+    <string id="30003">Enable Artist Thumbs from HTBackdrops.com</string>
+    <string id="30004">Enable Artist Fanarts from fanart.tv</string>
+    <string id="30005">Enable Artist Thumbs from fanart.tv</string>
+    <string id="30006">Get Artist Biography from</string>
+    <string id="30007">Artwork</string>
+    <string id="30008">Get Artist Discography from</string>
+    <string id="30009">Get Artist Genres from</string>
+    <string id="30010">Get Artist Styles from</string>
+    <string id="30011">Get Artist Life-Span from</string>
+    <string id="30012">Get Artist Moods from</string>
+    <string id="30014">Get Artist Years Active from</string>
+    <string id="30015">     Preferred Language</string>
+    <string id="30016">Fallback to Artist Biography from</string>
+    <string id="30017">Fallback to Artist Discography from</string>
+    <string id="30018">Fallback to Artist Genres from</string>
+    <string id="30019">Fallback to Artist Styles from</string>
+    <string id="30020">Fallback to Artist Life-Span from</string>
+    <string id="30021">Fallbacks</string>
+</strings>
diff --git a/addons/metadata.artists.universal/resources/settings.xml b/addons/metadata.artists.universal/resources/settings.xml
new file mode 100644 (file)
index 0000000..c91d6c5
--- /dev/null
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<settings>
+  <category label="128">
+      <setting label="30006" type="labelenum" values="last.fm|None" id="biogsource" default="last.fm"/>
+      <setting label="30015" type="labelenum" values="en|de|es|fr|it|jp|pl|pt|ru|sv|tr|zh" id="lastfmlanguage" default="en" visible="eq(-1,0)"/>
+      <setting type="sep"/>
+      <setting label="30008" type="labelenum" values="last.fm|MusicBrainz|allmusic.com|None" id="discogsource" default="MusicBrainz"/>
+      <setting type="sep"/>
+      <setting label="30009" type="labelenum" values="last.fm|allmusic.com|None" id="genressource" default="last.fm"/>
+      <setting label="30010" type="labelenum" values="last.fm|allmusic.com|None" id="stylessource" default="last.fm"/>
+      <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="last.fm|None" id="biogfbsource" default="None"/>
+      <setting label="30015" type="labelenum" values="en|de|es|fr|it|jp|pl|pt|ru|sv|tr|zh" id="lastfmlanguage" default="en" visible="eq(-1,0)"/>
+      <setting type="sep"/>
+      <setting label="30017" type="labelenum" values="last.fm|MusicBrainz|None" id="discogfbsource" default="None" visible="false"/>
+      <setting label="30018" type="labelenum" values="last.fm|allmusic.com|None" id="genresfbsource" default="None"/>
+      <setting label="30019" type="labelenum" values="last.fm|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">
+    <setting type="lsep" label="Thumb Sources"/>
+    <setting label="30005" type="bool" id="fanarttvthumbs" default="true"/>
+    <setting label="30003" type="bool" id="htbthumbs" default="true"/>
+    <setting label="30002" type="bool" id="lastfmartistthumbs" default="true"/>
+    <setting label="30001" type="bool" id="allmusicartistthumbs" default="true"/>
+    <setting type="lsep" label="Fanart Sources"/>
+    <setting label="30004" type="bool" id="fanarttvfanart" default="true"/>
+    <setting label="30000" type="bool" id="htbfanart" default="true"/>
+  </category>
+
+</settings>
index 0fc8372..8a990a9 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <addon id="metadata.common.allmusic.com"
        name="AllMusic"
-        version="1.9.0"
+        version="2.4.3"
        provider-name="Team XBMC">
   <requires>
     <import addon="xbmc.metadata" version="1.0"/>
index dec3959..fa593d6 100644 (file)
 <scraperfunctions>
-       <GetAMGDiscography dest="5">
-               <RegExp input="$$2$$3" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
-                       <RegExp input="$$1" output="&lt;album&gt;&lt;year&gt;\1&lt;/year&gt;&lt;title&gt;\2&lt;/title&gt;&lt;label&gt;\3&lt;/label&gt;&lt;/album&gt;" dest="2">
-                               <expression repeat="yes" clear="yes" noclean="1,3,4">&lt;td class=&quot;sorted cell&quot;&gt;([^&lt;]*)&lt;/td&gt;.*?&lt;td class=&quot;cell&quot;&gt;&lt;a href=&quot;[^&gt;]*&gt;([^&lt;]*)&lt;.*?&lt;td class=&quot;cell&quot;&gt;([^&lt;]*)&lt;</expression>
+       <GetAMGDiscographyByAMGID dest="5" clearbuffers="no">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url cache=&quot;am-\1-artist.html&quot; function=&quot;ParseAMGDiscography&quot;&gt;http://www.allmusic.com/artist/\1&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression clear="yes" noclean="1"/>
+               </RegExp>
+       </GetAMGDiscographyByAMGID>
+       <ParseAMGDiscography dest="5" clearbuffers="no">
+               <RegExp input="$$3" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="" output="" dest="3">
+                               <expression />
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;album&gt;&lt;year&gt;\1&lt;/year&gt;&lt;title&gt;\2&lt;/title&gt;&lt;label&gt;\3&lt;/label&gt;&lt;/album&gt;" dest="3">
+                               <expression repeat="yes" clear="yes" trim="1">&lt;td class=&quot;year[^&quot;]*&quot;(?:\stitle=&quot;[^&quot;]*&quot;)*\s*data-sort-value=&quot;[^&gt;]*&gt;([^&lt;]*)&lt;/td&gt;[^&lt;]*&lt;td class=&quot;.*?title=&quot;([^&quot;]*)</expression>
+                       </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </ParseAMGDiscography>
+
+       <GetAMGBiographyByAMGID dest="5" clearbuffers="no">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url cache=&quot;am-\1-artist.html&quot; function=&quot;ParseAMGBiography&quot;&gt;http://www.allmusic.com/artist/\1&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetAMGBiographyByAMGID>
+       <ParseAMGBiography dest="5" clearbuffers="no">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="" output="" dest="2">
+                               <expression />
                        </RegExp>
-                       <RegExp input="$$2" output="\1&amp;amp;\2" dest="3">
-                               <expression repeat="yes" noclean="1,2">(.*?)&amp;(.+)</expression>
+                       <RegExp input="$$1" output="\1" dest="11">
+                               <expression clear="yes">&quot; itemprop=&quot;description&quot;&gt;(.*?)div class=&quot;advertisement leaderboard&quot;&gt;</expression>
                        </RegExp>
-                       <RegExp input="$$3" output="" dest="2">
+                       <RegExp input="$$11" output="$$12" dest="2">
+                               <RegExp input="$INFO[biogfbsource]" output="&lt;chain function=&quot;GetLastFMFallbackBiographyByMBID&quot;&gt;$$8&lt;/chain&gt;" dest="12">
+                                       <expression>last.fm</expression>
+                               </RegExp>
+                               <expression>^$</expression>
+                       </RegExp>
+                       <RegExp input="$$11" output="&lt;biography&gt;\1&lt;/biography&gt;" dest="2">
                                <expression>(.+)</expression>
                        </RegExp>
-                       <expression noclean="1" />
+                       <expression noclean="1"/>
+               </RegExp>
+       </ParseAMGBiography>
+
+       <GetAMGFallbackBiographyByAMGID dest="5" clearbuffers="no">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url cache=&quot;am-\1-artist.html&quot; function=&quot;ParseAMGFallbackBiography&quot;&gt;http://www.allmusic.com/artist/\1&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
                </RegExp>
-       </GetAMGDiscography>
-       <GetAMGBiography dest="5">
+       </GetAMGFallbackBiographyByAMGID>
+       <ParseAMGFallbackBiography dest="5" clearbuffers="no">
                <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
-                       <RegExp input="$$1" output="&lt;biography&gt;Fetching artist biography from allmusic.com is not possible due to copyright reasons.&lt;/biography&gt;" dest="2">
-                               <expression clear="yes">Biography&lt;/h2&gt;.*?&lt;/p&gt;(.*?)&lt;/p&gt;</expression>
+                       <RegExp input="" output="" dest="2">
+                               <expression />
+                       </RegExp>
+                       <RegExp input="$$1" output="\1" dest="2">
+                               <expression clear="yes">&quot; itemprop=&quot;description&quot;&gt;(.*?)div class=&quot;advertisement leaderboard&quot;&gt;</expression>
                        </RegExp>
                        <expression noclean="1"/>
                </RegExp>
-       </GetAMGBiography>
-       <GetAMGReview dest="5">
+       </ParseAMGFallbackBiography>
+
+       <GetAMGArtistNameByAMGID dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url cache=&quot;am-\1-artist.html&quot; function=&quot;ParseAMGArtistName&quot;&gt;http://www.allmusic.com/artist/\1&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetAMGArtistNameByAMGID>
+       <ParseAMGArtistName dest="5">
                <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
-                       <RegExp input="$$1" output="&lt;review&gt;Fetching album review from allmusic.com is not possible due to copyright reasons.&lt;/review&gt;" dest="2">
-                               <expression>&lt;h2 class=&quot;title&quot;&gt;Review&lt;/h2&gt;.*?&lt;/p&gt;(.*?)&lt;/p&gt;</expression>
+                       <RegExp input="$$1" output="&lt;name&gt;\1&lt;/name&gt;" dest="2">
+                               <expression noclean="1">http://schema.org/MusicGroup&quot;&gt;[^&lt;]*&lt;span itemprop=&quot;name&quot;&gt;([^&lt;]*)&lt;/span&gt;</expression>
                        </RegExp>
-                       <expression noclean="1" />
+                       <expression noclean="1"/>
                </RegExp>
-       </GetAMGReview>
-       <ParseAMGArtist dest="3">
-               <RegExp input="$$5" output="&lt;details&gt;\1&lt;/details&gt;" dest="3">
-                       <RegExp input="$$1" output="&lt;name&gt;\1&lt;/name&gt;" dest="5">
-                               <expression noclean="1">&lt;meta name=&quot;title&quot; content=&quot;([^&quot;]*)</expression>
+       </ParseAMGArtistName>
+
+       <GetAMGArtistLifeSpanByAMGID dest="5" clearbuffers="no">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url cache=&quot;am-\1-artist.html&quot; function=&quot;ParseAMGArtistLifeSpan&quot;&gt;http://www.allmusic.com/artist/\1&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetAMGArtistLifeSpanByAMGID>
+       <ParseAMGArtistLifeSpan dest="5" clearbuffers="no">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="" output="" dest="2">
+                               <expression />
+                       </RegExp>
+                       <RegExp input="" output="" dest="11">
+                               <expression />
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;born&gt;\1 \2&lt;/born&gt;" dest="11+">
+                               <expression trim="1,2">&lt;dt&gt;\s*Born[^&gt;]*&gt;[^&gt;]*&gt;[^&gt;]*&gt;(.*?\d{4})\s*([^&lt;]*)?</expression>
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;died&gt;\1 \2&lt;/died&gt;" dest="11+">
+                               <expression trim="1,2">&lt;dt&gt;\s*Died[^&gt;]*&gt;[^&gt;]*&gt;[^&gt;]*&gt;(.*?\d{4})\s*([^&lt;]*)?</expression>
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;formed&gt;\1&lt;/formed&gt;" dest="11+">
+                               <expression trim="1,2">&lt;dt&gt;\s*Formed[^&gt;]*&gt;[^&gt;]*&gt;[^&gt;]*&gt;(.*?\d{4})\s*([^&lt;]*)?</expression>
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;disbanded&gt;\1&lt;/disbanded&gt;" dest="11+">
+                               <expression trim="1,2">&lt;dt&gt;\s*Disbanded[^&gt;]*&gt;[^&gt;]*&gt;[^&gt;]*&gt;(.*?\d{4})\s*([^&lt;]*)?</expression>
+                       </RegExp>
+                       <RegExp input="$$11" output="$$12" dest="2">
+                               <RegExp input="$INFO[lifespanfbsource]" output="&lt;chain function=&quot;GetMBFallbackLafeSpanByMBID&quot;&gt;$$8&lt;/chain&gt;" dest="12">
+                                       <expression>MusicBrainz</expression>
+                               </RegExp>
+                       <expression>^$</expression>
+                       </RegExp>
+                       <RegExp input="$$11" output="$$11" dest="2">
+                       <expression noclean="1">&lt;(?:born|formed)*&gt;(.+)&lt;/(?:born|formed)*&gt;</expression>
                        </RegExp>
-                       <RegExp input="$$1" output="&lt;born&gt;\1&lt;/born&gt;" dest="5+">
-                               <expression>&lt;h3&gt;Born[^&gt;]*&gt;[^&gt;]*&gt;(.*?)&lt;/p&gt;</expression>
+                       <expression noclean="1"/>
+               </RegExp>
+       </ParseAMGArtistLifeSpan>
+
+       <GetAMGFallbackArtistLifeSpanByAMGID dest="5" clearbuffers="no">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url cache=&quot;am-\1-artist.html&quot; function=&quot;ParseAMGFallbackArtistLifeSpan&quot;&gt;http://www.allmusic.com/artist/\1&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetAMGFallbackArtistLifeSpanByAMGID>
+       <ParseAMGFallbackArtistLifeSpan dest="5" clearbuffers="no">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="" output="" dest="2">
+                               <expression />
                        </RegExp>
-                       <RegExp input="$$1" output="&lt;born&gt;\1&lt;/born&gt;" dest="5+">
-                               <expression>&lt;h3&gt;Birth[^&gt;]*&gt;[^&gt;]*&gt;(.*?)&lt;/p&gt;</expression>
+                       <RegExp input="$$1" output="&lt;born&gt;\1 \2&lt;/born&gt;" dest="2">
+                               <expression trim="1,2">&lt;dt&gt;\s*Born[^&gt;]*&gt;[^&gt;]*&gt;[^&gt;]*&gt;(.*?\d{4})\s*([^&lt;]*)?</expression>
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;died&gt;\1 \2&lt;/died&gt;" dest="2+">
+                               <expression trim="1,2">&lt;dt&gt;\s*Died[^&gt;]*&gt;[^&gt;]*&gt;[^&gt;]*&gt;(.*?\d{4})\s*([^&lt;]*)?</expression>
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;formed&gt;\1&lt;/formed&gt;" dest="2">
+                               <expression trim="1,2">&lt;dt&gt;\s*Formed[^&gt;]*&gt;[^&gt;]*&gt;[^&gt;]*&gt;(.*?\d{4})\s*([^&lt;]*)?</expression>
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;disbanded&gt;\1&lt;/disbanded&gt;" dest="2+">
+                               <expression trim="1,2">&lt;dt&gt;\s*Disbanded[^&gt;]*&gt;[^&gt;]*&gt;[^&gt;]*&gt;(.*?\d{4})\s*([^&lt;]*)?</expression>
+                       </RegExp>
+                       <expression noclean="1"/>
+               </RegExp>
+       </ParseAMGFallbackArtistLifeSpan>
+
+       <GetAMGArtistYearsActiveByAMGID dest="5" clearbuffers="no">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url cache=&quot;am-\1-artist.html&quot; function=&quot;ParseAMGArtistYearsActive&quot;&gt;http://www.allmusic.com/artist/\1&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetAMGArtistYearsActiveByAMGID>
+       <ParseAMGArtistYearsActive dest="5" clearbuffers="no">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="" output="" dest="2">
+                               <expression />
                        </RegExp>
-                       <RegExp input="$$1" output="&lt;died&gt;\1&lt;/died&gt;" dest="5+">
-                               <expression>&lt;h3&gt;Died[^&gt;]*&gt;[^&gt;]*&gt;(.*?)&lt;/p&gt;</expression>
+                       <RegExp input="$$1" output="&lt;yearsactive&gt;\1&lt;/yearsactive&gt;" dest="2">
+                               <expression trim="1" noclean="1">&lt;dd class=&quot;active&quot;&gt;([^&lt;]*)&lt;</expression>
                        </RegExp>
-                       <RegExp input="$$1" output="&lt;formed&gt;\1&lt;/formed&gt;" dest="5+">
-                               <expression>&lt;h3&gt;Formed[^&gt;]*&gt;[^&gt;]*&gt;(.*?)&lt;/p&gt;</expression>
+                       <expression noclean="1" />
+               </RegExp>
+       </ParseAMGArtistYearsActive>
+
+       <GetAMGArtistGenresByAMGID dest="5" clearbuffers="no">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url cache=&quot;am-\1-artist.html&quot; function=&quot;ParseAMGArtistGenres&quot;&gt;http://www.allmusic.com/artist/\1&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetAMGArtistGenresByAMGID>
+       <ParseAMGArtistGenres dest="5" clearbuffers="no">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="" output="" dest="2">
+                               <expression />
                        </RegExp>
-                       <RegExp input="$$1" output="&lt;disbanded&gt;\1&lt;/disbanded&gt;" dest="5+">
-                               <expression>&lt;h3&gt;Disbanded[^&gt;]*&gt;[^&gt;]*&gt;(.*?)&lt;/p&gt;</expression>
+                       <RegExp input="" output="" dest="6">
+                               <expression />
                        </RegExp>
                        <RegExp input="$$1" output="\1" dest="6">
-                               <expression noclean="1">&lt;h3&gt;Years Active&lt;/h3&gt;(.*?)&lt;/p&gt;</expression>
+                               <expression noclean="1">&lt;dt&gt;Genres&lt;/dt&gt;(.*?)&lt;/dd&gt;</expression>
+                       </RegExp>
+                       <RegExp input="$$6" output="&lt;genre&gt;\2&lt;/genre&gt;" dest="11">
+                               <expression repeat="yes" noclean="1">&lt;li&gt;&lt;a href=&quot;/genre/[^&quot;]*&quot;&gt;(&lt;strong&gt;)?([^&lt;]*)</expression>
                        </RegExp>
-                       <RegExp input="$$6" output="\1's/" dest="7+">
-                               <expression repeat="yes">&lt;span class=&quot;active&quot;&gt;([0-9]+)&lt;/span&gt;</expression>
+                       <RegExp input="$$11" output="$$12" dest="2">
+                               <RegExp input="$INFO[genresfbsource]" output="&lt;chain function=&quot;GetLastFMFallbackArtistGenresByMBID&quot;&gt;$$8&lt;/chain&gt;" dest="12">
+                                       <expression>last.fm</expression>
+                               </RegExp>
+                               <expression>&lt;genre&gt;&lt;/genre&gt;</expression>
                        </RegExp>
-                       <RegExp input="$$7" output="&lt;yearsactive&gt;\1&lt;/yearsactive&gt;" dest="5+">
-                               <expression noclean="1">(.+)/</expression>
+                       <RegExp input="$$11" output="$$11" dest="2">
+                               <expression>&lt;genre&gt;(.+)&lt;/genre&gt;</expression>
+                       </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </ParseAMGArtistGenres>
+
+       <GetAMGFallbackArtistGenresByAMGID dest="5" clearbuffers="no">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url cache=&quot;am-\1-artist.html&quot; function=&quot;ParseAMGFallbackArtistGenres&quot;&gt;http://www.allmusic.com/artist/\1&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetAMGFallbackArtistGenresByAMGID>
+       <ParseAMGFallbackArtistGenres dest="5" clearbuffers="no">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="" output="" dest="2">
+                               <expression />
+                       </RegExp>
+                       <RegExp input="" output="" dest="6">
+                               <expression />
                        </RegExp>
                        <RegExp input="$$1" output="\1" dest="6">
-                               <expression noclean="1">&lt;h3&gt;Genres&lt;/h3&gt;(.*?)&lt;/div&gt;</expression>
+                               <expression noclean="1">&lt;dt&gt;Genres&lt;/dt&gt;(.*?)&lt;/dd&gt;</expression>
+                       </RegExp>
+                       <RegExp input="$$6" output="&lt;genre&gt;\2&lt;/genre&gt;" dest="2">
+                               <expression repeat="yes" noclean="1">&lt;li&gt;&lt;a href=&quot;/genre/[^&quot;]*&quot;&gt;(&lt;strong&gt;)?([^&lt;]*)</expression>
+                       </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </ParseAMGFallbackArtistGenres>
+
+       <GetAMGArtistStylesByAMGID dest="5" clearbuffers="no">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url cache=&quot;am-\1-artist.html&quot; function=&quot;ParseAMGArtistStyles&quot;&gt;http://www.allmusic.com/artist/\1&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetAMGArtistStylesByAMGID>
+       <ParseAMGArtistStyles dest="5" clearbuffers="no">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="" output="" dest="2">
+                               <expression />
                        </RegExp>
-                       <RegExp input="$$6" output="&lt;genre&gt;\2&lt;/genre&gt;" dest="5+">
-                               <expression repeat="yes" noclean="1">&lt;a href=&quot;/explore/genre/[^&gt;]*&gt;(&lt;strong&gt;)?([^&lt;]*)</expression>
+                       <RegExp input="" output="" dest="7">
+                               <expression />
                        </RegExp>
                        <RegExp input="$$1" output="\1" dest="7">
-                               <expression noclean="1">&lt;h3&gt;Styles&lt;/h3&gt;(.*?)&lt;/div&gt;</expression>
+                               <expression noclean="1">&lt;dt&gt;Styles&lt;/dt&gt;(.*?)&lt;/dd&gt;</expression>
                        </RegExp>
-                       <RegExp input="$$7" output="&lt;style&gt;\1&lt;/style&gt;" dest="5+">
-                               <expression repeat="yes" noclean="1">&lt;li&gt;[^&gt;]*&gt;([^&lt;]*)&lt;/a&gt;&lt;/li&gt;</expression>
+                       <RegExp input="$$7" output="&lt;style&gt;\1&lt;/style&gt;" dest="11">
+                               <expression repeat="yes" noclean="1">&lt;li&gt;&lt;a href=&quot;/style/[^&quot;]*&quot;&gt;([^&lt;]*)</expression>
+                       </RegExp>
+                       <RegExp input="$$11" output="$$12" dest="2">
+                               <RegExp input="$INFO[stylesfbsource]" output="&lt;chain function=&quot;GetLastFMFallbackArtistStylesByMBID&quot;&gt;$$8&lt;/chain&gt;" dest="12">
+                                       <expression>last.fm</expression>
+                               </RegExp>
+                               <expression>&lt;style&gt;&lt;/style&gt;</expression>
+                       </RegExp>
+                       <RegExp input="$$11" output="$$11" dest="2">
+                               <expression>&lt;style&gt;(.+)&lt;/style&gt;</expression>
+                       </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </ParseAMGArtistStyles>
+
+       <GetAMGFallbackArtistStylesByAMGID dest="5" clearbuffers="no">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url cache=&quot;am-\1-artist.html&quot; function=&quot;ParseAMGFallbackArtistStyles&quot;&gt;http://www.allmusic.com/artist/\1&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetAMGFallbackArtistStylesByAMGID>
+       <ParseAMGFallbackArtistStyles dest="5" clearbuffers="no">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="" output="" dest="2">
+                               <expression />
+                       </RegExp>
+                       <RegExp input="" output="" dest="7">
+                               <expression />
+                       </RegExp>
+                       <RegExp input="$$1" output="\1" dest="7">
+                               <expression noclean="1">&lt;dt&gt;Styles&lt;/dt&gt;(.*?)&lt;/dd&gt;</expression>
+                       </RegExp>
+                       <RegExp input="$$7" output="&lt;style&gt;\1&lt;/style&gt;" dest="2">
+                               <expression repeat="yes" noclean="1">&lt;li&gt;&lt;a href=&quot;/style/[^&quot;]*&quot;&gt;([^&lt;]*)</expression>
+                       </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </ParseAMGFallbackArtistStyles>
+
+       <GetAMGArtistMoodsByAMGID dest="5" clearbuffers="no">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url cache=&quot;am-\1-artist.html&quot; function=&quot;ParseAMGArtistMoods&quot;&gt;http://www.allmusic.com/artist/\1&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetAMGArtistMoodsByAMGID>
+       <ParseAMGArtistMoods dest="5" clearbuffers="no">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="" output="" dest="2">
+                               <expression />
                        </RegExp>
                        <RegExp input="$$1" output="\1" dest="8">
-                               <expression noclean="1">&lt;h3&gt;Moods&lt;/h3&gt;(.*?)&lt;/div&gt;</expression>
+                               <expression noclean="1">&lt;h4&gt;artist moods&lt;/h4&gt;(.*?)&lt;/ul&gt;</expression>
                        </RegExp>
-                       <RegExp input="$$8" output="&lt;mood&gt;\1&lt;/mood&gt;" dest="5+">
+                       <RegExp input="$$8" output="&lt;mood&gt;\1&lt;/mood&gt;" dest="2">
                                <expression repeat="yes" noclean="1">&lt;li&gt;[^&gt;]*&gt;([^&lt;]*)&lt;/a&gt;&lt;/li&gt;</expression>
                        </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </ParseAMGArtistMoods>
+
+       <GetAMGArtistThumbsByAMGID dest="5" clearbuffers="no">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url cache=&quot;am-\1-artist.html&quot; function=&quot;ParseAMGArtistThumbs&quot;&gt;http://www.allmusic.com/artist/\1&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetAMGArtistThumbsByAMGID>
+       <ParseAMGArtistThumbs dest="5" clearbuffers="no">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="" output="" dest="2">
+                               <expression />
+                       </RegExp>
                        <RegExp input="$$1" output="\1" dest="9">
-                               <expression noclean="1">&lt;h3&gt;Instruments&lt;/h3&gt;(.*?)&lt;/div&gt;</expression>
+                               <expression noclean="1">&lt;h4&gt;photo gallery&lt;/h4&gt;(.*?)&lt;h4&gt;</expression>
                        </RegExp>
-                       <RegExp input="$$9" output="&lt;instruments&gt;\1&lt;/instruments&gt;" dest="5+">
-                               <expression repeat="yes" noclean="1">&lt;li&gt;[^&gt;]*&gt;([^&lt;]*)&lt;/a&gt;&lt;/li&gt;</expression>
+                       <RegExp input="$$9" output="&lt;thumb&gt;http://cps-static.rovicorp.com/3/JPG_1080/\1&lt;/thumb&gt;" dest="2">
+                               <expression repeat="yes" noclean="1">&lt;img src=&quot;http://cps-static.rovicorp.com/3/JPG_[^/]*/([^&quot;]*)</expression>
                        </RegExp>
-                       <RegExp conditional="allmusicartistthumbs" input="$$1" output="&lt;thumb&gt;\1&lt;/thumb&gt;" dest="5+">
-                               <expression noclean="1">&lt;img id=&quot;artist_image&quot; src=&quot;([^&quot;]*)&quot;</expression>
+                       <expression noclean="1"/>
+               </RegExp>
+       </ParseAMGArtistThumbs>
+
+
+       <GetAMGAlbumReviewByAMGID dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url cache=&quot;am-\1-album.html&quot; function=&quot;ParseAMGAlbumReview&quot;&gt;http://www.allmusic.com/album/\1&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetAMGAlbumReviewByAMGID>
+       <ParseAMGAlbumReview dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$$1" output="&lt;review&gt;\1&lt;/review&gt;" dest="2">
+                               <expression>&lt;span itemprop=&quot;description&quot;&gt;([^&lt;]*)</expression>
                        </RegExp>
                        <expression noclean="1" />
                </RegExp>
-       </ParseAMGArtist>
-       <ParseAMGAlbum dest="3">
-               <RegExp input="$$5" output="&lt;details&gt;\1&lt;/details&gt;" dest="3">
-                       <RegExp input="$$1" output="&lt;title&gt;\1&lt;/title&gt;" dest="5">
-                               <expression trim="1" noclean="1">&lt;meta name=&quot;title&quot; content=&quot;([^-]*)-[^&lt;]*&quot; /&gt;</expression>
-                       </RegExp>
-                       <RegExp input="$$1" output="&lt;artist&gt;\1&lt;/artist&gt;" dest="5+">
-                               <expression noclean="1">&lt;meta name=&quot;title&quot; content=&quot;[^-]*- ([^&lt;]*)&quot; /&gt;</expression>
-                       </RegExp>
-                       <RegExp input="$$1" output="&lt;rating&gt;\1&lt;/rating&gt;" dest="5+">
-                               <expression noclean="1">&lt;h3&gt;Rating&lt;/h3&gt;[^_]*_r([0-9^]*)</expression>
+       </ParseAMGAlbumReview>
+
+       <GetAMGAlbumTitleByAMGID dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url cache=&quot;am-\1-album.html&quot; function=&quot;ParseAMGAlbumTitle&quot;&gt;http://www.allmusic.com/album/\1&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetAMGAlbumTitleByAMGID>
+       <ParseAMGAlbumTitle dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$$1" output="&lt;title&gt;\1&lt;/title&gt;" dest="2">
+                               <expression trim="1" noclean="1">&lt;div class=&quot;album-title&quot;&gt;([^&lt;]*)</expression>
                        </RegExp>
-                       <RegExp input="$$1" output="&lt;label&gt;\1&lt;/label&gt;" dest="5+">
-                               <expression noclean="1">&lt;h3&gt;Label&lt;/h3&gt;[^&gt;]*&gt;([^&lt;]*)</expression>
+                       <expression noclean="1" />
+               </RegExp>
+       </ParseAMGAlbumTitle>
+
+       <GetAMGAlbumArtistByAMGID dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url cache=&quot;am-\1-album.html&quot; function=&quot;ParseAMGAlbumArtist&quot;&gt;http://www.allmusic.com/album/\1&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetAMGAlbumArtistByAMGID>
+       <ParseAMGAlbumArtist dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$$1" output="&lt;artist&gt;\1&lt;/artist&gt;" dest="2">
+                               <expression noclean="1">&lt;div class=&quot;album-artist&quot;&gt;[^&gt;]*&gt;([^&lt;]*)</expression>
                        </RegExp>
-                       <RegExp input="$$1" output="&lt;type&gt;\1&lt;/type&gt;" dest="5+">
-                               <expression noclean="1">&lt;h3&gt;Type&lt;/h3&gt;[^&gt;]*&gt;([^&lt;]*)</expression>
+                       <expression noclean="1" />
+               </RegExp>
+       </ParseAMGAlbumArtist>
+
+       <GetAMGAlbumRatingByAMGID dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url cache=&quot;am-\1-album.html&quot; function=&quot;ParseAMGAlbumRating&quot;&gt;http://www.allmusic.com/album/\1&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetAMGAlbumRatingByAMGID>
+       <ParseAMGAlbumRating dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$$1" output="&lt;rating max=&quot;5.0&quot;&gt;\1&lt;/rating&gt;" dest="2">
+                               <expression noclean="1">itemprop=&quot;rating&quot;&gt;([0-9^]*)</expression>
                        </RegExp>
-                       <RegExp input="$$1" output="&lt;releasedate&gt;\1&lt;/releasedate&gt;" dest="5+">
-                               <expression noclean="1">&lt;h3&gt;Release Date&lt;/h3&gt;[^&gt;]*&gt;([^&lt;]*)</expression>
+                       <expression noclean="1" />
+               </RegExp>
+       </ParseAMGAlbumRating>
+
+       <GetAMGAlbumDateByAMGID dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url cache=&quot;am-\1-album.html&quot; function=&quot;ParseAMGAlbumDate&quot;&gt;http://www.allmusic.com/album/\1&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetAMGAlbumDateByAMGID>
+       <ParseAMGAlbumDate dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$$1" output="&lt;releasedate&gt;\1&lt;/releasedate&gt;" dest="2">
+                               <expression noclean="1">&lt;dd class=&quot;release-date&quot;&gt;([^&lt;]*)</expression>
                        </RegExp>
-                       <RegExp input="$$1" output="&lt;year&gt;\1&lt;/year&gt;" dest="5+">
-                               <expression noclean="1">&lt;span&gt;Release Date.*?([0-9]+)&lt;/</expression>
+                       <RegExp input="$$1" output="&lt;year&gt;\2&lt;/year&gt;" dest="2+">
+                               <expression trim="1" noclean="1">&lt;dd class=&quot;release-date&quot;&gt;([^,]*,)?([^&lt;]*)</expression>
                        </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </ParseAMGAlbumDate>
+
+       <GetAMGAlbumGenresByAMGID dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url cache=&quot;am-\1-album.html&quot; function=&quot;ParseAMGAlbumGenres&quot;&gt;http://www.allmusic.com/album/\1&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetAMGAlbumGenresByAMGID>
+       <ParseAMGAlbumGenres dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
                        <RegExp input="$$1" output="\1" dest="6">
-                               <expression noclean="1">&lt;h3&gt;Genre[s]?&lt;/h3&gt;(.*?)&lt;/div&gt;</expression>
+                               <expression noclean="1">&lt;dd class=&quot;genres&quot;&gt;(.*?)&lt;/dd&gt;</expression>
                        </RegExp>
-                       <RegExp input="$$6" output="&lt;genre&gt;\1&lt;/genre&gt;" dest="5+">
+                       <RegExp input="$$6" output="&lt;genre&gt;\1&lt;/genre&gt;" dest="2">
                                <expression repeat="yes" trim="1" noclean="1">&lt;li&gt;[^&gt;]*&gt;([^&lt;]*)&lt;/a&gt;&lt;/li&gt;</expression>
                        </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </ParseAMGAlbumGenres>
+
+       <GetAMGAlbumStylesByAMGID dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url cache=&quot;am-\1-album.html&quot; function=&quot;ParseAMGAlbumStyles&quot;&gt;http://www.allmusic.com/album/\1&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetAMGAlbumStylesByAMGID>
+       <ParseAMGAlbumStyles dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
                        <RegExp input="$$1" output="\1" dest="7">
-                               <expression noclean="1">&lt;h3&gt;Style[s]?&lt;/h3&gt;(.*?)&lt;/div&gt;</expression>
+                               <expression noclean="1">&lt;dd class=&quot;styles&quot;&gt;(.*?)&lt;/dd&gt;</expression>
                        </RegExp>
-                       <RegExp input="$$7" output="&lt;style&gt;\1&lt;/style&gt;" dest="5+">
+                       <RegExp input="$$7" output="&lt;style&gt;\1&lt;/style&gt;" dest="2">
                                <expression repeat="yes" trim="1" noclean="1">&lt;li&gt;[^&gt;]*&gt;([^&lt;]*)&lt;/a&gt;&lt;/li&gt;</expression>
                        </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </ParseAMGAlbumStyles>
+
+       <GetAMGAlbumMoodsByAMGID dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url cache=&quot;am-\1-album.html&quot; function=&quot;ParseAMGAlbumMoods&quot;&gt;http://www.allmusic.com/album/\1&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetAMGAlbumMoodsByAMGID>
+       <ParseAMGAlbumMoods dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
                        <RegExp input="$$1" output="\1" dest="8">
-                               <expression trim="1" noclean="1">&lt;h3&gt;Mood[s]?&lt;/h3&gt;(.*?)&lt;/div&gt;</expression>
+                               <expression trim="1" noclean="1">&gt;\s*&lt;h4&gt;album moods&lt;/h4&gt;(.*?)&lt;/ul&gt;</expression>
                        </RegExp>
-                       <RegExp input="$$8" output="&lt;mood&gt;\1&lt;/mood&gt;" dest="5+">
+                       <RegExp input="$$8" output="&lt;mood&gt;\1&lt;/mood&gt;" dest="2">
                                <expression repeat="yes" noclean="1">&lt;li&gt;[^&gt;]*&gt;([^&lt;]*)&lt;/a&gt;&lt;/li&gt;</expression>
                        </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </ParseAMGAlbumMoods>
+
+       <GetAMGAlbumThemesByAMGID dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url cache=&quot;am-\1-album.html&quot; function=&quot;ParseAMGAlbumThemes&quot;&gt;http://www.allmusic.com/album/\1&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetAMGAlbumThemesByAMGID>
+       <ParseAMGAlbumThemes dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
                        <RegExp input="$$1" output="\1" dest="9">
-                               <expression noclean="1">&lt;h3&gt;Theme[s]?&lt;/h3&gt;(.*?)&lt;/div&gt;</expression>
+                               <expression noclean="1">&lt;h4&gt;album themes&lt;/h4&gt;(.*?)&lt;/ul&gt;</expression>
                        </RegExp>
-                       <RegExp input="$$9" output="&lt;theme&gt;\1&lt;/theme&gt;" dest="5+">
+                       <RegExp input="$$9" output="&lt;theme&gt;\1&lt;/theme&gt;" dest="2">
                                <expression repeat="yes" noclean="1">&lt;li&gt;[^&gt;]*&gt;([^&lt;]*)&lt;/a&gt;&lt;/li&gt;</expression>
                        </RegExp>
-                       <RegExp input="$$1" output="&lt;track&gt;&lt;position&gt;\1&lt;/position&gt;&lt;title&gt;\2&lt;/title&gt;&lt;duration&gt;\3&lt;/duration&gt;&lt;/track&gt;" dest="5+">
-                               <expression repeat="yes" noclean="1,2,3">&quot;cell&quot;&gt;([0-9]+)&lt;.*?&lt;td class=&quot;cell&quot;&gt;[^&gt;]*&gt;([^&lt;]*)&lt;/a&gt;&lt;/td&gt;.*?&lt;td class=&quot;cell&quot;&gt;([0-9]*:[0-9]*)&lt;/td&gt;</expression>
+                       <expression noclean="1" />
+               </RegExp>
+       </ParseAMGAlbumThemes>
+
+       <GetAMGAlbumTracksByAMGID dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url cache=&quot;am-\1-album.html&quot; function=&quot;ParseAMGAlbumTracks&quot;&gt;http://www.allmusic.com/album/\1&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetAMGAlbumTracksByAMGID>
+       <ParseAMGAlbumTracks dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$$1" output="&lt;track&gt;&lt;position&gt;\1&lt;/position&gt;&lt;title&gt;\2&lt;/title&gt;&lt;duration&gt;\3&lt;/duration&gt;&lt;/track&gt;" dest="2">
+                               <expression repeat="yes" trim="1" noclean="1,2,3">&lt;td class=&quot;tracknum&quot;&gt;([0-9]*).*?&lt;div class=&quot;title&quot;&gt;[^&gt;]*&gt;([^&lt;]*).*?&lt;td class=&quot;time&quot;&gt;([^&lt;]*)</expression>
                        </RegExp>
-                       <RegExp conditional="allmusicalbumthumbs" input="$$1" output="&lt;thumb&gt;http://image.allmusic.com/\1&lt;/thumb&gt;" dest="5+">
-                               <expression noclean="1">http://image.allmusic.com/([^&quot;]*)&quot;</expression>
+                       <expression noclean="1" />
+               </RegExp>
+       </ParseAMGAlbumTracks>
+
+       <GetAMGAlbumThumbsByAMGID dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url cache=&quot;am-\1-album.html&quot; function=&quot;ParseAMGAlbumThumbs&quot;&gt;http://www.allmusic.com/album/\1&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetAMGAlbumThumbsByAMGID>
+       <ParseAMGAlbumThumbs dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$$1" output="&lt;thumb&gt;http://cps-static.rovicorp.com/3/JPG_500/\1&lt;/thumb&gt;" dest="2">
+                               <expression noclean="1">&lt;meta property=&quot;og:image&quot; content=&quot;http://cps-static.rovicorp.com/3/JPG_[^/]*/([^&quot;]*)</expression>
+                       </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </ParseAMGAlbumThumbs>
+
+
+       <GetAMGFakeBiographyByAMGID dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url cache=&quot;am-\1-artist.html&quot; function=&quot;ParseAMGFakeBiography&quot;&gt;http://www.allmusic.com/artist/\1&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetAMGFakeBiographyByAMGID>
+       <ParseAMGFakeBiography dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$$1" output="&lt;biography&gt;Fetching artist biography from allmusic.com is not possible due to copyright reasons.&lt;/biography&gt;" dest="2">
+                               <expression noclean="1" />
+                       </RegExp>
+                       <expression noclean="1"/>
+               </RegExp>
+       </ParseAMGFakeBiography>
+
+       <GetAMGFakeAlbumReviewByAMGID dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url cache=&quot;am-\1-album.html&quot; function=&quot;ParseAMGFakeAlbumReview&quot;&gt;http://www.allmusic.com/album/\1&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetAMGFakeAlbumReviewByAMGID>
+       <ParseAMGFakeAlbumReview dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$$1" output="&lt;review&gt;Fetching album review from allmusic.com is not possible due to copyright reasons.&lt;/review&gt;" dest="2">
+                               <expression noclean="1"/>
                        </RegExp>
                        <expression noclean="1" />
                </RegExp>
-       </ParseAMGAlbum>
+       </ParseAMGFakeAlbumReview>
+
 </scraperfunctions>
diff --git a/addons/metadata.common.allmusic.com/icon.png b/addons/metadata.common.allmusic.com/icon.png
new file mode 100644 (file)
index 0000000..9c18e20
Binary files /dev/null and b/addons/metadata.common.allmusic.com/icon.png differ
diff --git a/addons/metadata.common.amazon.de/addon.xml b/addons/metadata.common.amazon.de/addon.xml
new file mode 100644 (file)
index 0000000..d9750bc
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<addon id="metadata.common.amazon.de"
+       name="Amazon.de"
+       version="1.0.0"
+       provider-name="Team XBMC">
+  <requires>
+    <import addon="xbmc.metadata" version="1.0"/>
+  </requires>
+  <extension point="xbmc.metadata.scraper.library"
+             library="amazonde.xml"/>
+  <extension point="xbmc.addon.metadata">
+    <platform>all</platform>
+    <minversion>20000</minversion>
+    <summary lang="en">amazon.de Scraper Library</summary>
+    <description lang="en">Download Music information from amazon.de</description>
+  </extension>
+</addon>
diff --git a/addons/metadata.common.amazon.de/amazonde.xml b/addons/metadata.common.amazon.de/amazonde.xml
new file mode 100644 (file)
index 0000000..a8e054b
--- /dev/null
@@ -0,0 +1,15 @@
+<scraperfunctions>
+       <GetAmazonDEAlbumReviewByASIN dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseAmazonDEAlbumReview&quot;&gt;http://www.amazon.de/exec/obidos/ASIN/\1&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1">(.+)</expression>
+               </RegExp>
+       </GetAmazonDEAlbumReviewByASIN>
+       <ParseAmazonDEAlbumReview dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$$1" output="&lt;review&gt;\1&lt;/review&gt;" dest="2">
+                               <expression fixchars="1">Kurzbeschreibung&lt;/h3&gt;\s*&lt;div class=&quot;productDescriptionWrapper&quot;&gt;(.*?)&lt;div class</expression>
+                       </RegExp>
+                       <expression noclean="1">(.+)</expression>
+               </RegExp>
+       </ParseAmazonDEAlbumReview>
+</scraperfunctions>
diff --git a/addons/metadata.common.fanart.tv/addon.xml b/addons/metadata.common.fanart.tv/addon.xml
new file mode 100644 (file)
index 0000000..0d60546
--- /dev/null
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<addon id="metadata.common.fanart.tv"
+       name="fanart.tv"
+       version="1.1.0"
+       provider-name="Team XBMC">
+  <requires>
+    <import addon="xbmc.metadata" version="1.0"/>
+  </requires>
+  <extension point="xbmc.metadata.scraper.library"
+             library="fanarttv.xml"/>
+  <extension point="xbmc.addon.metadata">
+    <platform>all</platform>
+    <minversion>20000</minversion>
+    <summary lang="bg">Библиотека за сваляне на инф. от fanart.tv</summary>
+    <summary lang="en">fanart.tv Scraper Library</summary>
+    <summary lang="de">Scraper für Hintergründe von fanart.tv</summary>
+    <summary lang="es">Scraper de fanart.tv</summary>
+    <summary lang="fi">fanart.tv taustakuvalataajan kirjasto</summary>
+    <summary lang="fr">Scraper fanart.tv</summary>
+    <summary lang="hu">fanart.tv leolvasó-könyvtár</summary>
+    <summary lang="nl">fanart.tv-scraperfuncties</summary>
+    <summary lang="pl">Scraper biblioteki fanart.tv</summary>
+    <summary lang="pt">Biblioteca de fundos fanart.tv</summary>
+    <summary lang="ru">Обработчик Фоновых изображений с fanart.tv</summary>
+    <summary lang="se">Skrapa för fanart.tv</summary>
+    <summary lang="zh">fanart.tv刮削器代码库</summary>
+    <description lang="bg">Сваля декорации от www.fanart.tv.com</description>
+    <description lang="en">Download backdrops from www.fanart.tv.com</description>
+    <description lang="de">Downloade Hintergründe von www.fanart.tv.com</description>
+    <description lang="es">Descarga fanart y fotos de artistas de www.fanart.tv.com</description>
+    <description lang="fi">Lataa taustakuvia osoitteesta www.fanart.tv.com</description>
+    <description lang="fr">Télécharge les backdrops depuis www.htbackgrops.com</description>
+    <description lang="hu">Fanartképek letöltése www.fanart.tv.com webhelyről</description>
+    <description lang="nl">Achtergronden ophalen van www.fanart.tv.com</description>
+    <description lang="pl">Pobieraj tła z www.fanart.tv.com</description>
+    <description lang="pt">Descarregar fundos de www.fanart.tv.com</description>
+    <description lang="ru">Загружать фоновые изображения с www.fanart.tv.com</description>
+    <description lang="se">Ladda ner bakgrundsbilder från www.fanart.tv.com</description>
+    <description lang="zh">从www.fanart.tv.com下载背景图</description>
+  </extension>
+</addon>
diff --git a/addons/metadata.common.fanart.tv/fanarttv.xml b/addons/metadata.common.fanart.tv/fanarttv.xml
new file mode 100644 (file)
index 0000000..f5b6faf
--- /dev/null
@@ -0,0 +1,58 @@
+<scraperfunctions>
+       <GetFanartTvArtistThumbsByMBID dest="5" clearbuffers="no">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseFanartTvArtistThumbs&quot; cache=&quot;fanarttv-artistimages-\1.xml&quot;&gt;http://fanart.tv/webservice/artist/ed4b784f97227358b31ca4dd966a04f1/\1/xml/&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1" />
+               </RegExp>
+       </GetFanartTvArtistThumbsByMBID>
+       <ParseFanartTvArtistThumbs dest="5" clearbuffers="no">
+               <RegExp input="$$13" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="" output="" dest="13">
+                               <expression />
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;thumb preview=&quot;\1/preview&quot;&gt;\1&lt;/thumb&gt;" dest="13">
+                               <expression repeat="yes" noclean="1">&lt;artistthumb id=&quot;[^&quot;]*&quot; url=&quot;([^&quot;]*)</expression>
+                       </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </ParseFanartTvArtistThumbs>
+
+       <GetFanartTvArtistFanartsByMBID dest="5" clearbuffers="no">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseFanartTvArtistFanarts&quot; cache=&quot;fanarttv-artistimages-\1.xml&quot;&gt;http://fanart.tv/webservice/artist/ed4b784f97227358b31ca4dd966a04f1/\1/xml/&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1" />
+               </RegExp>
+       </GetFanartTvArtistFanartsByMBID>
+       <ParseFanartTvArtistFanarts dest="5" clearbuffers="no">
+               <RegExp input="$$13" output="&lt;details&gt;&lt;fanart&gt;\1&lt;/fanart&gt;&lt;/details&gt;" dest="5">
+                       <RegExp input="" output="" dest="13">
+                               <expression />
+                       </RegExp>
+                       <RegExp input="" output="" dest="14">
+                               <expression />
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;thumb preview=&quot;\1/preview&quot;&gt;\1&lt;/thumb&gt;" dest="14">
+                               <expression repeat="yes" noclean="1">&lt;artistbackground id=&quot;[^&quot;]*&quot; url=&quot;([^&quot;]*)</expression>
+                       </RegExp>
+                       <RegExp input="$$14" output="\1" dest="13">
+                               <expression noclean="1">(.+)</expression>
+                       </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </ParseFanartTvArtistFanarts>
+
+       <GetFanartTvAlbumThumbsByMBID dest="5" clearbuffers="no">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseFanartTvAlbumThumbs&quot; cache=&quot;fanarttv-albumimages-\1.xml&quot;&gt;http://fanart.tv/webservice/album/ed4b784f97227358b31ca4dd966a04f1/\1/xml/&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1" />
+               </RegExp>
+       </GetFanartTvAlbumThumbsByMBID>
+       <ParseFanartTvAlbumThumbs dest="5" clearbuffers="no">
+               <RegExp input="$$13" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="" output="" dest="13">
+                               <expression />
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;thumb preview=&quot;\1/preview&quot;&gt;\1&lt;/thumb&gt;" dest="13">
+                               <expression repeat="yes" noclean="1">&lt;albumcover id=&quot;[^&quot;]*&quot; url=&quot;([^&quot;]*)</expression>
+                       </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </ParseFanartTvAlbumThumbs>
+</scraperfunctions>
index c77de5f..2b7d8b3 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <addon id="metadata.common.htbackdrops.com"
        name="HTBackdrops"
-       version="1.0.7"
+       version="1.2.0"
        provider-name="Team XBMC">
   <requires>
     <import addon="xbmc.metadata" version="1.0"/>
index e29ee83..0531585 100644 (file)
@@ -1,28 +1,51 @@
 <scraperfunctions>
+       <GetHTBThumbsByMBID dest="5" clearbuffers="no">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseHTBThumbs&quot; post=&quot;yes&quot; cache=&quot;htb-images-\1.xml&quot;&gt;http://htbackdrops.com/api/7681a907c805e0670330c694e788e8e8/searchXML?mbid=\1&amp;aid=1,5&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1" />
+               </RegExp>
+       </GetHTBThumbsByMBID>
        <GetHTBThumbs dest="5">
                <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseHTBThumbs&quot; post=&quot;yes&quot; cache=&quot;htb-images-\1.xml&quot;&gt;http://htbackdrops.com/api/7681a907c805e0670330c694e788e8e8/searchXML?keywords=\1&amp;default_operator=and&amp;aid=1,5&lt;/url&gt;&lt;/details&gt;" dest="5">
                        <expression noclean="1" />
                </RegExp>
        </GetHTBThumbs>
-       <ParseHTBThumbs dest="5">
+       <ParseHTBThumbs dest="5" clearbuffers="no">
                <RegExp input="$$13" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="" output="" dest="13">
+                               <expression />
+                       </RegExp>
                        <RegExp input="$$1" output="&lt;thumb preview=&quot;http://www.htbackdrops.com/api/7681a907c805e0670330c694e788e8e8/download/\1/thumbnail&quot;&gt;http://www.htbackdrops.com/api/7681a907c805e0670330c694e788e8e8/download/\1/fullsize&lt;/thumb&gt;" dest="13">
                                <expression repeat="yes" noclean="1">&lt;id&gt;([^&lt;]+)&lt;/id&gt;\n[^&lt;]+&lt;aid&gt;5&lt;/aid&gt;</expression>
                        </RegExp>
-                       <expression noclean="1">(.+)</expression>
+                       <expression noclean="1" />
                </RegExp>
        </ParseHTBThumbs>
+
+       <GetHTBFanartByMBID dest="5" clearbuffers="no">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseHTBFanart&quot; post=&quot;yes&quot; cache=&quot;htb-images-\1.xml&quot;&gt;http://htbackdrops.com/api/7681a907c805e0670330c694e788e8e8/searchXML?mbid=\1&amp;aid=1,5&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1" />
+               </RegExp>
+       </GetHTBFanartByMBID>
        <GetHTBFanart dest="5">
                <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseHTBFanart&quot; post=&quot;yes&quot; cache=&quot;htb-images-\1.xml&quot;&gt;http://htbackdrops.com/api/7681a907c805e0670330c694e788e8e8/searchXML?keywords=\1&amp;default_operator=and&amp;aid=1,5&lt;/url&gt;&lt;/details&gt;" dest="5">
                        <expression noclean="1" />
                </RegExp>
        </GetHTBFanart>
-       <ParseHTBFanart dest="5">
-               <RegExp input="$$13" output="&lt;details&gt;&lt;fanart url=&quot;http://www.htbackdrops.com/&quot;&gt;\1&lt;/fanart&gt;&lt;/details&gt;" dest="5">
-                       <RegExp input="$$1" output="&lt;thumb preview=&quot;api/7681a907c805e0670330c694e788e8e8/download/\1/thumbnail&quot;&gt;api/7681a907c805e0670330c694e788e8e8/download/\1/fullsize&lt;/thumb&gt;" dest="13">
+       <ParseHTBFanart dest="5" clearbuffers="no">
+               <RegExp input="$$13" output="&lt;details&gt;&lt;fanart&gt;\1&lt;/fanart&gt;&lt;/details&gt;" dest="5">
+                       <RegExp input="" output="" dest="13">
+                               <expression />
+                       </RegExp>
+                       <RegExp input="" output="" dest="14">
+                               <expression />
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;thumb preview=&quot;http://www.htbackdrops.com/api/7681a907c805e0670330c694e788e8e8/download/\1/thumbnail&quot;&gt;http://www.htbackdrops.com/api/7681a907c805e0670330c694e788e8e8/download/\1/fullsize&lt;/thumb&gt;" dest="14">
                                <expression repeat="yes" noclean="1">&lt;id&gt;([^&lt;]+)&lt;/id&gt;\n[^&lt;]+&lt;aid&gt;1&lt;/aid&gt;</expression>
                        </RegExp>
-                       <expression noclean="1">(.+)</expression>
+                       <RegExp input="$$14" output="\1" dest="13">
+                               <expression noclean="1">(.+)</expression>
+                       </RegExp>
+                       <expression noclean="1" />
                </RegExp>
        </ParseHTBFanart>
 </scraperfunctions>
diff --git a/addons/metadata.common.htbackdrops.com/icon.png b/addons/metadata.common.htbackdrops.com/icon.png
new file mode 100644 (file)
index 0000000..277ec12
Binary files /dev/null and b/addons/metadata.common.htbackdrops.com/icon.png differ
index 981cf95..8bece1a 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <addon id="metadata.common.last.fm"
        name="Last.FM"
-       version="1.1.0"
+       version="1.4.1"
        provider-name="Team XBMC">
   <requires>
     <import addon="xbmc.metadata" version="1.0"/>
diff --git a/addons/metadata.common.last.fm/icon.png b/addons/metadata.common.last.fm/icon.png
new file mode 100644 (file)
index 0000000..b253ec5
Binary files /dev/null and b/addons/metadata.common.last.fm/icon.png differ
index 6bd19c6..e8c8ee2 100644 (file)
 <scraperfunctions>
-       <GetLastFMDiscography dest="5">
+       <GetLastFMDiscographyByMBID dest="5" clearbuffers="no">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseLastFMDiscography&quot; cache=&quot;lastfmdiscog-\1.xml&quot;&gt;http://ws.audioscrobbler.com/2.0/?method=artist.gettopalbums&amp;amp;mbid=\1&amp;amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetLastFMDiscographyByMBID>
+       <GetLastFMDiscography dest="5" clearbuffers="no">
                <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseLastFMDiscography&quot;&gt;http://ws.audioscrobbler.com/2.0/?method=artist.gettopalbums&amp;amp;artist=\1&amp;amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&lt;/url&gt;&lt;/details&gt;" dest="5">
                        <expression noclean="1"/>
                </RegExp>
        </GetLastFMDiscography>
-       <ParseLastFMDiscography dest="5">
+       <ParseLastFMDiscography dest="5" clearbuffers="no">
                <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
-                       <RegExp input="$$1" output="&lt;album&gt;&lt;title&gt;\1&lt;/title&gt;&lt;/album&gt;" dest="2+">
+                       <RegExp input="" output="" dest="2">
+                               <expression />
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;album&gt;&lt;title&gt;\1&lt;/title&gt;&lt;/album&gt;" dest="2">
                                <expression repeat="yes">&lt;album[^&gt;]*&gt;[^&lt;]*&lt;name&gt;([^&lt;]*?)&lt;/name&gt;</expression>
                        </RegExp>
                        <expression noclean="1"/>
                </RegExp>
        </ParseLastFMDiscography>
-       <GetLastFMArtistThumbsByID dest="5">
-               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseLastFMArtistThumbs&quot;&gt;http://ws.audioscrobbler.com/2.0/?method=artist.getimages&amp;mbid=\1&amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&lt;/url&gt;&lt;/details&gt;" dest="5">
+
+       <GetLastFMBiographyByMBID dest="5" clearbuffers="no">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseLastFMBiography&quot; cache=&quot;lastfmartistinfo-\1.xml&quot;&gt;http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&amp;amp;mbid=\1&amp;amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&amp;lang=$INFO[lastfmlanguage]&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetLastFMBiographyByMBID>
+       <ParseLastFMBiography dest="5" clearbuffers="no">
+               <RegExp input="$$6" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="" output="" dest="6">
+                               <expression />
+                       </RegExp>
+                       <RegExp input="" output="" dest="11">
+                               <expression />
+                       </RegExp>
+                       <RegExp input="$$1" output="\1" dest="11">
+                               <expression fixchars="1">&lt;content&gt;&lt;!\[CDATA\[(.*?)\]\]</expression>
+                       </RegExp>
+                       <RegExp input="$$11" output="$$12" dest="2">
+                               <RegExp input="$INFO[biogfbsource]" output="&lt;chain function=&quot;GetAMGFallbackBiographyByAMGID&quot;&gt;$$9&lt;/chain&gt;" dest="12">
+                                       <expression>allmusic.com</expression>
+                               </RegExp>
+                               <expression>^$</expression>
+                       </RegExp>
+                       <RegExp input="$$11" output="&lt;biography&gt;\1&lt;/biography&gt;" dest="6">
+                               <expression>(.+)</expression>
+                       </RegExp>
+                       <expression noclean="1"/>
+               </RegExp>
+       </ParseLastFMBiography>
+
+       <GetLastFMFallbackBiographyByMBID dest="5" clearbuffers="no">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseLastFMFallbackBiography&quot; cache=&quot;lastfmartistinfo-\1.xml&quot;&gt;http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&amp;amp;mbid=\1&amp;amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&amp;lang=$INFO[lastfmlanguage]&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetLastFMFallbackBiographyByMBID>
+       <ParseLastFMFallbackBiography dest="5" clearbuffers="no">
+               <RegExp input="$$6" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="" output="" dest="6">
+                               <expression />
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;biography&gt;\1&lt;/biography&gt;" dest="6">
+                               <expression fixchars="1">&lt;content&gt;&lt;!\[CDATA\[(.*?)\]\]</expression>
+                       </RegExp>
+                       <expression noclean="1"/>
+               </RegExp>
+       </ParseLastFMFallbackBiography>
+
+       <GetLastFMArtistGenresByMBID dest="5" clearbuffers="no">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseLastFMArtistGenres&quot; cache=&quot;lastfmgenres-\1.xml&quot;&gt;http://ws.audioscrobbler.com/2.0/?method=artist.gettoptags&amp;amp;mbid=\1&amp;amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&amp;lang=$INFO[lastfmlanguage]&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetLastFMArtistGenresByMBID>
+       <ParseLastFMArtistGenres dest="5" clearbuffers="no">
+               <RegExp input="$$4" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="" output="" dest="4">
+                               <expression />
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;genre&gt;\1&lt;/genre&gt;" dest="11">
+                               <expression noclean="1">&lt;tag&gt;.*?&lt;name&gt;([^/lt;]*)&lt;/name&gt;</expression>
+                       </RegExp>
+                       <RegExp input="$$11" output="$$12" dest="4">
+                               <RegExp input="$INFO[genresfbsource]" output="&lt;chain function=&quot;GetAMGFallbackArtistGenresByAMGID&quot;&gt;$$9&lt;/chain&gt;" dest="12">
+                                       <expression>allmusic.com</expression>
+                               </RegExp>
+                               <expression>&lt;genre&gt;&lt;/genre&gt;</expression>
+                       </RegExp>
+                       <RegExp input="$$11" output="$$11" dest="4">
+                               <expression>&lt;genre&gt;(.+)&lt;/genre&gt;</expression>
+                       </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </ParseLastFMArtistGenres>
+
+       <GetLastFMFallbackArtistGenresByMBID dest="5" clearbuffers="no">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseLastFMFallbackArtistGenres&quot; cache=&quot;lastfmgenres-\1.xml&quot;&gt;http://ws.audioscrobbler.com/2.0/?method=artist.gettoptags&amp;amp;mbid=\1&amp;amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&amp;lang=$INFO[lastfmlanguage]&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetLastFMFallbackArtistGenresByMBID>
+       <ParseLastFMFallbackArtistGenres dest="5" clearbuffers="no">
+               <RegExp input="$$4" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="" output="" dest="4">
+                               <expression />
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;genre&gt;\1&lt;/genre&gt;" dest="4">
+                               <expression noclean="1">&lt;tag&gt;.*?&lt;name&gt;([^/lt;]*)&lt;/name&gt;</expression>
+                       </RegExp>
+                       <expression noclean="1"/>
+               </RegExp>
+       </ParseLastFMFallbackArtistGenres>
+
+       <GetLastFMArtistStylesByMBID dest="5" clearbuffers="no">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseLastFMArtistStyles&quot; cache=&quot;lastfmgenres-\1.xml&quot;&gt;http://ws.audioscrobbler.com/2.0/?method=artist.gettoptags&amp;amp;mbid=\1&amp;amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&amp;lang=$INFO[lastfmlanguage]&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetLastFMArtistStylesByMBID>
+       <ParseLastFMArtistStyles dest="5" clearbuffers="no">
+               <RegExp input="$$4" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="" output="" dest="4">
+                               <expression />
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;style&gt;\1&lt;/style&gt;" dest="11">
+                               <expression repeat="yes" noclean="1">&lt;tag&gt;.*?&lt;name&gt;([^/lt;]*)&lt;/name&gt;</expression>
+                       </RegExp>
+                       <RegExp input="$$11" output="$$12" dest="4">
+                               <RegExp input="$INFO[genresfbsource]" output="&lt;chain function=&quot;GetAMGFallbackArtistStylesByAMGID&quot;&gt;$$9&lt;/chain&gt;" dest="12">
+                                       <expression>allmusic.com</expression>
+                               </RegExp>
+                               <expression>&lt;style&gt;&lt;/style&gt;</expression>
+                       </RegExp>
+                       <RegExp input="$$11" output="$$11" dest="4">
+                               <expression>&lt;style&gt;(.+)&lt;/style&gt;</expression>
+                       </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </ParseLastFMArtistStyles>
+
+       <GetLastFMFallbackArtistStylesByMBID dest="5" clearbuffers="no">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseLastFMFallbackArtistStyles&quot; cache=&quot;lastfmgenres-\1.xml&quot;&gt;http://ws.audioscrobbler.com/2.0/?method=artist.gettoptags&amp;amp;mbid=\1&amp;amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&amp;lang=$INFO[lastfmlanguage]&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetLastFMFallbackArtistStylesByMBID>
+       <ParseLastFMFallbackArtistStyles dest="5" clearbuffers="no">
+               <RegExp input="$$4" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="" output="" dest="4">
+                               <expression />
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;style&gt;\1&lt;/style&gt;" dest="4">
+                               <expression repeat="yes" noclean="1">&lt;tag&gt;.*?&lt;name&gt;([^/lt;]*)&lt;/name&gt;</expression>
+                       </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </ParseLastFMFallbackArtistStyles>
+
+       <GetLastFMArtistThumbsByMBID dest="5" clearbuffers="no">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseLastFMArtistThumbs&quot; cache=&quot;lastfmartistimages-\1.xml&quot;&gt;http://ws.audioscrobbler.com/2.0/?method=artist.getimages&amp;amp;mbid=\1&amp;amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&amp;lang=$INFO[lastfmlanguage]&lt;/url&gt;&lt;/details&gt;" dest="5">
                        <expression noclean="1" />
                </RegExp>
-       </GetLastFMArtistThumbsByID>
-       <GetLastFMArtistThumbsByName dest="5">
-               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseLastFMArtistThumbs&quot;&gt;http://ws.audioscrobbler.com/2.0/?method=artist.getimages&amp;artist=\1&amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&lt;/url&gt;&lt;/details&gt;" dest="5">
+       </GetLastFMArtistThumbsByMBID>
+       <GetLastFMArtistThumbsByName dest="5" clearbuffers="no">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseLastFMArtistThumbs&quot;&gt;http://ws.audioscrobbler.com/2.0/?method=artist.getimages&amp;amp;artist=\1&amp;amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&amp;lang=$INFO[lastfmlanguage]&lt;/url&gt;&lt;/details&gt;" dest="5">
                        <expression noclean="1" />
                </RegExp>
        </GetLastFMArtistThumbsByName>
-       <ParseLastFMArtistThumbs dest="5">
+       <ParseLastFMArtistThumbs dest="5" clearbuffers="no">
                <RegExp input="$$6" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="" output="" dest="6">
+                               <expression />
+                       </RegExp>
                        <RegExp input="$$1" output="&lt;thumb preview=&quot;\2&quot;&gt;\1&lt;/thumb&gt;" dest="6">
-                               <expression repeat="yes" noclean="1">&lt;size name="original"[^&gt;]*&gt;([^&lt;]*)&lt;[^&lt;]*&lt;size name="large"[^&gt;]*&gt;([^&lt;]*)&lt;</expression>
+                               <expression repeat="yes" noclean="1">&lt;size name=&quot;original&quot;[^&gt;]*&gt;([^&lt;]*)&lt;[^&lt;]*&lt;size name=&quot;large&quot;[^&gt;]*&gt;([^&lt;]*)&lt;</expression>
                        </RegExp>
-                       <expression noclean="1">(.+)</expression>
+                       <expression noclean="1" />
                </RegExp>
        </ParseLastFMArtistThumbs>
+
+
+       <GetLastFMAlbumTitleByMBID dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseLastFMAlbumTitle&quot; cache=&quot;lastfmalbum-\1.xml&quot;&gt;http://ws.audioscrobbler.com/2.0/?method=album.getinfo&amp;amp;mbid=\1&amp;amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&amp;lang=$INFO[lastfmlanguage]&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetLastFMAlbumTitleByMBID>
+       <GetLastFMAlbumTitleByAlbumAndArtist dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseLastFMAlbumTitle&quot; cache=&quot;lastfmalbum-\4-\3.xml&quot;&gt;http://ws.audioscrobbler.com/2.0/?method=album.getinfo&amp;artist=\2&amp;amp;album=\1&amp;amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&amp;lang=$INFO[lastfmlanguage]&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression encode="1,2">(.+)::(.+)::(.+)::(.+)</expression>
+               </RegExp>
+       </GetLastFMAlbumTitleByAlbumAndArtist>
+       <ParseLastFMAlbumTitle dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$$1" output="&lt;title&gt;\1&lt;/title&gt;" dest="2">
+                               <expression noclean="1">&lt;name&gt;(.*?)&lt;/name&gt;</expression>
+                       </RegExp>
+                       <expression noclean="1">(.+)</expression>
+               </RegExp>
+       </ParseLastFMAlbumTitle>
+
+       <GetLastFMAlbumArtistByMBID dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseLastFMAlbumArtist&quot; cache=&quot;lastfmalbum-\1.xml&quot;&gt;http://ws.audioscrobbler.com/2.0/?method=album.getinfo&amp;amp;mbid=\1&amp;amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&amp;lang=$INFO[lastfmlanguage]&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetLastFMAlbumArtistByMBID>
+       <GetLastFMAlbumArtistByAlbumAndArtist dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseLastFMAlbumArtist&quot; cache=&quot;lastfmalbum-\4-\3.xml&quot;&gt;http://ws.audioscrobbler.com/2.0/?method=album.getinfo&amp;artist=\2&amp;amp;album=\1&amp;amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&amp;lang=$INFO[lastfmlanguage]&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression encode="1,2">(.+)::(.+)::(.+)::(.+)</expression>
+               </RegExp>
+       </GetLastFMAlbumArtistByAlbumAndArtist>
+       <ParseLastFMAlbumArtist dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$$1" output="&lt;artist&gt;\1&lt;/artist&gt;" dest="2">
+                               <expression noclean="1">&lt;artist&gt;(.*?)&lt;/artist&gt;</expression>
+                       </RegExp>
+                       <expression noclean="1">(.+)</expression>
+               </RegExp>
+       </ParseLastFMAlbumArtist>
+
+       <GetLastFMAlbumDateByMBID dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseLastFMAlbumDate&quot; cache=&quot;lastfmalbum-\1.xml&quot;&gt;http://ws.audioscrobbler.com/2.0/?method=album.getinfo&amp;amp;mbid=\1&amp;amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&amp;lang=$INFO[lastfmlanguage]&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetLastFMAlbumDateByMBID>
+       <GetLastFMAlbumDateByAlbumAndArtist dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseLastFMAlbumDate&quot; cache=&quot;lastfmalbum-\4-\3.xml&quot;&gt;http://ws.audioscrobbler.com/2.0/?method=album.getinfo&amp;artist=\2&amp;amp;album=\1&amp;amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&amp;lang=$INFO[lastfmlanguage]&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression encode="1,2">(.+)::(.+)::(.+)::(.+)</expression>
+               </RegExp>
+       </GetLastFMAlbumDateByAlbumAndArtist>
+       <ParseLastFMAlbumDate dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$$1" output="&lt;releasedate&gt;\1&lt;/releasedate&gt;" dest="2">
+                               <expression trim="1">&lt;releasedate&gt;([^,]*)?([^&lt;]*)?&lt;/releasedate&gt;</expression>
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;year&gt;\1&lt;/year&gt;" dest="2+">
+                               <expression trim="1">&lt;releasedate&gt;.*?([0-9]{4})[^&lt;]*&lt;/releasedate&gt;</expression>
+                       </RegExp>
+                       <expression noclean="1">(.+)</expression>
+               </RegExp>
+       </ParseLastFMAlbumDate>
+
+       <GetLastFMAlbumTracksByMBID dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseLastFMAlbumTracks&quot; cache=&quot;lastfmalbum-\1.xml&quot;&gt;http://ws.audioscrobbler.com/2.0/?method=album.getinfo&amp;amp;mbid=\1&amp;amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&amp;lang=$INFO[lastfmlanguage]&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetLastFMAlbumTracksByMBID>
+       <GetLastFMAlbumTracksByAlbumAndArtist dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseLastFMAlbumTracks&quot; cache=&quot;lastfmalbum-\4-\3.xml&quot;&gt;http://ws.audioscrobbler.com/2.0/?method=album.getinfo&amp;artist=\2&amp;amp;album=\1&amp;amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&amp;lang=$INFO[lastfmlanguage]&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression encode="1,2">(.+)::(.+)::(.+)::(.+)</expression>
+               </RegExp>
+       </GetLastFMAlbumTracksByAlbumAndArtist>
+       <ParseLastFMAlbumTracks dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$$1" output="&lt;track&gt;&lt;position&gt;\1&lt;/position&gt;&lt;title&gt;\2&lt;/title&gt;&lt;/track&gt;" dest="2">
+                               <expression repeat="yes" noclean="1">&lt;track rank=&quot;(.*?)&quot;.*?&lt;name&gt;(.*?)&lt;/name&gt;</expression>
+                       </RegExp>
+                       <expression noclean="1">(.+)</expression>
+               </RegExp>
+       </ParseLastFMAlbumTracks>
+
+       <GetLastFMAlbumReviewByMBID dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseLastFMAlbumReview&quot; cache=&quot;lastfmalbum-\1.xml&quot;&gt;http://ws.audioscrobbler.com/2.0/?method=album.getinfo&amp;amp;mbid=\1&amp;amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&amp;lang=$INFO[lastfmlanguage]&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetLastFMAlbumReviewByMBID>
+       <GetLastFMAlbumReviewByAlbumAndArtist dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseLastFMAlbumReview&quot; cache=&quot;lastfmalbum-\4-\3.xml&quot;&gt;http://ws.audioscrobbler.com/2.0/?method=album.getinfo&amp;artist=\2&amp;amp;album=\1&amp;amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&amp;lang=$INFO[lastfmlanguage]&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression encode="1,2">(.+)::(.+)::(.+)::(.+)</expression>
+               </RegExp>
+       </GetLastFMAlbumReviewByAlbumAndArtist>
+       <ParseLastFMAlbumReview dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$$1" output="&lt;review&gt;\1&lt;/review&gt;" dest="2">
+                               <expression fixchars="1">&lt;content&gt;&lt;!\[CDATA\[(.*?)(User-|\]\])</expression>
+                       </RegExp>
+                       <expression noclean="1">(.+)</expression>
+               </RegExp>
+       </ParseLastFMAlbumReview>
+
+       <GetLastFMAlbumThumbsByMBID dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseLastFMAlbumThumbs&quot; cache=&quot;lastfmalbum-\1.xml&quot;&gt;http://ws.audioscrobbler.com/2.0/?method=album.getinfo&amp;amp;mbid=\1&amp;amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&amp;lang=$INFO[lastfmlanguage]&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetLastFMAlbumThumbsByMBID>
        <GetLastFMAlbumThumbs dest="5">
-               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseLastFMAlbumThumbs&quot;&gt;http://ws.audioscrobbler.com/2.0/?method=album.getinfo&amp;artist=\2&amp;album=\1&amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&lt;/url&gt;&lt;/details&gt;" dest="5">
-                       <expression>(.+)::(.+)</expression>
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseLastFMAlbumThumbs&quot; cache=&quot;lastfmalbum-\4-\3.xml&quot;&gt;http://ws.audioscrobbler.com/2.0/?method=album.getinfo&amp;artist=\2&amp;amp;album=\1&amp;amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&amp;lang=$INFO[lastfmlanguage]&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression encode="1,2">(.+)::(.+)::(.+)::(.+)</expression>
                </RegExp>
        </GetLastFMAlbumThumbs>
        <ParseLastFMAlbumThumbs dest="5">
                        <RegExp input="$$1" output="&lt;thumb&gt;\1&lt;/thumb&gt;" dest="2+">
                                <expression noclean="1">&lt;image size=&quot;large&quot;&gt;([^&lt;]*)&lt;/image&gt;</expression>
                        </RegExp>
-                       <expression noclean="1"></expression>
+                       <expression noclean="1">(.+)</expression>
                </RegExp>
        </ParseLastFMAlbumThumbs>
+
 </scraperfunctions>
diff --git a/addons/metadata.common.musicbrainz.org/addon.xml b/addons/metadata.common.musicbrainz.org/addon.xml
new file mode 100644 (file)
index 0000000..42a2635
--- /dev/null
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<addon id="metadata.common.musicbrainz.org"
+       name="musicbrainz"
+        version="1.2.3"
+       provider-name="Team XBMC">
+  <requires>
+    <import addon="xbmc.metadata" version="1.0"/>
+  </requires>
+  <extension point="xbmc.metadata.scraper.library"
+             library="musicbrainz.xml"/>
+  <extension point="xbmc.addon.metadata">
+    <platform>all</platform>
+    <minversion>20000</minversion>
+    <summary lang="bg">Библиотека за сваляне на музикална инф. от MusicBrainz</summary>
+    <summary lang="en">MusicBrainz Music Scraper Library</summary>
+    <summary lang="de">Musik-Scraper für musicbrainz.org</summary>
+    <summary lang="es">Scraper de música de MusicBrainz</summary>
+    <summary lang="fi">MusicBrainz musiikkitietojen lataajan kirjasto</summary>
+    <summary lang="fr">Scraper MusicBrainz pour la musique</summary>
+    <summary lang="hu">MusicBrainz zenei adat leolvasó</summary>
+    <summary lang="nl">MusicBrainz-scraperfuncties</summary>
+    <summary lang="pl">Scraper muzyki MusicBrainz</summary>
+    <summary lang="pt">Scraper de música MusicBrainz</summary>
+    <summary lang="ro">Bibliotecă catalog de muzică MusicBrainz</summary>
+    <summary lang="ru">Музыкальная Информация MusicBrainz</summary>
+    <summary lang="se">Skrapa för musicbrainz.org</summary>
+    <summary lang="zh">MusicBrainz音乐刮削器代码库</summary>
+    <description lang="bg">Извлича инф. за музикални файлове от www.musicbrainz.org</description>
+    <description lang="en">Download Music information from www.musicbrainz.org</description>
+    <description lang="de">Downloade Musik Informationen von www.musicbrainz.org</description>
+    <description lang="es">Descarga información musical de www.musicbrainz.org</description>
+    <description lang="fi">Lataa musiikkitietoja osoitteesta www.musicbrainz.org</description>
+    <description lang="fr">Télécharger les infos musicales depuis www.musicbrainz.org</description>
+    <description lang="hu">Zene információk letöltése a www.musicbrainz.org webhelyről</description>
+    <description lang="nl">Muziekinformatie ophalen van www.musicbrainz.org</description>
+    <description lang="pl">Pobieraj informacje o muzyce z www.musicbrainz.org</description>
+    <description lang="pt">Descarregar informação de música de www.musicbrainz.org</description>
+    <description lang="ro">Descărcați informații muzică de pe www.musicbrainz.org</description>
+    <description lang="ru">Загружать информацию о Музыке с www.musicbrainz.org</description>
+    <description lang="se">Ladda ner musikinformation från www.musicbrainz.org</description>
+    <description lang="zh">从www.musicbrainz.org下载音乐信息</description>
+  </extension>
+</addon>
diff --git a/addons/metadata.common.musicbrainz.org/musicbrainz.xml b/addons/metadata.common.musicbrainz.org/musicbrainz.xml
new file mode 100644 (file)
index 0000000..16e539b
--- /dev/null
@@ -0,0 +1,170 @@
+<scraperfunctions>
+       <GetMBDiscographyByMBID dest="5" clearbuffers="no">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseMBDiscography&quot; cache=&quot;mb-\1-discog.xml&quot;&gt;http://musicbrainz.org/ws/2/release-group?artist=\1&amp;amp;limit=100&amp;amp;type=album&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1" />
+               </RegExp>
+       </GetMBDiscographyByMBID>
+       <ParseMBDiscography dest="5" clearbuffers="no">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="" output="" dest="2">
+                               <expression />
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;album&gt;&lt;year&gt;\4&lt;/year&gt;&lt;title&gt;\2&lt;/title&gt;&lt;label&gt;\1&lt;/label&gt;&lt;/album&gt;" dest="2">
+                               <expression repeat="yes" clear="yes" fixchars="1,2,3" noclean="1,2,3"> type="Album" id="([^"]*)"&gt;&lt;title&gt;([^&lt;]*)&lt;/title&gt;&lt;first-release-date(\s/)?&gt;(\d{4})?</expression>
+                       </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </ParseMBDiscography>
+
+       <GetMBLafeSpanByMBID dest="5" clearbuffers="no">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseMBLifeSpan&quot; cache=&quot;mb-\1-artist.xml&quot;&gt;http://www.musicbrainz.org/ws/2/artist/\1?inc=url-rels&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1" />
+               </RegExp>
+       </GetMBLafeSpanByMBID>
+       <ParseMBLifeSpan dest="5" clearbuffers="no">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="" output="" dest="2">
+                               <expression />
+                       </RegExp>
+                       <RegExp input="" output="" dest="11">
+                               <expression />
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;born&gt;\1&lt;/born&gt;" dest="11">
+                       <expression>&lt;artist type=&quot;Person&quot;.*?&lt;life-span&gt;&lt;begin&gt;([^&lt;]*)</expression>
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;died&gt;\1&lt;/died&gt;" dest="11+">
+                       <expression>&lt;artist type=&quot;Person&quot;.*?&lt;life-span&gt;&lt;begin&gt;[^&lt;]*&lt;/begin&gt;&lt;end&gt;([^&lt;]*)</expression>
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;formed&gt;\1&lt;/formed&gt;" dest="11">
+                       <expression>&lt;artist type=&quot;Group&quot;.*?&lt;life-span&gt;&lt;begin&gt;([^&lt;]*)</expression>
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;disbanded&gt;\1&lt;/disbanded&gt;" dest="11+">
+                       <expression>&lt;artist type=&quot;Group&quot;.*?&lt;life-span&gt;&lt;begin&gt;[^&lt;]*&lt;/begin&gt;&lt;end&gt;([^&lt;]*)</expression>
+                       </RegExp>
+                       <RegExp input="$$11" output="$$12" dest="2">
+                               <RegExp input="$INFO[lifespanfbsource]" output="&lt;chain function=&quot;GetAMGFallbackArtistLifeSpanByAMGID&quot;&gt;$$9&lt;/chain&gt;" dest="12">
+                                       <expression>allmusic.com</expression>
+                               </RegExp>
+                       <expression>^$</expression>
+                       </RegExp>
+                       <RegExp input="$$11" output="$$11" dest="2">
+                       <expression noclean="1">&lt;(?:born|formed)*&gt;(.+)&lt;/(?:born|formed)*&gt;</expression>
+                       </RegExp>
+                       <expression noclean="1"/>
+               </RegExp>
+       </ParseMBLifeSpan>
+
+       <GetMBFallbackLafeSpanByMBID dest="5" clearbuffers="no">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseFallbackMBLifeSpan&quot; cache=&quot;mb-\1-artist.xml&quot;&gt;http://www.musicbrainz.org/ws/2/artist/\1?inc=url-rels&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1" />
+               </RegExp>
+       </GetMBFallbackLafeSpanByMBID>
+       <ParseFallbackMBLifeSpan dest="5" clearbuffers="no">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="" output="" dest="2">
+                               <expression />
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;born&gt;\1&lt;/born&gt;" dest="2">
+                       <expression>&lt;artist type=&quot;Person&quot;.*?&lt;life-span&gt;&lt;begin&gt;([^&lt;]*)</expression>
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;died&gt;\1&lt;/died&gt;" dest="2+">
+                       <expression>&lt;artist type=&quot;Person&quot;.*?&lt;life-span&gt;&lt;begin&gt;[^&lt;]*&lt;/begin&gt;&lt;end&gt;([^&lt;]*)</expression>
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;formed&gt;\1&lt;/formed&gt;" dest="2">
+                       <expression>&lt;artist type=&quot;Group&quot;.*?&lt;life-span&gt;&lt;begin&gt;([^&lt;]*)</expression>
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;disbanded&gt;\1&lt;/disbanded&gt;" dest="2+">
+                       <expression>&lt;artist type=&quot;Group&quot;.*?&lt;life-span&gt;&lt;begin&gt;[^&lt;]*&lt;/begin&gt;&lt;end&gt;([^&lt;]*)</expression>
+                       </RegExp>
+                       <expression noclean="1"/>
+               </RegExp>
+       </ParseFallbackMBLifeSpan>
+
+       <GetMBAlbumTitleByMBID dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseMBAlbumTitle&quot; cache=&quot;mb-\1-album.xml&quot;&gt;http://musicbrainz.org/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1" />
+               </RegExp>
+       </GetMBAlbumTitleByMBID>
+       <ParseMBAlbumTitle dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$$1" output="&lt;title&gt;\1&lt;/title&gt;" dest="2">
+                               <expression noclean="1">&lt;release id=&quot;[^&quot;]*&quot;&gt;&lt;title&gt;([^&lt;]*)&lt;</expression>
+                       </RegExp>
+                       <expression noclean="1">(.+)</expression>
+               </RegExp>
+       </ParseMBAlbumTitle>
+
+       <GetMBAlbumArtistByMBID dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseMBAlbumArtist&quot; cache=&quot;mb-\1-album.xml&quot;&gt;http://musicbrainz.org/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1" />
+               </RegExp>
+       </GetMBAlbumArtistByMBID>
+       <ParseMBAlbumArtist dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$$1" output="&lt;artist&gt;\1&lt;/artist&gt;" dest="2">
+                               <expression noclean="1">&lt;artist id=&quot;[^&quot;]*&quot;&gt;&lt;name&gt;([^&lt;]*)&lt;</expression>
+                       </RegExp>
+                       <expression noclean="1">(.+)</expression>
+               </RegExp>
+       </ParseMBAlbumArtist>
+
+       <GetMBAlbumRatingByMBID dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseMBAlbumRating&quot; cache=&quot;mb-\1-album.xml&quot;&gt;http://musicbrainz.org/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1" />
+               </RegExp>
+       </GetMBAlbumRatingByMBID>
+       <ParseMBAlbumRating dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$$1" output="&lt;rating&gt;\1&lt;/rating&gt;" dest="2">
+                               <expression noclean="1">&lt;/primary-type&gt;&lt;rating votes-count="[^"]*"&gt;(\d)</expression>
+                       </RegExp>
+                       <expression noclean="1">(.+)</expression>
+               </RegExp>
+       </ParseMBAlbumRating>
+
+       <GetMBAlbumLabelByMBID dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseMBAlbumLabel&quot; cache=&quot;mb-\1-album.xml&quot;&gt;http://musicbrainz.org/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1" />
+               </RegExp>
+       </GetMBAlbumLabelByMBID>
+       <ParseMBAlbumLabel dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$$1" output="&lt;label&gt;\1&lt;/label&gt;" dest="2">
+                               <expression noclean="1">&lt;label id=&quot;[^&quot;]*&quot;&gt;&lt;name&gt;([^&lt;]*)</expression>
+                       </RegExp>
+                       <expression noclean="1">(.+)</expression>
+               </RegExp>
+       </ParseMBAlbumLabel>
+
+       <GetMBAlbumDateByMBID dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseMBAlbumDate&quot; cache=&quot;mb-\1-album.xml&quot;&gt;http://musicbrainz.org/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1" />
+               </RegExp>
+       </GetMBAlbumDateByMBID>
+       <ParseMBAlbumDate dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$$1" output="&lt;releasedate&gt;\1&lt;/releasedate&gt;" dest="2">
+                               <expression noclean="1">&lt;first-release-date&gt;([^&lt;]*)&lt;</expression>
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;year&gt;\1&lt;/year&gt;" dest="2+">
+                               <expression noclean="1">&lt;first-release-date&gt;(\d{4})</expression>
+                       </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </ParseMBAlbumDate>
+
+       <GetMBAlbumTracksByMBID dest="5">
+               <RegExp input="$$1" output="&lt;details&gt;&lt;url function=&quot;ParseMBAlbumTracks&quot; cache=&quot;mb-\1-album.xml&quot;&gt;http://musicbrainz.org/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings&lt;/url&gt;&lt;/details&gt;" dest="5">
+                       <expression noclean="1" />
+               </RegExp>
+       </GetMBAlbumTracksByMBID>
+       <ParseMBAlbumTracks dest="5">
+               <RegExp input="$$2" output="&lt;details&gt;\1&lt;/details&gt;" dest="5">
+                       <RegExp input="$$1" output="&lt;track&gt;&lt;position&gt;\1&lt;/position&gt;&lt;title&gt;\4&lt;/title&gt;&lt;duration&gt;\2&lt;/duration&gt;&lt;/track&gt;" dest="2">
+                               <expression repeat="yes">&lt;track&gt;&lt;position&gt;(\d+)&lt;/position&gt;&lt;number&gt;\d*&lt;/number&gt;(?:&lt;length&gt;(\d*?)\d{3}&lt;/length&gt;)*(?:&lt;recording id=&quot;([^&quot;]*)&quot;&gt;)*&lt;title&gt;([^&lt;]*)&lt;</expression>
+                       </RegExp>
+                       <expression noclean="1">(.+)</expression>
+               </RegExp>
+       </ParseMBAlbumTracks>
+
+</scraperfunctions>
diff --git a/addons/metadata.musicvideos.last.fm/addon.xml b/addons/metadata.musicvideos.last.fm/addon.xml
new file mode 100644 (file)
index 0000000..b687aa9
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<addon id="metadata.musicvideos.last.fm"
+       name="Last.fm for Music Videos"
+       version="1.0.0"
+       provider-name="Team XBMC">
+  <requires>
+    <import addon="xbmc.metadata" version="1.0"/>
+    <import addon="metadata.common.last.fm" version="1.3.2"/>
+    <import addon="metadata.common.fanart.tv" version="1.0.1"/>
+  </requires>
+  <extension point="xbmc.metadata.scraper.musicvideos"
+             language="en"
+             library="lastfmmusicvideos.xml"/>
+  <extension point="xbmc.addon.metadata">
+    <summary lang="bg">Сваля инф. за музикални клипове от Last.fm</summary>
+    <summary lang="en">Last.fm Music Video Scraper</summary>
+    <summary lang="fi">Last.fm musiikkivideotietojen lataaja</summary>
+    <summary lang="hu">Last.fm videóklip leolvasó</summary>
+    <summary lang="kr">야후! 뮤직 비디오 스크래퍼</summary>
+    <summary lang="pl">Scraper teledysków Last.fm</summary>
+    <summary lang="pt">Scraper de música Last.fm</summary>
+    <summary lang="se">Skrapa för Last.fm musik</summary>
+    <description lang="bg">Сваля информация за музикални клипове</description>
+    <description lang="en">Download Music Video information</description>
+    <description lang="fi">Lataa musiikkivideoiden tiedot</description>
+    <description lang="hu">Videóklip információk letöltése a Last.fm webhelyről</description>
+    <description lang="kr">뮤직 비디오 정보 다운로드</description>
+    <description lang="pl">Pobieraj informacje o teledyskach z last.fm</description>
+    <description lang="pt">Descarregar informação de filmes de last.fm</description>
+    <description lang="se">Ladda ner musikvideoinformation från last.fm</description>
+  </extension>
+</addon>
diff --git a/addons/metadata.musicvideos.last.fm/icon.png b/addons/metadata.musicvideos.last.fm/icon.png
new file mode 100644 (file)
index 0000000..b253ec5
Binary files /dev/null and b/addons/metadata.musicvideos.last.fm/icon.png differ
diff --git a/addons/metadata.musicvideos.last.fm/lastfmmusicvideos.xml b/addons/metadata.musicvideos.last.fm/lastfmmusicvideos.xml
new file mode 100644 (file)
index 0000000..64d58e7
--- /dev/null
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scraper framework="1.1" date="2012-06-10">
+       <CreateSearchUrl dest="3">
+               <RegExp input="$$1" output="&lt;url cache=&quot;lastfmm-\2.xml&quot;&gt;http://ws.audioscrobbler.com/2.0/?method=track.getinfo&amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&amp;artist=\1&amp;track=\2&lt;/url&gt;" dest="3">
+                       <expression trim="1,2">(.+)%20%20%20(.+)</expression>
+               </RegExp>
+       </CreateSearchUrl>
+       <GetSearchResults dest="3">
+               <RegExp input="$$5" output="&lt;results&gt;\1&lt;/results&gt;" dest="3">
+                       <RegExp input="$$1" output="\1" dest="6">
+                               <expression>&lt;/id&gt;\s*&lt;name&gt;([^&lt;]*).*?&lt;artist&gt;\s*&lt;name&gt;([^&lt;]*)</expression>
+                       </RegExp>
+                       <RegExp input="$$1" output="\2" dest="7">
+                               <expression>&lt;/id&gt;\s*&lt;name&gt;([^&lt;]*).*?&lt;artist&gt;\s*&lt;name&gt;([^&lt;]*)</expression>
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;entity&gt;&lt;title&gt;$$7 - $$6&lt;/title&gt;&lt;url cache=&quot;lastfmm-\1.xml&quot;&gt;http://ws.audioscrobbler.com/2.0/?method=track.getinfo&amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&amp;artist=\2&amp;track=\1&lt;/url&gt;&lt;/entity&gt;" dest="5">
+                               <expression encode="1,2">&lt;/id&gt;\s*&lt;name&gt;([^&lt;]*).*?&lt;artist&gt;\s*&lt;name&gt;([^&lt;]*)</expression>
+                       </RegExp>
+                       <expression noclean="1" />
+               </RegExp>
+       </GetSearchResults>
+       <GetDetails dest="3">
+               <RegExp input="$$5" output="&lt;details&gt;\1&lt;/details&gt;" dest="3">
+                       <RegExp input="$$1" output="\1" dest="4">
+                               <expression>&lt;/title&gt;\s*&lt;mbid&gt;([^&lt;]*)&lt;</expression>
+                       </RegExp>
+                       <RegExp input="$$1" output="\1" dest="7">
+                               <expression>&lt;album[^&gt;]*&gt;\s*&lt;artist&gt;\s*[^&lt;]*&lt;/artist&gt;\s*&lt;title&gt;([^&lt;]*)&lt;/title&gt;</expression>
+                       </RegExp>
+                       <RegExp input="$$1" output="\1" dest="8">
+                               <expression>&lt;artist&gt;\s*&lt;name&gt;([^&lt;]*)&lt;</expression>
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;title&gt;\1&lt;/title&gt;" dest="5">
+                               <expression>&lt;name&gt;([^&lt;]*)&lt;</expression>
+                       </RegExp>
+                       <RegExp input="$$8" output="&lt;artist&gt;\1&lt;/artist&gt;" dest="5+">
+                               <expression noclean="1" />
+                       </RegExp>
+                       <RegExp input="$$7" output="&lt;album&gt;\1&lt;/album&gt;" dest="5+">
+                               <expression noclean="1" />
+                       </RegExp>
+                       <RegExp input="$$4" output="&lt;chain function=&quot;GetLastFMAlbumDateByAlbumAndArtist&quot;&gt;$$7::$$8::$$7::$$8&lt;/chain&gt;" dest="5+">
+                               <expression noclean="1" />
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;plot&gt;\1&lt;/plot&gt;" dest="5+">
+                               <expression fixchars="1">&lt;content&gt;&lt;!\[CDATA\[(.*?)(User-|\]\])</expression>
+                       </RegExp>
+                       <RegExp input="$$1" output="&lt;genre&gt;\1&lt;/genre&gt;" dest="5+">
+                               <expression repeat="yes">&lt;tag&gt;\s*&lt;name&gt;([^&lt;]*)&lt;/name&gt;</expression>
+                       </RegExp>
+                       <RegExp conditional="lastfmalbumthumbs" input="$$1" output="&lt;thumb&gt;\1&lt;/thumb&gt;" dest="5+">
+                               <expression>&lt;image size="extralarge"&gt;\s*([^&lt;]*)\s*&lt;/image&gt;</expression>
+                       </RegExp>
+                       <RegExp conditional="fanarttvalbumthumbs" input="$$1" output="&lt;chain function=&quot;GetFanartTvAlbumThumbsByMBID&quot;&gt;$$4&lt;/chain&gt;" dest="5+">
+                               <expression noclean="1">(.+)</expression>
+                       </RegExp>
+                       <RegExp conditional="lastfmalbumthumbs" input="$$1" output="&lt;chain function=&quot;GetLastFMAlbumThumbs&quot;&gt;$$7::$$8::$$7::$$8&lt;/chain&gt;" dest="5+">
+                               <expression noclean="1" />
+                       </RegExp>
+                       <expression noclean="1"/>
+               </RegExp>
+       </GetDetails>
+</scraper>
diff --git a/addons/metadata.musicvideos.last.fm/resources/language/English/strings.xml b/addons/metadata.musicvideos.last.fm/resources/language/English/strings.xml
new file mode 100644 (file)
index 0000000..acb2b4f
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<strings>
+    <string id="30000">Grab album thumbs from fanart.tv</string>
+    <string id="30001">Grab album thumbs from Last.fm</string>
+</strings>
diff --git a/addons/metadata.musicvideos.last.fm/resources/settings.xml b/addons/metadata.musicvideos.last.fm/resources/settings.xml
new file mode 100644 (file)
index 0000000..4034620
--- /dev/null
@@ -0,0 +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="lastfmalbumthumbs" default="true"/>
+</settings>
diff --git a/addons/metadata.yahoomusic.com/addon.xml b/addons/metadata.yahoomusic.com/addon.xml
deleted file mode 100644 (file)
index 425358f..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<addon id="metadata.yahoomusic.com"
-       name="Yahoo Music Videos"
-       version="1.0.4"
-       provider-name="Team XBMC">
-  <requires>
-    <import addon="xbmc.metadata" version="1.0"/>
-  </requires>
-  <extension point="xbmc.metadata.scraper.musicvideos"
-             language="en"
-             library="yahoomusic.xml"/>
-  <extension point="xbmc.addon.metadata">
-    <summary lang="bg">Сваля инф. за музикални клипове от Yahoo!</summary>
-    <summary lang="en">Yahoo! Music Video Scraper</summary>
-    <summary lang="fi">Yahoo! musiikkivideotietojen lataaja</summary>
-    <summary lang="hu">Yahoo! videóklip leolvasó</summary>
-    <summary lang="kr">야후! 뮤직 비디오 스크래퍼</summary>
-    <summary lang="pl">Scraper teledysków Yahoo!</summary>
-    <summary lang="pt">Scraper de música Yahoo!</summary>
-    <summary lang="se">Skrapa för Yahoo! musik</summary>
-    <description lang="bg">Сваля информация за музикални клипове</description>
-    <description lang="en">Download Music Video information</description>
-    <description lang="fi">Lataa musiikkivideoiden tiedot</description>
-    <description lang="hu">Videóklip információk letöltése a Yahoo! webhelyről</description>
-    <description lang="kr">뮤직 비디오 정보 다운로드</description>
-    <description lang="pl">Pobieraj informacje o teledyskach z music.yahoo.com</description>
-    <description lang="pt">Descarregar informação de filmes de music.yahoo.com</description>
-    <description lang="se">Ladda ner musikvideoinformation från music.yahoo.com</description>
-  </extension>
-</addon>
diff --git a/addons/metadata.yahoomusic.com/icon.png b/addons/metadata.yahoomusic.com/icon.png
deleted file mode 100644 (file)
index f04e6f4..0000000
Binary files a/addons/metadata.yahoomusic.com/icon.png and /dev/null differ
diff --git a/addons/metadata.yahoomusic.com/resources/language/Dutch/strings.xml b/addons/metadata.yahoomusic.com/resources/language/Dutch/strings.xml
deleted file mode 100644 (file)
index 93ec0c6..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<strings>
-    <!-- settings labels -->
-    <string id="30000">Afmetingen van de voorbeeld afbeeldingen</string>
-</strings>
diff --git a/addons/metadata.yahoomusic.com/resources/language/English/strings.xml b/addons/metadata.yahoomusic.com/resources/language/English/strings.xml
deleted file mode 100644 (file)
index b41bc3e..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<strings>
-    <!-- settings labels -->
-    <string id="30000">Thumb(s) Size</string>
-</strings>
diff --git a/addons/metadata.yahoomusic.com/resources/language/Finnish/strings.xml b/addons/metadata.yahoomusic.com/resources/language/Finnish/strings.xml
deleted file mode 100644 (file)
index cba8217..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<strings>
-    <!-- settings labels -->
-    <string id="30000">Pienoiskuvien koko</string>
-</strings>
diff --git a/addons/metadata.yahoomusic.com/resources/language/Hungarian/strings.xml b/addons/metadata.yahoomusic.com/resources/language/Hungarian/strings.xml
deleted file mode 100644 (file)
index 8944ed5..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<strings>
-    <!-- settings labels -->
-    <string id="30000">Bélyegképek mérete</string>
-</strings>
diff --git a/addons/metadata.yahoomusic.com/resources/language/Korean/strings.xml b/addons/metadata.yahoomusic.com/resources/language/Korean/strings.xml
deleted file mode 100644 (file)
index 4532347..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<strings>
-    <!-- settings labels -->
-    <string id="30000">미리보기 크기</string>
-</strings>
diff --git a/addons/metadata.yahoomusic.com/resources/language/Polish/strings.xml b/addons/metadata.yahoomusic.com/resources/language/Polish/strings.xml
deleted file mode 100644 (file)
index 05b9a8d..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<strings>
-    <!-- settings labels -->
-    <string id="30000">Rozmiar miniatur</string>
-</strings>
diff --git a/addons/metadata.yahoomusic.com/resources/language/Portuguese/strings.xml b/addons/metadata.yahoomusic.com/resources/language/Portuguese/strings.xml
deleted file mode 100644 (file)
index 72d365c..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<strings>
-    <!-- settings labels -->
-    <string id="30000">Tamanho de miniaturas</string>
-</strings>
diff --git a/addons/metadata.yahoomusic.com/resources/language/Swedish/strings.xml b/addons/metadata.yahoomusic.com/resources/language/Swedish/strings.xml
deleted file mode 100644 (file)
index aa781c2..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<!--Language file translated with Team XBMC Translator-->
-<!--Translator: blittan-->
-<!--Email: blittan@xbmc.org-->
-<!--Date of translation: 12/26/2011-->
-<!--$Revision$-->
-<strings>
-  <string id="30000">Miniatyrstorlek</string>
-</strings>
diff --git a/addons/metadata.yahoomusic.com/resources/settings.xml b/addons/metadata.yahoomusic.com/resources/settings.xml
deleted file mode 100644 (file)
index 373a6de..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<settings>
-    <setting label="30000" type="labelenum" values="192|256|384|512|1024" id="yahooscale" default="384"/>
-</settings>
diff --git a/addons/metadata.yahoomusic.com/yahoomusic.xml b/addons/metadata.yahoomusic.com/yahoomusic.xml
deleted file mode 100644 (file)
index 9bd5a3f..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<scraper framework="1.0" date="2009-05-22">
-       <CreateSearchUrl dest="3">
-               <RegExp input="$$1" output="&lt;url&gt;http://us.music.yahooapis.com/video/v1/list/search/all/\1?appid=r6QWQGXV34H0Sl3Wq4vWJI2v9IO1XnZw5JkeifPbTq2p0S9H9kg0JUc3SVN0Yw--&amp;amp;response=artists,images&lt;/url&gt;" dest="3">
-                       <expression noclean="1"/>
-               </RegExp>
-       </CreateSearchUrl>
-       <GetSearchResults dest="8">
-               <RegExp input="$$5" output="&lt;?xml version=&quot;1.0&quot; encoding=&quot;iso-8859-1&quot; standalone=&quot;yes&quot;?&gt;&lt;results&gt;\1&lt;/results&gt;" dest="8">
-                       <RegExp input="$$1" output="&lt;entity&gt;&lt;title&gt;\4 - \1 (\2)&lt;/title&gt;&lt;url&gt;http://us.music.yahooapis.com/video/v1/item/\3?format=xml&amp;amp;appid=r6QWQGXV34H0Sl3Wq4vWJI2v9IO1XnZw5JkeifPbTq2p0S9H9kg0JUc3SVN0Yw--&lt;/url&gt;&lt;/entity&gt;" dest="5">
-                               <expression repeat="yes">&lt;Video.*?title=&quot;([^&quot;]*)&quot;.*?copyrightYear=&quot;([^&quot;]*)&quot;.*?\/([0-9]*)\?size.*?name=&quot;([^&quot;]*)&quot;.*?&lt;/Video&gt;</expression>
-                       </RegExp>
-                       <expression noclean="1"/>
-               </RegExp>               
-       </GetSearchResults>
-       <GetDetails dest="3">
-               <RegExp input="$$5" output="&lt;details&gt;\1&lt;/details&gt;" dest="3">
-                       <RegExp input="$$1" output="&lt;title&gt;\1&lt;/title&gt;" dest="5">
-                               <expression>&lt;Video.*?title=&quot;([^&quot;]*)&quot;</expression>
-                       </RegExp>
-                       <RegExp input="$$1" output="&lt;artist&gt;\1&lt;/artist&gt;" dest="5+">
-                               <expression repeat="yes">&lt;Artist.*?name=&quot;([^&quot;]*)&quot;</expression>
-                       </RegExp>
-                       <RegExp input="$$1" output="&lt;album&gt;\1&lt;/album&gt;" dest="5+">
-                               <expression>&lt;Release.*?title=&quot;([^&quot;]*)&quot;</expression>
-                       </RegExp>
-                       <RegExp input="$$1" output="&lt;studio&gt;\1&lt;/studio&gt;" dest="5+">
-                               <expression repeat="yes">label=&quot;([^&quot;]*)&quot;</expression>
-                       </RegExp>
-                       <RegExp input="$$1" output="&lt;year&gt;\1&lt;/year&gt;" dest="5+">
-                               <expression>copyrightYear=&quot;([0-9]*)&quot;</expression>
-                       </RegExp>
-                       <RegExp input="$$1" output="&lt;genre&gt;\1&lt;/genre&gt;" dest="5+">
-                               <expression repeat="yes">&lt;Category.*?name=&quot;([^&quot;]*)&quot; rating=&quot;([^&quot;]*)&quot; type=&quot;Genre&quot;&gt;</expression>
-                       </RegExp>
-                       <RegExp input="$$1" output="&lt;thumb&gt;http://d.yimg.com/img.music.yahoo.com/image/v1/video/\1?size=$INFO[yahooscale]&lt;/thumb&gt;" dest="5+">
-                               <expression>\/([0-9]*)\?size</expression>
-                       </RegExp>
-                       <expression noclean="1"/>
-               </RegExp>
-       </GetDetails>
-</scraper>
index 1218736..025feb4 100644 (file)
@@ -27,6 +27,7 @@
                        <posy>0</posy>
                        <width>1280</width>
                        <height>720</height>
+                       <aspectratio>scale</aspectratio>
                        <texture background="true">$INFO[ListItem.Property(Fanart_Image)]</texture>
                        <include>backgroundfade</include>
                        <fadetime>FanartCrossfadeTime</fadetime>
index 1cb6cb4..730b98e 100755 (executable)
@@ -381,6 +381,12 @@ AC_ARG_ENABLE([asap-codec],
   [use_asap=$enableval],
   [use_asap=no])
 
+AC_ARG_ENABLE([mysql],
+  [AS_HELP_STRING([--disable-mysql],
+  [disable mysql])],
+  [use_mysql=$enableval],
+  [use_mysql=yes])
+
 AC_ARG_ENABLE([webserver],
   [AS_HELP_STRING([--disable-webserver],
   [disable webserver])],
@@ -731,14 +737,17 @@ else
 fi
 
 # platform common libraries
-AC_CHECK_PROG(MYSQL_CONFIG, mysql_config, "yes", "no")
-if test $MYSQL_CONFIG = "yes"; then
-  INCLUDES="$INCLUDES `mysql_config --include`"
-  MYSQL_LIBS=`mysql_config --libs`
-  LIBS="$LIBS $MYSQL_LIBS"
-  AC_SUBST(MYSQL_LIBS)
-else
-  AC_MSG_ERROR($missing_program)
+if test "$use_mysql" = "yes"; then
+  AC_CHECK_PROG(MYSQL_CONFIG, mysql_config, "yes", "no")
+  if test $MYSQL_CONFIG = "yes"; then
+    AC_DEFINE([HAVE_MYSQL],[1],["Define to 1 if you have the `mysql' library (-lmysqlclient)."])
+    INCLUDES="$INCLUDES `mysql_config --include`"
+    MYSQL_LIBS=`mysql_config --libs`
+    LIBS="$LIBS $MYSQL_LIBS"
+    AC_SUBST(MYSQL_LIBS)
+  else
+    AC_MSG_ERROR($missing_program)
+  fi
 fi
 AC_CHECK_HEADER([ass/ass.h],, AC_MSG_ERROR($missing_library))
 AC_CHECK_HEADER([mpeg2dec/mpeg2.h],, AC_MSG_ERROR($missing_library))
@@ -777,7 +786,9 @@ AC_CHECK_LIB([lzo2],        [main],, AC_MSG_ERROR($missing_library))
 AC_CHECK_LIB([z],           [main],, AC_MSG_ERROR($missing_library))
 AC_CHECK_LIB([crypto],      [main],, AC_MSG_ERROR($missing_library))
 AC_CHECK_LIB([ssl],         [main],, AC_MSG_ERROR($missing_library))
-AC_CHECK_LIB([mysqlclient], [main],, AC_MSG_ERROR($missing_library))
+if test "$use_mysql" = "yes"; then
+  AC_CHECK_LIB([mysqlclient], [main],, AC_MSG_ERROR($missing_library))
+fi
 AC_CHECK_LIB([ssh],         [sftp_tell64],, AC_MSG_RESULT([Could not find suitable version of libssh]))
 AC_CHECK_LIB([bluetooth],   [hci_devid],, AC_MSG_RESULT([Could not find suitable version of libbluetooth]))
 AC_CHECK_LIB([yajl],        [main],, AC_MSG_ERROR($missing_library))
@@ -1878,6 +1889,13 @@ else
   final_message="$final_message\n  ASAP Codec:\tNo"
 fi
 
+if test "$use_mysql" = "yes"; then
+  final_message="$final_message\n  MySQL:\tYes"
+  USE_MYSQL=1
+else
+  final_message="$final_message\n  MySQL:\tNo"
+  USE_MYSQL=0
+fi
 if test "$use_webserver" = "yes"; then
   final_message="$final_message\n  Webserver:\tYes"
   USE_WEB_SERVER=1
@@ -2105,6 +2123,7 @@ AC_SUBST(USE_AIRTUNES)
 AC_SUBST(USE_LIBUDEV)
 AC_SUBST(USE_LIBUSB)
 AC_SUBST(USE_LIBCEC)
+AC_SUBST(USE_MYSQL)
 AC_SUBST(USE_WEB_SERVER)
 
 
index 8219f01..f0527a2 100644 (file)
@@ -2784,7 +2784,21 @@ msgctxt "#798"
 msgid "Internet access"
 msgstr ""
 
-#empty strings from id 799 to 849
+msgctxt "#799"
+msgid "Library Update"
+msgstr ""
+
+#: xbmc/music/windows/GUIWindowMusicBase.cpp
+msgctxt "#800"
+msgid "Music library needs to rescan art from tags"
+msgstr ""
+
+#: xbmc/music/windows/GUIWindowMusicBase.cpp
+msgctxt "#801"
+msgid "Would you like to scan now?"
+msgstr ""
+
+#empty strings from id 802 to 849
 
 msgctxt "#850"
 msgid "Invalid port number entered"
@@ -7427,8 +7441,32 @@ msgctxt "#20458"
 msgid "Group movies in sets"
 msgstr ""
 
+msgctxt "#20459"
+msgid "Tags"
+msgstr ""
+
+msgctxt "#20460"
+msgid "Add %s"
+msgstr ""
+
+msgctxt "#20461"
+msgid "Remove %s"
+msgstr ""
+
+msgctxt "#20462"
+msgid "New tag..."
+msgstr ""
+
+msgctxt "#20463"
+msgid "A tag with the name '%s' already exists."
+msgstr ""
+
+msgctxt "#20464"
+msgid "Select %s"
+msgstr ""
+
 #up to 21329 is reserved for the video db !! !
-#empty strings from id 20459 to 21329
+#empty strings from id 20465 to 21329
 
 msgctxt "#21330"
 msgid "Show hidden files and directories"
@@ -7683,9 +7721,7 @@ msgctxt "#21415"
 msgid "Default music video scraper"
 msgstr ""
 
-msgctxt "#21416"
-msgid "Enable fallback based on scraper language"
-msgstr ""
+#empty string id 21416
 
 msgctxt "#21417"
 msgid "- Settings"
@@ -9304,7 +9340,13 @@ msgctxt "#35009"
 msgid "Do not use the custom keymap for this device"
 msgstr ""
 
-#empty strings from id 35010 to 35499
+#empty strings from id 35010 to 35099
+
+msgctxt "#35100"
+msgid "Enable joystick and gamepad support"
+msgstr ""
+
+#empty strings from id 35101 to 35499
 
 msgctxt "#35500"
 msgid "Location"
index 4f16521..4467f23 100644 (file)
@@ -50,7 +50,7 @@ typedef char my_bool;
 #define __WIN__
 #endif
 #ifdef __WIN__
-#include <winsock.h>                           /* For windows */
+#include <winsock2.h>                          /* For windows */
 #endif
 #if !defined(__WIN__)
 #define STDCALL
index 7ea4356..599bc4b 100644 (file)
@@ -91,7 +91,7 @@ EXPORTS
        cmyth_get_bookmark_mark
        cmyth_get_bookmark_offset
        cmyth_mysql_get_commbreak_list
-       cmyth_mythtv_remove_previos_recorded
+       cmyth_mythtv_remove_previous_recorded
        cmyth_mysql_testdb_connection
        cmyth_chanlist_create
        cmyth_chanlist_get_item
@@ -137,7 +137,7 @@ EXPORTS
        cmyth_proginfo_host
        cmyth_proginfo_card_id
        cmyth_proginfo_recgroup
-       cmyth_proginfo_prodyear
+       cmyth_proginfo_year
        cmyth_get_delete_list
        cmyth_proglist_create
        cmyth_proglist_get_item
@@ -215,4 +215,9 @@ EXPORTS
        cmyth_ringbuf_read
        cmyth_file_read
        cmyth_livetv_read
-       cmyth_get_cutlist
\ No newline at end of file
+       cmyth_get_cutlist
+       cmyth_tuner_type_check
+       cmyth_update_bookmark_setting
+       cmyth_proginfo_port
+       cmyth_proginfo_season
+       cmyth_proginfo_episode
\ No newline at end of file
index a698d8a..f2bd329 100644 (file)
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
       <PrecompiledHeader>
       </PrecompiledHeader>
-      <ProgramDataBaseFileName>$(OutDir)libcmythd.pdb</ProgramDataBaseFileName>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <CompileAs>CompileAsC</CompileAs>
     </ClCompile>
     <Link>
       <AdditionalDependencies>ws2_32.lib;mysqlclient.lib;%(AdditionalDependencies)</AdditionalDependencies>
       </PrecompiledHeader>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <CompileAs>CompileAsC</CompileAs>
       <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
     </ClCompile>
     <Link>
index d8cb364..fae6889 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2004-2006, Eric Lund, Jon Gettler
+ *  Copyright (C) 2004-2012, Eric Lund, Jon Gettler
  *  http://www.mvpmc.org/
  *
  *  This library is free software; you can redistribute it and/or
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+/*! \mainpage cmyth
+ *
+ * cmyth is a library that provides a C language API to access and control
+ * a MythTV backend.
+ *
+ * \section projectweb Project website
+ * http://www.mvpmc.org/
+ *
+ * \section repos Source repositories
+ * http://git.mvpmc.org/
+ *
+ * \section libraries Libraries
+ * \li \link cmyth.h libcmyth \endlink
+ * \li \link refmem.h librefmem \endlink
+ */
+
 /** \file cmyth.h
  * A C library for communicating with a MythTV server.
  */
@@ -65,12 +81,12 @@ typedef enum {
        CHANNEL_DIRECTION_UP = 0,
        CHANNEL_DIRECTION_DOWN = 1,
        CHANNEL_DIRECTION_FAVORITE = 2,
-       CHANNEL_DIRECTION_SAME = 4
+       CHANNEL_DIRECTION_SAME = 4,
 } cmyth_channeldir_t;
 
 typedef enum {
        ADJ_DIRECTION_UP = 1,
-       ADJ_DIRECTION_DOWN = 0
+       ADJ_DIRECTION_DOWN = 0,
 } cmyth_adjdir_t;
 
 typedef enum {
@@ -79,13 +95,13 @@ typedef enum {
        BROWSE_DIRECTION_DOWN = 2,
        BROWSE_DIRECTION_LEFT = 3,
        BROWSE_DIRECTION_RIGHT = 4,
-       BROWSE_DIRECTION_FAVORITE = 5
+       BROWSE_DIRECTION_FAVORITE = 5,
 } cmyth_browsedir_t;
 
 typedef enum {
        WHENCE_SET = 0,
        WHENCE_CUR = 1,
-       WHENCE_END = 2
+       WHENCE_END = 2,
 } cmyth_whence_t;
 
 typedef enum {
@@ -105,13 +121,13 @@ typedef enum {
        CMYTH_EVENT_SYSTEM_EVENT,
        CMYTH_EVENT_UPDATE_FILE_SIZE,
        CMYTH_EVENT_GENERATED_PIXMAP,
-       CMYTH_EVENT_CLEAR_SETTINGS_CACHE
+       CMYTH_EVENT_CLEAR_SETTINGS_CACHE,
 } cmyth_event_t;
 
 #define CMYTH_NUM_SORTS 2
 typedef enum {
        MYTHTV_SORT_DATE_RECORDED = 0,
-       MYTHTV_SORT_ORIGINAL_AIRDATE
+       MYTHTV_SORT_ORIGINAL_AIRDATE,
 } cmyth_proglist_sort_t;
 
 struct cmyth_timestamp;
@@ -198,7 +214,7 @@ extern void cmyth_dbg_none(void);
 extern void cmyth_dbg(int level, char *fmt, ...);
 
 /**
- * Define a callback to use to send messages rather than using stderr
+ * Define a callback to use to send messages rather than using stdout
  * \param msgcb function pointer to pass a string to
  */
 extern void cmyth_set_dbg_msgcallback(void (*msgcb)(int level,char *));
@@ -234,7 +250,7 @@ extern cmyth_conn_t cmyth_conn_connect_event(char *server,
                                             unsigned buflen, int tcp_rcvbuf);
 
 /**
- * Create a file connection to a backend.
+ * Create a file connection to a backend for reading a recording.
  * \param prog program handle
  * \param control control handle
  * \param buflen buffer size for the connection to use
@@ -364,6 +380,11 @@ extern char * cmyth_conn_get_setting(cmyth_conn_t conn,
  */
 extern cmyth_event_t cmyth_event_get(cmyth_conn_t conn, char * data, int len);
 
+/**
+ * Selects on the event socket, waiting for an event to show up.
+ * allows nonblocking access to events.
+ * \return <= 0 on failure
+ */
 extern int cmyth_event_select(cmyth_conn_t conn, struct timeval *timeout);
 
 /*
@@ -558,6 +579,7 @@ extern int cmyth_livetv_read(cmyth_recorder_t rec,
 extern int cmyth_livetv_keep_recording(cmyth_recorder_t rec, cmyth_database_t db, int keep);
 
 extern int mythtv_new_livetv(void);
+extern int cmyth_tuner_type_check(cmyth_database_t db, cmyth_recorder_t rec, int check_tuner_enabled);
 
 /*
  * -----------------------------------------------------------------
@@ -685,7 +707,7 @@ typedef enum {
        RS_LATER_SHOWING = 8,
        RS_REPEAT = 9,
        RS_LOW_DISKSPACE = 11,
-       RS_TUNER_BUSY = 12
+       RS_TUNER_BUSY = 12,
 } cmyth_proginfo_rec_status_t;
 
 /**
@@ -883,6 +905,8 @@ extern long long cmyth_proginfo_length(cmyth_proginfo_t prog);
  */
 extern char *cmyth_proginfo_host(cmyth_proginfo_t prog);
 
+extern int cmyth_proginfo_port(cmyth_proginfo_t prog);
+
 /**
  * Determine if two proginfo handles refer to the same program.
  * \param a proginfo handle a
@@ -941,9 +965,9 @@ extern char *cmyth_proginfo_chanicon(cmyth_proginfo_t prog);
 /**
  * Retrieve the production year for this program info
  * \param prog proginfo handle
- * \return null-terminated string
+ * \return production year
  */
-extern char *cmyth_proginfo_prodyear(cmyth_proginfo_t prog);
+extern unsigned short cmyth_proginfo_year(cmyth_proginfo_t prog);
 
 /*
  * -----------------------------------------------------------------
@@ -1032,8 +1056,9 @@ extern cmyth_freespace_t cmyth_freespace_create(void);
  * -------
  */
 extern long long cmyth_get_bookmark(cmyth_conn_t conn, cmyth_proginfo_t prog);
-extern int cmyth_get_bookmark_offset(cmyth_database_t db, long chanid, long long mark);
-extern int cmyth_get_bookmark_mark(cmyth_database_t, cmyth_proginfo_t, long long);
+extern int cmyth_get_bookmark_offset(cmyth_database_t db, long chanid, long long mark, char *starttime, int mode);
+extern int cmyth_update_bookmark_setting(cmyth_database_t, cmyth_proginfo_t);
+extern long long cmyth_get_bookmark_mark(cmyth_database_t, cmyth_proginfo_t, long long, int);
 extern int cmyth_set_bookmark(cmyth_conn_t conn, cmyth_proginfo_t prog,
        long long bookmark);
 extern cmyth_commbreaklist_t cmyth_commbreaklist_create(void);
@@ -1094,7 +1119,7 @@ extern int cmyth_get_delete_list(cmyth_conn_t, char *, cmyth_proglist_t);
 
 #define PROGRAM_ADJUST  3600
 
-extern int cmyth_mythtv_remove_previos_recorded(cmyth_database_t db,char *query);
+extern int cmyth_mythtv_remove_previous_recorded(cmyth_database_t db,char *query);
 
 extern cmyth_chanlist_t cmyth_mysql_get_chanlist(cmyth_database_t db);
 #endif /* __CMYTH_H */
index 72c863a..6a868bf 100644 (file)
@@ -1,28 +1,29 @@
-/** \file mvp_debug.h
+/** \file debug.h
  * A C library for generating and controlling debug output
  */
 
-#ifndef __MVP_DEBUG_H
-#define  __MVP_DEBUG_H
+#ifndef __CMYTH_DEBUG_H
+#define  __CMYTH_DEBUG_H
 
 #include <stdio.h>
 #include <stdarg.h>
+#include <string.h>
 
 typedef struct {
        char *name;
        int  cur_level;
        int  (*selector)(int plevel, int slevel);
        void (*msg_callback)(int level, char *msg);
-} mvp_debug_ctx_t;
+} cmyth_debug_ctx_t;
 
 /**
- * Make a static initializer for an mvp_debug_ctx_t which provides a debug
+ * Make a static initializer for an cmyth_debug_ctx_t which provides a debug
  * context for a subsystem.  This is a macro.
  * \param n subsystem name (a static string is fine)
  * \param l initial debug level for the subsystem
  * \param s custom selector function pointer (NULL is okay)
  */
-#define MVP_DEBUG_CTX_INIT(n,l,s) { n, l, s, NULL }
+#define CMYTH_DEBUG_CTX_INIT(n,l,s) { n, l, s, NULL }
 
 /**
  * Set the debug level to be used for the subsystem
@@ -31,7 +32,7 @@ typedef struct {
  * \return an integer subsystem id used for future interaction
  */
 static inline void
-mvp_dbg_setlevel(mvp_debug_ctx_t *ctx, int level)
+__cmyth_dbg_setlevel(cmyth_debug_ctx_t *ctx, int level)
 {
        if (ctx != NULL) {
                ctx->cur_level = level;
@@ -46,7 +47,7 @@ mvp_dbg_setlevel(mvp_debug_ctx_t *ctx, int level)
  * \param ... arguments to the format
  */
 static inline void
-mvp_dbg(mvp_debug_ctx_t *ctx, int level, char *fmt, va_list ap)
+__cmyth_dbg(cmyth_debug_ctx_t *ctx, int level, char *fmt, va_list ap)
 {
        char msg[4096];
        int len;
@@ -65,4 +66,4 @@ mvp_dbg(mvp_debug_ctx_t *ctx, int level, char *fmt, va_list ap)
        }
 }
 
-#endif /*  __MVP_DEBUG_H */
+#endif /*  __CMYTH_DEBUG_H */
index 71d9a6e..5c107f5 100644 (file)
@@ -1,3 +1,22 @@
+/*
+ *  Copyright (C) 2004-2008, Eric Lund, Jon Gettler
+ *  http://www.mvpmc.org/
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
 #ifndef __MVP_ATOMIC_H
 #define __MVP_ATOMIC_H
 
index 7866469..cc8155c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2004-2006, Eric Lund, Jon Gettler
+ *  Copyright (C) 2004-2012, Eric Lund, Jon Gettler
  *  http://www.mvpmc.org/
  *
  *  This library is free software; you can redistribute it and/or
index 4681c21..4352969 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2005-2006, Jon Gettler
+ *  Copyright (C) 2005-2009, Jon Gettler
  *  http://www.mvpmc.org/
  *
  *  This library is free software; you can redistribute it and/or
@@ -32,7 +32,7 @@ long long cmyth_get_bookmark(cmyth_conn_t conn, cmyth_proginfo_t prog)
        int err;
        long long ret;
        int count;
-       long long ll;
+       int64_t ll;
        int r;
        char start_ts_dt[CMYTH_TIMESTAMP_LEN + 1];
        cmyth_datetime_to_string(start_ts_dt, prog->proginfo_rec_start_ts);
@@ -58,9 +58,9 @@ long long cmyth_get_bookmark(cmyth_conn_t conn, cmyth_proginfo_t prog)
                ret = count;
                goto out;
        }
-       if ((r=cmyth_rcv_long_long(conn, &err, &ll, count)) < 0) {
+       if ((r=cmyth_rcv_int64(conn, &err, &ll, count)) < 0) {
                cmyth_dbg(CMYTH_DBG_ERROR,
-                       "%s: cmyth_rcv_long_long() failed (%d)\n",
+                       "%s: cmyth_rcv_int64() failed (%d)\n",
                        __FUNCTION__, r);
                ret = err;
                goto out;
index f7b85fb..a7e5359 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2004-2006, Eric Lund, Jon Gettler
+ *  Copyright (C) 2004-2012, Eric Lund, Jon Gettler
  *  http://www.mvpmc.org/
  *
  *  This library is free software; you can redistribute it and/or
 #ifndef __CMYTH_LOCAL_H
 #define __CMYTH_LOCAL_H
 
-#ifdef _MSC_VER
 #include <stdio.h>
-#include <malloc.h>
-#else
-#include <unistd.h>
+#include <stdlib.h>
+#if !defined(_MSC_VER)
+#include <sys/time.h>
 #endif
 #include <refmem/refmem.h>
 #include <cmyth/cmyth.h>
 #include <time.h>
-#include <mysql/mysql.h>
 #include <stdint.h>
+#include <mysql/mysql.h>
 
-#ifdef _MSC_VER
-#pragma warning(disable:4267)
-#define pthread_mutex_lock(a)
-#define pthread_mutex_unlock(a)
-#define PTHREAD_MUTEX_INITIALIZER NULL;
-typedef void* pthread_mutex_t;
-extern pthread_mutex_t mutex;
-#define mutex __cmyth_mutex
-#define SHUT_RDWR SD_BOTH
-typedef SOCKET cmyth_socket_t;
-typedef int socklen_t;
-#define snprintf _snprintf
-#define sleep(a) Sleep(a*1000)
-#define usleep(a) Sleep(a/1000)
-static inline struct tm* localtime_r (const time_t *clock, struct tm *result) { 
-       struct tm* data;
-  if (!clock || !result) return NULL;
-  data = localtime(clock);
-  if (!data) return NULL;
-       memcpy(result,data,sizeof(*result)); 
-       return result; 
-}
-static inline __int64 atoll(const char* s)
-{
-  __int64 value;
-  if(sscanf(s,"%I64d", &value))
-    return value;
-  else
-    return 0;
-}
-
+#if defined(_MSC_VER)
+#include "cmyth_msc.h"
 #else
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
 #include <pthread.h>
+
+typedef int cmyth_socket_t;
+#define closesocket(fd) close(fd)
+#endif /* _MSC_VER */
+
 #define mutex __cmyth_mutex
 extern pthread_mutex_t mutex;
-#define closesocket(fd) close(fd)
-typedef int cmyth_socket_t;
-#endif
+
 /*
  * Some useful constants
  */
@@ -170,10 +150,10 @@ struct cmyth_file {
        long file_id;                   /**< file identifier */
        /** callback when close is completed */
        void (*closed_callback)(cmyth_file_t file);
-       unsigned long long file_start;  /**< file start offest */
-       unsigned long long file_length; /**< file length */
-       unsigned long long file_pos;    /**< current file position */
-       unsigned long long file_req;    /**< current file position requested */
+       uint64_t file_start;    /**< file start offest */
+       uint64_t file_length;   /**< file length */
+       uint64_t file_pos;      /**< current file position */
+       uint64_t file_req;      /**< current file position requested */
        cmyth_conn_t file_control;      /**< master backend connection */
 };
 
@@ -181,10 +161,10 @@ struct cmyth_ringbuf {
        cmyth_conn_t conn_data;
        long file_id;
        char *ringbuf_url;
-       unsigned long long ringbuf_size;
-       unsigned long long file_length;
-       unsigned long long file_pos;
-       unsigned long long ringbuf_fill;
+       uint64_t ringbuf_size;
+       uint64_t file_length;
+       uint64_t file_pos;
+       uint64_t ringbuf_fill;
        char *ringbuf_hostname;
        int ringbuf_port;
 };
@@ -197,7 +177,7 @@ struct cmyth_rec_num {
 
 struct cmyth_keyframe {
        unsigned long keyframe_number;
-       unsigned long long keyframe_pos;
+       uint64_t keyframe_pos;
 };
 
 struct cmyth_posmap {
@@ -206,8 +186,8 @@ struct cmyth_posmap {
 };
 
 struct cmyth_freespace {
-       unsigned long long freespace_total;
-       unsigned long long freespace_used;
+       uint64_t freespace_total;
+       uint64_t freespace_used;
 };
 
 struct cmyth_timestamp {
@@ -233,7 +213,7 @@ struct cmyth_proginfo {
        char *proginfo_channame;  /* Deprecated in V8, simulated for compat. */
        char *proginfo_chanicon;  /* New in V8 */
        char *proginfo_url;
-       long long proginfo_Length;
+       int64_t proginfo_Length;
        cmyth_timestamp_t proginfo_start_ts;
        cmyth_timestamp_t proginfo_end_ts;
        unsigned long proginfo_conflicting; /* Deprecated in V8, always 0 */
@@ -276,7 +256,7 @@ struct cmyth_proginfo {
        unsigned long proginfo_audioproperties; /* new in v35 */
        unsigned long proginfo_videoproperties; /* new in v35 */
        unsigned long proginfo_subtitletype; /* new in v35 */
-       char *proginfo_prodyear; /* new in v41 */
+       unsigned short proginfo_year; /* new in v43 */
 };
 
 struct cmyth_proglist {
@@ -315,14 +295,27 @@ extern int cmyth_rcv_short(cmyth_conn_t conn, int *err, short *buf, int count);
 extern int cmyth_rcv_long(cmyth_conn_t conn, int *err, long *buf, int count);
 #define cmyth_rcv_u_long(c, e, b, n) cmyth_rcv_long(c, e, (long*)b, n)
 
-#define cmyth_rcv_long_long __cmyth_rcv_long_long
-extern int cmyth_rcv_long_long(cmyth_conn_t conn, int *err, long long *buf,
+#define cmyth_rcv_old_int64 __cmyth_rcv_old_int64
+extern int cmyth_rcv_old_int64(cmyth_conn_t conn, int *err, int64_t *buf,
                               int count);
-#define cmyth_rcv_u_long_long(c, e, b, n) cmyth_rcv_long_long(c, e, (long long*)b, n)
 
-#define cmyth_rcv_int64 __cmyth_rcv_int64
-extern int cmyth_rcv_int64(cmyth_conn_t conn, int *err, long long *buf,
-                              int count);
+#define cmyth_rcv_new_int64 __cmyth_rcv_new_int64
+extern int cmyth_rcv_new_int64(cmyth_conn_t conn, int *err, int64_t *buf,
+                              int count, int forced);
+
+#define cmyth_rcv_old_uint64 __cmyth_rcv_old_uint64
+extern int cmyth_rcv_old_uint64(cmyth_conn_t conn, int *err, uint64_t *buf,
+                               int count);
+
+#define cmyth_rcv_new_uint64 __cmyth_rcv_new_uint64
+extern int cmyth_rcv_new_uint64(cmyth_conn_t conn, int *err, uint64_t *buf,
+                               int count, int forced);
+
+#define cmyth_rcv_int64(conn, err, buf, count) \
+       cmyth_rcv_new_int64(conn, err, buf, count, 0)
+
+#define cmyth_rcv_uint64(conn, err, buf, count)        \
+       cmyth_rcv_new_uint64(conn, err, buf, count, 0)
 
 #define cmyth_rcv_ubyte __cmyth_rcv_ubyte
 extern int cmyth_rcv_ubyte(cmyth_conn_t conn, int *err, unsigned char *buf,
diff --git a/lib/cmyth/libcmyth/cmyth_msc.h b/lib/cmyth/libcmyth/cmyth_msc.h
new file mode 100644 (file)
index 0000000..78e0c92
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ *  Copyright (C) 2012, Jon Gettler
+ *  http://www.mvpmc.org/
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/**
+ * \file cmyth_msc.h
+ * Contain most of the Microsoft related differences in a single file.
+ */
+
+#ifndef __CMYTH_MSC_H
+#define __CMYTH_MSC_H
+
+#if !defined(_MSC_VER)
+#error This file may only be included on windows builds!
+#endif /* !_MSC_VER */
+
+#include <malloc.h>
+#include <winsock2.h>
+#include <Ws2tcpip.h>
+
+#pragma warning(disable:4267)
+#pragma warning(disable:4996)
+
+#define pthread_mutex_lock(a)
+#define pthread_mutex_unlock(a)
+#define PTHREAD_MUTEX_INITIALIZER NULL;
+typedef void *pthread_mutex_t;
+
+#undef ECANCELED
+#undef ETIMEDOUT
+
+#define ECANCELED -1
+#define ETIMEDOUT -1
+#define SHUT_RDWR SD_BOTH
+
+typedef SOCKET cmyth_socket_t;
+typedef int socklen_t;
+
+#define snprintf _snprintf
+#define sleep(a) Sleep(a*1000)
+#define usleep(a) Sleep(a/1000)
+
+static inline struct tm *localtime_r(const time_t * clock, struct tm *result)
+{
+       struct tm *data;
+       if (!clock || !result)
+               return NULL;
+       data = localtime(clock);
+       if (!data)
+               return NULL;
+       memcpy(result, data, sizeof(*result));
+       return result;
+}
+
+static inline __int64 atoll(const char *s)
+{
+       __int64 value;
+       if (sscanf(s, "%I64d", &value))
+               return value;
+       else
+               return 0;
+}
+
+#endif /* __CMYTH_MSC_H */
index e66adf1..ad5391f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2005-2006, Jon Gettler
+ *  Copyright (C) 2005-2012, Jon Gettler
  *  http://www.mvpmc.org/
  *
  *  This library is free software; you can redistribute it and/or
@@ -190,14 +190,13 @@ int cmyth_rcv_commbreaklist(cmyth_conn_t conn, int *err,
        int consumed;
        int total = 0;
        long rows;
-       long long mark;
+       int64_t mark;
        long long start = -1;
        char *failed = NULL;
        cmyth_commbreak_t commbreak;
        unsigned short type;
        unsigned short start_type;
        int i;
-       int j;
 
        if (count <= 0) {
                *err = EINVAL;
@@ -230,7 +229,7 @@ int cmyth_rcv_commbreaklist(cmyth_conn_t conn, int *err,
                        goto fail;
                }
 
-               consumed = cmyth_rcv_long_long(conn, err, &mark, count);
+               consumed = cmyth_rcv_int64(conn, err, &mark, count);
                count -= consumed;
                total += consumed;
                if (*err) {
@@ -242,8 +241,8 @@ int cmyth_rcv_commbreaklist(cmyth_conn_t conn, int *err,
                        start_type = type;
                } else if (type == CMYTH_COMMBREAK_END || type == CMYTH_CUTLIST_END) {
                        if (start >= 0 &&
-                          (type == CMYTH_COMMBREAK_END && start_type == CMYTH_COMMBREAK_START
-                           || type == CMYTH_CUTLIST_END && start_type == CMYTH_CUTLIST_START))
+                           ((type == CMYTH_COMMBREAK_END && start_type == CMYTH_COMMBREAK_START)
+                            || (type == CMYTH_CUTLIST_END && start_type == CMYTH_CUTLIST_START)))
                        {
                                commbreak = cmyth_commbreak_create();
                                commbreak->start_mark = start;
@@ -295,7 +294,11 @@ cmyth_mysql_get_commbreaklist(cmyth_database_t db, cmyth_conn_t conn, cmyth_prog
        }
 
        fprintf(stderr, "Found %li commercial breaks for current program.\n", breaklist->commbreak_count);
-
+       if (r != breaklist->commbreak_count) {
+               fprintf(stderr, "commbreak error.  Setting number of commercial breaks to zero\n");
+               cmyth_dbg(CMYTH_DBG_ERROR, "%s  - returned rows=%d commbreak_count=%li\n",__FUNCTION__, r,breaklist->commbreak_count);
+               breaklist->commbreak_count = 0;
+       }
        out:
        pthread_mutex_unlock(&mutex);
        return breaklist;
index a577275..16fe074 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2004-2006, Eric Lund, Jon Gettler
+ *  Copyright (C) 2004-2012, Eric Lund, Jon Gettler
  *  http://www.mvpmc.org/
  *
  *  This library is free software; you can redistribute it and/or
  * interacting with those connections.  
  */
 
-#include <sys/types.h>
 #include <stdlib.h>
-#ifndef _MSC_VER
-#include <unistd.h>
-#endif
 #include <stdio.h>
-#ifdef _MSC_VER
-#include <winsock2.h>
-#include <Ws2tcpip.h>
-#else
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-#endif
 #include <errno.h>
 #include <string.h>
 #include <signal.h>
@@ -48,7 +35,7 @@ static char * cmyth_conn_get_setting_unlocked(cmyth_conn_t conn, const char* hos
 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
 
 typedef struct {
-       int version;
+       unsigned int version;
        char token[9]; // 8 characters + the terminating NULL character
 } myth_protomap_t;
 
@@ -65,7 +52,7 @@ static myth_protomap_t protomap[] = {
        {71, "05e82186"},
        {72, "D78EFD6F"},
        {73, "D7FE8D6F"},
-       {0, 0}
+       {0, ""}
 };
 
 /*
@@ -564,6 +551,10 @@ cmyth_conn_connect_file(cmyth_proginfo_t prog,  cmyth_conn_t control,
        if (control->conn_version >= 17) {
                myth_host = cmyth_conn_get_setting_unlocked(control, prog->proginfo_host,
                                                   "BackendServerIP");
+               if (myth_host && (strcmp(myth_host, "-1") == 0)) {
+                       ref_release(myth_host);
+                       myth_host = NULL;
+               }
        }
        if (!myth_host) {
                cmyth_dbg(CMYTH_DBG_PROTO,
@@ -643,14 +634,18 @@ cmyth_conn_connect_file(cmyth_proginfo_t prog,  cmyth_conn_t control,
                goto shut;
        }
        count -= r;
-       r = cmyth_rcv_u_long_long(conn, &err, &ret->file_length, count);
+       r = cmyth_rcv_uint64(conn, &err, &ret->file_length, count);
        if (err) {
                cmyth_dbg(CMYTH_DBG_ERROR,
-                         "%s: (length) cmyth_rcv_u_long_long() failed (%d)\n",
+                         "%s: (length) cmyth_rcv_uint64() failed (%d)\n",
                          __FUNCTION__, err);
                goto shut;
        }
        count -= r;
+       if (count != 0) {
+               cmyth_dbg(CMYTH_DBG_ERROR, "%s: %d leftover bytes\n",
+                         __FUNCTION__, count);
+       }
        free(announcement);
        ref_release(conn);
        ref_release(myth_host);
@@ -789,10 +784,10 @@ cmyth_conn_connect_path(char* path, cmyth_conn_t control,
                goto shut;
        }
        count -= r;
-       r = cmyth_rcv_u_long_long(conn, &err, &ret->file_length, count);
+       r = cmyth_rcv_uint64(conn, &err, &ret->file_length, count);
        if (err) {
                cmyth_dbg(CMYTH_DBG_ERROR,
-                         "%s: (length) cmyth_rcv_u_long_long() failed (%d)\n",
+                         "%s: (length) cmyth_rcv_uint64() failed (%d)\n",
                          __FUNCTION__, err);
                goto shut;
        }
@@ -949,7 +944,7 @@ int
 cmyth_conn_check_block(cmyth_conn_t conn, unsigned long size)
 {
        fd_set check;
-       struct timeval timeout = {0,0};
+       struct timeval timeout;
        int length;
        int err = 0;
        unsigned long sent;
@@ -957,6 +952,7 @@ cmyth_conn_check_block(cmyth_conn_t conn, unsigned long size)
        if (!conn) {
                return -EINVAL;
        }
+       timeout.tv_sec = timeout.tv_usec = 0;
        FD_ZERO(&check);
        FD_SET(conn->conn_fd, &check);
        if (select((int)conn->conn_fd + 1, &check, NULL, NULL, &timeout) < 0) {
@@ -1201,7 +1197,7 @@ cmyth_conn_get_freespace(cmyth_conn_t control,
        int r;
        char msg[256];
        char reply[256];
-       long long lreply;
+       int64_t lreply;
 
        if (control == NULL)
                return -EINVAL;
@@ -1235,19 +1231,17 @@ cmyth_conn_get_freespace(cmyth_conn_t control,
        }
        
        if (control->conn_version >= 17) {
-               if ((r=cmyth_rcv_long_long(control, &err, &lreply,
-                                          count)) < 0) {
+               if ((r=cmyth_rcv_int64(control, &err, &lreply, count)) < 0) {
                        cmyth_dbg(CMYTH_DBG_ERROR,
-                                 "%s: cmyth_rcv_long_long() failed (%d)\n",
+                                 "%s: cmyth_rcv_int64() failed (%d)\n",
                                  __FUNCTION__, err);
                        ret = err;
                        goto out;
                }
                *total = lreply;
-               if ((r=cmyth_rcv_long_long(control, &err, &lreply,
-                                          count-r)) < 0) {
+               if ((r=cmyth_rcv_int64(control, &err, &lreply, count - r)) < 0) {
                        cmyth_dbg(CMYTH_DBG_ERROR,
-                                 "%s: cmyth_rcv_long_long() failed (%d)\n",
+                                 "%s: cmyth_rcv_int64() failed (%d)\n",
                                  __FUNCTION__, err);
                        ret = err;
                        goto out;
@@ -1356,18 +1350,6 @@ cmyth_conn_get_free_recorder_count(cmyth_conn_t conn)
        return ret;
 }
 
-char *
-cmyth_conn_get_setting(cmyth_conn_t conn, const char* hostname, const char* setting)
-{
-       char* result = NULL;
-
-       pthread_mutex_lock(&mutex);
-       result = cmyth_conn_get_setting_unlocked(conn, hostname, setting);
-       pthread_mutex_unlock(&mutex);
-
-       return result;
-}
-
 static char *
 cmyth_conn_get_setting_unlocked(cmyth_conn_t conn, const char* hostname, const char* setting)
 {
@@ -1427,3 +1409,14 @@ err:
        return NULL;
 }
 
+char *
+cmyth_conn_get_setting(cmyth_conn_t conn, const char* hostname, const char* setting)
+{
+       char* result = NULL;
+
+       pthread_mutex_lock(&mutex);
+       result = cmyth_conn_get_setting_unlocked(conn, hostname, setting);
+       pthread_mutex_unlock(&mutex);
+
+       return result;
+}
index 197801d..77b852c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2004-2006, Eric Lund
+ *  Copyright (C) 2004-2009, Eric Lund
  *  http://www.mvpmc.org/
  *
  *  This library is free software; you can redistribute it and/or
@@ -27,9 +27,9 @@
 
 #include "debug.h"
 
-static mvp_debug_ctx_t cmyth_debug_ctx = MVP_DEBUG_CTX_INIT("cmyth",
-                                                           CMYTH_DBG_NONE,
-                                                           NULL);
+static cmyth_debug_ctx_t cmyth_debug_ctx = CMYTH_DEBUG_CTX_INIT("cmyth",
+                                                               CMYTH_DBG_NONE,
+                                                               NULL);
 
 /*
  * cmyth_dbg_level(int l)
@@ -49,7 +49,7 @@ static mvp_debug_ctx_t cmyth_debug_ctx = MVP_DEBUG_CTX_INIT("cmyth",
 void
 cmyth_dbg_level(int l)
 {
-       mvp_dbg_setlevel(&cmyth_debug_ctx, l);
+       __cmyth_dbg_setlevel(&cmyth_debug_ctx, l);
 }
 
 /*
@@ -68,7 +68,7 @@ cmyth_dbg_level(int l)
 void
 cmyth_dbg_all()
 {
-       mvp_dbg_setlevel(&cmyth_debug_ctx, CMYTH_DBG_ALL);
+       __cmyth_dbg_setlevel(&cmyth_debug_ctx, CMYTH_DBG_ALL);
 }
 
 /*
@@ -87,7 +87,7 @@ cmyth_dbg_all()
 void
 cmyth_dbg_none()
 {
-       mvp_dbg_setlevel(&cmyth_debug_ctx, CMYTH_DBG_NONE);
+       __cmyth_dbg_setlevel(&cmyth_debug_ctx, CMYTH_DBG_NONE);
 }
 
 /*
@@ -111,7 +111,7 @@ cmyth_dbg(int level, char *fmt, ...)
        va_list ap;
 
        va_start(ap, fmt);
-       mvp_dbg(&cmyth_debug_ctx, level, fmt, ap);
+       __cmyth_dbg(&cmyth_debug_ctx, level, fmt, ap);
        va_end(ap);
 }
 
index f340ac6..2208c3e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2005-2006, Jon Gettler
+ *  Copyright (C) 2005-2012, Jon Gettler
  *  http://www.mvpmc.org/
  *
  *  This library is free software; you can redistribute it and/or
index 640f299..1939aa9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2004-2006, Eric Lund
+ *  Copyright (C) 2004-2012, Eric Lund
  *  http://www.mvpmc.org/
  *
  *  This library is free software; you can redistribute it and/or
@@ -21,9 +21,7 @@
 #include <stdlib.h>
 #include <errno.h>
 #include <inttypes.h>
-#ifndef _MSC_VER
-#include <sys/socket.h>
-#endif
+#include <sys/types.h>
 #include <cmyth_local.h>
 
 /*
@@ -426,7 +424,7 @@ cmyth_file_seek(cmyth_file_t file, long long offset, int whence)
        char msg[128];
        int err;
        int count;
-       long long c;
+       int64_t c;
        long r;
        long long ret;
 
@@ -488,9 +486,9 @@ cmyth_file_seek(cmyth_file_t file, long long offset, int whence)
                ret = count;
                goto out;
        }
-       if ((r=cmyth_rcv_long_long(file->file_control, &err, &c, count)) < 0) {
+       if ((r=cmyth_rcv_int64(file->file_control, &err, &c, count)) < 0) {
                cmyth_dbg(CMYTH_DBG_ERROR,
-                         "%s: cmyth_rcv_long_long() failed (%d)\n",
+                         "%s: cmyth_rcv_int64() failed (%d)\n",
                          __FUNCTION__, r);
                ret = err;
                goto out;
@@ -541,7 +539,7 @@ int cmyth_file_read(cmyth_file_t file, char *buf, unsigned long len)
        int ret, req, nfds, rec;
        char *end, *cur;
        char msg[256];
-       long long len64;
+       int64_t len64;
        struct timeval tv;
        fd_set fds;
 
@@ -624,9 +622,20 @@ int cmyth_file_read(cmyth_file_t file, char *buf, unsigned long len)
                                goto out;
                        }
 
-                       if ((ret=cmyth_rcv_int64 (file->file_control, &err, &len64, count))< 0) {
+                       /*
+                        * MythTV originally sent back a signed 32bit value but was changed to a
+                        * signed 64bit value in http://svn.mythtv.org/trac/changeset/18011 (1-Aug-2008).
+                        *
+                        * libcmyth now retrieves the 64-bit signed value, does error-checking,
+                        * and then converts to a 32bit unsigned.
+                        *
+                        * This rcv_ method needs to be forced to use new_int64 to pull back a
+                        * single 64bit number otherwise the handling in rcv_int64 will revert to
+                        * the old two 32bit hi and lo long values.
+                        */
+                       if ((ret=cmyth_rcv_new_int64 (file->file_control, &err, &len64, count, 1))< 0) {
                                cmyth_dbg (CMYTH_DBG_ERROR,
-                                          "%s: cmyth_rcv_int64() failed (%d)\n",
+                                          "%s: cmyth_rcv_new_int64() failed (%d)\n",
                                           __FUNCTION__, ret);
                                ret = err;
                                goto out;
@@ -634,8 +643,8 @@ int cmyth_file_read(cmyth_file_t file, char *buf, unsigned long len)
                        if (len64 >= 0x100000000LL || len64 < 0) {
                                /* -1 seems to be a common result, but isn't valid so use 0 instead. */
                                cmyth_dbg (CMYTH_DBG_WARN,
-                                          "%s: cmyth_rcv_int64() returned out of bound value (%d). Using 0\n",
-                                          __FUNCTION__, (long)len64);
+                                          "%s: cmyth_rcv_new_int64() returned out of bound value (%"PRId64"). Using 0 instead.\n",
+                                          __FUNCTION__, len64);
                                len64 = 0;
                        }
                        len = (unsigned long)len64;
@@ -644,8 +653,8 @@ int cmyth_file_read(cmyth_file_t file, char *buf, unsigned long len)
 
                        if (file->file_req < file->file_pos) {
                                cmyth_dbg (CMYTH_DBG_ERROR,
-                                          "%s: received invalid invalid length, read position is ahead of request (req: %d, rec: %d, len: %d)\n",
-                                          __FUNCTION__, file->file_req, file->file_pos, len);
+                                          "%s: received invalid invalid length, read position is ahead of request (req: %"PRIu64", pos: %"PRIu64", len: %"PRId64")\n",
+                                          __FUNCTION__, file->file_req, file->file_pos, len64);
                                ret = -1;
                                goto out;
                        }
index d800f68..6b291ac 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2004-2006, Eric Lund
+ *  Copyright (C) 2004-2010, Eric Lund
  *  http://www.mvpmc.org/
  *
  *  This library is free software; you can redistribute it and/or
 /*
  * freespace.c - functions to manage freespace structures.
  */
-#include <sys/types.h>
 #include <stdlib.h>
-#ifndef _MSC_VER
-#include <unistd.h>
-#endif
-#include <stdio.h>
-#include <errno.h>
 #include <cmyth_local.h>
 
 /*
index 3803986..4f6f912 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2004-2006, Eric Lund
+ *  Copyright (C) 2004-2010, Eric Lund
  *  http://www.mvpmc.org/
  *
  *  This library is free software; you can redistribute it and/or
@@ -23,9 +23,6 @@
  */
 #include <sys/types.h>
 #include <stdlib.h>
-#ifndef _MSC_VER
-#include <unistd.h>
-#endif
 #include <string.h>
 #include <stdio.h>
 #include <cmyth_local.h>
index 96e50a2..9f5ccd7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2006, Sergio Slobodrian
+ *  Copyright (C) 2006-2012, Sergio Slobodrian
  *  http://www.mvpmc.org/
  *
  *  This library is free software; you can redistribute it and/or
  *                This allows the watcher to do things like pause, rewind
  *                and so forth on live-tv.
  */
-#include <sys/types.h>
 #include <stdlib.h>
-#ifndef _MSC_VER
-#include <unistd.h>
-#include <sys/socket.h>
-#endif
 #include <stdio.h>
 #include <errno.h>
 #include <string.h>
+#include <sys/types.h>
 #include <cmyth_local.h>
 
-#ifdef _MSC_VER
-static void nullprint(a, ...) { return; }
-#define PRINTF nullprint
-#define TRC  nullprint
-#elif 0
-#define PRINTF(x...) PRINTF(x)
-#define TRC(fmt, args...) PRINTF(fmt, ## args) 
-#else
-#define PRINTF(x...)
-#define TRC(fmt, args...) 
-#endif
-
 #define LAST 0x7FFFFFFF
 
 static int cmyth_livetv_chain_has_url(cmyth_recorder_t rec, char * url);
@@ -427,7 +411,6 @@ cmyth_livetv_chain_update(cmyth_recorder_t rec, char * chainid,
 {
        int ret=0;
        char url[1024];
-       cmyth_conn_t control;
        cmyth_proginfo_t loc_prog;
        cmyth_file_t ft;
 
@@ -436,8 +419,6 @@ cmyth_livetv_chain_update(cmyth_recorder_t rec, char * chainid,
                goto out;
        }
 
-       control = rec->rec_conn;
-
        loc_prog = cmyth_recorder_get_cur_proginfo(rec);
        pthread_mutex_lock(&mutex);
 
@@ -665,7 +646,6 @@ cmyth_livetv_chain_switch(cmyth_recorder_t rec, int dir)
        ret = 0;
 
        if(dir == LAST) {
-               PRINTF("**SSDEBUG:(cmyth_livetv_chain_switch) dir: %d\n", dir);
                dir = rec->rec_livetv_chain->chain_ct
                                - rec->rec_livetv_chain->chain_current - 1;
                ret = 1;
@@ -676,8 +656,6 @@ cmyth_livetv_chain_switch(cmyth_recorder_t rec, int dir)
                          rec->rec_livetv_chain->chain_ct - dir )) {
                ref_release(rec->rec_livetv_file);
                ret = rec->rec_livetv_chain->chain_current += dir;
-               PRINTF("**SSDEBUG:(cmyth_livetv_chain_switch): %s:%d\n",
-               "dooingSwitcheroo",ret);
                rec->rec_livetv_file = ref_hold(rec->rec_livetv_chain->chain_files[ret]);
                rec->rec_livetv_chain
                                        ->prog_update_callback(rec->rec_livetv_chain->progs[ret]);
@@ -711,7 +689,6 @@ cmyth_livetv_chain_switch_last(cmyth_recorder_t rec)
        pthread_mutex_lock(&mutex);
        dir = rec->rec_livetv_chain->chain_ct
                        - rec->rec_livetv_chain->chain_current - 1;
-       PRINTF("#@@@@#SSDEBUG: switch file changing adjusted dir: %d\n", dir);
        if(dir != 0) {
                cmyth_livetv_chain_switch(rec, dir);
        }
@@ -759,8 +736,6 @@ cmyth_livetv_chain_request_block(cmyth_recorder_t rec, unsigned long len)
                ret = cmyth_file_request_block(rec->rec_livetv_file, len);
                if (ret == 0) { /* We've gotten to the end, need to progress in the chain */
                        /* Switch if there are files left in the chain */
-                       PRINTF("**SSDEBUG:(cmyth_livetv_request_block): %s\n",
-                       "reached end of stream must dooSwitcheroo");
                        retry = cmyth_livetv_chain_switch(rec, 1);
                }
        }
@@ -792,8 +767,6 @@ int cmyth_livetv_chain_read(cmyth_recorder_t rec, char *buf, unsigned long len)
                ret = cmyth_file_read(rec->rec_livetv_file, buf, len);  
                if (ret == 0) {
                        /* eof, switch to next file */
-                       PRINTF("**SSDEBUG:(cmyth_livetv_chain_read): %s\n",
-                       "reached end of stream must dooSwitcheroo");
                        retry = cmyth_livetv_chain_switch(rec, 1);
                }
        } while(retry);
@@ -895,8 +868,6 @@ cmyth_livetv_chain_seek(cmyth_recorder_t rec, long long offset, int whence)
 
        ret = cmyth_file_seek(fp, offset, whence);
 
-       PRINTF("** SSDEBUG: new pos %lld after seek command\n", ret);
-
        cur -= rec->rec_livetv_chain->chain_current;
        if (ret >= 0 && cur) {
                cmyth_livetv_chain_switch(rec, cur);
@@ -1040,7 +1011,6 @@ cmyth_spawn_live_tv(cmyth_recorder_t rec, unsigned buflen, int tcp_rcvbuf,
        cmyth_recorder_t rtrn = NULL;
        int i;
 
-       //printf("** SSDEBUG: version is %ld\n", rec->rec_conn->conn_version);
        if(rec->rec_conn->conn_version >= 26) {
                if (cmyth_recorder_spawn_chain_livetv(rec, channame) != 0) {
                        *err = "Spawn livetv failed.";
index 6370e13..ade4c5c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2006, Simon Hyde
+ *  Copyright (C) 2006-2009, Simon Hyde
  *  http://www.mvpmc.org/
  *
  *  This library is free software; you can redistribute it and/or
index 3ff23fa..de5695c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2004-2006, Eric Lund
+ *  Copyright (C) 2004-2012, Eric Lund
  *  http://www.mvpmc.org/
  *
  *  This library is free software; you can redistribute it and/or
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include <sys/types.h>
 #include <stdlib.h>
-#ifndef _MSC_VER
-#include <unistd.h>
-#endif
 #include <stdio.h>
 #include <errno.h>
 #include <string.h>
-#ifdef _MSC_VER
-#include <time.h>
-#else
-#include <sys/time.h>
-#endif
 #include <mysql/mysql.h>
 #include <cmyth_local.h>
 #include <safe_string.h>
 
-#ifdef _MSC_VER
-static void nullprint(a, ...) { return; }
-#define PRINTF nullprint
-#define TRC  nullprint
-#elif 0
-#define PRINTF(x...) PRINTF(x)
-#define TRC(fmt, args...) PRINTF(fmt, ## args) 
-#else
-#define PRINTF(x...)
-#define TRC(fmt, args...) 
-#endif
-
-
 void
 cmyth_database_close(cmyth_database_t db)
 {
@@ -76,7 +54,6 @@ cmyth_database_init(char *host, char *db_name, char *user, char *pass)
 int
 cmyth_database_set_host(cmyth_database_t db, char *host)
 {
-       PRINTF("** SSDEBUG: setting the db host to %s\n", host);
        cmyth_database_close(db);
        ref_release(db->db_host);
        db->db_host = ref_strdup(host);
@@ -89,7 +66,6 @@ cmyth_database_set_host(cmyth_database_t db, char *host)
 int
 cmyth_database_set_user(cmyth_database_t db, char *user)
 {
-       PRINTF("** SSDEBUG: setting the db user to %s\n", user);
        cmyth_database_close(db);
        ref_release(db->db_user);
        db->db_user = ref_strdup(user);
@@ -102,7 +78,6 @@ cmyth_database_set_user(cmyth_database_t db, char *user)
 int
 cmyth_database_set_pass(cmyth_database_t db, char *pass)
 {
-       PRINTF("** SSDEBUG: setting the db pass to %s\n", pass);
        cmyth_database_close(db);
        ref_release(db->db_user);
        db->db_pass = ref_strdup(pass);
@@ -115,7 +90,6 @@ cmyth_database_set_pass(cmyth_database_t db, char *pass)
 int
 cmyth_database_set_name(cmyth_database_t db, char *name)
 {
-       PRINTF("** SSDEBUG: setting the db name to %s\n", name);
        cmyth_database_close(db);
        ref_release(db->db_name);
        db->db_name = ref_strdup(name);
@@ -129,7 +103,6 @@ cmyth_database_set_name(cmyth_database_t db, char *name)
 static int
 cmyth_db_check_connection(cmyth_database_t db)
 {
-    int new_conn = 0;
     if(db->mysql != NULL)
     {
        /* Fetch the mysql stats (uptime and stuff) to check the connection is
@@ -143,7 +116,6 @@ cmyth_db_check_connection(cmyth_database_t db)
     if(db->mysql == NULL)
     {
        db->mysql = mysql_init(NULL);
-       new_conn = 1;
        if(db->mysql == NULL)
        {
            fprintf(stderr,"%s: mysql_init() failed, insufficient memory?",
@@ -671,21 +643,49 @@ fill_program_recording_status(cmyth_conn_t conn, char * msg)
        }
        return err;
 }
+int
+cmyth_update_bookmark_setting(cmyth_database_t db, cmyth_proginfo_t prog)
+{
+       MYSQL_RES *res = NULL;
+       const char *query_str = "UPDATE recorded SET bookmark = 1 WHERE chanid = ? AND starttime = ?";
+       cmyth_mysql_query_t * query;
+       char starttime[CMYTH_TIMESTAMP_LEN + 1];
 
-int 
-cmyth_get_bookmark_mark(cmyth_database_t db, cmyth_proginfo_t prog, long long bk)
+       cmyth_timestamp_to_string(starttime, prog->proginfo_rec_start_ts);
+       query = cmyth_mysql_query_create(db,query_str);
+       if (cmyth_mysql_query_param_long(query, prog->proginfo_chanId) < 0
+               || cmyth_mysql_query_param_str(query, starttime) < 0 ) {
+               cmyth_dbg(CMYTH_DBG_ERROR,"%s, binding of query parameters failed! Maybe we're out of memory?\n", __FUNCTION__);
+               ref_release(query);
+               return -1;
+       }
+       res = cmyth_mysql_query_result(query);
+       ref_release(query);
+       if (res == NULL) {
+               cmyth_dbg(CMYTH_DBG_ERROR, "%s, finalisation/execution of query failed!\n", __FUNCTION__);
+               return -1;
+       }
+       mysql_free_result(res);
+       return (1);
+}
+
+long long 
+cmyth_get_bookmark_mark(cmyth_database_t db, cmyth_proginfo_t prog, long long bk, int mode)
 {
        MYSQL_RES *res = NULL;
        MYSQL_ROW row;
-       const char *query_str = "SELECT mark FROM recordedseek WHERE chanid = ? AND offset>= ? AND type = 6 ORDER by MARK ASC LIMIT 0,1;";
+       const char *query_str = "SELECT mark, type FROM recordedseek WHERE chanid = ? AND offset < ? AND (type = 6 or type = 9 ) AND starttime = ? ORDER by MARK DESC LIMIT 0, 1;";
        int rows = 0;
-       int mark=0;
+       long long mark=0;
+       int rectype = 0;
        char start_ts_dt[CMYTH_TIMESTAMP_LEN + 1];
        cmyth_mysql_query_t * query;
-       cmyth_datetime_to_string(start_ts_dt, prog->proginfo_rec_start_ts);
+       cmyth_timestamp_to_string(start_ts_dt, prog->proginfo_rec_start_ts);
        query = cmyth_mysql_query_create(db,query_str);
+
        if (cmyth_mysql_query_param_long(query, prog->proginfo_chanId) < 0
                || cmyth_mysql_query_param_long(query, bk) < 0
+               || cmyth_mysql_query_param_str(query, start_ts_dt) < 0
                ) {
                cmyth_dbg(CMYTH_DBG_ERROR,"%s, binding of query parameters failed! Maybe we're out of memory?\n", __FUNCTION__);
                ref_release(query);
@@ -699,24 +699,39 @@ cmyth_get_bookmark_mark(cmyth_database_t db, cmyth_proginfo_t prog, long long bk
        }
        while ((row = mysql_fetch_row(res))) {
                mark = safe_atoi(row[0]);
+               rectype = safe_atoi(row[1]);
                rows++;
        }
        mysql_free_result(res);
+
+       if (rectype == 6) {
+               if (mode == 0) {
+                       mark=(mark-1)*15;
+               }
+               else if (mode == 1) {
+                       mark=(mark-1)*12;
+               }
+       }
+
        return mark;
 }
 
 int 
-cmyth_get_bookmark_offset(cmyth_database_t db, long chanid, long long mark) 
+cmyth_get_bookmark_offset(cmyth_database_t db, long chanid, long long mark, char *starttime, int mode
 {
        MYSQL_RES *res = NULL;
        MYSQL_ROW row;
-       const char *query_str = "SELECT * FROM recordedseek WHERE chanid = ? AND mark= ?;";
        int offset=0;
        int rows = 0;
+       int rectype = 0;
        cmyth_mysql_query_t * query;
+       
+       const char *query_str = "SELECT * FROM recordedseek WHERE chanid = ? AND mark<= ? AND starttime = ? ORDER BY MARK DESC LIMIT 1;";
+
        query = cmyth_mysql_query_create(db,query_str);
        if (cmyth_mysql_query_param_long(query, chanid) < 0
                || cmyth_mysql_query_param_long(query, mark) < 0
+               || cmyth_mysql_query_param_str(query, starttime) < 0
                ) {
                cmyth_dbg(CMYTH_DBG_ERROR,"%s, binding of query parameters failed! Maybe we're out of memory?\n", __FUNCTION__);
                ref_release(query);
@@ -730,8 +745,36 @@ cmyth_get_bookmark_offset(cmyth_database_t db, long chanid, long long mark)
        }
        while ((row = mysql_fetch_row(res))) {
                offset = safe_atoi(row[3]);
+               rectype = safe_atoi(row[4]);
                rows++;
        }
+       if (rectype != 9) {
+               if (mode == 0) {
+                       mark=(mark/15)+1;
+               }
+               else if (mode == 1) {
+                       mark=(mark/12)+1;
+               }
+               query = cmyth_mysql_query_create(db, query_str);
+               if (cmyth_mysql_query_param_long(query, chanid) < 0
+                       || cmyth_mysql_query_param_long(query, mark) < 0
+                       || cmyth_mysql_query_param_str(query, starttime) < 0
+                       ) {
+                       cmyth_dbg(CMYTH_DBG_ERROR,"%s, binding of query parameters failed! Maybe we're out of memory?\n", __FUNCTION__);
+                       ref_release(query);
+                       return -1;
+               }
+               res = cmyth_mysql_query_result(query);
+               ref_release(query);
+               if (res == NULL) {
+                       cmyth_dbg(CMYTH_DBG_ERROR, "%s, finalisation/execution of query failed!\n", __FUNCTION__);
+                       return -1;
+               }
+               while ((row = mysql_fetch_row(res))) {
+                       offset = safe_atoi(row[3]);
+                       rows++;
+               }
+       }
        mysql_free_result(res);
        return offset;
 }
@@ -903,7 +946,49 @@ cmyth_mysql_get_commbreak_list(cmyth_database_t db, int chanid, char * start_ts_
 }
 
 int
-cmyth_mythtv_remove_previos_recorded(cmyth_database_t db,char *query)
+cmyth_tuner_type_check(cmyth_database_t db, cmyth_recorder_t rec, int check_tuner_type) {
+       MYSQL_RES *res=NULL;
+       MYSQL_ROW row;
+       const char * query_str = "SELECT cardtype from capturecard WHERE cardid=?";
+       cmyth_mysql_query_t * query;
+
+       if ( check_tuner_type == 0 ) {
+               cmyth_dbg(CMYTH_DBG_ERROR,"MythTV Tuner check not enabled in Mythtv Options\n");
+               return (1);
+       }
+       
+
+       query = cmyth_mysql_query_create(db,query_str);
+       if (cmyth_mysql_query_param_uint(query,rec->rec_id) < 0) {
+               cmyth_dbg(CMYTH_DBG_ERROR,"%s, binding of query failed\n",__FUNCTION__);
+               ref_release(query);
+               return -1;
+       }
+       res = cmyth_mysql_query_result(query);
+
+       if(res == NULL) {
+               cmyth_dbg(CMYTH_DBG_ERROR,"%s, finalisation/execution\n",__FUNCTION__);
+               return -1;
+       }
+       row = mysql_fetch_row(res);
+       ref_release(query);
+       mysql_free_result(res);
+       if (strcmp(row[0],"MPEG") == 0) {
+               return (1); //return the first available MPEG tuner
+       }
+       else if (strcmp(row[0],"HDHOMERUN") == 0) {
+               return (1); //return the first available MPEG2TS tuner
+       }
+       else if (strcmp(row[0],"DVB") == 0) {
+               return (1); //return the first available DVB tuner
+       }
+       else {
+               return (0);
+       }
+}
+
+int
+cmyth_mythtv_remove_previous_recorded(cmyth_database_t db,char *query)
 {
        MYSQL_RES *res=NULL;
        char N_query[128];
@@ -930,6 +1015,7 @@ cmyth_mythtv_remove_previos_recorded(cmyth_database_t db,char *query)
                cmyth_dbg(CMYTH_DBG_ERROR, "%s: mysql_query() Failed: %s\n", 
                        __FUNCTION__, mysql_error(db->mysql));
        }
+       mysql_free_result(res);
 
        return rows;
 }
index e5ffc96..c5043ec 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2004-2006, Eric Lund
+ *  Copyright (C) 2004-2010, Eric Lund
  *  http://www.mvpmc.org/
  *
  *  This library is free software; you can redistribute it and/or
  *            be markers inserted by commercial detection.  A position
  *            map collects these in one place.
  */
-#include <sys/types.h>
 #include <stdlib.h>
-#ifndef _MSC_VER
-#include <unistd.h>
-#endif
 #include <stdio.h>
 #include <cmyth_local.h>
 
index f6f9347..fa9db29 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2004-2006, Eric Lund
+ *  Copyright (C) 2004-2010, Eric Lund
  *  http://www.mvpmc.org/
  *
  *  This library is free software; you can redistribute it and/or
  *              also retrieve and manipulate recordings and program
  *              material based on program information.
  */
-#include <sys/types.h>
 #include <stdlib.h>
-#ifndef _MSC_VER
-#include <unistd.h>
-#endif
 #include <stdio.h>
 #include <errno.h>
 #include <string.h>
@@ -152,8 +148,8 @@ cmyth_proginfo_destroy(cmyth_proginfo_t p)
        if (p->proginfo_storagegroup) {
                ref_release(p->proginfo_storagegroup);
        }
-       if (p->proginfo_prodyear) {
-               ref_release(p->proginfo_prodyear);
+       if (p->proginfo_recpriority_2) {
+               ref_release(p->proginfo_recpriority_2);
        }
        cmyth_dbg(CMYTH_DBG_DEBUG, "%s }\n", __FUNCTION__);
 }
@@ -266,7 +262,7 @@ cmyth_proginfo_create(void)
        ret->proginfo_audioproperties = 0;
        ret->proginfo_videoproperties = 0;
        ret->proginfo_subtitletype = 0;
-       ret->proginfo_prodyear = NULL;
+       ret->proginfo_year = 0;
        cmyth_dbg(CMYTH_DBG_DEBUG, "%s }\n", __FUNCTION__);
        return ret;
 
@@ -359,7 +355,7 @@ cmyth_proginfo_dup(cmyth_proginfo_t p)
        ret->proginfo_audioproperties = p->proginfo_audioproperties;
        ret->proginfo_videoproperties = p->proginfo_videoproperties;
        ret->proginfo_subtitletype = p->proginfo_subtitletype;
-       ret->proginfo_prodyear = ref_hold(p->proginfo_prodyear);
+       ret->proginfo_year = p->proginfo_year;
        cmyth_dbg(CMYTH_DBG_DEBUG, "%s }\n", __FUNCTION__);
        return ret;
 }
@@ -429,7 +425,6 @@ delete_command(cmyth_conn_t control, cmyth_proginfo_t prog, char *cmd)
        len += strlen(S(prog->proginfo_inetref));
        len += strlen(S(prog->proginfo_recpriority_2));
        len += strlen(S(prog->proginfo_storagegroup));
-       len += strlen(S(prog->proginfo_prodyear));
 
        buf = alloca(len + 1+2048);
        if (!buf) {
@@ -470,86 +465,85 @@ delete_command(cmyth_conn_t control, cmyth_proginfo_t prog, char *cmd)
                          "%s: delete not supported with protocol ver %d\n",
                          __FUNCTION__, control->conn_version);
                return -EINVAL;
+       }
+       sprintf(buf, "%s 0[]:[]", cmd);
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_title));
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_subtitle));
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_description));
+       if (control->conn_version >= 67) {
+               sprintf(buf + strlen(buf), "%u[]:[]", prog->proginfo_season);
+               sprintf(buf + strlen(buf), "%u[]:[]", prog->proginfo_episode);
+       }
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_category));
+       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_chanId);
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_chanstr));
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_chansign));
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_channame));
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_url));
+       if (control->conn_version >= 57) {
+               sprintf(buf + strlen(buf), "%"PRId64"[]:[]", prog->proginfo_Length);
        } else {
-               sprintf(buf, "%s 0[]:[]", cmd);
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_title));
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_subtitle));
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_description));
-               if (control->conn_version >= 67) {
-                       sprintf(buf + strlen(buf), "%u[]:[]", prog->proginfo_season);
-                       sprintf(buf + strlen(buf), "%u[]:[]", prog->proginfo_episode);
-               }
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_category));
-               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_chanId);
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_chanstr));
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_chansign));
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_channame));
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_url));
-               if (control->conn_version >= 57) {
-                       sprintf(buf + strlen(buf), "%"PRId64"[]:[]", prog->proginfo_Length);
-               } else {
-                       sprintf(buf + strlen(buf), "%d[]:[]", (int32_t)(prog->proginfo_Length >> 32));
-                       sprintf(buf + strlen(buf), "%d[]:[]", (int32_t)(prog->proginfo_Length & 0xffffffff));
-               }
-               sprintf(buf + strlen(buf), "%s[]:[]",  start_ts);
-               sprintf(buf + strlen(buf), "%s[]:[]",  end_ts);
-               if (control->conn_version < 57) {
-                       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_unknown_0)); // "duplicate"
-                       sprintf(buf + strlen(buf), "%ld[]:[]", 0L); // "shareable"
-               }
-               sprintf(buf + strlen(buf), "%ld[]:[]", 0L); // "findid"
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_hostname));
-               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_source_id);
-               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_card_id);
-               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_input_id);
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_rec_priority));
-               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_rec_status);
-               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_record_id);
-               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_rec_type);
-               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_rec_dups);
-               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_unknown_1); // "dupmethod"
-               sprintf(buf + strlen(buf), "%s[]:[]",  rec_start_ts);
-               sprintf(buf + strlen(buf), "%s[]:[]",  rec_end_ts);
-               if (control->conn_version < 57) {
-                       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_repeat);
-               }
-               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_program_flags);
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_recgroup));
-               if (control->conn_version < 57) {
-                       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_chancommfree));
-               }
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_chan_output_filters));
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_seriesid));
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_programid));
-               if (control->conn_version >= 67) {
-                       sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_inetref));
-               }
-               sprintf(buf + strlen(buf), "%s[]:[]",  lastmodified);
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_stars));
-               sprintf(buf + strlen(buf), "%s[]:[]",  originalairdate);
-               if (control->conn_version >= 15 && control->conn_version < 57) {
-                       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_hasairdate);
-               }
-               if (control->conn_version >= 18) {
-                       sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_playgroup));
-               }
-               if (control->conn_version >= 25) {
-                       sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_recpriority_2));
-               }
-               if (control->conn_version >= 31) {
-                       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_parentid);
-               }
-               if (control->conn_version >= 32) {
-                       sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_storagegroup));
-               }
-               if (control->conn_version >= 35) {
-                       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_audioproperties);
-                       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_videoproperties);
-                       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_subtitletype);
-               }
-               if (control->conn_version >= 41) {
-                       sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_prodyear));
-               }
+               sprintf(buf + strlen(buf), "%d[]:[]", (int32_t)(prog->proginfo_Length >> 32));
+               sprintf(buf + strlen(buf), "%d[]:[]", (int32_t)(prog->proginfo_Length & 0xffffffff));
+       }
+       sprintf(buf + strlen(buf), "%s[]:[]",  start_ts);
+       sprintf(buf + strlen(buf), "%s[]:[]",  end_ts);
+       if (control->conn_version < 57) {
+               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_unknown_0)); // "duplicate"
+               sprintf(buf + strlen(buf), "%ld[]:[]", 0L); // "shareable"
+       }
+       sprintf(buf + strlen(buf), "%ld[]:[]", 0L); // "findid"
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_hostname));
+       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_source_id);
+       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_card_id);
+       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_input_id);
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_rec_priority));
+       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_rec_status);
+       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_record_id);
+       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_rec_type);
+       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_rec_dups);
+       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_unknown_1); // "dupmethod"
+       sprintf(buf + strlen(buf), "%s[]:[]",  rec_start_ts);
+       sprintf(buf + strlen(buf), "%s[]:[]",  rec_end_ts);
+       if (control->conn_version < 57) {
+               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_repeat);
+       }
+       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_program_flags);
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_recgroup));
+       if (control->conn_version < 57) {
+               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_chancommfree));
+       }
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_chan_output_filters));
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_seriesid));
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_programid));
+       if (control->conn_version >= 67) {
+               sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_inetref));
+       }
+       sprintf(buf + strlen(buf), "%s[]:[]",  lastmodified);
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_stars));
+       sprintf(buf + strlen(buf), "%s[]:[]",  originalairdate);
+       if (control->conn_version >= 15 && control->conn_version < 57) {
+               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_hasairdate);
+       }
+       if (control->conn_version >= 18) {
+               sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_playgroup));
+       }
+       if (control->conn_version >= 25) {
+               sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_recpriority_2));
+       }
+       if (control->conn_version >= 31) {
+               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_parentid);
+       }
+       if (control->conn_version >= 32) {
+               sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_storagegroup));
+       }
+       if (control->conn_version >= 35) {
+               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_audioproperties);
+               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_videoproperties);
+               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_subtitletype);
+       }
+       if (control->conn_version >= 43) {
+               sprintf(buf + strlen(buf), "%d[]:[]", prog->proginfo_year);
        }
 #undef S
 
@@ -1274,33 +1268,29 @@ cmyth_proginfo_flags(cmyth_proginfo_t prog)
 }
 
 /*
- * cmyth_proginfo_prodyear(cmyth_proginfo_t prog)
+ * cmyth_proginfo_year(cmyth_proginfo_t prog)
  *
  *
  * Scope: PUBLIC
  *
  * Description
  *
- * Retrieves the 'proginfo_prodyear' field of a program info
+ * Retrieves the 'proginfo_year' field of a program info
  * structure.
  *
- * The returned string is a pointer to the string within the program
- * info structure, so it should not be modified by the caller.  The
- * return value is a 'char *' for this reason.
- *
  * Return Value:
  *
- * Success: A pointer to a 'char *' pointing to the field.
+ * Success: the production year for the program
  *
- * Failure: NULL
+ * Failure: 0
  */
-char *
-cmyth_proginfo_prodyear(cmyth_proginfo_t prog)
+unsigned short
+cmyth_proginfo_year(cmyth_proginfo_t prog)
 {
        if (!prog) {
-               return NULL;
+               return 0;
        }
-       return ref_hold(prog->proginfo_prodyear);
+       return prog->proginfo_year;
 }
 
 static int
@@ -1318,7 +1308,7 @@ fill_command(cmyth_conn_t control, cmyth_proginfo_t prog, char *cmd)
        char lastmodified[CMYTH_TIMESTAMP_LEN + 1];
        int err = 0;
        int ret = 0;
-       char *host = "mediamvp";
+       char *host = "libcmyth";
 
        if (!prog) {
                cmyth_dbg(CMYTH_DBG_ERROR, "%s: no program info\n",
@@ -1342,7 +1332,6 @@ fill_command(cmyth_conn_t control, cmyth_proginfo_t prog, char *cmd)
        len += strlen(S(prog->proginfo_inetref));
        len += strlen(S(prog->proginfo_recpriority_2));
        len += strlen(S(prog->proginfo_storagegroup));
-       len += strlen(S(prog->proginfo_prodyear));
 
        buf = alloca(len + 1+2048);
        if (!buf) {
@@ -1383,86 +1372,85 @@ fill_command(cmyth_conn_t control, cmyth_proginfo_t prog, char *cmd)
                          "%s: fill not supported with protocol ver %d\n",
                          __FUNCTION__, control->conn_version);
                return -EINVAL;
+       }
+       sprintf(buf, "%s %s[]:[]0[]:[]", cmd, host);
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_title));
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_subtitle));
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_description));
+       if (control->conn_version >= 67) {
+               sprintf(buf + strlen(buf), "%u[]:[]", prog->proginfo_season);
+               sprintf(buf + strlen(buf), "%u[]:[]", prog->proginfo_episode);
+       }
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_category));
+       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_chanId);
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_chanstr));
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_chansign));
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_channame));
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_url));
+       if (control->conn_version >= 57) {
+               sprintf(buf + strlen(buf), "%"PRId64"[]:[]", prog->proginfo_Length);
        } else {
-               sprintf(buf, "%s %s[]:[]0[]:[]", cmd, host);
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_title));
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_subtitle));
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_description));
-               if (control->conn_version >= 67) {
-                       sprintf(buf + strlen(buf), "%u[]:[]", prog->proginfo_season);
-                       sprintf(buf + strlen(buf), "%u[]:[]", prog->proginfo_episode);
-               }
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_category));
-               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_chanId);
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_chanstr));
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_chansign));
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_channame));
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_url));
-               if (control->conn_version >= 57) {
-                       sprintf(buf + strlen(buf), "%"PRId64"[]:[]", prog->proginfo_Length);
-               } else {
-                       sprintf(buf + strlen(buf), "%d[]:[]", (int32_t)(prog->proginfo_Length >> 32));
-                       sprintf(buf + strlen(buf), "%d[]:[]", (int32_t)(prog->proginfo_Length & 0xffffffff));
-               }
-               sprintf(buf + strlen(buf), "%s[]:[]",  start_ts);
-               sprintf(buf + strlen(buf), "%s[]:[]",  end_ts);
-               if (control->conn_version < 57) {
-                       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_unknown_0)); // "duplicate"
-                       sprintf(buf + strlen(buf), "%ld[]:[]", 0L); // "shareable"
-               }
-               sprintf(buf + strlen(buf), "%ld[]:[]", 0L); // "findid"
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_hostname));
-               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_source_id);
-               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_card_id);
-               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_input_id);
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_rec_priority));
-               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_rec_status);
-               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_record_id);
-               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_rec_type);
-               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_rec_dups);
-               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_unknown_1); // "dupmethod"
-               sprintf(buf + strlen(buf), "%s[]:[]",  rec_start_ts);
-               sprintf(buf + strlen(buf), "%s[]:[]",  rec_end_ts);
-               if (control->conn_version < 57) {
-                       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_repeat);
-               }
-               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_program_flags);
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_recgroup));
-               if (control->conn_version < 57) {
-                       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_chancommfree));
-               }
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_chan_output_filters));
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_seriesid));
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_programid));
-               if (control->conn_version >= 67) {
-                       sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_inetref));
-               }
-               sprintf(buf + strlen(buf), "%s[]:[]",  lastmodified);
-               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_stars));
-               sprintf(buf + strlen(buf), "%s[]:[]",  originalairdate);
-               if (control->conn_version >= 15 && control->conn_version < 57) {
-                       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_hasairdate);
-               }
-               if (control->conn_version >= 18) {
-                       sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_playgroup));
-               }
-               if (control->conn_version >= 25) {
-                       sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_recpriority_2));
-               }
-               if (control->conn_version >= 31) {
-                       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_parentid);
-               }
-               if (control->conn_version >= 32) {
-                       sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_storagegroup));
-               }
-               if (control->conn_version >= 35) {
-                       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_audioproperties);
-                       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_videoproperties);
-                       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_subtitletype);
-               }
-               if (control->conn_version >= 41) {
-                       sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_prodyear));
-               }
+               sprintf(buf + strlen(buf), "%d[]:[]", (int32_t)(prog->proginfo_Length >> 32));
+               sprintf(buf + strlen(buf), "%d[]:[]", (int32_t)(prog->proginfo_Length & 0xffffffff));
+       }
+       sprintf(buf + strlen(buf), "%s[]:[]",  start_ts);
+       sprintf(buf + strlen(buf), "%s[]:[]",  end_ts);
+       if (control->conn_version < 57) {
+               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_unknown_0)); // "duplicate"
+               sprintf(buf + strlen(buf), "%ld[]:[]", 0L); // "shareable"
+       }
+       sprintf(buf + strlen(buf), "%ld[]:[]", 0L); // "findid"
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_hostname));
+       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_source_id);
+       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_card_id);
+       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_input_id);
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_rec_priority));
+       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_rec_status);
+       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_record_id);
+       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_rec_type);
+       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_rec_dups);
+       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_unknown_1); // "dupmethod"
+       sprintf(buf + strlen(buf), "%s[]:[]",  rec_start_ts);
+       sprintf(buf + strlen(buf), "%s[]:[]",  rec_end_ts);
+       if (control->conn_version < 57) {
+               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_repeat);
+       }
+       sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_program_flags);
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_recgroup));
+       if (control->conn_version < 57) {
+               sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_chancommfree));
+       }
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_chan_output_filters));
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_seriesid));
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_programid));
+       if (control->conn_version >= 67) {
+               sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_inetref));
+       }
+       sprintf(buf + strlen(buf), "%s[]:[]",  lastmodified);
+       sprintf(buf + strlen(buf), "%s[]:[]",  S(prog->proginfo_stars));
+       sprintf(buf + strlen(buf), "%s[]:[]",  originalairdate);
+       if (control->conn_version >= 15 && control->conn_version < 57) {
+               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_hasairdate);
+       }
+       if (control->conn_version >= 18) {
+               sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_playgroup));
+       }
+       if (control->conn_version >= 25) {
+               sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_recpriority_2));
+       }
+       if (control->conn_version >= 31) {
+               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_parentid);
+       }
+       if (control->conn_version >= 32) {
+               sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_storagegroup));
+       }
+       if (control->conn_version >= 35) {
+               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_audioproperties);
+               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_videoproperties);
+               sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_subtitletype);
+       }
+       if (control->conn_version >= 43) {
+               sprintf(buf + strlen(buf), "%d[]:[]", prog->proginfo_year);
        }
 #undef S
 
@@ -1683,6 +1671,18 @@ cmyth_proginfo_host(cmyth_proginfo_t prog)
        return ref_hold(prog->proginfo_host);
 }
 
+int
+cmyth_proginfo_port(cmyth_proginfo_t prog)
+{
+       if (!prog) {
+               cmyth_dbg(CMYTH_DBG_ERROR,
+                         "%s: no program info\n", __FUNCTION__);
+               return -1;
+       }
+
+       return prog->proginfo_port;
+}
+
 long
 cmyth_proginfo_card_id(cmyth_proginfo_t prog)
 {
index fe75577..b0a4820 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2004-2006, Eric Lund
+ *  Copyright (C) 2004-2010, Eric Lund
  *  http://www.mvpmc.org/
  *
  *  This library is free software; you can redistribute it and/or
  *               and cmyth_proglist_t and between long long and
  *               cmyth_proglist_t.
  */
-#include <sys/types.h>
 #include <stdlib.h>
-#ifndef _MSC_VER
-#include <unistd.h>
-#endif
 #include <stdio.h>
 #include <errno.h>
 #include <string.h>
index ee82f26..a5ae2b3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2004-2006, Eric Lund
+ *  Copyright (C) 2004-2010, Eric Lund
  *  http://www.mvpmc.org/
  *
  *  This library is free software; you can redistribute it and/or
  * rec_num.c -  functions to manage recorder number structures.  Mostly
  *              just allocating, freeing, and filling them out.
  */
-#include <sys/types.h>
 #include <stdlib.h>
-#ifndef _MSC_VER
-#include <unistd.h>
-#endif
 #include <stdio.h>
 #include <string.h>
-#include <errno.h>
 #include <cmyth_local.h>
 
 /*
index d0ebbce..207a241 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2004-2006, Eric Lund, Jon Gettler
+ *  Copyright (C) 2004-2009, Eric Lund, Jon Gettler
  *  http://www.mvpmc.org/
  *
  *  This library is free software; you can redistribute it and/or
  *                owns the tuner and channel information (i.e. program
  *                guide data).
  */
-#include <sys/types.h>
 #include <stdlib.h>
-#ifndef _MSC_VER
-#include <unistd.h>
-#endif
 #include <stdio.h>
 #include <errno.h>
 #include <string.h>
-#ifdef _MSC_VER
 #include <time.h>
-#else
-#include <sys/time.h>
-#endif
 #include <cmyth_local.h>
 
-#ifdef _MSC_VER
-static void nullprint(a, ...) { return; }
-#define PRINTF nullprint
-#define TRC  nullprint
-#elif 0
-#define PRINTF(x...) PRINTF(x)
-#define TRC(fmt, args...) PRINTF(fmt, ## args) 
-#else
-#define PRINTF(x...)
-#define TRC(fmt, args...) 
-#endif
-
 /*
  * cmyth_recorder_destroy(cmyth_recorder_t rec)
  * 
@@ -509,7 +489,6 @@ cmyth_recorder_pause(cmyth_recorder_t rec)
 
        pthread_mutex_lock(&mutex);
 
-       PRINTF("** SSDEBUG: trying to pause recorder:%p:%p\n",rec,rec->rec_conn);
        sprintf(Buffer, "QUERY_RECORDER %ld[]:[]PAUSE", (long) rec->rec_id);
        if ((ret=cmyth_send_message(rec->rec_conn, Buffer)) < 0) {
                cmyth_dbg(CMYTH_DBG_ERROR,
@@ -527,7 +506,6 @@ cmyth_recorder_pause(cmyth_recorder_t rec)
        ret = 0;
 
     err:
-       PRINTF("** SSDEBUG: recorder paused:\n");
        pthread_mutex_unlock(&mutex);
 
        return ret;
index 4279f85..77ea52d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2004-2006, Eric Lund
+ *  Copyright (C) 2004-2012, Eric Lund
  *  http://www.mvpmc.org/
  *
  *  This library is free software; you can redistribute it and/or
  *                This allows the watcher to do things like pause, rewind
  *                and so forth on live-tv.
  */
-#include <sys/types.h>
 #include <stdlib.h>
-#ifndef _MSC_VER
-#include <unistd.h>
-#include <sys/socket.h>
-#endif
 #include <stdio.h>
 #include <errno.h>
 #include <string.h>
+#include <sys/types.h>
 #include <cmyth_local.h>
 
 /*
@@ -135,7 +131,7 @@ cmyth_ringbuf_setup(cmyth_recorder_t rec)
 
        int err, count;
        int r;
-       long long size, fill;
+       int64_t size, fill;
        char msg[256];
        char url[1024];
        char buf[32];
@@ -171,7 +167,7 @@ cmyth_ringbuf_setup(cmyth_recorder_t rec)
        r = cmyth_rcv_string(control, &err, url, sizeof(url)-1, count); 
        count -= r;
 
-       if ((r=cmyth_rcv_long_long(control, &err, &size, count)) < 0) {
+       if ((r=cmyth_rcv_int64(control, &err, &size, count)) < 0) {
                cmyth_dbg(CMYTH_DBG_ERROR,
                          "%s: cmyth_rcv_length() failed (%d)\n",
                          __FUNCTION__, r);
@@ -179,7 +175,7 @@ cmyth_ringbuf_setup(cmyth_recorder_t rec)
        }
        count -= r;
 
-       if ((r=cmyth_rcv_long_long(control, &err, &fill, count)) < 0) {
+       if ((r=cmyth_rcv_int64(control, &err, &fill, count)) < 0) {
                cmyth_dbg(CMYTH_DBG_ERROR,
                          "%s: cmyth_rcv_length() failed (%d)\n",
                          __FUNCTION__, r);
@@ -532,7 +528,7 @@ cmyth_ringbuf_seek(cmyth_recorder_t rec,
        char msg[128];
        int err;
        int count;
-       long long c;
+       int64_t c;
        long r;
        long long ret;
        cmyth_ringbuf_t ring;
@@ -565,7 +561,7 @@ cmyth_ringbuf_seek(cmyth_recorder_t rec,
        }
 
        count = cmyth_rcv_length(rec->rec_conn);
-       if ((r=cmyth_rcv_long_long(rec->rec_conn, &err, &c, count)) < 0) {
+       if ((r=cmyth_rcv_int64(rec->rec_conn, &err, &c, count)) < 0) {
                cmyth_dbg(CMYTH_DBG_ERROR,
                          "%s: cmyth_rcv_length() failed (%d)\n",
                          __FUNCTION__, r);
index 35dd1be..3efa9a1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2006, Simon Hyde
+ *  Copyright (C) 2006-2009, Simon Hyde
  *  http://www.mvpmc.org/
  *
  *  This library is free software; you can redistribute it and/or
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-/** \file mvp_string.h
+/** \file safe_string.h
  * Some basic string handling routines to help avoid segfaults/buffer overflows
  */
 
-#ifndef __MVP_STRING_H
-#define __MVP_STRING_H
+#ifndef __CMYTH_STRING_H
+#define __CMYTH_STRING_H
 
 #include <stdio.h>
 
@@ -46,4 +46,4 @@ static inline char * safe_strncpy(char *dest,const char *src,size_t n)
 #define safe_atoll(str) (((str) == NULL)? (long long)0: atoll(str))
 #define safe_atoi(str) (((str) == NULL)? (int)0: atoi(str))
 
-#endif /* __MVP_STRING_H */
+#endif /* __CMYTH_STRING_H */
index 552b88d..4340f2e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2004-2006, Eric Lund
+ *  Copyright (C) 2004-2012, Eric Lund
  *  http://www.mvpmc.org/
  *
  *  This library is free software; you can redistribute it and/or
  * socket.c - functions to handle low level socket interactions with a
  *            MythTV frontend.  
  */
-#include <sys/types.h>
 #include <stdlib.h>
-#ifndef _MSC_VER
-#include <unistd.h>
-#include <sys/socket.h>
-#endif
 #include <stdio.h>
-#include <string.h>
 #include <ctype.h>
+#include <string.h>
 #include <errno.h>
+#include <sys/types.h>
 #include <cmyth_local.h>
 
 #define __UNSIGNED     "0123456789"
@@ -367,7 +363,7 @@ cmyth_rcv_string(cmyth_conn_t conn, int *err, char *buf, int buflen, int count)
                        }
                }
 
-               if (conn->conn_buf[conn->conn_pos] == *state) {
+               if (conn->conn_buf[conn->conn_pos] == (unsigned char)*state) {
                        /*
                         * We matched the next (possibly first) step
                         * of a separator, advance to the next.
@@ -460,7 +456,7 @@ cmyth_rcv_ulong(cmyth_conn_t conn, int *err, unsigned long *buf,
        int consumed;
        int tmp;
 
-  *buf = 0;
+       *buf = 0;
 
        if (!err) {
                err = &tmp;
@@ -836,7 +832,7 @@ cmyth_rcv_short(cmyth_conn_t conn, int *err, short *buf, int count)
 }
 
 /*
- * cmyth_rcv_long_long(cmyth_conn_t conn, int *err, long long *buf, int count)
+ * cmyth_rcv_old_int64(cmyth_conn_t conn, int *err, long long *buf, int count)
  * 
  * Scope: PRIVATE (mapped to __cmyth_rcv_long)
  *
@@ -867,9 +863,9 @@ cmyth_rcv_short(cmyth_conn_t conn, int *err, short *buf, int count)
  * EINVAL       The token received is not numeric
  */
 int
-cmyth_rcv_long_long(cmyth_conn_t conn, int *err, long long *buf, int count)
+cmyth_rcv_old_int64(cmyth_conn_t conn, int *err, int64_t *buf, int count)
 {
-       long long val;
+       int64_t val;
        int consumed;
        int tmp;
        unsigned long hi, lo;
@@ -883,45 +879,138 @@ cmyth_rcv_long_long(cmyth_conn_t conn, int *err, long long *buf, int count)
                return 0;
        }
 
-       if (conn->conn_version >= 66) {
-               /*
-                * Since protocol 66 mythbackend now sends a single 64 bit integer rather than two hi and lo
-                * 32 bit integers for ALL 64 bit values.
-                */
-               consumed = cmyth_rcv_int64(conn, err, &val, count);
-               if (*err) {
-                       cmyth_dbg(CMYTH_DBG_ERROR,
-                                 "%s: cmyth_rcv_int64() failed (%d)\n",
-                                 __FUNCTION__, consumed);
-                       return consumed;
-               }
+       consumed = cmyth_rcv_u_long(conn, err, &hi, count);
+       if (*err) {
+               cmyth_dbg(CMYTH_DBG_ERROR,
+                         "%s: cmyth_rcv_u_long() failed (%d)\n",
+                         __FUNCTION__, consumed);
+               return consumed;
        }
-       else {
-               consumed = cmyth_rcv_u_long(conn, err, &hi, count);
-               if (*err) {
+       consumed += cmyth_rcv_u_long(conn, err, &lo, count-consumed);
+       if (*err) {
+               cmyth_dbg(CMYTH_DBG_ERROR,
+                         "%s: cmyth_rcv_u_long() failed (%d)\n",
+                         __FUNCTION__, consumed);
+               return consumed;
+       }
+       val = (((long long)hi) << 32) | ((long long)(lo & 0xFFFFFFFF));
+
+       *err = 0;
+       *buf = val;
+
+       return consumed;
+}
+
+/*
+ * cmyth_rcv_new_int64(cmyth_conn_t conn, int *err, long long *buf, int count)
+ *
+ * Scope: PRIVATE (mapped to __cmyth_rcv_long)
+ *
+ * Description
+ *
+ * Receive a long long (signed 64 bit) integer token from a list of tokens
+ * in a MythTV Protocol message.  Tokens in MythTV Protocol messages
+ * are separated by the string: []:[] or terminated by running out of
+ * message.  Up to 'count' Bytes will be consumed from the socket
+ * specified by 'conn' (stopping when a separator is seen or 'count'
+ * is exhausted).  The long integer value of the token is placed in
+ * the location pointed to by 'buf'.  If an error is encountered and
+ * 'err' is not NULL, an indication of the nature of the error will be
+ * recorded by placing an error code in the location pointed to by
+ * 'err'.  If all goes well, 'err' wil be set to 0.
+ *
+ * As of protocol version 57, Myth now sends a single 64bit string instead
+ * of 2 32bit strings when sending proginfo data.  This does not seem to
+ * apply uniformly though. For instance 'ANN FILETRANSFER' still uses
+ * the old method
+ *
+ * Return Value:
+ *
+ * A value >=0 indicating the number of bytes consumed.
+ *
+ * Error Codes:
+ *
+ * In addition to system call error codes, the following errors may be
+ * placed in 'err':
+ *
+ * ERANGE       The token received is too large to fit in a long integer
+ *
+ * EINVAL       The token received is not numeric
+ */
+int
+cmyth_rcv_new_int64(cmyth_conn_t conn, int *err, int64_t *buf, int count,
+                   int forced)
+{
+       char num[32];
+       char *num_p = num;
+       unsigned long long val = 0;
+       int sign = 1;
+       long long limit = 0x7fffffffffffffffLL;
+       int consumed;
+       int tmp;
+
+       /*
+        * Between protocols 57 and 66, not all messages used the new
+        * format for 64-bit values.
+        */
+       if ((conn->conn_version < 57) ||
+           ((conn->conn_version < 66) && !forced)) {
+               return cmyth_rcv_old_int64(conn, err, buf, count);
+       }
+
+       if (!err) {
+               err = &tmp;
+       }
+       if (count <= 0) {
+               *err = EINVAL;
+               return 0;
+       }
+       *err = 0;
+       consumed = cmyth_rcv_string(conn, err, num, sizeof(num), count);
+       if (*err) {
+               cmyth_dbg(CMYTH_DBG_ERROR,
+                       "%s: cmyth_rcv_string() failed (%d)\n",
+                       __FUNCTION__, consumed);
+               return consumed;
+       }
+       if (*num_p && (*num_p == '-')) {
+               ++num_p;
+               sign = -1;
+       }
+       while (*num_p) {
+               if (!isdigit(*num_p)) {
                        cmyth_dbg(CMYTH_DBG_ERROR,
-                                 "%s: cmyth_rcv_u_long_long() failed (%d)\n",
-                                 __FUNCTION__, consumed);
+                                 "%s: received illegal integer: '%s'\n",
+                                 __FUNCTION__, num);
+                       *err = EINVAL;
                        return consumed;
                }
-               consumed += cmyth_rcv_u_long(conn, err, &lo, count-consumed);
-               if (*err) {
+               val *= 10;
+               val += ((*num_p) - '0');
+               /*
+                * Check and make sure we are still under the limit (this is
+                * an absolute value limit, sign will be applied later).
+                */
+               if (val > (unsigned long long)limit) {
                        cmyth_dbg(CMYTH_DBG_ERROR,
-                                 "%s: cmyth_rcv_u_long_long() failed (%d)\n",
-                                 __FUNCTION__, consumed);
+                                 "%s: long long out of range: '%s'\n",
+                                 __FUNCTION__, num, limit);
+                       *err = ERANGE;
                        return consumed;
                }
-               val = (((long long)hi) << 32) | ((long long)(lo & 0xFFFFFFFF));
+               num_p++;
        }
 
-       *err = 0;
-       *buf = val;
+       /*
+        * Got a result, return it.
+        */
+       *buf = (long long)(sign * val);
 
        return consumed;
 }
 
 /*
- * cmyth_rcv_int64(cmyth_conn_t conn, int *err, long long *buf, int count)
+ * cmyth_rcv_new_uint64(cmyth_conn_t conn, int *err, uint64_t *buf, int count)
  *
  * Scope: PRIVATE (mapped to __cmyth_rcv_long)
  *
@@ -957,16 +1046,26 @@ cmyth_rcv_long_long(cmyth_conn_t conn, int *err, long long *buf, int count)
  * EINVAL       The token received is not numeric
  */
 int
-cmyth_rcv_int64(cmyth_conn_t conn, int *err, long long *buf, int count)
+cmyth_rcv_new_uint64(cmyth_conn_t conn, int *err, uint64_t *buf, int count,
+                    int forced)
 {
        char num[32];
        char *num_p = num;
-       unsigned long long val = 0;
+       uint64_t val = 0;
        int sign = 1;
        long long limit = 0x7fffffffffffffffLL;
        int consumed;
        int tmp;
 
+       /*
+        * Between protocols 57 and 66, not all messages used the new
+        * format for 64-bit values.
+        */
+       if ((conn->conn_version < 57) ||
+           ((conn->conn_version < 66) && !forced)) {
+               return cmyth_rcv_old_uint64(conn, err, buf, count);
+       }
+
        if (!err) {
                err = &tmp;
        }
@@ -1183,16 +1282,14 @@ cmyth_rcv_ushort(cmyth_conn_t conn, int *err, unsigned short *buf, int count)
  * EINVAL       The token received is not numeric or is signed
  */
 int
-cmyth_rcv_ulong_long(cmyth_conn_t conn, int *err,
-                    unsigned long long *buf, int count)
+cmyth_rcv_old_uint64(cmyth_conn_t conn, int *err, uint64_t *buf, int count)
 {
        unsigned long long val;
-       long long val64;
        unsigned long hi, lo;
        int consumed;
        int tmp;
 
-  *buf = 0;
+       *buf = 0;
 
        if (!err) {
                err = &tmp;
@@ -1203,44 +1300,22 @@ cmyth_rcv_ulong_long(cmyth_conn_t conn, int *err,
                return 0;
        }
        
-       if (conn->conn_version >= 66) {
-               /*
-                * Since protocol 66 mythbackend now sends a single 64 bit integer rather than two hi and lo
-                * 32 bit integers for ALL 64 bit values.
-                */
-               consumed = cmyth_rcv_int64(conn, err, &val64, count);
-               if (*err) {
-                       cmyth_dbg(CMYTH_DBG_ERROR,
-                                 "%s: cmyth_rcv_int64() failed (%d)\n",
-                                 __FUNCTION__, consumed);
-                       return consumed;
-               }
-               if (val64 < 0) {
-                       cmyth_dbg(CMYTH_DBG_ERROR,
-                                 "%s: cmyth_rcv_int64() failed as signed 64 bit integer received\n",
-                                 __FUNCTION__, consumed);
-                       *err = EINVAL;
-                       return consumed;
-               }
-               val = (unsigned long long)val64;
+       consumed = cmyth_rcv_u_long(conn, err, &hi, count);
+       if (*err) {
+               cmyth_dbg(CMYTH_DBG_ERROR,
+                         "%s: cmyth_rcv_u_long() failed (%d)\n",
+                         __FUNCTION__, consumed);
+               return consumed;
        }
-       else {
-               consumed = cmyth_rcv_u_long(conn, err, &hi, count);
-               if (*err) {
-                       cmyth_dbg(CMYTH_DBG_ERROR,
-                                 "%s: cmyth_rcv_u_long_long() failed (%d)\n",
-                                 __FUNCTION__, consumed);
-                       return consumed;
-               }
-               consumed += cmyth_rcv_u_long(conn, err, &lo, count);
-               if (*err) {
-                       cmyth_dbg(CMYTH_DBG_ERROR,
-                                 "%s: cmyth_rcv_u_long_long() failed (%d)\n",
-                                 __FUNCTION__, consumed);
-                       return consumed;
-               }
-               val = (((unsigned long long)hi) << 32) | ((unsigned long long)(lo & 0xFFFFFFFF));
+       consumed += cmyth_rcv_u_long(conn, err, &lo, count - consumed);
+       if (*err) {
+               cmyth_dbg(CMYTH_DBG_ERROR,
+                         "%s: cmyth_rcv_u_long() failed (%d)\n",
+                         __FUNCTION__, consumed);
+               return consumed;
        }
+       val = (((unsigned long long)hi) << 32) | ((unsigned long long)(lo & 0xFFFFFFFF));
+
        *err = 0;
        *buf = val;
 
@@ -1446,7 +1521,7 @@ cmyth_proginfo_parse_url(cmyth_proginfo_t p)
        }
 
     out:
-       if (host && port) {
+       if (host && port && path) {
                char tmp = *(port - 1);
                *(port - 1) = '\0';
                if (p->proginfo_host)
@@ -1508,7 +1583,6 @@ cmyth_rcv_proginfo(cmyth_conn_t conn, int *err, cmyth_proginfo_t buf,
        int total = 0;
        char *failed = NULL;
        char tmp_str[32768];
-       int (*rcv_64)(cmyth_conn_t, int *, long long *, int);
 
        if (count <= 0) {
                *err = EINVAL;
@@ -1521,15 +1595,6 @@ cmyth_rcv_proginfo(cmyth_conn_t conn, int *err, cmyth_proginfo_t buf,
        cmyth_dbg(CMYTH_DBG_DEBUG, "%s: VERSION IS %ld\n",
                  __FUNCTION__, buf->proginfo_version);
 
-       if (buf->proginfo_version >= 57) {
-               /*
-                * Since protocol 57 mythbackend now sends a single 64 bit integer rather than two 32 bit
-                * hi and lo integers for the proginfo length.
-                */
-               rcv_64 = &cmyth_rcv_int64;
-       } else {
-               rcv_64 = &cmyth_rcv_long_long;
-       }
        /*
         * Get proginfo_title (string)
         */
@@ -1707,7 +1772,18 @@ cmyth_rcv_proginfo(cmyth_conn_t conn, int *err, cmyth_proginfo_t buf,
        /*
         * Get proginfo_Length (long_long)
         */
-       consumed = rcv_64(conn, err, &buf->proginfo_Length, count);
+       if (buf->proginfo_version < 57) {
+               consumed = cmyth_rcv_old_int64(conn, err, &buf->proginfo_Length,
+                                              count);
+       } else {
+               /*
+                * Since protocol 57 mythbackend now sends a single 64 bit
+                * integer rather than two 32 bit hi and lo integers for the
+                * proginfo length.
+                */
+               consumed = cmyth_rcv_new_int64(conn, err, &buf->proginfo_Length,
+                                              count, 1);
+       }
        count -= consumed;
        total += consumed;
        if (*err) {
@@ -2269,31 +2345,30 @@ cmyth_rcv_proginfo(cmyth_conn_t conn, int *err, cmyth_proginfo_t buf,
                        failed = "cmyth_rcv_ulong subtitletype";
                        goto fail;
                }
-       }
-  if (buf->proginfo_version >= 41) {
-               /*
-               * Get proginfo_prodyear (string)
-               */
-               consumed = cmyth_rcv_string(conn, err,
-                                                       tmp_str, sizeof(tmp_str) - 1, count);
+       }       
+
+       /*
+        * Get Year
+        */
+       if (buf->proginfo_version >= 43) {
+               consumed = cmyth_rcv_ushort(conn, err, &buf->proginfo_year,
+                                               count);
                count -= consumed;
                total += consumed;
                if (*err) {
-                       failed = "cmyth_rcv_string";
+                       failed = "cmyth_rcv_ushort proginfo_year";
                        goto fail;
                }
-               if (buf->proginfo_prodyear)
-                       ref_release(buf->proginfo_prodyear);
-               buf->proginfo_prodyear = ref_strdup(tmp_str);
-  }
+       }
+
        cmyth_dbg(CMYTH_DBG_INFO, "%s: got recording info\n", __FUNCTION__);
 
        cmyth_proginfo_parse_url(buf);
        return total;
 
     fail:
-       cmyth_dbg(CMYTH_DBG_ERROR, "%s: %s() failed (%d)\n",
-                 __FUNCTION__, failed, *err);
+       cmyth_dbg(CMYTH_DBG_ERROR, "%s: %s() failed (%d) (count = %d)\n",
+                 __FUNCTION__, failed, *err, count);
        return total;
 }
 
@@ -2560,8 +2635,8 @@ cmyth_rcv_chaninfo(cmyth_conn_t conn, int *err, cmyth_proginfo_t buf,
        return total;
 
     fail:
-       cmyth_dbg(CMYTH_DBG_ERROR, "%s: %s() failed (%d)\n",
-                 __FUNCTION__, failed, *err);
+       cmyth_dbg(CMYTH_DBG_ERROR, "%s: %s() failed (%d) (count = %d)\n",
+                 __FUNCTION__, failed, *err, count);
        return total;
 }
 
@@ -2890,7 +2965,7 @@ cmyth_rcv_data(cmyth_conn_t conn, int *err, unsigned char *buf, int count)
                *err = EINVAL;
                return 0;
        }
-       err = 0;
+       *err = 0;
        if (!conn) {
                cmyth_dbg(CMYTH_DBG_ERROR, "%s: no connection\n",
                          __FUNCTION__);
index 43e94c5..e19e37a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2004-2006, Eric Lund
+ *  Copyright (C) 2004-2010, Eric Lund
  *  http://www.mvpmc.org/
  *
  *  This library is free software; you can redistribute it and/or
  *               and cmyth_timestamp_t and between time_t and
  *               cmyth_timestamp_t.
  */
-#include <sys/types.h>
 #include <stdlib.h>
-#ifndef _MSC_VER
-#include <unistd.h>
-#endif
-#include <ctype.h>
 #include <stdio.h>
+#include <ctype.h>
 #include <errno.h>
 #include <string.h>
 #include <cmyth_local.h>
-#include <time.h>
-
 
 /*
  * cmyth_timestamp_create(void)
index f7338fa..50b09a7 100644 (file)
@@ -30,7 +30,7 @@
 
 #include "debug.h"
 
-static mvp_debug_ctx_t refmem_debug_ctx = MVP_DEBUG_CTX_INIT("refmem",
+static cmyth_debug_ctx_t refmem_debug_ctx = CMYTH_DEBUG_CTX_INIT("refmem",
                                                             REF_DBG_NONE,
                                                             NULL);
 /*
@@ -51,7 +51,7 @@ static mvp_debug_ctx_t refmem_debug_ctx = MVP_DEBUG_CTX_INIT("refmem",
 void
 refmem_dbg_level(int l)
 {
-       mvp_dbg_setlevel(&refmem_debug_ctx, l);
+       __cmyth_dbg_setlevel(&refmem_debug_ctx, l);
 }
 
 /*
@@ -70,7 +70,7 @@ refmem_dbg_level(int l)
 void
 refmem_dbg_all()
 {
-       mvp_dbg_setlevel(&refmem_debug_ctx, REF_DBG_ALL);
+       __cmyth_dbg_setlevel(&refmem_debug_ctx, REF_DBG_ALL);
 }
 
 /*
@@ -89,7 +89,7 @@ refmem_dbg_all()
 void
 refmem_dbg_none()
 {
-       mvp_dbg_setlevel(&refmem_debug_ctx, REF_DBG_NONE);
+       __cmyth_dbg_setlevel(&refmem_debug_ctx, REF_DBG_NONE);
 }
 
 /*
@@ -113,6 +113,6 @@ refmem_dbg(int level, char *fmt, ...)
        va_list ap;
 
        va_start(ap, fmt);
-       mvp_dbg(&refmem_debug_ctx, level, fmt, ap);
+       __cmyth_dbg(&refmem_debug_ctx, level, fmt, ap);
        va_end(ap);
 }
index e077c24..7c4d21c 100644 (file)
@@ -60,7 +60,6 @@
       </PrecompiledHeader>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
-      <CompileAs>CompileAsC</CompileAs>
     </ClCompile>
     <Link>
       <AdditionalDependencies>libexpat.lib;%(AdditionalDependencies)</AdditionalDependencies>
index a25ee79..931ac23 100644 (file)
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unicode Release|Win32'" Label="Configuration">
     <ConfigurationType>DynamicLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
     <CharacterSet>Unicode</CharacterSet>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
     <ConfigurationType>DynamicLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
     <CharacterSet>MultiByte</CharacterSet>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>DynamicLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
     <CharacterSet>MultiByte</CharacterSet>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unicode Debug|Win32'" Label="Configuration">
     <ConfigurationType>DynamicLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
     <CharacterSet>Unicode</CharacterSet>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
     <ClCompile>
       <Optimization>Disabled</Optimization>
       <AdditionalIncludeDirectories>zlib;zlib\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_WINDOWS;_USRDLL;JAS_WIN_MSVC_BUILD;WIN32;_DEBUG;UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_NON_CONFORMING_SWPRINTFS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;JAS_WIN_MSVC_BUILD;_CRT_SECURE_NO_DEPRECATE;UNICODE;_CRT_NON_CONFORMING_SWPRINTFS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Unicode_Debug/CxImageCrtDll.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Unicode_Debug/</AssemblerListingLocation>
-      <ObjectFileName>.\Unicode_Debug/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Unicode_Debug/</ProgramDataBaseFileName>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\CxImageCrtDll.pch</PrecompiledHeaderOutputFile>
+      <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
+      <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
+      <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
       <WarningLevel>Level3</WarningLevel>
       <SuppressStartupBanner>true</SuppressStartupBanner>
       <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
-      <CompileAs>Default</CompileAs>
+      <ExceptionHandling>Async</ExceptionHandling>
     </ClCompile>
     <ResourceCompile>
       <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
       <SuppressStartupBanner>true</SuppressStartupBanner>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <ProgramDatabaseFile>.\Unicode_Debug/cximagecrtdu.pdb</ProgramDatabaseFile>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
+      <ProgramDatabaseFile>$(Configuration)\vs2010\ImageLib.pdb</ProgramDatabaseFile>
       <DataExecutionPrevention>
       </DataExecutionPrevention>
-      <ImportLibrary>.\Unicode_Debug/cximagecrtdu.lib</ImportLibrary>
+      <ImportLibrary>$(Configuration)\vs2010\cximagecrtd.lib</ImportLibrary>
       <TargetMachine>MachineX86</TargetMachine>
     </Link>
     <CustomBuildStep>
       <WarningLevel>Level3</WarningLevel>
       <SuppressStartupBanner>true</SuppressStartupBanner>
       <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
-      <CompileAs>Default</CompileAs>
     </ClCompile>
     <ResourceCompile>
       <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <SuppressStartupBanner>true</SuppressStartupBanner>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <ProgramDatabaseFile>$(Configuration)\vs2010\ImageLib.pdb</ProgramDatabaseFile>
-      <RandomizedBaseAddress>true</RandomizedBaseAddress>
       <DataExecutionPrevention>
       </DataExecutionPrevention>
       <ImportLibrary>$(Configuration)\vs2010\cximagecrtd.lib</ImportLibrary>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
       <WarningLevel>Level3</WarningLevel>
       <SuppressStartupBanner>true</SuppressStartupBanner>
-      <CompileAs>Default</CompileAs>
     </ClCompile>
     <ResourceCompile>
       <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ProgramDatabaseFile>$(Configuration)\vs2010\cximagecrt.pdb</ProgramDatabaseFile>
       <OptimizeReferences>true</OptimizeReferences>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <RandomizedBaseAddress>true</RandomizedBaseAddress>
       <DataExecutionPrevention>
       </DataExecutionPrevention>
       <ImportLibrary>$(Configuration)\vs2010\cximagecrt.lib</ImportLibrary>
       <Optimization>MaxSpeed</Optimization>
       <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
       <AdditionalIncludeDirectories>zlib;zlib\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_WINDOWS;_USRDLL;JAS_WIN_MSVC_BUILD;WIN32;NDEBUG;UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_NON_CONFORMING_SWPRINTFS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;JAS_WIN_MSVC_BUILD;_CRT_SECURE_NO_DEPRECATE;UNICODE;_CRT_NON_CONFORMING_SWPRINTFS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Unicode_Release/CxImageCrtDll.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Unicode_Release/</AssemblerListingLocation>
-      <ObjectFileName>.\Unicode_Release/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Unicode_Release/</ProgramDataBaseFileName>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\CxImageCrtDll.pch</PrecompiledHeaderOutputFile>
+      <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
+      <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
+      <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
       <WarningLevel>Level3</WarningLevel>
       <SuppressStartupBanner>true</SuppressStartupBanner>
-      <CompileAs>Default</CompileAs>
+      <ExceptionHandling>Async</ExceptionHandling>
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
+      <BufferSecurityCheck>false</BufferSecurityCheck>
     </ClCompile>
     <ResourceCompile>
       <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
     <Link>
       <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
       <SuppressStartupBanner>true</SuppressStartupBanner>
-      <ProgramDatabaseFile>.\Unicode_Release/cximagecrtu.pdb</ProgramDatabaseFile>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
+      <ProgramDatabaseFile>$(Configuration)\vs2010\ImageLib.pdb</ProgramDatabaseFile>
       <DataExecutionPrevention>
       </DataExecutionPrevention>
-      <ImportLibrary>.\Unicode_Release/cximagecrtu.lib</ImportLibrary>
+      <ImportLibrary>$(Configuration)\vs2010\cximagecrt.lib</ImportLibrary>
       <TargetMachine>MachineX86</TargetMachine>
     </Link>
     <CustomBuildStep>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
-</Project>
+</Project>
\ No newline at end of file
index 26304ee..d798359 100644 (file)
@@ -94,7 +94,6 @@
       <WarningLevel>Level2</WarningLevel>
       <SuppressStartupBanner>true</SuppressStartupBanner>
       <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
-      <CompileAs>Default</CompileAs>
     </ClCompile>
     <ResourceCompile>
       <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
       <WarningLevel>Level2</WarningLevel>
       <SuppressStartupBanner>true</SuppressStartupBanner>
-      <CompileAs>Default</CompileAs>
       <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
     </ClCompile>
     <ResourceCompile>
       <Optimization>MaxSpeed</Optimization>
       <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
       <AdditionalIncludeDirectories>.\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_LIB;JAS_WIN_MSVC_BUILD;WIN32;NDEBUG;UNICODE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>NDEBUG;WIN32;_LIB;JAS_WIN_MSVC_BUILD;_CRT_SECURE_NO_DEPRECATE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Unicode_Release/jasper.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Unicode_Release/</AssemblerListingLocation>
-      <ObjectFileName>.\Unicode_Release/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Unicode_Release/</ProgramDataBaseFileName>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\jasper.pch</PrecompiledHeaderOutputFile>
+      <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
+      <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
+      <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
       <WarningLevel>Level2</WarningLevel>
       <SuppressStartupBanner>true</SuppressStartupBanner>
-      <CompileAs>Default</CompileAs>
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
     </ClCompile>
     <ResourceCompile>
       <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
     <ClCompile>
       <Optimization>Disabled</Optimization>
       <AdditionalIncludeDirectories>.\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_LIB;JAS_WIN_MSVC_BUILD;WIN32;_DEBUG;UNICODE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>_DEBUG;WIN32;_LIB;JAS_WIN_MSVC_BUILD;_CRT_SECURE_NO_DEPRECATE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Unicode_Debug/jasper.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Unicode_Debug/</AssemblerListingLocation>
-      <ObjectFileName>.\Unicode_Debug/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Unicode_Debug/</ProgramDataBaseFileName>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\jasper.pch</PrecompiledHeaderOutputFile>
+      <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
+      <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
+      <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
       <WarningLevel>Level2</WarningLevel>
       <SuppressStartupBanner>true</SuppressStartupBanner>
       <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
-      <CompileAs>Default</CompileAs>
     </ClCompile>
     <ResourceCompile>
       <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
index dfe2c0c..8a9078c 100644 (file)
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unicode Debug|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
     <CharacterSet>Unicode</CharacterSet>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unicode Release|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
     <CharacterSet>Unicode</CharacterSet>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
@@ -88,7 +84,7 @@
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Release/jbig.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\jbig.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
     <ClCompile>
       <Optimization>MaxSpeed</Optimization>
       <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
-      <PreprocessorDefinitions>_LIB;WIN32;NDEBUG;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Unicode_Release/jbig.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\jbig.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
       <WarningLevel>Level3</WarningLevel>
       <SuppressStartupBanner>true</SuppressStartupBanner>
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
     </ClCompile>
     <ResourceCompile>
       <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Debug/jbig.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\jbig.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Unicode Debug|Win32'">
     <ClCompile>
       <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>_LIB;WIN32;_DEBUG;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Unicode_Debug/jbig.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\jbig.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
index 4a80cc4..d4c8da4 100644 (file)
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unicode Debug|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
     <CharacterSet>Unicode</CharacterSet>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unicode Release|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
     <CharacterSet>Unicode</CharacterSet>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
     <ClCompile>
       <Optimization>MaxSpeed</Optimization>
       <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
-      <PreprocessorDefinitions>_WINDOWS;WIN32;NDEBUG;UNICODE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Unicode_Release/jpeg.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\jpeg.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
       <WarningLevel>Level3</WarningLevel>
       <SuppressStartupBanner>true</SuppressStartupBanner>
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
     </ClCompile>
     <ResourceCompile>
       <Culture>0x0809</Culture>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Unicode Debug|Win32'">
     <ClCompile>
       <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>_WINDOWS;WIN32;_DEBUG;UNICODE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Unicode_Debug/jpeg.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\jpeg.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
       <Optimization>Disabled</Optimization>
       <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Debug/jpeg.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\jpeg.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Release/jpeg.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\jpeg.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
index dfa1bc9..41fc8c3 100644 (file)
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unicode Debug|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
     <CharacterSet>Unicode</CharacterSet>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unicode Release|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
     <CharacterSet>Unicode</CharacterSet>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
@@ -88,7 +84,7 @@
       <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;MNG_SUPPORT_DISPLAY;MNG_SUPPORT_READ;MNG_SUPPORT_WRITE;MNG_ACCESS_CHUNKS;MNG_STORE_CHUNKS;_CRT_SECURE_NO_DEPRECATE;MNG_ERROR_TELLTALE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Debug/mng.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\mng.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
       <Optimization>MaxSpeed</Optimization>
       <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
       <AdditionalIncludeDirectories>..\zlib\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;MNG_SUPPORT_DISPLAY;MNG_SUPPORT_READ;MNG_SUPPORT_WRITE;MNG_ACCESS_CHUNKS;MNG_STORE_CHUNKS;UNICODE;_CRT_SECURE_NO_DEPRECATE;MNG_ERROR_TELLTALE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;MNG_SUPPORT_DISPLAY;MNG_SUPPORT_READ;MNG_SUPPORT_WRITE;MNG_ACCESS_CHUNKS;MNG_STORE_CHUNKS;_CRT_SECURE_NO_DEPRECATE;MNG_ERROR_TELLTALE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Unicode_Release/mng.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\mng.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
       <WarningLevel>Level3</WarningLevel>
       <SuppressStartupBanner>true</SuppressStartupBanner>
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
     </ClCompile>
     <ResourceCompile>
       <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
     <ClCompile>
       <Optimization>Disabled</Optimization>
       <AdditionalIncludeDirectories>..\zlib\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;MNG_SUPPORT_DISPLAY;MNG_SUPPORT_READ;MNG_SUPPORT_WRITE;MNG_ACCESS_CHUNKS;MNG_STORE_CHUNKS;UNICODE;_CRT_SECURE_NO_DEPRECATE;MNG_ERROR_TELLTALE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;MNG_SUPPORT_DISPLAY;MNG_SUPPORT_READ;MNG_SUPPORT_WRITE;MNG_ACCESS_CHUNKS;MNG_STORE_CHUNKS;_CRT_SECURE_NO_DEPRECATE;MNG_ERROR_TELLTALE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Unicode_Debug/mng.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\mng.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Release/mng.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\mng.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
index 01d5c90..fefaf43 100644 (file)
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unicode Debug|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
     <CharacterSet>Unicode</CharacterSet>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unicode Release|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
     <CharacterSet>Unicode</CharacterSet>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
       <AdditionalIncludeDirectories>..\zlib;..\zlib\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Debug/png.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\png.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
       <WarningLevel>Level3</WarningLevel>
       <SuppressStartupBanner>true</SuppressStartupBanner>
       <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
-      <CompileAs>Default</CompileAs>
     </ClCompile>
     <ResourceCompile>
       <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <Optimization>MaxSpeed</Optimization>
       <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
       <AdditionalIncludeDirectories>..\zlib;..\zlib\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_WINDOWS;WIN32;NDEBUG;UNICODE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Unicode_Release/png.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\png.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
       <WarningLevel>Level3</WarningLevel>
       <SuppressStartupBanner>true</SuppressStartupBanner>
-      <CompileAs>Default</CompileAs>
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
     </ClCompile>
     <ResourceCompile>
       <Culture>0x0809</Culture>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Release/png.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\png.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
       <WarningLevel>Level3</WarningLevel>
       <SuppressStartupBanner>true</SuppressStartupBanner>
-      <CompileAs>Default</CompileAs>
       <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
     </ClCompile>
     <ResourceCompile>
     <ClCompile>
       <Optimization>Disabled</Optimization>
       <AdditionalIncludeDirectories>..\zlib;..\zlib\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_WINDOWS;WIN32;_DEBUG;UNICODE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Unicode_Debug/png.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\png.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
       <WarningLevel>Level3</WarningLevel>
       <SuppressStartupBanner>true</SuppressStartupBanner>
       <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
-      <CompileAs>Default</CompileAs>
     </ClCompile>
     <ResourceCompile>
       <Culture>0x0809</Culture>
index 7af2a9f..ec0a465 100644 (file)
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unicode Debug|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
     <CharacterSet>Unicode</CharacterSet>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unicode Release|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
     <CharacterSet>Unicode</CharacterSet>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
@@ -88,7 +84,7 @@
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Release/libdcr.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\libdcr.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
       <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Debug/libdcr.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\libdcr.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
     <ClCompile>
       <Optimization>MaxSpeed</Optimization>
       <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;UNICODE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Unicode_Release/libdcr.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\libdcr.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
       <WarningLevel>Level3</WarningLevel>
       <SuppressStartupBanner>true</SuppressStartupBanner>
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
     </ClCompile>
     <ResourceCompile>
       <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Unicode Debug|Win32'">
     <ClCompile>
       <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;UNICODE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Unicode_Debug/libdcr.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\libdcr.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
index 1b1f4a8..add003c 100644 (file)
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unicode Debug|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
     <CharacterSet>Unicode</CharacterSet>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unicode Release|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
     <CharacterSet>Unicode</CharacterSet>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
@@ -88,7 +84,7 @@
       <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Debug/Tiff.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\Tiff.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Release/Tiff.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\Tiff.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
       <Optimization>MinSpace</Optimization>
       <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
       <AdditionalIncludeDirectories>..\zlib;..\zlib\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_LIB;WIN32;NDEBUG;UNICODE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Unicode_Release/Tiff.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\Tiff.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
       <WarningLevel>Level3</WarningLevel>
       <SuppressStartupBanner>true</SuppressStartupBanner>
       <CompileAs>Default</CompileAs>
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
     </ClCompile>
     <ResourceCompile>
       <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
     <ClCompile>
       <Optimization>Disabled</Optimization>
       <AdditionalIncludeDirectories>..\zlib;..\zlib\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_LIB;WIN32;_DEBUG;UNICODE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Unicode_Debug/Tiff.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\Tiff.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
index 48adf33..91e99aa 100644 (file)
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unicode Debug|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
     <CharacterSet>Unicode</CharacterSet>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unicode Release|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
     <CharacterSet>Unicode</CharacterSet>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
@@ -77,8 +73,6 @@
     <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)objs\$(TargetName)\$(Configuration)\</IntDir>
     <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)libs\$(TargetName)\$(Configuration)\</OutDir>
     <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)objs\$(TargetName)\$(Configuration)\</IntDir>
-    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(DXSDK_DIR)Include;$(IncludePath)</IncludePath>
-    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(DXSDK_DIR)Lib\x86;$(LibraryPath)</LibraryPath>
     <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">zlib</TargetName>
     <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">zlib</TargetName>
     <TargetName Condition="'$(Configuration)|$(Platform)'=='Unicode Debug|Win32'">zlib</TargetName>
       <Optimization>MaxSpeed</Optimization>
       <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
       <AdditionalIncludeDirectories>..\zlib\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_WINDOWS;WIN32;NDEBUG;UNICODE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Unicode_Release/zlib.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\zlib.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
       <WarningLevel>Level3</WarningLevel>
       <SuppressStartupBanner>true</SuppressStartupBanner>
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
     </ClCompile>
     <ResourceCompile>
       <Culture>0x0809</Culture>
     <ClCompile>
       <Optimization>Disabled</Optimization>
       <AdditionalIncludeDirectories>..\zlib\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_WINDOWS;WIN32;_DEBUG;UNICODE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Unicode_Debug/zlib.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\zlib.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
       <AdditionalIncludeDirectories>..\zlib\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Debug/zlib.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\zlib.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Release/zlib.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\zlib.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
index 3c7aced..8a3c90e 100644 (file)
       <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
       <PrecompiledHeader>
       </PrecompiledHeader>
-      <PrecompiledHeaderOutputFile>$(OutDir)$(ProjectName).pch</PrecompiledHeaderOutputFile>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
       <CompileAs>Default</CompileAs>
     <ClCompile>
       <Optimization>Full</Optimization>
       <OmitFramePointers>true</OmitFramePointers>
-      <PreprocessorDefinitions>NDEBUG;_XBOX;PROFILE;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>NDEBUG;_WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;PROFILE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
       <PrecompiledHeader>
       </PrecompiledHeader>
-      <PrecompiledHeaderOutputFile>$(OutDir)$(ProjectName).pch</PrecompiledHeaderOutputFile>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
     </ClCompile>
     <ClCompile>
       <Optimization>Full</Optimization>
       <OmitFramePointers>true</OmitFramePointers>
-      <PreprocessorDefinitions>NDEBUG;_XBOX;PROFILE;FASTCAP;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>NDEBUG;_WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;PROFILE;FASTCAP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
       <PrecompiledHeader>
       </PrecompiledHeader>
-      <PrecompiledHeaderOutputFile>$(OutDir)$(ProjectName).pch</PrecompiledHeaderOutputFile>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
     </ClCompile>
       <RuntimeTypeInfo>true</RuntimeTypeInfo>
       <PrecompiledHeader>
       </PrecompiledHeader>
-      <PrecompiledHeaderOutputFile>$(OutDir)$(ProjectName).pch</PrecompiledHeaderOutputFile>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>
       </DebugInformationFormat>
     <ClCompile>
       <Optimization>Full</Optimization>
       <OmitFramePointers>true</OmitFramePointers>
-      <PreprocessorDefinitions>NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>NDEBUG;_WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
       <PrecompiledHeader>
       </PrecompiledHeader>
-      <PrecompiledHeaderOutputFile>$(OutDir)$(ProjectName).pch</PrecompiledHeaderOutputFile>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
     </ClCompile>
index 5d2aa80..cbbc77a 100644 (file)
       <MinimalRebuild>true</MinimalRebuild>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <PrecompiledHeader>
-      </PrecompiledHeader>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
-      <CompileAs>CompileAsC</CompileAs>
     </ClCompile>
     <Lib>
       <OutputFile>$(OutDir)$(TargetFileName)</OutputFile>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <BufferSecurityCheck>false</BufferSecurityCheck>
       <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeader>
-      </PrecompiledHeader>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>
       </DebugInformationFormat>
-      <CompileAs>CompileAsC</CompileAs>
       <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
     </ClCompile>
     <Lib>
index 1f631b9..2be4dbc 100644 (file)
@@ -59,7 +59,6 @@
     </ClCompile>
     <Lib>
       <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
-      <IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
     </Lib>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
index fc341b2..4d4e17a 100644 (file)
@@ -55,7 +55,7 @@
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <ClCompile>
       <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>.\;..\..\..\enca\lib</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>.\;..\..\..\enca\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBASS_WIN32_EXPORTS;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <MinimalRebuild>true</MinimalRebuild>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
@@ -70,7 +70,7 @@
     <Link>
       <AdditionalDependencies>fontconfig.lib;zlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
-      <IgnoreSpecificDefaultLibraries>LIBCMTD;LIBCMT;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+      <IgnoreSpecificDefaultLibraries>libcmt;libcmtd;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <ProgramDatabaseFile>Debug/libass_win32.pdb</ProgramDatabaseFile>
       <SubSystem>Windows</SubSystem>
index 3c48a98..22feb4a 100644 (file)
       </PrecompiledHeader>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
     </ClCompile>
     <Link>
       <OutputFile>$(OutDir)libexif.exe</OutputFile>
index ddb894f..dcd2cbc 100644 (file)
@@ -66,7 +66,6 @@
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
       <PrecompiledHeader>
       </PrecompiledHeader>
-      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
       <CompileAs>CompileAsCpp</CompileAs>
index 9ee37f6..ffc4f86 100644 (file)
@@ -60,7 +60,6 @@
     </ClCompile>
     <Lib>
       <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
-      <IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
     </Lib>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
index d52e53d..2a9a8e0 100644 (file)
@@ -24,7 +24,7 @@
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
     <ConfigurationType>DynamicLibrary</ConfigurationType>
     <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>NotSet</CharacterSet>
+    <CharacterSet>MultiByte</CharacterSet>
     <WholeProgramOptimization>true</WholeProgramOptimization>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
       <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
       <OmitFramePointers>true</OmitFramePointers>
       <AdditionalIncludeDirectories>../msvc++;../../zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>NDEBUG;WIN32;HAVE_CONFIG_H;_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>HAVE_CONFIG_H;_DLL;WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>false</StringPooling>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <BufferSecurityCheck>false</BufferSecurityCheck>
       <FunctionLevelLinking>false</FunctionLevelLinking>
       <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
       <RuntimeTypeInfo>true</RuntimeTypeInfo>
-      <PrecompiledHeaderOutputFile>.\Release\vs2010\libid3tag.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\libid3tag.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>
       </AssemblerListingLocation>
       <ObjectFileName>
@@ -91,7 +91,8 @@
     </ResourceCompile>
     <Link>
       <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
-      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>
+      </AdditionalLibraryDirectories>
       <SubSystem>Windows</SubSystem>
       <TerminalServerAware>
       </TerminalServerAware>
       <PreprocessorDefinitions>HAVE_CONFIG_H;_DLL;WIN32;_DEBUG;DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Debug\vs2010\libid3tag.pch</PrecompiledHeaderOutputFile>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\libid3tag.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>
       </AssemblerListingLocation>
       <ObjectFileName>
     </ResourceCompile>
     <Link>
       <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
-      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>
+      </AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <ProgramDatabaseFile>$(TargetName).pdb</ProgramDatabaseFile>
       <ProfileGuidedDatabase>
index eb02de7..053624f 100644 (file)
@@ -1,4 +1,4 @@
-LIBRARY  lame_enc.DLL
+LIBRARY  libmp3lame.dll
 EXPORTS
 
 lame_init              @1
index 751fabb..1d0c799 100644 (file)
@@ -84,6 +84,7 @@
       <AdditionalIncludeDirectories>../libmp3lame;../;../mpglib;../include;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>NDEBUG;_WINDOWS;HAVE_MPGLIB;WIN32;HAVE_CONFIG_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
     </ClCompile>
     <ResourceCompile>
       <PreprocessorDefinitions>_VC80_UPGRADE=0x0600;_DLL=$(TargetFileName);%(PreprocessorDefinitions)</PreprocessorDefinitions>
index cc4c33c..426c567 100644 (file)
       <PreprocessorDefinitions>FPM_DEFAULT;_LIB;HAVE_CONFIG_H;ASO_ZEROCHECK;WIN32;_DEBUG;DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-      <PrecompiledHeaderOutputFile>.\Debug/libmad.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
-      <ObjectFileName>.\Debug/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\libmad.pch</PrecompiledHeaderOutputFile>
       <SuppressStartupBanner>true</SuppressStartupBanner>
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <CompileAs>Default</CompileAs>
       <MinimalRebuild>true</MinimalRebuild>
     </ClCompile>
     <ResourceCompile>
       <Optimization>MaxSpeed</Optimization>
       <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
       <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>NDEBUG;FPM_INTEL;WIN32;_LIB;HAVE_CONFIG_H;ASO_ZEROCHECK;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>FPM_INTEL;_LIB;HAVE_CONFIG_H;ASO_ZEROCHECK;WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
-      <PrecompiledHeaderOutputFile>.\Release/libmad.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>.\Release/</AssemblerListingLocation>
-      <ObjectFileName>.\Release/</ObjectFileName>
-      <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
+      <PrecompiledHeaderOutputFile>$(Configuration)\vs2010\libmad.pch</PrecompiledHeaderOutputFile>
       <SuppressStartupBanner>true</SuppressStartupBanner>
-      <CompileAs>Default</CompileAs>
       <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
     </ClCompile>
     <ResourceCompile>
index d4c8802..00effaf 100644 (file)
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
     <ConfigurationType>DynamicLibrary</ConfigurationType>
-    <CharacterSet>NotSet</CharacterSet>
+    <CharacterSet>MultiByte</CharacterSet>
     <WholeProgramOptimization>true</WholeProgramOptimization>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>DynamicLibrary</ConfigurationType>
-    <CharacterSet>NotSet</CharacterSet>
+    <CharacterSet>MultiByte</CharacterSet>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
@@ -57,8 +57,6 @@
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
       <RuntimeTypeInfo>false</RuntimeTypeInfo>
-      <PrecompiledHeader>
-      </PrecompiledHeader>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
     </ClCompile>
@@ -80,8 +78,6 @@
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <RuntimeTypeInfo>false</RuntimeTypeInfo>
-      <PrecompiledHeader>
-      </PrecompiledHeader>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
       <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
index ddfdf94..9ba0fb9 100644 (file)
@@ -70,7 +70,7 @@
     <ClCompile>
       <Optimization>MaxSpeed</Optimization>
       <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
-      <AdditionalIncludeDirectories>../../../builders/resid-builder/include/sidplay/builders;../../../libsidplay/include;../../../libsidplay/include/sidplay;../../include;../../include/sidplay;../../../resid;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>../../../builders/resid-builder/include/sidplay/builders;../../include;../../include/sidplay;../../../resid;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;DLL_EXPORT;HAVE_MSWINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <ExceptionHandling>Sync</ExceptionHandling>
       <PrecompiledHeader>
       </PrecompiledHeader>
       <PrecompiledHeaderOutputFile>$(OutDir)libsidplay.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
-      <ObjectFileName>$(IntDir)</ObjectFileName>
-      <ProgramDataBaseFileName>$(IntDir)</ProgramDataBaseFileName>
       <WarningLevel>Level3</WarningLevel>
       <SuppressStartupBanner>true</SuppressStartupBanner>
-      <CompileAs>Default</CompileAs>
       <DisableSpecificWarnings>4231;4355;4910;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
     </ClCompile>
     <ResourceCompile>
     </Midl>
     <ClCompile>
       <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>../../../builders/resid-builder/include/sidplay/builders;../../../libsidplay/include;../../../libsidplay/include/sidplay;../../include;../../include/sidplay;../../../resid;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>../../../builders/resid-builder/include/sidplay/builders;../../include;../../include/sidplay;../../../resid;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;DLL_EXPORT;HAVE_MSWINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
       <PrecompiledHeader>
       </PrecompiledHeader>
       <PrecompiledHeaderOutputFile>$(OutDir)libsidplay.pch</PrecompiledHeaderOutputFile>
-      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
-      <ObjectFileName>$(IntDir)</ObjectFileName>
-      <ProgramDataBaseFileName>$(IntDir)</ProgramDataBaseFileName>
       <WarningLevel>Level3</WarningLevel>
       <SuppressStartupBanner>true</SuppressStartupBanner>
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <CompileAs>Default</CompileAs>
       <DisableSpecificWarnings>4231;4355;4910;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
-      <XMLDocumentationFileName>$(IntDir)</XMLDocumentationFileName>
       <MinimalRebuild>true</MinimalRebuild>
     </ClCompile>
     <ResourceCompile>
index bc24075..bf2e4dc 100644 (file)
@@ -56,8 +56,6 @@
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
       <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
       <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
-      <PrecompiledHeader>
-      </PrecompiledHeader>
       <WarningLevel>Level4</WarningLevel>
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
     </ClCompile>
@@ -75,8 +73,6 @@
       <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;SQUISH_USE_SSE=2;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
-      <PrecompiledHeader>
-      </PrecompiledHeader>
       <WarningLevel>Level4</WarningLevel>
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
       <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
index 878ce44..d21b7b6 100644 (file)
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <ClCompile>
       <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..\..\..\..\win32\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
       <PrecompiledHeader>
       </PrecompiledHeader>
-      <PrecompiledHeaderOutputFile>.\Debug/StSoundLibrary.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
     <ClCompile>
       <Optimization>MaxSpeed</Optimization>
       <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
-      <AdditionalIncludeDirectories>..\..\..\..\win32\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <PrecompiledHeader>
       </PrecompiledHeader>
-      <PrecompiledHeaderOutputFile>.\Release/StSoundLibrary.pch</PrecompiledHeaderOutputFile>
       <AssemblerListingLocation>$(Configuration)\vs2010\</AssemblerListingLocation>
       <ObjectFileName>$(Configuration)\vs2010\</ObjectFileName>
       <ProgramDataBaseFileName>$(Configuration)\vs2010\</ProgramDataBaseFileName>
index a5a071c..09921d8 100644 (file)
@@ -47,7 +47,7 @@
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <ClCompile>
       <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>.;..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>NO_RECURSE;WIN32;_DEBUG;_LIB;HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_SECURE_SCL=0;_HAS_ITERATOR_DEBUGGING=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <MinimalRebuild>true</MinimalRebuild>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
@@ -68,7 +68,7 @@
       <Optimization>Full</Optimization>
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <WholeProgramOptimization>false</WholeProgramOptimization>
-      <AdditionalIncludeDirectories>.;..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>NO_RECURSE;WIN32;NDEBUG;_LIB;HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
index 919f859..8497687 100644 (file)
     <TargetName Condition="'$(Configuration)|$(Platform)'=='Release (OpenGL)|Win32'">UnrarXLib</TargetName>
     <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release (DirectX)|Win32'">$(DXSDK_DIR)Include;$(IncludePath)</IncludePath>
     <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Release (DirectX)|Win32'">$(DXSDK_DIR)Lib\x86;$(LibraryPath)</LibraryPath>
-    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug (OpenGL)|Win32'">$(DXSDK_DIR)Include;$(IncludePath)</IncludePath>
-    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release (OpenGL)|Win32'">$(DXSDK_DIR)Include;$(IncludePath)</IncludePath>
   </PropertyGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release (OpenGL)|Win32'">
     <ClCompile>
       <AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
       <Optimization>Full</Optimization>
       <OmitFramePointers>true</OmitFramePointers>
-      <AdditionalIncludeDirectories>..\..\guilib;..\..\xbmc;..\..\xbmc\win32\;..\..\lib\win32\boost;..\..\lib\libSDL-WIN32\include</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..\..\xbmc;..\..\xbmc\win32\;</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>TARGET_WINDOWS;NOMINMAX;NDEBUG;WIN32;_LIB;_XBMC;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug (DirectX)|Win32'">
     <ClCompile>
       <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..\..\guilib;..\..\xbmc;..\..\xbmc\win32\;..\..\lib\win32\boost;..\..\lib\libSDL-WIN32\include</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..\..\xbmc;..\..\xbmc\win32\;</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>TARGET_WINDOWS;NOMINMAX;WIN32;_DEBUG;_LIB;_XBMC;_USE_32BIT_TIME_T;HAS_DX;_SECURE_SCL=0;_HAS_ITERATOR_DEBUGGING=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <MinimalRebuild>false</MinimalRebuild>
       <AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
       <Optimization>Full</Optimization>
       <OmitFramePointers>true</OmitFramePointers>
-      <AdditionalIncludeDirectories>..\..\guilib;..\..\xbmc;..\..\xbmc\win32\;..\..\lib\win32\boost;..\..\lib\libSDL-WIN32\include</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..\..\xbmc;..\..\xbmc\win32\;</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>TARGET_WINDOWS;NOMINMAX;NDEBUG;WIN32;_LIB;_XBMC;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug (OpenGL)|Win32'">
     <ClCompile>
       <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..\..\guilib;..\..\xbmc;..\..\xbmc\win32\;..\..\lib\win32\boost;..\..\lib\libSDL-WIN32\include</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..\..\xbmc;..\..\xbmc\win32\;</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>TARGET_WINDOWS;NOMINMAX;WIN32;_DEBUG;_LIB;_XBMC;_USE_32BIT_TIME_T;_SECURE_SCL=0;_HAS_ITERATOR_DEBUGGING=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <MinimalRebuild>false</MinimalRebuild>
index f657d19..8c8a5bf 100644 (file)
     <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
     <OutDir Condition="'$(Configuration)|$(Platform)'=='Release (OpenGL)|Win32'">XBMC\$(Configuration)\</OutDir>
     <IntDir Condition="'$(Configuration)|$(Platform)'=='Release (OpenGL)|Win32'">XBMC\$(Configuration)\objs\</IntDir>
-    <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Release (OpenGL)|Win32'">false</IgnoreImportLibrary>
     <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release (OpenGL)|Win32'">false</LinkIncremental>
     <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug (DirectX)|Win32'">XBMC\$(Configuration)\</OutDir>
     <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug (DirectX)|Win32'">XBMC\$(Configuration)\objs\</IntDir>
-    <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Debug (DirectX)|Win32'">false</IgnoreImportLibrary>
     <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug (DirectX)|Win32'">true</LinkIncremental>
     <OutDir Condition="'$(Configuration)|$(Platform)'=='Release (DirectX)|Win32'">XBMC\$(Configuration)\</OutDir>
     <IntDir Condition="'$(Configuration)|$(Platform)'=='Release (DirectX)|Win32'">XBMC\$(Configuration)\objs\</IntDir>
-    <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Release (DirectX)|Win32'">false</IgnoreImportLibrary>
     <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release (DirectX)|Win32'">false</LinkIncremental>
     <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug (OpenGL)|Win32'">XBMC\$(Configuration)\</OutDir>
     <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug (OpenGL)|Win32'">XBMC\$(Configuration)\objs\</IntDir>
       <InlineFunctionExpansion>Default</InlineFunctionExpansion>
       <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
       <OmitFramePointers>true</OmitFramePointers>
-      <AdditionalIncludeDirectories>..\..\;..\..\xbmc\;..\..\xbmc\win32\;..\..\xbmc\cores\dvdplayer;..\..\lib;..\..\lib\ffmpeg;..\..\lib\ffmpeg\include-xbmc-win32;..\..\lib\liblame\include;..\..\lib\libUPnP\Platinum\Source\Devices\MediaRenderer;..\..\lib\libUPnP\Platinum\Source\Devices\MediaConnect;..\..\lib\libUPnP\Platinum\Source\Devices\MediaServer;..\..\lib\libUPnP\Platinum\Source\Platinum;..\..\lib\libUPnP\Platinum\Source\Core;..\..\lib\libUPnP\Neptune\Source\Core;..\..\lib\libUPnP\Neptune\Source\System\Win32;..\..\lib\win32\pcre;..\..\lib\win32</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..\..\;..\..\xbmc\;..\..\xbmc\cores\dvdplayer;..\..\xbmc\win32;..\..\lib;..\..\lib\ffmpeg;..\..\lib\liblame\include;..\..\lib\libUPnP\Platinum\Source\Devices\MediaRenderer;..\..\lib\libUPnP\Platinum\Source\Devices\MediaConnect;..\..\lib\libUPnP\Platinum\Source\Devices\MediaServer;..\..\lib\libUPnP\Platinum\Source\Platinum;..\..\lib\libUPnP\Platinum\Source\Core;..\..\lib\libUPnP\Neptune\Source\Core;..\..\lib\libUPnP\Neptune\Source\System\Win32;..\..\lib\win32\pcre;..\..\lib\win32;..\..\xbmc\cores\AudioEngine\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>TARGET_WINDOWS;_WINDOWS;_MSVC;WIN32;NDEBUG;_WIN32_WINNT=0x0501;NTDDI_VERSION=0x05010300;NOMINMAX;_USE_32BIT_TIME_T;HAS_GL;__STDC_CONSTANT_MACROS;XMD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>false</StringPooling>
       <MinimalRebuild>false</MinimalRebuild>
       <ExceptionHandling>Async</ExceptionHandling>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <BufferSecurityCheck>false</BufferSecurityCheck>
+      <BufferSecurityCheck>true</BufferSecurityCheck>
       <FunctionLevelLinking>false</FunctionLevelLinking>
       <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
       <PrecompiledHeader>Use</PrecompiledHeader>
     </ClCompile>
     <Link>
       <AdditionalOptions>/MACHINE:I386 /IGNORE:4089 /ignore:4254 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalDependencies>SDL.lib;opengl32.lib;DSound.lib;glew32.lib;glu32.lib;winmm.lib;ws2_32.lib;Mpr.lib;Iphlpapi.lib;PowrProf.lib;setupapi.lib;dwmapi.lib;yajl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>DInput8.lib;DSound.lib;winmm.lib;Mpr.lib;Iphlpapi.lib;PowrProf.lib;setupapi.lib;dwmapi.lib;yajl.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <OutputFile>$(OutDir)XBMC.exe</OutputFile>
-      <AdditionalLibraryDirectories>..\..\lib\libSDL-WIN32\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <IgnoreSpecificDefaultLibraries>libc;msvcrt;libci;msvcprt;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
       <DelayLoadDLLs>dnssd.dll;dwmapi.dll;libmicrohttpd-5.dll;ssh.dll;sqlite3.dll;libsamplerate-0.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <LargeAddressAware>true</LargeAddressAware>
       <OptimizeReferences>true</OptimizeReferences>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
+      <RandomizedBaseAddress>true</RandomizedBaseAddress>
+      <DataExecutionPrevention>true</DataExecutionPrevention>
       <TargetMachine>MachineX86</TargetMachine>
+      <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
     </Link>
     <Manifest>
       <AdditionalManifestFiles>VC90.CRT.x86.manifest;%(AdditionalManifestFiles)</AdditionalManifestFiles>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug (DirectX)|Win32'">
     <ClCompile>
       <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..\..\;..\..\xbmc\;..\..\xbmc\cores\dvdplayer;..\..\xbmc\win32;..\..\lib;..\..\lib\ffmpeg;..\..\lib\ffmpeg\include-xbmc-win32;..\..\lib\liblame\include;..\..\lib\libUPnP\Platinum\Source\Devices\MediaRenderer;..\..\lib\libUPnP\Platinum\Source\Devices\MediaConnect;..\..\lib\libUPnP\Platinum\Source\Devices\MediaServer;..\..\lib\libUPnP\Platinum\Source\Platinum;..\..\lib\libUPnP\Platinum\Source\Core;..\..\lib\libUPnP\Neptune\Source\Core;..\..\lib\libUPnP\Neptune\Source\System\Win32;..\..\lib\win32\pcre;..\..\lib\win32;..\..\xbmc\cores\AudioEngine\;..\..\xbmc\cores\AudioEngine\Utils\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..\..\;..\..\xbmc\;..\..\xbmc\cores\dvdplayer;..\..\xbmc\win32;..\..\lib;..\..\lib\ffmpeg;..\..\lib\liblame\include;..\..\lib\libUPnP\Platinum\Source\Devices\MediaRenderer;..\..\lib\libUPnP\Platinum\Source\Devices\MediaConnect;..\..\lib\libUPnP\Platinum\Source\Devices\MediaServer;..\..\lib\libUPnP\Platinum\Source\Platinum;..\..\lib\libUPnP\Platinum\Source\Core;..\..\lib\libUPnP\Neptune\Source\Core;..\..\lib\libUPnP\Neptune\Source\System\Win32;..\..\lib\win32\pcre;..\..\lib\win32;..\..\xbmc\cores\AudioEngine\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>TARGET_WINDOWS;_WINDOWS;_MSVC;WIN32;_DEBUG;_WIN32_WINNT=0x0501;NTDDI_VERSION=0x05010300;NOMINMAX;_USE_32BIT_TIME_T;HAS_DX;D3D_DEBUG_INFO;__STDC_CONSTANT_MACROS;_SECURE_SCL=0;_HAS_ITERATOR_DEBUGGING=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <MinimalRebuild>false</MinimalRebuild>
       <ExceptionHandling>Async</ExceptionHandling>
     </ClCompile>
     <Link>
       <AdditionalOptions>/MACHINE:I386 /IGNORE:4089 /ignore:4254 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalDependencies>D3D9.lib;D3dx9.lib;DInput8.lib;DSound.lib;winmm.lib;ws2_32.lib;Mpr.lib;Iphlpapi.lib;PowrProf.lib;setupapi.lib;dwmapi.lib;strmiids.lib;dxguid.lib;mfuuid.lib;comctl32.lib;yajl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>D3dx9.lib;DInput8.lib;DSound.lib;winmm.lib;Mpr.lib;Iphlpapi.lib;PowrProf.lib;setupapi.lib;dwmapi.lib;yajl.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <OutputFile>$(OutDir)XBMC.exe</OutputFile>
-      <AdditionalLibraryDirectories>..\..\lib\libSDL-WIN32\lib;..\..\xbmc\cores\DSPlayer\Libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <IgnoreSpecificDefaultLibraries>libc;msvcrt;libcmt;msvcrtd;msvcprtd;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
       <ModuleDefinitionFile>
       </ModuleDefinitionFile>
       <InlineFunctionExpansion>Default</InlineFunctionExpansion>
       <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
       <OmitFramePointers>true</OmitFramePointers>
-      <AdditionalIncludeDirectories>..\..\;..\..\xbmc\;..\..\xbmc\win32\;..\..\xbmc\cores\dvdplayer;..\..\lib;..\..\lib\ffmpeg;..\..\lib\ffmpeg\include-xbmc-win32;..\..\lib\liblame\include;..\..\lib\libUPnP\Platinum\Source\Devices\MediaRenderer;..\..\lib\libUPnP\Platinum\Source\Devices\MediaConnect;..\..\lib\libUPnP\Platinum\Source\Devices\MediaServer;..\..\lib\libUPnP\Platinum\Source\Platinum;..\..\lib\libUPnP\Platinum\Source\Core;..\..\lib\libUPnP\Neptune\Source\Core;..\..\lib\libUPnP\Neptune\Source\System\Win32;..\..\lib\win32\pcre;..\..\lib\win32;..\..\xbmc\cores\AudioEngine</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..\..\;..\..\xbmc\;..\..\xbmc\cores\dvdplayer;..\..\xbmc\win32;..\..\lib;..\..\lib\ffmpeg;..\..\lib\liblame\include;..\..\lib\libUPnP\Platinum\Source\Devices\MediaRenderer;..\..\lib\libUPnP\Platinum\Source\Devices\MediaConnect;..\..\lib\libUPnP\Platinum\Source\Devices\MediaServer;..\..\lib\libUPnP\Platinum\Source\Platinum;..\..\lib\libUPnP\Platinum\Source\Core;..\..\lib\libUPnP\Neptune\Source\Core;..\..\lib\libUPnP\Neptune\Source\System\Win32;..\..\lib\win32\pcre;..\..\lib\win32;..\..\xbmc\cores\AudioEngine\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>TARGET_WINDOWS;_WINDOWS;_MSVC;WIN32;NDEBUG;_WIN32_WINNT=0x0501;NTDDI_VERSION=0x05010300;NOMINMAX;_USE_32BIT_TIME_T;HAS_DX;__STDC_CONSTANT_MACROS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>false</StringPooling>
       <MinimalRebuild>false</MinimalRebuild>
     </ClCompile>
     <Link>
       <AdditionalOptions>/MACHINE:I386 /IGNORE:4089 /ignore:4254 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalDependencies>D3D9.lib;D3dx9.lib;DInput8.lib;DSound.lib;winmm.lib;ws2_32.lib;Mpr.lib;Iphlpapi.lib;PowrProf.lib;setupapi.lib;dwmapi.lib;strmiids.lib;dxguid.lib;mfuuid.lib;comctl32.lib;yajl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>D3dx9.lib;DInput8.lib;DSound.lib;winmm.lib;Mpr.lib;Iphlpapi.lib;PowrProf.lib;setupapi.lib;dwmapi.lib;yajl.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <OutputFile>$(OutDir)XBMC.exe</OutputFile>
-      <AdditionalLibraryDirectories>..\..\lib\libSDL-WIN32\lib;..\..\xbmc\cores\DSPlayer\Libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <IgnoreSpecificDefaultLibraries>libc;msvcrt;libci;msvcprt;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
       <DelayLoadDLLs>dnssd.dll;dwmapi.dll;libmicrohttpd-5.dll;ssh.dll;sqlite3.dll;libsamplerate-0.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
       <GenerateDebugInformation>true</GenerateDebugInformation>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug (OpenGL)|Win32'">
     <ClCompile>
       <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..\..\;..\..\xbmc\;..\..\xbmc\win32\;..\..\xbmc\cores\dvdplayer;..\..\lib;..\..\lib\ffmpeg;..\..\lib\ffmpeg\include-xbmc-win32;..\..\lib\liblame\include;..\..\lib\libUPnP\Platinum\Source\Devices\MediaRenderer;..\..\lib\libUPnP\Platinum\Source\Devices\MediaConnect;..\..\lib\libUPnP\Platinum\Source\Devices\MediaServer;..\..\lib\libUPnP\Platinum\Source\Platinum;..\..\lib\libUPnP\Platinum\Source\Core;..\..\lib\libUPnP\Neptune\Source\Core;..\..\lib\libUPnP\Neptune\Source\System\Win32;..\..\lib\win32\pcre;..\..\lib\win32</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..\..\;..\..\xbmc\;..\..\xbmc\cores\dvdplayer;..\..\xbmc\win32;..\..\lib;..\..\lib\ffmpeg;..\..\lib\liblame\include;..\..\lib\libUPnP\Platinum\Source\Devices\MediaRenderer;..\..\lib\libUPnP\Platinum\Source\Devices\MediaConnect;..\..\lib\libUPnP\Platinum\Source\Devices\MediaServer;..\..\lib\libUPnP\Platinum\Source\Platinum;..\..\lib\libUPnP\Platinum\Source\Core;..\..\lib\libUPnP\Neptune\Source\Core;..\..\lib\libUPnP\Neptune\Source\System\Win32;..\..\lib\win32\pcre;..\..\lib\win32;..\..\xbmc\cores\AudioEngine\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>TARGET_WINDOWS;_WINDOWS;_MSVC;WIN32;_DEBUG;_WIN32_WINNT=0x0501;NTDDI_VERSION=0x05010300;NOMINMAX;_USE_32BIT_TIME_T;HAS_GL;__STDC_CONSTANT_MACROS;_SECURE_SCL=0;_HAS_ITERATOR_DEBUGGING=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <MinimalRebuild>false</MinimalRebuild>
       <ExceptionHandling>Async</ExceptionHandling>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
       <PrecompiledHeader>Use</PrecompiledHeader>
       <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
-      <ProgramDataBaseFileName>$(IntDir)XBMC.pdb</ProgramDataBaseFileName>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
       <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
     </ClCompile>
     <Link>
       <AdditionalOptions>/MACHINE:I386 /IGNORE:4089 /ignore:4254 %(AdditionalOptions)</AdditionalOptions>
-      <AdditionalDependencies>SDL.lib;D3D9.lib;DInput8.lib;DSound.lib;winmm.lib;ws2_32.lib;Mpr.lib;Iphlpapi.lib;PowrProf.lib;setupapi.lib;dwmapi.lib;yajl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>DInput8.lib;DSound.lib;winmm.lib;Mpr.lib;Iphlpapi.lib;PowrProf.lib;setupapi.lib;dwmapi.lib;yajl.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <OutputFile>$(OutDir)XBMC.exe</OutputFile>
-      <AdditionalLibraryDirectories>..\..\lib\libSDL-WIN32\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <IgnoreSpecificDefaultLibraries>libc;msvcrt;libcmt;msvcrtd;msvcprtd;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
       <ModuleDefinitionFile>
       </ModuleDefinitionFile>
       <LargeAddressAware>true</LargeAddressAware>
       <EntryPointSymbol>
       </EntryPointSymbol>
-      <RandomizedBaseAddress>false</RandomizedBaseAddress>
-      <DataExecutionPrevention>
-      </DataExecutionPrevention>
+      <RandomizedBaseAddress>true</RandomizedBaseAddress>
+      <DataExecutionPrevention>true</DataExecutionPrevention>
       <TargetMachine>MachineX86</TargetMachine>
     </Link>
     <Manifest>
       <EnableDPIAwareness>true</EnableDPIAwareness>
     </Manifest>
   </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Template|Win32'">
+    <ClCompile>
+      <AdditionalIncludeDirectories>..\..\;..\..\xbmc\;..\..\xbmc\cores\dvdplayer;..\..\xbmc\win32;..\..\lib;..\..\lib\ffmpeg;..\..\lib\ffmpeg\include-xbmc-win32;..\..\lib\liblame\include;..\..\lib\libUPnP\Platinum\Source\Devices\MediaRenderer;..\..\lib\libUPnP\Platinum\Source\Devices\MediaConnect;..\..\lib\libUPnP\Platinum\Source\Devices\MediaServer;..\..\lib\libUPnP\Platinum\Source\Platinum;..\..\lib\libUPnP\Platinum\Source\Core;..\..\lib\libUPnP\Neptune\Source\Core;..\..\lib\libUPnP\Neptune\Source\System\Win32;..\..\lib\win32\pcre;..\..\lib\win32;..\..\xbmc\cores\AudioEngine\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+  </ItemDefinitionGroup>
   <ItemGroup>
     <ClCompile Include="..\..\lib\SlingboxLib\SlingboxLib.cpp" />
     <ClCompile Include="..\..\xbmc\addons\AddonDatabase.cpp" />
     <ClCompile Include="..\..\xbmc\filesystem\UPnPFile.cpp" />
     <ClCompile Include="..\..\xbmc\filesystem\VideoDatabaseDirectory.cpp" />
     <ClCompile Include="..\..\xbmc\FileSystem\VideoDatabaseDirectory\DirectoryNodeCountry.cpp" />
+    <ClCompile Include="..\..\xbmc\filesystem\VideoDatabaseDirectory\DirectoryNodeTags.cpp" />
     <ClCompile Include="..\..\xbmc\filesystem\windows\WINFileSMB.cpp" />
     <ClCompile Include="..\..\xbmc\filesystem\windows\WINSMBDirectory.cpp" />
     <ClCompile Include="..\..\xbmc\filesystem\VirtualDirectory.cpp" />
     <ClInclude Include="..\..\xbmc\cores\dvdplayer\DVDCodecs\Audio\DVDAudioCodecPassthrough.h" />
     <ClInclude Include="..\..\xbmc\cores\paplayer\PCMCodec.h" />
     <ClInclude Include="..\..\xbmc\filesystem\ImageFile.h" />
+    <ClInclude Include="..\..\xbmc\filesystem\VideoDatabaseDirectory\DirectoryNodeTags.h" />
     <ClInclude Include="..\..\xbmc\filesystem\windows\WINFileSMB.h" />
     <ClInclude Include="..\..\xbmc\filesystem\windows\WINSMBDirectory.h" />
     <ClInclude Include="..\..\xbmc\input\windows\WINJoystick.h" />
     <ClCompile Include="..\..\xbmc\utils\DatabaseUtils.cpp" />
     <ClCompile Include="..\..\xbmc\utils\DownloadQueue.cpp" />
     <ClCompile Include="..\..\xbmc\utils\DownloadQueueManager.cpp" />
+    <ClCompile Include="..\..\xbmc\utils\EndianSwap.cpp" />
     <ClCompile Include="..\..\xbmc\utils\Fanart.cpp" />
     <ClCompile Include="..\..\xbmc\utils\fft.cpp" />
     <ClCompile Include="..\..\xbmc\utils\FileOperationJob.cpp" />
index b0cc008..3181cca 100644 (file)
     <ClCompile Include="..\..\xbmc\utils\DatabaseUtils.cpp">
       <Filter>utils</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\xbmc\filesystem\VideoDatabaseDirectory\DirectoryNodeTags.cpp">
+      <Filter>filesystem\VideoDatabaseDirectory</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\xbmc\utils\EndianSwap.cpp">
+      <Filter>utils</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\xbmc\win32\pch.h">
     <ClInclude Include="..\..\xbmc\utils\ISortable.h">
       <Filter>utils</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\xbmc\filesystem\VideoDatabaseDirectory\DirectoryNodeTags.h">
+      <Filter>filesystem\VideoDatabaseDirectory</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="..\..\xbmc\win32\XBMC_PC.rc">
index 0fadaf9..746851e 100644 (file)
       <BufferSecurityCheck>true</BufferSecurityCheck>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <PrecompiledHeaderOutputFile>$(OutDir)$(ProjectName).pch</PrecompiledHeaderOutputFile>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
       <DisableSpecificWarnings>4800;4018;4146;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
     </ClCompile>
-    <Lib>
-      <OutputFile>$(TargetPath)</OutputFile>
-    </Lib>
+    <Lib />
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     <ClCompile>
       <AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
       <Optimization>Full</Optimization>
       <OmitFramePointers>true</OmitFramePointers>
-      <AdditionalIncludeDirectories>..\..\guilib;..\..\xbmc;..\..\xbmc\win32\;..\..\lib\win32\boost;..\..\lib\libSDL-WIN32\include</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..\..\xbmc;..\..\xbmc\win32</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>TARGET_WINDOWS;NOMINMAX;NDEBUG;WIN32;_LIB;_XBMC;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
       <PrecompiledHeaderFile>commons.hpp</PrecompiledHeaderFile>
-      <PrecompiledHeaderOutputFile>$(OutDir)$(ProjectName).pch</PrecompiledHeaderOutputFile>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>
       </DebugInformationFormat>
       <DisableSpecificWarnings>4800;4018;4146;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
     </ClCompile>
-    <Lib>
-      <OutputFile>$(OutDir)$(ProjectName).lib</OutputFile>
-    </Lib>
+    <Lib />
   </ItemDefinitionGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
index f006e37..f16c54b 100644 (file)
     <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)objs\$(TargetName)\$(Configuration)\</IntDir>
     <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)libs\$(TargetName)\$(Configuration)\</OutDir>
     <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)objs\$(TargetName)\$(Configuration)\</IntDir>
-    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(DXSDK_DIR)Include;$(IncludePath)</IncludePath>
-    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(DXSDK_DIR)Lib\x86;$(LibraryPath)</LibraryPath>
     <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">XbmcThreadsd</TargetName>
     <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">XbmcThreads</TargetName>
-    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(DXSDK_DIR)Include;$(IncludePath)</IncludePath>
-    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(DXSDK_DIR)Lib\x86;$(LibraryPath)</LibraryPath>
   </PropertyGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <ClCompile>
       <Optimization>Disabled</Optimization>
       <AdditionalIncludeDirectories>..\..\xbmc;..\..\xbmc\win32</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>TARGET_WINDOWS;NOMINMAX;WIN32;_DEBUG;_LIB;_XBMC;_USE_32BIT_TIME_T;HAS_DX;_SECURE_SCL=0;_HAS_ITERATOR_DEBUGGING=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>TARGET_WINDOWS;NOMINMAX;WIN32;_DEBUG;_LIB;_XBMC;_USE_32BIT_TIME_T;_SECURE_SCL=0;_HAS_ITERATOR_DEBUGGING=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <MinimalRebuild>false</MinimalRebuild>
       <BasicRuntimeChecks>Default</BasicRuntimeChecks>
       <BufferSecurityCheck>true</BufferSecurityCheck>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
-      <PrecompiledHeaderOutputFile>$(OutDir)$(ProjectName).pch</PrecompiledHeaderOutputFile>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
       <DisableSpecificWarnings>4800;4018;4146;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
       <AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
       <Optimization>Full</Optimization>
       <OmitFramePointers>true</OmitFramePointers>
-      <AdditionalIncludeDirectories>..\..\guilib;..\..\xbmc;..\..\xbmc\win32\;..\..\lib\win32\boost;..\..\lib\libSDL-WIN32\include</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>TARGET_WINDOWS;NOMINMAX;NDEBUG;WIN32;_LIB;_XBMC;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>..\..\xbmc;..\..\xbmc\win32</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>TARGET_WINDOWS;NOMINMAX;WIN32;NDEBUG;_LIB;_XBMC;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
-      <PrecompiledHeader>NotUsing</PrecompiledHeader>
       <PrecompiledHeaderFile>commons.hpp</PrecompiledHeaderFile>
-      <PrecompiledHeaderOutputFile>$(OutDir)$(ProjectName).pch</PrecompiledHeaderOutputFile>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>
       </DebugInformationFormat>
index b009eab..89cd09f 100644 (file)
                <channelminus>KEY_CHANNELDOWN</channelminus>
                <skipplus>KEY_NEXTSONG</skipplus>
                <skipminus>KEY_PREVIOUSSONG</skipminus>
-               <title>KEY_TEXT</title>
+               <title>KEY_TITLE</title>
                <subtitle>KEY_SUBTITLE</subtitle>
                <language>KEY_LANGUAGE</language>
                <mute>KEY_MUTE</mute>
diff --git a/system/library/video/movies/tags.xml b/system/library/video/movies/tags.xml
new file mode 100644 (file)
index 0000000..c88abc1
--- /dev/null
@@ -0,0 +1,5 @@
+<node order="9" type="folder">
+  <label>20459</label>
+  <path>videodb://1/9</path>
+  <icon>DefaultTags.png</icon>
+</node>
index 9f3f23f..b54b253 100644 (file)
 #include <X11/Xatom.h>
 #include <X11/extensions/Xrandr.h>
 #include <X11/extensions/Xrender.h>    /* we share subpixel information */
+#include <strings.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdarg.h>
 #include <stdint.h>
 #include <math.h>
 
-#if RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 2)
-#define HAS_RANDR_1_2 1
+#ifndef _X_NORETURN
+#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 205)
+#define _X_NORETURN __attribute((noreturn))
+#else
+#define _X_NORETURN
+#endif
 #endif
 
 static char    *program_name;
@@ -49,6 +54,8 @@ static int    screen = -1;
 static Bool    verbose = False;
 static Bool    automatic = False;
 static Bool    properties = False;
+static Bool    grab_server = True;
+static Bool    no_primary = False;
 
 static char *direction[5] = {
     "normal", 
@@ -89,7 +96,7 @@ static const struct {
     { NULL,        0 }
 };
 
-static void
+static void _X_NORETURN
 usage(void)
 {
     fprintf(stderr, "usage: %s [options]\n", program_name);
@@ -106,16 +113,13 @@ usage(void)
     fprintf(stderr, "  -y        (reflect in y)\n");
     fprintf(stderr, "  --screen <screen>\n");
     fprintf(stderr, "  --verbose\n");
+    fprintf(stderr, "  --current\n");
     fprintf(stderr, "  --dryrun\n");
-#if HAS_RANDR_1_2
+    fprintf(stderr, "  --nograb\n");
     fprintf(stderr, "  --prop or --properties\n");
     fprintf(stderr, "  --fb <width>x<height>\n");
     fprintf(stderr, "  --fbmm <width>x<height>\n");
     fprintf(stderr, "  --dpi <dpi>/<output>\n");
-#if 0
-    fprintf(stderr, "  --clone\n");
-    fprintf(stderr, "  --extend\n");
-#endif
     fprintf(stderr, "  --output <output>\n");
     fprintf(stderr, "      --auto\n");
     fprintf(stderr, "      --mode <mode>\n");
@@ -130,22 +134,30 @@ usage(void)
     fprintf(stderr, "      --below <output>\n");
     fprintf(stderr, "      --same-as <output>\n");
     fprintf(stderr, "      --set <property> <value>\n");
+    fprintf(stderr, "      --scale <x>x<y>\n");
+    fprintf(stderr, "      --scale-from <w>x<h>\n");
+    fprintf(stderr, "      --transform <a>,<b>,<c>,<d>,<e>,<f>,<g>,<h>,<i>\n");
     fprintf(stderr, "      --off\n");
     fprintf(stderr, "      --crtc <crtc>\n");
+    fprintf(stderr, "      --panning <w>x<h>[+<x>+<y>[/<track:w>x<h>+<x>+<y>[/<border:l>/<t>/<r>/<b>]]]\n");
+    fprintf(stderr, "      --gamma <r>:<g>:<b>\n");
+    fprintf(stderr, "      --primary\n");
+    fprintf(stderr, "  --noprimary\n");
     fprintf(stderr, "  --newmode <name> <clock MHz>\n");
     fprintf(stderr, "            <hdisp> <hsync-start> <hsync-end> <htotal>\n");
     fprintf(stderr, "            <vdisp> <vsync-start> <vsync-end> <vtotal>\n");
-    fprintf(stderr, "            [+HSync] [-HSync] [+VSync] [-VSync]\n");
+    fprintf(stderr, "            [flags...]\n");
+    fprintf(stderr, "            Valid flags: +HSync -HSync +VSync -VSync\n");
+    fprintf(stderr, "                         +CSync -CSync CSync Interlace DoubleScan\n");
     fprintf(stderr, "  --rmmode <name>\n");
     fprintf(stderr, "  --addmode <output> <name>\n");
     fprintf(stderr, "  --delmode <output> <name>\n");
-#endif
 
     exit(1);
     /*NOTREACHED*/
 }
 
-static void
+static void _X_NORETURN
 fatal (const char *format, ...)
 {
     va_list ap;
@@ -158,6 +170,23 @@ fatal (const char *format, ...)
     /*NOTREACHED*/
 }
 
+static void
+warning (const char *format, ...)
+{
+    va_list ap;
+    
+    va_start (ap, format);
+    fprintf (stderr, "%s: ", program_name);
+    vfprintf (stderr, format, ap);
+    va_end (ap);
+}
+
+/* Because fmin requires C99 suppport */
+static inline double dmin (double x, double y)
+{
+    return x < y ? x : y;
+}
+
 static char *
 rotation_name (Rotation rotation)
 {
@@ -188,15 +217,26 @@ reflection_name (Rotation rotation)
     return "invalid reflection";
 }
 
-#if HAS_RANDR_1_2
-typedef enum _policy {
-    cloned, extend
-} policy_t;
-
 typedef enum _relation {
-    left_of, right_of, above, below, same_as
+    relation_left_of,
+    relation_right_of,
+    relation_above,
+    relation_below,
+    relation_same_as,
 } relation_t;
 
+typedef struct {
+    int            x, y, width, height;
+} rectangle_t;
+
+typedef struct {
+    int            x1, y1, x2, y2;
+} box_t;
+
+typedef struct {
+    int            x, y;
+} point_t;
+
 typedef enum _changes {
     changes_none = 0,
     changes_crtc = (1 << 0),
@@ -207,7 +247,11 @@ typedef enum _changes {
     changes_reflection = (1 << 5),
     changes_automatic = (1 << 6),
     changes_refresh = (1 << 7),
-    changes_property = (1 << 8)
+    changes_property = (1 << 8),
+    changes_transform = (1 << 9),
+    changes_panning = (1 << 10),
+    changes_gamma = (1 << 11),
+    changes_primary = (1 << 12),
 } changes_t;
 
 typedef enum _name_kind {
@@ -215,7 +259,7 @@ typedef enum _name_kind {
     name_string = (1 << 0),
     name_xid = (1 << 1),
     name_index = (1 << 2),
-    name_preferred = (1 << 3)
+    name_preferred = (1 << 3),
 } name_kind_t;
 
 typedef struct {
@@ -227,20 +271,30 @@ typedef struct {
 
 typedef struct _crtc crtc_t;
 typedef struct _output output_t;
+typedef struct _transform transform_t;
 typedef struct _umode  umode_t;
 typedef struct _output_prop output_prop_t;
 
+struct _transform {
+    XTransform     transform;
+    char           *filter;
+    int                    nparams;
+    XFixed         *params;
+};
+
 struct _crtc {
     name_t         crtc;
     Bool           changing;
     XRRCrtcInfo            *crtc_info;
 
     XRRModeInfo            *mode_info;
+    XRRPanning      *panning_info;
     int                    x;
     int                    y;
     Rotation       rotation;
     output_t       **outputs;
     int                    noutput;
+    transform_t            current_transform, pending_transform;
 };
 
 struct _output_prop {
@@ -264,7 +318,7 @@ struct _output {
     crtc_t         *current_crtc_info;
     
     name_t         mode;
-    float          refresh;
+    double         refresh;
     XRRModeInfo            *mode_info;
     
     name_t         addmode;
@@ -274,8 +328,24 @@ struct _output {
 
     int                    x, y;
     Rotation       rotation;
-    
+
+    XRRPanning      panning;
+
     Bool           automatic;
+    int            scale_from_w, scale_from_h;
+    transform_t            transform;
+
+    struct {
+       float red;
+       float green;
+       float blue;
+    } gamma;
+
+    float          brightness;
+
+    Bool           primary;
+
+    Bool           found;
 };
 
 typedef enum _umode_action {
@@ -327,11 +397,12 @@ static int        num_crtcs;
 static XRRScreenResources  *res;
 static int     fb_width = 0, fb_height = 0;
 static int     fb_width_mm = 0, fb_height_mm = 0;
-static float   dpi = 0;
+static double  dpi = 0;
 static char    *dpi_output = NULL;
 static Bool    dryrun = False;
 static int     minWidth, maxWidth, minHeight, maxHeight;
 static Bool            has_1_2 = False;
+static Bool            has_1_3 = False;
 
 static int
 mode_height (XRRModeInfo *mode_info, Rotation rotation)
@@ -363,28 +434,104 @@ mode_width (XRRModeInfo *mode_info, Rotation rotation)
     }
 }
 
+static Bool
+transform_point (XTransform *transform, double *xp, double *yp)
+{
+    double  vector[3];
+    double  result[3];
+    int            i, j;
+    double  v;
+
+    vector[0] = *xp;
+    vector[1] = *yp;
+    vector[2] = 1;
+    for (j = 0; j < 3; j++)
+    {
+       v = 0;
+       for (i = 0; i < 3; i++)
+           v += (XFixedToDouble (transform->matrix[j][i]) * vector[i]);
+       result[j] = v;
+    }
+    if (!result[2])
+       return False;
+    for (j = 0; j < 2; j++) {
+       vector[j] = result[j] / result[2];
+       if (vector[j] > 32767 || vector[j] < -32767)
+           return False;
+    }
+    *xp = vector[0];
+    *yp = vector[1];
+    return True;
+}
+
+static void
+path_bounds (XTransform *transform, point_t *points, int npoints, box_t *box)
+{
+    int            i;
+    box_t   point;
+
+    for (i = 0; i < npoints; i++) {
+       double  x, y;
+       x = points[i].x;
+       y = points[i].y;
+       transform_point (transform, &x, &y);
+       point.x1 = floor (x);
+       point.y1 = floor (y);
+       point.x2 = ceil (x);
+       point.y2 = ceil (y);
+       if (i == 0)
+           *box = point;
+       else {
+           if (point.x1 < box->x1) box->x1 = point.x1;
+           if (point.y1 < box->y1) box->y1 = point.y1;
+           if (point.x2 > box->x2) box->x2 = point.x2;
+           if (point.y2 > box->y2) box->y2 = point.y2;
+       }
+    }
+}
+
+static void
+mode_geometry (XRRModeInfo *mode_info, Rotation rotation,
+              XTransform *transform,
+              box_t *bounds)
+{
+    point_t rect[4];
+    int        width = mode_width (mode_info, rotation);
+    int height = mode_height (mode_info, rotation);
+
+    rect[0].x = 0;
+    rect[0].y = 0;
+    rect[1].x = width;
+    rect[1].y = 0;
+    rect[2].x = width;
+    rect[2].y = height;
+    rect[3].x = 0;
+    rect[3].y = height;
+    path_bounds (transform, rect, 4, bounds);
+}
+
 /* v refresh frequency in Hz */
-static float
+static double
 mode_refresh (XRRModeInfo *mode_info)
 {
-    float rate;
+    double rate;
     
     if (mode_info->hTotal && mode_info->vTotal)
-       rate = ((float) mode_info->dotClock / 
-               ((float) mode_info->hTotal * (float) mode_info->vTotal));
+       rate = ((double) mode_info->dotClock /
+               ((double) mode_info->hTotal * (double) mode_info->vTotal));
     else
        rate = 0;
     return rate;
 }
 
 /* h sync frequency in Hz */
-static float
+static double
 mode_hsync (XRRModeInfo *mode_info)
 {
-    float rate;
+    double rate;
     
     if (mode_info->hTotal)
-       rate = (float) mode_info->dotClock / (float) mode_info->hTotal;
+       rate = (double) mode_info->dotClock / (double) mode_info->hTotal;
     else
        rate = 0;
     return rate;
@@ -438,10 +585,11 @@ set_name_all (name_t *name, name_t *old)
 static void
 set_name (name_t *name, char *string, name_kind_t valid)
 {
-    XID        xid;
+    unsigned int xid; /* don't make it XID (which is unsigned long):
+                        scanf() takes unsigned int */
     int index;
 
-    if ((valid & name_xid) && sscanf (string, "0x%lx", &xid) == 1)
+    if ((valid & name_xid) && sscanf (string, "0x%x", &xid) == 1)
        set_name_xid (name, xid);
     else if ((valid & name_index) && sscanf (string, "%d", &index) == 1)
        set_name_index (name, index);
@@ -451,14 +599,63 @@ set_name (name_t *name, char *string, name_kind_t valid)
        usage ();
 }
 
+static void
+init_transform (transform_t *transform)
+{
+    int x;
+    memset (&transform->transform, '\0', sizeof (transform->transform));
+    for (x = 0; x < 3; x++)
+       transform->transform.matrix[x][x] = XDoubleToFixed (1.0);
+    transform->filter = "";
+    transform->nparams = 0;
+    transform->params = NULL;
+}
+
+static void
+set_transform (transform_t  *dest,
+              XTransform   *transform,
+              char         *filter,
+              XFixed       *params,
+              int          nparams)
+{
+    dest->transform = *transform;
+    dest->filter = strdup (filter);
+    dest->nparams = nparams;
+    dest->params = malloc (nparams * sizeof (XFixed));
+    memcpy (dest->params, params, nparams * sizeof (XFixed));
+}
+
+static void
+copy_transform (transform_t *dest, transform_t *src)
+{
+    set_transform (dest, &src->transform,
+                  src->filter, src->params, src->nparams);
+}
+
+static Bool
+equal_transform (transform_t *a, transform_t *b)
+{
+    if (memcmp (&a->transform, &b->transform, sizeof (XTransform)) != 0)
+       return False;
+    if (strcmp (a->filter, b->filter) != 0)
+       return False;
+    if (a->nparams != b->nparams)
+       return False;
+    if (memcmp (a->params, b->params, a->nparams * sizeof (XFixed)) != 0)
+       return False;
+    return True;
+}
+
 static output_t *
 add_output (void)
 {
     output_t *output = calloc (1, sizeof (output_t));
 
     if (!output)
-       fatal ("out of memory");
+       fatal ("out of memory\n");
     output->next = NULL;
+    output->found = False;
+    output->brightness = 1.0;
     *outputs_tail = output;
     outputs_tail = &output->next;
     return output;
@@ -538,11 +735,11 @@ find_crtc_by_xid (RRCrtc crtc)
 }
 
 static XRRModeInfo *
-find_mode (name_t *name, float refresh)
+find_mode (name_t *name, double refresh)
 {
     int                m;
     XRRModeInfo        *best = NULL;
-    float      bestDist = 0;
+    double     bestDist = 0;
 
     for (m = 0; m < res->nmode; m++)
     {
@@ -554,7 +751,7 @@ find_mode (name_t *name, float refresh)
        }
        if ((name->kind & name_string) && !strcmp (name->string, mode->name))
        {
-           float   dist;
+           double   dist;
            
            if (refresh)
                dist = fabs (mode_refresh (mode) - refresh);
@@ -565,7 +762,6 @@ find_mode (name_t *name, float refresh)
                bestDist = dist;
                best = mode;
            }
-           break;
        }
     }
     return best;
@@ -581,18 +777,30 @@ find_mode_by_xid (RRMode mode)
     return find_mode (&mode_name, 0);
 }
 
+#if 0
 static XRRModeInfo *
+find_mode_by_name (char *name)
+{
+    name_t  mode_name;
+    init_name (&mode_name);
+    set_name_string (&mode_name, name);
+    return find_mode (&mode_name, 0);
+}
+#endif
+
+static
+XRRModeInfo *
 find_mode_for_output (output_t *output, name_t *name)
 {
     XRROutputInfo   *output_info = output->output_info;
     int                    m;
     XRRModeInfo            *best = NULL;
-    float          bestDist = 0;
+    double         bestDist = 0;
 
     for (m = 0; m < output_info->nmode; m++)
     {
        XRRModeInfo         *mode;
-       
+
        mode = find_mode_by_xid (output_info->modes[m]);
        if (!mode) continue;
        if ((name->kind & name_xid) && name->xid == mode->id)
@@ -602,8 +810,12 @@ find_mode_for_output (output_t *output, name_t *name)
        }
        if ((name->kind & name_string) && !strcmp (name->string, mode->name))
        {
-           float   dist;
-           
+           double   dist;
+
+           /* Stay away from doublescan modes unless refresh rate is specified. */
+           if (!output->refresh && (mode->modeFlags & RR_DoubleScan))
+               continue;
+
            if (output->refresh)
                dist = fabs (mode_refresh (mode) - output->refresh);
            else
@@ -618,7 +830,7 @@ find_mode_for_output (output_t *output, name_t *name)
     return best;
 }
 
-XRRModeInfo *
+static XRRModeInfo *
 preferred_mode (output_t *output)
 {
     XRROutputInfo   *output_info = output->output_info;
@@ -686,6 +898,45 @@ crtc_can_use_rotation (crtc_t *crtc, Rotation rotation)
     return False;
 }
 
+#if 0
+static Bool
+crtc_can_use_transform (crtc_t *crtc, XTransform *transform)
+{
+    int        major, minor;
+
+    XRRQueryVersion (dpy, &major, &minor);
+    if (major > 1 || (major == 1 && minor >= 3))
+       return True;
+    return False;
+}
+#endif
+
+/*
+ * Report only rotations that are supported by all crtcs
+ */
+static Rotation
+output_rotations (output_t *output)
+{
+    Bool           found = False;
+    Rotation       rotation = RR_Rotate_0;
+    XRROutputInfo   *output_info = output->output_info;
+    int                    c;
+    
+    for (c = 0; c < output_info->ncrtc; c++)
+    {
+       crtc_t  *crtc = find_crtc_by_xid (output_info->crtcs[c]);
+       if (crtc)
+       {
+           if (!found) {
+               rotation = crtc->crtc_info->rotations;
+               found = True;
+           } else
+               rotation &= crtc->crtc_info->rotations;
+       }
+    }
+    return rotation;
+}
+
 static Bool
 output_can_use_rotation (output_t *output, Rotation rotation)
 {
@@ -706,13 +957,111 @@ output_can_use_rotation (output_t *output, Rotation rotation)
     return True;
 }
 
+static Bool
+output_is_primary(output_t *output)
+{
+    if (has_1_3)
+           return XRRGetOutputPrimary(dpy, root) == output->output.xid;
+    return False;
+}
+
+/* Returns the index of the last value in an array < 0xffff */
+static int
+find_last_non_clamped(CARD16 array[], int size) {
+    int i;
+    for (i = size - 1; i > 0; i--) {
+        if (array[i] < 0xffff)
+           return i;
+    }
+    return 0;
+}
+
+static void
+set_gamma_info(output_t *output)
+{
+    XRRCrtcGamma *gamma;
+    double i1, v1, i2, v2;
+    int size, middle, last_best, last_red, last_green, last_blue;
+    CARD16 *best_array;
+
+    if (!output->crtc_info)
+       return;
+
+    size = XRRGetCrtcGammaSize(dpy, output->crtc_info->crtc.xid);
+    if (!size) {
+       warning("Failed to get size of gamma for output %s\n", output->output.string);
+       return;
+    }
+
+    gamma = XRRGetCrtcGamma(dpy, output->crtc_info->crtc.xid);
+    if (!gamma) {
+       warning("Failed to get gamma for output %s\n", output->output.string);
+       return;
+    }
+
+    /*
+     * Here is a bit tricky because gamma is a whole curve for each
+     * color.  So, typically, we need to represent 3 * 256 values as 3 + 1
+     * values.  Therefore, we approximate the gamma curve (v) by supposing
+     * it always follows the way we set it: a power function (i^g)
+     * multiplied by a brightness (b).
+     * v = i^g * b
+     * so g = (ln(v) - ln(b))/ln(i)
+     * and b can be found using two points (v1,i1) and (v2, i2):
+     * b = e^((ln(v2)*ln(i1) - ln(v1)*ln(i2))/ln(i1/i2))
+     * For the best resolution, we select i2 at the highest place not
+     * clamped and i1 at i2/2. Note that if i2 = 1 (as in most normal
+     * cases), then b = v2.
+     */
+    last_red = find_last_non_clamped(gamma->red, size);
+    last_green = find_last_non_clamped(gamma->green, size);
+    last_blue = find_last_non_clamped(gamma->blue, size);
+    best_array = gamma->red;
+    last_best = last_red;
+    if (last_green > last_best) {
+       last_best = last_green;
+       best_array = gamma->green;
+    }
+    if (last_blue > last_best) {
+       last_best = last_blue;
+       best_array = gamma->blue;
+    }
+    if (last_best == 0)
+       last_best = 1;
+
+    middle = last_best / 2;
+    i1 = (double)(middle + 1) / size;
+    v1 = (double)(best_array[middle]) / 65535;
+    i2 = (double)(last_best + 1) / size;
+    v2 = (double)(best_array[last_best]) / 65535;
+    if (v2 < 0.0001) { /* The screen is black */
+       output->brightness = 0;
+       output->gamma.red = 1;
+       output->gamma.green = 1;
+       output->gamma.blue = 1;
+    } else {
+       if ((last_best + 1) == size)
+           output->brightness = v2;
+       else
+           output->brightness = exp((log(v2)*log(i1) - log(v1)*log(i2))/log(i1/i2));
+       output->gamma.red = log((double)(gamma->red[last_red / 2]) / output->brightness
+                               / 65535) / log((double)((last_red / 2) + 1) / size);
+       output->gamma.green = log((double)(gamma->green[last_green / 2]) / output->brightness
+                                 / 65535) / log((double)((last_green / 2) + 1) / size);
+       output->gamma.blue = log((double)(gamma->blue[last_blue / 2]) / output->brightness
+                                / 65535) / log((double)((last_blue / 2) + 1) / size);
+    }
+
+    XRRFreeGamma(gamma);
+}
+
 static void
 set_output_info (output_t *output, RROutput xid, XRROutputInfo *output_info)
 {
     /* sanity check output info */
     if (output_info->connection != RR_Disconnected && !output_info->nmode)
-       fatal ("Output %s is not disconnected but has no modes\n",
-              output_info->name);
+       warning ("Output %s is not disconnected but has no modes\n",
+                output_info->name);
     
     /* set output name and info */
     if (!(output->output.kind & name_xid))
@@ -745,7 +1094,13 @@ set_output_info (output_t *output, RROutput xid, XRROutputInfo *output_info)
     /* set mode name and info */
     if (!(output->changes & changes_mode))
     {
-       if (output->crtc_info)
+       crtc_t  *crtc = NULL;
+       
+       if (output_info->crtc)
+           crtc = find_crtc_by_xid(output_info->crtc);
+       if (crtc && crtc->crtc_info)
+           set_name_xid (&output->mode, crtc->crtc_info->mode);
+       else if (output->crtc_info)
            set_name_xid (&output->mode, output->crtc_info->crtc_info->mode);
        else
            set_name_xid (&output->mode, None);
@@ -817,10 +1172,51 @@ set_output_info (output_t *output, RROutput xid, XRROutputInfo *output_info)
               output->output.string,
               rotation_name (output->rotation),
               reflection_name (output->rotation));
+
+    /* set gamma */
+    if (!(output->changes & changes_gamma))
+           set_gamma_info(output);
+
+    /* set transformation */
+    if (!(output->changes & changes_transform))
+    {
+       if (output->crtc_info)
+           copy_transform (&output->transform, &output->crtc_info->current_transform);
+       else
+           init_transform (&output->transform);
+    } else {
+       /* transform was already set for --scale or --transform */
+
+       /* for --scale-from, figure out the mode size and compute the transform
+        * for the target framebuffer area */
+       if (output->scale_from_w > 0 && output->mode_info) {
+           double sx = (double)output->scale_from_w /
+                               output->mode_info->width;
+           double sy = (double)output->scale_from_h /
+                               output->mode_info->height;
+           if (verbose)
+               printf("scaling %s by %lfx%lf\n", output->output.string, sx,
+                      sy);
+           init_transform (&output->transform);
+           output->transform.transform.matrix[0][0] = XDoubleToFixed (sx);
+           output->transform.transform.matrix[1][1] = XDoubleToFixed (sy);
+           output->transform.transform.matrix[2][2] = XDoubleToFixed (1.0);
+           if (sx != 1 || sy != 1)
+               output->transform.filter = "bilinear";
+           else
+               output->transform.filter = "nearest";
+           output->transform.nparams = 0;
+           output->transform.params = NULL;
+       }
+    }
+
+    /* set primary */
+    if (!(output->changes & changes_primary))
+       output->primary = output_is_primary(output);
 }
     
 static void
-get_screen (void)
+get_screen (Bool current)
 {
     if (!has_1_2)
         fatal ("Server RandR version before 1.2\n");
@@ -828,7 +1224,10 @@ get_screen (void)
     XRRGetScreenSizeRange (dpy, root, &minWidth, &minHeight,
                           &maxWidth, &maxHeight);
     
-    res = XRRGetScreenResources (dpy, root);
+    if (current)
+       res = XRRGetScreenResourcesCurrent (dpy, root);
+    else
+       res = XRRGetScreenResources (dpy, root);
     if (!res) fatal ("could not get screen resources");
 }
 
@@ -839,15 +1238,30 @@ get_crtcs (void)
 
     num_crtcs = res->ncrtc;
     crtcs = calloc (num_crtcs, sizeof (crtc_t));
-    if (!crtcs) fatal ("out of memory");
+    if (!crtcs) fatal ("out of memory\n");
     
     for (c = 0; c < res->ncrtc; c++)
     {
        XRRCrtcInfo *crtc_info = XRRGetCrtcInfo (dpy, res, res->crtcs[c]);
+       XRRCrtcTransformAttributes  *attr;
+       XRRPanning  *panning_info = NULL;
+
+       if (has_1_3) {
+           XRRPanning zero;
+           memset(&zero, 0, sizeof(zero));
+           panning_info = XRRGetPanning  (dpy, res, res->crtcs[c]);
+           zero.timestamp = panning_info->timestamp;
+           if (!memcmp(panning_info, &zero, sizeof(zero))) {
+               Xfree(panning_info);
+               panning_info = NULL;
+           }
+       }
+
        set_name_xid (&crtcs[c].crtc, res->crtcs[c]);
        set_name_index (&crtcs[c].crtc, c);
-       if (!crtc_info) fatal ("could not get crtc 0x%x information", res->crtcs[c]);
+       if (!crtc_info) fatal ("could not get crtc 0x%x information\n", res->crtcs[c]);
        crtcs[c].crtc_info = crtc_info;
+       crtcs[c].panning_info = panning_info;
        if (crtc_info->mode == None)
        {
            crtcs[c].mode_info = NULL;
@@ -855,7 +1269,20 @@ get_crtcs (void)
            crtcs[c].y = 0;
            crtcs[c].rotation = RR_Rotate_0;
        }
-    }
+       if (XRRGetCrtcTransform (dpy, res->crtcs[c], &attr) && attr) {
+           set_transform (&crtcs[c].current_transform,
+                          &attr->currentTransform,
+                          attr->currentFilter,
+                          attr->currentParams,
+                          attr->currentNparams);
+           XFree (attr);
+       }
+       else
+       {
+           init_transform (&crtcs[c].current_transform);
+       }
+       copy_transform (&crtcs[c].pending_transform, &crtcs[c].current_transform);
+   }
 }
 
 static void
@@ -870,8 +1297,9 @@ crtc_add_output (crtc_t *crtc, output_t *output)
        crtc->y = output->y;
        crtc->rotation = output->rotation;
        crtc->mode_info = output->mode_info;
-    }
-    if (!crtc->outputs) fatal ("out of memory");
+       copy_transform (&crtc->pending_transform, &output->transform);
+   }
+    if (!crtc->outputs) fatal ("out of memory\n");
     crtc->outputs[crtc->noutput++] = output;
 }
 
@@ -887,6 +1315,106 @@ set_crtcs (void)
     }
 }
 
+static void
+set_panning (void)
+{
+    output_t   *output;
+
+    for (output = outputs; output; output = output->next)
+    {
+       if (! output->crtc_info)
+           continue;
+       if (! (output->changes & changes_panning))
+           continue;
+       if (! output->crtc_info->panning_info)
+           output->crtc_info->panning_info = malloc (sizeof(XRRPanning));
+       memcpy (output->crtc_info->panning_info, &output->panning, sizeof(XRRPanning));
+       output->crtc_info->changing = 1;
+    }
+}
+
+static void
+set_gamma(void)
+{
+    output_t   *output;
+
+    for (output = outputs; output; output = output->next) {
+       int i, size;
+       crtc_t *crtc;
+       XRRCrtcGamma *gamma;
+
+       if (!(output->changes & changes_gamma))
+           continue;
+
+       if (!output->crtc_info) {
+           fatal("Need crtc to set gamma on.\n");
+           continue;
+       }
+
+       crtc = output->crtc_info;
+
+       size = XRRGetCrtcGammaSize(dpy, crtc->crtc.xid);
+
+       if (!size) {
+           fatal("Gamma size is 0.\n");
+           continue;
+       }
+
+       gamma = XRRAllocGamma(size);
+       if (!gamma) {
+           fatal("Gamma allocation failed.\n");
+           continue;
+       }
+
+       if(output->gamma.red == 0.0 && output->gamma.green == 0.0 && output->gamma.blue == 0.0)
+           output->gamma.red = output->gamma.green = output->gamma.blue = 1.0;
+
+       for (i = 0; i < size; i++) {
+           if (output->gamma.red == 1.0 && output->brightness == 1.0)
+               gamma->red[i] = (i << 8) + i;
+           else
+               gamma->red[i] = dmin(pow((double)i/(double)(size - 1),
+                                        output->gamma.red) * output->brightness,
+                                    1.0) * 65535.0;
+
+           if (output->gamma.green == 1.0 && output->brightness == 1.0)
+               gamma->green[i] = (i << 8) + i;
+           else
+               gamma->green[i] = dmin(pow((double)i/(double)(size - 1),
+                                          output->gamma.green) * output->brightness,
+                                      1.0) * 65535.0;
+
+           if (output->gamma.blue == 1.0 && output->brightness == 1.0)
+               gamma->blue[i] = (i << 8) + i;
+           else
+               gamma->blue[i] = dmin(pow((double)i/(double)(size - 1),
+                                         output->gamma.blue) * output->brightness,
+                                     1.0) * 65535.0;
+       }
+
+       XRRSetCrtcGamma(dpy, crtc->crtc.xid, gamma);
+
+       free(gamma);
+    }
+}
+
+static void
+set_primary(void)
+{
+    output_t *output;
+
+    if (no_primary) {
+       XRRSetOutputPrimary(dpy, root, None);
+    } else {
+       for (output = outputs; output; output = output->next) {
+           if (!(output->changes & changes_primary))
+               continue;
+           if (output->primary)
+               XRRSetOutputPrimary(dpy, root, output->output.xid);
+       }
+    }
+}
+
 static Status
 crtc_disable (crtc_t *crtc)
 {
@@ -899,6 +1427,20 @@ crtc_disable (crtc_t *crtc)
                             0, 0, None, RR_Rotate_0, NULL, 0);
 }
 
+static void
+crtc_set_transform (crtc_t *crtc, transform_t *transform)
+{
+    int        major, minor;
+
+    XRRQueryVersion (dpy, &major, &minor);
+    if (major > 1 || (major == 1 && minor >= 3))
+       XRRSetCrtcTransform (dpy, crtc->crtc.xid,
+                            &transform->transform,
+                            transform->filter,
+                            transform->params,
+                            transform->nparams);
+}
+
 static Status
 crtc_revert (crtc_t *crtc)
 {
@@ -909,6 +1451,9 @@ crtc_revert (crtc_t *crtc)
        
     if (dryrun)
        return RRSetConfigSuccess;
+
+    if (!equal_transform (&crtc->current_transform, &crtc->pending_transform))
+       crtc_set_transform (crtc, &crtc->current_transform);
     return XRRSetCrtcConfig (dpy, res, crtc->crtc.xid, CurrentTime,
                            crtc_info->x, crtc_info->y,
                            crtc_info->mode, crtc_info->rotation,
@@ -944,9 +1489,19 @@ crtc_apply (crtc_t *crtc)
     if (dryrun)
        s = RRSetConfigSuccess;
     else
+    {
+       if (!equal_transform (&crtc->current_transform, &crtc->pending_transform))
+           crtc_set_transform (crtc, &crtc->pending_transform);
        s = XRRSetCrtcConfig (dpy, res, crtc->crtc.xid, CurrentTime,
                              crtc->x, crtc->y, mode, crtc->rotation,
                              rr_outputs, crtc->noutput);
+       if (s == RRSetConfigSuccess && crtc->panning_info) {
+           if (has_1_3)
+               s = XRRSetPanning (dpy, res, crtc->crtc.xid, crtc->panning_info);
+           else
+               fatal ("panning needs RandR 1.3\n");
+       }
+    }
     free (rr_outputs);
     return s;
 }
@@ -1005,7 +1560,7 @@ revert (void)
  * the configuration. Revert to the previous configuration
  * and bail
  */
-static void
+static void _X_NORETURN
 panic (Status s, crtc_t *crtc)
 {
     int            c = crtc->crtc.index;
@@ -1025,13 +1580,22 @@ panic (Status s, crtc_t *crtc)
     exit (1);
 }
 
-void
+static void
 apply (void)
 {
     Status  s;
     int            c;
     
     /*
+     * Hold the server grabbed while messing with
+     * the screen so that apps which notice the resize
+     * event and ask for xinerama information from the server
+     * receive up-to-date information
+     */
+    if (grab_server)
+       XGrabServer (dpy);
+    
+    /*
      * Turn off any crtcs which are to be disabled or which are
      * larger than the target size
      */
@@ -1052,16 +1616,21 @@ apply (void)
        {
            XRRModeInfo *old_mode = find_mode_by_xid (crtc_info->mode);
            int x, y, w, h;
+           box_t bounds;
 
            if (!old_mode) 
                panic (RRSetConfigFailed, crtc);
            
            /* old position and size information */
-           x = crtc_info->x;
-           y = crtc_info->y;
-           w = mode_width (old_mode, crtc_info->rotation);
-           h = mode_height (old_mode, crtc_info->rotation);
-           
+           mode_geometry (old_mode, crtc_info->rotation,
+                          &crtc->current_transform.transform,
+                          &bounds);
+
+           x = crtc_info->x + bounds.x1;
+           y = crtc_info->y + bounds.y1;
+           w = bounds.x2 - bounds.x1;
+           h = bounds.y2 - bounds.y1;
+
            /* if it fits, skip it */
            if (x + w <= fb_width && y + h <= fb_height) 
                continue;
@@ -1073,13 +1642,6 @@ apply (void)
     }
 
     /*
-     * Hold the server grabbed while messing with
-     * the screen so that apps which notice the resize
-     * event receive up-to-date information
-     */
-    XGrabServer (dpy);
-    
-    /*
      * Set the screen size
      */
     screen_apply ();
@@ -1096,27 +1658,32 @@ apply (void)
        if (s != RRSetConfigSuccess)
            panic (s, crtc);
     }
+
+    set_primary ();
+
     /*
      * Release the server grab and let all clients
      * respond to the updated state
      */
-    XUngrabServer (dpy);
+    if (grab_server)
+       XUngrabServer (dpy);
 }
 
 /*
  * Use current output state to complete the output list
  */
-void
+static void
 get_outputs (void)
 {
     int                o;
+    output_t    *q;
     
     for (o = 0; o < res->noutput; o++)
     {
        XRROutputInfo   *output_info = XRRGetOutputInfo (dpy, res, res->outputs[o]);
        output_t        *output;
        name_t          output_name;
-       if (!output_info) fatal ("could not get output 0x%x information", res->outputs[o]);
+       if (!output_info) fatal ("could not get output 0x%x information\n", res->outputs[o]);
        set_name_xid (&output_name, res->outputs[o]);
        set_name_index (&output_name, o);
        set_name_string (&output_name, output_info->name);
@@ -1148,6 +1715,7 @@ get_outputs (void)
                }
            }
        }
+       output->found = True;
 
        /*
         * Automatic mode -- track connection state and enable/disable outputs
@@ -1178,9 +1746,17 @@ get_outputs (void)
 
        set_output_info (output, res->outputs[o], output_info);
     }
+    for (q = outputs; q; q = q->next)
+    {
+       if (!q->found)
+       {
+           fprintf(stderr, "warning: output %s not found; ignoring\n",
+                   q->output.string);
+       }
+    }
 }
 
-void
+static void
 mark_changing_crtcs (void)
 {
     int        c;
@@ -1213,7 +1789,7 @@ mark_changing_crtcs (void)
 /*
  * Test whether 'crtc' can be used for 'output'
  */
-Bool
+static Bool
 check_crtc_for_output (crtc_t *crtc, output_t *output)
 {
     int                c;
@@ -1256,11 +1832,27 @@ check_crtc_for_output (crtc_t *crtc, output_t *output)
            return False;
        if (crtc->rotation != output->rotation)
            return False;
+       if (!equal_transform (&crtc->current_transform, &output->transform))
+           return False;
+    }
+    else if (crtc->crtc_info->noutput)
+    {
+       /* make sure the state matches the already used state */
+       XRRModeInfo *mode = find_mode_by_xid (crtc->crtc_info->mode);
+
+       if (mode != output->mode_info)
+           return False;
+       if (crtc->crtc_info->x != output->x)
+           return False;
+       if (crtc->crtc_info->y != output->y)
+           return False;
+       if (crtc->crtc_info->rotation != output->rotation)
+           return False;
     }
     return True;
 }
 
-crtc_t *
+static crtc_t *
 find_crtc_for_output (output_t *output)
 {
     int            c;
@@ -1323,23 +1915,23 @@ set_positions (void)
            }
            
            switch (output->relation) {
-           case left_of:
+           case relation_left_of:
                output->y = relation->y;
                output->x = relation->x - mode_width (output->mode_info, output->rotation);
                break;
-           case right_of:
+           case relation_right_of:
                output->y = relation->y;
                output->x = relation->x + mode_width (relation->mode_info, relation->rotation);
                break;
-           case above:
+           case relation_above:
                output->x = relation->x;
                output->y = relation->y - mode_height (output->mode_info, output->rotation);
                break;
-           case below:
+           case relation_below:
                output->x = relation->x;
                output->y = relation->y + mode_height (relation->mode_info, relation->rotation);
                break;
-           case same_as:
+           case relation_same_as:
                output->x = relation->x;
                output->y = relation->y;
            }
@@ -1388,25 +1980,40 @@ set_screen_size (void)
     {
        XRRModeInfo *mode_info = output->mode_info;
        int         x, y, w, h;
+       box_t       bounds;
        
        if (!mode_info) continue;
        
-       x = output->x;
-       y = output->y;
-       w = mode_width (mode_info, output->rotation);
-       h = mode_height (mode_info, output->rotation);
+       mode_geometry (mode_info, output->rotation,
+                      &output->transform.transform,
+                      &bounds);
+       x = output->x + bounds.x1;
+       y = output->y + bounds.y1;
+       w = bounds.x2 - bounds.x1;
+       h = bounds.y2 - bounds.y1;
        /* make sure output fits in specified size */
        if (fb_specified)
        {
            if (x + w > fb_width || y + h > fb_height)
-               fatal ("specified screen %dx%d not large enough for output %s (%dx%d+%d+%d)\n",
-                      fb_width, fb_height, output->output.string, w, h, x, y);
+               warning ("specified screen %dx%d not large enough for output %s (%dx%d+%d+%d)\n",
+                        fb_width, fb_height, output->output.string, w, h, x, y);
        }
        /* fit fb to output */
        else
        {
-           if (x + w > fb_width) fb_width = x + w;
-           if (y + h > fb_height) fb_height = y + h;
+           XRRPanning *pan;
+           if (x + w > fb_width)
+               fb_width = x + w;
+           if (y + h > fb_height)
+               fb_height = y + h;
+           if (output->changes & changes_panning)
+               pan = &output->panning;
+           else
+               pan = output->crtc_info ? output->crtc_info->panning_info : NULL;
+           if (pan && pan->left + pan->width > fb_width)
+               fb_width = pan->left + pan->width;
+           if (pan && pan->top + pan->height > fb_height)
+               fb_height = pan->top + pan->height;
        }
     }  
 
@@ -1425,9 +2032,8 @@ set_screen_size (void)
     }
 }
     
-#endif
-    
-void
+
+static void
 disable_outputs (output_t *outputs)
 {
     while (outputs)
@@ -1440,7 +2046,7 @@ disable_outputs (output_t *outputs)
 /*
  * find the best mapping from output to crtc available
  */
-int
+static int
 pick_crtcs_score (output_t *outputs)
 {
     output_t   *output;
@@ -1493,21 +2099,20 @@ pick_crtcs_score (output_t *outputs)
            best_score = score;
        }
     }
+    if (output->crtc_info != best_crtc)
+       output->crtc_info = best_crtc;
     /*
      * Reset other outputs based on this one using the best crtc
      */
-    if (output->crtc_info != best_crtc)
-    {
-       output->crtc_info = best_crtc;
-       (void) pick_crtcs_score (outputs);
-    }
+    (void) pick_crtcs_score (outputs);
+
     return best_score;
 }
 
 /*
  * Pick crtcs for any changing outputs that don't have one
  */
-void
+static void
 pick_crtcs (void)
 {
     output_t   *output;
@@ -1517,11 +2122,18 @@ pick_crtcs (void)
      */
     for (output = outputs; output; output = output->next)
     {
-       if (output->changes && output->mode_info && !output->crtc_info)
+       if (output->changes && output->mode_info)
        {
-           output->crtc_info = find_crtc_for_output (output);
-           if (!output->crtc_info)
-               break;
+           if (output->crtc_info) {
+               if (output->crtc_info->crtc_info->noutput > 0 &&
+                   (output->crtc_info->crtc_info->noutput > 1 ||
+                    output != find_output_by_xid (output->crtc_info->crtc_info->outputs[0])))
+                   break;
+           } else {
+               output->crtc_info = find_crtc_for_output (output);
+               if (!output->crtc_info)
+                   break;
+           }
        }
     }
     /*
@@ -1545,6 +2157,26 @@ pick_crtcs (void)
     }
 }
 
+static int
+check_strtol(char *s)
+{
+    char *endptr;
+    int result = strtol(s, &endptr, 10);
+    if (s == endptr)
+       usage();
+    return result;
+}
+
+static double
+check_strtod(char *s)
+{
+    char *endptr;
+    double result = strtod(s, &endptr);
+    if (s == endptr)
+       usage();
+    return result;
+}
+
 int
 main (int argc, char **argv)
 {
@@ -1555,7 +2187,8 @@ main (int argc, char **argv)
     short              *rates;
     Status     status = RRSetConfigFailed;
     int                rot = -1;
-    int                query = 0;
+    int                query = False;
+    int                action_requested = False;
     Rotation   rotation, current_rotation, rotations;
     XRRScreenChangeNotifyEvent event;
     XRRScreenChangeNotifyEvent *sce;    
@@ -1563,7 +2196,7 @@ main (int argc, char **argv)
     int                i, j;
     SizeID     current_size;
     short      current_rate;
-    float      rate = -1;
+    double     rate = -1;
     int                size = -1;
     int                dirind = 0;
     Bool       setit = False;
@@ -1573,19 +2206,16 @@ main (int argc, char **argv)
     int                width = 0, height = 0;
     Bool       have_pixel_size = False;
     int                ret = 0;
-#if HAS_RANDR_1_2
     output_t   *output = NULL;
-    policy_t   policy = cloned;
     Bool       setit_1_2 = False;
     Bool       query_1_2 = False;
     Bool       modeit = False;
     Bool       propit = False;
     Bool       query_1 = False;
     int                major, minor;
-#endif
+    Bool       current = False;
 
     program_name = argv[0];
-    if (argc == 1) query = True;
     for (i = 1; i < argc; i++) {
        if (!strcmp ("-display", argv[i]) || !strcmp ("-d", argv[i])) {
            if (++i>=argc) usage ();
@@ -1594,6 +2224,7 @@ main (int argc, char **argv)
        }
        if (!strcmp("-help", argv[i])) {
            usage();
+           action_requested = True;
            continue;
        }
        if (!strcmp ("--verbose", argv[i])) {
@@ -1605,16 +2236,25 @@ main (int argc, char **argv)
            verbose = True;
            continue;
        }
+       if (!strcmp ("--nograb", argv[i])) {
+           grab_server = False;
+           continue;
+       }
+       if (!strcmp("--current", argv[i])) {
+           current = True;
+           continue;
+       }
 
        if (!strcmp ("-s", argv[i]) || !strcmp ("--size", argv[i])) {
            if (++i>=argc) usage ();
-           if (sscanf (argv[i], "%dx%d", &width, &height) == 2)
+           if (sscanf (argv[i], "%dx%d", &width, &height) == 2) {
                have_pixel_size = True;
-           else {
-               size = atoi (argv[i]);
-               if (size < 0) usage();
-           }
+           else {
+               size = check_strtol(argv[i]);
+                if (size < 0) usage();
+            }
            setit = True;
+           action_requested = True;
            continue;
        }
 
@@ -1623,38 +2263,39 @@ main (int argc, char **argv)
            !strcmp ("--refresh", argv[i]))
        {
            if (++i>=argc) usage ();
-           if (sscanf (argv[i], "%f", &rate) != 1)
-               usage ();
+           rate = check_strtod(argv[i]);
            setit = True;
-#if HAS_RANDR_1_2
            if (output)
            {
                output->refresh = rate;
                output->changes |= changes_refresh;
                setit_1_2 = True;
            }
-#endif
+           action_requested = True;
            continue;
        }
 
        if (!strcmp ("-v", argv[i]) || !strcmp ("--version", argv[i])) {
            version = True;
+           action_requested = True;
            continue;
        }
 
        if (!strcmp ("-x", argv[i])) {
            reflection |= RR_Reflect_X;
            setit = True;
+           action_requested = True;
            continue;
        }
        if (!strcmp ("-y", argv[i])) {
            reflection |= RR_Reflect_Y;
            setit = True;
+           action_requested = True;
            continue;
        }
        if (!strcmp ("--screen", argv[i])) {
            if (++i>=argc) usage ();
-           screen = atoi (argv[i]);
+           screen = check_strtol(argv[i]);
            if (screen < 0) usage();
            continue;
        }
@@ -1665,8 +2306,8 @@ main (int argc, char **argv)
        if (!strcmp ("-o", argv[i]) || !strcmp ("--orientation", argv[i])) {
            char *endptr;
            if (++i>=argc) usage ();
-           dirind = strtol(argv[i], &endptr, 0);
-           if (*endptr != '\0') {
+           dirind = strtol(argv[i], &endptr, 10);
+           if (argv[i] == endptr) {
                for (dirind = 0; dirind < 4; dirind++) {
                    if (strcmp (direction[dirind], argv[i]) == 0) break;
                }
@@ -1674,22 +2315,30 @@ main (int argc, char **argv)
            }
            rot = dirind;
            setit = True;
+           action_requested = True;
            continue;
        }
-#if HAS_RANDR_1_2
-       if (!strcmp ("--prop", argv[i]) || !strcmp ("--properties", argv[i]))
+       if (!strcmp ("--prop", argv[i]) ||
+           !strcmp ("--props", argv[i]) ||
+           !strcmp ("--madprops", argv[i]) ||
+           !strcmp ("--properties", argv[i]))
        {
            query_1_2 = True;
            properties = True;
+           action_requested = True;
            continue;
        }
        if (!strcmp ("--output", argv[i])) {
            if (++i >= argc) usage();
-           output = add_output ();
 
-           set_name (&output->output, argv[i], name_string|name_xid);
+           output = find_output_by_name (argv[i]);
+           if (!output) {
+               output = add_output ();
+               set_name (&output->output, argv[i], name_string|name_xid);
+           }
            
            setit_1_2 = True;
+           action_requested = True;
            continue;
        }
        if (!strcmp ("--crtc", argv[i])) {
@@ -1750,7 +2399,7 @@ main (int argc, char **argv)
        if (!strcmp ("--left-of", argv[i])) {
            if (++i>=argc) usage ();
            if (!output) usage();
-           output->relation = left_of;
+           output->relation = relation_left_of;
            output->relative_to = argv[i];
            output->changes |= changes_relation;
            continue;
@@ -1758,7 +2407,7 @@ main (int argc, char **argv)
        if (!strcmp ("--right-of", argv[i])) {
            if (++i>=argc) usage ();
            if (!output) usage();
-           output->relation = right_of;
+           output->relation = relation_right_of;
            output->relative_to = argv[i];
            output->changes |= changes_relation;
            continue;
@@ -1766,7 +2415,7 @@ main (int argc, char **argv)
        if (!strcmp ("--above", argv[i])) {
            if (++i>=argc) usage ();
            if (!output) usage();
-           output->relation = above;
+           output->relation = relation_above;
            output->relative_to = argv[i];
            output->changes |= changes_relation;
            continue;
@@ -1774,7 +2423,7 @@ main (int argc, char **argv)
        if (!strcmp ("--below", argv[i])) {
            if (++i>=argc) usage ();
            if (!output) usage();
-           output->relation = below;
+           output->relation = relation_below;
            output->relative_to = argv[i];
            output->changes |= changes_relation;
            continue;
@@ -1782,11 +2431,72 @@ main (int argc, char **argv)
        if (!strcmp ("--same-as", argv[i])) {
            if (++i>=argc) usage ();
            if (!output) usage();
-           output->relation = same_as;
+           output->relation = relation_same_as;
            output->relative_to = argv[i];
            output->changes |= changes_relation;
            continue;
        }
+       if (!strcmp ("--panning", argv[i])) {
+           XRRPanning *pan;
+           if (++i>=argc) usage ();
+           if (!output) usage();
+           pan = &output->panning;
+           switch (sscanf (argv[i], "%dx%d+%d+%d/%dx%d+%d+%d/%d/%d/%d/%d",
+                           &pan->width, &pan->height, &pan->left, &pan->top,
+                           &pan->track_width, &pan->track_height,
+                           &pan->track_left, &pan->track_top,
+                           &pan->border_left, &pan->border_top,
+                           &pan->border_right, &pan->border_bottom)) {
+           case 2:
+               pan->left = pan->top = 0;
+               /* fall through */
+           case 4:
+               pan->track_left = pan->track_top =
+                   pan->track_width = pan->track_height = 0;
+               /* fall through */
+           case 8:
+               pan->border_left = pan->border_top =
+                   pan->border_right = pan->border_bottom = 0;
+               /* fall through */
+           case 12:
+               break;
+           default:
+               usage ();
+           }
+           output->changes |= changes_panning;
+           continue;
+       }
+       if (!strcmp ("--gamma", argv[i])) {
+           if (!output) usage();
+           if (++i>=argc) usage ();
+           if (sscanf(argv[i], "%f:%f:%f", &output->gamma.red, 
+                   &output->gamma.green, &output->gamma.blue) != 3)
+               usage ();
+           output->changes |= changes_gamma;
+           setit_1_2 = True;
+           continue;
+       }
+       if (!strcmp ("--brightness", argv[i])) {
+           if (!output) usage();
+           if (++i>=argc) usage();
+           if (sscanf(argv[i], "%f", &output->brightness) != 1)
+               usage ();
+           output->changes |= changes_gamma;
+           setit_1_2 = True;
+           continue;
+       }
+       if (!strcmp ("--primary", argv[i])) {
+           if (!output) usage();
+           output->changes |= changes_primary;
+           output->primary = True;
+           setit_1_2 = True;
+           continue;
+       }
+       if (!strcmp ("--noprimary", argv[i])) {
+           no_primary = True;
+           setit_1_2 = True;
+           continue;
+       }
        if (!strcmp ("--set", argv[i])) {
            output_prop_t   *prop;
            if (!output) usage();
@@ -1802,6 +2512,66 @@ main (int argc, char **argv)
            setit_1_2 = True;
            continue;
        }
+       if (!strcmp ("--scale", argv[i]))
+       {
+           double  sx, sy;
+           if (!output) usage();
+           if (++i>=argc) usage();
+           if (sscanf (argv[i], "%lfx%lf", &sx, &sy) != 2)
+               usage ();
+           init_transform (&output->transform);
+           output->transform.transform.matrix[0][0] = XDoubleToFixed (sx);
+           output->transform.transform.matrix[1][1] = XDoubleToFixed (sy);
+           output->transform.transform.matrix[2][2] = XDoubleToFixed (1.0);
+           if (sx != 1 || sy != 1)
+               output->transform.filter = "bilinear";
+           else
+               output->transform.filter = "nearest";
+           output->transform.nparams = 0;
+           output->transform.params = NULL;
+           output->changes |= changes_transform;
+           continue;
+       }
+       if (!strcmp ("--scale-from", argv[i]))
+       {
+           int w, h;
+           if (!output) usage();
+           if (++i>=argc) usage();
+           if (sscanf (argv[i], "%dx%d", &w, &h) != 2)
+               usage ();
+           if (w <=0 || h <= 0)
+               usage ();
+           output->scale_from_w = w;
+           output->scale_from_h = h;
+           output->changes |= changes_transform;
+           continue;
+       }
+       if (!strcmp ("--transform", argv[i])) {
+           double  transform[3][3];
+           int     k, l;
+           if (!output) usage();
+           if (++i>=argc) usage ();
+           init_transform (&output->transform);
+           if (strcmp (argv[i], "none") != 0)
+           {
+               if (sscanf(argv[i], "%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf",
+                          &transform[0][0],&transform[0][1],&transform[0][2],
+                          &transform[1][0],&transform[1][1],&transform[1][2],
+                          &transform[2][0],&transform[2][1],&transform[2][2])
+                   != 9)
+                   usage ();
+               init_transform (&output->transform);
+               for (k = 0; k < 3; k++)
+                   for (l = 0; l < 3; l++) {
+                       output->transform.transform.matrix[k][l] = XDoubleToFixed (transform[k][l]);
+                   }
+               output->transform.filter = "bilinear";
+               output->transform.nparams = 0;
+               output->transform.params = NULL;
+           }
+           output->changes |= changes_transform;
+           continue;
+       }
        if (!strcmp ("--off", argv[i])) {
            if (!output) usage();
            set_name_xid (&output->mode, None);
@@ -1815,6 +2585,7 @@ main (int argc, char **argv)
                        &fb_width, &fb_height) != 2)
                usage ();
            setit_1_2 = True;
+           action_requested = True;
            continue;
        }
        if (!strcmp ("--fbmm", argv[i])) {
@@ -1823,26 +2594,20 @@ main (int argc, char **argv)
                        &fb_width_mm, &fb_height_mm) != 2)
                usage ();
            setit_1_2 = True;
+           action_requested = True;
            continue;
        }
        if (!strcmp ("--dpi", argv[i])) {
+           char *strtod_error;
            if (++i>=argc) usage ();
-           if (sscanf (argv[i], "%f", &dpi) != 1)
+           dpi = strtod(argv[i], &strtod_error);
+           if (argv[i] == strtod_error)
            {
                dpi = 0.0;
                dpi_output = argv[i];
            }
            setit_1_2 = True;
-           continue;
-       }
-       if (!strcmp ("--clone", argv[i])) {
-           policy = cloned;
-           setit_1_2 = True;
-           continue;
-       }
-       if (!strcmp ("--extend", argv[i])) {
-           policy = extend;
-           setit_1_2 = True;
+           action_requested = True;
            continue;
        }
        if (!strcmp ("--auto", argv[i])) {
@@ -1854,6 +2619,7 @@ main (int argc, char **argv)
            else
                automatic = True;
            setit_1_2 = True;
+           action_requested = True;
            continue;
        }
        if (!strcmp ("--q12", argv[i]))
@@ -1869,25 +2635,24 @@ main (int argc, char **argv)
        if (!strcmp ("--newmode", argv[i]))
        {
            umode_t  *m = malloc (sizeof (umode_t));
-           float   clock;
+           double    clock;
            
            ++i;
            if (i + 9 >= argc) usage ();
            m->mode.name = argv[i];
            m->mode.nameLength = strlen (argv[i]);
            i++;
-           if (sscanf (argv[i++], "%f", &clock) != 1)
-               usage ();
+           clock = check_strtod(argv[i++]);
            m->mode.dotClock = clock * 1e6;
 
-           if (sscanf (argv[i++], "%d", &m->mode.width) != 1) usage();
-           if (sscanf (argv[i++], "%d", &m->mode.hSyncStart) != 1) usage();
-           if (sscanf (argv[i++], "%d", &m->mode.hSyncEnd) != 1) usage();
-           if (sscanf (argv[i++], "%d", &m->mode.hTotal) != 1) usage();
-           if (sscanf (argv[i++], "%d", &m->mode.height) != 1) usage();
-           if (sscanf (argv[i++], "%d", &m->mode.vSyncStart) != 1) usage();
-           if (sscanf (argv[i++], "%d", &m->mode.vSyncEnd) != 1) usage();
-           if (sscanf (argv[i++], "%d", &m->mode.vTotal) != 1) usage();
+           m->mode.width = check_strtol(argv[i++]);
+           m->mode.hSyncStart = check_strtol(argv[i++]);
+           m->mode.hSyncEnd = check_strtol(argv[i++]);
+           m->mode.hTotal = check_strtol(argv[i++]);
+           m->mode.height = check_strtol(argv[i++]);
+           m->mode.vSyncStart = check_strtol(argv[i++]);
+           m->mode.vSyncEnd = check_strtol(argv[i++]);
+           m->mode.vTotal = check_strtol(argv[i++]);
            m->mode.modeFlags = 0;
            while (i < argc) {
                int f;
@@ -1905,6 +2670,7 @@ main (int argc, char **argv)
            m->action = umode_create;
            umodes = m;
            modeit = True;
+           action_requested = True;
            continue;
        }
        if (!strcmp ("--rmmode", argv[i]))
@@ -1917,6 +2683,7 @@ main (int argc, char **argv)
            m->next = umodes;
            umodes = m;
            modeit = True;
+           action_requested = True;
            continue;
        }
        if (!strcmp ("--addmode", argv[i]))
@@ -1931,6 +2698,7 @@ main (int argc, char **argv)
            m->next = umodes;
            umodes = m;
            modeit = True;
+           action_requested = True;
            continue;
        }
        if (!strcmp ("--delmode", argv[i]))
@@ -1945,11 +2713,13 @@ main (int argc, char **argv)
            m->next = umodes;
            umodes = m;
            modeit = True;
+           action_requested = True;
            continue;
        }
-#endif
        usage();
     }
+    if (!action_requested)
+           query = True;
     if (verbose) 
     {
        query = True;
@@ -1957,6 +2727,11 @@ main (int argc, char **argv)
            query_1 = True;
     }
 
+/*
+    if (version)
+       printf("xrandr program version       " VERSION "\n");
+*/
+
     dpy = XOpenDisplay (display_name);
 
     if (dpy == NULL) {
@@ -1973,20 +2748,22 @@ main (int argc, char **argv)
 
     root = RootWindow (dpy, screen);
 
-#if HAS_RANDR_1_2
-    if (!XRRQueryVersion (dpy, &major, &minor))
+    if (!XRRQueryExtension (dpy, &event_base, &error_base) ||
+        !XRRQueryVersion (dpy, &major, &minor))
     {
        fprintf (stderr, "RandR extension missing\n");
        exit (1);
     }
     if (major > 1 || (major == 1 && minor >= 2))
        has_1_2 = True;
+    if (major > 1 || (major == 1 && minor >= 3))
+       has_1_3 = True;
        
     if (has_1_2 && modeit)
     {
        umode_t *m;
 
-        get_screen ();
+        get_screen (current);
        get_crtcs();
        get_outputs();
        
@@ -2034,7 +2811,7 @@ main (int argc, char **argv)
     if (has_1_2 && propit)
     {
        
-        get_screen ();
+        get_screen (current);
        get_crtcs();
        get_outputs();
        
@@ -2046,9 +2823,9 @@ main (int argc, char **argv)
            {
                Atom            name = XInternAtom (dpy, prop->name, False);
                Atom            type;
-               int             format;
-               unsigned char   *data = NULL;
-               int             nelements = 0;
+               int             format = 0;
+               unsigned char   *data;
+               int             nelements;
                int             int_value;
                unsigned long   ulong_value;
                unsigned char   *prop_data;
@@ -2058,7 +2835,6 @@ main (int argc, char **argv)
                XRRPropertyInfo *propinfo;
 
                type = AnyPropertyType;
-               format=0;
                
                if (XRRGetOutputProperty (dpy, output->output.xid, name,
                                          0, 100, False, False,
@@ -2088,7 +2864,6 @@ main (int argc, char **argv)
                    ulong_value = XInternAtom (dpy, prop->value, False);
                    data = (unsigned char *) &ulong_value;
                    nelements = 1;
-                   format = 32;
                }
                else if ((type == XA_STRING || type == AnyPropertyType))
                {
@@ -2097,6 +2872,8 @@ main (int argc, char **argv)
                    nelements = strlen (prop->value);
                    format = 8;
                }
+               else
+                   continue;
                XRRChangeOutputProperty (dpy, output->output.xid,
                                         name, type, format, PropModeReplace,
                                         data, nelements);
@@ -2110,7 +2887,7 @@ main (int argc, char **argv)
     }
     if (setit_1_2)
     {
-       get_screen ();
+       get_screen (current);
        get_crtcs ();
        get_outputs ();
        set_positions ();
@@ -2181,6 +2958,16 @@ main (int argc, char **argv)
        }
        
        /*
+        * Set panning
+        */
+       set_panning ();
+
+       /* 
+        * Set gamma on crtc's that belong to the outputs.
+        */
+       set_gamma ();
+
+       /*
         * Now apply all of the changes
         */
        apply ();
@@ -2194,7 +2981,7 @@ main (int argc, char **argv)
        
 #define ModeShown   0x80000000
        
-       get_screen ();
+       get_screen (current);
        get_crtcs ();
        get_outputs ();
 
@@ -2206,18 +2993,25 @@ main (int argc, char **argv)
        for (output = outputs; output; output = output->next)
        {
            XRROutputInfo   *output_info = output->output_info;
+           crtc_t          *crtc = output->crtc_info;
+           XRRCrtcInfo     *crtc_info = crtc ? crtc->crtc_info : NULL;
            XRRModeInfo     *mode = output->mode_info;
            Atom            *props;
            int             j, k, nprop;
            Bool            *mode_shown;
+           Rotation        rotations = output_rotations (output);
 
            printf ("  <output name=\"%s\" connected=\"%s\"", output_info->name, connection[output_info->connection]);
            if (mode)
            {
-               printf (" w=\"%d\" h=\"%d\" x=\"%d\" y=\"%d\"",
-                       mode_width (mode, output->rotation),
-                       mode_height (mode, output->rotation),
-                       output->x, output->y);
+               if (crtc_info) {
+                   printf (" w=\"%d\" h=\"%d\" x=\"%d\" y=\"%d\"",
+                           crtc_info->width, crtc_info->height,
+                           crtc_info->x, crtc_info->y);
+               } else {
+                   printf (" w=\"%d\" h=\"%d\" x=\"%d\" y=\"%d\"",
+                           mode->width, mode->height, output->x, output->y);
+               }
                if (verbose)
                    printf (" id=\"%lx\"", mode->id);
                if (output->rotation != RR_Rotate_0 || verbose)
@@ -2237,7 +3031,6 @@ main (int argc, char **argv)
                    if ((rotations >> i) & 1) {
                        if (!first) printf (" "); first = False;
                        printf("%s", direction[i]);
-                       first = False;
                    }
                }
                if (rotations & RR_Reflect_X)
@@ -2247,30 +3040,58 @@ main (int argc, char **argv)
                }
                if (rotations & RR_Reflect_Y)
                {
-                   if (!first) printf (" "); first = False;
+                   if (!first) printf (" ");
                    printf ("y axis");
                }
                printf (")");
            }
 */
+
            if (mode)
            {
-               printf (" wmm=\"%lu\" hmm=\"%lu\"",
-                       output_info->mm_width, output_info->mm_height);
+               printf (" wmm=\"%d\" hmm=\"%d\"",
+                       (int)output_info->mm_width, (int)output_info->mm_height);
+           }
+
+           if (crtc && crtc->panning_info && crtc->panning_info->width > 0)
+           {
+               XRRPanning *pan = crtc->panning_info;
+               printf (" panning %dx%d+%d+%d",
+                       pan->width, pan->height, pan->left, pan->top);
+               if ((pan->track_width    != 0 &&
+                    (pan->track_left    != pan->left           ||
+                     pan->track_width   != pan->width          ||
+                     pan->border_left   != 0                   ||
+                     pan->border_right  != 0))                 ||
+                   (pan->track_height   != 0 &&
+                    (pan->track_top     != pan->top            ||
+                     pan->track_height  != pan->height         ||
+                     pan->border_top    != 0                   ||
+                     pan->border_bottom != 0)))
+                   printf (" tracking %dx%d+%d+%d border %d/%d/%d/%d",
+                           pan->track_width,  pan->track_height,
+                           pan->track_left,   pan->track_top,
+                           pan->border_left,  pan->border_top,
+                           pan->border_right, pan->border_bottom);
            }
            printf (">\n");
 
            if (verbose)
            {
-               printf ("\tIdentifier: 0x%lx\n", output->output.xid);
-               printf ("\tTimestamp:  %lu\n", output_info->timestamp);
+               printf ("\tIdentifier: 0x%x\n", (int)output->output.xid);
+               printf ("\tTimestamp:  %d\n", (int)output_info->timestamp);
                printf ("\tSubpixel:   %s\n", order[output_info->subpixel_order]);
+               if (output->gamma.red != 0.0 && output->gamma.green != 0.0 && output->gamma.blue != 0.0) {
+                   printf ("\tGamma:      %#.2g:%#.2g:%#.2g\n",
+                           output->gamma.red, output->gamma.green, output->gamma.blue);
+                   printf ("\tBrightness: %#.2g\n", output->brightness);
+               }
                printf ("\tClones:    ");
                for (j = 0; j < output_info->nclone; j++)
                {
-                   output_t    *cloned = find_output_by_xid (output_info->clones[j]);
+                   output_t    *clone = find_output_by_xid (output_info->clones[j]);
 
-                   if (cloned) printf (" %s", cloned->output.string);
+                   if (clone) printf (" %s", clone->output.string);
                }
                printf ("\n");
                if (output->crtc_info)
@@ -2283,6 +3104,33 @@ main (int argc, char **argv)
                        printf (" %d", crtc->crtc.index);
                }
                printf ("\n");
+               if (output->crtc_info && output->crtc_info->panning_info) {
+                   XRRPanning *pan = output->crtc_info->panning_info;
+                   printf ("\tPanning:    %dx%d+%d+%d\n",
+                           pan->width, pan->height, pan->left, pan->top);
+                   printf ("\tTracking:   %dx%d+%d+%d\n",
+                           pan->track_width,  pan->track_height,
+                           pan->track_left,   pan->track_top);
+                   printf ("\tBorder:     %d/%d/%d/%d\n",
+                           pan->border_left,  pan->border_top,
+                           pan->border_right, pan->border_bottom);
+               }
+           }
+           if (verbose)
+           {
+               int x, y;
+
+               printf ("\tTransform: ");
+               for (y = 0; y < 3; y++)
+               {
+                   for (x = 0; x < 3; x++)
+                       printf (" %f", XFixedToDouble (output->transform.transform.matrix[y][x]));
+                   if (y < 2)
+                       printf ("\n\t           ");
+               }
+               if (output->transform.filter)
+                   printf ("\n\t           filter: %s", output->transform.filter);
+               printf ("\n");
            }
            if (verbose || properties)
            {
@@ -2318,26 +3166,35 @@ main (int argc, char **argv)
                    } else if (actual_type == XA_INTEGER &&
                               actual_format == 32)
                    {
-                       printf("\t%s: %d (0x%08x)",
-                              XGetAtomName (dpy, props[j]),
-                              *(int32_t*)prop, *(uint32_t*)prop);
+                       printf("\t%s: ", XGetAtomName (dpy, props[j]));
+                       for (k = 0; k < nitems; k++) {
+                           if (k > 0)
+                               printf ("\n\t\t\t");
+                           printf("%d (0x%08x)",
+                                  (int)((INT32 *)prop)[k], (int)((INT32 *)prop)[k]);
+                       }
 
                        if (propinfo->range && propinfo->num_values > 0) {
-                           printf(" range%s: ",
+                           if (nitems > 1)
+                               printf ("\n\t\t");
+                           printf("\trange%s: ",
                                   (propinfo->num_values == 2) ? "" : "s");
 
                            for (k = 0; k < propinfo->num_values / 2; k++)
-                               printf(" (%ld,%ld)", propinfo->values[k * 2],
-                                      propinfo->values[k * 2 + 1]);
+                               printf(" (%d,%d)", (int)propinfo->values[k * 2],
+                                      (int)propinfo->values[k * 2 + 1]);
                        }
 
                        printf("\n");
                    } else if (actual_type == XA_ATOM &&
                               actual_format == 32)
                    {
-                       printf("\t%s: %s",
-                              XGetAtomName (dpy, props[j]),
-                              XGetAtomName (dpy, *(Atom *)prop));
+                       printf("\t%s:", XGetAtomName (dpy, props[j]));
+                       for (k = 0; k < nitems; k++) {
+                           if (k > 0 && (k & 1) == 0)
+                               printf ("\n\t\t");
+                           printf("\t%s", XGetAtomName (dpy, ((Atom *)prop)[k]));
+                       }
 
                        if (!propinfo->range && propinfo->num_values > 0) {
                            printf("\n\t\tsupported:");
@@ -2351,17 +3208,18 @@ main (int argc, char **argv)
                            }
                        }
                        printf("\n");
-                       
                    } else if (actual_format == 8) {
-                       printf ("\t\t%s: %s%s\n", XGetAtomName (dpy, props[j]),
+                       printf ("\t%s: %s%s\n", XGetAtomName (dpy, props[j]),
                                prop, bytes_after ? "..." : "");
                    } else {
-                       printf ("\t\t%s: ????\n", XGetAtomName (dpy, props[j]));
+                       char    *type = actual_type ? XGetAtomName (dpy, actual_type) : "none";
+                       printf ("\t%s: %s(%d) (format %d items %d) ????\n",
+                               XGetAtomName (dpy, props[j]),
+                               type, (int)actual_type, actual_format, (int)nitems);
                    }
 
                    free(propinfo);
                }
-              printf("  </output>\n");
            }
            
            if (verbose)
@@ -2371,12 +3229,16 @@ main (int argc, char **argv)
                    XRRModeInfo *mode = find_mode_by_xid (output_info->modes[j]);
                    int         f;
                    
-                   printf ("  %s (0x%lx) %6.1fMHz",
-                           mode->name, mode->id,
-                           (float)mode->dotClock / 1000000.0);
+                   printf ("  %s (0x%x) %6.1fMHz",
+                           mode->name, (int)mode->id,
+                           (double)mode->dotClock / 1000000.0);
                    for (f = 0; mode_flags[f].flag; f++)
                        if (mode->modeFlags & mode_flags[f].flag)
                            printf (" %s", mode_flags[f].string);
+                   if (mode == output->mode_info)
+                       printf (" *current");
+                   if (j < output_info->npreferred)
+                       printf (" +preferred");
                    printf ("\n");
                    printf ("        h: width  %4d start %4d end %4d total %4d skew %4d clock %6.1fKHz\n",
                            mode->width, mode->hSyncStart, mode->hSyncEnd,
@@ -2414,40 +3276,36 @@ main (int argc, char **argv)
                            printf (" preferred=\"true\"");
                        else
                            printf (" preferred=\"false\"");
-                        printf("/>\n");
+                       printf("/>\n");
                    }
                }
                free (mode_shown);
            }
-
            printf("  </output>\n");
        }
-
-/* 
-        printf("  <unused>\n");
+       
+/*
        for (m = 0; m < res->nmode; m++)
        {
            XRRModeInfo *mode = &res->modes[m];
 
            if (!(mode->modeFlags & ModeShown))
            {
-               printf ("    <modeline name=\"%s\" id=\"%x\" mhz=\"%.1f\"",
-                       mode->name, mode->id,
-                       (float)mode->dotClock / 1000000.0);
-               printf (" hwidth=\"%d\" hstart=\"%d\" hend=\"%d\" htotal=\"%d\" hskew=\"%d=\" hclock=\"%.1fKHz\"",
+               printf ("  %s (0x%x) %6.1fMHz\n",
+                       mode->name, (int)mode->id,
+                       (double)mode->dotClock / 1000000.0);
+               printf ("        h: width  %4d start %4d end %4d total %4d skew %4d clock %6.1fKHz\n",
                        mode->width, mode->hSyncStart, mode->hSyncEnd,
                        mode->hTotal, mode->hSkew, mode_hsync (mode) / 1000);
-               printf (" vheight=\"%d\" vstart=\"%d\" vend=\"%d\" vtotal=\"%d\" vclock=\"%.1fHz\"/>\n",
+               printf ("        v: height %4d start %4d end %4d total %4d           clock %6.1fHz\n",
                        mode->height, mode->vSyncStart, mode->vSyncEnd, mode->vTotal,
                        mode_refresh (mode));
            }
        }
-        printf("  </unused>\n");
 */
-        printf("</screen>\n");
+       printf("</screen>\n");
        exit (0);
     }
-#endif
     
     sc = XRRGetScreenInfo (dpy, root);
 
@@ -2582,11 +3440,9 @@ main (int argc, char **argv)
     if (setit && !dryrun) XRRSelectInput (dpy, root,
                               RRScreenChangeNotifyMask);
     if (setit && !dryrun) status = XRRSetScreenConfigAndRate (dpy, sc,
-                                                  DefaultRootWindow (dpy), 
+                                                  root,
                                                   (SizeID) size, (Rotation) (rotation | reflection), rate, CurrentTime);
 
-    XRRQueryExtension(dpy, &event_base, &error_base);
-
     if (setit && !dryrun && status == RRSetConfigFailed) {
        printf ("Failed to change the screen configuration!\n");
        ret = 1;
index e837809..d4e93db 100644 (file)
@@ -1351,7 +1351,7 @@ bool CApplication::Initialize()
   ResetScreenSaver();
 
 #ifdef HAS_SDL_JOYSTICK
-  g_Joystick.Initialize();
+  g_Joystick.SetEnabled(g_guiSettings.GetBool("input.enablejoystick"));
 #endif
 
   return true;
@@ -2815,8 +2815,9 @@ bool CApplication::ProcessGamepad(float frameTime)
 #ifdef HAS_SDL_JOYSTICK
   if (!m_AppFocused)
     return false;
+
   int iWin = GetActiveWindowID();
-  int bid;
+  int bid = 0;
   g_Joystick.Update();
   if (g_Joystick.GetButton(bid))
   {
@@ -2875,7 +2876,7 @@ bool CApplication::ProcessGamepad(float frameTime)
       g_Joystick.ResetAxis(abs(bid));
     }
   }
-  int position;
+  int position = 0;
   if (g_Joystick.GetHat(bid, position))
   {
     // reset Idle Timer
@@ -2894,7 +2895,7 @@ bool CApplication::ProcessGamepad(float frameTime)
 
     bid = position<<16|bid;
 
-    if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_HAT, actionID, actionName, fullrange))
+    if (bid && CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_HAT, actionID, actionName, fullrange))
     {
       CAction action(actionID, 1.0f, 0.0f, actionName);
       g_audioManager.PlayActionSound(action);
@@ -3060,6 +3061,16 @@ bool CApplication::ProcessJsonRpcButtons()
 {
 #ifdef HAS_JSONRPC
   CKey tempKey(JSONRPC::CInputOperations::GetKey());
+  if (tempKey.GetButtonCode() == KEY_UNICODE && tempKey.GetUnicode() != 0)
+  {
+    XBMC_Event event = { 0 };
+    event.type = XBMC_KEYDOWN;
+    event.key.type = XBMC_KEYDOWN;
+    event.key.keysym.unicode = (uint16_t)tempKey.GetUnicode();
+    event.key.keysym.sym = (XBMCKey)tempKey.GetUnicode();
+
+    return OnEvent(event);
+  }
   if (tempKey.GetButtonCode() != KEY_INVALID)
   {
     tempKey.SetFromService(true);
@@ -5409,6 +5420,13 @@ float CApplication::GetPercentage() const
 {
   if (IsPlaying() && m_pPlayer)
   {
+    if (m_pPlayer->GetTotalTime() == 0 && IsPlayingAudio() && m_itemCurrentFile->HasMusicInfoTag())
+    {
+      const CMusicInfoTag& tag = *m_itemCurrentFile->GetMusicInfoTag();
+      if (tag.GetDuration() > 0)
+        return (float)(GetTime() / tag.GetDuration() * 100);
+    }
+
     if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
       return (float)(GetTime() / GetTotalTime() * 100);
     else
@@ -5560,12 +5578,20 @@ void CApplication::StartVideoScan(const CStdString &strDirectory, bool scanAll)
   m_videoInfoScanner->Start(strDirectory,scanAll);
 }
 
-void CApplication::StartMusicScan(const CStdString &strDirectory)
+void CApplication::StartMusicScan(const CStdString &strDirectory, int flags)
 {
   if (m_musicInfoScanner->IsScanning())
     return;
 
-  if (!g_guiSettings.GetBool("musiclibrary.backgroundupdate"))
+  if (!flags)
+  { // setup default flags
+    if (g_guiSettings.GetBool("musiclibrary.downloadinfo"))
+      flags |= CMusicInfoScanner::SCAN_ONLINE;
+    if (g_guiSettings.GetBool("musiclibrary.backgroundupdate"))
+      flags |= CMusicInfoScanner::SCAN_BACKGROUND;
+  }
+
+  if (!(flags & CMusicInfoScanner::SCAN_BACKGROUND))
   {
     CGUIDialogMusicScan *musicScan = (CGUIDialogMusicScan *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_SCAN);
     if (musicScan)
@@ -5575,7 +5601,7 @@ void CApplication::StartMusicScan(const CStdString &strDirectory)
     }
   }
   SaveMusicScanSettings();
-  m_musicInfoScanner->Start(strDirectory);
+  m_musicInfoScanner->Start(strDirectory, flags);
 }
 
 void CApplication::StartMusicAlbumScan(const CStdString& strDirectory,
index ca95da8..2ce5bdb 100644 (file)
@@ -230,7 +230,7 @@ public:
   void StartVideoCleanup();
 
   void StartVideoScan(const CStdString &path, bool scanAll = false);
-  void StartMusicScan(const CStdString &path);
+  void StartMusicScan(const CStdString &path, int flags = 0);
   void StartMusicAlbumScan(const CStdString& strDirectory, bool refresh=false);
   void StartMusicArtistScan(const CStdString& strDirectory, bool refresh=false);
 
index c2b94a3..40273e8 100644 (file)
@@ -189,6 +189,8 @@ const infomap player_labels[] =  {{ "hasmedia",         PLAYER_HAS_MEDIA },
                                   { "folderpath",       PLAYER_PATH },
                                   { "filenameandpath",  PLAYER_FILEPATH }};
 
+const infomap player_param[] =   {{ "property",         PLAYER_ITEM_PROPERTY }};
+
 const infomap player_times[] =   {{ "seektime",         PLAYER_SEEKTIME },
                                   { "seekoffset",       PLAYER_SEEKOFFSET },
                                   { "timeremaining",    PLAYER_TIME_REMAINING },
@@ -683,6 +685,14 @@ int CGUIInfoManager::TranslateSingleString(const CStdString &strCondition)
         if (prop.name == player_times[i].str)
           return AddMultiInfo(GUIInfo(player_times[i].val, TranslateTimeFormat(prop.param())));
       }
+      if (prop.num_params() == 1)
+      {
+        for (size_t i = 0; i < sizeof(player_param) / sizeof(infomap); i++)
+        {
+          if (prop.name == player_param[i].str)
+            return AddMultiInfo(GUIInfo(player_param[i].val, ConditionalStringParameter(prop.param())));
+        }
+      }
     }
     else if (cat.name == "weather")
     {
@@ -2741,6 +2751,10 @@ CStdString CGUIInfoManager::GetMultiInfoLabel(const GUIInfo &info, int contextWi
     if (m_seekOffset > 0)
       return "+" + seekOffset;
   }
+  else if (info.m_info == PLAYER_ITEM_PROPERTY)
+  {
+    return m_currentFile->GetProperty(m_stringParameters[info.GetData1()]).asString();
+  }
   else if (info.m_info == SYSTEM_TIME)
   {
     return GetTime((TIME_FORMAT)info.GetData1());
index 8121e6f..f4d7c35 100644 (file)
@@ -103,6 +103,7 @@ namespace INFO
 #define PLAYER_FILEPATH              46
 #define PLAYER_SEEKOFFSET            47
 #define PLAYER_PROGRESS_CACHE        48
+#define PLAYER_ITEM_PROPERTY         49
 
 #define WEATHER_CONDITIONS          100
 #define WEATHER_TEMPERATURE         101
index 137ff4a..e55570b 100644 (file)
@@ -93,18 +93,29 @@ CNfoFile::NFOResult CNfoFile::Create(const CStdString& strPath, const ScraperPtr
 
   vector<ScraperPtr> vecScrapers;
 
-  // add selected scraper
+  // add selected scraper - first proirity
   if (m_info)
     vecScrapers.push_back(m_info);
 
+  // Add all scrapers except selected and default
   VECADDONS addons;
   CAddonMgr::Get().GetAddons(m_type,addons);
-  // first pass - add language based scrapers
-  if (m_info && g_guiSettings.GetBool("scrapers.langfallback"))
-    AddScrapers(addons,vecScrapers);
 
-  // add default scraper
-  if (defaultScraper && m_info && m_info->ID() != defaultScraper->ID())
+  for (unsigned i = 0; i < addons.size(); ++i)
+  {
+    ScraperPtr scraper = boost::dynamic_pointer_cast<CScraper>(addons[i]);
+
+    // skip if scraper requires settings and there's nothing set yet
+    if (scraper->RequiresSettings() && !scraper->HasUserSettings())
+      continue;
+
+    if( (!m_info || m_info->ID() != scraper->ID()) && (!defaultScraper || defaultScraper->ID() != scraper->ID()) )
+      vecScrapers.push_back(scraper);
+  }
+
+  // add default scraper - not user selectable so it's last priority
+  if( defaultScraper && (!m_info || m_info->ID() != defaultScraper->ID()) &&
+      ( !defaultScraper->RequiresSettings() || defaultScraper->HasUserSettings() ) )
     vecScrapers.push_back(defaultScraper);
 
   // search ..
@@ -179,20 +190,3 @@ void CNfoFile::Close()
   m_doc = NULL;
   m_scurl.Clear();
 }
-
-void CNfoFile::AddScrapers(VECADDONS& addons,
-                           vector<ScraperPtr>& vecScrapers)
-{
-  for (unsigned i=0;i<addons.size();++i)
-  {
-    ScraperPtr scraper = boost::dynamic_pointer_cast<CScraper>(addons[i]);
-
-    // skip if scraper requires settings and there's nothing set yet
-    if (scraper->RequiresSettings() && !scraper->HasUserSettings())
-      continue;
-
-    // add same language and multi-language
-    if (scraper->Language() == m_info->Language() || scraper->Language().Equals("multi"))
-      vecScrapers.push_back(scraper);
-  }
-}
index ffa2844..95ca81a 100644 (file)
@@ -81,8 +81,6 @@ private:
 
   int Load(const CStdString&);
   int Scrape(ADDON::ScraperPtr& scraper);
-  void AddScrapers(ADDON::VECADDONS& addons,
-                   std::vector<ADDON::ScraperPtr>& vecScrapers);
 };
 
 #endif // !defined(AFX_NfoFile_H__641CCF68_6D2A_426E_9204_C0E4BEF12D00__INCLUDED_)
index 19a0d84..0d4bfbb 100644 (file)
 #ifdef HAS_PYTHON
 #include "interfaces/python/XBPython.h"
 #endif
+#if defined(TARGET_WINDOWS)
+#include "input/windows/WINJoystick.h"
+#elif defined(HAS_SDL_JOYSTICK) 
+#include "input/SDLJoystick.h"
+#endif
+
+
 
   CGUISettings       g_guiSettings;
   CSettings          g_settings;
@@ -57,6 +64,9 @@
   CGUITextureManager g_TextureManager;
   CGUILargeTextureManager g_largeTextureManager;
   CMouseStat         g_Mouse;
+#if defined(HAS_SDL_JOYSTICK) 
+  CJoystick          g_Joystick; 
+#endif
   CGUIPassword       g_passwordManager;
   CGUIInfoManager    g_infoManager;
 
index 7747431..bdcf8c2 100644 (file)
@@ -74,81 +74,70 @@ bool CTextureDatabase::CreateTables()
 
 bool CTextureDatabase::UpdateOldVersion(int version)
 {
-  BeginTransaction();
-  try
-  {
-    if (version < 7)
-    { // update all old thumb://foo urls to image://foo?size=thumb
-      m_pDS->query("select id,texture from path where texture like 'thumb://%'");
-      while (!m_pDS->eof())
-      {
-        unsigned int id = m_pDS->fv(0).get_asInt();
-        CURL url(m_pDS->fv(1).get_asString());
-        m_pDS2->exec(PrepareSQL("update path set texture='image://%s?size=thumb' where id=%u", url.GetHostName().c_str(), id));
-        m_pDS->next();
-      }
-      m_pDS->query("select id, url from texture where url like 'thumb://%'");
-      while (!m_pDS->eof())
-      {
-        unsigned int id = m_pDS->fv(0).get_asInt();
-        CURL url(m_pDS->fv(1).get_asString());
-        m_pDS2->exec(PrepareSQL("update texture set url='image://%s?size=thumb', urlhash=0 where id=%u", url.GetHostName().c_str(), id));
-        m_pDS->next();
-      }
-      m_pDS->close();
-    }
-    if (version < 8)
-    { // get rid of old cached thumbs as they were previously set to the cached thumb name instead of the source thumb
-      m_pDS->exec("delete from path");
-    }
-    if (version < 9)
-    { // get rid of the old path table and add the type column
-      m_pDS->dropIndex("path", "idxPath");
-      m_pDS->exec("DROP TABLE path");
-      m_pDS->exec("CREATE TABLE path (id integer primary key, urlhash integer, url text, type text, texture text)\n");
-      m_pDS->exec("CREATE INDEX idxPath ON path(urlhash, type)");
-    }
-    if (version < 10)
-    { // get rid of urlhash in both tables...
-      m_pDS->dropIndex("path", "idxPath");
-      m_pDS->exec("DROP TABLE path");
-      m_pDS->exec("CREATE TABLE path (id integer primary key, url text, type text, texture text)\n");
-      m_pDS->exec("CREATE INDEX idxPath ON path(url, type)");
-
-      m_pDS->dropIndex("texture", "idxTexture");
-      m_pDS->exec("CREATE TEMPORARY TABLE texture_backup(id,url,cachedurl,usecount,lastusetime,imagehash,lasthashcheck)");
-      m_pDS->exec("INSERT INTO texture_backup SELECT id,url,cachedurl,usecount,lastusetime,imagehash,lasthashcheck FROM texture");
-      m_pDS->exec("DROP TABLE texture");
-      m_pDS->exec("CREATE TABLE texture (id integer primary key, url text, cachedurl text, usecount integer, lastusetime text, imagehash text, lasthashcheck text)");
-      m_pDS->exec("CREATE INDEX idxTexture ON texture(url)");
-      m_pDS->exec("INSERT INTO texture SELECT * FROM texture_backup");
-      m_pDS->exec("DROP TABLE texture_backup");
-    }
-    if (version < 11)
-    { // get rid of cached URLs that don't have the correct extension
-      m_pDS->exec("DELETE FROM texture WHERE SUBSTR(cachedUrl,-4,4) NOT IN ('.jpg', '.png')");
+  if (version < 7)
+  { // update all old thumb://foo urls to image://foo?size=thumb
+    m_pDS->query("select id,texture from path where texture like 'thumb://%'");
+    while (!m_pDS->eof())
+    {
+      unsigned int id = m_pDS->fv(0).get_asInt();
+      CURL url(m_pDS->fv(1).get_asString());
+      m_pDS2->exec(PrepareSQL("update path set texture='image://%s?size=thumb' where id=%u", url.GetHostName().c_str(), id));
+      m_pDS->next();
     }
-    if (version < 12)
-    { // create new sizes table and move usecount info to it.
-      m_pDS->exec("DROP TABLE texture");
-      m_pDS->exec("CREATE TABLE texture (id integer primary key, url text, cachedurl text, imagehash text, lasthashcheck text)");
-      m_pDS->exec("CREATE INDEX idxTexture ON texture(url)");
-      m_pDS->exec("CREATE TABLE sizes (idtexture integer, size integer, width integer, height integer, usecount integer, lastusetime text)");
-      m_pDS->exec("CREATE INDEX idxSize ON sizes(idtexture, size)");
-      m_pDS->exec("CREATE TRIGGER textureDelete AFTER delete ON texture FOR EACH ROW BEGIN delete from sizes where sizes.idtexture=old.id; END");
-    }
-    if (version < 13)
-    { // index for updateusecount
-      m_pDS->exec("CREATE INDEX idxSize2 ON sizes(idtexture, width, height)");
+    m_pDS->query("select id, url from texture where url like 'thumb://%'");
+    while (!m_pDS->eof())
+    {
+      unsigned int id = m_pDS->fv(0).get_asInt();
+      CURL url(m_pDS->fv(1).get_asString());
+      m_pDS2->exec(PrepareSQL("update texture set url='image://%s?size=thumb', urlhash=0 where id=%u", url.GetHostName().c_str(), id));
+      m_pDS->next();
     }
+    m_pDS->close();
   }
-  catch (...)
-  {
-    CLog::Log(LOGERROR, "%s(%d) failed", __FUNCTION__, version);
-    RollbackTransaction();
-    return false;
+  if (version < 8)
+  { // get rid of old cached thumbs as they were previously set to the cached thumb name instead of the source thumb
+    m_pDS->exec("delete from path");
+  }
+  if (version < 9)
+  { // get rid of the old path table and add the type column
+    m_pDS->dropIndex("path", "idxPath");
+    m_pDS->exec("DROP TABLE path");
+    m_pDS->exec("CREATE TABLE path (id integer primary key, urlhash integer, url text, type text, texture text)\n");
+    m_pDS->exec("CREATE INDEX idxPath ON path(urlhash, type)");
+  }
+  if (version < 10)
+  { // get rid of urlhash in both tables...
+    m_pDS->dropIndex("path", "idxPath");
+    m_pDS->exec("DROP TABLE path");
+    m_pDS->exec("CREATE TABLE path (id integer primary key, url text, type text, texture text)\n");
+    m_pDS->exec("CREATE INDEX idxPath ON path(url, type)");
+
+    m_pDS->dropIndex("texture", "idxTexture");
+    m_pDS->exec("CREATE TEMPORARY TABLE texture_backup(id,url,cachedurl,usecount,lastusetime,imagehash,lasthashcheck)");
+    m_pDS->exec("INSERT INTO texture_backup SELECT id,url,cachedurl,usecount,lastusetime,imagehash,lasthashcheck FROM texture");
+    m_pDS->exec("DROP TABLE texture");
+    m_pDS->exec("CREATE TABLE texture (id integer primary key, url text, cachedurl text, usecount integer, lastusetime text, imagehash text, lasthashcheck text)");
+    m_pDS->exec("CREATE INDEX idxTexture ON texture(url)");
+    m_pDS->exec("INSERT INTO texture SELECT * FROM texture_backup");
+    m_pDS->exec("DROP TABLE texture_backup");
+  }
+  if (version < 11)
+  { // get rid of cached URLs that don't have the correct extension
+    m_pDS->exec("DELETE FROM texture WHERE SUBSTR(cachedUrl,-4,4) NOT IN ('.jpg', '.png')");
+  }
+  if (version < 12)
+  { // create new sizes table and move usecount info to it.
+    m_pDS->exec("DROP TABLE texture");
+    m_pDS->exec("CREATE TABLE texture (id integer primary key, url text, cachedurl text, imagehash text, lasthashcheck text)");
+    m_pDS->exec("CREATE INDEX idxTexture ON texture(url)");
+    m_pDS->exec("CREATE TABLE sizes (idtexture integer, size integer, width integer, height integer, usecount integer, lastusetime text)");
+    m_pDS->exec("CREATE INDEX idxSize ON sizes(idtexture, size)");
+    m_pDS->exec("CREATE TRIGGER textureDelete AFTER delete ON texture FOR EACH ROW BEGIN delete from sizes where sizes.idtexture=old.id; END");
+  }
+  if (version < 13)
+  { // index for updateusecount
+    m_pDS->exec("CREATE INDEX idxSize2 ON sizes(idtexture, width, height)");
   }
-  CommitTransaction();
   return true;
 }
 
index 8d8a37f..3e34e78 100644 (file)
@@ -388,9 +388,15 @@ bool CVideoThumbLoader::FillLibraryArt(CFileItem *pItem)
     // For episodes and seasons, we want to set fanart for that of the show
     if (!pItem->HasProperty("fanart_image") && tag.m_iIdShow >= 0)
     {
-      string fanart = m_database->GetArtForItem(tag.m_iIdShow, "tvshow", "fanart");
-      if (!fanart.empty())
-        pItem->SetProperty("fanart_image", fanart);
+      map<string, string> showArt;
+      if (m_database->GetArtForItem(tag.m_iIdShow, "tvshow", showArt))
+      {
+        map<string, string>::iterator i = showArt.find("fanart");
+        if (i != showArt.end())
+          pItem->SetProperty("fanart_image", i->second);
+        if ((i = showArt.find("thumb")) != showArt.end())
+          pItem->SetProperty("tvshowthumb", i->second);
+      }
     }
     m_database->Close();
   }
index e1f0001..fa13a3a 100644 (file)
@@ -101,32 +101,20 @@ bool CAddonDatabase::CreateTables()
 
 bool CAddonDatabase::UpdateOldVersion(int version)
 {
-  BeginTransaction();
-  
-  try
+  if (version < 13)
   {
-    if (version < 13)
-    {
-      m_pDS->exec("CREATE TABLE dependencies (id integer, addon text, version text, optional boolean)\n");
-      m_pDS->exec("CREATE INDEX idxDependencies ON dependencies(id)");
-    }
-    if (version < 14)
-    {
-      m_pDS->exec("ALTER TABLE addon add minversion text");
-    }
-    if (version < 15)
-    {
-      m_pDS->exec("CREATE TABLE blacklist (id integer primary key, addonID text, version text)\n");
-      m_pDS->exec("CREATE UNIQUE INDEX idxBlack ON blacklist(addonID)");
-    }
+    m_pDS->exec("CREATE TABLE dependencies (id integer, addon text, version text, optional boolean)\n");
+    m_pDS->exec("CREATE INDEX idxDependencies ON dependencies(id)");
   }
-  catch (...)
+  if (version < 14)
   {
-    CLog::Log(LOGERROR, "Error attempting to upgrade an old addon database!");
-    RollbackTransaction();
-    return false;
+    m_pDS->exec("ALTER TABLE addon add minversion text");
+  }
+  if (version < 15)
+  {
+    m_pDS->exec("CREATE TABLE blacklist (id integer primary key, addonID text, version text)\n");
+    m_pDS->exec("CREATE UNIQUE INDEX idxBlack ON blacklist(addonID)");
   }
-  CommitTransaction();
   return true;
 }
 
index f57ad05..dd43e20 100644 (file)
@@ -398,19 +398,26 @@ ADDON_STATUS CAddonDll<TheDll, TheStruct, TheProps>::TransferSettings()
       ADDON_STATUS status = ADDON_STATUS_OK;
       const char *id = setting->Attribute("id");
       const char *type = setting->Attribute("type");
+      const char *option = setting->Attribute("option");
 
       if (type)
       {
-        if (strcmpi(type, "text") == 0 || strcmpi(type, "ipaddress") == 0 ||
-          strcmpi(type, "folder") == 0 || strcmpi(type, "action") == 0 ||
-          strcmpi(type, "music") == 0 || strcmpi(type, "pictures") == 0 ||
-          strcmpi(type, "folder") == 0 || strcmpi(type, "programs") == 0 ||
-          strcmpi(type, "files") == 0 || strcmpi(type, "fileenum") == 0)
+        if (strcmpi(type,"sep") == 0 || strcmpi(type,"lsep") == 0)
+        {
+          /* Don't propagate separators */
+        }
+        else if (strcmpi(type, "text") == 0 || strcmpi(type, "ipaddress") == 0 ||
+          strcmpi(type, "video") == 0 || strcmpi(type, "audio") == 0 ||
+          strcmpi(type, "image") == 0 || strcmpi(type, "folder") == 0 ||
+          strcmpi(type, "executable") == 0 || strcmpi(type, "file") == 0 ||
+          strcmpi(type, "action") == 0 || strcmpi(type, "date") == 0 ||
+          strcmpi(type, "time") == 0 || strcmpi(type, "select") == 0 ||
+          strcmpi(type, "addon") == 0 || strcmpi(type, "labelenum") == 0 ||
+          strcmpi(type, "fileenum") == 0 )
         {
           status = m_pDll->SetSetting(id, (const char*) GetSetting(id).c_str());
         }
-        else if (strcmpi(type, "integer") == 0 || strcmpi(type, "enum") == 0 ||
-          strcmpi(type, "labelenum") == 0 || strcmpi(type, "rangeofnum") == 0)
+        else if (strcmpi(type, "enum") == 0)
         {
           int tmp = atoi(GetSetting(id));
           status = m_pDll->SetSetting(id, (int*) &tmp);
@@ -420,9 +427,27 @@ ADDON_STATUS CAddonDll<TheDll, TheStruct, TheProps>::TransferSettings()
           bool tmp = (GetSetting(id) == "true") ? true : false;
           status = m_pDll->SetSetting(id, (bool*) &tmp);
         }
+        else if (strcmpi(type, "rangeofnum") == 0 || strcmpi(type, "slider") == 0 ||
+                 strcmpi(type, "number") == 0)
+        {
+          float tmpf = (float)atof(GetSetting(id));
+          int   tmpi;
+
+          if (option && strcmpi(option,"int") == 0)
+          {
+            tmpi = (int)floor(tmpf);
+            status = m_pDll->SetSetting(id, (int*) &tmpi);
+          }
+          else
+          {
+            status = m_pDll->SetSetting(id, (float*) &tmpf);
+          }
+        }
         else
         {
+          /* Log unknowns as an error, but go ahead and transfer the string */
           CLog::Log(LOGERROR, "Unknown setting type '%s' for %s", type, Name().c_str());
+          status = m_pDll->SetSetting(id, (const char*) GetSetting(id).c_str());
         }
 
         if (status == ADDON_STATUS_NEED_RESTART)
index 472d825..a23babd 100644 (file)
@@ -31,7 +31,6 @@ enum AEEngine
   AE_ENGINE_PULSE
 };
 
-class IAE;
 class CAEFactory
 {
 public:
index 3e7d2a0..810d4fe 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 #include "AESinkFactory.h"
+#include "Interfaces/AESink.h"
 #include "utils/SystemInfo.h"
 #include "utils/log.h"
 #include "settings/AdvancedSettings.h"
index b2a9057..32fd250 100644 (file)
 #include <string>
 #include <vector>
 
-#include "Interfaces/AESink.h"
 #include "Utils/AEDeviceInfo.h"
 
+class IAESink;
+
 typedef struct
 {
   std::string      m_sinkName;
index fdc9f41..2dd6e8d 100644 (file)
@@ -90,7 +90,9 @@ const char* StreamDescriptionToString(AudioStreamBasicDescription desc, std::str
     case kAudioFormat60958AC3:
       sstr  << "["
             << fourCC
-            << "] AC-3/DTS for S/PDIF ("
+            << "] AC-3/DTS for S/PDIF "
+            << ((desc.mFormatFlags & kAudioFormatFlagIsBigEndian) ? "BE" : "LE")
+            << " ("
             << (UInt32)desc.mSampleRate
             << "Hz)";
       str = sstr.str();
index 67249a4..a61b1b3 100644 (file)
@@ -311,7 +311,6 @@ void CCoreAudioUnit::GetFormatDesc(AEAudioFormat format,
       streamDesc->mFormatFlags |= kAudioFormatFlagIsSignedInteger;
       break;
     case AE_FMT_S16LE:
-      streamDesc->mFormatFlags |= kAudioFormatFlagsNativeEndian;
       streamDesc->mFormatFlags |= kAudioFormatFlagIsSignedInteger;
       break;
     case AE_FMT_S16BE:
index 54dfb7e..82a9858 100644 (file)
@@ -314,7 +314,6 @@ void CCoreAudioUnit::GetFormatDesc(AEAudioFormat format,
       streamDesc->mFormatFlags |= kAudioFormatFlagIsSignedInteger;
       break;
     case AE_FMT_S16LE:
-      streamDesc->mFormatFlags |= kAudioFormatFlagsNativeEndian;
       streamDesc->mFormatFlags |= kAudioFormatFlagIsSignedInteger;
       break;
     case AE_FMT_S16BE:
index 7fb4deb..65cb37b 100644 (file)
@@ -27,6 +27,7 @@
 #include "utils/log.h"
 #include "utils/TimeUtils.h"
 #include "utils/MathUtils.h"
+#include "utils/EndianSwap.h"
 #include "threads/SingleLock.h"
 #include "settings/GUISettings.h"
 #include "settings/Settings.h"
@@ -809,7 +810,7 @@ double CSoftAE::GetCacheTime()
   CSharedLock sinkLock(m_sinkLock);
 
   double time;
-  time  = (double)m_buffer.Free() * m_sinkFormatFrameSizeMul * m_sinkFormatSampleRateMul;
+  time  = (double)m_buffer.Used() * m_sinkFormatFrameSizeMul * m_sinkFormatSampleRateMul;
   time += m_sink->GetCacheTime();
 
   return time;
@@ -853,11 +854,13 @@ void CSoftAE::Run()
   CSingleLock runningLock(m_runningLock);
   CLog::Log(LOGINFO, "CSoftAE::Run - Thread Started");
 
+  bool hasAudio = false;
   while (m_running)
   {
     bool restart = false;
 
-    (this->*m_outputStageFn)();
+    if ((this->*m_outputStageFn)(hasAudio) > 0)
+      hasAudio = false; /* taken some audio - reset our silence flag */
 
     /* if we have enough room in the buffer */
     if (m_buffer.Free() >= m_frameSize)
@@ -868,7 +871,8 @@ void CSoftAE::Run()
 
       /* run the stream stage */
       CSoftAEStream *oldMaster = m_masterStream;
-      (this->*m_streamStageFn)(m_chLayout.Count(), out, restart);
+      if ((this->*m_streamStageFn)(m_chLayout.Count(), out, restart) > 0)
+        hasAudio = true; /* have some audio */
 
       /* if in audiophile mode and the master stream has changed, flag for restart */
       if (m_audiophile && oldMaster != m_masterStream)
@@ -884,10 +888,21 @@ void CSoftAE::Run()
   }
 }
 
-void CSoftAE::MixSounds(float *buffer, unsigned int samples)
+void CSoftAE::AllocateConvIfNeeded(size_t convertedSize)
+{
+  if (m_convertedSize < convertedSize)
+  {
+    _aligned_free(m_converted);
+    m_converted = (uint8_t *)_aligned_malloc(convertedSize, 16);
+    m_convertedSize = convertedSize;
+  }
+}
+
+unsigned int CSoftAE::MixSounds(float *buffer, unsigned int samples)
 {
   SoundStateList::iterator itt;
 
+  unsigned int mixed = 0;
   CSingleLock lock(m_soundSampleLock);
   for (itt = m_playing_sounds.begin(); itt != m_playing_sounds.end(); )
   {
@@ -915,18 +930,24 @@ void CSoftAE::MixSounds(float *buffer, unsigned int samples)
     ss->samples     += mixSamples;
 
     ++itt;
+    ++mixed;
   }
+  return mixed;
 }
 
-void CSoftAE::FinalizeSamples(float *buffer, unsigned int samples)
+bool CSoftAE::FinalizeSamples(float *buffer, unsigned int samples, bool hasAudio)
 {
   if (m_soundMode != AE_SOUND_OFF)
-    MixSounds(buffer, samples);
+    hasAudio |= MixSounds(buffer, samples) > 0;
+
+  /* no need to process if we don't have audio (buffer is memset to 0) */
+  if (!hasAudio)
+    return false;
 
   if (m_muted)
   {
     memset(buffer, 0, samples * sizeof(float));
-    return;
+    return false;
   }
 
   /* deamplify */
@@ -962,37 +983,33 @@ void CSoftAE::FinalizeSamples(float *buffer, unsigned int samples)
 
   /* if there were no samples outside of the range, dont clamp the buffer */
   if (!clamp)
-    return;
+    return true;
 
   CLog::Log(LOGDEBUG, "CSoftAE::FinalizeSamples - Clamping buffer of %d samples", samples);
   CAEUtil::ClampArray(buffer, samples);
+  return true;
 }
 
-void CSoftAE::RunOutputStage()
+int CSoftAE::RunOutputStage(bool hasAudio)
 {
   const unsigned int needSamples = m_sinkFormat.m_frames * m_sinkFormat.m_channelLayout.Count();
   const size_t needBytes = needSamples * sizeof(float);
   if (m_buffer.Used() < needBytes)
-    return;
+    return 0;
 
   void *data = m_buffer.Raw(needBytes);
-  FinalizeSamples((float*)data, needSamples);
+  hasAudio = FinalizeSamples((float*)data, needSamples, hasAudio);
 
   int wroteFrames;
   if (m_convertFn)
   {
     const unsigned int convertedBytes = m_sinkFormat.m_frames * m_sinkFormat.m_frameSize;
-    if (m_convertedSize < convertedBytes)
-    {
-      _aligned_free(m_converted);
-      m_converted = (uint8_t *)_aligned_malloc(convertedBytes, 16);
-      m_convertedSize = convertedBytes;
-    }
+    AllocateConvIfNeeded(convertedBytes);
     m_convertFn((float*)data, needSamples, m_converted);
     data = m_converted;
   }
 
-  wroteFrames = m_sink->AddPackets((uint8_t*)data, m_sinkFormat.m_frames);
+  wroteFrames = m_sink->AddPackets((uint8_t*)data, m_sinkFormat.m_frames, hasAudio);
 
   /* Return value of INT_MAX signals error in sink - restart */
   if (wroteFrames == INT_MAX)
@@ -1003,14 +1020,34 @@ void CSoftAE::RunOutputStage()
   }
 
   m_buffer.Shift(NULL, wroteFrames * m_sinkFormat.m_channelLayout.Count() * sizeof(float));
+  return wroteFrames;
 }
 
-void CSoftAE::RunRawOutputStage()
+int CSoftAE::RunRawOutputStage(bool hasAudio)
 {
   if(m_buffer.Used() < m_sinkBlockSize)
-    return;
+    return 0;
+
+  void *data = m_buffer.Raw(m_sinkBlockSize);
+
+  if (CAEUtil::S16NeedsByteSwap(AE_FMT_S16NE, m_sinkFormat.m_dataFormat))
+  {
+    /*
+     * It would really be preferable to handle this at packing stage, so that
+     * it could byteswap the data efficiently without wasting CPU time on
+     * swapping the huge IEC 61937 zero padding between frames (or not
+     * byteswap at all, if there are two byteswaps).
+     *
+     * Unfortunately packing is done on a higher level and we can't easily
+     * tell it the needed format from here, so do it here for now (better than
+     * nothing)...
+     */
+    AllocateConvIfNeeded(m_sinkBlockSize);
+    Endian_Swap16_buf((uint16_t *)m_converted, (uint16_t *)data, m_sinkBlockSize / 2);
+    data = m_converted;
+  }
 
-  int wroteFrames = m_sink->AddPackets((uint8_t*)m_buffer.Raw(m_sinkBlockSize), m_sinkFormat.m_frames);
+  int wroteFrames = m_sink->AddPackets((uint8_t *)data, m_sinkFormat.m_frames, hasAudio);
 
   /* Return value of INT_MAX signals error in sink - restart */
   if (wroteFrames == INT_MAX)
@@ -1021,17 +1058,19 @@ void CSoftAE::RunRawOutputStage()
   }
 
   m_buffer.Shift(NULL, wroteFrames * m_sinkFormat.m_frameSize);
+  return wroteFrames;
 }
 
-void CSoftAE::RunTranscodeStage()
+int CSoftAE::RunTranscodeStage(bool hasAudio)
 {
   /* 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;
 
+  int encodedFrames = 0;
   if (m_buffer.Used() >= block && m_encodedBuffer.Used() < sinkBlock * 2)
   {
-    FinalizeSamples((float*)m_buffer.Raw(block), m_encoderFormat.m_frameSamples);
+    hasAudio = FinalizeSamples((float*)m_buffer.Raw(block), m_encoderFormat.m_frameSamples, hasAudio);
 
     void *buffer;
     if (m_convertFn)
@@ -1053,7 +1092,7 @@ void CSoftAE::RunTranscodeStage()
     else
       buffer = m_buffer.Raw(block);
 
-    int encodedFrames  = m_encoder->Encode((float*)buffer, m_encoderFormat.m_frames);
+    encodedFrames = m_encoder->Encode((float*)buffer, m_encoderFormat.m_frames);
     m_buffer.Shift(NULL, encodedFrames * m_encoderFormat.m_frameSize);
 
     uint8_t *packet;
@@ -1069,7 +1108,7 @@ void CSoftAE::RunTranscodeStage()
   /* if we have enough data to write */
   if (m_encodedBuffer.Used() >= sinkBlock)
   {
-    int wroteFrames = m_sink->AddPackets((uint8_t*)m_encodedBuffer.Raw(sinkBlock), m_sinkFormat.m_frames);
+    int wroteFrames = m_sink->AddPackets((uint8_t*)m_encodedBuffer.Raw(sinkBlock), m_sinkFormat.m_frames, hasAudio);
     
     /* Return value of INT_MAX signals error in sink - restart */
     if (wroteFrames == INT_MAX)
@@ -1081,6 +1120,7 @@ void CSoftAE::RunTranscodeStage()
 
     m_encodedBuffer.Shift(NULL, wroteFrames * m_sinkFormat.m_frameSize);
   }
+  return encodedFrames;
 }
 
 unsigned int CSoftAE::RunRawStreamStage(unsigned int channelCount, void *out, bool &restart)
index 7f4420b..11501ef 100644 (file)
 #include "threads/SharedSection.h"
 
 #include "Interfaces/ThreadedAE.h"
-#include "Interfaces/AESink.h"
-#include "Interfaces/AEEncoder.h"
-#include "Utils/AEConvert.h"
-#include "Utils/AERemap.h"
 #include "Utils/AEBuffer.h"
 #include "AEAudioFormat.h"
 #include "AESinkFactory.h"
 #include "cores/IAudioCallback.h"
 
 /* forward declarations */
-class IThreadedAE;
-class CSoftAEStream;
-class CSoftAESound;
 class IAESink;
+class IAEEncoder;
 
 class CSoftAE : public IThreadedAE
 {
@@ -192,16 +186,38 @@ private:
   uint8_t        *m_converted;
   size_t          m_convertedSize;
 
+  void         AllocateConvIfNeeded(size_t convertedSize);
+
   /* thread run stages */
-  void         MixSounds        (float *buffer, unsigned int samples);
-  void         FinalizeSamples  (float *buffer, unsigned int samples);
+
+  /*! \brief Mix UI sounds into the current stream.
+   \param buffer the buffer to mix into.
+   \param samples the number of samples in the buffer.
+   \return the number of sounds mixed into the buffer.
+   */
+  unsigned int MixSounds        (float *buffer, unsigned int samples);
+
+  /*! \brief Finalize samples ready for sending to the output device.
+   Mixes in any UI sounds, applies volume adjustment, and clamps to [-1,1].
+   \param buffer the audio data.
+   \param samples the number of samples in the buffer.
+   \param hasAudio whether we have audio from a stream (true) or silence (false)
+   \return true if we have audio to output, false if we have only silence.
+   */
+  bool         FinalizeSamples  (float *buffer, unsigned int samples, bool hasAudio);
 
   CSoftAEStream *m_masterStream;
 
-  void         (CSoftAE::*m_outputStageFn)();
-  void         RunOutputStage   ();
-  void         RunRawOutputStage();
-  void         RunTranscodeStage();
+  /*! \brief Run the output stage on the audio.
+   Prepares streamed data, mixes in any UI sounds, converts to a format suitable
+   for the sink, then outputs to the sink.
+   \param hasAudio whether or not we have audio (true) or silence (false).
+   \return the number of samples sent to the sink.
+   */
+  int          (CSoftAE::*m_outputStageFn)(bool);
+  int          RunOutputStage   (bool hasAudio);
+  int          RunRawOutputStage(bool hasAudio);
+  int          RunTranscodeStage(bool hasAudio);
 
   unsigned int (CSoftAE::*m_streamStageFn)(unsigned int channelCount, void *out, bool &restart);
   unsigned int RunRawStreamStage (unsigned int channelCount, void *out, bool &restart);
index 9682c33..b04a75e 100644 (file)
@@ -28,9 +28,6 @@
 
 #include "AEFactory.h"
 #include "AEAudioFormat.h"
-#include "Utils/AEConvert.h"
-#include "Utils/AERemap.h"
-#include "Utils/AEUtil.h"
 
 #include "SoftAE.h"
 #include "SoftAESound.h"
index af64ba3..edf8e9c 100644 (file)
@@ -26,7 +26,6 @@
 #include "Interfaces/AESound.h"
 #include "Utils/AEWAVLoader.h"
 
-class CWAVLoader;
 class CSoftAESound : public IAESound
 {
 public:
index 31a34c7..33f282a 100644 (file)
@@ -489,8 +489,8 @@ double CSoftAEStream::GetCacheTime()
     return 0.0;
 
   double time;
-  time  = (double)(m_inputBuffer.Free() / m_format.m_frameSize) / (double)m_format.m_sampleRate;
-  time += (double)(m_waterLevel - m_refillBuffer)               / (double)AE.GetSampleRate();
+  time  = (double)(m_inputBuffer.Used() / m_format.m_frameSize) / (double)m_format.m_sampleRate;
+  time += (double)(m_waterLevel - m_framesBuffered)             / (double)AE.GetSampleRate();
   time += AE.GetCacheTime();
   return time;
 }
index 2be733d..1ab77c9 100644 (file)
@@ -27,8 +27,6 @@
 #include "threads/CriticalSection.h"
 
 #include "../AEAudioFormat.h"
-#include "AEStream.h"
-#include "AESound.h"
 
 typedef std::pair<std::string, std::string> AEDevice;
 typedef std::vector<AEDevice> AEDeviceList;
index 1ef1333..7083d08 100644 (file)
@@ -53,24 +53,26 @@ public:
   virtual bool IsCompatible(const AEAudioFormat format, const std::string device) = 0;
 
   /*
-    This method must return the delay in seconds till new data will be sent out
+    This method returns the time in seconds that it will take
+    for the next added packet to be heard from the speakers.
   */
   virtual double GetDelay() = 0;
 
   /*
-    This method returns the time in seconds till the sink's cache is full
+    This method returns the time in seconds that it will take
+    to underrun the cache if no sample is added.
   */
   virtual double GetCacheTime() = 0;
 
   /*
-    This method returns the total length of the cache in seconds
+    This method returns the total time in seconds of the cache.
   */
   virtual double GetCacheTotal() = 0;
 
   /*
-    Adds packets to be sent out, must block after at-least one block is being rendered
+    Adds packets to be sent out, this routine MUST block or sleep.
   */
-  virtual unsigned int AddPackets(uint8_t *data, unsigned int frames) = 0;
+  virtual unsigned int AddPackets(uint8_t *data, unsigned int frames, bool hasAudio) = 0;
 
   /*
     Drain the sink
index b8def17..e5fbe2b 100644 (file)
@@ -23,7 +23,6 @@
 #include "utils/StdString.h"
 #include "AE.h"
 
-class IAE;
 class IAESound
 {
 protected:
index e7f63f6..474a5f3 100644 (file)
@@ -59,8 +59,9 @@ public:
   virtual unsigned int AddData(void *data, unsigned int size) = 0;
 
   /**
-   * Returns how long until new data will be played
-   * @return The delay in seconds
+   * Returns the time in seconds that it will take
+   * for the next added packet to be heard from the speakers.
+   * @return seconds
    */
   virtual double GetDelay() = 0;
 
@@ -71,14 +72,15 @@ public:
   virtual bool IsBuffering() = 0;
 
   /**
-   * Returns how long until playback will start
-   * @return The delay in seconds
+   * Returns the time in seconds that it will take
+   * to underrun the cache if no sample is added.
+   * @return seconds
    */
   virtual double GetCacheTime() = 0;
 
   /**
-   * Returns the total length of the cache before playback will start
-   * @return The delay in seconds
+   * Returns the total time in seconds of the cache
+   * @return seconds
    */
   virtual double GetCacheTotal() = 0;
 
index 574178a..8a1eba4 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <stdint.h>
 #include <limits.h>
+#include <set>
 #include <sstream>
 
 #include "AESinkALSA.h"
@@ -34,7 +35,7 @@
 #include "threads/SingleLock.h"
 #include "settings/GUISettings.h"
 
-#define ALSA_OPTIONS (SND_PCM_NONBLOCK | SND_PCM_NO_AUTO_FORMAT | SND_PCM_NO_AUTO_RESAMPLE)
+#define ALSA_OPTIONS (SND_PCM_NONBLOCK | SND_PCM_NO_AUTO_FORMAT | SND_PCM_NO_AUTO_CHANNELS | SND_PCM_NO_AUTO_RESAMPLE)
 #define ALSA_PERIODS 16
 
 #define ALSA_MAX_CHANNELS 16
@@ -105,17 +106,23 @@ inline CAEChannelInfo CAESinkALSA::GetChannelLayout(AEAudioFormat format)
   return info;
 }
 
-void CAESinkALSA::GetPassthroughDevice(AEAudioFormat format, std::string& device)
+void CAESinkALSA::GetAESParams(AEAudioFormat format, std::string& params)
 {
-  device += ",AES0=0x06,AES1=0x82,AES2=0x00";
-       if (format.m_sampleRate == 192000) device += ",AES3=0x0e";
-  else if (format.m_sampleRate == 176400) device += ",AES3=0x0c";
-  else if (format.m_sampleRate ==  96000) device += ",AES3=0x0a";
-  else if (format.m_sampleRate ==  88200) device += ",AES3=0x08";
-  else if (format.m_sampleRate ==  48000) device += ",AES3=0x02";
-  else if (format.m_sampleRate ==  44100) device += ",AES3=0x00";
-  else if (format.m_sampleRate ==  32000) device += ",AES3=0x03";
-  else device += ",AES3=0x01";
+  if (m_passthrough)
+    params = "AES0=0x06";
+  else
+    params = "AES0=0x04";
+
+  params += ",AES1=0x82,AES2=0x00";
+
+       if (format.m_sampleRate == 192000) params += ",AES3=0x0e";
+  else if (format.m_sampleRate == 176400) params += ",AES3=0x0c";
+  else if (format.m_sampleRate ==  96000) params += ",AES3=0x0a";
+  else if (format.m_sampleRate ==  88200) params += ",AES3=0x08";
+  else if (format.m_sampleRate ==  48000) params += ",AES3=0x02";
+  else if (format.m_sampleRate ==  44100) params += ",AES3=0x00";
+  else if (format.m_sampleRate ==  32000) params += ",AES3=0x03";
+  else params += ",AES3=0x01";
 }
 
 bool CAESinkALSA::Initialize(AEAudioFormat &format, std::string &device)
@@ -144,26 +151,40 @@ bool CAESinkALSA::Initialize(AEAudioFormat &format, std::string &device)
 
   format.m_channelLayout = m_channelLayout;
 
-  /* if passthrough we need the additional AES flags */
-  if (m_passthrough)
-    GetPassthroughDevice(format, device);
+  std::string AESParams;
+  /* digital interfaces should have AESx set, though in practice most
+   * receivers don't care */
+  if (m_passthrough || device.substr(0, 6) == "iec958" || device.substr(0, 4) == "hdmi")
+    GetAESParams(format, AESParams);
 
-  m_device = device;
-  CLog::Log(LOGINFO, "CAESinkALSA::Initialize - Attempting to open device %s", device.c_str());
+  CLog::Log(LOGINFO, "CAESinkALSA::Initialize - Attempting to open device \"%s\"", device.c_str());
 
   /* get the sound config */
   snd_config_t *config;
   snd_config_copy(&config, snd_config);
-  int error;
 
-  error = snd_pcm_open_lconf(&m_pcm, device.c_str(), SND_PCM_STREAM_PLAYBACK, ALSA_OPTIONS, config);
-  if (error < 0)
+  snd_config_t *dmixRateConf;
+  long dmixRate;
+
+  if (snd_config_search(config, "defaults.pcm.dmix.rate", &dmixRateConf) < 0
+      || snd_config_get_integer(dmixRateConf, &dmixRate) < 0)
+    dmixRate = 48000; /* assume default */
+
+
+  /* Prefer dmix for non-passthrough stereo when sample rate matches */
+  if (!OpenPCMDevice(device, AESParams, m_channelLayout.Count(), &m_pcm, config, format.m_sampleRate == dmixRate && !m_passthrough))
   {
-    CLog::Log(LOGERROR, "CAESinkALSA::Initialize - snd_pcm_open_lconf(%d) - %s", error, device.c_str());
+    CLog::Log(LOGERROR, "CAESinkALSA::Initialize - failed to initialize device \"%s\"", device.c_str());
     snd_config_delete(config);
     return false;
   }
 
+  /* get the actual device name that was used */
+  device = snd_pcm_name(m_pcm);
+  m_device = device;
+
+  CLog::Log(LOGINFO, "CAESinkALSA::Initialize - Opened device \"%s\"", device.c_str());
+
   /* free the sound config */
   snd_config_delete(config);
 
@@ -193,13 +214,15 @@ bool CAESinkALSA::IsCompatible(const AEAudioFormat format, const std::string dev
 snd_pcm_format_t CAESinkALSA::AEFormatToALSAFormat(const enum AEDataFormat format)
 {
   if (AE_IS_RAW(format))
-    return SND_PCM_FORMAT_S16_LE;
+    return SND_PCM_FORMAT_S16;
 
   switch (format)
   {
     case AE_FMT_S8    : return SND_PCM_FORMAT_S8;
     case AE_FMT_U8    : return SND_PCM_FORMAT_U8;
     case AE_FMT_S16NE : return SND_PCM_FORMAT_S16;
+    case AE_FMT_S16LE : return SND_PCM_FORMAT_S16_LE;
+    case AE_FMT_S16BE : return SND_PCM_FORMAT_S16_BE;
     case AE_FMT_S24NE4: return SND_PCM_FORMAT_S24;
 #ifdef __BIG_ENDIAN__
     case AE_FMT_S24NE3: return SND_PCM_FORMAT_S24_3BE;
@@ -258,6 +281,10 @@ bool CAESinkALSA::InitializeHW(AEAudioFormat &format)
     {
       if (AE_IS_RAW(i) || i == AE_FMT_MAX)
         continue;
+
+      if (m_passthrough && i != AE_FMT_S16BE && i != AE_FMT_S16LE)
+       continue;
+
       fmt = AEFormatToALSAFormat(i);
 
       if (fmt == SND_PCM_FORMAT_UNKNOWN || snd_pcm_hw_params_set_format(m_pcm, hw_params, fmt) < 0)
@@ -334,7 +361,7 @@ bool CAESinkALSA::InitializeHW(AEAudioFormat &format)
         {
           CLog::Log(LOGERROR, "CAESinkALSA::InitializeHW - Failed to set the parameters");
           return false;
-       }
+        }
       }
     }
   }
@@ -447,7 +474,7 @@ double CAESinkALSA::GetCacheTotal()
   return (double)m_bufferSize * m_formatSampleRateMul;
 }
 
-unsigned int CAESinkALSA::AddPackets(uint8_t *data, unsigned int frames)
+unsigned int CAESinkALSA::AddPackets(uint8_t *data, unsigned int frames, bool hasAudio)
 {
   if (!m_pcm)
     return 0;
@@ -525,220 +552,505 @@ void CAESinkALSA::Drain()
   snd_pcm_nonblock(m_pcm, 1);
 }
 
-void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list)
+void CAESinkALSA::AppendParams(std::string &device, const std::string &params)
 {
-  /* ensure that ALSA has been initialized */
-  if(!snd_config)
-    snd_config_update();
+  /* Note: escaping, e.g. "plug:'something:X=y'" isn't handled,
+   * but it is not normally encountered at this point. */
 
-  snd_ctl_t *ctlhandle;
-  snd_pcm_t *pcmhandle;
+  device += (device.find(':') == std::string::npos) ? ':' : ',';
+  device += params;
+}
 
-  snd_ctl_card_info_t *ctlinfo;
-  snd_ctl_card_info_alloca(&ctlinfo);
-  memset(ctlinfo, 0, snd_ctl_card_info_sizeof());
+bool CAESinkALSA::TryDevice(const std::string &name, snd_pcm_t **pcmp, snd_config_t *lconf)
+{
+  /* Check if this device was already open (e.g. when checking for supported
+   * channel count in EnumerateDevice()) */
+  if (*pcmp)
+  {
+    if (name == snd_pcm_name(*pcmp))
+      return true;
 
-  snd_pcm_hw_params_t *hwparams;
-  snd_pcm_hw_params_alloca(&hwparams);
-  memset(hwparams, 0, snd_pcm_hw_params_sizeof());
+    snd_pcm_close(*pcmp);
+    *pcmp = NULL;
+  }
 
-  snd_pcm_info_t *pcminfo;
-  snd_pcm_info_alloca(&pcminfo);
-  memset(pcminfo, 0, snd_pcm_info_sizeof());
+  int err = snd_pcm_open_lconf(pcmp, name.c_str(), SND_PCM_STREAM_PLAYBACK, ALSA_OPTIONS, lconf);
+  if (err < 0)
+  {
+    CLog::Log(LOGINFO, "CAESinkALSA - Unable to open device \"%s\" for playback", name.c_str());
+  }
 
-  /* get the sound config */
-  snd_config_t *config;
-  snd_config_copy(&config, snd_config);
+  return err == 0;
+}
 
-  std::string strHwName;
-  int n_cards = -1;
-  while (snd_card_next(&n_cards) == 0 && n_cards != -1)
+bool CAESinkALSA::TryDeviceWithParams(const std::string &name, const std::string &params, snd_pcm_t **pcmp, snd_config_t *lconf)
+{
+  if (!params.empty())
   {
-    std::stringstream sstr;
-    sstr << "hw:" << n_cards;
-    std::string strHwName = sstr.str();
+    std::string nameWithParams = name;
+    AppendParams(nameWithParams, params);
+    if (TryDevice(nameWithParams, pcmp, lconf))
+      return true;
+  }
 
-    if (snd_ctl_open_lconf(&ctlhandle, strHwName.c_str(), 0, config) != 0)
+  /* Try the variant without extra parameters.
+   * Custom devices often do not take the AESx parameters, for example.
+   */
+  return TryDevice(name, pcmp, lconf);
+}
+
+bool CAESinkALSA::OpenPCMDevice(const std::string &name, const std::string &params, int channels, snd_pcm_t **pcmp, snd_config_t *lconf, bool preferDmixStereo)
+{
+ /* Special name denoting surroundXX mangling. This is needed for some
+   * devices for multichannel to work. */
+  if (name == "@" || name.substr(0, 2) == "@:")
+  {
+    std::string openName = name.substr(1);
+
+    /* These device names allow alsa-lib to perform special routing if needed
+     * for multichannel to work with the audio hardware.
+     * Fall through in switch() so that devices with more channels are
+     * added as fallback. */
+    switch (channels)
     {
-      CLog::Log(LOGDEBUG, "CAESinkALSA::EnumerateDevicesEx - Unable to open control for device %s", strHwName.c_str());
-      continue;
+      case 3:
+      case 4:
+        if (TryDeviceWithParams("surround40" + openName, params, pcmp, lconf))
+          return true;
+      case 5:
+      case 6:
+        if (TryDeviceWithParams("surround51" + openName, params, pcmp, lconf))
+          return true;
+      case 7:
+      case 8:
+        if (TryDeviceWithParams("surround71" + openName, params, pcmp, lconf))
+          return true;
     }
 
-    if (snd_ctl_card_info(ctlhandle, ctlinfo) != 0)
+    /* If preferDmix is false, try non-dmix configuration first.
+     * This allows output with non-48000 sample rate if device is free */
+    if (!preferDmixStereo && TryDeviceWithParams("front" + openName, params, pcmp, lconf))
+      return true;
+
+    /* Try "sysdefault" and "default" (they provide dmix),
+     * unless the selected devices is not DEV=0 of the card, in which case
+     * "sysdefault" and "default" would point to another device.
+     * "sysdefault" is a newish device name that won't be overwritten in case
+     * system configuration redefines "default". "default" is still tried
+     * because "sysdefault" is rather new. */
+    size_t devPos = openName.find(",DEV=");
+    if (devPos == std::string::npos || (devPos + 5 < openName.size() && openName[devPos+5] == '0'))
     {
-      CLog::Log(LOGDEBUG, "CAESinkALSA::EnumerateDevicesEx - Unable to get card control info for device %s", strHwName.c_str());
-      snd_ctl_close(ctlhandle);
-      continue;
+      /* "sysdefault" and "default" do not have "DEV=0", drop it */
+      std::string nameWithoutDev = openName;
+      if (devPos != std::string::npos)
+        nameWithoutDev.erase(nameWithoutDev.begin() + devPos, nameWithoutDev.begin() + devPos + 6);
+
+      if (TryDeviceWithParams("sysdefault" + nameWithoutDev, params, pcmp, lconf)
+          || TryDeviceWithParams("default" + nameWithoutDev, params, pcmp, lconf))
+        return true;
     }
 
-    snd_hctl_t *hctl;
-    if (snd_hctl_open_ctl(&hctl, ctlhandle) != 0)
-      hctl = NULL;
-    snd_hctl_load(hctl);
+    /* Try non-dmix "front" */
+    if (preferDmixStereo && TryDeviceWithParams("front" + openName, params, pcmp, lconf))
+      return true;
 
-    int pcm_index    = 0;
-    int iec958_index = 0;
-    int hdmi_index   = 0;
+  }
+  else
+  {
+    /* Non-surroundXX device, just add it */
+    if (TryDeviceWithParams(name, params, pcmp, lconf))
+      return true;
+  }
 
-    int dev = -1;
-    while (snd_ctl_pcm_next_device(ctlhandle, &dev) == 0 && dev != -1)
+  return false;
+}
+
+void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list)
+{
+  /* ensure that ALSA has been initialized */
+  snd_lib_error_set_handler(sndLibErrorHandler);
+  if(!snd_config)
+    snd_config_update();
+
+  snd_config_t *config;
+  snd_config_copy(&config, snd_config);
+
+  /* Always enumerate the default device.
+   * Note: If "default" is a stereo device, EnumerateDevice()
+   * will automatically add "@" instead to enable surroundXX mangling.
+   * We don't want to do that if "default" can handle multichannel
+   * itself (e.g. in case of a pulseaudio server). */
+  EnumerateDevice(list, "default", "", config);
+
+  void **hints;
+
+  if (snd_device_name_hint(-1, "pcm", &hints) < 0)
+  {
+    CLog::Log(LOGINFO, "CAESinkALSA - Unable to get a list of devices");
+    return;
+  }
+
+  std::string defaultDescription;
+
+  for (void** hint = hints; *hint != NULL; ++hint)
+  {
+    char *io = snd_device_name_get_hint(*hint, "IOID");
+    char *name = snd_device_name_get_hint(*hint, "NAME");
+    char *desc = snd_device_name_get_hint(*hint, "DESC");
+    if ((!io || strcmp(io, "Output") == 0) && name
+        && strcmp(name, "null") != 0)
     {
-      snd_pcm_info_set_device   (pcminfo, dev);
-      snd_pcm_info_set_subdevice(pcminfo, 0  );
-      snd_pcm_info_set_stream   (pcminfo, SND_PCM_STREAM_PLAYBACK);
+      std::string baseName = std::string(name);
+      baseName = baseName.substr(0, baseName.find(':'));
 
-      if (snd_ctl_pcm_info(ctlhandle, pcminfo) < 0)
+      if (strcmp(name, "default") == 0)
       {
-        CLog::Log(LOGDEBUG, "CAESinkALSA::EnumerateDevicesEx - Skipping device %s,%d as it does not have PCM playback ability", strHwName.c_str(), dev);
-        continue;
+        /* added already, but lets get the description if we have one */
+        if (desc)
+          defaultDescription = desc;
+      }
+      else if (baseName == "front")
+      {
+        /* Enumerate using the surroundXX mangling */
+        /* do not enumerate basic "front", it is already handled
+         * by the default "@" entry added in the very beginning */
+        if (strcmp(name, "front") != 0)
+          EnumerateDevice(list, std::string("@") + (name+5), desc ? desc : name, config);
+      }
+      /* Do not enumerate the sysdefault or surroundXX devices, those are
+       * always accompanied with a "front" device and it is handled above
+       * as "@". The below devices will be automatically used if available
+       * for a "@" device. */
+      else if (baseName != "default"
+            && baseName != "sysdefault"
+            && baseName != "surround40"
+            && baseName != "surround41"
+            && baseName != "surround50"
+            && baseName != "surround51"
+            && baseName != "surround71")
+      {
+        EnumerateDevice(list, name, desc ? desc : name, config);
       }
+    }
+    free(io);
+    free(name);
+    free(desc);
+  }
+  snd_device_name_free_hint(hints);
 
-      int dev_index;
-      sstr.str(std::string());
-      CAEDeviceInfo info;
-      std::string devname = snd_pcm_info_get_name(pcminfo);
+  /* set the displayname for default device */
+  if (!list.empty() && list[0].m_deviceName == "default")
+  {
+    /* If we have one from a hint (DESC), use it */
+    if (!defaultDescription.empty())
+      list[0].m_displayName = defaultDescription;
+    /* Otherwise use the discovered name or (unlikely) "Default" */
+    else if (list[0].m_displayName.empty())
+      list[0].m_displayName = "Default";
+  }
 
-      bool maybeHDMI = false;
+  /* lets check uniqueness, we may need to append DEV or CARD to DisplayName */
+  /* If even a single device of card/dev X clashes with Y, add suffixes to
+   * all devices of both them, for clarity. */
 
-      /* detect HDMI */
-      if (devname.find("HDMI") != std::string::npos)
-      { 
-        info.m_deviceType = AE_DEVTYPE_HDMI;
-        dev_index = hdmi_index++;
-        sstr << "hdmi";
-      }
-      else
-      {
-        /* detect IEC958 */
+  /* clashing card names, e.g. "NVidia", "NVidia_2" */
+  std::set<std::string> cardsToAppend;
 
-        /* some HDMI devices (intel) report Digital for HDMI also */
-        if (devname.find("Digital") != std::string::npos)
-          maybeHDMI = true;
+  /* clashing basename + cardname combinations, e.g. ("hdmi","Nvidia") */
+  std::set<std::pair<std::string, std::string> > devsToAppend;
 
-        if (maybeHDMI || devname.find("IEC958" ) != std::string::npos)
+  for (AEDeviceInfoList::iterator it1 = list.begin(); it1 != list.end(); ++it1)
+  {
+    for (AEDeviceInfoList::iterator it2 = it1+1; it2 != list.end(); ++it2)
+    {
+      if (it1->m_displayName == it2->m_displayName
+       && it1->m_displayNameExtra == it2->m_displayNameExtra)
+      {
+        /* something needs to be done */
+        std::string cardString1;
+        std::string cardString2;
+        GetParamFromName(it1->m_deviceName, "CARD", cardString1);
+        GetParamFromName(it2->m_deviceName, "CARD", cardString2);
+
+        if (cardString1 != cardString2)
         {
-          info.m_deviceType = AE_DEVTYPE_IEC958;
-          dev_index = iec958_index; /* dont increment, it might be HDMI */
-          sstr << "iec958";
+          /* card name differs, add identifiers to all devices */
+          cardsToAppend.insert(cardString1);
+          cardsToAppend.insert(cardString2);
+          continue;
         }
-        else
+
+        std::string devString1;
+        std::string devString2;
+        GetParamFromName(it1->m_deviceName, "DEV", devString1);
+        GetParamFromName(it2->m_deviceName, "DEV", devString2);
+
+        if (devString1 != devString2)
         {
-          info.m_deviceType = AE_DEVTYPE_PCM;
-          dev_index = pcm_index++;
-          sstr << "hw";
+          /* device number differs, add identifiers to all such devices */
+          devsToAppend.insert(std::make_pair(it1->m_deviceName.substr(0, it1->m_deviceName.find(':')), cardString1));
+          devsToAppend.insert(std::make_pair(it2->m_deviceName.substr(0, it2->m_deviceName.find(':')), cardString2));
+          continue;
         }
+
+        /* if we got here, the configuration is really weird, just give up */
+        it1->m_displayName = it1->m_deviceName;
+        it2->m_displayName = it2->m_deviceName;
+      }
+    }
+  }
+
+  for (std::set<std::string>::iterator it = cardsToAppend.begin();
+       it != cardsToAppend.end(); ++it)
+  {
+    for (AEDeviceInfoList::iterator itl = list.begin(); itl != list.end(); ++itl)
+    {
+      std::string cardString;
+      GetParamFromName(itl->m_deviceName, "CARD", cardString);
+      if (cardString == *it)
+        /* "HDA NVidia (NVidia)", "HDA NVidia (NVidia_2)", ... */
+        itl->m_displayName += " (" + cardString + ")";
+    }
+  }
+
+  for (std::set<std::pair<std::string, std::string> >::iterator it = devsToAppend.begin();
+       it != devsToAppend.end(); ++it)
+  {
+    for (AEDeviceInfoList::iterator itl = list.begin(); itl != list.end(); ++itl)
+    {
+      std::string baseName = itl->m_deviceName.substr(0, itl->m_deviceName.find(':'));
+      std::string cardString;
+      GetParamFromName(itl->m_deviceName, "CARD", cardString);
+      if (baseName == it->first && cardString == it->second)
+      {
+        std::string devString;
+        GetParamFromName(itl->m_deviceName, "DEV", devString);
+        /* "HDMI #0", "HDMI #1" ... */
+        itl->m_displayNameExtra += " #" + devString;
       }
+    }
+  }
+}
 
-      /* build the driver string to pass to ALSA */
-      sstr << ":CARD=" << snd_ctl_card_info_get_id(ctlinfo) << ",DEV=" << dev_index;
-      info.m_deviceName = sstr.str();
+void CAESinkALSA::GetParamFromName(const std::string &name, const std::string &param, std::string &value)
+{
+  /* name = "hdmi:CARD=x,DEV=y" param = "CARD" => value = "x" */
+  size_t parPos = name.find(param + '=');
+  if (parPos != std::string::npos)
+  {
+    parPos += param.size() + 1;
+    value = name.substr(parPos, name.find_first_of(",'\"", parPos)-parPos);
+  }
+  else
+  {
+    value = "";
+  }
+}
 
-      /* get the friendly display name*/
-      info.m_displayName      = snd_ctl_card_info_get_name(ctlinfo);
-      info.m_displayNameExtra = devname;
+void CAESinkALSA::EnumerateDevice(AEDeviceInfoList &list, const std::string &device, const std::string &description, snd_config_t *config)
+{
+  snd_pcm_t *pcmhandle = NULL;
+  if (!OpenPCMDevice(device, "", ALSA_MAX_CHANNELS, &pcmhandle, config, false))
+    return;
 
-      /* open the device for testing */
-      int err = snd_pcm_open_lconf(&pcmhandle, info.m_deviceName.c_str(), SND_PCM_STREAM_PLAYBACK, 0, config);
+  snd_pcm_info_t *pcminfo;
+  snd_pcm_info_alloca(&pcminfo);
+  memset(pcminfo, 0, snd_pcm_info_sizeof());
 
-      /* if open of possible IEC958 failed and it could be HDMI, try as HDMI */
-      if (err < 0 && maybeHDMI)
-      {
-        /* check for HDMI if it failed */
-        sstr.str(std::string());
-        dev_index = hdmi_index;
+  int err = snd_pcm_info(pcmhandle, pcminfo);
+  if (err < 0)
+  {
+    CLog::Log(LOGINFO, "CAESinkALSA - Unable to get pcm_info for \"%s\"", device.c_str());
+    snd_pcm_close(pcmhandle);
+  }
 
-        sstr << "hdmi";
-        sstr << ":CARD=" << snd_ctl_card_info_get_id(ctlinfo) << ",DEV=" << dev_index;
-        info.m_deviceName = sstr.str();
-        err = snd_pcm_open_lconf(&pcmhandle, info.m_deviceName.c_str(), SND_PCM_STREAM_PLAYBACK, 0, config);
+  int cardNr = snd_pcm_info_get_card(pcminfo);
 
-        /* if it was valid, increment the index and set the type */
-        if (err >= 0)
-        {
-          ++hdmi_index;
-          info.m_deviceType = AE_DEVTYPE_HDMI;
-        }
-      }
+  CAEDeviceInfo info;
+  info.m_deviceName = device;
 
-      /* if it's still IEC958, increment the index */
-      if (info.m_deviceType == AE_DEVTYPE_IEC958)
-        ++iec958_index;
+  bool isHDMI  = (device.substr(0, 4) == "hdmi");
+  bool isSPDIF = (device.substr(0, 6) == "iec958");
 
-      /* final error check */
-      if (err < 0)
-      {
-        CLog::Log(LOGINFO, "CAESinkALSA::EnumerateDevicesEx - Unable to open %s for capability detection", strHwName.c_str());
-        continue;
-      }
+  if (isHDMI)
+    info.m_deviceType = AE_DEVTYPE_HDMI;
+  else if (isSPDIF)
+    info.m_deviceType = AE_DEVTYPE_IEC958;
+  else
+    info.m_deviceType = AE_DEVTYPE_PCM;
+
+  if (cardNr >= 0)
+  {
+    /* "HDA NVidia", "HDA Intel", "HDA ATI HDMI", "SB Live! 24-bit External", ... */
+    char *cardName;
+    if (snd_card_get_name(cardNr, &cardName) == 0)
+      info.m_displayName = cardName;
+
+    if (isHDMI && info.m_displayName.size() > 5 &&
+        info.m_displayName.substr(info.m_displayName.size()-5) == " HDMI")
+    {
+      /* We already know this is HDMI, strip it */
+      info.m_displayName.erase(info.m_displayName.size()-5);
+    }
+
+    /* "CONEXANT Analog", "USB Audio", "HDMI 0", "ALC889 Digital" ... */
+    std::string pcminfoName = snd_pcm_info_get_name(pcminfo);
 
-      /* see if we can get ELD for this device */
-      if (info.m_deviceType == AE_DEVTYPE_HDMI)
+    /*
+     * Filter "USB Audio", in those cases snd_card_get_name() is more
+     * meaningful already
+     */
+    if (pcminfoName != "USB Audio")
+      info.m_displayNameExtra = pcminfoName;
+
+    if (isHDMI)
+    {
+      /* replace, this was likely "HDMI 0" */
+      info.m_displayNameExtra = "HDMI";
+
+      int dev = snd_pcm_info_get_device(pcminfo);
+
+      if (dev >= 0)
       {
-        bool badHDMI = false;
-        if (hctl && !GetELD(hctl, dev, info, badHDMI))
-          CLog::Log(LOGDEBUG, "CAESinkALSA::EnumerateDevicesEx - Unable to obtain ELD information for device %s, make sure you have ALSA >= 1.0.25", info.m_deviceName.c_str());
+        /* lets see if we can get ELD info */
+
+        snd_ctl_t *ctlhandle;
+        std::stringstream sstr;
+        sstr << "hw:" << cardNr;
+        std::string strHwName = sstr.str();
 
-        if (badHDMI)
+        if (snd_ctl_open_lconf(&ctlhandle, strHwName.c_str(), 0, config) == 0)
         {
-          CLog::Log(LOGDEBUG, "CAESinkALSA::EnumerateDevicesEx - Skipping HDMI device %s as it has no ELD data", info.m_deviceName.c_str());
-          snd_pcm_close(pcmhandle);
-          continue;
+          snd_hctl_t *hctl;
+          if (snd_hctl_open_ctl(&hctl, ctlhandle) == 0)
+          {
+            snd_hctl_load(hctl);
+            bool badHDMI = false;
+            if (!GetELD(hctl, dev, info, badHDMI))
+              CLog::Log(LOGDEBUG, "CAESinkALSA - Unable to obtain ELD information for device \"%s\" (not supported by device, or kernel older than 3.2)",
+                        device.c_str());
+
+            /* snd_hctl_close also closes ctlhandle */
+            snd_hctl_close(hctl);
+
+            if (badHDMI)
+            {
+              /* unconnected HDMI port */
+              CLog::Log(LOGDEBUG, "CAESinkALSA - Skipping HDMI device \"%s\" as it has no ELD data", device.c_str());
+              snd_pcm_close(pcmhandle);
+              return;
+            }
+          }
+          else
+          {
+            snd_ctl_close(ctlhandle);
+          }
         }
       }
+    }
+    else if (isSPDIF)
+    {
+      /* append instead of replace, pcminfoName is useful for S/PDIF */
+      if (!info.m_displayNameExtra.empty())
+        info.m_displayNameExtra += ' ';
+      info.m_displayNameExtra += "S/PDIF";
+    }
+    else if (info.m_displayNameExtra.empty())
+    {
+      /* for USB audio, it gets a bit confusing as there is
+       * - "SB Live! 24-bit External"
+       * - "SB Live! 24-bit External, S/PDIF"
+       * so add "Analog" qualifier to the first one */
+      info.m_displayNameExtra = "Analog";
+    }
 
-      /* ensure we can get a playback configuration for the device */
-      if (snd_pcm_hw_params_any(pcmhandle, hwparams) < 0)
-      {
-        CLog::Log(LOGINFO, "CAESinkALSA::EnumerateDevicesEx - No playback configurations available for device %s", info.m_deviceName.c_str());
-        snd_pcm_close(pcmhandle);
-        continue;
-      }
-
-      /* detect the available sample rates */
-      for (unsigned int *rate = ALSASampleRateList; *rate != 0; ++rate)
-        if (snd_pcm_hw_params_test_rate(pcmhandle, hwparams, *rate, 0) >= 0)
-          info.m_sampleRates.push_back(*rate);
+    /* "default" is a device that will be used for all inputs, while
+     * "@" will be mangled to front/default/surroundXX as necessary */
+    if (device == "@" || device == "default")
+    {
+      /* Make it "Default (whatever)" */
+      info.m_displayName = "Default (" + info.m_displayName + (info.m_displayNameExtra.empty() ? "" : " " + info.m_displayNameExtra + ")");
+      info.m_displayNameExtra = "";
+    }
 
-      /* detect the channels available */
-      int channels = 0;
-      for (int i = 1; i <= ALSA_MAX_CHANNELS; ++i)
-        if (snd_pcm_hw_params_test_channels(pcmhandle, hwparams, i) >= 0)
-          channels = i;
+  }
+  else
+  {
+    /* virtual devices: "default", "pulse", ... */
+    /* description can be e.g. "PulseAudio Sound Server" - for hw devices it is
+     * normally uninteresting, like "HDMI Audio Output" or "Default Audio Device",
+     * so we only use it for virtual devices that have no better display name */
+    info.m_displayName = description;
+  }
 
-      CAEChannelInfo alsaChannels;
-      for (int i = 0; i < channels; ++i)
-      {
-        if (!info.m_channels.HasChannel(ALSAChannelMap[i]))
-          info.m_channels += ALSAChannelMap[i];
-        alsaChannels += ALSAChannelMap[i];
-      }
+  snd_pcm_hw_params_t *hwparams;
+  snd_pcm_hw_params_alloca(&hwparams);
+  memset(hwparams, 0, snd_pcm_hw_params_sizeof());
 
-      /* remove the channels from m_channels that we cant use */
-      info.m_channels.ResolveChannels(alsaChannels);
+  /* ensure we can get a playback configuration for the device */
+  if (snd_pcm_hw_params_any(pcmhandle, hwparams) < 0)
+  {
+    CLog::Log(LOGINFO, "CAESinkALSA - No playback configurations available for device \"%s\"", device.c_str());
+    snd_pcm_close(pcmhandle);
+    return;
+  }
 
-      /* detect the PCM sample formats that are available */
-      for (enum AEDataFormat i = AE_FMT_MAX; i > AE_FMT_INVALID; i = (enum AEDataFormat)((int)i - 1))
-      {
-        if (AE_IS_RAW(i) || i == AE_FMT_MAX)
-          continue;
-        snd_pcm_format_t fmt = AEFormatToALSAFormat(i);
-        if (fmt == SND_PCM_FORMAT_UNKNOWN)
-          continue;
+  /* detect the available sample rates */
+  for (unsigned int *rate = ALSASampleRateList; *rate != 0; ++rate)
+    if (snd_pcm_hw_params_test_rate(pcmhandle, hwparams, *rate, 0) >= 0)
+      info.m_sampleRates.push_back(*rate);
 
-        if (snd_pcm_hw_params_test_format(pcmhandle, hwparams, fmt) >= 0)
-          info.m_dataFormats.push_back(i);
-      }
+  /* detect the channels available */
+  int channels = 0;
+  for (int i = ALSA_MAX_CHANNELS; i >= 1; --i)
+  {
+    /* Reopen the device if needed on the special "surroundXX" cases */
+    if (info.m_deviceType == AE_DEVTYPE_PCM && (i == 8 || i == 6 || i == 4))
+      OpenPCMDevice(device, "", i, &pcmhandle, config, false);
 
-      snd_pcm_close(pcmhandle);
-      list.push_back(info);
+    if (snd_pcm_hw_params_test_channels(pcmhandle, hwparams, i) >= 0)
+    {
+      channels = i;
+      break;
     }
+  }
+
+  if (device == "default" && channels == 2)
+  {
+    /* This looks like the ALSA standard default stereo dmix device, we
+     * probably want to use "@" instead to get surroundXX. */
+    snd_pcm_close(pcmhandle);
+    EnumerateDevice(list, "@", description, config);
+    return;
+  }
 
-    /* snd_hctl_close also closes ctlhandle */
-    if (hctl)
-      snd_hctl_close(hctl);
-    else
-      snd_ctl_close(ctlhandle);
+  CAEChannelInfo alsaChannels;
+  for (int i = 0; i < channels; ++i)
+  {
+    if (!info.m_channels.HasChannel(ALSAChannelMap[i]))
+      info.m_channels += ALSAChannelMap[i];
+    alsaChannels += ALSAChannelMap[i];
   }
+
+  /* remove the channels from m_channels that we cant use */
+  info.m_channels.ResolveChannels(alsaChannels);
+
+  /* detect the PCM sample formats that are available */
+  for (enum AEDataFormat i = AE_FMT_MAX; i > AE_FMT_INVALID; i = (enum AEDataFormat)((int)i - 1))
+  {
+    if (AE_IS_RAW(i) || i == AE_FMT_MAX)
+      continue;
+    snd_pcm_format_t fmt = AEFormatToALSAFormat(i);
+    if (fmt == SND_PCM_FORMAT_UNKNOWN)
+      continue;
+
+    if (snd_pcm_hw_params_test_format(pcmhandle, hwparams, fmt) >= 0)
+      info.m_dataFormats.push_back(i);
+  }
+
+  snd_pcm_close(pcmhandle);
+  list.push_back(info);
 }
 
 bool CAESinkALSA::GetELD(snd_hctl_t *hctl, int device, CAEDeviceInfo& info, bool& badHDMI)
@@ -792,4 +1104,19 @@ bool CAESinkALSA::GetELD(snd_hctl_t *hctl, int device, CAEDeviceInfo& info, bool
   info.m_deviceType = AE_DEVTYPE_HDMI;
   return true;
 }
+
+void CAESinkALSA::sndLibErrorHandler(const char *file, int line, const char *function, int err, const char *fmt, ...)
+{
+  va_list arg;
+  va_start(arg, fmt);
+  char *errorStr;
+  if (vasprintf(&errorStr, fmt, arg) >= 0)
+  {
+    CLog::Log(LOGINFO, "CAESinkALSA - ALSA: %s:%d:(%s) %s%s%s",
+              file, line, function, errorStr, err ? ": " : "", err ? snd_strerror(err) : "");
+    free(errorStr);
+  }
+  va_end(arg);
+}
+
 #endif
index b735cbc..53cb479 100644 (file)
@@ -48,13 +48,13 @@ public:
   virtual double       GetDelay        ();
   virtual double       GetCacheTime    ();
   virtual double       GetCacheTotal   ();
-  virtual unsigned int AddPackets      (uint8_t *data, unsigned int frames);
+  virtual unsigned int AddPackets      (uint8_t *data, unsigned int frames, bool hasAudio);
   virtual void         Drain           ();
 
   static void EnumerateDevicesEx(AEDeviceInfoList &list);
 private:
   CAEChannelInfo GetChannelLayout(AEAudioFormat format);
-  void           GetPassthroughDevice(const AEAudioFormat format, std::string& device);
+  void           GetAESParams(const AEAudioFormat format, std::string& params);
   void           HandleError(const char* name, int err);
 
   std::string       m_initDevice;
@@ -73,8 +73,17 @@ private:
   bool InitializeHW(AEAudioFormat &format);
   bool InitializeSW(AEAudioFormat &format);
 
+  static void AppendParams(std::string &device, const std::string &params);
+  static bool TryDevice(const std::string &name, snd_pcm_t **pcmp, snd_config_t *lconf);
+  static bool TryDeviceWithParams(const std::string &name, const std::string &params, snd_pcm_t **pcmp, snd_config_t *lconf);
+  static bool OpenPCMDevice(const std::string &name, const std::string &params, int channels, snd_pcm_t **pcmp, snd_config_t *lconf, bool preferDmixStereo = false);
+
+  static void GetParamFromName(const std::string &name, const std::string &param, std::string &value);
+  static void EnumerateDevice(AEDeviceInfoList &list, const std::string &device, const std::string &description, snd_config_t *config);
   static bool SoundDeviceExists(const std::string& device);
   static bool GetELD(snd_hctl_t *hctl, int device, CAEDeviceInfo& info, bool& badHDMI);
+
+  static void sndLibErrorHandler(const char *file, int line, const char *function, int err, const char *fmt, ...);
 };
 #endif
 
index e1de033..e38d20c 100644 (file)
@@ -35,6 +35,7 @@
 #include <mmdeviceapi.h>
 #include <Functiondiscoverykeys_devpkey.h>
 #include <Rpc.h>
+#include "cores/AudioEngine/Utils/AEUtil.h"
 #pragma comment(lib, "Rpcrt4.lib")
 
 extern HWND g_hWnd;
@@ -354,7 +355,7 @@ bool CAESinkDirectSound::IsCompatible(const AEAudioFormat format, const std::str
   return false;
 }
 
-unsigned int CAESinkDirectSound::AddPackets(uint8_t *data, unsigned int frames)
+unsigned int CAESinkDirectSound::AddPackets(uint8_t *data, unsigned int frames, bool hasAudio)
 {
   if (!m_initialized)
     return 0;
index 0509193..4672a0f 100644 (file)
@@ -43,7 +43,7 @@ public:
   virtual double       GetDelay           ();
   virtual double       GetCacheTime       ();
   virtual double       GetCacheTotal      ();
-  virtual unsigned int AddPackets         (uint8_t *data, unsigned int frames);
+  virtual unsigned int AddPackets         (uint8_t *data, unsigned int frames, bool hasAudio);
   static  void         EnumerateDevicesEx (AEDeviceInfoList &deviceInfoList);
 private:
   void          AEChannelsFromSpeakerMask(DWORD speakers);
index d42d239..b6a0a8f 100644 (file)
@@ -81,7 +81,7 @@ double CAESinkNULL::GetDelay()
   return std::max(0.0, (double)(m_ts - CurrentHostCounter()) / 1000000.0f);
 }
 
-unsigned int CAESinkNULL::AddPackets(uint8_t *data, unsigned int frames)
+unsigned int CAESinkNULL::AddPackets(uint8_t *data, unsigned int frames, bool hasAudio)
 {
   float timeout = m_msPerFrame * frames;
   m_ts = CurrentHostCounter() + MathUtils::round_int(timeout * 1000000.0f);
index 461b1b0..20b7cc5 100644 (file)
@@ -40,7 +40,7 @@ public:
   virtual double       GetDelay        ();
   virtual double       GetCacheTime    () { return 0.0; }
   virtual double       GetCacheTotal   () { return 0.0; }
-  virtual unsigned int AddPackets      (uint8_t *data, unsigned int frames);
+  virtual unsigned int AddPackets      (uint8_t *data, unsigned int frames, bool hasAudio);
   virtual void         Drain           ();
   static void          EnumerateDevices(AEDeviceList &devices, bool passthrough);
 private:
index 188caf3..f7010c8 100644 (file)
@@ -427,7 +427,7 @@ double CAESinkOSS::GetDelay()
   return (double)delay / (m_format.m_frameSize * m_format.m_sampleRate);
 }
 
-unsigned int CAESinkOSS::AddPackets(uint8_t *data, unsigned int frames)
+unsigned int CAESinkOSS::AddPackets(uint8_t *data, unsigned int frames, bool hasAudio)
 {
   int size = frames * m_format.m_frameSize;
   int wrote = write(m_fd, data, size);
index 4010d77..d845525 100644 (file)
@@ -42,7 +42,7 @@ public:
   virtual double       GetDelay        ();
   virtual double       GetCacheTime    () { return 0.0; } /* FIXME */
   virtual double       GetCacheTotal   () { return 0.0; } /* FIXME */
-  virtual unsigned int AddPackets      (uint8_t *data, unsigned int frames);
+  virtual unsigned int AddPackets      (uint8_t *data, unsigned int frames, bool hasAudio);
   virtual void         Drain           ();
   static  void         EnumerateDevicesEx(AEDeviceInfoList &list);
 private:
index 0962aca..29bd07a 100644 (file)
@@ -73,7 +73,7 @@ double CAESinkProfiler::GetDelay()
   return 0.0f;
 }
 
-unsigned int CAESinkProfiler::AddPackets(uint8_t *data, unsigned int frames)
+unsigned int CAESinkProfiler::AddPackets(uint8_t *data, unsigned int frames, bool hasAudio)
 {
   int64_t ts = CurrentHostCounter();
   CLog::Log(LOGDEBUG, "CAESinkProfiler::AddPackets - latency %f ms", (float)(ts - m_ts) / 1000000.0f);
index 9edb6c2..6048091 100644 (file)
@@ -40,7 +40,7 @@ public:
   virtual double       GetDelay        ();
   virtual double       GetCacheTime    () { return 0.0; }
   virtual double       GetCacheTotal   () { return 0.0; }
-  virtual unsigned int AddPackets      (uint8_t *data, unsigned int frames);
+  virtual unsigned int AddPackets      (uint8_t *data, unsigned int frames, bool hasAudio);
   virtual void         Drain           ();
   static void          EnumerateDevices(AEDeviceList &devices, bool passthrough);
 private:
index 0806fc1..b94e6e8 100644 (file)
@@ -332,19 +332,7 @@ bool CAESinkWASAPI::IsCompatible(const AEAudioFormat format, const std::string d
 
 double CAESinkWASAPI::GetDelay()
 {
-  HRESULT hr;
-  if (!m_initialized)
-    return 0.0;
-
-  hr = m_pAudioClient->GetBufferSize(&m_uiBufferLen);
-  if (FAILED(hr))
-  {
-    #ifdef _DEBUG
-    CLog::Log(LOGERROR, __FUNCTION__": GetBufferSize Failed : %s", WASAPIErrToStr(hr));
-    #endif
-    return 0.0;
-  }
-  return (double)m_uiBufferLen / (double)m_format.m_sampleRate;
+  return GetCacheTime();
 }
 
 double CAESinkWASAPI::GetCacheTime()
@@ -352,11 +340,14 @@ double CAESinkWASAPI::GetCacheTime()
   if (!m_initialized)
     return 0.0;
 
-  REFERENCE_TIME hnsLatency;
-  HRESULT hr = m_pAudioClient->GetStreamLatency(&hnsLatency);
-
-  /** returns buffer duration in seconds */
-  return hnsLatency / 10.0;
+  unsigned int numPaddingFrames;
+  HRESULT hr = m_pAudioClient->GetCurrentPadding(&numPaddingFrames);
+  if (FAILED(hr))
+  {
+    CLog::Log(LOGERROR, __FUNCTION__": GetCurrentPadding Failed : %s", WASAPIErrToStr(hr));
+    return 0.0;
+  }
+  return (double)numPaddingFrames / (double)m_format.m_sampleRate;
 }
 
 double CAESinkWASAPI::GetCacheTotal()
@@ -371,7 +362,7 @@ double CAESinkWASAPI::GetCacheTotal()
   return hnsLatency / 10.0;
 }
 
-unsigned int CAESinkWASAPI::AddPackets(uint8_t *data, unsigned int frames)
+unsigned int CAESinkWASAPI::AddPackets(uint8_t *data, unsigned int frames, bool hasAudio)
 {
   if (!m_initialized)
     return 0;
index 498184b..3f04602 100644 (file)
@@ -43,7 +43,7 @@ public:
     virtual double       GetDelay                    ();
     virtual double       GetCacheTime                ();
     virtual double       GetCacheTotal               ();
-    virtual unsigned int AddPackets                  (uint8_t *data, unsigned int frames);
+    virtual unsigned int AddPackets                  (uint8_t *data, unsigned int frames, bool hasAudio);
     static  void         EnumerateDevicesEx          (AEDeviceInfoList &deviceInfoList);
 private:
     bool         InitializeExclusive(AEAudioFormat &format);
index f6f2731..17b9440 100644 (file)
@@ -20,6 +20,8 @@
  */
 
 #include "AEBitstreamPacker.h"
+#include "AEPackIEC61937.h"
+#include "AEStreamInfo.h"
 #include <stdint.h>
 #include <stddef.h>
 #include <string.h>
@@ -56,6 +58,18 @@ void CAEBitstreamPacker::Pack(CAEStreamInfo &info, uint8_t* data, int size)
       PackDTSHD (info, data, size);
       break;
 
+    case CAEStreamInfo::STREAM_TYPE_DTS_512:
+      m_dataSize = CAEPackIEC61937::PackDTS_512(data, size, m_packedBuffer, info.IsLittleEndian());
+      break;
+
+    case CAEStreamInfo::STREAM_TYPE_DTS_1024:
+      m_dataSize = CAEPackIEC61937::PackDTS_1024(data, size, m_packedBuffer, info.IsLittleEndian());
+      break;
+
+    case CAEStreamInfo::STREAM_TYPE_DTS_2048:
+      m_dataSize = CAEPackIEC61937::PackDTS_2048(data, size, m_packedBuffer, info.IsLittleEndian());
+      break;
+
     default:
       /* pack the data into an IEC61937 frame */
       CAEPackIEC61937::PackFunc pack = info.GetPackFunc();
index efbb80c..dc08fdb 100644 (file)
@@ -23,7 +23,8 @@
 #include <stdint.h>
 #include <list>
 #include "AEPackIEC61937.h"
-#include "AEStreamInfo.h"
+
+class CAEStreamInfo;
 
 class CAEBitstreamPacker
 {
index 08d1221..49fd6b8 100644 (file)
@@ -23,8 +23,6 @@
 #include <stdint.h>
 #include "../AEAudioFormat.h"
 
-/* note: always converts to machine byte endian */
-
 class CAEConvert{
 private:
   static unsigned int U8_Float    (uint8_t *data, const unsigned int samples, float   *dest);
index fbfed76..7604ace 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <sstream>
 #include "AEDeviceInfo.h"
+#include "AEUtil.h"
 
 CAEDeviceInfo::operator std::string()
 {
index 2449ec1..fc9c29e 100644 (file)
@@ -24,7 +24,6 @@
 #include <vector>
 #include "AEAudioFormat.h"
 #include "Utils/AEChannelInfo.h"
-#include "Utils/AEUtil.h"
 
 typedef std::vector<unsigned int     > AESampleRateList;
 typedef std::vector<enum AEDataFormat> AEDataFormatList;
index 6421007..e2babde 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 #include "AEELDParser.h"
+#include "AEDeviceInfo.h"
 #include "utils/EndianSwap.h"
 #include <string.h>
 
index 8196e00..2e06256 100644 (file)
@@ -22,7 +22,8 @@
 
 #include <stdint.h>
 #include <cstring>
-#include "AEDeviceInfo.h"
+
+class CAEDeviceInfo;
 
 class CAEELDParser {
 public:
index 437d844..2c69d14 100644 (file)
@@ -19,8 +19,6 @@
  *
  */
 
-/* DTS spec shows it suppors both BE and LE, we should not need to convert */
-
 #include <cassert>
 #include "system.h"
 #include "AEPackIEC61937.h"
@@ -85,73 +83,19 @@ int CAEPackIEC61937::PackEAC3(uint8_t *data, unsigned int size, uint8_t *dest)
   return OUT_FRAMESTOBYTES(EAC3_FRAME_SIZE);
 }
 
-int CAEPackIEC61937::PackDTS_512(uint8_t *data, unsigned int size, uint8_t *dest)
+int CAEPackIEC61937::PackDTS_512(uint8_t *data, unsigned int size, uint8_t *dest, bool littleEndian)
 {
-  assert(size <= OUT_FRAMESTOBYTES(DTS1_FRAME_SIZE));
-  struct IEC61937Packet *packet = (struct IEC61937Packet*)dest;
-  packet->m_preamble1 = IEC61937_PREAMBLE1;
-  packet->m_preamble2 = IEC61937_PREAMBLE2;
-  packet->m_type      = IEC61937_TYPE_DTS1;
-  packet->m_length    = size << 3;
-
-  if (data == NULL)
-    data = packet->m_data;
-#ifdef __BIG_ENDIAN__
-  else
-    memcpy(packet->m_data, data, size);
-#else
-  size += size & 0x1;
-  SwapEndian((uint16_t*)packet->m_data, (uint16_t*)data, size >> 1);
-#endif
-
-  memset(packet->m_data + size, 0, OUT_FRAMESTOBYTES(DTS1_FRAME_SIZE) - IEC61937_DATA_OFFSET - size);
-  return OUT_FRAMESTOBYTES(DTS1_FRAME_SIZE);
+  return PackDTS(data, size, dest, littleEndian, OUT_FRAMESTOBYTES(DTS1_FRAME_SIZE), IEC61937_TYPE_DTS1);
 }
 
-int CAEPackIEC61937::PackDTS_1024(uint8_t *data, unsigned int size, uint8_t *dest)
+int CAEPackIEC61937::PackDTS_1024(uint8_t *data, unsigned int size, uint8_t *dest, bool littleEndian)
 {
-  assert(size <= OUT_FRAMESTOBYTES(DTS2_FRAME_SIZE));
-  struct IEC61937Packet *packet = (struct IEC61937Packet*)dest;
-  packet->m_preamble1 = IEC61937_PREAMBLE1;
-  packet->m_preamble2 = IEC61937_PREAMBLE2;
-  packet->m_type      = IEC61937_TYPE_DTS2;
-  packet->m_length    = size << 3;
-
-  if (data == NULL)
-    data = packet->m_data;
-#ifdef __BIG_ENDIAN__
-  else
-    memcpy(packet->m_data, data, size);
-#else
-  size += size & 0x1;
-  SwapEndian((uint16_t*)packet->m_data, (uint16_t*)data, size >> 1);
-#endif
-
-  memset(packet->m_data + size, 0, OUT_FRAMESTOBYTES(DTS2_FRAME_SIZE) - IEC61937_DATA_OFFSET - size);
-  return OUT_FRAMESTOBYTES(DTS2_FRAME_SIZE);
+  return PackDTS(data, size, dest, littleEndian, OUT_FRAMESTOBYTES(DTS2_FRAME_SIZE), IEC61937_TYPE_DTS2);
 }
 
-int CAEPackIEC61937::PackDTS_2048(uint8_t *data, unsigned int size, uint8_t *dest)
+int CAEPackIEC61937::PackDTS_2048(uint8_t *data, unsigned int size, uint8_t *dest, bool littleEndian)
 {
-  assert(size <= OUT_FRAMESTOBYTES(DTS3_FRAME_SIZE));
-  struct IEC61937Packet *packet = (struct IEC61937Packet*)dest;
-  packet->m_preamble1 = IEC61937_PREAMBLE1;
-  packet->m_preamble2 = IEC61937_PREAMBLE2;
-  packet->m_type      = IEC61937_TYPE_DTS3;
-  packet->m_length    = size << 3;
-
-  if (data == NULL)
-    data = packet->m_data;
-#ifdef __BIG_ENDIAN__
-  else
-    memcpy(packet->m_data, data, size);
-#else
-  size += size & 0x1;
-  SwapEndian((uint16_t*)packet->m_data, (uint16_t*)data, size >> 1);
-#endif
-
-  memset(packet->m_data + size, 0, OUT_FRAMESTOBYTES(DTS3_FRAME_SIZE) - IEC61937_DATA_OFFSET - size);
-  return OUT_FRAMESTOBYTES(DTS3_FRAME_SIZE);
+  return PackDTS(data, size, dest, littleEndian, OUT_FRAMESTOBYTES(DTS3_FRAME_SIZE), IEC61937_TYPE_DTS3);
 }
 
 int CAEPackIEC61937::PackTrueHD(uint8_t *data, unsigned int size, uint8_t *dest)
@@ -220,3 +164,56 @@ int CAEPackIEC61937::PackDTSHD(uint8_t *data, unsigned int size, uint8_t *dest,
   return burstsize;
 }
 
+int CAEPackIEC61937::PackDTS(uint8_t *data, unsigned int size, uint8_t *dest, bool littleEndian,
+                             unsigned int frameSize, uint16_t type)
+{
+  assert(size <= frameSize);
+
+  /* BE is the standard endianness, byteswap needed if LE */
+  bool byteSwapNeeded = littleEndian;
+
+#ifndef __BIG_ENDIAN__
+  /* on LE systems we want LE output, byteswap needed */
+  byteSwapNeeded ^= true;
+#endif
+
+  struct IEC61937Packet *packet = (struct IEC61937Packet*)dest;
+  uint8_t *dataTo;
+
+  if (size == frameSize)
+  {
+    /* No packing possible or needed, DTS stream is suitable for direct output */
+    dataTo = dest;
+  }
+  else if (size <= frameSize - IEC61937_DATA_OFFSET)
+  {
+    /* Fits to IEC61937, perform packing */
+    packet->m_preamble1 = IEC61937_PREAMBLE1;
+    packet->m_preamble2 = IEC61937_PREAMBLE2;
+    packet->m_type      = type;
+    packet->m_length    = size << 3;
+
+    dataTo = packet->m_data;
+  }
+  else
+  {
+    /* Stream is unsuitable for both packing and direct output */
+    return 0;
+  }
+
+  if (data == NULL)
+    data = dataTo;
+  else if (!byteSwapNeeded)
+    memcpy(dataTo, data, size);
+
+  if (byteSwapNeeded)
+  {
+    size += size & 0x1;
+    SwapEndian((uint16_t*)dataTo, (uint16_t*)data, size >> 1);
+  }
+  
+  if (size != frameSize)
+    memset(packet->m_data + size, 0, frameSize - IEC61937_DATA_OFFSET - size);
+
+  return frameSize;
+}
index a59bbfa..b604127 100644 (file)
@@ -52,12 +52,16 @@ public:
 
   static int PackAC3     (uint8_t *data, unsigned int size, uint8_t *dest);
   static int PackEAC3    (uint8_t *data, unsigned int size, uint8_t *dest);
-  static int PackDTS_512 (uint8_t *data, unsigned int size, uint8_t *dest);
-  static int PackDTS_1024(uint8_t *data, unsigned int size, uint8_t *dest);
-  static int PackDTS_2048(uint8_t *data, unsigned int size, uint8_t *dest);
+  static int PackDTS_512 (uint8_t *data, unsigned int size, uint8_t *dest, bool littleEndian);
+  static int PackDTS_1024(uint8_t *data, unsigned int size, uint8_t *dest, bool littleEndian);
+  static int PackDTS_2048(uint8_t *data, unsigned int size, uint8_t *dest, bool littleEndian);
   static int PackTrueHD  (uint8_t *data, unsigned int size, uint8_t *dest);
   static int PackDTSHD   (uint8_t *data, unsigned int size, uint8_t *dest, unsigned int period);
 private:
+
+  static int PackDTS(uint8_t *data, unsigned int size, uint8_t *dest, bool littleEndian,
+                     unsigned int frameSize, uint16_t type);
+
   enum IEC61937DataType
   {
     IEC61937_TYPE_NULL   = 0x00,
index 8a7e7f6..4213fec 100644 (file)
@@ -504,9 +504,9 @@ unsigned int CAEStreamInfo::SyncDTS(uint8_t *data, unsigned int size)
     DataType dataType;
     switch (dtsBlocks << 5)
     {
-      case 512 : dataType = STREAM_TYPE_DTS_512 ; m_packFunc = &CAEPackIEC61937::PackDTS_512 ; break;
-      case 1024: dataType = STREAM_TYPE_DTS_1024; m_packFunc = &CAEPackIEC61937::PackDTS_1024; break;
-      case 2048: dataType = STREAM_TYPE_DTS_2048; m_packFunc = &CAEPackIEC61937::PackDTS_2048; break;
+      case 512 : dataType = STREAM_TYPE_DTS_512 ; break;
+      case 1024: dataType = STREAM_TYPE_DTS_1024; break;
+      case 2048: dataType = STREAM_TYPE_DTS_2048; break;
       default:
         invalid = true;
         break;
index 0926d30..f2a01f3 100644 (file)
@@ -455,3 +455,20 @@ void CAEUtil::FloatRand4(const float min, const float max, float result[4], __m1
     result[3] = ((float)(m_seed = (214013 * m_seed + 2531011)) * factor) - delta;
   #endif
 }
+
+bool CAEUtil::S16NeedsByteSwap(AEDataFormat in, AEDataFormat out)
+{
+  const AEDataFormat nativeFormat =
+#ifdef WORDS_BIGENDIAN
+    AE_FMT_S16BE;
+#else
+    AE_FMT_S16LE;
+#endif
+
+  if (in == AE_FMT_S16NE || AE_IS_RAW(in))
+    in = nativeFormat;
+  if (out == AE_FMT_S16NE || AE_IS_RAW(out))
+    out = nativeFormat;
+
+  return in != out;
+}
index c5dec2a..12353a5 100644 (file)
@@ -90,4 +90,6 @@ public:
   */
   static float FloatRand1(const float min, const float max);
   static void  FloatRand4(const float min, const float max, float result[4], __m128 *sseresult = NULL);
+
+  static bool S16NeedsByteSwap(AEDataFormat in, AEDataFormat out);
 };
index 5770dd6..0ef2a76 100644 (file)
@@ -27,6 +27,7 @@
 #include "DVDCodecs/DVDCodecs.h"
 #include "DVDPlayerAudio.h"
 #include "cores/AudioEngine/AEFactory.h"
+#include "cores/AudioEngine/Interfaces/AEStream.h"
 #include "settings/Settings.h"
 
 using namespace std;
index 35529f0..7886d43 100644 (file)
@@ -27,7 +27,8 @@
 #include "threads/CriticalSection.h"
 #include "PlatformDefs.h"
 
-#include "cores/AudioEngine/Interfaces/AEStream.h"
+#include "cores/AudioEngine/Utils/AEChannelInfo.h"
+class IAEStream;
 
 #ifndef _LINUX
 enum CodecID;
index 7037dfa..faf3c81 100644 (file)
  */
 
 #include "DVDPlayerTeletext.h"
-#include "settings/Settings.h"
-#include "DVDPlayer.h"
+#include "DVDClock.h"
 #include "DVDStreamInfo.h"
-#include "Application.h"
 #include "DVDCodecs/DVDCodecs.h"
 #include "utils/log.h"
 #include "threads/SingleLock.h"
index 08c1dce..b26d5d0 100644 (file)
@@ -22,6 +22,7 @@
 #include "system.h"
 #include "BXAcodec.h"
 #include "utils/EndianSwap.h"
+#include "cores/AudioEngine/Utils/AEUtil.h"
 
 BXACodec::BXACodec()
 {
index ffe9b05..7821471 100644 (file)
@@ -22,6 +22,7 @@
 #include "FLACcodec.h"
 #include "music/tags/FlacTag.h"
 #include "utils/log.h"
+#include "cores/AudioEngine/Utils/AEUtil.h"
 
 using namespace MUSIC_INFO;
 
index c1bfecc..dc31d1a 100644 (file)
@@ -26,7 +26,6 @@
 #include "filesystem/File.h"
 
 #include "cores/AudioEngine/AEAudioFormat.h"
-#include "cores/AudioEngine/Utils/AEUtil.h"
 
 #define READ_EOF      -1
 #define READ_SUCCESS   0
@@ -94,7 +93,8 @@ public:
 
   // GetChannelInfo()
   // Return the channel layout and count information in an CAEChannelInfo object
-  virtual CAEChannelInfo GetChannelInfo() {return CAEUtil::GuessChLayout(m_Channels);}
+  // Implemented in PAPlayer.cpp to avoid an include here
+  virtual CAEChannelInfo GetChannelInfo(); 
 
   int64_t m_TotalTime;  // time in ms
   int m_SampleRate;
index bd1cc4c..03871a8 100644 (file)
@@ -22,6 +22,7 @@
 #include "MP3codec.h"
 #include "FileItem.h"
 #include "utils/log.h"
+#include "cores/AudioEngine/Utils/AEUtil.h"
 
 using namespace MUSIC_INFO;
 
index 120eb49..524f902 100644 (file)
@@ -24,6 +24,7 @@
 #include "FileItem.h"
 #include "utils/log.h"
 #include "utils/URIUtils.h"
+#include "cores/AudioEngine/Utils/AEUtil.h"
 
 using namespace MUSIC_INFO;
 
index fe805d0..492bdfd 100644 (file)
 #include "utils/MathUtils.h"
 
 #include "threads/SingleLock.h"
+#include "cores/AudioEngine/AEFactory.h"
 #include "cores/AudioEngine/Utils/AEUtil.h"
+#include "cores/AudioEngine/Interfaces/AEStream.h"
 
 #define TIME_TO_CACHE_NEXT_FILE 5000 /* 5 seconds before end of song, start caching the next song */
 #define FAST_XFADE_TIME           80 /* 80 milliseconds */
+#define MAX_SKIP_XFADE_TIME     2000 /* max 2 seconds crossfade on track skip */
+
+CAEChannelInfo ICodec::GetChannelInfo()
+{
+  return CAEUtil::GuessChLayout(m_Channels);
+}
 
 // PAP: Psycho-acoustic Audio Player
 // Supporting all open  audio codec standards.
 // First one being nullsoft's nsv audio decoder format
 
 PAPlayer::PAPlayer(IPlayerCallback& callback) :
-  IPlayer            (callback),
-  CThread            ("PAPlayer"),
-  m_signalSpeedChange(false),
-  m_playbackSpeed    (1    ),
-  m_isPlaying        (false),
-  m_isPaused         (false),
-  m_isFinished       (false),
-  m_currentStream    (NULL ),
-  m_audioCallback    (NULL ),
-  m_FileItem         (new CFileItem() )
+  IPlayer              (callback),
+  CThread              ("PAPlayer"),
+  m_signalSpeedChange  (false),
+  m_playbackSpeed      (1    ),
+  m_isPlaying          (false),
+  m_isPaused           (false),
+  m_isFinished         (false),
+  m_defaultCrossfadeMS (0),
+  m_upcomingCrossfadeMS(0),
+  m_currentStream      (NULL ),
+  m_audioCallback      (NULL ),
+  m_FileItem           (new CFileItem())
 {
 }
 
@@ -221,12 +231,29 @@ void PAPlayer::CloseAllStreams(bool fade/* = true */)
 
 bool PAPlayer::OpenFile(const CFileItem& file, const CPlayerOptions &options)
 {
-  CloseAllStreams();
-  m_crossFadeTime = g_guiSettings.GetInt("musicplayer.crossfade") * 1000;
+  m_defaultCrossfadeMS = g_guiSettings.GetInt("musicplayer.crossfade") * 1000;
+
+  if (m_streams.size() > 1 || !m_defaultCrossfadeMS)
+  {
+    CloseAllStreams();
+  }
 
   if (!QueueNextFileEx(file, false))
     return false;
 
+  CSharedLock lock(m_streamsLock);
+  if (m_streams.size() == 2)
+  {
+    //do a short crossfade on trackskip, set to max 2 seconds for these prev/next transitions
+    m_upcomingCrossfadeMS = std::min(m_defaultCrossfadeMS, (unsigned int)MAX_SKIP_XFADE_TIME);
+
+    //start transition to next track
+    StreamInfo* si = m_streams.front();
+    si->m_playNextAtFrame  = si->m_framesSent; //start next track at current frame
+    si->m_prepareTriggered = true; //next track is ready to go
+  }
+  lock.Leave();
+
   if (!IsRunning())
     Create();
 
@@ -236,9 +263,10 @@ bool PAPlayer::OpenFile(const CFileItem& file, const CPlayerOptions &options)
   return true;
 }
 
-void PAPlayer::UpdateCrossFadingTime(const CFileItem& file)
+void PAPlayer::UpdateCrossfadeTime(const CFileItem& file)
 {
-  if ((m_crossFadeTime = g_guiSettings.GetInt("musicplayer.crossfade") * 1000))
+  m_upcomingCrossfadeMS = m_defaultCrossfadeMS = g_guiSettings.GetInt("musicplayer.crossfade") * 1000;
+  if (m_upcomingCrossfadeMS)
   {
     if (
         file.HasMusicInfoTag() && !g_guiSettings.GetBool("musicplayer.crossfadealbumtracks") &&
@@ -250,7 +278,7 @@ void PAPlayer::UpdateCrossFadingTime(const CFileItem& file)
     )
     {
       //do not crossfade when playing consecutive albumtracks
-      m_crossFadeTime = 0;
+      m_upcomingCrossfadeMS = 0;
     }
   }
 }
@@ -262,9 +290,6 @@ bool PAPlayer::QueueNextFile(const CFileItem &file)
 
 bool PAPlayer::QueueNextFileEx(const CFileItem &file, bool fadeIn/* = true */)
 {
-  //set crossfade time for the file being queued
-  UpdateCrossFadingTime(file);
-
   StreamInfo *si = new StreamInfo();
 
   if (!si->m_decoder.Create(file, (file.m_lStartOffset * 1000) / 75))
@@ -297,6 +322,8 @@ bool PAPlayer::QueueNextFileEx(const CFileItem &file, bool fadeIn/* = true */)
     CThread::Sleep(1);
   }
 
+  UpdateCrossfadeTime(file);
+
   /* init the streaminfo struct */
   si->m_decoder.GetDataFormat(&si->m_channelInfo, &si->m_sampleRate, &si->m_encodedSampleRate, &si->m_dataFormat);
   si->m_startOffset        = file.m_lStartOffset * 1000 / 75;
@@ -309,24 +336,21 @@ bool PAPlayer::QueueNextFileEx(const CFileItem &file, bool fadeIn/* = true */)
   si->m_seekNextAtFrame    = 0;
   si->m_seekFrame          = -1;
   si->m_stream             = NULL;
-  si->m_volume             = (fadeIn && m_crossFadeTime) ? 0.0f : 1.0f;
+  si->m_volume             = (fadeIn && m_upcomingCrossfadeMS) ? 0.0f : 1.0f;
   si->m_fadeOutTriggered   = false;
   si->m_isSlaved           = false;
 
   int64_t streamTotalTime = si->m_decoder.TotalTime();
   if (si->m_endOffset)
     streamTotalTime = si->m_endOffset - si->m_startOffset;
-
-  if (streamTotalTime >= TIME_TO_CACHE_NEXT_FILE + m_crossFadeTime)
-    si->m_prepareNextAtFrame = (int)((streamTotalTime - TIME_TO_CACHE_NEXT_FILE - m_crossFadeTime) * si->m_sampleRate / 1000.0f);
+  
+  si->m_prepareNextAtFrame = 0;
+  if (streamTotalTime >= TIME_TO_CACHE_NEXT_FILE + m_defaultCrossfadeMS)
+    si->m_prepareNextAtFrame = (int)((streamTotalTime - TIME_TO_CACHE_NEXT_FILE - m_defaultCrossfadeMS) * si->m_sampleRate / 1000.0f);
 
   si->m_prepareTriggered = false;
 
-  if (streamTotalTime < m_crossFadeTime)
-    si->m_playNextAtFrame = (int)((streamTotalTime / 2) * si->m_sampleRate / 1000.0f);
-  else
-    si->m_playNextAtFrame = (int)((streamTotalTime - m_crossFadeTime) * si->m_sampleRate / 1000.0f);
-
+  si->m_playNextAtFrame = 0;
   si->m_playNextTriggered = false;
 
   PrepareStream(si);
@@ -334,12 +358,28 @@ bool PAPlayer::QueueNextFileEx(const CFileItem &file, bool fadeIn/* = true */)
   /* add the stream to the list */
   CExclusiveLock lock(m_streamsLock);
   m_streams.push_back(si);
+  //update the current stream to start playing the next track at the correct frame.
+  UpdateStreamInfoPlayNextAtFrame(m_currentStream, m_upcomingCrossfadeMS);
 
   *m_FileItem = file;
 
   return true;
 }
 
+void PAPlayer::UpdateStreamInfoPlayNextAtFrame(StreamInfo *si, unsigned int crossFadingTime)
+{
+  if (si)
+  {
+    int64_t streamTotalTime = si->m_decoder.TotalTime();
+    if (si->m_endOffset)
+      streamTotalTime = si->m_endOffset - si->m_startOffset;
+    if (streamTotalTime < crossFadingTime)
+      si->m_playNextAtFrame = (int)((streamTotalTime / 2) * si->m_sampleRate / 1000.0f);
+    else
+      si->m_playNextAtFrame = (int)((streamTotalTime - crossFadingTime) * si->m_sampleRate / 1000.0f);
+  }
+}
+
 inline bool PAPlayer::PrepareStream(StreamInfo *si)
 {
   /* if we have a stream we are already prepared */
@@ -365,7 +405,7 @@ inline bool PAPlayer::PrepareStream(StreamInfo *si)
   si->m_stream->SetReplayGain(si->m_decoder.GetReplayGain());
 
   /* if its not the first stream and crossfade is not enabled */
-  if (m_currentStream && m_currentStream != si && !m_crossFadeTime)
+  if (m_currentStream && m_currentStream != si && !m_upcomingCrossfadeMS)
   {
     /* slave the stream for gapless */
     si->m_isSlaved = true;
@@ -523,9 +563,9 @@ inline void PAPlayer::ProcessStreams(double &delay, double &buffer)
 
       if (!m_isFinished)
       {
-        if (m_crossFadeTime)
+        if (m_upcomingCrossfadeMS)
         {
-          si->m_stream->FadeVolume(1.0f, 0.0f, m_crossFadeTime);
+          si->m_stream->FadeVolume(1.0f, 0.0f, m_upcomingCrossfadeMS);
           si->m_fadeOutTriggered = true;
         }
         m_currentStream = NULL;
@@ -548,7 +588,7 @@ inline bool PAPlayer::ProcessStream(StreamInfo *si, double &delay, double &buffe
     si->m_stream->RegisterAudioCallback(m_audioCallback);
     if (!si->m_isSlaved)
       si->m_stream->Resume();
-    si->m_stream->FadeVolume(0.0f, 1.0f, m_crossFadeTime);
+    si->m_stream->FadeVolume(0.0f, 1.0f, m_upcomingCrossfadeMS);
     m_callback.OnPlayBackStarted();
   }
 
index 205ea67..46d04b5 100644 (file)
@@ -29,8 +29,9 @@
 #include "threads/SharedSection.h"
 
 #include "cores/IAudioCallback.h"
-#include "cores/AudioEngine/AEFactory.h"
-#include "cores/AudioEngine/Interfaces/AEStream.h"
+#include "cores/AudioEngine/Utils/AEChannelInfo.h"
+
+class IAEStream;
 
 class CFileItem;
 class PAPlayer : public IPlayer, public CThread
@@ -114,7 +115,8 @@ private:
   bool                m_isPlaying;
   bool                m_isPaused;
   bool                m_isFinished;          /* if there are no more songs in the queue */
-  unsigned int        m_crossFadeTime;       /* how long the crossfade is */
+  unsigned int        m_defaultCrossfadeMS;  /* how long the default crossfade is in ms */
+  unsigned int        m_upcomingCrossfadeMS; /* how long the upcoming crossfade is in ms */
   CEvent              m_startEvent;          /* event for playback start */
   StreamInfo*         m_currentStream;       /* the current playing stream */
   IAudioCallback*     m_audioCallback;       /* the viz audio callback */
@@ -133,7 +135,8 @@ private:
   bool PrepareStream(StreamInfo *si);
   bool ProcessStream(StreamInfo *si, double &delay, double &buffer);
   bool QueueData(StreamInfo *si);
-  void UpdateCrossFadingTime(const CFileItem& file);
   int64_t GetTotalTime64();
+  void UpdateCrossfadeTime(const CFileItem& file);
+  void UpdateStreamInfoPlayNextAtFrame(StreamInfo *si, unsigned int crossFadingTime);
 };
 
index c8d9f78..7c1b932 100644 (file)
 #include "utils/AutoPtrHandle.h"
 #include "utils/log.h"
 #include "utils/URIUtils.h"
-#include "mysqldataset.h"
 #include "sqlitedataset.h"
 #include "threads/SingleLock.h"
 
+#ifdef HAS_MYSQL
+#include "mysqldataset.h"
+#endif
 
 using namespace AUTOPTR;
 using namespace dbiplus;
@@ -263,6 +265,7 @@ bool CDatabase::Open(const DatabaseSettings &settings)
 
   m_sqlite = true;
 
+#ifdef HAS_MYSQL
   if ( dbSettings.type.Equals("mysql") )
   {
     // check we have all information before we cancel the fallback
@@ -273,6 +276,10 @@ bool CDatabase::Open(const DatabaseSettings &settings)
       CLog::Log(LOGINFO, "Essential mysql database information is missing. Require at least host, user and pass defined.");
   }
   else
+#else
+  if ( dbSettings.type.Equals("mysql") )
+    CLog::Log(LOGERROR, "MySQL library requested but MySQL support is not compiled in. Falling back to sqlite3.");
+#endif
   {
     dbSettings.type = "sqlite3";
     dbSettings.host = CSpecialProtocol::TranslatePath(g_settings.GetDatabaseFolder());
@@ -366,10 +373,12 @@ bool CDatabase::Connect(const DatabaseSettings &dbSettings, bool create)
   {
     m_pDB.reset( new SqliteDatabase() ) ;
   }
+#ifdef HAS_MYSQL
   else if (dbSettings.type.Equals("mysql"))
   {
     m_pDB.reset( new MysqlDatabase() ) ;
   }
+#endif
   else
   {
     CLog::Log(LOGERROR, "Unable to determine database type: %s", dbSettings.type.c_str());
@@ -452,13 +461,27 @@ bool CDatabase::UpdateVersion(const CStdString &dbName)
   if (version < GetMinVersion())
   {
     CLog::Log(LOGNOTICE, "Attempting to update the database %s from version %i to %i", dbName.c_str(), version, GetMinVersion());
-    if (UpdateOldVersion(version) && UpdateVersionNumber())
-      CLog::Log(LOGINFO, "Update to version %i successfull", GetMinVersion());
-    else
+    bool success = false;
+    BeginTransaction();
+    try
     {
-      CLog::Log(LOGERROR, "Can't update the database %s from version %i to %i", dbName.c_str(), version, GetMinVersion());
+      success = UpdateOldVersion(version);
+      if (success)
+        success = UpdateVersionNumber();
+    }
+    catch (...)
+    {
+      CLog::Log(LOGERROR, "Exception updating database %s from version %i to %i", dbName.c_str(), version, GetMinVersion());
+      success = false;
+    }
+    if (!success)
+    {
+      CLog::Log(LOGERROR, "Error updating database %s from version %i to %i", dbName.c_str(), version, GetMinVersion());
+      RollbackTransaction();
       return false;
     }
+    CommitTransaction();
+    CLog::Log(LOGINFO, "Update to version %i successful", GetMinVersion());
   }
   else if (version > GetMinVersion())
   {
@@ -597,18 +620,8 @@ bool CDatabase::CreateTables()
 
 bool CDatabase::UpdateVersionNumber()
 {
-  try
-  {
-    CStdString strSQL=PrepareSQL("UPDATE version SET idVersion=%i\n", GetMinVersion());
-    m_pDS->exec(strSQL.c_str());
-
-    CommitTransaction();
-  }
-  catch(...)
-  {
-    return false;
-  }
-
+  CStdString strSQL=PrepareSQL("UPDATE version SET idVersion=%i\n", GetMinVersion());
+  m_pDS->exec(strSQL.c_str());
   return true;
 }
 
index b3ea5b2..21ea5e7 100644 (file)
 #include <string>
 #include <set>
 
-#include "mysqldataset.h"
 #include "utils/log.h"
 #include "system.h" // for GetLastError()
+
+#ifdef HAS_MYSQL
+#include "mysqldataset.h"
 #include "mysql/errmsg.h"
 #ifdef _WIN32
 #pragma comment(lib, "mysqlclient.lib")
@@ -1597,4 +1599,5 @@ void MysqlDataset::interrupt() {
 }
 
 }//namespace
+#endif //HAS_MYSQL
 
index 9a9600f..0771c7d 100644 (file)
@@ -104,6 +104,8 @@ enum CONTEXT_BUTTON { CONTEXT_BUTTON_CANCELLED = 0,
                       CONTEXT_BUTTON_SET_MOVIESET_FANART,
                       CONTEXT_BUTTON_DELETE_PLUGIN,
                       CONTEXT_BUTTON_PLAY_AND_QUEUE,
+                      CONTEXT_BUTTON_TAGS_ADD_ITEMS,
+                      CONTEXT_BUTTON_TAGS_REMOVE_ITEMS,
                       CONTEXT_BUTTON_USER1,
                       CONTEXT_BUTTON_USER2,
                       CONTEXT_BUTTON_USER3,
index 205c10b..594de64 100644 (file)
@@ -34,6 +34,7 @@
 #include "Application.h"
 #include "settings/AdvancedSettings.h"
 #include "guilib/LocalizeStrings.h"
+#include "interfaces/AnnouncementManager.h"
 
 // Symbol mapping (based on MS virtual keyboard - may need improving)
 static char symbol_map[37] = ")!@#$%^&*([]{}-_=+;:\'\",.<>/?\\|`~    ";
@@ -98,6 +99,11 @@ void CGUIDialogKeyboard::OnInitWindow()
   {
     SET_CONTROL_HIDDEN(CTL_LABEL_HEADING);
   }
+
+  CVariant data;
+  data["title"] = m_strHeading;
+  data["type"] = "keyboard";
+  ANNOUNCEMENT::CAnnouncementManager::Announce(ANNOUNCEMENT::Input, "xbmc", "OnInputRequested", data);
 }
 
 bool CGUIDialogKeyboard::OnAction(const CAction &action)
@@ -255,6 +261,14 @@ bool CGUIDialogKeyboard::OnMessage(CGUIMessage& message)
       }
     }
     break;
+
+  case GUI_MSG_SET_TEXT:
+    SetText(message.GetLabel());
+
+    // close the dialog if requested
+    if (message.GetParam1() > 0)
+      OnOK();
+    break;
   }
 
   return true;
@@ -664,6 +678,8 @@ void CGUIDialogKeyboard::OnDeinitWindow(int nextWindowID)
   CGUIDialog::OnDeinitWindow(nextWindowID);
   // reset the heading (we don't always have this)
   m_strHeading = "";
+
+  ANNOUNCEMENT::CAnnouncementManager::Announce(ANNOUNCEMENT::Input, "xbmc", "OnInputFinished");
 }
 
 void CGUIDialogKeyboard::MoveCursor(int iAmount)
index fb930be..0443f48 100644 (file)
@@ -27,6 +27,7 @@
 #include "input/XBMC_vkeys.h"
 #include "utils/StringUtils.h"
 #include "guilib/LocalizeStrings.h"
+#include "interfaces/AnnouncementManager.h"
 
 #define CONTROL_HEADING_LABEL  1
 #define CONTROL_INPUT_LABEL    4
@@ -54,6 +55,51 @@ CGUIDialogNumeric::~CGUIDialogNumeric(void)
 {
 }
 
+void CGUIDialogNumeric::OnInitWindow()
+{
+  CGUIDialog::OnInitWindow();
+
+  CVariant data;
+  switch (m_mode)
+  {
+  case INPUT_TIME:
+    data["type"] = "time";
+    break;
+  case INPUT_DATE:
+    data["type"] = "date";
+    break;
+  case INPUT_IP_ADDRESS:
+    data["type"] = "ip";
+    break;
+  case INPUT_PASSWORD:
+    data["type"] = "password";
+    break;
+  case INPUT_NUMBER:
+    data["type"] = "number";
+    break;
+  case INPUT_TIME_SECONDS:
+    data["type"] = "seconds";
+    break;
+  default:
+    data["type"] = "keyboard";
+    break;
+  }
+
+  const CGUILabelControl *control = (const CGUILabelControl *)GetControl(CONTROL_HEADING_LABEL);
+  if (control != NULL)
+    data["title"] = control->GetDescription();
+
+  ANNOUNCEMENT::CAnnouncementManager::Announce(ANNOUNCEMENT::Input, "xbmc", "OnInputRequested", data);
+}
+
+void CGUIDialogNumeric::OnDeinitWindow(int nextWindowID)
+{
+  // call base class
+  CGUIDialog::OnDeinitWindow(nextWindowID);
+
+  ANNOUNCEMENT::CAnnouncementManager::Announce(ANNOUNCEMENT::Input, "xbmc", "OnInputFinished");
+}
+
 bool CGUIDialogNumeric::OnAction(const CAction &action)
 {
   if (action.GetID() == ACTION_NEXT_ITEM)
@@ -139,6 +185,14 @@ bool CGUIDialogNumeric::OnMessage(CGUIMessage& message)
       }
     }
     break;
+
+  case GUI_MSG_SET_TEXT:
+    SetMode(m_mode, message.GetLabel());
+
+    // close the dialog if requested
+    if (message.GetParam1() > 0)
+      OnOK();
+    break;
   }
   return CGUIDialog::OnMessage(message);
 }
@@ -462,7 +516,7 @@ void CGUIDialogNumeric::SetMode(INPUT_MODE mode, void *initial)
     m_datetime = *(SYSTEMTIME *)initial;
     m_lastblock = (m_mode == INPUT_DATE) ? 2 : 1;
   }
-  if (m_mode == INPUT_IP_ADDRESS)
+  else if (m_mode == INPUT_IP_ADDRESS)
   {
     m_lastblock = 3;
     m_ip[0] = m_ip[1] = m_ip[2] = m_ip[3] = 0;
@@ -484,10 +538,51 @@ void CGUIDialogNumeric::SetMode(INPUT_MODE mode, void *initial)
       }
     }
   }
-  if (m_mode == INPUT_NUMBER || m_mode == INPUT_PASSWORD)
-  {
+  else if (m_mode == INPUT_NUMBER || m_mode == INPUT_PASSWORD)
     m_number = *(CStdString *)initial;
+}
+
+void CGUIDialogNumeric::SetMode(INPUT_MODE mode, const CStdString &initial)
+{
+  m_mode = mode;
+  m_block = 0;
+  m_lastblock = 0;
+  if (m_mode == INPUT_TIME || m_mode == INPUT_TIME_SECONDS || m_mode == INPUT_DATE)
+  {
+    CDateTime dateTime;
+    if (m_mode == INPUT_TIME || m_mode == INPUT_TIME_SECONDS)
+    {
+      // check if we have a pure number
+      if (initial.find_first_not_of("0123456789") == std::string::npos)
+      {
+        long seconds = strtol(initial.c_str(), NULL, 10);
+        dateTime = seconds;
+      }
+      else
+      {
+        CStdString tmp = initial;
+        // if we are handling seconds and if the string only contains
+        // "mm:ss" we need to add dummy "hh:" to get "hh:mm:ss"
+        if (m_mode == INPUT_TIME_SECONDS && tmp.size() <= 5)
+          tmp = "00:" + tmp;
+        dateTime.SetFromDBTime(tmp);
+      }
+    }
+    else if (m_mode == INPUT_DATE)
+    {
+      CStdString tmp = initial;
+      tmp.Replace("/", ".");
+      dateTime.SetFromDBDate(tmp);
+    }
+
+    if (!dateTime.IsValid())
+      return;
+
+    dateTime.GetAsSystemTime(m_datetime);
+    m_lastblock = (m_mode == INPUT_DATE) ? 2 : 1;
   }
+  else
+    SetMode(mode, (void*)&initial);
 }
 
 void CGUIDialogNumeric::GetOutput(void *output)
index ef1517b..7f74cf1 100644 (file)
@@ -44,6 +44,7 @@ public:
 
   void SetHeading(const CStdString &strHeading);
   void SetMode(INPUT_MODE mode, void *initial);
+  void SetMode(INPUT_MODE mode, const CStdString &initial);
   void GetOutput(void *output);
 
   static bool ShowAndGetTime(SYSTEMTIME &time, const CStdString &heading);
@@ -53,6 +54,9 @@ public:
   static bool ShowAndGetSeconds(CStdString& timeString, const CStdString &heading);
 
 protected:
+  virtual void OnInitWindow();
+  virtual void OnDeinitWindow(int nextWindowID);
+
   void OnNumber(unsigned int num);
   void VerifyDate(bool checkYear);
   void OnNext();
index 29856b4..1ca5f02 100644 (file)
@@ -240,6 +240,14 @@ void CGUIDialogSmartPlaylistRule::OnBrowse()
     videodatabase.GetSetsNav("videodb://1/7/", items, VIDEODB_CONTENT_MOVIES);
     iLabel = 20434;
   }
+  else if (m_rule.m_field == FieldTag)
+  {
+    if (m_type == "movies")
+      videodatabase.GetTagsNav("videodb://1/9/", items, VIDEODB_CONTENT_MOVIES);
+    else
+      return;
+    iLabel = 20459;
+  }
   else
   { // TODO: Add browseability in here.
     assert(false);
index 76d1a13..2c3e9f3 100644 (file)
@@ -106,7 +106,7 @@ public:
   virtual cmyth_timestamp_t proginfo_rec_start      (cmyth_proginfo_t prog)=0;
   virtual cmyth_timestamp_t proginfo_rec_end        (cmyth_proginfo_t prog)=0;
   virtual cmyth_proginfo_rec_status_t proginfo_rec_status(cmyth_proginfo_t prog)=0;
-  virtual char*             proginfo_prodyear       (cmyth_proginfo_t prog)=0;
+  virtual unsigned short    proginfo_year           (cmyth_proginfo_t prog)=0;
   virtual cmyth_proginfo_t  proginfo_get_from_basename   (cmyth_conn_t control, const char* basename)=0;
   virtual int               proginfo_delete_recording(cmyth_conn_t control, cmyth_proginfo_t prog)=0;
   virtual int               proginfo_stop_recording(cmyth_conn_t control, cmyth_proginfo_t prog)=0;
@@ -207,7 +207,7 @@ class DllLibCMyth : public DllDynamic, DllLibCMythInterface
   DEFINE_METHOD1(cmyth_timestamp_t,   proginfo_rec_end,         (cmyth_proginfo_t p1))
   DEFINE_METHOD1(cmyth_proginfo_rec_status_t, proginfo_rec_status, (cmyth_proginfo_t p1))
   DEFINE_METHOD1(unsigned long,       proginfo_flags,           (cmyth_proginfo_t p1))
-  DEFINE_METHOD1(char*,               proginfo_prodyear,        (cmyth_proginfo_t p1))
+  DEFINE_METHOD1(unsigned short,      proginfo_year,            (cmyth_proginfo_t p1))
   DEFINE_METHOD2(cmyth_proginfo_t,    proginfo_get_from_basename,    (cmyth_conn_t p1, const char* p2))
   DEFINE_METHOD2(int,                 proginfo_delete_recording, (cmyth_conn_t p1, cmyth_proginfo_t p2))
   DEFINE_METHOD2(int,                 proginfo_stop_recording,  (cmyth_conn_t p1, cmyth_proginfo_t p2))
@@ -302,7 +302,7 @@ class DllLibCMyth : public DllDynamic, DllLibCMythInterface
     RESOLVE_METHOD_RENAME(cmyth_proginfo_rec_end, proginfo_rec_end)
     RESOLVE_METHOD_RENAME(cmyth_proginfo_rec_status, proginfo_rec_status)
     RESOLVE_METHOD_RENAME(cmyth_proginfo_flags, proginfo_flags)
-    RESOLVE_METHOD_RENAME(cmyth_proginfo_prodyear, proginfo_prodyear)
+    RESOLVE_METHOD_RENAME(cmyth_proginfo_year, proginfo_year)
     RESOLVE_METHOD_RENAME(cmyth_proginfo_get_from_basename, proginfo_get_from_basename)
     RESOLVE_METHOD_RENAME(cmyth_proginfo_delete_recording, proginfo_delete_recording)
     RESOLVE_METHOD_RENAME(cmyth_proginfo_stop_recording, proginfo_stop_recording)
index c69654d..c0b36ef 100644 (file)
@@ -309,9 +309,9 @@ bool CMythDirectory::GetRecordings(const CStdString& base, CFileItemList &items,
          * lookups.
          */
         CStdString label(item->m_strTitle);
-        CStdString prodyear = GetValue(m_dll->proginfo_prodyear(program));
-        if (!prodyear.IsEmpty())
-          label += " (" + prodyear + ")";
+        unsigned short year = m_dll->proginfo_year(program);
+        if (year > 0)
+          label.AppendFormat(" (%d)", year);
         item->SetLabel(label);
         item->SetLabelPreformated(true);
       }
index ce8ba39..1b7bbcc 100644 (file)
@@ -160,6 +160,10 @@ bool CVideoDatabaseDirectory::GetLabel(const CStdString& strDirectory, CStdStrin
   if (params.GetSetId() != -1)
     strLabel += videodatabase.GetSetById(params.GetSetId());
 
+  // get tag
+  if (params.GetTagId() != -1)
+    strLabel += videodatabase.GetTagById(params.GetTagId());
+
   // get year
   if (params.GetYear() != -1)
   {
@@ -190,6 +194,8 @@ bool CVideoDatabaseDirectory::GetLabel(const CStdString& strDirectory, CStdStrin
       strLabel = g_localizeStrings.Get(20348); break;
     case NODE_TYPE_SETS: // Sets
       strLabel = g_localizeStrings.Get(20434); break;
+    case NODE_TYPE_TAGS: // Tags
+      strLabel = g_localizeStrings.Get(20459); break;
     case NODE_TYPE_MOVIES_OVERVIEW: // Movies
       strLabel = g_localizeStrings.Get(342); break;
     case NODE_TYPE_TVSHOWS_OVERVIEW: // TV Shows
@@ -253,6 +259,8 @@ CStdString CVideoDatabaseDirectory::GetIcon(const CStdString &strDirectory)
     return "DefaultCountry.png";
   case NODE_TYPE_SETS: // Sets
     return "DefaultSets.png";
+  case NODE_TYPE_TAGS: // Tags
+    return "DefaultTags.png";
   case NODE_TYPE_YEAR: // Year
     return "DefaultYear.png";
   case NODE_TYPE_DIRECTOR: // Director
index 6fcfeaa..1eb27b3 100644 (file)
@@ -43,6 +43,7 @@
 #include "DirectoryNodeRecentlyAddedMusicVideos.h"
 #include "DirectoryNodeTitleMusicVideos.h"
 #include "DirectoryNodeMusicVideoAlbum.h"
+#include "DirectoryNodeTags.h"
 #include "video/VideoInfoTag.h"
 #include "URL.h"
 #include "settings/AdvancedSettings.h"
@@ -122,6 +123,8 @@ CDirectoryNode* CDirectoryNode::CreateNode(NODE_TYPE Type, const CStdString& str
     return new CDirectoryNodeCountry(strName, pParent);
   case NODE_TYPE_SETS:
     return new CDirectoryNodeSets(strName, pParent);
+  case NODE_TYPE_TAGS:
+    return new CDirectoryNodeTags(strName, pParent);
   case NODE_TYPE_YEAR:
     return new CDirectoryNodeYear(strName, pParent);
   case NODE_TYPE_ACTOR:
index 8a51a50..0ba9896 100644 (file)
@@ -54,7 +54,8 @@ namespace XFILE
       NODE_TYPE_TITLE_MUSICVIDEOS,
       NODE_TYPE_MUSICVIDEOS_ALBUM,
       NODE_TYPE_SETS,
-      NODE_TYPE_COUNTRY
+      NODE_TYPE_COUNTRY,
+      NODE_TYPE_TAGS
     } NODE_TYPE;
 
     typedef struct {
index 1d9b7f6..87c5370 100644 (file)
@@ -36,6 +36,7 @@ Node MovieChildren[] = {
                         { NODE_TYPE_STUDIO,       6, 20388 },
                         { NODE_TYPE_SETS,         7, 20434 },
                         { NODE_TYPE_COUNTRY,      8, 20451 },
+                        { NODE_TYPE_TAGS,         9, 20459 }
                        };
 
 CDirectoryNodeMoviesOverview::CDirectoryNodeMoviesOverview(const CStdString& strName, CDirectoryNode* pParent)
diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTags.cpp b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTags.cpp
new file mode 100644 (file)
index 0000000..d95da74
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ *      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, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include "DirectoryNodeTags.h"
+#include "QueryParams.h"
+#include "video/VideoDatabase.h"
+
+using namespace XFILE::VIDEODATABASEDIRECTORY;
+
+CDirectoryNodeTags::CDirectoryNodeTags(const CStdString& strName, CDirectoryNode* pParent)
+  : CDirectoryNode(NODE_TYPE_TAGS, strName, pParent)
+{
+
+}
+
+NODE_TYPE CDirectoryNodeTags::GetChildType() const
+{
+  return NODE_TYPE_TITLE_MOVIES;
+}
+
+CStdString CDirectoryNodeTags::GetLocalizedName() const
+{
+  CVideoDatabase db;
+  if (db.Open())
+    return db.GetTagById(GetID());
+  return "";
+}
+
+bool CDirectoryNodeTags::GetContent(CFileItemList& items) const
+{
+  CVideoDatabase videodatabase;
+  if (!videodatabase.Open())
+    return false;
+
+  CQueryParams params;
+  CollectQueryParams(params);
+
+  bool bSuccess = videodatabase.GetTagsNav(BuildPath(), items, params.GetContentType());
+  videodatabase.Close();
+
+  return bSuccess;
+}
diff --git a/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTags.h b/xbmc/filesystem/VideoDatabaseDirectory/DirectoryNodeTags.h
new file mode 100644 (file)
index 0000000..7ab10ec
--- /dev/null
@@ -0,0 +1,41 @@
+#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, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include "DirectoryNode.h"
+
+namespace XFILE
+{
+  namespace VIDEODATABASEDIRECTORY
+  {
+    class CDirectoryNodeTags : public CDirectoryNode
+    {
+    public:
+      CDirectoryNodeTags(const CStdString& strName, CDirectoryNode* pParent);
+    protected:
+      virtual NODE_TYPE GetChildType() const;
+      virtual bool GetContent(CFileItemList& items) const;
+      virtual CStdString GetLocalizedName() const;
+    };
+  }
+}
+
+
index 07557c7..7989c81 100644 (file)
@@ -41,7 +41,7 @@ bool CDirectoryNodeTitleMovies::GetContent(CFileItemList& items) const
   CollectQueryParams(params);
 
   CStdString strBaseDir=BuildPath();
-  bool bSuccess=videodatabase.GetMoviesNav(strBaseDir, items, params.GetGenreId(), params.GetYear(), params.GetActorId(), params.GetDirectorId(), params.GetStudioId(), params.GetCountryId(), params.GetSetId());
+  bool bSuccess=videodatabase.GetMoviesNav(strBaseDir, items, params.GetGenreId(), params.GetYear(), params.GetActorId(), params.GetDirectorId(), params.GetStudioId(), params.GetCountryId(), params.GetSetId(), params.GetTagId());
 
   videodatabase.Close();
 
index 2bd4107..bda9117 100644 (file)
@@ -15,6 +15,7 @@ SRCS=DirectoryNode.cpp \
      DirectoryNodeSeasons.cpp \
      DirectoryNodeSets.cpp \
      DirectoryNodeStudio.cpp \
+     DirectoryNodeTags.cpp \
      DirectoryNodeTitleMovies.cpp \
      DirectoryNodeTitleMusicVideos.cpp \
      DirectoryNodeTitleTvShows.cpp \
index ea84cbe..5c2089e 100644 (file)
@@ -39,6 +39,7 @@ CQueryParams::CQueryParams()
   m_idMVideo = -1;
   m_idAlbum = -1;
   m_idSet = -1;
+  m_idTag = -1;
 }
 
 void CQueryParams::SetQueryParam(NODE_TYPE NodeType, const CStdString& strNodeName)
@@ -92,6 +93,9 @@ void CQueryParams::SetQueryParam(NODE_TYPE NodeType, const CStdString& strNodeNa
   case NODE_TYPE_SETS:
     m_idSet = idDb;
     break;
+  case NODE_TYPE_TAGS:
+    m_idTag = idDb;
+    break;
   default:
     break;
   }
index 60adaea..9fb7efc 100644 (file)
@@ -44,6 +44,7 @@ namespace XFILE
       long GetStudioId() const { return m_idStudio; }
       long GetMVideoId() const { return m_idMVideo; }
       long GetSetId() const { return m_idSet; }
+      long GetTagId() const { return m_idTag; }
 
     protected:
       void SetQueryParam(NODE_TYPE NodeType, const CStdString& strNodeName);
@@ -64,6 +65,7 @@ namespace XFILE
       long m_idMVideo;
       long m_idAlbum;
       long m_idSet;
+      long m_idTag;
     };
   }
 }
index 2da538f..2fa67b9 100644 (file)
@@ -94,6 +94,11 @@ bool CGUIEditControl::OnMessage(CGUIMessage &message)
   {
     m_smsTimer.Stop();
   }
+  else if (message.GetMessage() == GUI_MSG_SET_TEXT)
+  {
+    SetLabel2(message.GetLabel());
+    UpdateText();
+  }
   return CGUIButtonControl::OnMessage(message);
 }
 
index ed40a75..28463e0 100644 (file)
  */
 #define GUI_MSG_UNFOCUS_ALL 41
 
+#define GUI_MSG_SET_TEXT        42
+
 #define GUI_MSG_USER         1000
 
 /*!
index 1aa4e16..0220748 100644 (file)
@@ -845,6 +845,15 @@ bool CButtonTranslator::TranslateJoystickString(int window, const char* szDevice
 }
 #endif
 
+void CButtonTranslator::GetActions(std::vector<std::string> &actionList)
+{
+  unsigned int size = sizeof(actions) / sizeof(ActionMapping);
+  actionList.clear();
+  actionList.reserve(size);
+  for (unsigned int index = 0; index < size; index++)
+    actionList.push_back(actions[index].name);
+}
+
 CAction CButtonTranslator::GetAction(int window, const CKey &key, bool fallback)
 {
   CStdString strAction;
index d48c543..a8ba512 100644 (file)
@@ -25,6 +25,7 @@
 #pragma once
 
 #include <map>
+#include <vector>
 #include "system.h" // for HAS_EVENT_SERVER, HAS_SDL_JOYSTICK, HAS_LIRC
 
 #ifdef HAS_EVENT_SERVER
@@ -69,6 +70,8 @@ public:
   /// clears the maps
   void Clear();
 
+  static void GetActions(std::vector<std::string> &actionList);
+
   CAction GetAction(int window, const CKey &key, bool fallback = true);
 
   /*! \brief Translate between a window name and it's id
index 9ad993c..d4c2772 100644 (file)
 
 using namespace std;
 
-CJoystick g_Joystick; // global
-
 CJoystick::CJoystick()
 {
-  Reset();
+  Reset(true);
+  m_joystickEnabled = false;
   m_NumAxes = 0;
   m_AxisId = 0;
   m_JoyId = 0;
@@ -44,13 +43,20 @@ CJoystick::CJoystick()
   m_HatId = 0;
   m_HatState = SDL_HAT_CENTERED;
   m_ActiveFlags = JACTIVE_NONE;
-  for (int i = 0 ; i<MAX_AXES ; i++)
-    m_Amount[i] = 0;
   SetDeadzone(0);
 }
 
 void CJoystick::Initialize()
 {
+  if (!IsEnabled())
+    return;
+
+  if(SDL_InitSubSystem(SDL_INIT_JOYSTICK) != 0)
+  {
+    CLog::Log(LOGERROR, "(Re)start joystick subsystem failed : %s",SDL_GetError());
+    return;
+  }
+
   // clear old joystick names
   m_JoystickNames.clear();
 
@@ -108,7 +114,7 @@ void CJoystick::Initialize()
   SDL_JoystickEventState(SDL_DISABLE);
 }
 
-void CJoystick::Reset(bool axis)
+void CJoystick::Reset(bool axis /*=false*/)
 {
   if (axis)
   {
@@ -122,6 +128,9 @@ void CJoystick::Reset(bool axis)
 
 void CJoystick::Update()
 {
+  if (!IsEnabled())
+    return;
+
   int buttonId    = -1;
   int axisId      = -1;
   int hatId       = -1;
@@ -236,6 +245,9 @@ void CJoystick::Update()
 
 void CJoystick::Update(SDL_Event& joyEvent)
 {
+  if (!IsEnabled())
+    return;
+
   int buttonId = -1;
   int axisId = -1;
   int joyId = -1;
@@ -303,8 +315,11 @@ void CJoystick::Update(SDL_Event& joyEvent)
 
 bool CJoystick::GetHat(int &id, int &position,bool consider_repeat) 
 {
-  if (!IsHatActive())
+  if (!IsEnabled() || !IsHatActive())
+  {
+    id = position = 0;
     return false;
+  }
   position = m_HatState;
   id = m_HatId;
   if (!consider_repeat)
@@ -336,8 +351,11 @@ bool CJoystick::GetHat(int &id, int &position,bool consider_repeat)
 
 bool CJoystick::GetButton(int &id, bool consider_repeat)
 {
-  if (!IsButtonActive())
+  if (!IsEnabled() || !IsButtonActive())
+  {
+    id = 0;
     return false;
+  }
   if (!consider_repeat)
   {
     id = m_ButtonId;
@@ -372,6 +390,17 @@ bool CJoystick::GetButton(int &id, bool consider_repeat)
   return true;
 }
 
+bool CJoystick::GetAxis (int &id)
+{ 
+  if (!IsEnabled() || !IsAxisActive()) 
+  {
+    id = 0;
+    return false; 
+  }
+  id = m_AxisId; 
+  return true; 
+}
+
 int CJoystick::GetAxisWithMaxAmount()
 {
   static int maxAmount;
@@ -401,6 +430,20 @@ float CJoystick::GetAmount(int axis)
   return 0;
 }
 
+void CJoystick::SetEnabled(bool enabled /*=true*/)
+{
+  if( enabled && !m_joystickEnabled )
+  {
+    m_joystickEnabled = true;
+    Initialize();
+  }
+  else if( !enabled && m_joystickEnabled )
+  {
+    ReleaseJoysticks();
+    m_joystickEnabled = false;
+  }
+}
+
 float CJoystick::SetDeadzone(float val)
 {
   if (val<0) val=0;
@@ -409,8 +452,16 @@ float CJoystick::SetDeadzone(float val)
   return val;
 }
 
-bool CJoystick::Reinitialize()
+bool CJoystick::ReleaseJoysticks()
 {
+  m_Joysticks.clear();
+  m_JoystickNames.clear();
+  m_HatId = 0;
+  m_ButtonId = 0;
+  m_HatState = SDL_HAT_CENTERED;
+  m_ActiveFlags = JACTIVE_NONE;
+  Reset(true);
+
   // Restart SDL joystick subsystem
   SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
   if (SDL_WasInit(SDL_INIT_JOYSTICK) !=  0)
@@ -418,12 +469,12 @@ bool CJoystick::Reinitialize()
     CLog::Log(LOGERROR, "Stop joystick subsystem failed");
     return false;
   }
-  if(SDL_InitSubSystem(SDL_INIT_JOYSTICK) != 0)
-  {
-    CLog::Log(LOGERROR, "Restart joystick subsystem failed : %s",SDL_GetError());
-    return false;
-  }
+  return true;
+}
 
+bool CJoystick::Reinitialize()
+{
+  if( !ReleaseJoysticks() ) return false;
   Initialize();
 
   return true;
index e7803d1..c110901 100644 (file)
@@ -57,12 +57,14 @@ public:
   void Update();
   void Update(SDL_Event& event);
   bool GetButton (int& id, bool consider_repeat=true);
-  bool GetAxis (int &id) { if (!IsAxisActive()) return false; id=m_AxisId; return true; }
+  bool GetAxis (int &id);
   bool GetHat (int &id, int &position, bool consider_repeat=true);
   std::string GetJoystick() { return (m_JoyId>-1)?m_JoystickNames[m_JoyId]:""; }
   int GetAxisWithMaxAmount();
   float GetAmount(int axis);
   float GetAmount() { return GetAmount(m_AxisId); }
+  bool IsEnabled() const { return m_joystickEnabled; }
+  void SetEnabled(bool enabled = true);
   float SetDeadzone(float val);
   bool Reinitialize();
 
@@ -74,6 +76,8 @@ private:
   bool IsAxisActive() { return (m_ActiveFlags & JACTIVE_AXIS) == JACTIVE_AXIS; }
   bool IsHatActive() { return (m_ActiveFlags & JACTIVE_HAT) == JACTIVE_HAT; }
 
+  bool ReleaseJoysticks();
+
   int m_Amount[MAX_AXES];
   int m_AxisId;
   int m_ButtonId;
@@ -82,6 +86,7 @@ private:
   int m_JoyId;
   int m_NumAxes;
   int m_DeadzoneRange;
+  bool m_joystickEnabled;
   uint32_t m_pressTicksButton;
   uint32_t m_pressTicksHat;
   uint8_t m_ActiveFlags;
index 2e05e7e..f7d821f 100644 (file)
@@ -31,8 +31,6 @@
 
 using namespace std;
 
-CJoystick g_Joystick; // global
-
 extern HWND g_hWnd;
 
 #define MAX_AXISAMOUNT  32768
@@ -53,7 +51,8 @@ extern HWND g_hWnd;
 
 CJoystick::CJoystick()
 {
-  Reset();
+  Reset(true);
+  m_joystickEnabled = false;
   m_NumAxes = 0;
   m_AxisId = 0;
   m_JoyId = 0;
@@ -61,8 +60,6 @@ CJoystick::CJoystick()
   m_HatId = 0;
   m_HatState = SDL_HAT_CENTERED;
   m_ActiveFlags = JACTIVE_NONE;
-  for (int i = 0 ; i<MAX_AXES ; i++)
-    m_Amount[i] = 0;
   SetDeadzone(0);
 
   m_pDI = NULL;
@@ -88,6 +85,13 @@ void CJoystick::ReleaseJoysticks()
   m_pJoysticks.clear();
   m_JoystickNames.clear();
   m_devCaps.clear();
+  m_HatId = 0;
+  m_ButtonId = 0;
+  m_HatState = SDL_HAT_CENTERED;
+  m_ActiveFlags = JACTIVE_NONE;
+  Reset(true);
+  m_lastPressTicks = 0;
+  m_lastTicks = 0;
   // Release any DirectInput objects.
   SAFE_RELEASE( m_pDI );
 }
@@ -172,6 +176,9 @@ BOOL CALLBACK CJoystick::EnumObjectsCallback( const DIDEVICEOBJECTINSTANCE* pdid
 
 void CJoystick::Initialize()
 {
+  if (!IsEnabled())
+    return;
+
   HRESULT hr;
 
   // clear old joystick names
@@ -208,7 +215,7 @@ void CJoystick::Initialize()
   SetDeadzone(g_advancedSettings.m_controllerDeadzone);
 }
 
-void CJoystick::Reset(bool axis)
+void CJoystick::Reset(bool axis /*=true*/)
 {
   if (axis)
   {
@@ -222,6 +229,9 @@ void CJoystick::Reset(bool axis)
 
 void CJoystick::Update()
 {
+  if (!IsEnabled())
+    return;
+
   int buttonId    = -1;
   int axisId      = -1;
   int hatId       = -1;
@@ -360,8 +370,11 @@ void CJoystick::Update()
 
 bool CJoystick::GetHat(int &id, int &position,bool consider_repeat)
 {
-  if (!IsHatActive())
+  if (!IsEnabled() || !IsHatActive())
+  {
+    id = position = 0;
     return false;
+  }
   position = m_HatState;
   id = m_HatId;
   if (!consider_repeat)
@@ -391,8 +404,11 @@ bool CJoystick::GetHat(int &id, int &position,bool consider_repeat)
 
 bool CJoystick::GetButton(int &id, bool consider_repeat)
 {
-  if (!IsButtonActive())
+  if (!IsEnabled() || !IsButtonActive())
+  {
+    id = 0;
     return false;
+  }
   if (!consider_repeat)
   {
     id = m_ButtonId;
@@ -425,6 +441,17 @@ bool CJoystick::GetButton(int &id, bool consider_repeat)
   return true;
 }
 
+bool CJoystick::GetAxis (int &id)
+{ 
+  if (!IsEnabled() || !IsAxisActive()) 
+  {
+    id = 0;
+    return false; 
+  }
+  id = m_AxisId; 
+  return true; 
+}
+
 int CJoystick::GetAxisWithMaxAmount()
 {
   int maxAmount = 0;
@@ -452,6 +479,20 @@ float CJoystick::GetAmount(int axis)
   return 0;
 }
 
+void CJoystick::SetEnabled(bool enabled /*=true*/)
+{
+  if( enabled && !m_joystickEnabled )
+  {
+    m_joystickEnabled = true;
+    Initialize();
+  }
+  else if( !enabled && m_joystickEnabled )
+  {
+    ReleaseJoysticks();
+    m_joystickEnabled = false;
+  }
+}
+
 float CJoystick::SetDeadzone(float val)
 {
   if (val<0) val=0;
@@ -468,6 +509,8 @@ bool CJoystick::Reinitialize()
 
 void CJoystick::Acquire()
 {
+  if (!IsEnabled())
+    return;
   if(!m_pJoysticks.empty())
   {
     CLog::Log(LOGDEBUG, __FUNCTION__": Focus back, acquire Joysticks");
index c06686f..9ee6a9e 100644 (file)
@@ -47,12 +47,14 @@ public:
   void ResetAxis(int axisId) { m_Amount[axisId] = 0; }
   void Update();
   bool GetButton (int& id, bool consider_repeat=true);
-  bool GetAxis (int &id) { if (!IsAxisActive()) return false; id=m_AxisId; return true; }
+  bool GetAxis (int &id);
   bool GetHat (int &id, int &position, bool consider_repeat=true);
   std::string GetJoystick() { return (m_JoyId>-1)?m_JoystickNames[m_JoyId]:""; }
   int GetAxisWithMaxAmount();
   float GetAmount(int axis);
   float GetAmount() { return GetAmount(m_AxisId); }
+  bool IsEnabled() const { return m_joystickEnabled; }
+  void SetEnabled(bool enabled = true);
   float SetDeadzone(float val);
   bool Reinitialize();
   void Acquire();
@@ -77,6 +79,7 @@ private:
   int m_JoyId;
   int m_NumAxes;
   int m_DeadzoneRange;
+  bool m_joystickEnabled;
   uint32_t m_pressTicksButton;
   uint32_t m_pressTicksHat;
   uint8_t m_ActiveFlags;
index 35360a6..64e76eb 100644 (file)
@@ -25,16 +25,17 @@ namespace ANNOUNCEMENT
 {
   enum AnnouncementFlag
   {
-    Player = 0x1,
-    GUI = 0x2,
-    System = 0x4,
-    VideoLibrary = 0x8,
-    AudioLibrary = 0x10,
-    Application = 0x20,
-    Other = 0x40
+    Player        = 0x01,
+    GUI           = 0x02,
+    System        = 0x04,
+    VideoLibrary  = 0x08,
+    AudioLibrary  = 0x10,
+    Application   = 0x20,
+    Input         = 0x40,
+    Other         = 0x80
   };
 
-  #define ANNOUNCE_ALL (Player | GUI | System | VideoLibrary | AudioLibrary | Application | Other)
+  #define ANNOUNCE_ALL (Player | GUI | System | VideoLibrary | AudioLibrary | Application | Input | Other)
 
   /*!
     \brief Returns a string representation for the 
@@ -58,6 +59,8 @@ namespace ANNOUNCEMENT
       return "AudioLibrary";
     case Application:
       return "Application";
+    case Input:
+      return "Input";
     case Other:
       return "Other";
     default:
index 541c679..1bf3a1c 100644 (file)
 #include "InputOperations.h"
 #include "Application.h"
 #include "guilib/GUIAudioManager.h"
+#include "guilib/GUIWindow.h"
+#include "guilib/GUIWindowManager.h"
+#include "input/ButtonTranslator.h"
+#include "input/XBMC_keyboard.h"
 #include "input/XBMC_vkeys.h"
 #include "threads/SingleLock.h"
+#include "utils/CharsetConverter.h"
 
 using namespace JSONRPC;
 
 CCriticalSection CInputOperations::m_critSection;
-uint32_t CInputOperations::m_key = KEY_INVALID;
+CKey CInputOperations::m_key(KEY_INVALID);
 
-uint32_t CInputOperations::GetKey()
+CKey CInputOperations::GetKey()
 {
   CSingleLock lock(m_critSection);
-  uint32_t currentKey = m_key;
-  m_key = KEY_INVALID;
+  CKey currentKey = m_key;
+  m_key = CKey(KEY_INVALID);
   return currentKey;
 }
 
@@ -55,13 +60,16 @@ bool CInputOperations::handleScreenSaver()
   return screenSaverBroken;
 }
 
-JSONRPC_STATUS CInputOperations::SendKey(uint32_t keyCode)
+JSONRPC_STATUS CInputOperations::SendKey(uint32_t keyCode, bool unicode /* = false */)
 {
   if (keyCode == KEY_INVALID)
     return InternalError;
 
   CSingleLock lock(m_critSection);
-  m_key = keyCode | KEY_VKEY;
+  if (unicode)
+    m_key = CKey(0, (wchar_t)keyCode, 0, 0, 0);
+  else
+    m_key = CKey(keyCode | KEY_VKEY);
   return ACK;
 }
 
@@ -84,6 +92,33 @@ JSONRPC_STATUS CInputOperations::activateWindow(int windowID)
   return ACK;
 }
 
+JSONRPC_STATUS CInputOperations::SendText(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
+{
+  std::string text = parameterObject["text"].asString();
+  if (text.empty())
+    return InvalidParams;
+
+  int controlID = 0;
+  CGUIWindow *window = g_windowManager.GetWindow(g_windowManager.GetFocusedWindow());
+  if (!window)
+    return InternalError;
+
+  CGUIMessage msg(GUI_MSG_SET_TEXT, 0, 0);
+  msg.SetLabel(text);
+  msg.SetParam1(parameterObject["done"].asBoolean() ? 1 : 0);
+  g_application.getApplicationMessenger().SendGUIMessage(msg, window->GetID());
+  return ACK;
+}
+
+JSONRPC_STATUS CInputOperations::ExecuteAction(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
+{
+  int action;
+  if (!CButtonTranslator::TranslateActionString(parameterObject["action"].asString().c_str(), action))
+    return InvalidParams;
+
+  return SendAction(action);
+}
+
 JSONRPC_STATUS CInputOperations::Left(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
 {
   return SendKey(XBMCVK_LEFT);
@@ -128,3 +163,13 @@ JSONRPC_STATUS CInputOperations::Home(const CStdString &method, ITransportLayer
 {
   return activateWindow(WINDOW_HOME);
 }
+
+JSONRPC_STATUS CInputOperations::ShowCodec(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
+{
+  return SendAction(ACTION_SHOW_CODEC);
+}
+
+JSONRPC_STATUS CInputOperations::ShowOSD(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
+{
+  return SendAction(ACTION_SHOW_OSD);
+}
index 2d82ed4..d744c8d 100644 (file)
@@ -21,6 +21,7 @@
  */
 
 #include "JSONRPC.h"
+#include "guilib/Key.h"
 #include "threads/CriticalSection.h"
 #include "utils/StdString.h"
 
@@ -29,7 +30,10 @@ namespace JSONRPC
   class CInputOperations
   {
   public:
-    static uint32_t GetKey();
+    static CKey GetKey();
+
+    static JSONRPC_STATUS SendText(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result);
+    static JSONRPC_STATUS ExecuteAction(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result);
 
     static JSONRPC_STATUS Left(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result);
     static JSONRPC_STATUS Right(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result);
@@ -42,7 +46,10 @@ namespace JSONRPC
     static JSONRPC_STATUS Info(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result);
     static JSONRPC_STATUS Home(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result);
 
-    static JSONRPC_STATUS SendKey(uint32_t keyCode);
+    static JSONRPC_STATUS ShowCodec(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result);
+    static JSONRPC_STATUS ShowOSD(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result);
+
+    static JSONRPC_STATUS SendKey(uint32_t keyCode, bool unicode = false);
     static JSONRPC_STATUS SendAction(int actionID, bool wakeScreensaver = true, bool waitResult = false);
 
   private:
@@ -50,6 +57,6 @@ namespace JSONRPC
     static bool        handleScreenSaver();
 
     static CCriticalSection m_critSection;
-    static uint32_t m_key;
+    static CKey m_key;
   };
 }
index f437952..31278b3 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "JSONRPC.h"
 #include "ServiceDescription.h"
+#include "input/ButtonTranslator.h"
 #include "interfaces/AnnouncementManager.h"
 #include "settings/AdvancedSettings.h"
 #include "utils/log.h"
@@ -39,6 +40,11 @@ void CJSONRPC::Initialize()
   if (m_initialized)
     return;
 
+  // Add some types/enums at runtime
+  vector<string> inputActions;
+  CButtonTranslator::GetActions(inputActions);
+  CJSONServiceDescription::AddEnum("Input.Action", inputActions);
+
   unsigned int size = sizeof(JSONRPC_SERVICE_TYPES) / sizeof(char*);
 
   for (unsigned int index = 0; index < size; index++)
index faf133c..7c2cff4 100644 (file)
@@ -162,6 +162,8 @@ JsonRpcMethodMap CJSONServiceDescription::m_methodMaps[] = {
   { "System.Reboot",                                CSystemOperations::Reboot },
 
 // Input operations
+  { "Input.SendText",                               CInputOperations::SendText },
+  { "Input.ExecuteAction",                          CInputOperations::ExecuteAction },
   { "Input.Left",                                   CInputOperations::Left },
   { "Input.Right",                                  CInputOperations::Right },
   { "Input.Down",                                   CInputOperations::Down },
@@ -171,6 +173,8 @@ JsonRpcMethodMap CJSONServiceDescription::m_methodMaps[] = {
   { "Input.ContextMenu",                            CInputOperations::ContextMenu },
   { "Input.Info",                                   CInputOperations::Info },
   { "Input.Home",                                   CInputOperations::Home },
+  { "Input.ShowCodec",                              CInputOperations::ShowCodec },
+  { "Input.ShowOSD",                                CInputOperations::ShowOSD },
 
 // Application operations
   { "Application.GetProperties",                    CApplicationOperations::GetProperties },
index 5c722a4..35d2b8d 100644 (file)
@@ -2,13 +2,13 @@ SRCS=ApplicationOperations.cpp \
      AudioLibrary.cpp \
      FileItemHandler.cpp \
      FileOperations.cpp \
-                GUIOperations.cpp \
+     GUIOperations.cpp \
+     InputOperations.cpp \
      JSONRPC.cpp \
      JSONServiceDescription.cpp \
      PlayerOperations.cpp \
      PlaylistOperations.cpp \
      SystemOperations.cpp \
-     InputOperations.cpp \
      VideoLibrary.cpp \
      XBMCOperations.cpp \
 
index e9df4a9..adf6a0a 100644 (file)
@@ -2328,6 +2328,27 @@ namespace JSONRPC
       "\"params\": [],"
       "\"returns\": \"string\""
     "}",
+    "\"Input.SendText\": {"
+      "\"type\": \"method\","
+      "\"description\": \"Send a generic (unicode) text\","
+      "\"transport\": \"Response\","
+      "\"permission\": \"Navigate\","
+      "\"params\": ["
+        "{ \"name\": \"text\", \"type\": \"string\", \"minLength\": 1, \"required\": true, \"description\": \"Unicode text\" },"
+        "{ \"name\": \"done\", \"type\": \"boolean\", \"default\": true, \"description\": \"Whether this is the whole input or not (closes an open input dialog if true).\" }"
+      "],"
+      "\"returns\": \"string\""
+    "}",
+    "\"Input.ExecuteAction\": {"
+      "\"type\": \"method\","
+      "\"description\": \"Execute a specific action\","
+      "\"transport\": \"Response\","
+      "\"permission\": \"Navigate\","
+      "\"params\": ["
+        "{ \"name\": \"action\", \"$ref\": \"Input.Action\", \"required\": true }"
+      "],"
+      "\"returns\": \"string\""
+    "}",
     "\"Input.Left\": {"
       "\"type\": \"method\","
       "\"description\": \"Navigate left in GUI\","
@@ -2400,6 +2421,22 @@ namespace JSONRPC
       "\"params\": [],"
       "\"returns\": \"string\""
     "}",
+    "\"Input.ShowCodec\": {"
+      "\"type\": \"method\","
+      "\"description\": \"Show codec information of the playing item\","
+      "\"transport\": \"Response\","
+      "\"permission\": \"Navigate\","
+      "\"params\": [],"
+      "\"returns\": \"string\""
+    "}",
+    "\"Input.ShowOSD\": {"
+      "\"type\": \"method\","
+      "\"description\": \"Show the on-screen display for the current player\","
+      "\"transport\": \"Response\","
+      "\"permission\": \"Navigate\","
+      "\"params\": [],"
+      "\"returns\": \"string\""
+    "}",
     "\"Application.GetProperties\": {"
       "\"type\": \"method\","
       "\"description\": \"Retrieves the values of the given properties\","
@@ -2660,6 +2697,29 @@ namespace JSONRPC
         "}"
       "],"
       "\"returns\": null"
+    "}",
+    "\"Input.OnInputRequested\": {"
+      "\"type\": \"notification\","
+      "\"description\": \"The user is requested to provide some information.\","
+      "\"params\": ["
+        "{ \"name\": \"sender\", \"type\": \"string\", \"required\": true },"
+        "{ \"name\": \"data\", \"type\": \"object\", \"required\": true,"
+          "\"properties\": {"
+            "\"type\": { \"type\": \"string\", \"enum\": [ \"keyboard\", \"time\", \"date\", \"ip\", \"password\", \"number\", \"seconds\" ], \"required\": true },"
+            "\"title\": { \"type\": \"string\" }"
+          "}"
+        "}"
+      "],"
+      "\"returns\": null"
+    "}",
+    "\"Input.OnInputFinished\": {"
+      "\"type\": \"notification\","
+      "\"description\": \"The user has provided the requested input.\","
+      "\"params\": ["
+        "{ \"name\": \"sender\", \"type\": \"string\", \"required\": true },"
+        "{ \"name\": \"data\", \"type\": \"null\", \"required\": true }"
+      "],"
+      "\"returns\": null"
     "}"
   };
 }
index 1340d84..877a998 100644 (file)
     "params": [],
     "returns": "string"
   },
+  "Input.SendText": {
+    "type": "method",
+    "description": "Send a generic (unicode) text",
+    "transport": "Response",
+    "permission": "Navigate",
+    "params": [
+      { "name": "text", "type": "string", "minLength": 1, "required": true, "description": "Unicode text" },
+      { "name": "done", "type": "boolean", "default": true, "description": "Whether this is the whole input or not (closes an open input dialog if true)." }
+    ],
+    "returns": "string"
+  },
+  "Input.ExecuteAction": {
+    "type": "method",
+    "description": "Execute a specific action",
+    "transport": "Response",
+    "permission": "Navigate",
+    "params": [
+      { "name": "action", "$ref": "Input.Action", "required": true }
+    ],
+    "returns": "string"
+  },
   "Input.Left": {
     "type": "method",
     "description": "Navigate left in GUI",
     "params": [],
     "returns": "string"
   },
+  "Input.ShowCodec": {
+    "type": "method",
+    "description": "Show codec information of the playing item",
+    "transport": "Response",
+    "permission": "Navigate",
+    "params": [],
+    "returns": "string"
+  },
+  "Input.ShowOSD": {
+    "type": "method",
+    "description": "Show the on-screen display for the current player",
+    "transport": "Response",
+    "permission": "Navigate",
+    "params": [],
+    "returns": "string"
+  },
   "Application.GetProperties": {
     "type": "method",
     "description": "Retrieves the values of the given properties",
index f4bf792..3721229 100644 (file)
       }
     ],
     "returns": null
+  },
+  "Input.OnInputRequested": {
+    "type": "notification",
+    "description": "The user is requested to provide some information.",
+    "params": [
+      { "name": "sender", "type": "string", "required": true },
+      { "name": "data", "type": "object", "required": true,
+        "properties": {
+          "type": { "type": "string", "enum": [ "keyboard", "time", "date", "ip", "password", "number", "seconds" ], "required": true },
+          "title": { "type": "string" }
+        }
+      }
+    ],
+    "returns": null
+  },
+  "Input.OnInputFinished": {
+    "type": "notification",
+    "description": "The user has provided the requested input.",
+    "params": [
+      { "name": "sender", "type": "string", "required": true },
+      { "name": "data", "type": "null", "required": true }
+    ],
+    "returns": null
   }
 }
\ No newline at end of file
index ebaa3ec..ad1a87b 100644 (file)
@@ -431,7 +431,8 @@ void XBPyThread::stop()
     PyThreadState* old = PyThreadState_Swap((PyThreadState*)m_threadState);
 
     //tell xbmc.Monitor to call onAbortRequested()
-    g_pythonParser.OnAbortRequested(addon->ID());
+    if (addon)
+      g_pythonParser.OnAbortRequested(addon->ID());
 
     PyObject *m;
     m = PyImport_AddModule((char*)"xbmc");
index dbd5e01..c646aa9 100644 (file)
@@ -3182,357 +3182,342 @@ bool CMusicDatabase::GetSongsNav(const CStdString& strBaseDir, CFileItemList& it
 
 bool CMusicDatabase::UpdateOldVersion(int version)
 {
-  if (NULL == m_pDB.get()) return false;
-  if (NULL == m_pDS.get()) return false;
-  if (NULL == m_pDS2.get()) return false;
-
-  BeginTransaction();
-
-  try
-  {
-    if (version < 16)
-    {
-      // only if MySQL is used and default character set is not utf8
-      // string data needs to be converted to proper utf8
-      CStdString charset = m_pDS->getDatabase()->getDefaultCharset();
-      if (!m_sqlite && !charset.empty() && charset != "utf8")
+  if (version < 16)
+  {
+    // only if MySQL is used and default character set is not utf8
+    // string data needs to be converted to proper utf8
+    CStdString charset = m_pDS->getDatabase()->getDefaultCharset();
+    if (!m_sqlite && !charset.empty() && charset != "utf8")
+    {
+      map<CStdString, CStdStringArray> tables;
+      map<CStdString, CStdStringArray>::iterator itt;
+      CStdStringArray::iterator itc;
+
+      //columns that need to be converted
+      CStdStringArray c1;
+      c1.push_back("strAlbum");
+      c1.push_back("strExtraArtists");
+      c1.push_back("strExtraGenres");
+      tables.insert(pair<CStdString, CStdStringArray> ("album", c1));
+
+      CStdStringArray c2;
+      c2.push_back("strExtraGenres");
+      c2.push_back("strMoods");
+      c2.push_back("strStyles");
+      c2.push_back("strThemes");
+      c2.push_back("strReview");
+      c2.push_back("strLabel");
+      tables.insert(pair<CStdString, CStdStringArray> ("albuminfo", c2));
+
+      CStdStringArray c3;
+      c3.push_back("strTitle");
+      tables.insert(pair<CStdString, CStdStringArray> ("albuminfosong", c3));
+
+      CStdStringArray c4;
+      c4.push_back("strArtist");
+      tables.insert(pair<CStdString, CStdStringArray> ("artist", c4));
+
+      CStdStringArray c5;
+      c5.push_back("strBorn");
+      c5.push_back("strFormed");
+      c5.push_back("strGenres");
+      c5.push_back("strMoods");
+      c5.push_back("strStyles");
+      c5.push_back("strInstruments");
+      c5.push_back("strBiography");
+      c5.push_back("strDied");
+      c5.push_back("strDisbanded");
+      c5.push_back("strYearsActive");
+      tables.insert(pair<CStdString, CStdStringArray> ("artistinfo", c5));
+
+      CStdStringArray c6;
+      c6.push_back("strAlbum");
+      tables.insert(pair<CStdString, CStdStringArray> ("discography", c6));
+
+      CStdStringArray c7;
+      c7.push_back("strGenre");
+      tables.insert(pair<CStdString, CStdStringArray> ("genre", c7));
+
+      CStdStringArray c8;
+      c8.push_back("strKaraLyrics");
+      tables.insert(pair<CStdString, CStdStringArray> ("karaokedata", c8));
+
+      CStdStringArray c9;
+      c9.push_back("strTitle");
+      c9.push_back("strFilename");
+      c9.push_back("comment");
+      tables.insert(pair<CStdString, CStdStringArray> ("song", c9));
+
+      CStdStringArray c10;
+      c10.push_back("strPath");
+      tables.insert(pair<CStdString, CStdStringArray> ("path", c10));
+
+      for (itt = tables.begin(); itt != tables.end(); ++itt)
       {
-        map<CStdString, CStdStringArray> tables;
-        map<CStdString, CStdStringArray>::iterator itt;
-        CStdStringArray::iterator itc;
-
-        //columns that need to be converted
-        CStdStringArray c1;
-        c1.push_back("strAlbum");
-        c1.push_back("strExtraArtists");
-        c1.push_back("strExtraGenres");
-        tables.insert(pair<CStdString, CStdStringArray> ("album", c1));
-
-        CStdStringArray c2;
-        c2.push_back("strExtraGenres");
-        c2.push_back("strMoods");
-        c2.push_back("strStyles");
-        c2.push_back("strThemes");
-        c2.push_back("strReview");
-        c2.push_back("strLabel");
-        tables.insert(pair<CStdString, CStdStringArray> ("albuminfo", c2));
-
-        CStdStringArray c3;
-        c3.push_back("strTitle");
-        tables.insert(pair<CStdString, CStdStringArray> ("albuminfosong", c3));
-
-        CStdStringArray c4;
-        c4.push_back("strArtist");
-        tables.insert(pair<CStdString, CStdStringArray> ("artist", c4));
-
-        CStdStringArray c5;
-        c5.push_back("strBorn");
-        c5.push_back("strFormed");
-        c5.push_back("strGenres");
-        c5.push_back("strMoods");
-        c5.push_back("strStyles");
-        c5.push_back("strInstruments");
-        c5.push_back("strBiography");
-        c5.push_back("strDied");
-        c5.push_back("strDisbanded");
-        c5.push_back("strYearsActive");
-        tables.insert(pair<CStdString, CStdStringArray> ("artistinfo", c5));
-
-        CStdStringArray c6;
-        c6.push_back("strAlbum");
-        tables.insert(pair<CStdString, CStdStringArray> ("discography", c6));
-
-        CStdStringArray c7;
-        c7.push_back("strGenre");
-        tables.insert(pair<CStdString, CStdStringArray> ("genre", c7));
-
-        CStdStringArray c8;
-        c8.push_back("strKaraLyrics");
-        tables.insert(pair<CStdString, CStdStringArray> ("karaokedata", c8));
-
-        CStdStringArray c9;
-        c9.push_back("strTitle");
-        c9.push_back("strFilename");
-        c9.push_back("comment");
-        tables.insert(pair<CStdString, CStdStringArray> ("song", c9));
-
-        CStdStringArray c10;
-        c10.push_back("strPath");
-        tables.insert(pair<CStdString, CStdStringArray> ("path", c10));
-
-        for (itt = tables.begin(); itt != tables.end(); ++itt)
+        CStdString q;
+        q = PrepareSQL("UPDATE `%s` SET", itt->first.c_str());
+        for (itc = itt->second.begin(); itc != itt->second.end(); ++itc)
         {
-          CStdString q;
-          q = PrepareSQL("UPDATE `%s` SET", itt->first.c_str());
-          for (itc = itt->second.begin(); itc != itt->second.end(); ++itc)
+          q += PrepareSQL(" `%s` = CONVERT(CAST(CONVERT(`%s` USING %s) AS BINARY) USING utf8)",
+                          itc->c_str(), itc->c_str(), charset.c_str());
+          if (*itc != itt->second.back())
           {
-            q += PrepareSQL(" `%s` = CONVERT(CAST(CONVERT(`%s` USING %s) AS BINARY) USING utf8)",
-                            itc->c_str(), itc->c_str(), charset.c_str());
-            if (*itc != itt->second.back())
-            {
-              q += ", ";
-            }
+            q += ", ";
           }
-          m_pDS->exec(q);
         }
+        m_pDS->exec(q);
       }
     }
-    if (version < 17)
+  }
+  if (version < 17)
+  {
+    m_pDS->exec("CREATE INDEX idxAlbum2 ON album(idArtist)");
+    m_pDS->exec("CREATE INDEX idxSong3 ON song(idAlbum)");
+    m_pDS->exec("CREATE INDEX idxSong4 ON song(idArtist)");
+    m_pDS->exec("CREATE INDEX idxSong5 ON song(idGenre)");
+    m_pDS->exec("CREATE INDEX idxSong6 ON song(idPath)");
+  }
+  if (version < 19)
+  {
+    int len = g_advancedSettings.m_musicItemSeparator.size() + 1;
+    CStdString sql = PrepareSQL("UPDATE song SET strExtraArtists=SUBSTR(strExtraArtists,%i), strExtraGenres=SUBSTR(strExtraGenres,%i)", len, len);
+    m_pDS->exec(sql.c_str());
+    sql = PrepareSQL("UPDATE album SET strExtraArtists=SUBSTR(strExtraArtists,%i), strExtraGenres=SUBSTR(strExtraGenres,%i)", len, len);
+    m_pDS->exec(sql.c_str());
+  }
+
+  if (version < 21)
+  {
+    m_pDS->exec("CREATE TABLE album_artist ( idArtist integer, idAlbum integer, boolFeatured integer, iOrder integer )\n");
+    m_pDS->exec("CREATE UNIQUE INDEX idxAlbumArtist_1 ON album_artist ( idAlbum, idArtist )\n");
+    m_pDS->exec("CREATE UNIQUE INDEX idxAlbumArtist_2 ON album_artist ( idArtist, idAlbum )\n");
+    m_pDS->exec("CREATE INDEX idxAlbumArtist_3 ON album_artist ( boolFeatured )\n");
+    m_pDS->exec("INSERT INTO album_artist (idArtist, idAlbum, boolFeatured, iOrder) SELECT idArtist, idAlbum, 1, iPosition FROM exartistalbum");
+    m_pDS->exec("REPLACE INTO album_artist (idArtist, idAlbum, boolFeatured, iOrder) SELECT idArtist, idAlbum, 0, 0 FROM album");
+
+    CStdString strSQL;
+    strSQL=PrepareSQL("SELECT album.idAlbum AS idAlbum, strExtraArtists,"
+                      "  album.idArtist AS idArtist, strArtist FROM album "
+                      "  LEFT OUTER JOIN artist ON album.idArtist=artist.idArtist");
+    if (!m_pDS->query(strSQL.c_str()))
     {
-      m_pDS->exec("CREATE INDEX idxAlbum2 ON album(idArtist)");
-      m_pDS->exec("CREATE INDEX idxSong3 ON song(idAlbum)");
-      m_pDS->exec("CREATE INDEX idxSong4 ON song(idArtist)");
-      m_pDS->exec("CREATE INDEX idxSong5 ON song(idGenre)");
-      m_pDS->exec("CREATE INDEX idxSong6 ON song(idPath)");
+      CLog::Log(LOGDEBUG, "%s could not upgrade albums table", __FUNCTION__);
+      return false;
     }
-    if (version < 19)
+
+    VECALBUMS albums;
+    while (!m_pDS->eof())
     {
-      int len = g_advancedSettings.m_musicItemSeparator.size() + 1;
-      CStdString sql = PrepareSQL("UPDATE song SET strExtraArtists=SUBSTR(strExtraArtists,%i), strExtraGenres=SUBSTR(strExtraGenres,%i)", len, len);
-      m_pDS->exec(sql.c_str());
-      sql = PrepareSQL("UPDATE album SET strExtraArtists=SUBSTR(strExtraArtists,%i), strExtraGenres=SUBSTR(strExtraGenres,%i)", len, len);
-      m_pDS->exec(sql.c_str());
+      CAlbum album;
+      album.idAlbum = m_pDS->fv("idAlbum").get_asInt();
+      album.artist.push_back(m_pDS->fv("strArtist").get_asString());
+      if (!m_pDS->fv("strExtraArtists").get_asString().empty())
+      {
+        std::vector<std::string> extraArtists = StringUtils::Split(m_pDS->fv("strExtraArtists").get_asString(), g_advancedSettings.m_musicItemSeparator);
+        album.artist.insert(album.artist.end(), extraArtists.begin(), extraArtists.end());
+      }
+      albums.push_back(album);
+      m_pDS->next();
     }
+    m_pDS->close();
+    m_pDS->exec("CREATE TABLE album_new ( idAlbum integer primary key, strAlbum varchar(256), strArtists text, idGenre integer, strExtraGenres text, iYear integer, idThumb integer)");
+    m_pDS->exec("INSERT INTO album_new ( idAlbum, strAlbum, idGenre, strExtraGenres, iYear, idThumb ) SELECT idAlbum, strAlbum, idGenre, strExtraGenres, iYear, idThumb FROM album");
 
-    if (version < 21)
+    for (VECALBUMS::iterator it = albums.begin(); it != albums.end(); ++it)
     {
-      m_pDS->exec("CREATE TABLE album_artist ( idArtist integer, idAlbum integer, boolFeatured integer, iOrder integer )\n");
-      m_pDS->exec("CREATE UNIQUE INDEX idxAlbumArtist_1 ON album_artist ( idAlbum, idArtist )\n");
-      m_pDS->exec("CREATE UNIQUE INDEX idxAlbumArtist_2 ON album_artist ( idArtist, idAlbum )\n");
-      m_pDS->exec("CREATE INDEX idxAlbumArtist_3 ON album_artist ( boolFeatured )\n");
-      m_pDS->exec("INSERT INTO album_artist (idArtist, idAlbum, boolFeatured, iOrder) SELECT idArtist, idAlbum, 1, iPosition FROM exartistalbum");
-      m_pDS->exec("REPLACE INTO album_artist (idArtist, idAlbum, boolFeatured, iOrder) SELECT idArtist, idAlbum, 0, 0 FROM album");
-
       CStdString strSQL;
-      strSQL=PrepareSQL("SELECT album.idAlbum AS idAlbum, strExtraArtists,"
-                        "  album.idArtist AS idArtist, strArtist FROM album "
-                        "  LEFT OUTER JOIN artist ON album.idArtist=artist.idArtist");
-      if (!m_pDS->query(strSQL.c_str()))
-      {
-        CLog::Log(LOGDEBUG, "%s could not upgrade albums table", __FUNCTION__);
-        return false;
-      }
+      strSQL = PrepareSQL("UPDATE album_new SET strArtists='%s' WHERE idAlbum=%i", StringUtils::Join(it->artist, g_advancedSettings.m_musicItemSeparator).c_str(), it->idAlbum);
+      m_pDS->exec(strSQL);
+    }
 
-      VECALBUMS albums;
-      while (!m_pDS->eof())
-      {
-        CAlbum album;
-        album.idAlbum = m_pDS->fv("idAlbum").get_asInt();
-        album.artist.push_back(m_pDS->fv("strArtist").get_asString());
-        if (!m_pDS->fv("strExtraArtists").get_asString().empty())
-        {
-          std::vector<std::string> extraArtists = StringUtils::Split(m_pDS->fv("strExtraArtists").get_asString(), g_advancedSettings.m_musicItemSeparator);
-          album.artist.insert(album.artist.end(), extraArtists.begin(), extraArtists.end());
-        }
-        albums.push_back(album);
-        m_pDS->next();
-      }
-      m_pDS->close();
-      m_pDS->exec("CREATE TABLE album_new ( idAlbum integer primary key, strAlbum varchar(256), strArtists text, idGenre integer, strExtraGenres text, iYear integer, idThumb integer)");
-      m_pDS->exec("INSERT INTO album_new ( idAlbum, strAlbum, idGenre, strExtraGenres, iYear, idThumb ) SELECT idAlbum, strAlbum, idGenre, strExtraGenres, iYear, idThumb FROM album");
+    m_pDS->exec("DROP TABLE album");
+    m_pDS->exec("ALTER TABLE album_new RENAME TO album");
+    m_pDS->exec("CREATE INDEX idxAlbum ON album(strAlbum)");
+    m_pDS->exec("DROP TABLE IF EXISTS exartistalbum");
+  }
 
-      for (VECALBUMS::iterator it = albums.begin(); it != albums.end(); ++it)
-      {
-        CStdString strSQL;
-        strSQL = PrepareSQL("UPDATE album_new SET strArtists='%s' WHERE idAlbum=%i", StringUtils::Join(it->artist, g_advancedSettings.m_musicItemSeparator).c_str(), it->idAlbum);
-        m_pDS->exec(strSQL);
-      }
+  if (version < 22)
+  {
+    m_pDS->exec("CREATE TABLE song_artist ( idArtist integer, idSong integer, boolFeatured integer, iOrder integer )\n");
+    m_pDS->exec("CREATE UNIQUE INDEX idxSongArtist_1 ON song_artist ( idSong, idArtist )\n");
+    m_pDS->exec("CREATE UNIQUE INDEX idxSongArtist_2 ON song_artist ( idArtist, idSong )\n");
+    m_pDS->exec("CREATE INDEX idxSongArtist_3 ON song_artist ( boolFeatured )\n");
+    m_pDS->exec("INSERT INTO song_artist (idArtist, idSong, boolFeatured, iOrder) SELECT idArtist, idSong, 1, iPosition FROM exartistsong");
+    m_pDS->exec("REPLACE INTO song_artist (idArtist, idSong, boolFeatured, iOrder) SELECT idArtist, idSong, 0, 0 FROM song");
 
-      m_pDS->exec("DROP TABLE album");
-      m_pDS->exec("ALTER TABLE album_new RENAME TO album");
-      m_pDS->exec("CREATE INDEX idxAlbum ON album(strAlbum)");
-      m_pDS->exec("DROP TABLE IF EXISTS exartistalbum");
+    CStdString strSQL;
+    strSQL=PrepareSQL("SELECT song.idSong AS idSong, strExtraArtists,"
+                      "  song.idArtist AS idArtist, strArtist FROM song "
+                      "  LEFT OUTER JOIN artist ON song.idArtist=artist.idArtist");
+    if (!m_pDS->query(strSQL.c_str()))
+    {
+      CLog::Log(LOGDEBUG, "%s could not upgrade songs table", __FUNCTION__);
+      return false;
     }
 
-    if (version < 22)
+    VECSONGS songs;
+    while (!m_pDS->eof())
     {
-      m_pDS->exec("CREATE TABLE song_artist ( idArtist integer, idSong integer, boolFeatured integer, iOrder integer )\n");
-      m_pDS->exec("CREATE UNIQUE INDEX idxSongArtist_1 ON song_artist ( idSong, idArtist )\n");
-      m_pDS->exec("CREATE UNIQUE INDEX idxSongArtist_2 ON song_artist ( idArtist, idSong )\n");
-      m_pDS->exec("CREATE INDEX idxSongArtist_3 ON song_artist ( boolFeatured )\n");
-      m_pDS->exec("INSERT INTO song_artist (idArtist, idSong, boolFeatured, iOrder) SELECT idArtist, idSong, 1, iPosition FROM exartistsong");
-      m_pDS->exec("REPLACE INTO song_artist (idArtist, idSong, boolFeatured, iOrder) SELECT idArtist, idSong, 0, 0 FROM song");
-
-      CStdString strSQL;
-      strSQL=PrepareSQL("SELECT song.idSong AS idSong, strExtraArtists,"
-                        "  song.idArtist AS idArtist, strArtist FROM song "
-                        "  LEFT OUTER JOIN artist ON song.idArtist=artist.idArtist");
-      if (!m_pDS->query(strSQL.c_str()))
-      {
-        CLog::Log(LOGDEBUG, "%s could not upgrade songs table", __FUNCTION__);
-        return false;
-      }
-
-      VECSONGS songs;
-      while (!m_pDS->eof())
-      {
-        CSong song;
-        song.idSong = m_pDS->fv("idSong").get_asInt();
-        song.artist.push_back(m_pDS->fv("strArtist").get_asString());
-        if (!m_pDS->fv("strExtraArtists").get_asString().empty())
-        {
-          std::vector<std::string> extraArtists = StringUtils::Split(m_pDS->fv("strExtraArtists").get_asString(), g_advancedSettings.m_musicItemSeparator);
-          song.artist.insert(song.artist.end(), extraArtists.begin(), extraArtists.end());
-        }
-        songs.push_back(song);
-        m_pDS->next();
-      }
-      m_pDS->close();
-      m_pDS->exec("CREATE TABLE song_new ( idSong integer primary key, idAlbum integer, idPath integer, strArtists text, idGenre integer, strExtraGenres 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)");
-      m_pDS->exec("INSERT INTO song_new ( idSong, idAlbum, idPath, idGenre, strExtraGenres, strTitle, iTrack, iDuration, iYear, dwFileNameCRC, strFileName, strMusicBrainzTrackID, strMusicBrainzArtistID, strMusicBrainzAlbumID, strMusicBrainzAlbumArtistID, strMusicBrainzTRMID, iTimesPlayed, iStartOffset, iEndOffset, idThumb, lastplayed, rating, comment ) SELECT idSong, idAlbum, idPath, idGenre, strExtraGenres, strTitle, iTrack, iDuration, iYear, dwFileNameCRC, strFileName, strMusicBrainzTrackID, strMusicBrainzArtistID, strMusicBrainzAlbumID, strMusicBrainzAlbumArtistID, strMusicBrainzTRMID, iTimesPlayed, iStartOffset, iEndOffset, idThumb, lastplayed, rating, comment FROM song");
-
-      for (VECSONGS::iterator it = songs.begin(); it != songs.end(); ++it)
+      CSong song;
+      song.idSong = m_pDS->fv("idSong").get_asInt();
+      song.artist.push_back(m_pDS->fv("strArtist").get_asString());
+      if (!m_pDS->fv("strExtraArtists").get_asString().empty())
       {
-        CStdString strSQL;
-        strSQL = PrepareSQL("UPDATE song_new SET strArtists='%s' WHERE idSong=%i", StringUtils::Join(it->artist, g_advancedSettings.m_musicItemSeparator).c_str(), it->idSong);
-        m_pDS->exec(strSQL);
+        std::vector<std::string> extraArtists = StringUtils::Split(m_pDS->fv("strExtraArtists").get_asString(), g_advancedSettings.m_musicItemSeparator);
+        song.artist.insert(song.artist.end(), extraArtists.begin(), extraArtists.end());
       }
-
-      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("DROP TABLE IF EXISTS exartistsong");
+      songs.push_back(song);
+      m_pDS->next();
     }
+    m_pDS->close();
+    m_pDS->exec("CREATE TABLE song_new ( idSong integer primary key, idAlbum integer, idPath integer, strArtists text, idGenre integer, strExtraGenres 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)");
+    m_pDS->exec("INSERT INTO song_new ( idSong, idAlbum, idPath, idGenre, strExtraGenres, strTitle, iTrack, iDuration, iYear, dwFileNameCRC, strFileName, strMusicBrainzTrackID, strMusicBrainzArtistID, strMusicBrainzAlbumID, strMusicBrainzAlbumArtistID, strMusicBrainzTRMID, iTimesPlayed, iStartOffset, iEndOffset, idThumb, lastplayed, rating, comment ) SELECT idSong, idAlbum, idPath, idGenre, strExtraGenres, strTitle, iTrack, iDuration, iYear, dwFileNameCRC, strFileName, strMusicBrainzTrackID, strMusicBrainzArtistID, strMusicBrainzAlbumID, strMusicBrainzAlbumArtistID, strMusicBrainzTRMID, iTimesPlayed, iStartOffset, iEndOffset, idThumb, lastplayed, rating, comment FROM song");
 
-    if (version < 23)
+    for (VECSONGS::iterator it = songs.begin(); it != songs.end(); ++it)
     {
-      m_pDS->exec("CREATE TABLE album_genre ( idGenre integer, idAlbum integer, iOrder integer )\n");
-      m_pDS->exec("CREATE UNIQUE INDEX idxAlbumGenre_1 ON album_genre ( idAlbum, idGenre )\n");
-      m_pDS->exec("CREATE UNIQUE INDEX idxAlbumGenre_2 ON album_genre ( idGenre, idAlbum )\n");
-      m_pDS->exec("INSERT INTO album_genre ( idGenre, idAlbum, iOrder) SELECT idGenre, idAlbum, iPosition FROM exgenrealbum");
-      m_pDS->exec("REPLACE INTO album_genre ( idGenre, idAlbum, iOrder) SELECT idGenre, idAlbum, 0 FROM album");
-
       CStdString strSQL;
-      strSQL=PrepareSQL("SELECT album.idAlbum AS idAlbum, strExtraGenres,"
-                        "  album.idGenre AS idGenre, strGenre FROM album "
-                        "  JOIN genre ON album.idGenre=genre.idGenre");
-      if (!m_pDS->query(strSQL.c_str()))
-      {
-        CLog::Log(LOGDEBUG, "%s could not upgrade albums table", __FUNCTION__);
-        return false;
-      }
+      strSQL = PrepareSQL("UPDATE song_new SET strArtists='%s' WHERE idSong=%i", StringUtils::Join(it->artist, g_advancedSettings.m_musicItemSeparator).c_str(), it->idSong);
+      m_pDS->exec(strSQL);
+    }
 
-      VECALBUMS albums;
-      while (!m_pDS->eof())
-      {
-        CAlbum album;
-        album.idAlbum = m_pDS->fv("idAlbum").get_asInt();
-        album.genre.push_back(m_pDS->fv("strGenre").get_asString());
-        if (!m_pDS->fv("strExtraGenres").get_asString().empty())
-        {
-          std::vector<std::string> extraGenres = StringUtils::Split(m_pDS->fv("strExtraGenres").get_asString(), g_advancedSettings.m_musicItemSeparator);
-          album.genre.insert(album.genre.end(), extraGenres.begin(), extraGenres.end());
-        }
-        albums.push_back(album);
-        m_pDS->next();
-      }
-      m_pDS->close();
-      m_pDS->exec("CREATE TABLE album_new ( idAlbum integer primary key, strAlbum varchar(256), strArtists text, strGenres text, iYear integer, idThumb integer)");
-      m_pDS->exec("INSERT INTO album_new ( idAlbum, strAlbum, strArtists, iYear, idThumb) SELECT idAlbum, strAlbum, strArtists, iYear, idThumb FROM album");
+    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("DROP TABLE IF EXISTS exartistsong");
+  }
 
-      for (VECALBUMS::iterator it = albums.begin(); it != albums.end(); ++it)
-      {
-        CStdString strSQL;
-        strSQL = PrepareSQL("UPDATE album_new SET strGenres='%s' WHERE idAlbum=%i", StringUtils::Join(it->genre, g_advancedSettings.m_musicItemSeparator).c_str(), it->idAlbum);
-        m_pDS->exec(strSQL);
-      }
+  if (version < 23)
+  {
+    m_pDS->exec("CREATE TABLE album_genre ( idGenre integer, idAlbum integer, iOrder integer )\n");
+    m_pDS->exec("CREATE UNIQUE INDEX idxAlbumGenre_1 ON album_genre ( idAlbum, idGenre )\n");
+    m_pDS->exec("CREATE UNIQUE INDEX idxAlbumGenre_2 ON album_genre ( idGenre, idAlbum )\n");
+    m_pDS->exec("INSERT INTO album_genre ( idGenre, idAlbum, iOrder) SELECT idGenre, idAlbum, iPosition FROM exgenrealbum");
+    m_pDS->exec("REPLACE INTO album_genre ( idGenre, idAlbum, iOrder) SELECT idGenre, idAlbum, 0 FROM album");
 
-      m_pDS->exec("DROP TABLE album");
-      m_pDS->exec("ALTER TABLE album_new RENAME TO album");
-      m_pDS->exec("CREATE INDEX idxAlbum ON album(strAlbum)");
-      m_pDS->exec("DROP TABLE IF EXISTS exgenrealbum");
+    CStdString strSQL;
+    strSQL=PrepareSQL("SELECT album.idAlbum AS idAlbum, strExtraGenres,"
+                      "  album.idGenre AS idGenre, strGenre FROM album "
+                      "  JOIN genre ON album.idGenre=genre.idGenre");
+    if (!m_pDS->query(strSQL.c_str()))
+    {
+      CLog::Log(LOGDEBUG, "%s could not upgrade albums table", __FUNCTION__);
+      return false;
     }
 
-    if (version < 24)
+    VECALBUMS albums;
+    while (!m_pDS->eof())
     {
-      m_pDS->exec("CREATE TABLE song_genre ( idGenre integer, idSong integer, iOrder integer )\n");
-      m_pDS->exec("CREATE UNIQUE INDEX idxSongGenre_1 ON song_genre ( idSong, idGenre )\n");
-      m_pDS->exec("CREATE UNIQUE INDEX idxSongGenre_2 ON song_genre ( idGenre, idSong )\n");
-      m_pDS->exec("INSERT INTO song_genre ( idGenre, idSong, iOrder) SELECT idGenre, idSong, iPosition FROM exgenresong");
-      m_pDS->exec("REPLACE INTO song_genre ( idGenre, idSong, iOrder) SELECT idGenre, idSong, 0 FROM song");
-
-      CStdString strSQL;
-      strSQL=PrepareSQL("SELECT song.idSong AS idSong, strExtraGenres,"
-                        "  song.idGenre AS idGenre, strGenre FROM song "
-                        "  JOIN genre ON song.idGenre=genre.idGenre");
-      if (!m_pDS->query(strSQL.c_str()))
+      CAlbum album;
+      album.idAlbum = m_pDS->fv("idAlbum").get_asInt();
+      album.genre.push_back(m_pDS->fv("strGenre").get_asString());
+      if (!m_pDS->fv("strExtraGenres").get_asString().empty())
       {
-        CLog::Log(LOGDEBUG, "%s could not upgrade songs table", __FUNCTION__);
-        return false;
+        std::vector<std::string> extraGenres = StringUtils::Split(m_pDS->fv("strExtraGenres").get_asString(), g_advancedSettings.m_musicItemSeparator);
+        album.genre.insert(album.genre.end(), extraGenres.begin(), extraGenres.end());
       }
+      albums.push_back(album);
+      m_pDS->next();
+    }
+    m_pDS->close();
+    m_pDS->exec("CREATE TABLE album_new ( idAlbum integer primary key, strAlbum varchar(256), strArtists text, strGenres text, iYear integer, idThumb integer)");
+    m_pDS->exec("INSERT INTO album_new ( idAlbum, strAlbum, strArtists, iYear, idThumb) SELECT idAlbum, strAlbum, strArtists, iYear, idThumb FROM album");
 
-      VECSONGS songs;
-      while (!m_pDS->eof())
-      {
-        CSong song;
-        song.idSong = m_pDS->fv("idSong").get_asInt();
-        song.genre.push_back(m_pDS->fv("strGenre").get_asString());
-        if (!m_pDS->fv("strExtraGenres").get_asString().empty())
-        {
-          std::vector<std::string> extraGenres = StringUtils::Split(m_pDS->fv("strExtraGenres").get_asString(), g_advancedSettings.m_musicItemSeparator);
-          song.genre.insert(song.genre.end(), extraGenres.begin(), extraGenres.end());
-        }
-        songs.push_back(song);
-        m_pDS->next();
-      }
-      m_pDS->close();
-      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, 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("INSERT INTO song_new ( idSong, idAlbum, idPath, strArtists, strTitle, iTrack, iDuration, iYear, dwFileNameCRC, strFileName, strMusicBrainzTrackID, strMusicBrainzArtistID, strMusicBrainzAlbumID, strMusicBrainzAlbumArtistID, strMusicBrainzTRMID, iTimesPlayed, iStartOffset, iEndOffset, idThumb, lastplayed, rating, comment) SELECT idSong, idAlbum, idPath, strArtists, strTitle, iTrack, iDuration, iYear, dwFileNameCRC, strFileName, strMusicBrainzTrackID, strMusicBrainzArtistID, strMusicBrainzAlbumID, strMusicBrainzAlbumArtistID, strMusicBrainzTRMID, iTimesPlayed, iStartOffset, iEndOffset, idThumb, lastplayed, rating, comment FROM song");
+    for (VECALBUMS::iterator it = albums.begin(); it != albums.end(); ++it)
+    {
+      CStdString strSQL;
+      strSQL = PrepareSQL("UPDATE album_new SET strGenres='%s' WHERE idAlbum=%i", StringUtils::Join(it->genre, g_advancedSettings.m_musicItemSeparator).c_str(), it->idAlbum);
+      m_pDS->exec(strSQL);
+    }
 
-      for (VECSONGS::iterator it = songs.begin(); it != songs.end(); ++it)
-      {
-        CStdString strSQL;
-        strSQL = PrepareSQL("UPDATE song_new SET strGenres='%s' WHERE idSong=%i", StringUtils::Join(it->genre, g_advancedSettings.m_musicItemSeparator).c_str(), it->idSong);
-        m_pDS->exec(strSQL);
-      }
+    m_pDS->exec("DROP TABLE album");
+    m_pDS->exec("ALTER TABLE album_new RENAME TO album");
+    m_pDS->exec("CREATE INDEX idxAlbum ON album(strAlbum)");
+    m_pDS->exec("DROP TABLE IF EXISTS exgenrealbum");
+  }
 
-      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("DROP TABLE IF EXISTS exgenresong");
-    }
+  if (version < 24)
+  {
+    m_pDS->exec("CREATE TABLE song_genre ( idGenre integer, idSong integer, iOrder integer )\n");
+    m_pDS->exec("CREATE UNIQUE INDEX idxSongGenre_1 ON song_genre ( idSong, idGenre )\n");
+    m_pDS->exec("CREATE UNIQUE INDEX idxSongGenre_2 ON song_genre ( idGenre, idSong )\n");
+    m_pDS->exec("INSERT INTO song_genre ( idGenre, idSong, iOrder) SELECT idGenre, idSong, iPosition FROM exgenresong");
+    m_pDS->exec("REPLACE INTO song_genre ( idGenre, idSong, iOrder) SELECT idGenre, idSong, 0 FROM song");
 
-    if (version < 25)
+    CStdString strSQL;
+    strSQL=PrepareSQL("SELECT song.idSong AS idSong, strExtraGenres,"
+                      "  song.idGenre AS idGenre, strGenre FROM song "
+                      "  JOIN genre ON song.idGenre=genre.idGenre");
+    if (!m_pDS->query(strSQL.c_str()))
     {
-      m_pDS->exec("ALTER TABLE album ADD bCompilation integer not null default '0'");
-      m_pDS->exec("CREATE INDEX idxAlbum_1 ON album(bCompilation)");
+      CLog::Log(LOGDEBUG, "%s could not upgrade songs table", __FUNCTION__);
+      return false;
     }
 
-    if (version < 26)
-    { // add art table
-      m_pDS->exec("CREATE TABLE art(art_id INTEGER PRIMARY KEY, media_id INTEGER, media_type TEXT, type TEXT, url TEXT)");
-      m_pDS->exec("CREATE INDEX ix_art ON art(media_id, media_type(20), type(20))");
-      m_pDS->exec("CREATE TRIGGER delete_song AFTER DELETE ON song FOR EACH ROW BEGIN DELETE FROM art WHERE media_id=old.idSong AND media_type='song'; END");
-      m_pDS->exec("CREATE TRIGGER delete_album AFTER DELETE ON album FOR EACH ROW BEGIN DELETE FROM art WHERE media_id=old.idAlbum AND media_type='album'; END");
-      m_pDS->exec("CREATE TRIGGER delete_artist AFTER DELETE ON artist FOR EACH ROW BEGIN DELETE FROM art WHERE media_id=old.idArtist AND media_type='artist'; END");
+    VECSONGS songs;
+    while (!m_pDS->eof())
+    {
+      CSong song;
+      song.idSong = m_pDS->fv("idSong").get_asInt();
+      song.genre.push_back(m_pDS->fv("strGenre").get_asString());
+      if (!m_pDS->fv("strExtraGenres").get_asString().empty())
+      {
+        std::vector<std::string> extraGenres = StringUtils::Split(m_pDS->fv("strExtraGenres").get_asString(), g_advancedSettings.m_musicItemSeparator);
+        song.genre.insert(song.genre.end(), extraGenres.begin(), extraGenres.end());
+      }
+      songs.push_back(song);
+      m_pDS->next();
     }
+    m_pDS->close();
+    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, 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("INSERT INTO song_new ( idSong, idAlbum, idPath, strArtists, strTitle, iTrack, iDuration, iYear, dwFileNameCRC, strFileName, strMusicBrainzTrackID, strMusicBrainzArtistID, strMusicBrainzAlbumID, strMusicBrainzAlbumArtistID, strMusicBrainzTRMID, iTimesPlayed, iStartOffset, iEndOffset, idThumb, lastplayed, rating, comment) SELECT idSong, idAlbum, idPath, strArtists, strTitle, iTrack, iDuration, iYear, dwFileNameCRC, strFileName, strMusicBrainzTrackID, strMusicBrainzArtistID, strMusicBrainzAlbumID, strMusicBrainzAlbumArtistID, strMusicBrainzTRMID, iTimesPlayed, iStartOffset, iEndOffset, idThumb, lastplayed, rating, comment FROM song");
 
-    if (version < 27)
+    for (VECSONGS::iterator it = songs.begin(); it != songs.end(); ++it)
     {
-      m_pDS->exec("DROP TABLE thumb");
-
-      g_settings.m_musicNeedsUpdate = 27;
-      g_settings.Save();
+      CStdString strSQL;
+      strSQL = PrepareSQL("UPDATE song_new SET strGenres='%s' WHERE idSong=%i", StringUtils::Join(it->genre, g_advancedSettings.m_musicItemSeparator).c_str(), it->idSong);
+      m_pDS->exec(strSQL);
     }
 
-    // always recreate the views after any table change
-    CreateViews();
+    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("DROP TABLE IF EXISTS exgenresong");
+  }
 
-    CommitTransaction();
+  if (version < 25)
+  {
+    m_pDS->exec("ALTER TABLE album ADD bCompilation integer not null default '0'");
+    m_pDS->exec("CREATE INDEX idxAlbum_1 ON album(bCompilation)");
   }
-  catch (...)
+
+  if (version < 26)
+  { // add art table
+    m_pDS->exec("CREATE TABLE art(art_id INTEGER PRIMARY KEY, media_id INTEGER, media_type TEXT, type TEXT, url TEXT)");
+    m_pDS->exec("CREATE INDEX ix_art ON art(media_id, media_type(20), type(20))");
+    m_pDS->exec("CREATE TRIGGER delete_song AFTER DELETE ON song FOR EACH ROW BEGIN DELETE FROM art WHERE media_id=old.idSong AND media_type='song'; END");
+    m_pDS->exec("CREATE TRIGGER delete_album AFTER DELETE ON album FOR EACH ROW BEGIN DELETE FROM art WHERE media_id=old.idAlbum AND media_type='album'; END");
+    m_pDS->exec("CREATE TRIGGER delete_artist AFTER DELETE ON artist FOR EACH ROW BEGIN DELETE FROM art WHERE media_id=old.idArtist AND media_type='artist'; END");
+  }
+
+  if (version < 27)
   {
-    CLog::Log(LOGERROR, "Error attempting to update the database version!");
-    return false;
+    m_pDS->exec("DROP TABLE thumb");
+
+    g_settings.m_musicNeedsUpdate = 27;
+    g_settings.Save();
   }
+
+  // always recreate the views after any table change
+  CreateViews();
+
   return true;
 }
 
index 4631238..6f8928e 100644 (file)
@@ -65,6 +65,7 @@ CMusicInfoScanner::CMusicInfoScanner() : CThread("CMusicInfoScanner")
   m_bCanInterrupt = false;
   m_currentItem=0;
   m_itemCount=0;
+  m_flags = 0;
 }
 
 CMusicInfoScanner::~CMusicInfoScanner()
@@ -205,11 +206,12 @@ void CMusicInfoScanner::Process()
     m_pObserver->OnFinished();
 }
 
-void CMusicInfoScanner::Start(const CStdString& strDirectory)
+void CMusicInfoScanner::Start(const CStdString& strDirectory, int flags)
 {
   m_pathsToScan.clear();
   m_albumsScanned.clear();
   m_artistsScanned.clear();
+  m_flags = flags;
 
   if (strDirectory.IsEmpty())
   { // scan all paths in the database.  We do this by scanning all paths in the db, and crossing them off the list as
@@ -378,7 +380,7 @@ bool CMusicInfoScanner::DoScan(const CStdString& strDirectory)
 
   // check whether we need to rescan or not
   CStdString dbHash;
-  if (!m_musicDatabase.GetPathHash(strDirectory, dbHash) || dbHash != hash)
+  if ((m_flags & SCAN_RESCAN) || !m_musicDatabase.GetPathHash(strDirectory, dbHash) || dbHash != hash)
   { // path has changed - rescan
     if (dbHash.IsEmpty())
       CLog::Log(LOGDEBUG, "%s Scanning dir '%s' as not in the database", __FUNCTION__, strDirectory.c_str());
@@ -565,7 +567,7 @@ int CMusicInfoScanner::RetrieveMusicInfo(CFileItemList& items, const CStdString&
     {
       CStdString strArtist = m_musicDatabase.GetArtistById(*it);
       m_artistsScanned.push_back(*it);
-      if (!m_bStop && g_guiSettings.GetBool("musiclibrary.downloadinfo"))
+      if (!m_bStop && (m_flags & SCAN_ONLINE))
       {
         CStdString strPath;
         strPath.Format("musicdb://2/%u/", *it);
@@ -581,7 +583,7 @@ int CMusicInfoScanner::RetrieveMusicInfo(CFileItemList& items, const CStdString&
     }
   }
 
-  if (g_guiSettings.GetBool("musiclibrary.downloadinfo"))
+  if (m_flags & SCAN_ONLINE)
   {
     for (set<long>::iterator it = albumsToScan.begin(); it != albumsToScan.end(); ++it)
     {
@@ -663,7 +665,9 @@ void CMusicInfoScanner::CategoriseAlbums(VECSONGS &songsToCheck, VECALBUMS &albu
      3. no album artist is specified
      4. we have at least two different primary artists
      */
-    if (compilation && artists.size() > 1)
+    if (artists.size() == 1)
+      compilation = false;
+    if (compilation)
     {
       artists.clear();
       std::string various = g_localizeStrings.Get(340); // Various Artists
@@ -685,7 +689,7 @@ void CMusicInfoScanner::CategoriseAlbums(VECSONGS &songsToCheck, VECALBUMS &albu
       {
         unsigned int match = 0;
         vector<string> &compare = (*k)->albumArtist.empty() ? (*k)->artist : (*k)->albumArtist;
-        for (; match < common.size(), match < compare.size(); match++)
+        for (; match < common.size() && match < compare.size(); match++)
         {
           if (compare[match] != common[match])
             break;
@@ -700,6 +704,7 @@ void CMusicInfoScanner::CategoriseAlbums(VECSONGS &songsToCheck, VECALBUMS &albu
       CAlbum album;
       album.strAlbum = i->first;
       album.artist = common;
+      album.bCompilation = compilation;
       for (vector<CSong *>::iterator k = artistSongs.begin(); k != artistSongs.end(); ++k)
       {
         if ((*k)->albumArtist.empty())
@@ -708,6 +713,9 @@ void CMusicInfoScanner::CategoriseAlbums(VECSONGS &songsToCheck, VECALBUMS &albu
         // 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;
+        //       in addition, we may want to use year as discriminating for albums
+        if (album.iYear == 0)
+          album.iYear = (*k)->iYear;
       }
 
       albums.push_back(album);
index 37872cc..77ab776 100644 (file)
@@ -44,10 +44,17 @@ public:
 class CMusicInfoScanner : CThread, public IRunnable
 {
 public:
+  /*! \brief Flags for controlling the scanning process
+   */
+  enum SCAN_FLAGS { SCAN_NORMAL     = 0,
+                    SCAN_ONLINE     = 1 << 0,
+                    SCAN_BACKGROUND = 1 << 1,
+                    SCAN_RESCAN     = 1 << 2 };
+
   CMusicInfoScanner();
   virtual ~CMusicInfoScanner();
 
-  void Start(const CStdString& strDirectory);
+  void Start(const CStdString& strDirectory, int flags);
   void FetchAlbumInfo(const CStdString& strDirectory, bool refresh=false);
   void FetchArtistInfo(const CStdString& strDirectory, bool refresh=false);
   bool IsScanning();
@@ -126,5 +133,6 @@ protected:
   std::set<CStdString> m_pathsToCount;
   std::vector<long> m_artistsScanned;
   std::vector<long> m_albumsScanned;
+  int m_flags;
 };
 }
index 6fce444..1ac328c 100644 (file)
@@ -22,7 +22,6 @@
 
 #include "ImusicInfoTagLoader.h"
 #include "DllASAP.h"
-#include "cores/paplayer/ASAPCodec.h"
 
 namespace MUSIC_INFO
 {
index fddffa3..a168b15 100644 (file)
 #include "utils/URIUtils.h"
 #include "FileItem.h"
 
+#ifdef HAS_ASAP_CODEC
+#include "cores/paplayer/ASAPCodec.h"
+#endif
+
 using namespace MUSIC_INFO;
 
 CMusicInfoTagLoaderFactory::CMusicInfoTagLoaderFactory()
index c2fad63..1b0a5dd 100644 (file)
@@ -50,6 +50,7 @@
 #include "music/tags/MusicInfoTag.h"
 #include "guilib/GUIWindowManager.h"
 #include "dialogs/GUIDialogOK.h"
+#include "dialogs/GUIDialogYesNo.h"
 #include "dialogs/GUIDialogKeyboard.h"
 #include "dialogs/GUIDialogProgress.h"
 #include "FileItem.h"
@@ -1344,6 +1345,22 @@ void CGUIWindowMusicBase::OnPrepareFileItems(CFileItemList &items)
 {
 }
 
+void CGUIWindowMusicBase::OnInitWindow()
+{
+  CGUIMediaWindow::OnInitWindow();
+  if (g_settings.m_musicNeedsUpdate == 27 && !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);
+      g_settings.m_musicNeedsUpdate = false; // once is enough (user may interrupt, but that's up to them)
+      g_settings.Save();
+    }
+  }
+}
+
 CStdString CGUIWindowMusicBase::GetStartFolder(const CStdString &dir)
 {
   if (dir.Equals("Plugins") || dir.Equals("Addons"))
index 2021f62..42667bf 100644 (file)
@@ -51,6 +51,7 @@ public:
   void OnInfo(CFileItem *pItem, bool bShowInfo = false);
 
 protected:
+  virtual void OnInitWindow();
   /*!
   \brief Will be called when an popup context menu has been asked for
   \param itemNumber List/thumb control item that has been clicked on
index c99044c..db7c3ff 100644 (file)
@@ -132,7 +132,9 @@ void CGUIDialogNetworkSetup::OnInitWindow()
 #endif
   pSpin->AddLabel(g_localizeStrings.Get(20256), NET_PROTOCOL_HTSP);
   pSpin->AddLabel(g_localizeStrings.Get(20257), NET_PROTOCOL_VTP);
+#ifdef HAS_MYSQL
   pSpin->AddLabel(g_localizeStrings.Get(20258), NET_PROTOCOL_MYTH);
+#endif
   pSpin->AddLabel(g_localizeStrings.Get(21331), NET_PROTOCOL_TUXBOX);
   pSpin->AddLabel(g_localizeStrings.Get(20301), NET_PROTOCOL_HTTPS);
   pSpin->AddLabel(g_localizeStrings.Get(20300), NET_PROTOCOL_HTTP);
index 79aecf2..e66b0e8 100644 (file)
@@ -98,7 +98,8 @@ static const translateField fields[] = {
   { "audiolanguage",     FieldAudioLanguage,           SortByAudioLanguage,            CSmartPlaylistRule::TEXTIN_FIELD,     21447 },
   { "subtitlelanguage",  FieldSubtitleLanguage,        SortBySubtitleLanguage,         CSmartPlaylistRule::TEXTIN_FIELD,     21448 },
   { "random",            FieldRandom,                  SortByRandom,                   CSmartPlaylistRule::TEXT_FIELD,       590 },
-  { "playlist",          FieldPlaylist,                SortByPlaylistOrder,            CSmartPlaylistRule::PLAYLIST_FIELD,   559 }
+  { "playlist",          FieldPlaylist,                SortByPlaylistOrder,            CSmartPlaylistRule::PLAYLIST_FIELD,   559 },
+  { "tag",               FieldTag,                     SortByNone,                     CSmartPlaylistRule::BROWSEABLE_FIELD, 20459 }
 };
 
 #define NUM_FIELDS sizeof(fields) / sizeof(translateField)
@@ -382,6 +383,7 @@ vector<Field> CSmartPlaylistRule::GetFields(const CStdString &type)
     fields.push_back(FieldFilename);
     fields.push_back(FieldPath);
     fields.push_back(FieldSet);
+    fields.push_back(FieldTag);
     fields.push_back(FieldDateAdded);
     isVideo = true;
   }
@@ -716,6 +718,8 @@ CStdString CSmartPlaylistRule::GetWhereClause(CDatabase &db, const CStdString& s
         query = table + ".idFile " + negate + " IN (SELECT idFile FROM bookmark WHERE type = 1)";
       else if (m_field == FieldSet)
         query = GetField(FieldId, strType) + negate + " IN (SELECT idMovie FROM setlinkmovie JOIN sets ON sets.idSet=setlinkmovie.idSet WHERE sets.strSet" + parameter + ")";
+      else if (m_field == FieldTag)
+        query = GetField(FieldId, strType) + negate + " IN (SELECT idMedia FROM taglinks JOIN tag ON tag.idTag = taglinks.idTag WHERE tag.strTag" + parameter + " AND taglinks.media_type = 'movie')";
     }
     else if (strType == "musicvideos")
     {
index 6ddd4c3..99efdbd 100644 (file)
@@ -74,18 +74,6 @@ bool CProgramDatabase::CreateTables()
 
 bool CProgramDatabase::UpdateOldVersion(int version)
 {
-  if (NULL == m_pDB.get()) return false;
-  if (NULL == m_pDS.get()) return false;
-  if (NULL == m_pDS2.get()) return false;
-
-  try
-  {
-  }
-  catch (...)
-  {
-    CLog::Log(LOGERROR, "Error attempting to update the database version!");
-    return false;
-  }
   return true;
 }
 
index f772403..0416f79 100644 (file)
@@ -299,6 +299,9 @@ void CAdvancedSettings::Initialize()
   m_airTunesPort = 36666;
   m_airPlayPort = 36667;
   m_initialized = true;
+
+  m_databaseMusic.Reset();
+  m_databaseVideo.Reset();
 }
 
 bool CAdvancedSettings::Load()
index 366615c..50b9de4 100644 (file)
@@ -29,6 +29,15 @@ class TiXmlElement;
 class DatabaseSettings
 {
 public:
+  void Reset()
+  {
+    type.clear();
+    host.clear();
+    port.clear();
+    user.clear();
+    pass.clear();
+    name.clear();
+  };
   CStdString type;
   CStdString host;
   CStdString port;
index 849953c..c6c3cbb 100644 (file)
@@ -274,8 +274,8 @@ void CGUISettings::Initialize()
   AddBool(ml, "musiclibrary.showcompilationartists", 13414, true);
   AddSeparator(ml,"musiclibrary.sep1");
   AddBool(ml,"musiclibrary.downloadinfo", 20192, false);
-  AddDefaultAddon(ml, "musiclibrary.albumsscraper", 20193, "metadata.albums.allmusic.com", ADDON_SCRAPER_ALBUMS);
-  AddDefaultAddon(ml, "musiclibrary.artistsscraper", 20194, "metadata.artists.allmusic.com", ADDON_SCRAPER_ARTISTS);
+  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");
@@ -520,6 +520,9 @@ void CGUISettings::Initialize()
 #else
   AddBool(in, "input.enablemouse", 21369, true);
 #endif
+#if defined(HAS_SDL_JOYSTICK)
+  AddBool(in, "input.enablejoystick", 35100, true);
+#endif
 
   CSettingsCategory* net = AddCategory(4, "network", 798);
   if (g_application.IsStandAlone())
@@ -774,8 +777,7 @@ void CGUISettings::Initialize()
 
   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.yahoomusic.com", ADDON_SCRAPER_MUSICVIDEOS);
-  AddBool(NULL, "scrapers.langfallback", 21416, false);
+  AddDefaultAddon(NULL, "scrapers.musicvideosdefault", 21415, "metadata.musicvideos.last.fm", ADDON_SCRAPER_MUSICVIDEOS);
 
   // service settings
   AddGroup(6, 14036);
index 3b7b7fe..d982694 100644 (file)
 #include "Settings.h"
 #include "AdvancedSettings.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/LocalizeStrings.h"
 #include "LangInfo.h"
 #include "utils/StringUtils.h"
@@ -1388,6 +1393,12 @@ void CGUIWindowSettingsCategory::OnSettingChanged(CBaseSettingControl *pSettingC
   {
     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"));
+#endif
+  }
   else if (strSetting.Equals("videoscreen.screen"))
   {
     DisplayMode mode = g_guiSettings.GetInt("videoscreen.screen");
index aa6f2ae..918ccf4 100644 (file)
   #define HAS_AIRTUNES
 #endif
 
+#ifdef HAVE_MYSQL
+  #define HAS_MYSQL
+#endif
+
 /**********************
  * Non-free Components
  **********************/
 #define HAVE_LIBCEC
 #define HAVE_LIBMP3LAME
 #define HAVE_LIBVORBISENC
+#define HAS_MYSQL
 
 #define DECLARE_UNUSED(a,b) a b;
 #endif
index 5b09f18..2fc289a 100644 (file)
 
 #include "Atomics.h"
 
+// the only safe way to be absolutly sure that
+// gcc intrinsics are present when using an unknown GCC
+#if defined(__GNUC__) && defined(__GNUC_MINOR__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
+  #define HAS_GCC_INTRINSICS
+#elif defined(TARGET_DARWIN)
+  // safe under darwin gcc-4.2, llvm-gcc-4.2 and clang
+  #define HAS_GCC_INTRINSICS
+#elif defined(TARGET_FREEBSD)
+  // safe under freebsd gcc-4.2 and clang
+  #define HAS_GCC_INTRINSICS
+#endif
 ///////////////////////////////////////////////////////////////////////////
 // 32-bit atomic compare-and-swap
 // Returns previous value of *pAddr
 ///////////////////////////////////////////////////////////////////////////
-#if defined(__ppc__) || defined(__powerpc__) // PowerPC
-
 long cas(volatile long *pAddr, long expectedVal, long swapVal)
 {
+#if defined(HAS_GCC_INTRINSICS)
+  return(__sync_val_compare_and_swap(pAddr, expectedVal, swapVal));
+#elif defined(__ppc__) || defined(__powerpc__) // PowerPC
   unsigned int prev;
-
   __asm__ __volatile__ (
-                        "  1:      lwarx   %0,0,%2  \n" /* Load the current value of *pAddr(%2) into prev (%0) and lock pAddr,  */
-                        "          cmpw     0,%0,%3 \n" /* Verify that the current value (%2) == old value (%3) */
-                        "          bne-     2f      \n" /* Bail if the two values are not equal [not as expected] */
-                        "          stwcx.  %4,0,%2  \n" /* Attempt to store swapVal (%4) value into *pAddr (%2) [p must still be reserved] */
-                        "          bne-    1b       \n" /* Loop if p was no longer reserved */
-                        "          isync            \n" /* Reconcile multiple processors [if present] */
-                        "  2:                       \n"
-                        : "=&r" (prev), "+m" (*pAddr)                   /* Outputs [prev, *pAddr] */
-                        : "r" (pAddr), "r" (expectedVal), "r" (swapVal) /* Inputs [pAddr, expectedVal, swapVal] */
-                        : "cc", "memory");                              /* Clobbers */
-
+    "  1:      lwarx   %0,0,%2  \n" /* Load the current value of *pAddr(%2) into prev (%0) and lock pAddr,  */
+    "          cmpw     0,%0,%3 \n" /* Verify that the current value (%2) == old value (%3) */
+    "          bne-     2f      \n" /* Bail if the two values are not equal [not as expected] */
+    "          stwcx.  %4,0,%2  \n" /* Attempt to store swapVal (%4) value into *pAddr (%2) [p must still be reserved] */
+    "          bne-    1b       \n" /* Loop if p was no longer reserved */
+    "          isync            \n" /* Reconcile multiple processors [if present] */
+    "  2:                       \n"
+    : "=&r" (prev), "+m" (*pAddr)                   /* Outputs [prev, *pAddr] */
+    : "r" (pAddr), "r" (expectedVal), "r" (swapVal) /* Inputs [pAddr, expectedVal, swapVal] */
+    : "cc", "memory");                              /* Clobbers */
   return prev;
-}
 
 #elif defined(__arm__)
-long cas(volatile long* pAddr, long expectedVal, long swapVal)
-{
   register long prev;
   asm volatile (
-                "dmb      ish            \n" // Memory barrier. Make sure all memory accesses appearing before this complete before any that appear after
-                "1:                      \n"
-                "ldrex    %0, [%1]       \n" // Load the current value of *pAddr(%1) into prev (%0) and lock pAddr,
-                "cmp      %0,  %2        \n" // Verify that the current value (%0) == old value (%2)
-                "bne      2f             \n" // Bail if the two values are not equal [not as expected]
-                "strex    r1,  %3, [%1]  \n"
-                "cmp      r1,  #0        \n"
-                "bne      1b             \n"
-                "dmb      ish            \n" // Memory barrier.
-                "2:                      \n"
-                : "=&r" (prev)
-                : "r"(pAddr), "r"(expectedVal),"r"(swapVal)
-                : "r1"
-                );
+    "dmb      ish            \n" // Memory barrier. Make sure all memory accesses appearing before this complete before any that appear after
+    "1:                      \n"
+    "ldrex    %0, [%1]       \n" // Load the current value of *pAddr(%1) into prev (%0) and lock pAddr,
+    "cmp      %0,  %2        \n" // Verify that the current value (%0) == old value (%2)
+    "bne      2f             \n" // Bail if the two values are not equal [not as expected]
+    "strex    r1,  %3, [%1]  \n"
+    "cmp      r1,  #0        \n"
+    "bne      1b             \n"
+    "dmb      ish            \n" // Memory barrier.
+    "2:                      \n"
+    : "=&r" (prev)
+    : "r"(pAddr), "r"(expectedVal),"r"(swapVal)
+    : "r1"
+    );
   return prev;
-}
 
 #elif defined(__mips__)
 // TODO:
+  unsigned int prev;
+  #error atomic cas undefined for mips
+  return prev;
 
 #elif defined(WIN32)
-
-long cas(volatile long* pAddr, long expectedVal, long swapVal)
-{
   long prev;
-
   __asm
   {
     // Load parameters
@@ -90,41 +95,33 @@ long cas(volatile long* pAddr, long expectedVal, long swapVal)
     // Store the return value
     mov prev, eax;
   }
-
   return prev;
-}
 
 #else // Linux / OSX86 (GCC)
-
-long cas(volatile long* pAddr,long expectedVal, long swapVal)
-{
   long prev;
-
   __asm__ __volatile__ (
-                        "lock/cmpxchg %1, %2"
-                        : "=a" (prev)
-                        : "r" (swapVal), "m" (*pAddr), "0" (expectedVal)
-                        : "memory" );
+    "lock/cmpxchg %1, %2"
+    : "=a" (prev)
+    : "r" (swapVal), "m" (*pAddr), "0" (expectedVal)
+    : "memory" );
   return prev;
 
-}
-
 #endif
+}
 
 ///////////////////////////////////////////////////////////////////////////
 // 64-bit atomic compare-and-swap
 // Returns previous value of *pAddr
 ///////////////////////////////////////////////////////////////////////////
+long long cas2(volatile long long* pAddr, long long expectedVal, long long swapVal)
+{
 #if defined(__ppc__) || defined(__powerpc__) || defined(__arm__) || defined(__mips__) // PowerPC, ARM, and MIPS
-
 // Not available/required
+// Hack to allow compilation
+  throw "cas2 is not implemented";
 
 #elif defined(WIN32)
-
-long long cas2(volatile long long* pAddr, long long expectedVal, long long swapVal)
-{
   long long prev;
-
   __asm
   {
     mov esi, pAddr ;
@@ -136,86 +133,74 @@ long long cas2(volatile long long* pAddr, long long expectedVal, long long swapV
     mov dword ptr [prev], eax ;
     mov dword ptr prev[4], edx ;
   }
-
   return prev;
-}
 
 #else // Linux / OSX86 (GCC)
-#if !defined (__x86_64)
-long long cas2(volatile long long* pAddr, long long expectedVal, long long swapVal)
-{
-  long long prev;
-
-  __asm__ volatile (
-                        " push %%ebx        \n"  // We have to manually handle ebx, because PIC uses it and the compiler refuses to build anything that touches it
-                        " mov %4, %%ebx     \n"
-                        " lock/cmpxchg8b (%%esi) \n"
-                        " pop %%ebx"
-                        : "=A" (prev)
-                        : "c" ((unsigned long)(swapVal >> 32)), "0" (expectedVal), "S" (pAddr), "m" (swapVal)
-                        : "memory");
-  return prev;
-}
-#else
-// Hack to allow compilation on x86_64
-long long cas2(volatile long long* pAddr, long long expectedVal, long long swapVal)
-{
-  throw "cas2 is not implemented on x86_64!";
-}
-#endif // !defined (__x86_64)
+  #if !defined (__x86_64)
+      long long prev;
+      __asm__ volatile (
+        " push %%ebx        \n"  // We have to manually handle ebx, because PIC uses it and the compiler refuses to build anything that touches it
+        " mov %4, %%ebx     \n"
+        " lock/cmpxchg8b (%%esi) \n"
+        " pop %%ebx"
+        : "=A" (prev)
+        : "c" ((unsigned long)(swapVal >> 32)), "0" (expectedVal), "S" (pAddr), "m" (swapVal)
+        : "memory");
+      return prev;
+  #else
+    // Hack to allow compilation on x86_64
+      throw "cas2 is not implemented on x86_64!";
+  #endif
 #endif
+}
 
 ///////////////////////////////////////////////////////////////////////////
 // 32-bit atomic increment
 // Returns new value of *pAddr
 ///////////////////////////////////////////////////////////////////////////
-#if defined(__ppc__) || defined(__powerpc__) // PowerPC
-
 long AtomicIncrement(volatile long* pAddr)
 {
-  long val;
+#if defined(HAS_GCC_INTRINSICS)
+  return __sync_add_and_fetch(pAddr, 1);
 
+#elif defined(__ppc__) || defined(__powerpc__) // PowerPC
+  long val;
   __asm__ __volatile__ (
-                        "sync             \n"
-                     "1: lwarx  %0, 0, %1 \n"
-                        "addic  %0, %0, 1 \n"
-                        "stwcx. %0, 0, %1 \n"
-                        "bne-   1b        \n"
-                        "isync"
-                        : "=&r" (val)
-                        : "r" (pAddr)
-                        : "cc", "xer", "memory");
+    "sync             \n"
+    "1: lwarx  %0, 0, %1 \n"
+    "addic  %0, %0, 1 \n"
+    "stwcx. %0, 0, %1 \n"
+    "bne-   1b        \n"
+    "isync"
+    : "=&r" (val)
+    : "r" (pAddr)
+    : "cc", "xer", "memory");
   return val;
-}
 
 #elif defined(__arm__)
-
-long AtomicIncrement(volatile long* pAddr)
-{
   register long val;
   asm volatile (
-                "dmb      ish            \n" // Memory barrier. Make sure all memory accesses appearing before this complete before any that appear after
-                "1:                     \n" 
-                "ldrex   %0, [%1]       \n" // (val = *pAddr)
-                "add     %0,  #1        \n" // (val += 1)
-                "strex   r1,  %0, [%1] \n"
-                "cmp     r1,   #0       \n"
-                "bne     1b             \n"
-                "dmb     ish            \n" // Memory barrier.
-                : "=&r" (val)
-                : "r"(pAddr)
-                : "r1"
-                );
+    "dmb      ish            \n" // Memory barrier. Make sure all memory accesses appearing before this complete before any that appear after
+    "1:                     \n" 
+    "ldrex   %0, [%1]       \n" // (val = *pAddr)
+    "add     %0,  #1        \n" // (val += 1)
+    "strex   r1,  %0, [%1]     \n"
+    "cmp     r1,   #0       \n"
+    "bne     1b             \n"
+    "dmb     ish            \n" // Memory barrier.
+    : "=&r" (val)
+    : "r"(pAddr)
+    : "r1"
+    );
   return val;
-}
 
 #elif defined(__mips__)
 // TODO:
+  long val;
+  #error AtomicIncrement undefined for mips
+  return val;
 
 #elif defined(WIN32)
-
-long AtomicIncrement(volatile long* pAddr)
-{
   long val;
   __asm
   {
@@ -225,76 +210,75 @@ long AtomicIncrement(volatile long* pAddr)
     mov val, eax ;
   }
   return val;
-}
 
-#else // Linux / OSX86 (GCC)
+#elif defined(__x86_64__)
+  register long result;
+  __asm__ __volatile__ (
+    "lock/xaddq %q0, %1"
+    : "=r" (result), "=m" (*pAddr)
+    : "0" ((long) (1)), "m" (*pAddr));
+  return *pAddr;
 
-long AtomicIncrement(volatile long* pAddr)
-{
+#else // Linux / OSX86 (GCC)
   register long reg __asm__ ("eax") = 1;
   __asm__ __volatile__ (
-                        "lock/xadd %0, %1 \n"
-                        "inc %%eax"
-                        : "+r" (reg)
-                        : "m" (*pAddr)
-                        : "memory" );
+    "lock/xadd %0, %1 \n"
+    "inc %%eax"
+    : "+r" (reg)
+    : "m" (*pAddr)
+    : "memory" );
   return reg;
-}
 
 #endif
+}
 
 ///////////////////////////////////////////////////////////////////////////
 // 32-bit atomic add
 // Returns new value of *pAddr
 ///////////////////////////////////////////////////////////////////////////
-
-#if defined(__ppc__) || defined(__powerpc__) // PowerPC
-
 long AtomicAdd(volatile long* pAddr, long amount)
 {
-  long val;
+#if defined(HAS_GCC_INTRINSICS)
+  return __sync_add_and_fetch(pAddr, amount);
 
+#elif defined(__ppc__) || defined(__powerpc__) // PowerPC
+  long val;
   __asm__ __volatile__ (
-                        "sync             \n"
-                        "1: lwarx  %0, 0, %1 \n"
-                        "add  %0, %2, %0 \n"
-                        "stwcx. %0, 0, %1 \n"
-                        "bne-   1b        \n"
-                        "isync"
-                        : "=&r" (val)
-                        : "r" (pAddr), "r" (amount)
-                        : "cc", "memory");
+    "sync                 \n"
+    "1: lwarx  %0, 0, %1  \n"
+    "add  %0, %2, %0      \n"
+    "stwcx. %0, 0, %1     \n"
+    "bne-   1b            \n"
+    "isync"
+    : "=&r" (val)
+    : "r" (pAddr), "r" (amount)
+    : "cc", "memory");
   return val;
-}
 
 #elif defined(__arm__)
-
-long AtomicAdd(volatile long* pAddr, long amount)
-{
   register long val;
   asm volatile (
-                "dmb      ish            \n" // Memory barrier. Make sure all memory accesses appearing before this complete before any that appear after
-                "1:                     \n" 
-                "ldrex   %0, [%1]       \n" // (val = *pAddr)
-                "add     %0,  %2        \n" // (val += amount)
-                "strex   r1,  %0, [%1] \n"
-                "cmp     r1,   #0       \n"
-                "bne     1b             \n"
-                "dmb     ish            \n" // Memory barrier.
-                : "=&r" (val)
-                : "r"(pAddr), "r"(amount)
-                : "r1"
-                );
+    "dmb      ish           \n" // Memory barrier. Make sure all memory accesses appearing before this complete before any that appear after
+  "1:                       \n" 
+    "ldrex   %0, [%1]       \n" // (val = *pAddr)
+    "add     %0,  %2        \n" // (val += amount)
+    "strex   r1,  %0, [%1]     \n"
+    "cmp     r1,   #0       \n"
+    "bne     1b             \n"
+    "dmb     ish            \n" // Memory barrier.
+    : "=&r" (val)
+    : "r"(pAddr), "r"(amount)
+    : "r1"
+    );
   return val;
-}
 
 #elif defined(__mips__)
 // TODO:
+  long val;
+  #error AtomicAdd undefined for mips
+  return val;
 
 #elif defined(WIN32)
-
-long AtomicAdd(volatile long* pAddr, long amount)
-{
   __asm
   {
     mov eax, amount;
@@ -304,76 +288,75 @@ long AtomicAdd(volatile long* pAddr, long amount)
     mov amount, ebx;
   }
   return amount;
-}
 
-#else // Linux / OSX86 (GCC)
+#elif defined(__x86_64__)
+  register long result;
+  __asm__ __volatile__ (
+    "lock/xaddq %q0, %1"
+    : "=r" (result), "=m" (*pAddr)
+    : "0" ((long) (amount)), "m" (*pAddr));
+  return *pAddr;
 
-long AtomicAdd(volatile long* pAddr, long amount)
-{
+#else // Linux / OSX86 (GCC)
   register long reg __asm__ ("eax") = amount;
   __asm__ __volatile__ (
-                        "lock/xadd %0, %1 \n"
-                        "dec %%eax"
-                        : "+r" (reg)
-                        : "m" (*pAddr)
-                        : "memory" );
+    "lock/xadd %0, %1 \n"
+    "dec %%eax"
+    : "+r" (reg)
+    : "m" (*pAddr)
+    : "memory" );
   return reg;
-}
 
 #endif
+}
 
 ///////////////////////////////////////////////////////////////////////////
 // 32-bit atomic decrement
 // Returns new value of *pAddr
 ///////////////////////////////////////////////////////////////////////////
-#if defined(__ppc__) || defined(__powerpc__) // PowerPC
-
 long AtomicDecrement(volatile long* pAddr)
 {
-  long val;
+#if defined(HAS_GCC_INTRINSICS)
+  return __sync_sub_and_fetch(pAddr, 1);
 
+#elif defined(__ppc__) || defined(__powerpc__) // PowerPC
+  long val;
   __asm__ __volatile__ (
-                        "sync                \n"
-                     "1: lwarx  %0, 0, %1    \n"
-                        "addic  %0, %0, -1   \n"
-                        "stwcx. %0, 0, %1    \n"
-                        "bne-   1b           \n"
-                        "isync"
-                        : "=&r" (val)
-                        : "r" (pAddr)
-                        : "cc", "xer", "memory");
+    "sync                \n"
+"1: lwarx  %0, 0, %1     \n"
+    "addic  %0, %0, -1   \n"
+    "stwcx. %0, 0, %1    \n"
+    "bne-   1b           \n"
+    "isync"
+    : "=&r" (val)
+    : "r" (pAddr)
+    : "cc", "xer", "memory");
   return val;
-}
 
 #elif defined(__arm__)
-
-long AtomicDecrement(volatile long* pAddr)
-{
   register long val;
   asm volatile (
-                "dmb      ish            \n" // Memory barrier. Make sure all memory accesses appearing before this complete before any that appear after
-                "1:                     \n" 
-                "ldrex   %0, [%1]       \n" // (val = *pAddr)
-                "sub     %0,  #1        \n" // (val -= 1)
-                "strex   r1,  %0, [%1] \n"
-                "cmp     r1,   #0       \n"
-                "bne     1b             \n"
-                "dmb     ish            \n" // Memory barrier.
-                : "=&r" (val)
-                : "r"(pAddr)
-                : "r1"
-                );
-  
+    "dmb      ish           \n" // Memory barrier. Make sure all memory accesses appearing before this complete before any that appear after
+    "1:                     \n" 
+    "ldrex   %0, [%1]       \n" // (val = *pAddr)
+    "sub     %0,  #1        \n" // (val -= 1)
+    "strex   r1,  %0, [%1]     \n"
+    "cmp     r1,   #0       \n"
+    "bne     1b             \n"
+    "dmb     ish            \n" // Memory barrier.
+    : "=&r" (val)
+    : "r"(pAddr)
+    : "r1"
+    );
   return val;
-}
 
 #elif defined(__mips__)
 // TODO:
+  long val;
+  #error AtomicDecrement undefined for mips
+  return val;
 
 #elif defined(WIN32)
-
-long AtomicDecrement(volatile long* pAddr)
-{
   long val;
   __asm
   {
@@ -383,77 +366,75 @@ long AtomicDecrement(volatile long* pAddr)
     mov val, eax ;
   }
   return val;
-}
 
-#else // Linux / OSX86 (GCC)
+#elif defined(__x86_64__)
+  register long result;
+  __asm__ __volatile__ (
+    "lock/xaddq %q0, %1"
+    : "=r" (result), "=m" (*pAddr)
+    : "0" ((long) (-1)), "m" (*pAddr));
+  return *pAddr;
 
-long AtomicDecrement(volatile long* pAddr)
-{
+#else // Linux / OSX86 (GCC)
   register long reg __asm__ ("eax") = -1;
   __asm__ __volatile__ (
-                        "lock/xadd %0, %1 \n"
-                        "dec %%eax"
-                        : "+r" (reg)
-                        : "m" (*pAddr)
-                        : "memory" );
+    "lock/xadd %0, %1 \n"
+    "dec %%eax"
+    : "+r" (reg)
+    : "m" (*pAddr)
+    : "memory" );
   return reg;
-}
 
 #endif
+}
 
 ///////////////////////////////////////////////////////////////////////////
 // 32-bit atomic subtract
 // Returns new value of *pAddr
 ///////////////////////////////////////////////////////////////////////////
-#if defined(__ppc__) || defined(__powerpc__) // PowerPC
-
 long AtomicSubtract(volatile long* pAddr, long amount)
 {
+#if defined(HAS_GCC_INTRINSICS)
+  return __sync_sub_and_fetch(pAddr, amount);
+
+#elif defined(__ppc__) || defined(__powerpc__) // PowerPC
   long val;
   amount *= -1;
-
   __asm__ __volatile__ (
-                        "sync             \n"
-                        "1: lwarx  %0, 0, %1 \n"
-                        "add  %0, %2, %0 \n"
-                        "stwcx. %0, 0, %1 \n"
-                        "bne-   1b        \n"
-                        "isync"
-                        : "=&r" (val)
-                        : "r" (pAddr), "r" (amount)
-                        : "cc", "memory");
+    "sync                 \n"
+    "1: lwarx  %0, 0, %1  \n"
+    "add  %0, %2, %0      \n"
+    "stwcx. %0, 0, %1     \n"
+    "bne-   1b            \n"
+    "isync"
+    : "=&r" (val)
+    : "r" (pAddr), "r" (amount)
+    : "cc", "memory");
   return val;
-}
 
 #elif defined(__arm__)
-
-long AtomicSubtract(volatile long* pAddr, long amount)
-{
   register long val;
   asm volatile (
-                "dmb     ish            \n" // Memory barrier. Make sure all memory accesses appearing before this complete before any that appear after
-                "1:                     \n" 
-                "ldrex   %0, [%1]       \n" // (val = *pAddr)
-                "sub     %0,  %2        \n" // (val -= amount)
-                "strex   r1,  %0, [%1] \n"
-                "cmp     r1,   #0       \n"
-                "bne     1b             \n"
-                "dmb     ish            \n" // Memory barrier.
-                : "=&r" (val)
-                : "r"(pAddr), "r"(amount)
-                : "r1"
-                );
-  
+    "dmb     ish            \n" // Memory barrier. Make sure all memory accesses appearing before this complete before any that appear after
+    "1:                     \n" 
+    "ldrex   %0, [%1]       \n" // (val = *pAddr)
+    "sub     %0,  %2        \n" // (val -= amount)
+    "strex   r1,  %0, [%1]     \n"
+    "cmp     r1,   #0       \n"
+    "bne     1b             \n"
+    "dmb     ish            \n" // Memory barrier.
+    : "=&r" (val)
+    : "r"(pAddr), "r"(amount)
+    : "r1"
+    );
   return val;
-}
 
 #elif defined(__mips__)
 // TODO:
+  #error AtomicSubtract undefined for mips
+  return val;
 
 #elif defined(WIN32)
-
-long AtomicSubtract(volatile long* pAddr, long amount)
-{
   amount *= -1;
   __asm
   {
@@ -464,23 +445,27 @@ long AtomicSubtract(volatile long* pAddr, long amount)
     mov amount, ebx;
   }
   return amount;
-}
 
-#else // Linux / OSX86 (GCC)
+#elif defined(__x86_64__)
+  register long result;
+  __asm__ __volatile__ (
+    "lock/xaddq %q0, %1"
+    : "=r" (result), "=m" (*pAddr)
+    : "0" ((long) (-1 * amount)), "m" (*pAddr));
+  return *pAddr;
 
-long AtomicSubtract(volatile long* pAddr, long amount)
-{
+#else // Linux / OSX86 (GCC)
   register long reg __asm__ ("eax") = -1 * amount;
   __asm__ __volatile__ (
-                        "lock/xadd %0, %1 \n"
-                        "dec %%eax"
-                        : "+r" (reg)
-                        : "m" (*pAddr)
-                        : "memory" );
+    "lock/xadd %0, %1 \n"
+    "dec %%eax"
+    : "+r" (reg)
+    : "m" (*pAddr)
+    : "memory" );
   return reg;
-}
 
 #endif
+}
 
 ///////////////////////////////////////////////////////////////////////////
 // Fast spinlock implmentation. No backoff when busy
index 05252f0..967bff9 100644 (file)
@@ -136,8 +136,8 @@ bool CThread::WaitForThreadExit(unsigned int milliseconds)
   {
     // boost priority of thread we are waiting on to same as caller
     int callee = GetThreadPriority(m_ThreadOpaque.handle);
-    int caller = GetThreadPriority(GetCurrentThread());
-    if(caller > callee)
+    int caller = GetThreadPriority(::GetCurrentThread());
+    if(caller != THREAD_PRIORITY_ERROR_RETURN && caller > callee)
       SetThreadPriority(m_ThreadOpaque.handle, caller);
 
     lock.Leave();
@@ -145,7 +145,7 @@ bool CThread::WaitForThreadExit(unsigned int milliseconds)
     lock.Enter();
 
     // restore thread priority if thread hasn't exited
-    if(caller > callee && m_ThreadOpaque.handle)
+    if(callee != THREAD_PRIORITY_ERROR_RETURN && caller > callee && m_ThreadOpaque.handle)
       SetThreadPriority(m_ThreadOpaque.handle, callee);
   }
   return bReturn;
index 3cba581..3fb8457 100644 (file)
@@ -109,7 +109,8 @@ typedef enum {
   FieldAudioCodec,
   FieldAudioLanguage,
   FieldSubtitleLanguage,
-  FieldProductionCode
+  FieldProductionCode,
+  FieldTag
 } Field;
 
 typedef std::set<Field> Fields;
diff --git a/xbmc/utils/EndianSwap.cpp b/xbmc/utils/EndianSwap.cpp
new file mode 100644 (file)
index 0000000..c32b305
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ *      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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *  http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include "EndianSwap.h"
+
+/* based on libavformat/spdif.c */
+void Endian_Swap16_buf(uint16_t *dst, uint16_t *src, int w)
+{
+  int i;
+
+  for (i = 0; i + 8 <= w; i += 8) {
+    dst[i + 0] = Endian_Swap16(src[i + 0]);
+    dst[i + 1] = Endian_Swap16(src[i + 1]);
+    dst[i + 2] = Endian_Swap16(src[i + 2]);
+    dst[i + 3] = Endian_Swap16(src[i + 3]);
+    dst[i + 4] = Endian_Swap16(src[i + 4]);
+    dst[i + 5] = Endian_Swap16(src[i + 5]);
+    dst[i + 6] = Endian_Swap16(src[i + 6]);
+    dst[i + 7] = Endian_Swap16(src[i + 7]);
+  }
+
+  for (; i < w; i++)
+    dst[i + 0] = Endian_Swap16(src[i + 0]);
+}
+
index d083ff0..be7bf4c 100644 (file)
@@ -19,7 +19,7 @@
  *
  */
 
- /* Functions taken from SDL (SDL_endian.h) */
+ /* Endian_SwapXX functions taken from SDL (SDL_endian.h) */
 
 #ifndef __ENDIAN_SWAP_H__
 #define __ENDIAN_SWAP_H__
@@ -83,6 +83,8 @@ static __inline__ uint64_t Endian_Swap64(uint64_t x) {
 
 }
 
+void Endian_Swap16_buf(uint16_t *dst, uint16_t *src, int w);
+
 #ifndef WORDS_BIGENDIAN
 #define Endian_SwapLE16(X) (X)
 #define Endian_SwapLE32(X) (X)
index f086b48..b94dfc4 100644 (file)
@@ -12,6 +12,7 @@ SRCS=AlarmClock.cpp \
      DatabaseUtils.cpp \
      DownloadQueue.cpp \
      DownloadQueueManager.cpp \
+     EndianSwap.cpp \
      Fanart.cpp \
      fastmemcpy.c \
      fastmemcpy-arm.S \
index 37fb236..f1b26f8 100644 (file)
@@ -101,7 +101,6 @@ bool CRecentlyAddedJob::UpdateVideo()
  
   if (videodatabase.GetRecentlyAddedEpisodesNav("videodb://5/", TVShowItems, NUM_ITEMS))
   {
-    std::map<int, std::string> showThumbs;
     for (; i < TVShowItems.Size(); ++i)
     {    
       CFileItemPtr item          = TVShowItems.Get(i);
@@ -128,25 +127,12 @@ bool CRecentlyAddedJob::UpdateVideo()
       if (!item->HasThumbnail())
         m_thumbLoader.LoadItem(item.get());
 
-      std::string showThumb;
-      if (item->GetVideoInfoTag()->m_iIdShow > 0)
-      {
-        std::map<int, std::string>::const_iterator thumbIter;
-        if ((thumbIter = showThumbs.find(item->GetVideoInfoTag()->m_iIdShow)) != showThumbs.end())
-          showThumb = thumbIter->second;
-        else
-        {
-          showThumb = videodatabase.GetArtForItem(item->GetVideoInfoTag()->m_iIdShow, "tvshow", "thumb");
-          showThumbs[item->GetVideoInfoTag()->m_iIdShow] = showThumb;
-        }
-      }
-
       std::string seasonThumb;
       if (item->GetVideoInfoTag()->m_iIdSeason > 0)
         seasonThumb = videodatabase.GetArtForItem(item->GetVideoInfoTag()->m_iIdSeason, "season", "thumb");
 
       home->SetProperty("LatestEpisode." + value + ".Thumb"         , item->GetThumbnailImage());
-      home->SetProperty("LatestEpisode." + value + ".ShowThumb"     , showThumb);
+      home->SetProperty("LatestEpisode." + value + ".ShowThumb"     , item->GetProperty("tvshowthumb"));
       home->SetProperty("LatestEpisode." + value + ".SeasonThumb"   , seasonThumb);
       home->SetProperty("LatestEpisode." + value + ".Fanart"        , item->GetProperty("fanart_image"));
     }
index 219b134..4d2472a 100644 (file)
@@ -91,12 +91,9 @@ bool CXBMCTinyXML::LoadFile(FILE *f, TiXmlEncoding encoding)
 {
   CStdString data("");
   char buf[BUFFER_SIZE];
-  int result, count = 0;
+  int result;
   while ((result = fread(buf, 1, BUFFER_SIZE, f)) > 0)
-  {
-    data.reserve(BUFFER_SIZE * (++count));
-    data.append(buf);
-  }
+    data.append(buf, result);
   return Parse(data, NULL, encoding) != NULL;
 }
 
index c40db5f..0aa92fa 100644 (file)
@@ -211,6 +211,18 @@ CGUIViewStateWindowVideoNav::CGUIViewStateWindowVideoNav(const CFileItemList& it
         SetSortOrder(g_settings.m_viewStateVideoNavGenres.m_sortOrder);
       }
       break;
+    case NODE_TYPE_TAGS:
+      {
+        SORT_METHOD method = SORT_METHOD_LABEL_IGNORE_THE;
+        if (!g_guiSettings.GetBool("filelists.ignorethewhensorting"))
+          method = SORT_METHOD_LABEL;
+
+        AddSortMethod(method, 551, LABEL_MASKS("%T","", "%T",""));  // Title, empty | Title, empty
+        SetSortMethod(method);
+        SetViewAsControl(g_settings.m_viewStateVideoNavGenres.m_viewMode);
+        SetSortOrder(g_settings.m_viewStateVideoNavGenres.m_sortOrder);
+      }
+      break;
     case NODE_TYPE_EPISODES:
       {
         if (params.GetSeason() > -1)
index beff1f2..1505978 100644 (file)
@@ -321,6 +321,16 @@ bool CVideoDatabase::CreateTables()
     m_pDS->exec("CREATE TRIGGER delete_set AFTER DELETE ON sets FOR EACH ROW BEGIN DELETE FROM art WHERE media_id=old.idSet AND media_type='set'; END");
     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");
 
+    CLog::Log(LOGINFO, "create tag table");
+    m_pDS->exec("CREATE TABLE tag (idTag integer primary key, strTag text)");
+    m_pDS->exec("CREATE UNIQUE INDEX ix_tag_1 ON tag (strTag(255))");
+
+    CLog::Log(LOGINFO, "create taglinks table");
+    m_pDS->exec("CREATE TABLE taglinks (idTag integer, idMedia integer, media_type TEXT)");
+    m_pDS->exec("CREATE UNIQUE INDEX ix_taglinks_1 ON taglinks (idTag, media_type(20), idMedia)");
+    m_pDS->exec("CREATE UNIQUE INDEX ix_taglinks_2 ON taglinks (idMedia, media_type(20), idTag)");
+    m_pDS->exec("CREATE INDEX ix_taglinks_3 ON taglinks (media_type(20))");
+
     // we create views last to ensure all indexes are rolled in
     CreateViews();
   }
@@ -1240,7 +1250,7 @@ int CVideoDatabase::AddToTable(const CStdString& table, const CStdString& firstF
     {
       m_pDS->close();
       // doesnt exists, add it
-      strSQL = PrepareSQL("insert into %s (%s, %s) values( NULL, '%s')", table.c_str(), firstField.c_str(), secondField.c_str(), value.c_str());
+      strSQL = PrepareSQL("insert into %s (%s, %s) values(NULL, '%s')", table.c_str(), firstField.c_str(), secondField.c_str(), value.c_str());      
       m_pDS->exec(strSQL.c_str());
       int id = (int)m_pDS->lastinsertid();
       return id;
@@ -1265,6 +1275,14 @@ int CVideoDatabase::AddSet(const CStdString& strSet)
   return AddToTable("sets", "idSet", "strSet", strSet);
 }
 
+int CVideoDatabase::AddTag(const std::string& tag)
+{
+  if (tag.empty())
+    return -1;
+
+  return AddToTable("tag", "idTag", "strTag", tag);
+}
+
 int CVideoDatabase::AddGenre(const CStdString& strGenre)
 {
   return AddToTable("genre", "idGenre", "strGenre", strGenre);
@@ -1346,19 +1364,24 @@ void CVideoDatabase::AddLinkToActor(const char *table, int actorID, const char *
   }
 }
 
-void CVideoDatabase::AddToLinkTable(const char *table, const char *firstField, int firstID, const char *secondField, int secondID)
+void CVideoDatabase::AddToLinkTable(const char *table, const char *firstField, int firstID, const char *secondField, int secondID, const char *typeField /* = NULL */, const char *type /* = NULL */)
 {
   try
   {
     if (NULL == m_pDB.get()) return ;
     if (NULL == m_pDS.get()) return ;
 
-    CStdString strSQL=PrepareSQL("select * from %s where %s=%i and %s=%i", table, firstField, firstID, secondField, secondID);
+    CStdString strSQL = PrepareSQL("select * from %s where %s=%i and %s=%i", table, firstField, firstID, secondField, secondID);
+    if (typeField != NULL && type != NULL)
+      strSQL += PrepareSQL(" and %s='%s'", typeField, type);
     m_pDS->query(strSQL.c_str());
     if (m_pDS->num_rows() == 0)
     {
       // doesnt exists, add it
-      strSQL=PrepareSQL("insert into %s (%s,%s) values(%i,%i)", table, firstField, secondField, firstID, secondID);
+      if (typeField == NULL || type == NULL)
+        strSQL = PrepareSQL("insert into %s (%s,%s) values(%i,%i)", table, firstField, secondField, firstID, secondID);
+      else
+        strSQL = PrepareSQL("insert into %s (%s,%s,%s) values(%i,%i,'%s')", table, firstField, secondField, typeField, firstID, secondID, type);
       m_pDS->exec(strSQL.c_str());
     }
     m_pDS->close();
@@ -1369,11 +1392,45 @@ void CVideoDatabase::AddToLinkTable(const char *table, const char *firstField, i
   }
 }
 
+void CVideoDatabase::RemoveFromLinkTable(const char *table, const char *firstField, int firstID, const char *secondField, int secondID, const char *typeField /* = NULL */, const char *type /* = NULL */)
+{
+  try
+  {
+    if (NULL == m_pDB.get()) return ;
+    if (NULL == m_pDS.get()) return ;
+
+    CStdString strSQL = PrepareSQL("DELETE FROM %s WHERE %s = %i AND %s = %i", table, firstField, firstID, secondField, secondID);
+    if (typeField != NULL && type != NULL)
+      strSQL += PrepareSQL(" AND %s='%s'", typeField, type);
+    m_pDS->exec(strSQL.c_str());
+  }
+  catch (...)
+  {
+    CLog::Log(LOGERROR, "%s failed", __FUNCTION__);
+  }
+}
+
 //****Sets****
 void CVideoDatabase::AddSetToMovie(int idMovie, int idSet)
 {
   AddToLinkTable("setlinkmovie", "idSet", idSet, "idMovie", idMovie);
 }
+//****Tags****
+void CVideoDatabase::AddTagToItem(int idMovie, int idTag, const std::string &type)
+{
+  if (type.empty())
+    return;
+
+  AddToLinkTable("taglinks", "idTag", idTag, "idMedia", idMovie, "media_type", type.c_str());
+}
+
+void CVideoDatabase::RemoveTagFromItem(int idMovie, int idTag, const std::string &type)
+{
+  if (type.empty())
+    return;
+
+  RemoveFromLinkTable("taglinks", "idTag", idTag, "idMedia", idMovie, "media_type", type.c_str());
+}
 
 //****Actors****
 void CVideoDatabase::AddActorToMovie(int idMovie, int idActor, const CStdString& strRole, int order)
@@ -1898,6 +1955,13 @@ int CVideoDatabase::SetDetailsForMovie(const CStdString& strFilenameAndPath, con
       AddSetToMovie(idMovie, idSet);
     }
 
+    // add tags...
+    for (unsigned int i = 0; i < details.m_tags.size(); i++)
+    {
+      int idTag = AddTag(details.m_tags[i]);
+      AddTagToItem(idMovie, idTag, "movie");
+    }
+
     // add countries...
     for (unsigned int i = 0; i < details.m_country.size(); i++)
       AddCountryToMovie(idMovie, AddCountry(details.m_country[i]));
@@ -2838,6 +2902,31 @@ void CVideoDatabase::DeleteSet(int idSet)
   }
 }
 
+void CVideoDatabase::DeleteTag(int idTag, const std::string &mediaType)
+{
+  try
+  {
+    if (m_pDB.get() == NULL || m_pDS.get() == NULL)
+      return;
+
+    CStdString strSQL;
+    strSQL = PrepareSQL("DELETE FROM taglinks WHERE idTag = %i AND media_type = '%s'", idTag, mediaType.c_str());
+    m_pDS->exec(strSQL.c_str());
+
+    // check if the tag is used for another media type as well before deleting it completely
+    strSQL = PrepareSQL("SELECT 1 FROM taglinks WHERE idTag = %i", idTag);
+    if (RunQuery(strSQL) <= 0)
+    {
+      strSQL = PrepareSQL("DELETE FROM tag WHERE idTag = %i", idTag);
+      m_pDS->exec(strSQL.c_str());
+    }
+  }
+  catch (...)
+  {
+    CLog::Log(LOGERROR, "%s (%i) failed", __FUNCTION__, idTag);
+  }
+}
+
 void CVideoDatabase::GetDetailsFromDB(auto_ptr<Dataset> &pDS, int min, int max, const SDbTableOffsets *offsets, CVideoInfoTag &details, int idxOffset)
 {
   GetDetailsFromDB(pDS->get_sql_record(), min, max, offsets, details, idxOffset);
@@ -3058,6 +3147,15 @@ CVideoInfoTag CVideoDatabase::GetDetailsForMovie(const dbiplus::sql_record* cons
       m_pDS2->next();
     }
 
+    // get tags
+    strSQL = PrepareSQL("SELECT tag.strTag FROM tag, taglinks WHERE taglinks.idMedia = %i AND taglinks.media_type = 'movie' AND taglinks.idTag = tag.idTag ORDER BY tag.idTag", idMovie);
+    m_pDS2->query(strSQL.c_str());
+    while (!m_pDS2->eof())
+    {
+      details.m_tags.push_back(m_pDS2->fv("tag.strTag").get_asString());
+      m_pDS2->next();
+    }
+
     // create tvshowlink string
     vector<int> links;
     GetLinksToTvShow(idMovie,links);
@@ -3686,234 +3784,232 @@ bool CVideoDatabase::ScraperInUse(const CStdString &scraperID) const
 
 bool CVideoDatabase::UpdateOldVersion(int iVersion)
 {
-  BeginTransaction();
-
-  try
+  if (iVersion < 43)
   {
-    if (iVersion < 43)
-    {
-      m_pDS->exec("ALTER TABLE settings ADD VerticalShift float");
-    }
-    if (iVersion < 44)
+    m_pDS->exec("ALTER TABLE settings ADD VerticalShift float");
+  }
+  if (iVersion < 44)
+  {
+    // only if MySQL is used and default character set is not utf8
+    // string data needs to be converted to proper utf8
+    CStdString charset = m_pDS->getDatabase()->getDefaultCharset();
+    if (!m_sqlite && !charset.empty() && charset != "utf8")
     {
-      // only if MySQL is used and default character set is not utf8
-      // string data needs to be converted to proper utf8
-      CStdString charset = m_pDS->getDatabase()->getDefaultCharset();
-      if (!m_sqlite && !charset.empty() && charset != "utf8")
+      map<CStdString, CStdStringArray> tables;
+      map<CStdString, CStdStringArray>::iterator itt;
+      CStdStringArray::iterator itc;
+
+      // columns that need to be converted
+      // content columns
+      CStdStringArray c_columns;
+      for (int i = 0; i < 22; i++)
       {
-        map<CStdString, CStdStringArray> tables;
-        map<CStdString, CStdStringArray>::iterator itt;
-        CStdStringArray::iterator itc;
-
-        // columns that need to be converted
-        // content columns
-        CStdStringArray c_columns;
-        for (int i = 0; i < 22; i++)
-        {
-          CStdString c;
-          c.Format("c%02d", i);
-          c_columns.push_back(c);
-        }
+        CStdString c;
+        c.Format("c%02d", i);
+        c_columns.push_back(c);
+      }
 
-        tables.insert(pair<CStdString, CStdStringArray> ("episode", c_columns));
-        tables.insert(pair<CStdString, CStdStringArray> ("movie", c_columns));
-        tables.insert(pair<CStdString, CStdStringArray> ("musicvideo", c_columns));
-        tables.insert(pair<CStdString, CStdStringArray> ("tvshow", c_columns));
+      tables.insert(pair<CStdString, CStdStringArray> ("episode", c_columns));
+      tables.insert(pair<CStdString, CStdStringArray> ("movie", c_columns));
+      tables.insert(pair<CStdString, CStdStringArray> ("musicvideo", c_columns));
+      tables.insert(pair<CStdString, CStdStringArray> ("tvshow", c_columns));
 
-        //common columns
-        CStdStringArray c1;
-        c1.push_back("strRole");
-        tables.insert(pair<CStdString, CStdStringArray> ("actorlinkepisode", c1));
-        tables.insert(pair<CStdString, CStdStringArray> ("actorlinkmovie", c1));
-        tables.insert(pair<CStdString, CStdStringArray> ("actorlinktvshow", c1));
+      //common columns
+      CStdStringArray c1;
+      c1.push_back("strRole");
+      tables.insert(pair<CStdString, CStdStringArray> ("actorlinkepisode", c1));
+      tables.insert(pair<CStdString, CStdStringArray> ("actorlinkmovie", c1));
+      tables.insert(pair<CStdString, CStdStringArray> ("actorlinktvshow", c1));
 
-        //remaining columns
-        CStdStringArray c2;
-        c2.push_back("strActor");
-        tables.insert(pair<CStdString, CStdStringArray> ("actors", c2));
+      //remaining columns
+      CStdStringArray c2;
+      c2.push_back("strActor");
+      tables.insert(pair<CStdString, CStdStringArray> ("actors", c2));
 
-        CStdStringArray c3;
-        c3.push_back("strCountry");
-        tables.insert(pair<CStdString, CStdStringArray> ("country", c3));
+      CStdStringArray c3;
+      c3.push_back("strCountry");
+      tables.insert(pair<CStdString, CStdStringArray> ("country", c3));
 
-        CStdStringArray c4;
-        c4.push_back("strFilename");
-        tables.insert(pair<CStdString, CStdStringArray> ("files", c4));
+      CStdStringArray c4;
+      c4.push_back("strFilename");
+      tables.insert(pair<CStdString, CStdStringArray> ("files", c4));
 
-        CStdStringArray c5;
-        c5.push_back("strGenre");
-        tables.insert(pair<CStdString, CStdStringArray> ("genre", c5));
+      CStdStringArray c5;
+      c5.push_back("strGenre");
+      tables.insert(pair<CStdString, CStdStringArray> ("genre", c5));
 
-        CStdStringArray c6;
-        c6.push_back("strSet");
-        tables.insert(pair<CStdString, CStdStringArray> ("sets", c6));
+      CStdStringArray c6;
+      c6.push_back("strSet");
+      tables.insert(pair<CStdString, CStdStringArray> ("sets", c6));
 
-        CStdStringArray c7;
-        c7.push_back("strStudio");
-        tables.insert(pair<CStdString, CStdStringArray> ("studio", c7));
+      CStdStringArray c7;
+      c7.push_back("strStudio");
+      tables.insert(pair<CStdString, CStdStringArray> ("studio", c7));
 
-        CStdStringArray c8;
-        c8.push_back("strPath");
-        tables.insert(pair<CStdString, CStdStringArray> ("path", c8));
+      CStdStringArray c8;
+      c8.push_back("strPath");
+      tables.insert(pair<CStdString, CStdStringArray> ("path", c8));
 
-        for (itt = tables.begin(); itt != tables.end(); ++itt)
+      for (itt = tables.begin(); itt != tables.end(); ++itt)
+      {
+        CStdString q;
+        q = PrepareSQL("UPDATE `%s` SET", itt->first.c_str());
+        for (itc = itt->second.begin(); itc != itt->second.end(); ++itc)
         {
-          CStdString q;
-          q = PrepareSQL("UPDATE `%s` SET", itt->first.c_str());
-          for (itc = itt->second.begin(); itc != itt->second.end(); ++itc)
+          q += PrepareSQL(" `%s` = CONVERT(CAST(CONVERT(`%s` USING %s) AS BINARY) USING utf8)",
+                          itc->c_str(), itc->c_str(), charset.c_str());
+          if (*itc != itt->second.back())
           {
-            q += PrepareSQL(" `%s` = CONVERT(CAST(CONVERT(`%s` USING %s) AS BINARY) USING utf8)",
-                            itc->c_str(), itc->c_str(), charset.c_str());
-            if (*itc != itt->second.back())
-            {
-              q += ",";
-            }
+            q += ",";
           }
-          m_pDS->exec(q);
         }
+        m_pDS->exec(q);
       }
     }
-    if (iVersion < 45)
-    {
-      m_pDS->exec("ALTER TABLE movie ADD c22 text");
-      m_pDS->exec("ALTER TABLE episode ADD c22 text");
-      m_pDS->exec("ALTER TABLE musicvideo ADD c22 text");
-      m_pDS->exec("ALTER TABLE tvshow ADD c22 text");
-      // Now update our tables
-      UpdateBasePath("movie", "idMovie", VIDEODB_ID_BASEPATH);
-      UpdateBasePath("musicvideo", "idMVideo", VIDEODB_ID_MUSICVIDEO_BASEPATH);
-      UpdateBasePath("episode", "idEpisode", VIDEODB_ID_EPISODE_BASEPATH);
-      UpdateBasePath("tvshow", "idShow", VIDEODB_ID_TV_BASEPATH, true);
-    }
-    if (iVersion < 46)
-    { // add indices for dir entry lookups
-      m_pDS->exec("CREATE INDEX ixMovieBasePath ON movie ( c22(255) )");
-      m_pDS->exec("CREATE INDEX ixMusicVideoBasePath ON musicvideo ( c13(255) )");
-      m_pDS->exec("CREATE INDEX ixEpisodeBasePath ON episode ( c18(255) )");
-      m_pDS->exec("CREATE INDEX ixTVShowBasePath ON tvshow ( c16(255) )");
-    }
-    if (iVersion < 50)
-    {
-      m_pDS->exec("ALTER TABLE settings ADD ScalingMethod integer");
-      m_pDS->exec(PrepareSQL("UPDATE settings set ScalingMethod=%i", g_settings.m_defaultVideoSettings.m_ScalingMethod));
-    }
-    if (iVersion < 51)
-    {
-      // Add iOrder fields to actorlink* tables to be able to list
-      // actors by importance
-      m_pDS->exec("ALTER TABLE actorlinkmovie ADD iOrder integer");
-      m_pDS->exec("ALTER TABLE actorlinktvshow ADD iOrder integer");
-      m_pDS->exec("ALTER TABLE actorlinkepisode ADD iOrder integer");
-    }
-    if (iVersion < 52)
-    { // Add basepath link to path table for faster content retrieval, and indicies
-      m_pDS->exec("ALTER TABLE movie ADD c23 text");
-      m_pDS->exec("ALTER TABLE episode ADD c23 text");
-      m_pDS->exec("ALTER TABLE musicvideo ADD c23 text");
-      m_pDS->exec("ALTER TABLE tvshow ADD c23 text");
-      m_pDS->dropIndex("movie", "ixMovieBasePath");
-      m_pDS->dropIndex("musicvideo", "ixMusicVideoBasePath");
-      m_pDS->dropIndex("episode", "ixEpisodeBasePath");
-      m_pDS->dropIndex("tvshow", "ixTVShowBasePath");
-      m_pDS->exec("CREATE INDEX ixMovieBasePath ON movie ( c23(12) )");
-      m_pDS->exec("CREATE INDEX ixMusicVideoBasePath ON musicvideo ( c14(12) )");
-      m_pDS->exec("CREATE INDEX ixEpisodeBasePath ON episode ( c19(12) )");
-      m_pDS->exec("CREATE INDEX ixTVShowBasePath ON tvshow ( c17(12) )");
-      // now update the base path links
-      UpdateBasePathID("movie", "idMovie", VIDEODB_ID_BASEPATH, VIDEODB_ID_PARENTPATHID);
-      UpdateBasePathID("musicvideo", "idMVideo", VIDEODB_ID_MUSICVIDEO_BASEPATH, VIDEODB_ID_MUSICVIDEO_PARENTPATHID);
-      UpdateBasePathID("episode", "idEpisode", VIDEODB_ID_EPISODE_BASEPATH, VIDEODB_ID_EPISODE_PARENTPATHID);
-      UpdateBasePathID("tvshow", "idShow", VIDEODB_ID_TV_BASEPATH, VIDEODB_ID_TV_PARENTPATHID);
-    }
-    if (iVersion < 54)
-    { // Change INDEX for bookmark table
-      m_pDS->dropIndex("bookmark", "ix_bookmark");
-      m_pDS->exec("CREATE INDEX ix_bookmark ON bookmark (idFile, type)");
-    }
-    if (iVersion < 55)
-    {
-      m_pDS->exec("ALTER TABLE settings ADD DeinterlaceMode integer");
-      m_pDS->exec("UPDATE settings SET DeinterlaceMode = 2 WHERE Deinterlace NOT IN (0,1)"); // anything other than none: method auto => mode force
-      m_pDS->exec("UPDATE settings SET DeinterlaceMode = 1 WHERE Deinterlace = 1"); // method auto => mode auto
-      m_pDS->exec("UPDATE settings SET DeinterlaceMode = 0, Deinterlace = 1 WHERE Deinterlace = 0"); // method none => mode off, method auto
-    }
-
-    if (iVersion < 59)
-    { // base paths for video_ts and bdmv files was wrong (and inconsistent depending on where and when they were scanned)
-      CStdString where = PrepareSQL(" WHERE files.strFileName LIKE 'VIDEO_TS.IFO' or files.strFileName LIKE 'index.BDMV'");
-      UpdateBasePath("movie", "idMovie", VIDEODB_ID_BASEPATH, false, where);
-      UpdateBasePath("musicvideo", "idMVideo", VIDEODB_ID_MUSICVIDEO_BASEPATH, false, where);
-      UpdateBasePath("episode", "idEpisode", VIDEODB_ID_EPISODE_BASEPATH, false, where);
-      UpdateBasePathID("movie", "idMovie", VIDEODB_ID_BASEPATH, VIDEODB_ID_PARENTPATHID);
-      UpdateBasePathID("musicvideo", "idMVideo", VIDEODB_ID_MUSICVIDEO_BASEPATH, VIDEODB_ID_MUSICVIDEO_PARENTPATHID);
-      UpdateBasePathID("episode", "idEpisode", VIDEODB_ID_EPISODE_BASEPATH, VIDEODB_ID_EPISODE_PARENTPATHID);
-    }
-    if (iVersion < 61)
-    {
-      m_pDS->exec("ALTER TABLE path ADD dateAdded text");
-      m_pDS->exec("ALTER TABLE files ADD dateAdded text");
-    }
-    if (iVersion < 62)
-    { // add seasons table
-      m_pDS->exec("CREATE TABLE seasons ( idSeason integer primary key, idShow integer, season integer)");
-      m_pDS->exec("CREATE INDEX ix_seasons ON seasons (idShow, season)");
-      // insert all seasons for each show
-      m_pDS->query("SELECT idShow FROM tvshow");
-      while (!m_pDS->eof())
-      {
-        CStdString sql = PrepareSQL("INSERT INTO seasons (idShow,season)"
-                                    "  SELECT DISTINCT"
-                                    "    idShow,c%02d"
-                                    "  FROM"
-                                    "    episodeview"
-                                    "  WHERE idShow=%i", VIDEODB_ID_EPISODE_SEASON, m_pDS->fv(0).get_asInt());
-        m_pDS2->exec(sql.c_str());
-        // and the "all seasons node"
-        sql = PrepareSQL("INSERT INTO seasons (idShow,season) VALUES(%i,-1)", m_pDS->fv(0).get_asInt());
-        m_pDS2->exec(sql.c_str());
-        m_pDS->next();
-      }
+  }
+  if (iVersion < 45)
+  {
+    m_pDS->exec("ALTER TABLE movie ADD c22 text");
+    m_pDS->exec("ALTER TABLE episode ADD c22 text");
+    m_pDS->exec("ALTER TABLE musicvideo ADD c22 text");
+    m_pDS->exec("ALTER TABLE tvshow ADD c22 text");
+    // Now update our tables
+    UpdateBasePath("movie", "idMovie", VIDEODB_ID_BASEPATH);
+    UpdateBasePath("musicvideo", "idMVideo", VIDEODB_ID_MUSICVIDEO_BASEPATH);
+    UpdateBasePath("episode", "idEpisode", VIDEODB_ID_EPISODE_BASEPATH);
+    UpdateBasePath("tvshow", "idShow", VIDEODB_ID_TV_BASEPATH, true);
+  }
+  if (iVersion < 46)
+  { // add indices for dir entry lookups
+    m_pDS->exec("CREATE INDEX ixMovieBasePath ON movie ( c22(255) )");
+    m_pDS->exec("CREATE INDEX ixMusicVideoBasePath ON musicvideo ( c13(255) )");
+    m_pDS->exec("CREATE INDEX ixEpisodeBasePath ON episode ( c18(255) )");
+    m_pDS->exec("CREATE INDEX ixTVShowBasePath ON tvshow ( c16(255) )");
+  }
+  if (iVersion < 50)
+  {
+    m_pDS->exec("ALTER TABLE settings ADD ScalingMethod integer");
+    m_pDS->exec(PrepareSQL("UPDATE settings set ScalingMethod=%i", g_settings.m_defaultVideoSettings.m_ScalingMethod));
+  }
+  if (iVersion < 51)
+  {
+    // Add iOrder fields to actorlink* tables to be able to list
+    // actors by importance
+    m_pDS->exec("ALTER TABLE actorlinkmovie ADD iOrder integer");
+    m_pDS->exec("ALTER TABLE actorlinktvshow ADD iOrder integer");
+    m_pDS->exec("ALTER TABLE actorlinkepisode ADD iOrder integer");
+  }
+  if (iVersion < 52)
+  { // Add basepath link to path table for faster content retrieval, and indicies
+    m_pDS->exec("ALTER TABLE movie ADD c23 text");
+    m_pDS->exec("ALTER TABLE episode ADD c23 text");
+    m_pDS->exec("ALTER TABLE musicvideo ADD c23 text");
+    m_pDS->exec("ALTER TABLE tvshow ADD c23 text");
+    m_pDS->dropIndex("movie", "ixMovieBasePath");
+    m_pDS->dropIndex("musicvideo", "ixMusicVideoBasePath");
+    m_pDS->dropIndex("episode", "ixEpisodeBasePath");
+    m_pDS->dropIndex("tvshow", "ixTVShowBasePath");
+    m_pDS->exec("CREATE INDEX ixMovieBasePath ON movie ( c23(12) )");
+    m_pDS->exec("CREATE INDEX ixMusicVideoBasePath ON musicvideo ( c14(12) )");
+    m_pDS->exec("CREATE INDEX ixEpisodeBasePath ON episode ( c19(12) )");
+    m_pDS->exec("CREATE INDEX ixTVShowBasePath ON tvshow ( c17(12) )");
+    // now update the base path links
+    UpdateBasePathID("movie", "idMovie", VIDEODB_ID_BASEPATH, VIDEODB_ID_PARENTPATHID);
+    UpdateBasePathID("musicvideo", "idMVideo", VIDEODB_ID_MUSICVIDEO_BASEPATH, VIDEODB_ID_MUSICVIDEO_PARENTPATHID);
+    UpdateBasePathID("episode", "idEpisode", VIDEODB_ID_EPISODE_BASEPATH, VIDEODB_ID_EPISODE_PARENTPATHID);
+    UpdateBasePathID("tvshow", "idShow", VIDEODB_ID_TV_BASEPATH, VIDEODB_ID_TV_PARENTPATHID);
+  }
+  if (iVersion < 54)
+  { // Change INDEX for bookmark table
+    m_pDS->dropIndex("bookmark", "ix_bookmark");
+    m_pDS->exec("CREATE INDEX ix_bookmark ON bookmark (idFile, type)");
+  }
+  if (iVersion < 55)
+  {
+    m_pDS->exec("ALTER TABLE settings ADD DeinterlaceMode integer");
+    m_pDS->exec("UPDATE settings SET DeinterlaceMode = 2 WHERE Deinterlace NOT IN (0,1)"); // anything other than none: method auto => mode force
+    m_pDS->exec("UPDATE settings SET DeinterlaceMode = 1 WHERE Deinterlace = 1"); // method auto => mode auto
+    m_pDS->exec("UPDATE settings SET DeinterlaceMode = 0, Deinterlace = 1 WHERE Deinterlace = 0"); // method none => mode off, method auto
+  }
+
+  if (iVersion < 59)
+  { // base paths for video_ts and bdmv files was wrong (and inconsistent depending on where and when they were scanned)
+    CStdString where = PrepareSQL(" WHERE files.strFileName LIKE 'VIDEO_TS.IFO' or files.strFileName LIKE 'index.BDMV'");
+    UpdateBasePath("movie", "idMovie", VIDEODB_ID_BASEPATH, false, where);
+    UpdateBasePath("musicvideo", "idMVideo", VIDEODB_ID_MUSICVIDEO_BASEPATH, false, where);
+    UpdateBasePath("episode", "idEpisode", VIDEODB_ID_EPISODE_BASEPATH, false, where);
+    UpdateBasePathID("movie", "idMovie", VIDEODB_ID_BASEPATH, VIDEODB_ID_PARENTPATHID);
+    UpdateBasePathID("musicvideo", "idMVideo", VIDEODB_ID_MUSICVIDEO_BASEPATH, VIDEODB_ID_MUSICVIDEO_PARENTPATHID);
+    UpdateBasePathID("episode", "idEpisode", VIDEODB_ID_EPISODE_BASEPATH, VIDEODB_ID_EPISODE_PARENTPATHID);
+  }
+  if (iVersion < 61)
+  {
+    m_pDS->exec("ALTER TABLE path ADD dateAdded text");
+    m_pDS->exec("ALTER TABLE files ADD dateAdded text");
+  }
+  if (iVersion < 62)
+  { // add seasons table
+    m_pDS->exec("CREATE TABLE seasons ( idSeason integer primary key, idShow integer, season integer)");
+    m_pDS->exec("CREATE INDEX ix_seasons ON seasons (idShow, season)");
+    // insert all seasons for each show
+    m_pDS->query("SELECT idShow FROM tvshow");
+    while (!m_pDS->eof())
+    {
+      CStdString sql = PrepareSQL("INSERT INTO seasons (idShow,season)"
+                                  "  SELECT DISTINCT"
+                                  "    idShow,c%02d"
+                                  "  FROM"
+                                  "    episodeview"
+                                  "  WHERE idShow=%i", VIDEODB_ID_EPISODE_SEASON, m_pDS->fv(0).get_asInt());
+      m_pDS2->exec(sql.c_str());
+      // and the "all seasons node"
+      sql = PrepareSQL("INSERT INTO seasons (idShow,season) VALUES(%i,-1)", m_pDS->fv(0).get_asInt());
+      m_pDS2->exec(sql.c_str());
+      m_pDS->next();
     }
-    if (iVersion < 63)
-    { // add art table
-      m_pDS->exec("CREATE TABLE art(art_id INTEGER PRIMARY KEY, media_id INTEGER, media_type TEXT, type TEXT, url TEXT)");
-      m_pDS->exec("CREATE INDEX ix_art ON art(media_id, media_type(20), type(20))");
-      m_pDS->exec("CREATE TRIGGER delete_movie AFTER DELETE ON movie FOR EACH ROW BEGIN DELETE FROM art WHERE media_id=old.idMovie AND media_type='movie'; END");
-      m_pDS->exec("CREATE TRIGGER delete_tvshow AFTER DELETE ON tvshow FOR EACH ROW BEGIN DELETE FROM art WHERE media_id=old.idShow AND media_type='tvshow'; END");
-      m_pDS->exec("CREATE TRIGGER delete_musicvideo AFTER DELETE ON musicvideo FOR EACH ROW BEGIN DELETE FROM art WHERE media_id=old.idMVideo AND media_type='musicvideo'; END");
-      m_pDS->exec("CREATE TRIGGER delete_episode AFTER DELETE ON episode FOR EACH ROW BEGIN DELETE FROM art WHERE media_id=old.idEpisode AND media_type='episode'; END");
-      m_pDS->exec("CREATE TRIGGER delete_season AFTER DELETE ON seasons FOR EACH ROW BEGIN DELETE FROM art WHERE media_id=old.idSeason AND media_type='season'; END");
-      m_pDS->exec("CREATE TRIGGER delete_set AFTER DELETE ON sets FOR EACH ROW BEGIN DELETE FROM art WHERE media_id=old.idSet AND media_type='set'; END");
-      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");
-
-      g_settings.m_videoNeedsUpdate = 63;
-      g_settings.Save();
-    }
-    if (iVersion < 64)
-    { // add idShow to episode table
-      m_pDS->exec("ALTER TABLE episode ADD idShow integer");
-      m_pDS->query("SELECT idEpisode FROM episode");
-      while (!m_pDS->eof())
-      {
-        int idEpisode = m_pDS->fv(0).get_asInt();
-        CStdString update = PrepareSQL("UPDATE episode SET idShow=(SELECT idShow FROM tvshowlinkepisode WHERE idEpisode=%d) WHERE idEpisode=%d", idEpisode, idEpisode);
-        m_pDS2->exec(update.c_str());
-        m_pDS->next();
-      }
-      m_pDS->exec("DROP TABLE tvshowlinkepisode");
-      m_pDS->exec("CREATE INDEX ix_episode_show1 on episode(idEpisode,idShow)");
-      m_pDS->exec("CREATE INDEX ix_episode_show2 on episode(idShow,idEpisode)");
+  }
+  if (iVersion < 63)
+  { // add art table
+    m_pDS->exec("CREATE TABLE art(art_id INTEGER PRIMARY KEY, media_id INTEGER, media_type TEXT, type TEXT, url TEXT)");
+    m_pDS->exec("CREATE INDEX ix_art ON art(media_id, media_type(20), type(20))");
+    m_pDS->exec("CREATE TRIGGER delete_movie AFTER DELETE ON movie FOR EACH ROW BEGIN DELETE FROM art WHERE media_id=old.idMovie AND media_type='movie'; END");
+    m_pDS->exec("CREATE TRIGGER delete_tvshow AFTER DELETE ON tvshow FOR EACH ROW BEGIN DELETE FROM art WHERE media_id=old.idShow AND media_type='tvshow'; END");
+    m_pDS->exec("CREATE TRIGGER delete_musicvideo AFTER DELETE ON musicvideo FOR EACH ROW BEGIN DELETE FROM art WHERE media_id=old.idMVideo AND media_type='musicvideo'; END");
+    m_pDS->exec("CREATE TRIGGER delete_episode AFTER DELETE ON episode FOR EACH ROW BEGIN DELETE FROM art WHERE media_id=old.idEpisode AND media_type='episode'; END");
+    m_pDS->exec("CREATE TRIGGER delete_season AFTER DELETE ON seasons FOR EACH ROW BEGIN DELETE FROM art WHERE media_id=old.idSeason AND media_type='season'; END");
+    m_pDS->exec("CREATE TRIGGER delete_set AFTER DELETE ON sets FOR EACH ROW BEGIN DELETE FROM art WHERE media_id=old.idSet AND media_type='set'; END");
+    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");
+
+    g_settings.m_videoNeedsUpdate = 63;
+    g_settings.Save();
+  }
+  if (iVersion < 64)
+  { // add idShow to episode table
+    m_pDS->exec("ALTER TABLE episode ADD idShow integer");
+    m_pDS->query("SELECT idEpisode FROM episode");
+    while (!m_pDS->eof())
+    {
+      int idEpisode = m_pDS->fv(0).get_asInt();
+      CStdString update = PrepareSQL("UPDATE episode SET idShow=(SELECT idShow FROM tvshowlinkepisode WHERE idEpisode=%d) WHERE idEpisode=%d", idEpisode, idEpisode);
+      m_pDS2->exec(update.c_str());
+      m_pDS->next();
     }
-    // always recreate the view after any table change
-    CreateViews();
+    m_pDS->exec("DROP TABLE tvshowlinkepisode");
+    m_pDS->exec("CREATE INDEX ix_episode_show1 on episode(idEpisode,idShow)");
+    m_pDS->exec("CREATE INDEX ix_episode_show2 on episode(idShow,idEpisode)");
   }
-  catch (...)
+  if (iVersion < 67)
   {
-    CLog::Log(LOGERROR, "Error attempting to update the database version!");
-    RollbackTransaction();
-    return false;
+    m_pDS->exec("CREATE TABLE tag (idTag integer primary key, strTag text)");
+    m_pDS->exec("CREATE UNIQUE INDEX ix_tag_1 ON tag (strTag(255))");
+
+    m_pDS->exec("CREATE TABLE taglinks (idTag integer, idMedia integer, media_type TEXT)");
+    m_pDS->exec("CREATE UNIQUE INDEX ix_taglinks_1 ON taglinks (idTag, media_type(20), idMedia)");
+    m_pDS->exec("CREATE UNIQUE INDEX ix_taglinks_2 ON taglinks (idMedia, media_type(20), idTag)");
+    m_pDS->exec("CREATE INDEX ix_taglinks_3 ON taglinks (media_type(20))");
   }
-  CommitTransaction();
+  // always recreate the view after any table change
+  CreateViews();
   return true;
 }
 
@@ -4363,6 +4459,54 @@ bool CVideoDatabase::GetNavCommon(const CStdString& strBaseDir, CFileItemList& i
   return false;
 }
 
+bool CVideoDatabase::GetTagsNav(const CStdString& strBaseDir, CFileItemList& items, int idContent)
+{
+  CStdString mediaType;
+  if (idContent == VIDEODB_CONTENT_MOVIES)
+    mediaType = "movie";
+  else
+    return false;
+
+  try
+  {
+    if (NULL == m_pDB.get()) return false;
+    if (NULL == m_pDS.get()) return false;
+
+    int iRowsFound = RunQuery(PrepareSQL("SELECT tag.idTag, tag.strTag FROM taglinks JOIN tag ON tag.idTag = taglinks.idTag WHERE taglinks.media_type = '%s' GROUP BY taglinks.idTag", mediaType.c_str()));
+    if (iRowsFound <= 0)
+      return iRowsFound == 0;
+
+    while (!m_pDS->eof())
+    {
+      int idTag = m_pDS->fv(0).get_asInt();
+
+      CFileItemPtr pItem(new CFileItem(m_pDS->fv(1).get_asString()));
+      pItem->m_bIsFolder = true;
+      pItem->GetVideoInfoTag()->m_iDbId = idTag;
+      pItem->GetVideoInfoTag()->m_type = "tag";
+
+      CStdString strDir; strDir.Format("%ld/", idTag);
+      pItem->SetPath(strBaseDir + strDir);
+
+      if (!items.Contains(pItem->GetPath()))
+      {
+        pItem->SetLabelPreformated(true);
+        items.Add(pItem);
+      }
+
+      m_pDS->next();
+    }
+    m_pDS->close();
+
+    return true;
+  }
+  catch (...)
+  {
+    CLog::Log(LOGERROR, "%s failed", __FUNCTION__);
+  }
+  return false;
+}
+
 bool CVideoDatabase::GetSetsNav(const CStdString& strBaseDir, CFileItemList& items, int idContent)
 {
   if (idContent != VIDEODB_CONTENT_MOVIES)
@@ -5161,7 +5305,9 @@ bool CVideoDatabase::GetSortedVideos(MediaType mediaType, const CStdString& strB
   return success;
 }
 
-bool CVideoDatabase::GetMoviesNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre, int idYear, int idActor, int idDirector, int idStudio, int idCountry, int idSet)
+bool CVideoDatabase::GetMoviesNav(const CStdString& strBaseDir, CFileItemList& items,
+                                  int idGenre /* = -1 */, int idYear /* = -1 */, int idActor /* = -1 */, int idDirector /* = -1 */,
+                                  int idStudio /* = -1 */, int idCountry /* = -1 */, int idSet /* = -1 */, int idTag /* = -1 */)
 {
   Filter filter;
   if (idGenre != -1)
@@ -5196,6 +5342,11 @@ bool CVideoDatabase::GetMoviesNav(const CStdString& strBaseDir, CFileItemList& i
     filter.join  = PrepareSQL("join setlinkmovie on setlinkmovie.idMovie=movieview.idMovie");
     filter.where = PrepareSQL("setlinkmovie.idSet=%u",idSet);
   }
+  else if (idTag != -1)
+  {
+    filter.join  = PrepareSQL("join taglinks on taglinks.idMedia = movieview.idMovie AND taglinks.media_type = 'movie'");
+    filter.where = PrepareSQL("taglinks.idTag = %u", idTag);
+  }
 
   return GetMoviesByWhere(strBaseDir, filter, items, idSet == -1);
 }
@@ -5854,6 +6005,11 @@ CStdString CVideoDatabase::GetSetById(int id)
   return GetSingleValue("sets", "strSet", PrepareSQL("idSet=%i", id));
 }
 
+CStdString CVideoDatabase::GetTagById(int id)
+{
+  return GetSingleValue("tag", "strTag", PrepareSQL("idTag = %i", id));
+}
+
 CStdString CVideoDatabase::GetPersonById(int id)
 {
   return GetSingleValue("actors", "strActor", PrepareSQL("idActor=%i", id));
index 06331af..9cb16e0 100644 (file)
@@ -419,6 +419,7 @@ public:
   CStdString GetGenreById(int id);
   CStdString GetCountryById(int id);
   CStdString GetSetById(int id);
+  CStdString GetTagById(int id);
   CStdString GetPersonById(int id);
   CStdString GetStudioById(int id);
   CStdString GetTvShowTitleById(int id);
@@ -459,6 +460,7 @@ public:
   void RemoveContentForPath(const CStdString& strPath,CGUIDialogProgress *progress = NULL);
   void UpdateFanart(const CFileItem &item, VIDEODB_CONTENT_TYPE type);
   void DeleteSet(int idSet);
+  void DeleteTag(int idTag, const std::string &mediaType);
 
   // per-file video settings
   bool GetVideoSettings(const CStdString &strFilenameAndPath, CVideoSettings &settings);
@@ -584,9 +586,10 @@ public:
   bool GetDirectorsNav(const CStdString& strBaseDir, CFileItemList& items, int idContent=-1);
   bool GetWritersNav(const CStdString& strBaseDir, CFileItemList& items, int idContent=-1);
   bool GetSetsNav(const CStdString& strBaseDir, CFileItemList& items, int idContent=-1);
+  bool GetTagsNav(const CStdString& strBaseDir, CFileItemList& items, int idContent=-1);
   bool GetMusicVideoAlbumsNav(const CStdString& strBaseDir, CFileItemList& items, int idArtist);
 
-  bool GetMoviesNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre=-1, int idYear=-1, int idActor=-1, int idDirector=-1, int idStudio=-1, int idCountry=-1, int idSet=-1);
+  bool GetMoviesNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre=-1, int idYear=-1, int idActor=-1, int idDirector=-1, int idStudio=-1, int idCountry=-1, int idSet=-1, int idTag=-1);
   bool GetTvShowsNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre=-1, int idYear=-1, int idActor=-1, int idDirector=-1, int idStudio=-1);
   bool GetSeasonsNav(const CStdString& strBaseDir, CFileItemList& items, int idActor=-1, int idDirector=-1, int idGenre=-1, int idYear=-1, int idShow=-1);
   bool GetEpisodesNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre=-1, int idYear=-1, int idActor=-1, int idDirector=-1, int idShow=-1, int idSeason=-1, const SortDescription &sortDescription = SortDescription());
@@ -680,6 +683,10 @@ public:
   std::string GetArtForItem(int mediaId, const std::string &mediaType, const std::string &artType);
   bool GetTvShowSeasonArt(int mediaId, std::map<int, std::string> &seasonArt);
 
+  int AddTag(const std::string &tag);
+  void AddTagToItem(int idItem, int idTag, const std::string &type);
+  void RemoveTagFromItem(int idItem, int idTag, const std::string &type);
+
 protected:
   int GetMovieId(const CStdString& strFilenameAndPath);
   int GetMusicVideoId(const CStdString& strFilenameAndPath);
@@ -710,7 +717,8 @@ protected:
 
   // link functions - these two do all the work
   void AddLinkToActor(const char *table, int actorID, const char *secondField, int secondID, const CStdString &role, int order);
-  void AddToLinkTable(const char *table, const char *firstField, int firstID, const char *secondField, int secondID);
+  void AddToLinkTable(const char *table, const char *firstField, int firstID, const char *secondField, int secondID, const char *typeField = NULL, const char *type = NULL);
+  void RemoveFromLinkTable(const char *table, const char *firstField, int firstID, const char *secondField, int secondID, const char *typeField = NULL, const char *type = NULL);
 
   void AddSetToMovie(int idMovie, int idSet);
 
@@ -799,7 +807,7 @@ private:
    */
   bool LookupByFolders(const CStdString &path, bool shows = false);
 
-  virtual int GetMinVersion() const { return 66; };
+  virtual int GetMinVersion() const { return 67; };
   virtual int GetExportVersion() const { return 1; };
   const char *GetBaseDBName() const { return "MyVideos"; };
 
index d5913de..bb352db 100644 (file)
@@ -53,6 +53,7 @@ void CVideoInfoTag::Reset()
   m_cast.clear();
   m_set.clear();
   m_setId.clear();
+  m_tags.clear();
   m_strFile.clear();
   m_strPath.clear();
   m_strIMDBNumber.clear();
@@ -174,6 +175,7 @@ bool CVideoInfoTag::Save(TiXmlNode *node, const CStdString &tag, bool savePathIn
   XMLUtils::SetStringArray(movie, "genre", m_genre);
   XMLUtils::SetStringArray(movie, "country", m_country);
   XMLUtils::SetStringArray(movie, "set", m_set);
+  XMLUtils::SetStringArray(movie, "tag", m_tags);
   XMLUtils::SetStringArray(movie, "credits", m_writingCredits);
   XMLUtils::SetStringArray(movie, "director", m_director);
   XMLUtils::SetDate(movie, "premiered", m_premiered);
@@ -291,6 +293,7 @@ void CVideoInfoTag::Archive(CArchive& ar)
 
     ar << m_set;
     ar << m_setId;
+    ar << m_tags;
     ar << m_strRuntime;
     ar << m_strFile;
     ar << m_strPath;
@@ -367,6 +370,7 @@ void CVideoInfoTag::Archive(CArchive& ar)
 
     ar >> m_set;
     ar >> m_setId;
+    ar >> m_tags;
     ar >> m_strRuntime;
     ar >> m_strFile;
     ar >> m_strPath;
@@ -443,6 +447,7 @@ void CVideoInfoTag::Serialize(CVariant& value)
   value["setid"] = CVariant(CVariant::VariantTypeArray);
   for (unsigned int i = 0; i < m_setId.size(); i++)
     value["setid"].push_back(m_setId[i]);
+  value["tags"] = m_tags;
   value["runtime"] = m_strRuntime;
   value["file"] = m_strFile;
   value["path"] = m_strPath;
@@ -656,6 +661,7 @@ void CVideoInfoTag::ParseNative(const TiXmlElement* movie, bool prioritise)
   }
 
   XMLUtils::GetStringArray(movie, "set", m_set, prioritise, g_advancedSettings.m_videoItemSeparator);
+  XMLUtils::GetStringArray(movie, "tag", m_tags, prioritise, g_advancedSettings.m_videoItemSeparator);
   XMLUtils::GetStringArray(movie, "studio", m_studio, prioritise, g_advancedSettings.m_videoItemSeparator);
   // artists
   node = movie->FirstChildElement("artist");
index 7db64ad..06c99b6 100644 (file)
@@ -97,6 +97,7 @@ public:
   typedef std::vector< SActorInfo >::const_iterator iCast;
   std::vector<std::string> m_set;
   std::vector<int> m_setId;
+  std::vector<std::string> m_tags;
   CStdString m_strRuntime;
   CStdString m_strFile;
   CStdString m_strPath;
index f0071ee..0d1f63b 100644 (file)
@@ -309,12 +309,6 @@ void CGUIDialogVideoInfo::SetMovie(const CFileItem *item)
           if (!thumb.empty())
             m_movieItem->SetProperty("seasonthumb", thumb);
         }
-        if (m_movieItem->GetVideoInfoTag()->m_iIdShow > -1)
-        {
-          string thumb = db.GetArtForItem(m_movieItem->GetVideoInfoTag()->m_iIdShow, "tvshow", "thumb");
-          if (!thumb.empty())
-            m_movieItem->SetProperty("tvshowthumb", thumb);
-        }
         db.Close();
       }
     }
index bf59784..1bfa29a 100644 (file)
@@ -875,7 +875,8 @@ bool CGUIWindowVideoBase::OnSelect(int iItem)
   CFileItemPtr item = m_vecItems->Get(iItem);
 
   CStdString path = item->GetPath();
-  if (!item->m_bIsFolder && path != "add" && path != "addons://more/video" && path.Left(19) != "newsmartplaylist://" && path.Left(14) != "newplaylist://")
+  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 CGUIMediaWindow::OnSelect(iItem);
@@ -1187,7 +1188,7 @@ void CGUIWindowVideoBase::GetContextButtons(int itemNumber, CContextButtons &but
             buttons.Add(CONTEXT_BUTTON_PLAY_PART, 20324);
         }
 
-        if (!m_vecItems->GetPath().IsEmpty() && !item->GetPath().Left(19).Equals("newsmartplaylist://")
+        if (!m_vecItems->GetPath().IsEmpty() && !item->GetPath().Left(19).Equals("newsmartplaylist://") && !item->GetPath().Left(9).Equals("newtag://")
             && !m_vecItems->IsSourcesPath())
         {
           buttons.Add(CONTEXT_BUTTON_QUEUE_ITEM, 13347);      // Add to Playlist
@@ -1229,7 +1230,9 @@ void CGUIWindowVideoBase::GetContextButtons(int itemNumber, CContextButtons &but
       {
         buttons.Add(CONTEXT_BUTTON_RESUME_ITEM, GetResumeString(*(item.get())));     // Resume Video
       }
-      if (item->HasVideoInfoTag() && !item->m_bIsFolder && m_vecItems->Size() > 1 && itemNumber < m_vecItems->Size()-1)
+      //if the item isn't a folder, is a member of a list rather than a single item
+      //and we're not on the last element of the list, then add the 'play from here' option
+      if (!item->m_bIsFolder && m_vecItems->Size() > 1 && itemNumber < m_vecItems->Size()-1)
       {
         buttons.Add(CONTEXT_BUTTON_PLAY_AND_QUEUE, 13412);
       }
index b88a1db..2f2e839 100644 (file)
@@ -51,6 +51,7 @@
 #include "utils/URIUtils.h"
 #include "utils/StringUtils.h"
 #include "TextureCache.h"
+#include "dialogs/GUIDialogKeyboard.h"
 
 using namespace XFILE;
 using namespace VIDEODATABASEDIRECTORY;
@@ -207,6 +208,14 @@ CStdString CGUIWindowVideoNav::GetQuickpathName(const CStdString& strPath) const
     return "MovieActors";
   else if (strPath.Equals("videodb://1/5/"))
     return "MovieDirectors";
+  else if (strPath.Equals("videodb://1/6/"))
+    return "MovieStudios";
+  else if (strPath.Equals("videodb://1/7/"))
+    return "MovieSets";
+  else if (strPath.Equals("videodb://1/8/"))
+    return "MovieCountries";
+  else if (strPath.Equals("videodb://1/9/"))
+    return "MovieTags";
   else if (strPath.Equals("videodb://1/"))
     return "Movies";
   else if (strPath.Equals("videodb://2/1/"))
@@ -341,6 +350,8 @@ bool CGUIWindowVideoNav::GetDirectory(const CStdString &strDirectory, CFileItemL
         items.SetContent("years");
       else if (node == NODE_TYPE_MUSICVIDEOS_ALBUM)
         items.SetContent("albums");
+      else if (node == NODE_TYPE_TAGS)
+        items.SetContent("tags");
       else
         items.SetContent("");
     }
@@ -352,6 +363,15 @@ bool CGUIWindowVideoNav::GetDirectory(const CStdString &strDirectory, CFileItemL
       if (!items.IsSourcesPath())
         LoadVideoInfo(items);
     }
+
+    if (items.GetPath() == "videodb://1/9/" && !items.Contains("newtag://movie"))
+    {
+      CFileItemPtr newTag(new CFileItem("newtag://movie", false));
+      newTag->SetLabel(g_localizeStrings.Get(20462));
+      newTag->SetLabelPreformated(true);
+      newTag->SetSpecialSort(SortSpecialOnTop);
+      items.Add(newTag);
+    }
   }
   return bResult;
 }
@@ -624,7 +644,8 @@ void CGUIWindowVideoNav::OnDeleteItem(CFileItemPtr pItem)
   {
     if (!pItem->GetPath().Equals("newsmartplaylist://video") &&
         !pItem->GetPath().Equals("special://videoplaylists/") &&
-        !pItem->GetPath().Equals("sources://video/"))
+        !pItem->GetPath().Equals("sources://video/") &&
+        !pItem->GetPath().Left(9).Equals("newtag://"))
       CGUIWindowVideoBase::OnDeleteItem(pItem);
   }
   else if (pItem->GetPath().Left(14).Equals("videodb://1/7/") &&
@@ -644,10 +665,28 @@ void CGUIWindowVideoNav::OnDeleteItem(CFileItemPtr pItem)
       for (int i=0;i<items.Size();++i)
         OnDeleteItem(items[i]);
 
-       CVideoDatabaseDirectory dir;
-       CQueryParams params;
-       dir.GetQueryParams(pItem->GetPath(),params);
-       m_database.DeleteSet(params.GetSetId());
+      CVideoDatabaseDirectory dir;
+      CQueryParams params;
+      dir.GetQueryParams(pItem->GetPath(),params);
+      m_database.DeleteSet(params.GetSetId());
+    }
+  }
+  else if (pItem->GetPath().Left(14).Equals("videodb://1/9/") &&
+           pItem->GetPath().size() > 14 && pItem->m_bIsFolder)
+  {
+    CGUIDialogYesNo* pDialog = (CGUIDialogYesNo*)g_windowManager.GetWindow(WINDOW_DIALOG_YES_NO);
+    pDialog->SetHeading(432);
+    CStdString strLabel;
+    strLabel.Format(g_localizeStrings.Get(433),pItem->GetLabel());
+    pDialog->SetLine(1, strLabel);
+    pDialog->SetLine(2, "");;
+    pDialog->DoModal();
+    if (pDialog->IsConfirmed())
+    {
+      CVideoDatabaseDirectory dir;
+      CQueryParams params;
+      dir.GetQueryParams(pItem->GetPath(), params);
+      m_database.DeleteTag(params.GetTagId(), "movie");
     }
   }
   else if (m_vecItems->GetPath().Equals(CUtil::VideoPlaylistsLocation()) ||
@@ -883,7 +922,9 @@ void CGUIWindowVideoNav::GetContextButtons(int itemNumber, CContextButtons &butt
             buttons.Add(CONTEXT_BUTTON_UPDATE_TVSHOW, 13349);
         }
         if (!item->IsPlugin() && !item->IsScript() && !item->IsLiveTV() && !item->IsAddonsPath() &&
-             item->GetPath() != "sources://video/" && item->GetPath() != "special://videoplaylists/")
+             item->GetPath() != "sources://video/" && item->GetPath() != "special://videoplaylists/" &&
+             item->GetPath().Left(19) != "newsmartplaylist://" && item->GetPath().Left(14) != "newplaylist://" &&
+             item->GetPath().Left(9) != "newtag://")
         {
           if (item->m_bIsFolder)
           {
@@ -924,6 +965,15 @@ void CGUIWindowVideoNav::GetContextButtons(int itemNumber, CContextButtons &butt
           buttons.Add(CONTEXT_BUTTON_DELETE, 646);
         }
 
+        if (item->GetPath().Left(14).Equals("videodb://1/9/") && item->GetPath().size() > 14 && item->m_bIsFolder) // tags
+        {
+          CStdString strLabelAdd; strLabelAdd.Format(g_localizeStrings.Get(20460), g_localizeStrings.Get(20342).c_str());
+          CStdString strLabelRemove; strLabelRemove.Format(g_localizeStrings.Get(20461), g_localizeStrings.Get(20342).c_str());
+          buttons.Add(CONTEXT_BUTTON_TAGS_ADD_ITEMS, strLabelAdd);
+          buttons.Add(CONTEXT_BUTTON_TAGS_REMOVE_ITEMS, strLabelRemove);
+          buttons.Add(CONTEXT_BUTTON_DELETE, 646);
+        }
+
         if (node == NODE_TYPE_ACTOR && !dir.IsAllItem(item->GetPath()) && item->m_bIsFolder)
         {
           if (m_vecItems->GetPath().Left(11).Equals("videodb://3")) // mvids
@@ -1195,6 +1245,74 @@ bool CGUIWindowVideoNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
       Update(m_vecItems->GetPath());
       return true;
     }
+  case CONTEXT_BUTTON_TAGS_ADD_ITEMS:
+    {
+      if (!item->GetPath().Left(10).Equals("videodb://"))
+        return false;
+      
+      std::string mediaType;
+      if (item->GetPath().Mid(9, 3).Equals("/1/"))
+        mediaType = "movie";
+      else
+        return false;
+
+      CFileItemList items;
+      CStdString localizedType = GetLocalizedType(mediaType);
+      CStdString strLabel; strLabel.Format(g_localizeStrings.Get(20464), localizedType.c_str());
+      if (!GetItemsForTag(strLabel, mediaType, items, item->GetVideoInfoTag()->m_iDbId))
+        return true;
+
+      CVideoDatabase videodb;
+      if (!videodb.Open())
+        return true;
+
+      for (int index = 0; index < items.Size(); index++)
+      {
+        if (!items[index]->HasVideoInfoTag() || items[index]->GetVideoInfoTag()->m_iDbId <= 0)
+          continue;
+
+        videodb.AddTagToItem(items[index]->GetVideoInfoTag()->m_iDbId, item->GetVideoInfoTag()->m_iDbId, mediaType);
+      }
+
+      // we need to clear any cached version of this tag's listing
+      items.SetPath(item->GetPath());
+      items.RemoveDiscCache(GetID());
+      return true;
+    }
+  case CONTEXT_BUTTON_TAGS_REMOVE_ITEMS:
+    {
+      if (!item->GetPath().Left(10).Equals("videodb://"))
+        return false;
+      
+      std::string mediaType;
+      if (item->GetPath().Mid(9, 3).Equals("/1/"))
+        mediaType = "movie";
+      else
+        return false;
+
+      CFileItemList items;
+      CStdString localizedType = GetLocalizedType(mediaType);
+      CStdString strLabel; strLabel.Format(g_localizeStrings.Get(20464), localizedType.c_str());
+      if (!GetItemsForTag(strLabel, mediaType, items, item->GetVideoInfoTag()->m_iDbId, false))
+        return true;
+
+      CVideoDatabase videodb;
+      if (!videodb.Open())
+        return true;
+
+      for (int index = 0; index < items.Size(); index++)
+      {
+        if (!items[index]->HasVideoInfoTag() || items[index]->GetVideoInfoTag()->m_iDbId <= 0)
+          continue;
+
+        videodb.RemoveTagFromItem(items[index]->GetVideoInfoTag()->m_iDbId, item->GetVideoInfoTag()->m_iDbId, mediaType);
+      }
+
+      // we need to clear any cached version of this tag's listing
+      items.SetPath(item->GetPath());
+      items.RemoveDiscCache(GetID());
+      return true;
+    }
   case CONTEXT_BUTTON_UPDATE_LIBRARY:
     {
       OnScan("");
@@ -1332,6 +1450,54 @@ bool CGUIWindowVideoNav::OnClick(int iItem)
     m_viewControl.SetSelectedItem(iItem);
     return true;
   }
+  else if (item->GetPath().Left(9).Equals("newtag://"))
+  {
+    // dont allow update while scanning
+    if (g_application.IsVideoScanning())
+    {
+      CGUIDialogOK::ShowAndGetInput(257, 0, 14057, 0);
+      return true;
+    }
+
+    //Get the new title
+    CStdString strTag;
+    if (!CGUIDialogKeyboard::ShowAndGetInput(strTag, g_localizeStrings.Get(20462), false))
+      return true;
+
+    CVideoDatabase videodb;
+    if (!videodb.Open())
+      return true;
+
+    CStdString mediaType = item->GetPath().Mid(9);
+    CStdString localizedType = GetLocalizedType(mediaType);
+    if (localizedType.empty())
+      return true;
+
+    if (!videodb.GetSingleValue("tag", "tag.idTag", videodb.PrepareSQL("tag.strTag = '%s' AND tag.idTag IN (SELECT taglinks.idTag FROM taglinks WHERE taglinks.media_type = '%s')", strTag.c_str(), mediaType.c_str())).empty())
+    {
+      CStdString strError; strError.Format(g_localizeStrings.Get(20463), strTag.c_str());
+      CGUIDialogOK::ShowAndGetInput(20462, strError, "", "");
+      return true;
+    }
+
+    int idTag = videodb.AddTag(strTag);
+    CFileItemList items;
+    CStdString strLabel; strLabel.Format(g_localizeStrings.Get(20464), localizedType.c_str());
+    if (GetItemsForTag(strLabel, mediaType, items, idTag))
+    {
+      for (int index = 0; index < items.Size(); index++)
+      {
+        if (!items[index]->HasVideoInfoTag() || items[index]->GetVideoInfoTag()->m_iDbId <= 0)
+          continue;
+
+        videodb.AddTagToItem(items[index]->GetVideoInfoTag()->m_iDbId, idTag, mediaType);
+      }
+    }
+
+    m_vecItems->RemoveDiscCache(GetID());
+    Update(m_vecItems->GetPath());
+    return true;
+  }
 
   return CGUIWindowVideoBase::OnClick(iItem);
 }
@@ -1354,6 +1520,8 @@ CStdString CGUIWindowVideoNav::GetStartFolder(const CStdString &dir)
     return "videodb://1/7/";
   else if (dir.Equals("MovieCountries"))
     return "videodb://1/8/";
+  else if (dir.Equals("MovieTags"))
+    return "videodb://1/9/";
   else if (dir.Equals("Movies"))
     return "videodb://1/";
   else if (dir.Equals("TvShowGenres"))
@@ -1405,6 +1573,7 @@ void CGUIWindowVideoNav::ApplyWatchedFilter(CFileItemList &items)
   if (node == NODE_TYPE_EPISODES
   ||  node == NODE_TYPE_SEASONS
   ||  node == NODE_TYPE_SETS
+  ||  node == NODE_TYPE_TAGS
   ||  node == NODE_TYPE_TITLE_MOVIES
   ||  node == NODE_TYPE_TITLE_TVSHOWS
   ||  node == NODE_TYPE_TITLE_MUSICVIDEOS
@@ -1443,3 +1612,59 @@ void CGUIWindowVideoNav::ApplyWatchedFilter(CFileItemList &items)
     }
   }
 }
+
+bool CGUIWindowVideoNav::GetItemsForTag(const CStdString &strHeading, const std::string &type, CFileItemList &items, int idTag /* = -1 */, bool showAll /* = true */)
+{
+  CVideoDatabase videodb;
+  if (!videodb.Open())
+    return false;
+
+  CFileItemList listItems;
+  bool result = false;
+  if (idTag <= 0)
+    result = videodb.GetMoviesNav("videodb://1/2/", listItems);
+  else
+  {
+    if (showAll)
+    {
+      CVideoDatabase::Filter filter;
+      filter.where = videodb.PrepareSQL("movieview.idMovie NOT IN (SELECT taglinks.idMedia FROM taglinks WHERE taglinks.idTag = %d AND taglinks.media_type = '%s')", idTag, type.c_str());
+      result = videodb.GetMoviesByWhere("videodb://1/2/", filter, listItems);
+    }
+    else
+      result = videodb.GetMoviesNav("videodb://1/9/", listItems, -1, -1, -1, -1, -1, -1, -1, idTag);
+  }
+
+  if (!result || listItems.Size() <= 0)
+    return false;
+
+  CGUIDialogSelect *dialog = (CGUIDialogSelect *)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT);
+  if (dialog == NULL)
+    return false;
+
+  listItems.Sort(SORT_METHOD_LABEL_IGNORE_THE, SortOrderAscending);
+
+  dialog->Reset();
+  dialog->SetMultiSelection(true);
+  dialog->SetHeading(strHeading);
+  dialog->SetItems(&listItems);
+  dialog->EnableButton(true, 186);
+  dialog->DoModal();
+
+  items.Copy(dialog->GetSelectedItems());
+  return items.Size() > 0;
+}
+
+CStdString CGUIWindowVideoNav::GetLocalizedType(const std::string &strType)
+{
+  if (strType == "movie")
+    return g_localizeStrings.Get(20342);
+  else if (strType == "tvshow")
+    return g_localizeStrings.Get(20343);
+  else if (strType == "episode")
+    return g_localizeStrings.Get(20359);
+  else if (strType == "musicvideo")
+    return g_localizeStrings.Get(20391);
+  else
+    return "";
+}
index 6ee0708..631851b 100644 (file)
@@ -67,5 +67,8 @@ protected:
 
   virtual CStdString GetQuickpathName(const CStdString& strPath) const;
 
+  bool GetItemsForTag(const CStdString &strHeading, const std::string &type, CFileItemList &items, int idTag = -1, bool showAll = true);
+  static CStdString GetLocalizedType(const std::string &strType);
+
   VECSOURCES m_shares;
 };
index 9c62c55..daa08f5 100644 (file)
       <MinimalRebuild>true</MinimalRebuild>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-      <PrecompiledHeader>
-      </PrecompiledHeader>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
     </ClCompile>
     <Link>
       <AdditionalDependencies>d3dx9.lib;%(AdditionalDependencies)</AdditionalDependencies>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release (DirectX)|Win32'">
     <ClCompile>
       <Optimization>Full</Optimization>
-      <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;DIRECTX_SPEKTRUM_EXPORTS;_WIN32PC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;DIRECTX_SPEKTRUM_EXPORTS;_WIN32PC;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
-      <PrecompiledHeader>
-      </PrecompiledHeader>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
       <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
     </ClCompile>
     <Link>
-      <AdditionalDependencies>winmm.lib;ws2_32.lib;d3dx9.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>d3dx9.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <ProgramDatabaseFile>$(OutDir)Spectrum_win32dx.pdb</ProgramDatabaseFile>
index 2fce99b..1d91a5b 100644 (file)
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <ClCompile>
       <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;PLUGIN_EXPORTS;HAS_DX;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <MinimalRebuild>true</MinimalRebuild>
       <ExceptionHandling>Sync</ExceptionHandling>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-      <PrecompiledHeader>
-      </PrecompiledHeader>
       <AssemblerOutput>AssemblyAndSourceCode</AssemblerOutput>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     <ClCompile>
       <IntrinsicFunctions>true</IntrinsicFunctions>
-      <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;PLUGIN_EXPORTS;HAS_DX;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
-      <PrecompiledHeader>
-      </PrecompiledHeader>
       <WarningLevel>Level3</WarningLevel>
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
     </ClCompile>
index b92833d..966a8d4 100644 (file)
@@ -95,7 +95,6 @@
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug (OpenGL)|Win32'">
     <ClCompile>
       <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..\..\..\lib\libSDL-WIN32\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;HAS_SDL_OPENGL;HAS_SDL;WAVEFORM_EXPORTS;_WIN32PC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <MinimalRebuild>true</MinimalRebuild>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release (OpenGL)|Win32'">
     <ClCompile>
-      <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;HAS_SDL_OPENGL;HAS_SDL;_USRDLL;WAVEFORM_EXPORTS;_WIN32PC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <PrecompiledHeader>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release (DirectX)|Win32'">
     <ClCompile>
-      <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;WAVEFORM_EXPORTS;_WIN32PC;_CRT_NONSTDC_NO_DEPRECATE%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <PrecompiledHeader>
index 8d398ed..02a2c36 100644 (file)
@@ -1425,7 +1425,7 @@ void CGUIMediaWindow::GetContextButtons(int itemNumber, CContextButtons &buttons
 
   // TODO: FAVOURITES Conditions on masterlock and localisation
   if (!item->IsParentFolder() && !item->GetPath().Equals("add") && !item->GetPath().Equals("newplaylist://") &&
-      !item->GetPath().Left(19).Equals("newsmartplaylist://"))
+      !item->GetPath().Left(19).Equals("newsmartplaylist://") && !item->GetPath().Left(9).Equals("newtag://"))
   {
     if (CFavourites::IsFavourite(item.get(), GetID()))
       buttons.Add(CONTEXT_BUTTON_ADD_FAVOURITE, 14077);     // Remove Favourite