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
$(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: \
# 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:
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;
};
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;
};
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;
};
--- /dev/null
+<?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>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<scraper framework="1.1" date="2012-06-09">
+ <NfoUrl dest="3">
+ <RegExp input="$$1" output="<url>http://musicbrainz.org/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings</url>" dest="3">
+ <expression>release/(.+)</expression>
+ </RegExp>
+ </NfoUrl>
+ <CreateAlbumSearchUrl dest="3">
+ <RegExp input="$$1" output="<url>http://search.musicbrainz.org/ws/2/release/?fmt=xml&query=release:"\1"%20AND%20artist:"$$2"</url>" 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="<results>\1</results>" dest="8">
+ <RegExp input="$$1" output="<entity><year>\5-\4-T#\6</year><artist>\3</artist><title>\2</title><url cache="mb-\1-album.xml">http://musicbrainz.org/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings</url></entity>" dest="5">
+ <expression repeat="yes">id="([^"]*)"><title>([^<]*)</title><status>Official</status><text-representation><language>[^<]*</language><script>[^<]*</script></text-representation><artist-credit><name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>([^<]*)</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>.*?</alias-list>)*</artist></name-credit>(?:<name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>[^<]*</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>.*?</alias-list>)*</artist></name-credit>)*</artist-credit><release-group\stype="Album"\sid="[^"]*">(?:<primary-type>[^<]*</primary-type>)*(?:<secondary-type-list><secondary-type>[^<]*</secondary-type></secondary-type-list>)*</release-group><date>(\d{4})[^<]*</date>(?:<country>)*([^<]*)?.*?<track-list\scount="(\d+)</expression>
+ </RegExp>
+ <RegExp input="$$1" output="<entity><year>\5-\4-T#\6</year><artist>\3</artist><title>\2</title><url cache="mb-\1-album.xml">http://musicbrainz.org/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings</url></entity>" dest="5+">
+ <expression repeat="yes">id="([^"]*)"><title>([^<]*)</title><status>Official</status><text-representation><language>[^<]*</language><script>[^<]*</script></text-representation><artist-credit><name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>([^<]*)</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>.*?</alias-list>)*</artist></name-credit>(?:<name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>[^<]*</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>.*?</alias-list>)*</artist></name-credit>)*</artist-credit><release-group(?:\stype="[^"]*")*\sid="[^"]*">(?:<primary-type>[^<]*</primary-type>)*(?:<secondary-type-list><secondary-type>[^<]*</secondary-type></secondary-type-list>)*</release-group><date>(\d{4})[^<]*</date>(?:<country>)*([^<]*)?.*?<track-list\scount="(\d+)</expression>
+ </RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </GetAlbumSearchResults>
+ <GetAlbumDetails dest="3">
+ <RegExp input="$$5" output="<details>\1</details>" dest="3">
+ <!--MBID - release-->
+ <RegExp input="$$1" output="\1" dest="3">
+ <expression>id="([^"]*)</expression>
+ </RegExp>
+ <!--MBID - release group-->
+ <RegExp input="$$1" output="\1" dest="4">
+ <expression><release-group type="[^"]*" id="([^"]*)"</expression>
+ </RegExp>
+ <!--Album title-->
+ <RegExp input="$$1" output="\1" dest="7">
+ <expression trim="1"><release id="[^"]*"><title>([^<]*)<</expression>
+ </RegExp>
+ <!--Artist name-->
+ <RegExp input="$$1" output="\1" dest="8">
+ <expression trim="1"><release id="[^"]*"><title>[^<]*<.*?<artist id="[^"]*"><name>([^<]*)<</expression>
+ </RegExp>
+ <RegExp input="$$3" output="<chain function="GetMBAlbumTitleByMBID">\1</chain>" dest="5">
+ <expression noclean="1">(.+)</expression>
+ </RegExp>
+ <RegExp input="$$3" output="<chain function="GetMBAlbumArtistByMBID">\1</chain>" dest="5+">
+ <expression noclean="1">(.+)</expression>
+ </RegExp>
+ <RegExp input="$$3" output="<chain function="GetMBAlbumLabelByMBID">\1</chain>" dest="5+">
+ <expression noclean="1">(.+)</expression>
+ </RegExp>
+ <RegExp input="$$3" output="<chain function="GetMBAlbumDateByMBID">\1</chain>" dest="5+">
+ <expression noclean="1">(.+)</expression>
+ </RegExp>
+ <RegExp input="$$3" output="<chain function="GetMBAlbumTracksByMBID">\1</chain>" dest="5+">
+ <expression noclean="1">(.+)</expression>
+ </RegExp>
+ <RegExp input="$INFO[albumreviewsource]" output="<url function="GetAMGAlbumReview" cache="mb-$$4-rg.xml">http://musicbrainz.org/ws/2/release-group/$$4?inc=url-rels</url>" dest="5+">
+ <expression>allmusic.com</expression>
+ </RegExp>
+ <RegExp input="$INFO[albumreviewsource]" output="<chain function="GetLastFMAlbumReviewByAlbumAndArtist">$$7::$$8::$$7::$$8</chain>" dest="5+">
+ <expression>last.fm</expression>
+ </RegExp>
+ <RegExp input="$INFO[albumreviewsource]" output="<url function="GetAmazonDEAlbumReview">http://musicbrainz.org/ws/2/release-group/$$4?inc=url-rels</url>" dest="5+">
+ <expression>amazon.de</expression>
+ </RegExp>
+ <RegExp input="$INFO[albumratingsource]" output="<chain function="GetMBAlbumRatingByMBID">$$3</chain>" dest="5+">
+ <expression>MusicBrainz</expression>
+ </RegExp>
+ <RegExp input="$INFO[albumratingsource]" output="<url function="GetAMGAlbumRating" cache="mb-$$4-rg.xml">http://musicbrainz.org/ws/2/release-group/$$4?inc=url-rels</url>" dest="5+">
+ <expression>allmusic.com</expression>
+ </RegExp>
+ <RegExp input="$INFO[albumstylessource]" output="<url function="GetAMGAlbumStyles" cache="mb-$$4-rg.xml">http://musicbrainz.org/ws/2/release-group/$$4?inc=url-rels</url>" dest="5+">
+ <expression>allmusic.com</expression>
+ </RegExp>
+ <RegExp input="$INFO[albummoodssource]" output="<url function="GetAMGAlbumMoods" cache="mb-$$4-rg.xml">http://musicbrainz.org/ws/2/release-group/$$4?inc=url-rels</url>" dest="5+">
+ <expression>allmusic.com</expression>
+ </RegExp>
+ <RegExp input="$INFO[albumthemessource]" output="<url function="GetAMGAlbumThemes" cache="mb-$$4-rg.xml">http://musicbrainz.org/ws/2/release-group/$$4?inc=url-rels</url>" dest="5+">
+ <expression>allmusic.com</expression>
+ </RegExp>
+ <RegExp conditional="fanarttvalbumthumbs" input="$$1" output="<chain function="GetFanartTvAlbumThumbsByMBID">$$4</chain>" dest="5+">
+ <expression noclean="1" />
+ </RegExp>
+ <RegExp conditional="allmusicalbumthumbs" input="$$1" output="<url function="GetAMGAlbumThumbs" cache="mb-$$4-rg.xml">http://musicbrainz.org/ws/2/release-group/$$4?inc=url-rels</url>" dest="5+">
+ <expression noclean="1" />
+ </RegExp>
+ <RegExp conditional="lastfmalbumthumbs" input="$$1" output="<chain function="GetLastFMAlbumThumbs">$$7::$$8::$$7::$$8</chain>" dest="5+">
+ <expression noclean="1" />
+ </RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </GetAlbumDetails>
+
+ <GetAMGAlbumReview dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="$$1" output="<chain function="GetAMGAlbumReviewByAMGID">\1</chain>" dest="2">
+ <expression noclean="1">allmusic.com/album/([^<]*)</expression>
+ </RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </GetAMGAlbumReview>
+
+ <GetAMGAlbumRating dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="$$1" output="<chain function="GetAMGAlbumRatingByAMGID">\1</chain>" dest="2">
+ <expression noclean="1">allmusic.com/album/([^<]*)</expression>
+ </RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </GetAMGAlbumRating>
+
+ <GetAMGAlbumStyles dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="$$1" output="<chain function="GetAMGAlbumStylesByAMGID">\1</chain>" dest="2">
+ <expression noclean="1">allmusic.com/album/([^<]*)</expression>
+ </RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </GetAMGAlbumStyles>
+
+ <GetAMGAlbumMoods dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="$$1" output="<chain function="GetAMGAlbumMoodsByAMGID">\1</chain>" dest="2">
+ <expression noclean="1">allmusic.com/album/([^<]*)</expression>
+ </RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </GetAMGAlbumMoods>
+
+ <GetAMGAlbumThemes dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="$$1" output="<chain function="GetAMGAlbumThemesByAMGID">\1</chain>" dest="2">
+ <expression noclean="1">allmusic.com/album/([^<]*)</expression>
+ </RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </GetAMGAlbumThemes>
+
+ <GetAMGAlbumThumbs dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="$$1" output="<chain function="GetAMGAlbumThumbsByAMGID">\1</chain>" dest="2">
+ <expression noclean="1">allmusic.com/album/([^<]*)</expression>
+ </RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </GetAMGAlbumThumbs>
+
+ <GetAmazonDEAlbumReview dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="$$1" output="<chain function="GetAmazonDEAlbumReviewByASIN">\1</chain>" dest="2">
+ <expression noclean="1">http://www.amazon.de/gp/product/([^<]*)</expression>
+ </RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </GetAmazonDEAlbumReview>
+
+</scraper>
--- /dev/null
+[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
--- /dev/null
+<?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>
--- /dev/null
+<?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>
+++ /dev/null
-<?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>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<scraper framework="1.1" date="2010-10-16">
- <NfoUrl dest="3">
- <RegExp input="$$1" output="<url>http://www.\1/review</url>" dest="3">
- <expression>(allmusic.com/album/.*)</expression>
- </RegExp>
- </NfoUrl>
- <CreateAlbumSearchUrl dest="3">
- <RegExp input="$$1" output="<url>http://www.allmusic.com/search/album/\1</url>" dest="3">
- <expression />
- </RegExp>
- </CreateAlbumSearchUrl>
- <GetAlbumSearchResults dest="8">
- <RegExp input="$$5" output="<results>\1</results>" dest="8">
- <RegExp input="$$1" output="<entity><year>\4</year><artist>\3</artist><title>\2</title><url cache="am-\3-\2-album.html">http://www.allmusic.com/album/\1/review</url></entity>" dest="5">
- <expression repeat="yes" noclean="1,2,3"><td class="text-center">[^<]*<a href.*?www.allmusic.com/album/([^"]*)">([^<]*).*?<td>([^<]*)</td>.*?<td>.*?<td>([^<]*)</expression>
- </RegExp>
- <RegExp input="$$1" output="<entity><year>\4</year><artist>\3</artist><title>\2</title><url cache="am-\3-\2-album.html">http://www.allmusic.com/album/\1/review</url></entity>" dest="5+">
- <expression repeat="yes" noclean="1,2,3"><td class="text-center">[^<]*</td>.*?www.allmusic.com/album/([^"]*)">([^<]*).*?<td>([^<]*)</td>.*?<td>.*?<td>([^<]*)</expression>
- </RegExp>
- <expression noclean="1" />
- </RegExp>
- </GetAlbumSearchResults>
- <GetAlbumDetails dest="3">
- <RegExp input="$$5" output="<details>\1</details>" dest="3">
- <RegExp input="$$1" output="\1" dest="2">
- <expression noclean="1"><h1 class="title">([^<]*)</h1></expression>
- </RegExp>
- <RegExp input="$$1" output="\1" dest="3">
- <expression noclean="1"><a href="http://www.allmusic.com/album/([^"]*)">Overview<</expression>
- </RegExp>
- <RegExp conditional="lastfmalbumthumbs" input="$$1" output="<chain function="GetLastFMAlbumThumbs">\1::\2</chain>" dest="5+">
- <expression trim="1,2" encode="1,2"><meta name="title" content="([^-]*)- ([^<]*)" /></expression>
- </RegExp>
- <RegExp input="$$1" output="<url cache="am-$$3-$$2-album.html" function="ParseAMGAlbum">http://www.allmusic.com/album/\1/review</url>" dest="5+">
- <expression noclean="1"><a href="http://www.allmusic.com/album/([^"]*)">Overview<</expression>
- </RegExp>
- <RegExp input="$$1" output="<url cache="am-$$3-$$2-album.html" function="GetAMGReview">http://www.allmusic.com/album/\1/review</url>" dest="5+">
- <expression noclean="1"><a href="http://www.allmusic.com/album/([^"]*)">Overview<</expression>
- </RegExp>
- <expression noclean="1" />
- </RegExp>
- </GetAlbumDetails>
-</scraper>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
- <string id="30000">Вземи снимки за албум от Allmusic.com</string>
- <string id="30001">Вземи снимки за албум от Last.fm</string>
-</strings>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
- <string id="30000">从Allmusic.com获取专辑图片</string>
- <string id="30001">从Last.fm获取专辑图片</string>
-</strings>
+++ /dev/null
-<?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>
+++ /dev/null
-<?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>
+++ /dev/null
-<?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>
+++ /dev/null
-<?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>
+++ /dev/null
-<?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>
+++ /dev/null
-<?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>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
- <string id="30000">Allmusic.com 에서 앨범 사진 가져오기</string>
- <string id="30001">Last.fm 에서 앨범 사진 가져오기</string>
-</strings>
+++ /dev/null
-<?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>
+++ /dev/null
-<?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>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<strings>
- <string id="30000">Получать миниатюры альбомов с Allmusic.com</string>
- <string id="30001">Получать миниатюры альбомов с Last.fm</string>
-</strings>
+++ /dev/null
-<?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>
+++ /dev/null
-<?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
+++ /dev/null
-<?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>
+++ /dev/null
-<?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>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<scraper framework="1.1" date="2010-10-16">
- <NfoUrl dest="3">
- <RegExp input="$$1" output="<url>http://www.\1</url>" dest="3">
- <expression>(allmusic.com/artist/.*)</expression>
- </RegExp>
- </NfoUrl>
- <CreateArtistSearchUrl dest="3">
- <RegExp input="$$1" output="<url>http://www.allmusic.com/search/artist/\1</url>" dest="3">
- <expression/>
- </RegExp>
- </CreateArtistSearchUrl>
- <GetArtistSearchResults dest="8">
- <RegExp input="$$5" output="<results>\1</results>" dest="8">
- <RegExp input="$$1" output="<entity><title>\1</title><url cache="am-\2-artist.html">http://www.allmusic.com/artist/\2</url></entity>" dest="9">
- <expression noclean="1"><meta name="title" content="([^"]*)".*?<a href="http://www.allmusic.com/artist/([^/]*)/credits"</expression>
- </RegExp>
- <RegExp input="$$9" output="\1" dest="5">
- <expression noclean="1">(.+)</expression>
- </RegExp>
- <RegExp input="$$1" output="<entity><title>\1</title><url cache="am-\2-artist.html">http://www.allmusic.com/artist/\2</url></entity>" dest="9">
- <expression noclean="1"><meta name="title" content="([^"]*)".*?<a href="http://www.allmusic.com/artist/([^/]*)/biography"</expression>
- </RegExp>
- <RegExp input="$$9" output="\1" dest="5">
- <expression noclean="1">(.+)</expression>
- </RegExp>
- <RegExp input="$$1" output="<entity><title>\1</title><url cache="am-\2-artist.html">http://www.allmusic.com/artist/\2</url></entity>" dest="9">
- <expression noclean="1"><meta name="title" content="([^"]*)".*?<a href="http://www.allmusic.com/artist/([^/]*)/discography"</expression>
- </RegExp>
- <RegExp input="$$9" output="\1" dest="5">
- <expression noclean="1">(.+)</expression>
- </RegExp>
- <RegExp input="$$1" output="<entity><title>\2</title><genre>\3</genre><year>\4</year><url cache="am-\1-artist.html">http://www.allmusic.com/artist/\1</url></entity>" dest="5+">
- <expression repeat="yes" noclean="1,2"><td><a href="http://www.allmusic.com/artist/([^"]*)">([^<]*)</a></td>[^>]*>([^<]*)</td>[^>]*>([^<]*)</td></expression>
- </RegExp>
- <expression noclean="1"/>
- </RegExp>
- </GetArtistSearchResults>
- <GetArtistDetails dest="3">
- <RegExp input="$$5" output="<details>\1</details>" dest="3">
- <RegExp input="$$1" output="\1" dest="7">
- <expression noclean="1"><meta name="title" content="([^"]*)</expression>
- </RegExp>
- <RegExp input="$$1" output="\1" dest="8">
- <expression>http://www.allmusic.com/artist/([^&"/]*)/</expression>
- </RegExp>
- <RegExp input="$$7" conditional="htbthumbs" output="<chain function="GetHTBThumbs">\1</chain>" dest="5">
- <expression/>
- </RegExp>
- <RegExp input="$$2" conditional="lastfmartistthumbs" output="<chain function="GetLastFMArtistThumbsByName">\1</chain>" dest="5+">
- <expression/>
- </RegExp>
- <RegExp input="$$8" output="<url cache="am-\1-artist.html" function="ParseAMGArtist">http://www.allmusic.com/artist/\1</url>" dest="5+">
- <expression/>
- </RegExp>
- <RegExp input="$$7" conditional="htbfanart" output="<chain function="GetHTBFanart">\1</chain>" dest="5+">
- <expression/>
- </RegExp>
- <RegExp input="$$8" output="<url cache="am-\1-biog.html" function="GetAMGBiography">http://www.allmusic.com/artist/\1/biography</url>" dest="5+">
- <expression/>
- </RegExp>
- <RegExp input="$$8" output="<url cache="am-\1-discog.html" function="GetAMGDiscography">http://www.allmusic.com/artist/\1/discography</url>" dest="5+">
- <expression/>
- </RegExp>
- <expression noclean="1"/>
- </RegExp>
- </GetArtistDetails>
-</scraper>
+++ /dev/null
-<?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>
+++ /dev/null
-<?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>
+++ /dev/null
-<?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>
+++ /dev/null
-<?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>
+++ /dev/null
-<?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>
+++ /dev/null
-<?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>
+++ /dev/null
-<?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>
+++ /dev/null
-<?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>
+++ /dev/null
-<?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>
+++ /dev/null
-<?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>
+++ /dev/null
-<?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>
+++ /dev/null
-<?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>
+++ /dev/null
-<?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>
+++ /dev/null
-<?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
+++ /dev/null
-<?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>
--- /dev/null
+<?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>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<scraper framework="1.1" date="2012-05-28">
+ <NfoUrl dest="3">
+ <RegExp input="$$1" output="<url>http://www.musicbrainz.org/ws/2/artist/\1?inc=url-rels</url>" dest="3">
+ <expression>http://musicbrainz.org/artist/(.+)</expression>
+ </RegExp>
+ </NfoUrl>
+ <CreateArtistSearchUrl dest="3">
+ <RegExp input="$$1" output="<url>http://search.musicbrainz.org/ws/2/artist/?fmt=xml&query=artist:"$$4"&limit=100</url>" dest="3">
+ <RegExp input="$$1" output="\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="<results>\1</results>" dest="8">
+ <RegExp input="$$1" output="<entity><title>\2</title><genre>\7</genre><url cache="mb-\1-artist.xml">http://www.musicbrainz.org/ws/2/artist/\1?inc=url-rels</url></entity>" dest="9">
+ <expression repeat="yes" noclean="1">artist ext:score="[^"]*"(?:\stype="[^"]*")* id="([^"]*)"><name>([^<]*)</name>(<sort-name>[^<]*</sort-name>)?(<gender>[^<]*</gender>)?(<country>[^<]*</country>)?(<disambiguation>([^<]*))?</expression>
+ </RegExp>
+ <RegExp input="$$9" output="\1" dest="5">
+ <expression noclean="1">(.+)</expression>
+ </RegExp>
+ <expression noclean="1"/>
+ </RegExp>
+ </GetArtistSearchResults>
+ <GetArtistDetails dest="3" clearbuffers="no">
+ <RegExp input="$$5" output="<details>\1</details>" dest="3">
+ <!--MBID - Artist-->
+ <RegExp input="$$1" output="\1" dest="8">
+ <expression noclean="1"><artist(?:\stype="[^"]*")* id="([^"]*)"><name>([^<]*)</expression>
+ </RegExp>
+ <!--AMGID - Artist-->
+ <RegExp input="$$1" output="\2" dest="9">
+ <expression noclean="1">><relation type="allmusic"><target>http://(www.)?allmusic.com/artist/([^<]*)</expression>
+ </RegExp>
+ <RegExp input="$$8" conditional="fanarttvthumbs" output="<chain function="GetFanartTvArtistThumbsByMBID">\1</chain>" dest="5+">
+ <expression/>
+ </RegExp>
+ <RegExp input="$$8" conditional="htbthumbs" output="<chain function="GetHTBThumbsByMBID">\1</chain>" dest="5+">
+ <expression/>
+ </RegExp>
+ <RegExp input="$$8" conditional="lastfmartistthumbs" output="<chain function="GetLastFMArtistThumbsByMBID">\1</chain>" dest="5+">
+ <expression/>
+ </RegExp>
+ <RegExp input="$$8" conditional="fanarttvfanart" output="<chain function="GetFanartTvArtistFanartsByMBID">\1</chain>" dest="5+">
+ <expression/>
+ </RegExp>
+ <RegExp input="$$8" conditional="htbfanart" output="<chain function="GetHTBFanartByMBID">\1</chain>" dest="5+">
+ <expression/>
+ </RegExp>
+ <RegExp input="$$9" output="<chain function="GetAMGData">\1</chain>" dest="5+">
+ <expression noclean="1">(.+)</expression>
+ </RegExp>
+ <RegExp input="$$9" output="<chain function="AMGFallback">\1</chain>" dest="5+">
+ <expression noclean="1">^$</expression>
+ </RegExp>
+ <RegExp input="$INFO[discogsource]" output="<chain function="GetMBDiscographyByMBID">$$8</chain>" dest="5+">
+ <expression>MusicBrainz</expression>
+ </RegExp>
+ <RegExp input="$INFO[lifespansource]" output="<chain function="GetMBLafeSpanByMBID">$$8</chain>" dest="5+">
+ <expression>MusicBrainz</expression>
+ </RegExp>
+ <RegExp input="$INFO[biogsource]" output="<chain function="GetLastFMBiographyByMBID">$$8</chain>" dest="5+">
+ <expression>last.fm</expression>
+ </RegExp>
+ <RegExp input="$INFO[discogsource]" output="<chain function="GetLastFMDiscographyByMBID">$$8</chain>" dest="5+">
+ <expression>last.fm</expression>
+ </RegExp>
+ <RegExp input="$INFO[genressource]" output="<chain function="GetLastFMArtistGenresByMBID">$$8</chain>" dest="5+">
+ <expression>last.fm</expression>
+ </RegExp>
+ <RegExp input="$INFO[stylessource]" output="<chain function="GetLastFMArtistStylesByMBID">$$8</chain>" dest="5+">
+ <expression>last.fm</expression>
+ </RegExp>
+ <expression noclean="1"/>
+ </RegExp>
+ </GetArtistDetails>
+
+ <GetAMGData dest="5" clearbuffers="no">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="$$1" output="\1" dest="9">
+ <expression/>
+ </RegExp>
+ <RegExp input="" output="" dest="2">
+ <expression />
+ </RegExp>
+ <RegExp input="$INFO[discogsource]" output="<chain function="GetAMGDiscographyByAMGID">$$9</chain>" dest="2">
+ <expression>allmusic.com</expression>
+ </RegExp>
+ <RegExp input="$INFO[lifespansource]" output="<chain function="GetAMGArtistLifeSpanByAMGID">$$9</chain>" dest="2+">
+ <expression>allmusic.com</expression>
+ </RegExp>
+ <RegExp input="$INFO[biogsource]" output="<chain function="GetAMGBiographyByAMGID">$$9</chain>" dest="2+">
+ <expression>allmusic.com</expression>
+ </RegExp>
+ <RegExp input="$INFO[genressource]" output="<chain function="GetAMGArtistGenresByAMGID">$$9</chain>" dest="2+">
+ <expression>allmusic.com</expression>
+ </RegExp>
+ <RegExp input="$INFO[stylessource]" output="<chain function="GetAMGArtistStylesByAMGID">$$9</chain>" dest="2+">
+ <expression>allmusic.com</expression>
+ </RegExp>
+ <RegExp input="$INFO[moodssource]" output="<chain function="GetAMGArtistMoodsByAMGID">$$9</chain>" dest="2+">
+ <expression>allmusic.com</expression>
+ </RegExp>
+ <RegExp input="$INFO[yearsasource]" output="<chain function="GetAMGArtistYearsActiveByAMGID">$$9</chain>" dest="2+">
+ <expression>allmusic.com</expression>
+ </RegExp>
+ <RegExp input="$$9" conditional="allmusicartistthumbs" output="<chain function="GetAMGArtistThumbsByAMGID">\1</chain>" dest="2+">
+ <expression/>
+ </RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </GetAMGData>
+
+ <AMGFallback dest="5" clearbuffers="no">
+ <RegExp input="$$11" output="<details>\1</details>" dest="5">
+ <RegExp input="$INFO[biogfbsource]" output="<chain function="GetLastFMBiographyByMBID">$$8</chain>" dest="11+">
+ <expression>last.fm</expression>
+ </RegExp>
+ <RegExp input="$INFO[discogfbsource]" output="<chain function="GetLastFMDiscographyByMBID">$$8</chain>" dest="11+">
+ <expression>last.fm</expression>
+ </RegExp>
+ <RegExp input="$INFO[discogfbsource]" output="<chain function="GetMBDiscographyByMBID">$$8</chain>" dest="11+">
+ <expression>MusicBrainz</expression>
+ </RegExp>
+ <RegExp input="$INFO[genresfbsource]" output="<chain function="GetLastFMArtistGenresByMBID">$$8</chain>" dest="11+">
+ <expression>last.fm</expression>
+ </RegExp>
+ <RegExp input="$INFO[stylesfbsource]" output="<chain function="GetLastFMArtistStylesByMBID">$$8</chain>" dest="11+">
+ <expression>last.fm</expression>
+ </RegExp>
+ <RegExp input="$INFO[lifespanfbsource]" output="<chain function="GetMBLafeSpanByMBID">$$8</chain>" dest="11+">
+ <expression>MusicBrainz</expression>
+ </RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </AMGFallback>
+
+</scraper>
--- /dev/null
+[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
--- /dev/null
+<?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>
--- /dev/null
+<?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>
<?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"/>
<scraperfunctions>
- <GetAMGDiscography dest="5">
- <RegExp input="$$2$$3" output="<details>\1</details>" dest="5">
- <RegExp input="$$1" output="<album><year>\1</year><title>\2</title><label>\3</label></album>" dest="2">
- <expression repeat="yes" clear="yes" noclean="1,3,4"><td class="sorted cell">([^<]*)</td>.*?<td class="cell"><a href="[^>]*>([^<]*)<.*?<td class="cell">([^<]*)<</expression>
+ <GetAMGDiscographyByAMGID dest="5" clearbuffers="no">
+ <RegExp input="$$1" output="<details><url cache="am-\1-artist.html" function="ParseAMGDiscography">http://www.allmusic.com/artist/\1</url></details>" dest="5">
+ <expression clear="yes" noclean="1"/>
+ </RegExp>
+ </GetAMGDiscographyByAMGID>
+ <ParseAMGDiscography dest="5" clearbuffers="no">
+ <RegExp input="$$3" output="<details>\1</details>" dest="5">
+ <RegExp input="" output="" dest="3">
+ <expression />
+ </RegExp>
+ <RegExp input="$$1" output="<album><year>\1</year><title>\2</title><label>\3</label></album>" dest="3">
+ <expression repeat="yes" clear="yes" trim="1"><td class="year[^"]*"(?:\stitle="[^"]*")*\s*data-sort-value="[^>]*>([^<]*)</td>[^<]*<td class=".*?title="([^"]*)</expression>
+ </RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </ParseAMGDiscography>
+
+ <GetAMGBiographyByAMGID dest="5" clearbuffers="no">
+ <RegExp input="$$1" output="<details><url cache="am-\1-artist.html" function="ParseAMGBiography">http://www.allmusic.com/artist/\1</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetAMGBiographyByAMGID>
+ <ParseAMGBiography dest="5" clearbuffers="no">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="" output="" dest="2">
+ <expression />
</RegExp>
- <RegExp input="$$2" output="\1&amp;\2" dest="3">
- <expression repeat="yes" noclean="1,2">(.*?)&(.+)</expression>
+ <RegExp input="$$1" output="\1" dest="11">
+ <expression clear="yes">" itemprop="description">(.*?)div class="advertisement leaderboard"></expression>
</RegExp>
- <RegExp input="$$3" output="" dest="2">
+ <RegExp input="$$11" output="$$12" dest="2">
+ <RegExp input="$INFO[biogfbsource]" output="<chain function="GetLastFMFallbackBiographyByMBID">$$8</chain>" dest="12">
+ <expression>last.fm</expression>
+ </RegExp>
+ <expression>^$</expression>
+ </RegExp>
+ <RegExp input="$$11" output="<biography>\1</biography>" dest="2">
<expression>(.+)</expression>
</RegExp>
- <expression noclean="1" />
+ <expression noclean="1"/>
+ </RegExp>
+ </ParseAMGBiography>
+
+ <GetAMGFallbackBiographyByAMGID dest="5" clearbuffers="no">
+ <RegExp input="$$1" output="<details><url cache="am-\1-artist.html" function="ParseAMGFallbackBiography">http://www.allmusic.com/artist/\1</url></details>" dest="5">
+ <expression noclean="1"/>
</RegExp>
- </GetAMGDiscography>
- <GetAMGBiography dest="5">
+ </GetAMGFallbackBiographyByAMGID>
+ <ParseAMGFallbackBiography dest="5" clearbuffers="no">
<RegExp input="$$2" output="<details>\1</details>" dest="5">
- <RegExp input="$$1" output="<biography>Fetching artist biography from allmusic.com is not possible due to copyright reasons.</biography>" dest="2">
- <expression clear="yes">Biography</h2>.*?</p>(.*?)</p></expression>
+ <RegExp input="" output="" dest="2">
+ <expression />
+ </RegExp>
+ <RegExp input="$$1" output="\1" dest="2">
+ <expression clear="yes">" itemprop="description">(.*?)div class="advertisement leaderboard"></expression>
</RegExp>
<expression noclean="1"/>
</RegExp>
- </GetAMGBiography>
- <GetAMGReview dest="5">
+ </ParseAMGFallbackBiography>
+
+ <GetAMGArtistNameByAMGID dest="5">
+ <RegExp input="$$1" output="<details><url cache="am-\1-artist.html" function="ParseAMGArtistName">http://www.allmusic.com/artist/\1</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetAMGArtistNameByAMGID>
+ <ParseAMGArtistName dest="5">
<RegExp input="$$2" output="<details>\1</details>" dest="5">
- <RegExp input="$$1" output="<review>Fetching album review from allmusic.com is not possible due to copyright reasons.</review>" dest="2">
- <expression><h2 class="title">Review</h2>.*?</p>(.*?)</p></expression>
+ <RegExp input="$$1" output="<name>\1</name>" dest="2">
+ <expression noclean="1">http://schema.org/MusicGroup">[^<]*<span itemprop="name">([^<]*)</span></expression>
</RegExp>
- <expression noclean="1" />
+ <expression noclean="1"/>
</RegExp>
- </GetAMGReview>
- <ParseAMGArtist dest="3">
- <RegExp input="$$5" output="<details>\1</details>" dest="3">
- <RegExp input="$$1" output="<name>\1</name>" dest="5">
- <expression noclean="1"><meta name="title" content="([^"]*)</expression>
+ </ParseAMGArtistName>
+
+ <GetAMGArtistLifeSpanByAMGID dest="5" clearbuffers="no">
+ <RegExp input="$$1" output="<details><url cache="am-\1-artist.html" function="ParseAMGArtistLifeSpan">http://www.allmusic.com/artist/\1</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetAMGArtistLifeSpanByAMGID>
+ <ParseAMGArtistLifeSpan dest="5" clearbuffers="no">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="" output="" dest="2">
+ <expression />
+ </RegExp>
+ <RegExp input="" output="" dest="11">
+ <expression />
+ </RegExp>
+ <RegExp input="$$1" output="<born>\1 \2</born>" dest="11+">
+ <expression trim="1,2"><dt>\s*Born[^>]*>[^>]*>[^>]*>(.*?\d{4})\s*([^<]*)?</expression>
+ </RegExp>
+ <RegExp input="$$1" output="<died>\1 \2</died>" dest="11+">
+ <expression trim="1,2"><dt>\s*Died[^>]*>[^>]*>[^>]*>(.*?\d{4})\s*([^<]*)?</expression>
+ </RegExp>
+ <RegExp input="$$1" output="<formed>\1</formed>" dest="11+">
+ <expression trim="1,2"><dt>\s*Formed[^>]*>[^>]*>[^>]*>(.*?\d{4})\s*([^<]*)?</expression>
+ </RegExp>
+ <RegExp input="$$1" output="<disbanded>\1</disbanded>" dest="11+">
+ <expression trim="1,2"><dt>\s*Disbanded[^>]*>[^>]*>[^>]*>(.*?\d{4})\s*([^<]*)?</expression>
+ </RegExp>
+ <RegExp input="$$11" output="$$12" dest="2">
+ <RegExp input="$INFO[lifespanfbsource]" output="<chain function="GetMBFallbackLafeSpanByMBID">$$8</chain>" dest="12">
+ <expression>MusicBrainz</expression>
+ </RegExp>
+ <expression>^$</expression>
+ </RegExp>
+ <RegExp input="$$11" output="$$11" dest="2">
+ <expression noclean="1"><(?:born|formed)*>(.+)</(?:born|formed)*></expression>
</RegExp>
- <RegExp input="$$1" output="<born>\1</born>" dest="5+">
- <expression><h3>Born[^>]*>[^>]*>(.*?)</p></expression>
+ <expression noclean="1"/>
+ </RegExp>
+ </ParseAMGArtistLifeSpan>
+
+ <GetAMGFallbackArtistLifeSpanByAMGID dest="5" clearbuffers="no">
+ <RegExp input="$$1" output="<details><url cache="am-\1-artist.html" function="ParseAMGFallbackArtistLifeSpan">http://www.allmusic.com/artist/\1</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetAMGFallbackArtistLifeSpanByAMGID>
+ <ParseAMGFallbackArtistLifeSpan dest="5" clearbuffers="no">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="" output="" dest="2">
+ <expression />
</RegExp>
- <RegExp input="$$1" output="<born>\1</born>" dest="5+">
- <expression><h3>Birth[^>]*>[^>]*>(.*?)</p></expression>
+ <RegExp input="$$1" output="<born>\1 \2</born>" dest="2">
+ <expression trim="1,2"><dt>\s*Born[^>]*>[^>]*>[^>]*>(.*?\d{4})\s*([^<]*)?</expression>
+ </RegExp>
+ <RegExp input="$$1" output="<died>\1 \2</died>" dest="2+">
+ <expression trim="1,2"><dt>\s*Died[^>]*>[^>]*>[^>]*>(.*?\d{4})\s*([^<]*)?</expression>
+ </RegExp>
+ <RegExp input="$$1" output="<formed>\1</formed>" dest="2">
+ <expression trim="1,2"><dt>\s*Formed[^>]*>[^>]*>[^>]*>(.*?\d{4})\s*([^<]*)?</expression>
+ </RegExp>
+ <RegExp input="$$1" output="<disbanded>\1</disbanded>" dest="2+">
+ <expression trim="1,2"><dt>\s*Disbanded[^>]*>[^>]*>[^>]*>(.*?\d{4})\s*([^<]*)?</expression>
+ </RegExp>
+ <expression noclean="1"/>
+ </RegExp>
+ </ParseAMGFallbackArtistLifeSpan>
+
+ <GetAMGArtistYearsActiveByAMGID dest="5" clearbuffers="no">
+ <RegExp input="$$1" output="<details><url cache="am-\1-artist.html" function="ParseAMGArtistYearsActive">http://www.allmusic.com/artist/\1</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetAMGArtistYearsActiveByAMGID>
+ <ParseAMGArtistYearsActive dest="5" clearbuffers="no">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="" output="" dest="2">
+ <expression />
</RegExp>
- <RegExp input="$$1" output="<died>\1</died>" dest="5+">
- <expression><h3>Died[^>]*>[^>]*>(.*?)</p></expression>
+ <RegExp input="$$1" output="<yearsactive>\1</yearsactive>" dest="2">
+ <expression trim="1" noclean="1"><dd class="active">([^<]*)<</expression>
</RegExp>
- <RegExp input="$$1" output="<formed>\1</formed>" dest="5+">
- <expression><h3>Formed[^>]*>[^>]*>(.*?)</p></expression>
+ <expression noclean="1" />
+ </RegExp>
+ </ParseAMGArtistYearsActive>
+
+ <GetAMGArtistGenresByAMGID dest="5" clearbuffers="no">
+ <RegExp input="$$1" output="<details><url cache="am-\1-artist.html" function="ParseAMGArtistGenres">http://www.allmusic.com/artist/\1</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetAMGArtistGenresByAMGID>
+ <ParseAMGArtistGenres dest="5" clearbuffers="no">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="" output="" dest="2">
+ <expression />
</RegExp>
- <RegExp input="$$1" output="<disbanded>\1</disbanded>" dest="5+">
- <expression><h3>Disbanded[^>]*>[^>]*>(.*?)</p></expression>
+ <RegExp input="" output="" dest="6">
+ <expression />
</RegExp>
<RegExp input="$$1" output="\1" dest="6">
- <expression noclean="1"><h3>Years Active</h3>(.*?)</p></expression>
+ <expression noclean="1"><dt>Genres</dt>(.*?)</dd></expression>
+ </RegExp>
+ <RegExp input="$$6" output="<genre>\2</genre>" dest="11">
+ <expression repeat="yes" noclean="1"><li><a href="/genre/[^"]*">(<strong>)?([^<]*)</expression>
</RegExp>
- <RegExp input="$$6" output="\1's/" dest="7+">
- <expression repeat="yes"><span class="active">([0-9]+)</span></expression>
+ <RegExp input="$$11" output="$$12" dest="2">
+ <RegExp input="$INFO[genresfbsource]" output="<chain function="GetLastFMFallbackArtistGenresByMBID">$$8</chain>" dest="12">
+ <expression>last.fm</expression>
+ </RegExp>
+ <expression><genre></genre></expression>
</RegExp>
- <RegExp input="$$7" output="<yearsactive>\1</yearsactive>" dest="5+">
- <expression noclean="1">(.+)/</expression>
+ <RegExp input="$$11" output="$$11" dest="2">
+ <expression><genre>(.+)</genre></expression>
+ </RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </ParseAMGArtistGenres>
+
+ <GetAMGFallbackArtistGenresByAMGID dest="5" clearbuffers="no">
+ <RegExp input="$$1" output="<details><url cache="am-\1-artist.html" function="ParseAMGFallbackArtistGenres">http://www.allmusic.com/artist/\1</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetAMGFallbackArtistGenresByAMGID>
+ <ParseAMGFallbackArtistGenres dest="5" clearbuffers="no">
+ <RegExp input="$$2" output="<details>\1</details>" 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"><h3>Genres</h3>(.*?)</div></expression>
+ <expression noclean="1"><dt>Genres</dt>(.*?)</dd></expression>
+ </RegExp>
+ <RegExp input="$$6" output="<genre>\2</genre>" dest="2">
+ <expression repeat="yes" noclean="1"><li><a href="/genre/[^"]*">(<strong>)?([^<]*)</expression>
+ </RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </ParseAMGFallbackArtistGenres>
+
+ <GetAMGArtistStylesByAMGID dest="5" clearbuffers="no">
+ <RegExp input="$$1" output="<details><url cache="am-\1-artist.html" function="ParseAMGArtistStyles">http://www.allmusic.com/artist/\1</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetAMGArtistStylesByAMGID>
+ <ParseAMGArtistStyles dest="5" clearbuffers="no">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="" output="" dest="2">
+ <expression />
</RegExp>
- <RegExp input="$$6" output="<genre>\2</genre>" dest="5+">
- <expression repeat="yes" noclean="1"><a href="/explore/genre/[^>]*>(<strong>)?([^<]*)</expression>
+ <RegExp input="" output="" dest="7">
+ <expression />
</RegExp>
<RegExp input="$$1" output="\1" dest="7">
- <expression noclean="1"><h3>Styles</h3>(.*?)</div></expression>
+ <expression noclean="1"><dt>Styles</dt>(.*?)</dd></expression>
</RegExp>
- <RegExp input="$$7" output="<style>\1</style>" dest="5+">
- <expression repeat="yes" noclean="1"><li>[^>]*>([^<]*)</a></li></expression>
+ <RegExp input="$$7" output="<style>\1</style>" dest="11">
+ <expression repeat="yes" noclean="1"><li><a href="/style/[^"]*">([^<]*)</expression>
+ </RegExp>
+ <RegExp input="$$11" output="$$12" dest="2">
+ <RegExp input="$INFO[stylesfbsource]" output="<chain function="GetLastFMFallbackArtistStylesByMBID">$$8</chain>" dest="12">
+ <expression>last.fm</expression>
+ </RegExp>
+ <expression><style></style></expression>
+ </RegExp>
+ <RegExp input="$$11" output="$$11" dest="2">
+ <expression><style>(.+)</style></expression>
+ </RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </ParseAMGArtistStyles>
+
+ <GetAMGFallbackArtistStylesByAMGID dest="5" clearbuffers="no">
+ <RegExp input="$$1" output="<details><url cache="am-\1-artist.html" function="ParseAMGFallbackArtistStyles">http://www.allmusic.com/artist/\1</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetAMGFallbackArtistStylesByAMGID>
+ <ParseAMGFallbackArtistStyles dest="5" clearbuffers="no">
+ <RegExp input="$$2" output="<details>\1</details>" 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"><dt>Styles</dt>(.*?)</dd></expression>
+ </RegExp>
+ <RegExp input="$$7" output="<style>\1</style>" dest="2">
+ <expression repeat="yes" noclean="1"><li><a href="/style/[^"]*">([^<]*)</expression>
+ </RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </ParseAMGFallbackArtistStyles>
+
+ <GetAMGArtistMoodsByAMGID dest="5" clearbuffers="no">
+ <RegExp input="$$1" output="<details><url cache="am-\1-artist.html" function="ParseAMGArtistMoods">http://www.allmusic.com/artist/\1</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetAMGArtistMoodsByAMGID>
+ <ParseAMGArtistMoods dest="5" clearbuffers="no">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="" output="" dest="2">
+ <expression />
</RegExp>
<RegExp input="$$1" output="\1" dest="8">
- <expression noclean="1"><h3>Moods</h3>(.*?)</div></expression>
+ <expression noclean="1"><h4>artist moods</h4>(.*?)</ul></expression>
</RegExp>
- <RegExp input="$$8" output="<mood>\1</mood>" dest="5+">
+ <RegExp input="$$8" output="<mood>\1</mood>" dest="2">
<expression repeat="yes" noclean="1"><li>[^>]*>([^<]*)</a></li></expression>
</RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </ParseAMGArtistMoods>
+
+ <GetAMGArtistThumbsByAMGID dest="5" clearbuffers="no">
+ <RegExp input="$$1" output="<details><url cache="am-\1-artist.html" function="ParseAMGArtistThumbs">http://www.allmusic.com/artist/\1</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetAMGArtistThumbsByAMGID>
+ <ParseAMGArtistThumbs dest="5" clearbuffers="no">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="" output="" dest="2">
+ <expression />
+ </RegExp>
<RegExp input="$$1" output="\1" dest="9">
- <expression noclean="1"><h3>Instruments</h3>(.*?)</div></expression>
+ <expression noclean="1"><h4>photo gallery</h4>(.*?)<h4></expression>
</RegExp>
- <RegExp input="$$9" output="<instruments>\1</instruments>" dest="5+">
- <expression repeat="yes" noclean="1"><li>[^>]*>([^<]*)</a></li></expression>
+ <RegExp input="$$9" output="<thumb>http://cps-static.rovicorp.com/3/JPG_1080/\1</thumb>" dest="2">
+ <expression repeat="yes" noclean="1"><img src="http://cps-static.rovicorp.com/3/JPG_[^/]*/([^"]*)</expression>
</RegExp>
- <RegExp conditional="allmusicartistthumbs" input="$$1" output="<thumb>\1</thumb>" dest="5+">
- <expression noclean="1"><img id="artist_image" src="([^"]*)"</expression>
+ <expression noclean="1"/>
+ </RegExp>
+ </ParseAMGArtistThumbs>
+
+
+ <GetAMGAlbumReviewByAMGID dest="5">
+ <RegExp input="$$1" output="<details><url cache="am-\1-album.html" function="ParseAMGAlbumReview">http://www.allmusic.com/album/\1</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetAMGAlbumReviewByAMGID>
+ <ParseAMGAlbumReview dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="$$1" output="<review>\1</review>" dest="2">
+ <expression><span itemprop="description">([^<]*)</expression>
</RegExp>
<expression noclean="1" />
</RegExp>
- </ParseAMGArtist>
- <ParseAMGAlbum dest="3">
- <RegExp input="$$5" output="<details>\1</details>" dest="3">
- <RegExp input="$$1" output="<title>\1</title>" dest="5">
- <expression trim="1" noclean="1"><meta name="title" content="([^-]*)-[^<]*" /></expression>
- </RegExp>
- <RegExp input="$$1" output="<artist>\1</artist>" dest="5+">
- <expression noclean="1"><meta name="title" content="[^-]*- ([^<]*)" /></expression>
- </RegExp>
- <RegExp input="$$1" output="<rating>\1</rating>" dest="5+">
- <expression noclean="1"><h3>Rating</h3>[^_]*_r([0-9^]*)</expression>
+ </ParseAMGAlbumReview>
+
+ <GetAMGAlbumTitleByAMGID dest="5">
+ <RegExp input="$$1" output="<details><url cache="am-\1-album.html" function="ParseAMGAlbumTitle">http://www.allmusic.com/album/\1</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetAMGAlbumTitleByAMGID>
+ <ParseAMGAlbumTitle dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="$$1" output="<title>\1</title>" dest="2">
+ <expression trim="1" noclean="1"><div class="album-title">([^<]*)</expression>
</RegExp>
- <RegExp input="$$1" output="<label>\1</label>" dest="5+">
- <expression noclean="1"><h3>Label</h3>[^>]*>([^<]*)</expression>
+ <expression noclean="1" />
+ </RegExp>
+ </ParseAMGAlbumTitle>
+
+ <GetAMGAlbumArtistByAMGID dest="5">
+ <RegExp input="$$1" output="<details><url cache="am-\1-album.html" function="ParseAMGAlbumArtist">http://www.allmusic.com/album/\1</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetAMGAlbumArtistByAMGID>
+ <ParseAMGAlbumArtist dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="$$1" output="<artist>\1</artist>" dest="2">
+ <expression noclean="1"><div class="album-artist">[^>]*>([^<]*)</expression>
</RegExp>
- <RegExp input="$$1" output="<type>\1</type>" dest="5+">
- <expression noclean="1"><h3>Type</h3>[^>]*>([^<]*)</expression>
+ <expression noclean="1" />
+ </RegExp>
+ </ParseAMGAlbumArtist>
+
+ <GetAMGAlbumRatingByAMGID dest="5">
+ <RegExp input="$$1" output="<details><url cache="am-\1-album.html" function="ParseAMGAlbumRating">http://www.allmusic.com/album/\1</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetAMGAlbumRatingByAMGID>
+ <ParseAMGAlbumRating dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="$$1" output="<rating max="5.0">\1</rating>" dest="2">
+ <expression noclean="1">itemprop="rating">([0-9^]*)</expression>
</RegExp>
- <RegExp input="$$1" output="<releasedate>\1</releasedate>" dest="5+">
- <expression noclean="1"><h3>Release Date</h3>[^>]*>([^<]*)</expression>
+ <expression noclean="1" />
+ </RegExp>
+ </ParseAMGAlbumRating>
+
+ <GetAMGAlbumDateByAMGID dest="5">
+ <RegExp input="$$1" output="<details><url cache="am-\1-album.html" function="ParseAMGAlbumDate">http://www.allmusic.com/album/\1</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetAMGAlbumDateByAMGID>
+ <ParseAMGAlbumDate dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="$$1" output="<releasedate>\1</releasedate>" dest="2">
+ <expression noclean="1"><dd class="release-date">([^<]*)</expression>
</RegExp>
- <RegExp input="$$1" output="<year>\1</year>" dest="5+">
- <expression noclean="1"><span>Release Date.*?([0-9]+)</</expression>
+ <RegExp input="$$1" output="<year>\2</year>" dest="2+">
+ <expression trim="1" noclean="1"><dd class="release-date">([^,]*,)?([^<]*)</expression>
</RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </ParseAMGAlbumDate>
+
+ <GetAMGAlbumGenresByAMGID dest="5">
+ <RegExp input="$$1" output="<details><url cache="am-\1-album.html" function="ParseAMGAlbumGenres">http://www.allmusic.com/album/\1</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetAMGAlbumGenresByAMGID>
+ <ParseAMGAlbumGenres dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
<RegExp input="$$1" output="\1" dest="6">
- <expression noclean="1"><h3>Genre[s]?</h3>(.*?)</div></expression>
+ <expression noclean="1"><dd class="genres">(.*?)</dd></expression>
</RegExp>
- <RegExp input="$$6" output="<genre>\1</genre>" dest="5+">
+ <RegExp input="$$6" output="<genre>\1</genre>" dest="2">
<expression repeat="yes" trim="1" noclean="1"><li>[^>]*>([^<]*)</a></li></expression>
</RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </ParseAMGAlbumGenres>
+
+ <GetAMGAlbumStylesByAMGID dest="5">
+ <RegExp input="$$1" output="<details><url cache="am-\1-album.html" function="ParseAMGAlbumStyles">http://www.allmusic.com/album/\1</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetAMGAlbumStylesByAMGID>
+ <ParseAMGAlbumStyles dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
<RegExp input="$$1" output="\1" dest="7">
- <expression noclean="1"><h3>Style[s]?</h3>(.*?)</div></expression>
+ <expression noclean="1"><dd class="styles">(.*?)</dd></expression>
</RegExp>
- <RegExp input="$$7" output="<style>\1</style>" dest="5+">
+ <RegExp input="$$7" output="<style>\1</style>" dest="2">
<expression repeat="yes" trim="1" noclean="1"><li>[^>]*>([^<]*)</a></li></expression>
</RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </ParseAMGAlbumStyles>
+
+ <GetAMGAlbumMoodsByAMGID dest="5">
+ <RegExp input="$$1" output="<details><url cache="am-\1-album.html" function="ParseAMGAlbumMoods">http://www.allmusic.com/album/\1</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetAMGAlbumMoodsByAMGID>
+ <ParseAMGAlbumMoods dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
<RegExp input="$$1" output="\1" dest="8">
- <expression trim="1" noclean="1"><h3>Mood[s]?</h3>(.*?)</div></expression>
+ <expression trim="1" noclean="1">>\s*<h4>album moods</h4>(.*?)</ul></expression>
</RegExp>
- <RegExp input="$$8" output="<mood>\1</mood>" dest="5+">
+ <RegExp input="$$8" output="<mood>\1</mood>" dest="2">
<expression repeat="yes" noclean="1"><li>[^>]*>([^<]*)</a></li></expression>
</RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </ParseAMGAlbumMoods>
+
+ <GetAMGAlbumThemesByAMGID dest="5">
+ <RegExp input="$$1" output="<details><url cache="am-\1-album.html" function="ParseAMGAlbumThemes">http://www.allmusic.com/album/\1</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetAMGAlbumThemesByAMGID>
+ <ParseAMGAlbumThemes dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
<RegExp input="$$1" output="\1" dest="9">
- <expression noclean="1"><h3>Theme[s]?</h3>(.*?)</div></expression>
+ <expression noclean="1"><h4>album themes</h4>(.*?)</ul></expression>
</RegExp>
- <RegExp input="$$9" output="<theme>\1</theme>" dest="5+">
+ <RegExp input="$$9" output="<theme>\1</theme>" dest="2">
<expression repeat="yes" noclean="1"><li>[^>]*>([^<]*)</a></li></expression>
</RegExp>
- <RegExp input="$$1" output="<track><position>\1</position><title>\2</title><duration>\3</duration></track>" dest="5+">
- <expression repeat="yes" noclean="1,2,3">"cell">([0-9]+)<.*?<td class="cell">[^>]*>([^<]*)</a></td>.*?<td class="cell">([0-9]*:[0-9]*)</td></expression>
+ <expression noclean="1" />
+ </RegExp>
+ </ParseAMGAlbumThemes>
+
+ <GetAMGAlbumTracksByAMGID dest="5">
+ <RegExp input="$$1" output="<details><url cache="am-\1-album.html" function="ParseAMGAlbumTracks">http://www.allmusic.com/album/\1</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetAMGAlbumTracksByAMGID>
+ <ParseAMGAlbumTracks dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="$$1" output="<track><position>\1</position><title>\2</title><duration>\3</duration></track>" dest="2">
+ <expression repeat="yes" trim="1" noclean="1,2,3"><td class="tracknum">([0-9]*).*?<div class="title">[^>]*>([^<]*).*?<td class="time">([^<]*)</expression>
</RegExp>
- <RegExp conditional="allmusicalbumthumbs" input="$$1" output="<thumb>http://image.allmusic.com/\1</thumb>" dest="5+">
- <expression noclean="1">http://image.allmusic.com/([^"]*)"</expression>
+ <expression noclean="1" />
+ </RegExp>
+ </ParseAMGAlbumTracks>
+
+ <GetAMGAlbumThumbsByAMGID dest="5">
+ <RegExp input="$$1" output="<details><url cache="am-\1-album.html" function="ParseAMGAlbumThumbs">http://www.allmusic.com/album/\1</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetAMGAlbumThumbsByAMGID>
+ <ParseAMGAlbumThumbs dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="$$1" output="<thumb>http://cps-static.rovicorp.com/3/JPG_500/\1</thumb>" dest="2">
+ <expression noclean="1"><meta property="og:image" content="http://cps-static.rovicorp.com/3/JPG_[^/]*/([^"]*)</expression>
+ </RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </ParseAMGAlbumThumbs>
+
+
+ <GetAMGFakeBiographyByAMGID dest="5">
+ <RegExp input="$$1" output="<details><url cache="am-\1-artist.html" function="ParseAMGFakeBiography">http://www.allmusic.com/artist/\1</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetAMGFakeBiographyByAMGID>
+ <ParseAMGFakeBiography dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="$$1" output="<biography>Fetching artist biography from allmusic.com is not possible due to copyright reasons.</biography>" dest="2">
+ <expression noclean="1" />
+ </RegExp>
+ <expression noclean="1"/>
+ </RegExp>
+ </ParseAMGFakeBiography>
+
+ <GetAMGFakeAlbumReviewByAMGID dest="5">
+ <RegExp input="$$1" output="<details><url cache="am-\1-album.html" function="ParseAMGFakeAlbumReview">http://www.allmusic.com/album/\1</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetAMGFakeAlbumReviewByAMGID>
+ <ParseAMGFakeAlbumReview dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="$$1" output="<review>Fetching album review from allmusic.com is not possible due to copyright reasons.</review>" dest="2">
+ <expression noclean="1"/>
</RegExp>
<expression noclean="1" />
</RegExp>
- </ParseAMGAlbum>
+ </ParseAMGFakeAlbumReview>
+
</scraperfunctions>
--- /dev/null
+<?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>
--- /dev/null
+<scraperfunctions>
+ <GetAmazonDEAlbumReviewByASIN dest="5">
+ <RegExp input="$$1" output="<details><url function="ParseAmazonDEAlbumReview">http://www.amazon.de/exec/obidos/ASIN/\1</url></details>" dest="5">
+ <expression noclean="1">(.+)</expression>
+ </RegExp>
+ </GetAmazonDEAlbumReviewByASIN>
+ <ParseAmazonDEAlbumReview dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="$$1" output="<review>\1</review>" dest="2">
+ <expression fixchars="1">Kurzbeschreibung</h3>\s*<div class="productDescriptionWrapper">(.*?)<div class</expression>
+ </RegExp>
+ <expression noclean="1">(.+)</expression>
+ </RegExp>
+ </ParseAmazonDEAlbumReview>
+</scraperfunctions>
--- /dev/null
+<?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>
--- /dev/null
+<scraperfunctions>
+ <GetFanartTvArtistThumbsByMBID dest="5" clearbuffers="no">
+ <RegExp input="$$1" output="<details><url function="ParseFanartTvArtistThumbs" cache="fanarttv-artistimages-\1.xml">http://fanart.tv/webservice/artist/ed4b784f97227358b31ca4dd966a04f1/\1/xml/</url></details>" dest="5">
+ <expression noclean="1" />
+ </RegExp>
+ </GetFanartTvArtistThumbsByMBID>
+ <ParseFanartTvArtistThumbs dest="5" clearbuffers="no">
+ <RegExp input="$$13" output="<details>\1</details>" dest="5">
+ <RegExp input="" output="" dest="13">
+ <expression />
+ </RegExp>
+ <RegExp input="$$1" output="<thumb preview="\1/preview">\1</thumb>" dest="13">
+ <expression repeat="yes" noclean="1"><artistthumb id="[^"]*" url="([^"]*)</expression>
+ </RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </ParseFanartTvArtistThumbs>
+
+ <GetFanartTvArtistFanartsByMBID dest="5" clearbuffers="no">
+ <RegExp input="$$1" output="<details><url function="ParseFanartTvArtistFanarts" cache="fanarttv-artistimages-\1.xml">http://fanart.tv/webservice/artist/ed4b784f97227358b31ca4dd966a04f1/\1/xml/</url></details>" dest="5">
+ <expression noclean="1" />
+ </RegExp>
+ </GetFanartTvArtistFanartsByMBID>
+ <ParseFanartTvArtistFanarts dest="5" clearbuffers="no">
+ <RegExp input="$$13" output="<details><fanart>\1</fanart></details>" dest="5">
+ <RegExp input="" output="" dest="13">
+ <expression />
+ </RegExp>
+ <RegExp input="" output="" dest="14">
+ <expression />
+ </RegExp>
+ <RegExp input="$$1" output="<thumb preview="\1/preview">\1</thumb>" dest="14">
+ <expression repeat="yes" noclean="1"><artistbackground id="[^"]*" url="([^"]*)</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="<details><url function="ParseFanartTvAlbumThumbs" cache="fanarttv-albumimages-\1.xml">http://fanart.tv/webservice/album/ed4b784f97227358b31ca4dd966a04f1/\1/xml/</url></details>" dest="5">
+ <expression noclean="1" />
+ </RegExp>
+ </GetFanartTvAlbumThumbsByMBID>
+ <ParseFanartTvAlbumThumbs dest="5" clearbuffers="no">
+ <RegExp input="$$13" output="<details>\1</details>" dest="5">
+ <RegExp input="" output="" dest="13">
+ <expression />
+ </RegExp>
+ <RegExp input="$$1" output="<thumb preview="\1/preview">\1</thumb>" dest="13">
+ <expression repeat="yes" noclean="1"><albumcover id="[^"]*" url="([^"]*)</expression>
+ </RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </ParseFanartTvAlbumThumbs>
+</scraperfunctions>
<?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"/>
<scraperfunctions>
+ <GetHTBThumbsByMBID dest="5" clearbuffers="no">
+ <RegExp input="$$1" output="<details><url function="ParseHTBThumbs" post="yes" cache="htb-images-\1.xml">http://htbackdrops.com/api/7681a907c805e0670330c694e788e8e8/searchXML?mbid=\1&aid=1,5</url></details>" dest="5">
+ <expression noclean="1" />
+ </RegExp>
+ </GetHTBThumbsByMBID>
<GetHTBThumbs dest="5">
<RegExp input="$$1" output="<details><url function="ParseHTBThumbs" post="yes" cache="htb-images-\1.xml">http://htbackdrops.com/api/7681a907c805e0670330c694e788e8e8/searchXML?keywords=\1&default_operator=and&aid=1,5</url></details>" dest="5">
<expression noclean="1" />
</RegExp>
</GetHTBThumbs>
- <ParseHTBThumbs dest="5">
+ <ParseHTBThumbs dest="5" clearbuffers="no">
<RegExp input="$$13" output="<details>\1</details>" dest="5">
+ <RegExp input="" output="" dest="13">
+ <expression />
+ </RegExp>
<RegExp input="$$1" output="<thumb preview="http://www.htbackdrops.com/api/7681a907c805e0670330c694e788e8e8/download/\1/thumbnail">http://www.htbackdrops.com/api/7681a907c805e0670330c694e788e8e8/download/\1/fullsize</thumb>" dest="13">
<expression repeat="yes" noclean="1"><id>([^<]+)</id>\n[^<]+<aid>5</aid></expression>
</RegExp>
- <expression noclean="1">(.+)</expression>
+ <expression noclean="1" />
</RegExp>
</ParseHTBThumbs>
+
+ <GetHTBFanartByMBID dest="5" clearbuffers="no">
+ <RegExp input="$$1" output="<details><url function="ParseHTBFanart" post="yes" cache="htb-images-\1.xml">http://htbackdrops.com/api/7681a907c805e0670330c694e788e8e8/searchXML?mbid=\1&aid=1,5</url></details>" dest="5">
+ <expression noclean="1" />
+ </RegExp>
+ </GetHTBFanartByMBID>
<GetHTBFanart dest="5">
<RegExp input="$$1" output="<details><url function="ParseHTBFanart" post="yes" cache="htb-images-\1.xml">http://htbackdrops.com/api/7681a907c805e0670330c694e788e8e8/searchXML?keywords=\1&default_operator=and&aid=1,5</url></details>" dest="5">
<expression noclean="1" />
</RegExp>
</GetHTBFanart>
- <ParseHTBFanart dest="5">
- <RegExp input="$$13" output="<details><fanart url="http://www.htbackdrops.com/">\1</fanart></details>" dest="5">
- <RegExp input="$$1" output="<thumb preview="api/7681a907c805e0670330c694e788e8e8/download/\1/thumbnail">api/7681a907c805e0670330c694e788e8e8/download/\1/fullsize</thumb>" dest="13">
+ <ParseHTBFanart dest="5" clearbuffers="no">
+ <RegExp input="$$13" output="<details><fanart>\1</fanart></details>" dest="5">
+ <RegExp input="" output="" dest="13">
+ <expression />
+ </RegExp>
+ <RegExp input="" output="" dest="14">
+ <expression />
+ </RegExp>
+ <RegExp input="$$1" output="<thumb preview="http://www.htbackdrops.com/api/7681a907c805e0670330c694e788e8e8/download/\1/thumbnail">http://www.htbackdrops.com/api/7681a907c805e0670330c694e788e8e8/download/\1/fullsize</thumb>" dest="14">
<expression repeat="yes" noclean="1"><id>([^<]+)</id>\n[^<]+<aid>1</aid></expression>
</RegExp>
- <expression noclean="1">(.+)</expression>
+ <RegExp input="$$14" output="\1" dest="13">
+ <expression noclean="1">(.+)</expression>
+ </RegExp>
+ <expression noclean="1" />
</RegExp>
</ParseHTBFanart>
</scraperfunctions>
<?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"/>
<scraperfunctions>
- <GetLastFMDiscography dest="5">
+ <GetLastFMDiscographyByMBID dest="5" clearbuffers="no">
+ <RegExp input="$$1" output="<details><url function="ParseLastFMDiscography" cache="lastfmdiscog-\1.xml">http://ws.audioscrobbler.com/2.0/?method=artist.gettopalbums&amp;mbid=\1&amp;api_key=71e468a84c1f40d4991ddccc46e40f1b</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetLastFMDiscographyByMBID>
+ <GetLastFMDiscography dest="5" clearbuffers="no">
<RegExp input="$$1" output="<details><url function="ParseLastFMDiscography">http://ws.audioscrobbler.com/2.0/?method=artist.gettopalbums&amp;artist=\1&amp;api_key=71e468a84c1f40d4991ddccc46e40f1b</url></details>" dest="5">
<expression noclean="1"/>
</RegExp>
</GetLastFMDiscography>
- <ParseLastFMDiscography dest="5">
+ <ParseLastFMDiscography dest="5" clearbuffers="no">
<RegExp input="$$2" output="<details>\1</details>" dest="5">
- <RegExp input="$$1" output="<album><title>\1</title></album>" dest="2+">
+ <RegExp input="" output="" dest="2">
+ <expression />
+ </RegExp>
+ <RegExp input="$$1" output="<album><title>\1</title></album>" dest="2">
<expression repeat="yes"><album[^>]*>[^<]*<name>([^<]*?)</name></expression>
</RegExp>
<expression noclean="1"/>
</RegExp>
</ParseLastFMDiscography>
- <GetLastFMArtistThumbsByID dest="5">
- <RegExp input="$$1" output="<details><url function="ParseLastFMArtistThumbs">http://ws.audioscrobbler.com/2.0/?method=artist.getimages&mbid=\1&api_key=71e468a84c1f40d4991ddccc46e40f1b</url></details>" dest="5">
+
+ <GetLastFMBiographyByMBID dest="5" clearbuffers="no">
+ <RegExp input="$$1" output="<details><url function="ParseLastFMBiography" cache="lastfmartistinfo-\1.xml">http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&amp;mbid=\1&amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&lang=$INFO[lastfmlanguage]</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetLastFMBiographyByMBID>
+ <ParseLastFMBiography dest="5" clearbuffers="no">
+ <RegExp input="$$6" output="<details>\1</details>" 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"><content><!\[CDATA\[(.*?)\]\]</expression>
+ </RegExp>
+ <RegExp input="$$11" output="$$12" dest="2">
+ <RegExp input="$INFO[biogfbsource]" output="<chain function="GetAMGFallbackBiographyByAMGID">$$9</chain>" dest="12">
+ <expression>allmusic.com</expression>
+ </RegExp>
+ <expression>^$</expression>
+ </RegExp>
+ <RegExp input="$$11" output="<biography>\1</biography>" dest="6">
+ <expression>(.+)</expression>
+ </RegExp>
+ <expression noclean="1"/>
+ </RegExp>
+ </ParseLastFMBiography>
+
+ <GetLastFMFallbackBiographyByMBID dest="5" clearbuffers="no">
+ <RegExp input="$$1" output="<details><url function="ParseLastFMFallbackBiography" cache="lastfmartistinfo-\1.xml">http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&amp;mbid=\1&amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&lang=$INFO[lastfmlanguage]</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetLastFMFallbackBiographyByMBID>
+ <ParseLastFMFallbackBiography dest="5" clearbuffers="no">
+ <RegExp input="$$6" output="<details>\1</details>" dest="5">
+ <RegExp input="" output="" dest="6">
+ <expression />
+ </RegExp>
+ <RegExp input="$$1" output="<biography>\1</biography>" dest="6">
+ <expression fixchars="1"><content><!\[CDATA\[(.*?)\]\]</expression>
+ </RegExp>
+ <expression noclean="1"/>
+ </RegExp>
+ </ParseLastFMFallbackBiography>
+
+ <GetLastFMArtistGenresByMBID dest="5" clearbuffers="no">
+ <RegExp input="$$1" output="<details><url function="ParseLastFMArtistGenres" cache="lastfmgenres-\1.xml">http://ws.audioscrobbler.com/2.0/?method=artist.gettoptags&amp;mbid=\1&amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&lang=$INFO[lastfmlanguage]</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetLastFMArtistGenresByMBID>
+ <ParseLastFMArtistGenres dest="5" clearbuffers="no">
+ <RegExp input="$$4" output="<details>\1</details>" dest="5">
+ <RegExp input="" output="" dest="4">
+ <expression />
+ </RegExp>
+ <RegExp input="$$1" output="<genre>\1</genre>" dest="11">
+ <expression noclean="1"><tag>.*?<name>([^/lt;]*)</name></expression>
+ </RegExp>
+ <RegExp input="$$11" output="$$12" dest="4">
+ <RegExp input="$INFO[genresfbsource]" output="<chain function="GetAMGFallbackArtistGenresByAMGID">$$9</chain>" dest="12">
+ <expression>allmusic.com</expression>
+ </RegExp>
+ <expression><genre></genre></expression>
+ </RegExp>
+ <RegExp input="$$11" output="$$11" dest="4">
+ <expression><genre>(.+)</genre></expression>
+ </RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </ParseLastFMArtistGenres>
+
+ <GetLastFMFallbackArtistGenresByMBID dest="5" clearbuffers="no">
+ <RegExp input="$$1" output="<details><url function="ParseLastFMFallbackArtistGenres" cache="lastfmgenres-\1.xml">http://ws.audioscrobbler.com/2.0/?method=artist.gettoptags&amp;mbid=\1&amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&lang=$INFO[lastfmlanguage]</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetLastFMFallbackArtistGenresByMBID>
+ <ParseLastFMFallbackArtistGenres dest="5" clearbuffers="no">
+ <RegExp input="$$4" output="<details>\1</details>" dest="5">
+ <RegExp input="" output="" dest="4">
+ <expression />
+ </RegExp>
+ <RegExp input="$$1" output="<genre>\1</genre>" dest="4">
+ <expression noclean="1"><tag>.*?<name>([^/lt;]*)</name></expression>
+ </RegExp>
+ <expression noclean="1"/>
+ </RegExp>
+ </ParseLastFMFallbackArtistGenres>
+
+ <GetLastFMArtistStylesByMBID dest="5" clearbuffers="no">
+ <RegExp input="$$1" output="<details><url function="ParseLastFMArtistStyles" cache="lastfmgenres-\1.xml">http://ws.audioscrobbler.com/2.0/?method=artist.gettoptags&amp;mbid=\1&amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&lang=$INFO[lastfmlanguage]</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetLastFMArtistStylesByMBID>
+ <ParseLastFMArtistStyles dest="5" clearbuffers="no">
+ <RegExp input="$$4" output="<details>\1</details>" dest="5">
+ <RegExp input="" output="" dest="4">
+ <expression />
+ </RegExp>
+ <RegExp input="$$1" output="<style>\1</style>" dest="11">
+ <expression repeat="yes" noclean="1"><tag>.*?<name>([^/lt;]*)</name></expression>
+ </RegExp>
+ <RegExp input="$$11" output="$$12" dest="4">
+ <RegExp input="$INFO[genresfbsource]" output="<chain function="GetAMGFallbackArtistStylesByAMGID">$$9</chain>" dest="12">
+ <expression>allmusic.com</expression>
+ </RegExp>
+ <expression><style></style></expression>
+ </RegExp>
+ <RegExp input="$$11" output="$$11" dest="4">
+ <expression><style>(.+)</style></expression>
+ </RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </ParseLastFMArtistStyles>
+
+ <GetLastFMFallbackArtistStylesByMBID dest="5" clearbuffers="no">
+ <RegExp input="$$1" output="<details><url function="ParseLastFMFallbackArtistStyles" cache="lastfmgenres-\1.xml">http://ws.audioscrobbler.com/2.0/?method=artist.gettoptags&amp;mbid=\1&amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&lang=$INFO[lastfmlanguage]</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetLastFMFallbackArtistStylesByMBID>
+ <ParseLastFMFallbackArtistStyles dest="5" clearbuffers="no">
+ <RegExp input="$$4" output="<details>\1</details>" dest="5">
+ <RegExp input="" output="" dest="4">
+ <expression />
+ </RegExp>
+ <RegExp input="$$1" output="<style>\1</style>" dest="4">
+ <expression repeat="yes" noclean="1"><tag>.*?<name>([^/lt;]*)</name></expression>
+ </RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </ParseLastFMFallbackArtistStyles>
+
+ <GetLastFMArtistThumbsByMBID dest="5" clearbuffers="no">
+ <RegExp input="$$1" output="<details><url function="ParseLastFMArtistThumbs" cache="lastfmartistimages-\1.xml">http://ws.audioscrobbler.com/2.0/?method=artist.getimages&amp;mbid=\1&amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&lang=$INFO[lastfmlanguage]</url></details>" dest="5">
<expression noclean="1" />
</RegExp>
- </GetLastFMArtistThumbsByID>
- <GetLastFMArtistThumbsByName dest="5">
- <RegExp input="$$1" output="<details><url function="ParseLastFMArtistThumbs">http://ws.audioscrobbler.com/2.0/?method=artist.getimages&artist=\1&api_key=71e468a84c1f40d4991ddccc46e40f1b</url></details>" dest="5">
+ </GetLastFMArtistThumbsByMBID>
+ <GetLastFMArtistThumbsByName dest="5" clearbuffers="no">
+ <RegExp input="$$1" output="<details><url function="ParseLastFMArtistThumbs">http://ws.audioscrobbler.com/2.0/?method=artist.getimages&amp;artist=\1&amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&lang=$INFO[lastfmlanguage]</url></details>" dest="5">
<expression noclean="1" />
</RegExp>
</GetLastFMArtistThumbsByName>
- <ParseLastFMArtistThumbs dest="5">
+ <ParseLastFMArtistThumbs dest="5" clearbuffers="no">
<RegExp input="$$6" output="<details>\1</details>" dest="5">
+ <RegExp input="" output="" dest="6">
+ <expression />
+ </RegExp>
<RegExp input="$$1" output="<thumb preview="\2">\1</thumb>" dest="6">
- <expression repeat="yes" noclean="1"><size name="original"[^>]*>([^<]*)<[^<]*<size name="large"[^>]*>([^<]*)<</expression>
+ <expression repeat="yes" noclean="1"><size name="original"[^>]*>([^<]*)<[^<]*<size name="large"[^>]*>([^<]*)<</expression>
</RegExp>
- <expression noclean="1">(.+)</expression>
+ <expression noclean="1" />
</RegExp>
</ParseLastFMArtistThumbs>
+
+
+ <GetLastFMAlbumTitleByMBID dest="5">
+ <RegExp input="$$1" output="<details><url function="ParseLastFMAlbumTitle" cache="lastfmalbum-\1.xml">http://ws.audioscrobbler.com/2.0/?method=album.getinfo&amp;mbid=\1&amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&lang=$INFO[lastfmlanguage]</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetLastFMAlbumTitleByMBID>
+ <GetLastFMAlbumTitleByAlbumAndArtist dest="5">
+ <RegExp input="$$1" output="<details><url function="ParseLastFMAlbumTitle" cache="lastfmalbum-\4-\3.xml">http://ws.audioscrobbler.com/2.0/?method=album.getinfo&artist=\2&amp;album=\1&amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&lang=$INFO[lastfmlanguage]</url></details>" dest="5">
+ <expression encode="1,2">(.+)::(.+)::(.+)::(.+)</expression>
+ </RegExp>
+ </GetLastFMAlbumTitleByAlbumAndArtist>
+ <ParseLastFMAlbumTitle dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="$$1" output="<title>\1</title>" dest="2">
+ <expression noclean="1"><name>(.*?)</name></expression>
+ </RegExp>
+ <expression noclean="1">(.+)</expression>
+ </RegExp>
+ </ParseLastFMAlbumTitle>
+
+ <GetLastFMAlbumArtistByMBID dest="5">
+ <RegExp input="$$1" output="<details><url function="ParseLastFMAlbumArtist" cache="lastfmalbum-\1.xml">http://ws.audioscrobbler.com/2.0/?method=album.getinfo&amp;mbid=\1&amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&lang=$INFO[lastfmlanguage]</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetLastFMAlbumArtistByMBID>
+ <GetLastFMAlbumArtistByAlbumAndArtist dest="5">
+ <RegExp input="$$1" output="<details><url function="ParseLastFMAlbumArtist" cache="lastfmalbum-\4-\3.xml">http://ws.audioscrobbler.com/2.0/?method=album.getinfo&artist=\2&amp;album=\1&amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&lang=$INFO[lastfmlanguage]</url></details>" dest="5">
+ <expression encode="1,2">(.+)::(.+)::(.+)::(.+)</expression>
+ </RegExp>
+ </GetLastFMAlbumArtistByAlbumAndArtist>
+ <ParseLastFMAlbumArtist dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="$$1" output="<artist>\1</artist>" dest="2">
+ <expression noclean="1"><artist>(.*?)</artist></expression>
+ </RegExp>
+ <expression noclean="1">(.+)</expression>
+ </RegExp>
+ </ParseLastFMAlbumArtist>
+
+ <GetLastFMAlbumDateByMBID dest="5">
+ <RegExp input="$$1" output="<details><url function="ParseLastFMAlbumDate" cache="lastfmalbum-\1.xml">http://ws.audioscrobbler.com/2.0/?method=album.getinfo&amp;mbid=\1&amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&lang=$INFO[lastfmlanguage]</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetLastFMAlbumDateByMBID>
+ <GetLastFMAlbumDateByAlbumAndArtist dest="5">
+ <RegExp input="$$1" output="<details><url function="ParseLastFMAlbumDate" cache="lastfmalbum-\4-\3.xml">http://ws.audioscrobbler.com/2.0/?method=album.getinfo&artist=\2&amp;album=\1&amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&lang=$INFO[lastfmlanguage]</url></details>" dest="5">
+ <expression encode="1,2">(.+)::(.+)::(.+)::(.+)</expression>
+ </RegExp>
+ </GetLastFMAlbumDateByAlbumAndArtist>
+ <ParseLastFMAlbumDate dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="$$1" output="<releasedate>\1</releasedate>" dest="2">
+ <expression trim="1"><releasedate>([^,]*)?([^<]*)?</releasedate></expression>
+ </RegExp>
+ <RegExp input="$$1" output="<year>\1</year>" dest="2+">
+ <expression trim="1"><releasedate>.*?([0-9]{4})[^<]*</releasedate></expression>
+ </RegExp>
+ <expression noclean="1">(.+)</expression>
+ </RegExp>
+ </ParseLastFMAlbumDate>
+
+ <GetLastFMAlbumTracksByMBID dest="5">
+ <RegExp input="$$1" output="<details><url function="ParseLastFMAlbumTracks" cache="lastfmalbum-\1.xml">http://ws.audioscrobbler.com/2.0/?method=album.getinfo&amp;mbid=\1&amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&lang=$INFO[lastfmlanguage]</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetLastFMAlbumTracksByMBID>
+ <GetLastFMAlbumTracksByAlbumAndArtist dest="5">
+ <RegExp input="$$1" output="<details><url function="ParseLastFMAlbumTracks" cache="lastfmalbum-\4-\3.xml">http://ws.audioscrobbler.com/2.0/?method=album.getinfo&artist=\2&amp;album=\1&amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&lang=$INFO[lastfmlanguage]</url></details>" dest="5">
+ <expression encode="1,2">(.+)::(.+)::(.+)::(.+)</expression>
+ </RegExp>
+ </GetLastFMAlbumTracksByAlbumAndArtist>
+ <ParseLastFMAlbumTracks dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="$$1" output="<track><position>\1</position><title>\2</title></track>" dest="2">
+ <expression repeat="yes" noclean="1"><track rank="(.*?)".*?<name>(.*?)</name></expression>
+ </RegExp>
+ <expression noclean="1">(.+)</expression>
+ </RegExp>
+ </ParseLastFMAlbumTracks>
+
+ <GetLastFMAlbumReviewByMBID dest="5">
+ <RegExp input="$$1" output="<details><url function="ParseLastFMAlbumReview" cache="lastfmalbum-\1.xml">http://ws.audioscrobbler.com/2.0/?method=album.getinfo&amp;mbid=\1&amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&lang=$INFO[lastfmlanguage]</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetLastFMAlbumReviewByMBID>
+ <GetLastFMAlbumReviewByAlbumAndArtist dest="5">
+ <RegExp input="$$1" output="<details><url function="ParseLastFMAlbumReview" cache="lastfmalbum-\4-\3.xml">http://ws.audioscrobbler.com/2.0/?method=album.getinfo&artist=\2&amp;album=\1&amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&lang=$INFO[lastfmlanguage]</url></details>" dest="5">
+ <expression encode="1,2">(.+)::(.+)::(.+)::(.+)</expression>
+ </RegExp>
+ </GetLastFMAlbumReviewByAlbumAndArtist>
+ <ParseLastFMAlbumReview dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="$$1" output="<review>\1</review>" dest="2">
+ <expression fixchars="1"><content><!\[CDATA\[(.*?)(User-|\]\])</expression>
+ </RegExp>
+ <expression noclean="1">(.+)</expression>
+ </RegExp>
+ </ParseLastFMAlbumReview>
+
+ <GetLastFMAlbumThumbsByMBID dest="5">
+ <RegExp input="$$1" output="<details><url function="ParseLastFMAlbumThumbs" cache="lastfmalbum-\1.xml">http://ws.audioscrobbler.com/2.0/?method=album.getinfo&amp;mbid=\1&amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&lang=$INFO[lastfmlanguage]</url></details>" dest="5">
+ <expression noclean="1"/>
+ </RegExp>
+ </GetLastFMAlbumThumbsByMBID>
<GetLastFMAlbumThumbs dest="5">
- <RegExp input="$$1" output="<details><url function="ParseLastFMAlbumThumbs">http://ws.audioscrobbler.com/2.0/?method=album.getinfo&artist=\2&album=\1&api_key=71e468a84c1f40d4991ddccc46e40f1b</url></details>" dest="5">
- <expression>(.+)::(.+)</expression>
+ <RegExp input="$$1" output="<details><url function="ParseLastFMAlbumThumbs" cache="lastfmalbum-\4-\3.xml">http://ws.audioscrobbler.com/2.0/?method=album.getinfo&artist=\2&amp;album=\1&amp;api_key=71e468a84c1f40d4991ddccc46e40f1b&lang=$INFO[lastfmlanguage]</url></details>" dest="5">
+ <expression encode="1,2">(.+)::(.+)::(.+)::(.+)</expression>
</RegExp>
</GetLastFMAlbumThumbs>
<ParseLastFMAlbumThumbs dest="5">
<RegExp input="$$1" output="<thumb>\1</thumb>" dest="2+">
<expression noclean="1"><image size="large">([^<]*)</image></expression>
</RegExp>
- <expression noclean="1"></expression>
+ <expression noclean="1">(.+)</expression>
</RegExp>
</ParseLastFMAlbumThumbs>
+
</scraperfunctions>
--- /dev/null
+<?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>
--- /dev/null
+<scraperfunctions>
+ <GetMBDiscographyByMBID dest="5" clearbuffers="no">
+ <RegExp input="$$1" output="<details><url function="ParseMBDiscography" cache="mb-\1-discog.xml">http://musicbrainz.org/ws/2/release-group?artist=\1&amp;limit=100&amp;type=album</url></details>" dest="5">
+ <expression noclean="1" />
+ </RegExp>
+ </GetMBDiscographyByMBID>
+ <ParseMBDiscography dest="5" clearbuffers="no">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="" output="" dest="2">
+ <expression />
+ </RegExp>
+ <RegExp input="$$1" output="<album><year>\4</year><title>\2</title><label>\1</label></album>" dest="2">
+ <expression repeat="yes" clear="yes" fixchars="1,2,3" noclean="1,2,3"> type="Album" id="([^"]*)"><title>([^<]*)</title><first-release-date(\s/)?>(\d{4})?</expression>
+ </RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </ParseMBDiscography>
+
+ <GetMBLafeSpanByMBID dest="5" clearbuffers="no">
+ <RegExp input="$$1" output="<details><url function="ParseMBLifeSpan" cache="mb-\1-artist.xml">http://www.musicbrainz.org/ws/2/artist/\1?inc=url-rels</url></details>" dest="5">
+ <expression noclean="1" />
+ </RegExp>
+ </GetMBLafeSpanByMBID>
+ <ParseMBLifeSpan dest="5" clearbuffers="no">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="" output="" dest="2">
+ <expression />
+ </RegExp>
+ <RegExp input="" output="" dest="11">
+ <expression />
+ </RegExp>
+ <RegExp input="$$1" output="<born>\1</born>" dest="11">
+ <expression><artist type="Person".*?<life-span><begin>([^<]*)</expression>
+ </RegExp>
+ <RegExp input="$$1" output="<died>\1</died>" dest="11+">
+ <expression><artist type="Person".*?<life-span><begin>[^<]*</begin><end>([^<]*)</expression>
+ </RegExp>
+ <RegExp input="$$1" output="<formed>\1</formed>" dest="11">
+ <expression><artist type="Group".*?<life-span><begin>([^<]*)</expression>
+ </RegExp>
+ <RegExp input="$$1" output="<disbanded>\1</disbanded>" dest="11+">
+ <expression><artist type="Group".*?<life-span><begin>[^<]*</begin><end>([^<]*)</expression>
+ </RegExp>
+ <RegExp input="$$11" output="$$12" dest="2">
+ <RegExp input="$INFO[lifespanfbsource]" output="<chain function="GetAMGFallbackArtistLifeSpanByAMGID">$$9</chain>" dest="12">
+ <expression>allmusic.com</expression>
+ </RegExp>
+ <expression>^$</expression>
+ </RegExp>
+ <RegExp input="$$11" output="$$11" dest="2">
+ <expression noclean="1"><(?:born|formed)*>(.+)</(?:born|formed)*></expression>
+ </RegExp>
+ <expression noclean="1"/>
+ </RegExp>
+ </ParseMBLifeSpan>
+
+ <GetMBFallbackLafeSpanByMBID dest="5" clearbuffers="no">
+ <RegExp input="$$1" output="<details><url function="ParseFallbackMBLifeSpan" cache="mb-\1-artist.xml">http://www.musicbrainz.org/ws/2/artist/\1?inc=url-rels</url></details>" dest="5">
+ <expression noclean="1" />
+ </RegExp>
+ </GetMBFallbackLafeSpanByMBID>
+ <ParseFallbackMBLifeSpan dest="5" clearbuffers="no">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="" output="" dest="2">
+ <expression />
+ </RegExp>
+ <RegExp input="$$1" output="<born>\1</born>" dest="2">
+ <expression><artist type="Person".*?<life-span><begin>([^<]*)</expression>
+ </RegExp>
+ <RegExp input="$$1" output="<died>\1</died>" dest="2+">
+ <expression><artist type="Person".*?<life-span><begin>[^<]*</begin><end>([^<]*)</expression>
+ </RegExp>
+ <RegExp input="$$1" output="<formed>\1</formed>" dest="2">
+ <expression><artist type="Group".*?<life-span><begin>([^<]*)</expression>
+ </RegExp>
+ <RegExp input="$$1" output="<disbanded>\1</disbanded>" dest="2+">
+ <expression><artist type="Group".*?<life-span><begin>[^<]*</begin><end>([^<]*)</expression>
+ </RegExp>
+ <expression noclean="1"/>
+ </RegExp>
+ </ParseFallbackMBLifeSpan>
+
+ <GetMBAlbumTitleByMBID dest="5">
+ <RegExp input="$$1" output="<details><url function="ParseMBAlbumTitle" cache="mb-\1-album.xml">http://musicbrainz.org/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings</url></details>" dest="5">
+ <expression noclean="1" />
+ </RegExp>
+ </GetMBAlbumTitleByMBID>
+ <ParseMBAlbumTitle dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="$$1" output="<title>\1</title>" dest="2">
+ <expression noclean="1"><release id="[^"]*"><title>([^<]*)<</expression>
+ </RegExp>
+ <expression noclean="1">(.+)</expression>
+ </RegExp>
+ </ParseMBAlbumTitle>
+
+ <GetMBAlbumArtistByMBID dest="5">
+ <RegExp input="$$1" output="<details><url function="ParseMBAlbumArtist" cache="mb-\1-album.xml">http://musicbrainz.org/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings</url></details>" dest="5">
+ <expression noclean="1" />
+ </RegExp>
+ </GetMBAlbumArtistByMBID>
+ <ParseMBAlbumArtist dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="$$1" output="<artist>\1</artist>" dest="2">
+ <expression noclean="1"><artist id="[^"]*"><name>([^<]*)<</expression>
+ </RegExp>
+ <expression noclean="1">(.+)</expression>
+ </RegExp>
+ </ParseMBAlbumArtist>
+
+ <GetMBAlbumRatingByMBID dest="5">
+ <RegExp input="$$1" output="<details><url function="ParseMBAlbumRating" cache="mb-\1-album.xml">http://musicbrainz.org/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings</url></details>" dest="5">
+ <expression noclean="1" />
+ </RegExp>
+ </GetMBAlbumRatingByMBID>
+ <ParseMBAlbumRating dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="$$1" output="<rating>\1</rating>" dest="2">
+ <expression noclean="1"></primary-type><rating votes-count="[^"]*">(\d)</expression>
+ </RegExp>
+ <expression noclean="1">(.+)</expression>
+ </RegExp>
+ </ParseMBAlbumRating>
+
+ <GetMBAlbumLabelByMBID dest="5">
+ <RegExp input="$$1" output="<details><url function="ParseMBAlbumLabel" cache="mb-\1-album.xml">http://musicbrainz.org/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings</url></details>" dest="5">
+ <expression noclean="1" />
+ </RegExp>
+ </GetMBAlbumLabelByMBID>
+ <ParseMBAlbumLabel dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="$$1" output="<label>\1</label>" dest="2">
+ <expression noclean="1"><label id="[^"]*"><name>([^<]*)</expression>
+ </RegExp>
+ <expression noclean="1">(.+)</expression>
+ </RegExp>
+ </ParseMBAlbumLabel>
+
+ <GetMBAlbumDateByMBID dest="5">
+ <RegExp input="$$1" output="<details><url function="ParseMBAlbumDate" cache="mb-\1-album.xml">http://musicbrainz.org/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings</url></details>" dest="5">
+ <expression noclean="1" />
+ </RegExp>
+ </GetMBAlbumDateByMBID>
+ <ParseMBAlbumDate dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="$$1" output="<releasedate>\1</releasedate>" dest="2">
+ <expression noclean="1"><first-release-date>([^<]*)<</expression>
+ </RegExp>
+ <RegExp input="$$1" output="<year>\1</year>" dest="2+">
+ <expression noclean="1"><first-release-date>(\d{4})</expression>
+ </RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </ParseMBAlbumDate>
+
+ <GetMBAlbumTracksByMBID dest="5">
+ <RegExp input="$$1" output="<details><url function="ParseMBAlbumTracks" cache="mb-\1-album.xml">http://musicbrainz.org/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings</url></details>" dest="5">
+ <expression noclean="1" />
+ </RegExp>
+ </GetMBAlbumTracksByMBID>
+ <ParseMBAlbumTracks dest="5">
+ <RegExp input="$$2" output="<details>\1</details>" dest="5">
+ <RegExp input="$$1" output="<track><position>\1</position><title>\4</title><duration>\2</duration></track>" dest="2">
+ <expression repeat="yes"><track><position>(\d+)</position><number>\d*</number>(?:<length>(\d*?)\d{3}</length>)*(?:<recording id="([^"]*)">)*<title>([^<]*)<</expression>
+ </RegExp>
+ <expression noclean="1">(.+)</expression>
+ </RegExp>
+ </ParseMBAlbumTracks>
+
+</scraperfunctions>
--- /dev/null
+<?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>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<scraper framework="1.1" date="2012-06-10">
+ <CreateSearchUrl dest="3">
+ <RegExp input="$$1" output="<url cache="lastfmm-\2.xml">http://ws.audioscrobbler.com/2.0/?method=track.getinfo&api_key=71e468a84c1f40d4991ddccc46e40f1b&artist=\1&track=\2</url>" dest="3">
+ <expression trim="1,2">(.+)%20%20%20(.+)</expression>
+ </RegExp>
+ </CreateSearchUrl>
+ <GetSearchResults dest="3">
+ <RegExp input="$$5" output="<results>\1</results>" dest="3">
+ <RegExp input="$$1" output="\1" dest="6">
+ <expression></id>\s*<name>([^<]*).*?<artist>\s*<name>([^<]*)</expression>
+ </RegExp>
+ <RegExp input="$$1" output="\2" dest="7">
+ <expression></id>\s*<name>([^<]*).*?<artist>\s*<name>([^<]*)</expression>
+ </RegExp>
+ <RegExp input="$$1" output="<entity><title>$$7 - $$6</title><url cache="lastfmm-\1.xml">http://ws.audioscrobbler.com/2.0/?method=track.getinfo&api_key=71e468a84c1f40d4991ddccc46e40f1b&artist=\2&track=\1</url></entity>" dest="5">
+ <expression encode="1,2"></id>\s*<name>([^<]*).*?<artist>\s*<name>([^<]*)</expression>
+ </RegExp>
+ <expression noclean="1" />
+ </RegExp>
+ </GetSearchResults>
+ <GetDetails dest="3">
+ <RegExp input="$$5" output="<details>\1</details>" dest="3">
+ <RegExp input="$$1" output="\1" dest="4">
+ <expression></title>\s*<mbid>([^<]*)<</expression>
+ </RegExp>
+ <RegExp input="$$1" output="\1" dest="7">
+ <expression><album[^>]*>\s*<artist>\s*[^<]*</artist>\s*<title>([^<]*)</title></expression>
+ </RegExp>
+ <RegExp input="$$1" output="\1" dest="8">
+ <expression><artist>\s*<name>([^<]*)<</expression>
+ </RegExp>
+ <RegExp input="$$1" output="<title>\1</title>" dest="5">
+ <expression><name>([^<]*)<</expression>
+ </RegExp>
+ <RegExp input="$$8" output="<artist>\1</artist>" dest="5+">
+ <expression noclean="1" />
+ </RegExp>
+ <RegExp input="$$7" output="<album>\1</album>" dest="5+">
+ <expression noclean="1" />
+ </RegExp>
+ <RegExp input="$$4" output="<chain function="GetLastFMAlbumDateByAlbumAndArtist">$$7::$$8::$$7::$$8</chain>" dest="5+">
+ <expression noclean="1" />
+ </RegExp>
+ <RegExp input="$$1" output="<plot>\1</plot>" dest="5+">
+ <expression fixchars="1"><content><!\[CDATA\[(.*?)(User-|\]\])</expression>
+ </RegExp>
+ <RegExp input="$$1" output="<genre>\1</genre>" dest="5+">
+ <expression repeat="yes"><tag>\s*<name>([^<]*)</name></expression>
+ </RegExp>
+ <RegExp conditional="lastfmalbumthumbs" input="$$1" output="<thumb>\1</thumb>" dest="5+">
+ <expression><image size="extralarge">\s*([^<]*)\s*</image></expression>
+ </RegExp>
+ <RegExp conditional="fanarttvalbumthumbs" input="$$1" output="<chain function="GetFanartTvAlbumThumbsByMBID">$$4</chain>" dest="5+">
+ <expression noclean="1">(.+)</expression>
+ </RegExp>
+ <RegExp conditional="lastfmalbumthumbs" input="$$1" output="<chain function="GetLastFMAlbumThumbs">$$7::$$8::$$7::$$8</chain>" dest="5+">
+ <expression noclean="1" />
+ </RegExp>
+ <expression noclean="1"/>
+ </RegExp>
+ </GetDetails>
+</scraper>
--- /dev/null
+<?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>
--- /dev/null
+<?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>
+++ /dev/null
-<?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>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<strings>
- <!-- settings labels -->
- <string id="30000">Afmetingen van de voorbeeld afbeeldingen</string>
-</strings>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<strings>
- <!-- settings labels -->
- <string id="30000">Thumb(s) Size</string>
-</strings>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<strings>
- <!-- settings labels -->
- <string id="30000">Pienoiskuvien koko</string>
-</strings>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<strings>
- <!-- settings labels -->
- <string id="30000">Bélyegképek mérete</string>
-</strings>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<strings>
- <!-- settings labels -->
- <string id="30000">미리보기 크기</string>
-</strings>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<strings>
- <!-- settings labels -->
- <string id="30000">Rozmiar miniatur</string>
-</strings>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<strings>
- <!-- settings labels -->
- <string id="30000">Tamanho de miniaturas</string>
-</strings>
+++ /dev/null
-<?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>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<settings>
- <setting label="30000" type="labelenum" values="192|256|384|512|1024" id="yahooscale" default="384"/>
-</settings>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<scraper framework="1.0" date="2009-05-22">
- <CreateSearchUrl dest="3">
- <RegExp input="$$1" output="<url>http://us.music.yahooapis.com/video/v1/list/search/all/\1?appid=r6QWQGXV34H0Sl3Wq4vWJI2v9IO1XnZw5JkeifPbTq2p0S9H9kg0JUc3SVN0Yw--&amp;response=artists,images</url>" dest="3">
- <expression noclean="1"/>
- </RegExp>
- </CreateSearchUrl>
- <GetSearchResults dest="8">
- <RegExp input="$$5" output="<?xml version="1.0" encoding="iso-8859-1" standalone="yes"?><results>\1</results>" dest="8">
- <RegExp input="$$1" output="<entity><title>\4 - \1 (\2)</title><url>http://us.music.yahooapis.com/video/v1/item/\3?format=xml&amp;appid=r6QWQGXV34H0Sl3Wq4vWJI2v9IO1XnZw5JkeifPbTq2p0S9H9kg0JUc3SVN0Yw--</url></entity>" dest="5">
- <expression repeat="yes"><Video.*?title="([^"]*)".*?copyrightYear="([^"]*)".*?\/([0-9]*)\?size.*?name="([^"]*)".*?</Video></expression>
- </RegExp>
- <expression noclean="1"/>
- </RegExp>
- </GetSearchResults>
- <GetDetails dest="3">
- <RegExp input="$$5" output="<details>\1</details>" dest="3">
- <RegExp input="$$1" output="<title>\1</title>" dest="5">
- <expression><Video.*?title="([^"]*)"</expression>
- </RegExp>
- <RegExp input="$$1" output="<artist>\1</artist>" dest="5+">
- <expression repeat="yes"><Artist.*?name="([^"]*)"</expression>
- </RegExp>
- <RegExp input="$$1" output="<album>\1</album>" dest="5+">
- <expression><Release.*?title="([^"]*)"</expression>
- </RegExp>
- <RegExp input="$$1" output="<studio>\1</studio>" dest="5+">
- <expression repeat="yes">label="([^"]*)"</expression>
- </RegExp>
- <RegExp input="$$1" output="<year>\1</year>" dest="5+">
- <expression>copyrightYear="([0-9]*)"</expression>
- </RegExp>
- <RegExp input="$$1" output="<genre>\1</genre>" dest="5+">
- <expression repeat="yes"><Category.*?name="([^"]*)" rating="([^"]*)" type="Genre"></expression>
- </RegExp>
- <RegExp input="$$1" output="<thumb>http://d.yimg.com/img.music.yahoo.com/image/v1/video/\1?size=$INFO[yahooscale]</thumb>" dest="5+">
- <expression>\/([0-9]*)\?size</expression>
- </RegExp>
- <expression noclean="1"/>
- </RegExp>
- </GetDetails>
-</scraper>
<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>
[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])],
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))
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))
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
AC_SUBST(USE_LIBUDEV)
AC_SUBST(USE_LIBUSB)
AC_SUBST(USE_LIBCEC)
+AC_SUBST(USE_MYSQL)
AC_SUBST(USE_WEB_SERVER)
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"
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"
msgid "Default music video scraper"
msgstr ""
-msgctxt "#21416"
-msgid "Enable fallback based on scraper language"
-msgstr ""
+#empty string id 21416
msgctxt "#21417"
msgid "- Settings"
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"
#define __WIN__
#endif
#ifdef __WIN__
-#include <winsock.h> /* For windows */
+#include <winsock2.h> /* For windows */
#endif
#if !defined(__WIN__)
#define STDCALL
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
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
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
<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>
/*
- * 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.
*/
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 {
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 {
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;
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 *));
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
*/
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);
/*
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);
/*
* -----------------------------------------------------------------
RS_LATER_SHOWING = 8,
RS_REPEAT = 9,
RS_LOW_DISKSPACE = 11,
- RS_TUNER_BUSY = 12
+ RS_TUNER_BUSY = 12,
} cmyth_proginfo_rec_status_t;
/**
*/
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
/**
* 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);
/*
* -----------------------------------------------------------------
* -------
*/
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);
#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 */
-/** \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
* \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;
* \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;
}
}
-#endif /* __MVP_DEBUG_H */
+#endif /* __CMYTH_DEBUG_H */
+/*
+ * 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
/*
- * 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
/*
- * 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
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);
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;
/*
- * 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
*/
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 */
};
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;
};
struct cmyth_keyframe {
unsigned long keyframe_number;
- unsigned long long keyframe_pos;
+ uint64_t keyframe_pos;
};
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 {
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 */
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 {
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,
--- /dev/null
+/*
+ * 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 */
/*
- * 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
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;
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) {
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;
}
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;
/*
- * 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>
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;
{71, "05e82186"},
{72, "D78EFD6F"},
{73, "D7FE8D6F"},
- {0, 0}
+ {0, ""}
};
/*
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,
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);
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;
}
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;
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) {
int r;
char msg[256];
char reply[256];
- long long lreply;
+ int64_t lreply;
if (control == NULL)
return -EINVAL;
}
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;
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)
{
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;
+}
/*
- * 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
#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)
void
cmyth_dbg_level(int l)
{
- mvp_dbg_setlevel(&cmyth_debug_ctx, l);
+ __cmyth_dbg_setlevel(&cmyth_debug_ctx, l);
}
/*
void
cmyth_dbg_all()
{
- mvp_dbg_setlevel(&cmyth_debug_ctx, CMYTH_DBG_ALL);
+ __cmyth_dbg_setlevel(&cmyth_debug_ctx, 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);
}
/*
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);
}
/*
- * 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
/*
- * 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
#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>
/*
char msg[128];
int err;
int count;
- long long c;
+ int64_t c;
long r;
long long ret;
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;
int ret, req, nfds, rec;
char *end, *cur;
char msg[256];
- long long len64;
+ int64_t len64;
struct timeval tv;
fd_set fds;
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;
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;
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;
}
/*
- * 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>
/*
/*
- * 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
*/
#include <sys/types.h>
#include <stdlib.h>
-#ifndef _MSC_VER
-#include <unistd.h>
-#endif
#include <string.h>
#include <stdio.h>
#include <cmyth_local.h>
/*
- * 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);
{
int ret=0;
char url[1024];
- cmyth_conn_t control;
cmyth_proginfo_t loc_prog;
cmyth_file_t ft;
goto out;
}
- control = rec->rec_conn;
-
loc_prog = cmyth_recorder_get_cur_proginfo(rec);
pthread_mutex_lock(&mutex);
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;
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]);
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);
}
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);
}
}
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);
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);
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.";
/*
- * 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
/*
- * 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)
{
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);
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);
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);
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);
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
if(db->mysql == NULL)
{
db->mysql = mysql_init(NULL);
- new_conn = 1;
if(db->mysql == NULL)
{
fprintf(stderr,"%s: mysql_init() failed, insufficient memory?",
}
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);
}
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);
}
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;
}
}
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];
cmyth_dbg(CMYTH_DBG_ERROR, "%s: mysql_query() Failed: %s\n",
__FUNCTION__, mysql_error(db->mysql));
}
+ mysql_free_result(res);
return rows;
}
/*
- * 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>
/*
- * 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>
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__);
}
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;
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;
}
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) {
"%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
}
/*
- * 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
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",
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) {
"%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
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)
{
/*
- * 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>
/*
- * 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>
/*
/*
- * 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)
*
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,
ret = 0;
err:
- PRINTF("** SSDEBUG: recorder paused:\n");
pthread_mutex_unlock(&mutex);
return ret;
/*
- * 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>
/*
int err, count;
int r;
- long long size, fill;
+ int64_t size, fill;
char msg[256];
char url[1024];
char buf[32];
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);
}
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);
char msg[128];
int err;
int count;
- long long c;
+ int64_t c;
long r;
long long ret;
cmyth_ringbuf_t ring;
}
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);
/*
- * 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>
#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 */
/*
- * 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"
}
}
- 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.
int consumed;
int tmp;
- *buf = 0;
+ *buf = 0;
if (!err) {
err = &tmp;
}
/*
- * 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)
*
* 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;
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)
*
* 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;
}
* 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;
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;
}
out:
- if (host && port) {
+ if (host && port && path) {
char tmp = *(port - 1);
*(port - 1) = '\0';
if (p->proginfo_host)
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;
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)
*/
/*
* 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) {
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;
}
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;
}
*err = EINVAL;
return 0;
}
- err = 0;
+ *err = 0;
if (!conn) {
cmyth_dbg(CMYTH_DBG_ERROR, "%s: no connection\n",
__FUNCTION__);
/*
- * 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)
#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);
/*
void
refmem_dbg_level(int l)
{
- mvp_dbg_setlevel(&refmem_debug_ctx, l);
+ __cmyth_dbg_setlevel(&refmem_debug_ctx, l);
}
/*
void
refmem_dbg_all()
{
- mvp_dbg_setlevel(&refmem_debug_ctx, REF_DBG_ALL);
+ __cmyth_dbg_setlevel(&refmem_debug_ctx, REF_DBG_ALL);
}
/*
void
refmem_dbg_none()
{
- mvp_dbg_setlevel(&refmem_debug_ctx, REF_DBG_NONE);
+ __cmyth_dbg_setlevel(&refmem_debug_ctx, REF_DBG_NONE);
}
/*
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);
}
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
- <CompileAs>CompileAsC</CompileAs>
</ClCompile>
<Link>
<AdditionalDependencies>libexpat.lib;%(AdditionalDependencies)</AdditionalDependencies>
<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
<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>
<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">
<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>
<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>
<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">
<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>
<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>
<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">
<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>
<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">
<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>
<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" />
<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>
<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>
<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>
</ClCompile>
<Lib>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
- <IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<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>
<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>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
</ClCompile>
<Link>
<OutputFile>$(OutDir)libexif.exe</OutputFile>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
- <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<CompileAs>CompileAsCpp</CompileAs>
</ClCompile>
<Lib>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
- <IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<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>
</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>
-LIBRARY lame_enc.DLL
+LIBRARY libmp3lame.dll
EXPORTS
lame_init @1
<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>
<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>
<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">
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
- <PrecompiledHeader>
- </PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
</ClCompile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
- <PrecompiledHeader>
- </PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
<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>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
- <PrecompiledHeader>
- </PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<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>
<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>
<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>
<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>
<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>
<_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" />
<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">
<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">
<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>
<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>
--- /dev/null
+<node order="9" type="folder">
+ <label>20459</label>
+ <path>videodb://1/9</path>
+ <icon>DefaultTags.png</icon>
+</node>
#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;
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",
{ NULL, 0 }
};
-static void
+static void _X_NORETURN
usage(void)
{
fprintf(stderr, "usage: %s [options]\n", program_name);
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");
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;
/*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)
{
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),
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 {
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 {
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 {
crtc_t *current_crtc_info;
name_t mode;
- float refresh;
+ double refresh;
XRRModeInfo *mode_info;
name_t addmode;
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 {
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)
}
}
+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;
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);
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;
}
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++)
{
}
if ((name->kind & name_string) && !strcmp (name->string, mode->name))
{
- float dist;
+ double dist;
if (refresh)
dist = fabs (mode_refresh (mode) - refresh);
bestDist = dist;
best = mode;
}
- break;
}
}
return best;
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)
}
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
return best;
}
-XRRModeInfo *
+static XRRModeInfo *
preferred_mode (output_t *output)
{
XRROutputInfo *output_info = output->output_info;
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)
{
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))
/* 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);
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");
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");
}
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;
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
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;
}
}
}
+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)
{
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)
{
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,
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;
}
* 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;
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
*/
{
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;
}
/*
- * 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 ();
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);
}
}
}
+ output->found = True;
/*
* Automatic mode -- track connection state and enable/disable outputs
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;
/*
* Test whether 'crtc' can be used for 'output'
*/
-Bool
+static Bool
check_crtc_for_output (crtc_t *crtc, output_t *output)
{
int c;
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;
}
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;
}
{
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;
}
}
}
}
-#endif
-
-void
+
+static void
disable_outputs (output_t *outputs)
{
while (outputs)
/*
* find the best mapping from output to crtc available
*/
-int
+static int
pick_crtcs_score (output_t *outputs)
{
output_t *output;
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;
*/
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;
+ }
}
}
/*
}
}
+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)
{
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;
int i, j;
SizeID current_size;
short current_rate;
- float rate = -1;
+ double rate = -1;
int size = -1;
int dirind = 0;
Bool setit = False;
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 ();
}
if (!strcmp("-help", argv[i])) {
usage();
+ action_requested = True;
continue;
}
if (!strcmp ("--verbose", argv[i])) {
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;
}
!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;
}
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;
}
}
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])) {
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;
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;
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;
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;
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();
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);
&fb_width, &fb_height) != 2)
usage ();
setit_1_2 = True;
+ action_requested = True;
continue;
}
if (!strcmp ("--fbmm", argv[i])) {
&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])) {
else
automatic = True;
setit_1_2 = True;
+ action_requested = True;
continue;
}
if (!strcmp ("--q12", argv[i]))
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;
m->action = umode_create;
umodes = m;
modeit = True;
+ action_requested = True;
continue;
}
if (!strcmp ("--rmmode", argv[i]))
m->next = umodes;
umodes = m;
modeit = True;
+ action_requested = True;
continue;
}
if (!strcmp ("--addmode", argv[i]))
m->next = umodes;
umodes = m;
modeit = True;
+ action_requested = True;
continue;
}
if (!strcmp ("--delmode", argv[i]))
m->next = umodes;
umodes = m;
modeit = True;
+ action_requested = True;
continue;
}
-#endif
usage();
}
+ if (!action_requested)
+ query = True;
if (verbose)
{
query = True;
query_1 = True;
}
+/*
+ if (version)
+ printf("xrandr program version " VERSION "\n");
+*/
+
dpy = XOpenDisplay (display_name);
if (dpy == NULL) {
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();
if (has_1_2 && propit)
{
- get_screen ();
+ get_screen (current);
get_crtcs();
get_outputs();
{
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;
XRRPropertyInfo *propinfo;
type = AnyPropertyType;
- format=0;
if (XRRGetOutputProperty (dpy, output->output.xid, name,
0, 100, False, False,
ulong_value = XInternAtom (dpy, prop->value, False);
data = (unsigned char *) &ulong_value;
nelements = 1;
- format = 32;
}
else if ((type == XA_STRING || type == AnyPropertyType))
{
nelements = strlen (prop->value);
format = 8;
}
+ else
+ continue;
XRRChangeOutputProperty (dpy, output->output.xid,
name, type, format, PropModeReplace,
data, nelements);
}
if (setit_1_2)
{
- get_screen ();
+ get_screen (current);
get_crtcs ();
get_outputs ();
set_positions ();
}
/*
+ * Set panning
+ */
+ set_panning ();
+
+ /*
+ * Set gamma on crtc's that belong to the outputs.
+ */
+ set_gamma ();
+
+ /*
* Now apply all of the changes
*/
apply ();
#define ModeShown 0x80000000
- get_screen ();
+ get_screen (current);
get_crtcs ();
get_outputs ();
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)
if ((rotations >> i) & 1) {
if (!first) printf (" "); first = False;
printf("%s", direction[i]);
- first = False;
}
}
if (rotations & RR_Reflect_X)
}
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)
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)
{
} 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:");
}
}
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)
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,
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);
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;
ResetScreenSaver();
#ifdef HAS_SDL_JOYSTICK
- g_Joystick.Initialize();
+ g_Joystick.SetEnabled(g_guiSettings.GetBool("input.enablejoystick"));
#endif
return true;
#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))
{
g_Joystick.ResetAxis(abs(bid));
}
}
- int position;
+ int position = 0;
if (g_Joystick.GetHat(bid, position))
{
// reset Idle Timer
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);
{
#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);
{
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
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)
}
}
SaveMusicScanSettings();
- m_musicInfoScanner->Start(strDirectory);
+ m_musicInfoScanner->Start(strDirectory, flags);
}
void CApplication::StartMusicAlbumScan(const CStdString& strDirectory,
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);
{ "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 },
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")
{
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());
#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
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 ..
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);
- }
-}
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_)
#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;
CGUITextureManager g_TextureManager;
CGUILargeTextureManager g_largeTextureManager;
CMouseStat g_Mouse;
+#if defined(HAS_SDL_JOYSTICK)
+ CJoystick g_Joystick;
+#endif
CGUIPassword g_passwordManager;
CGUIInfoManager g_infoManager;
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;
}
// 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();
}
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;
}
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);
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)
AE_ENGINE_PULSE
};
-class IAE;
class CAEFactory
{
public:
*/
#include "AESinkFactory.h"
+#include "Interfaces/AESink.h"
#include "utils/SystemInfo.h"
#include "utils/log.h"
#include "settings/AdvancedSettings.h"
#include <string>
#include <vector>
-#include "Interfaces/AESink.h"
#include "Utils/AEDeviceInfo.h"
+class IAESink;
+
typedef struct
{
std::string m_sinkName;
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();
streamDesc->mFormatFlags |= kAudioFormatFlagIsSignedInteger;
break;
case AE_FMT_S16LE:
- streamDesc->mFormatFlags |= kAudioFormatFlagsNativeEndian;
streamDesc->mFormatFlags |= kAudioFormatFlagIsSignedInteger;
break;
case AE_FMT_S16BE:
streamDesc->mFormatFlags |= kAudioFormatFlagIsSignedInteger;
break;
case AE_FMT_S16LE:
- streamDesc->mFormatFlags |= kAudioFormatFlagsNativeEndian;
streamDesc->mFormatFlags |= kAudioFormatFlagIsSignedInteger;
break;
case AE_FMT_S16BE:
#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"
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;
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)
/* 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)
}
}
-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(); )
{
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 */
/* 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)
}
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)
}
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)
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;
/* 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)
m_encodedBuffer.Shift(NULL, wroteFrames * m_sinkFormat.m_frameSize);
}
+ return encodedFrames;
}
unsigned int CSoftAE::RunRawStreamStage(unsigned int channelCount, void *out, bool &restart)
#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
{
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);
#include "AEFactory.h"
#include "AEAudioFormat.h"
-#include "Utils/AEConvert.h"
-#include "Utils/AERemap.h"
-#include "Utils/AEUtil.h"
#include "SoftAE.h"
#include "SoftAESound.h"
#include "Interfaces/AESound.h"
#include "Utils/AEWAVLoader.h"
-class CWAVLoader;
class CSoftAESound : public IAESound
{
public:
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;
}
#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;
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
#include "utils/StdString.h"
#include "AE.h"
-class IAE;
class IAESound
{
protected:
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;
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;
#include <stdint.h>
#include <limits.h>
+#include <set>
#include <sstream>
#include "AESinkALSA.h"
#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
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)
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);
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;
{
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)
{
CLog::Log(LOGERROR, "CAESinkALSA::InitializeHW - Failed to set the parameters");
return false;
- }
+ }
}
}
}
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;
snd_pcm_nonblock(m_pcm, 1);
}
-void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list)
+void CAESinkALSA::AppendParams(std::string &device, const std::string ¶ms)
{
- /* 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 ¶ms, 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 ¶ms, 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 ¶m, 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)
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
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;
bool InitializeHW(AEAudioFormat &format);
bool InitializeSW(AEAudioFormat &format);
+ static void AppendParams(std::string &device, const std::string ¶ms);
+ 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 ¶ms, snd_pcm_t **pcmp, snd_config_t *lconf);
+ static bool OpenPCMDevice(const std::string &name, const std::string ¶ms, int channels, snd_pcm_t **pcmp, snd_config_t *lconf, bool preferDmixStereo = false);
+
+ static void GetParamFromName(const std::string &name, const std::string ¶m, 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
#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;
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;
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);
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);
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:
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);
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:
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);
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:
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()
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()
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;
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);
*/
#include "AEBitstreamPacker.h"
+#include "AEPackIEC61937.h"
+#include "AEStreamInfo.h"
#include <stdint.h>
#include <stddef.h>
#include <string.h>
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();
#include <stdint.h>
#include <list>
#include "AEPackIEC61937.h"
-#include "AEStreamInfo.h"
+
+class CAEStreamInfo;
class CAEBitstreamPacker
{
#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);
#include <sstream>
#include "AEDeviceInfo.h"
+#include "AEUtil.h"
CAEDeviceInfo::operator std::string()
{
#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;
*/
#include "AEELDParser.h"
+#include "AEDeviceInfo.h"
#include "utils/EndianSwap.h"
#include <string.h>
#include <stdint.h>
#include <cstring>
-#include "AEDeviceInfo.h"
+
+class CAEDeviceInfo;
class CAEELDParser {
public:
*
*/
-/* DTS spec shows it suppors both BE and LE, we should not need to convert */
-
#include <cassert>
#include "system.h"
#include "AEPackIEC61937.h"
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)
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;
+}
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,
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;
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;
+}
*/
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);
};
#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;
#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;
*/
#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"
#include "system.h"
#include "BXAcodec.h"
#include "utils/EndianSwap.h"
+#include "cores/AudioEngine/Utils/AEUtil.h"
BXACodec::BXACodec()
{
#include "FLACcodec.h"
#include "music/tags/FlacTag.h"
#include "utils/log.h"
+#include "cores/AudioEngine/Utils/AEUtil.h"
using namespace MUSIC_INFO;
#include "filesystem/File.h"
#include "cores/AudioEngine/AEAudioFormat.h"
-#include "cores/AudioEngine/Utils/AEUtil.h"
#define READ_EOF -1
#define READ_SUCCESS 0
// 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;
#include "MP3codec.h"
#include "FileItem.h"
#include "utils/log.h"
+#include "cores/AudioEngine/Utils/AEUtil.h"
using namespace MUSIC_INFO;
#include "FileItem.h"
#include "utils/log.h"
#include "utils/URIUtils.h"
+#include "cores/AudioEngine/Utils/AEUtil.h"
using namespace MUSIC_INFO;
#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())
{
}
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();
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") &&
)
{
//do not crossfade when playing consecutive albumtracks
- m_crossFadeTime = 0;
+ m_upcomingCrossfadeMS = 0;
}
}
}
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))
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;
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);
/* 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 */
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;
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;
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();
}
#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
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 */
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);
};
#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;
m_sqlite = true;
+#ifdef HAS_MYSQL
if ( dbSettings.type.Equals("mysql") )
{
// check we have all information before we cancel the fallback
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());
{
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());
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())
{
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;
}
#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")
}
}//namespace
+#endif //HAS_MYSQL
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,
#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] = ")!@#$%^&*([]{}-_=+;:\'\",.<>/?\\|`~ ";
{
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)
}
}
break;
+
+ case GUI_MSG_SET_TEXT:
+ SetText(message.GetLabel());
+
+ // close the dialog if requested
+ if (message.GetParam1() > 0)
+ OnOK();
+ break;
}
return true;
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)
#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
{
}
+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)
}
}
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);
}
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;
}
}
}
- 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)
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);
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();
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);
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;
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))
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)
* 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);
}
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)
{
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
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
#include "DirectoryNodeRecentlyAddedMusicVideos.h"
#include "DirectoryNodeTitleMusicVideos.h"
#include "DirectoryNodeMusicVideoAlbum.h"
+#include "DirectoryNodeTags.h"
#include "video/VideoInfoTag.h"
#include "URL.h"
#include "settings/AdvancedSettings.h"
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:
NODE_TYPE_TITLE_MUSICVIDEOS,
NODE_TYPE_MUSICVIDEOS_ALBUM,
NODE_TYPE_SETS,
- NODE_TYPE_COUNTRY
+ NODE_TYPE_COUNTRY,
+ NODE_TYPE_TAGS
} NODE_TYPE;
typedef struct {
{ 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)
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+#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;
+ };
+ }
+}
+
+
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();
DirectoryNodeSeasons.cpp \
DirectoryNodeSets.cpp \
DirectoryNodeStudio.cpp \
+ DirectoryNodeTags.cpp \
DirectoryNodeTitleMovies.cpp \
DirectoryNodeTitleMusicVideos.cpp \
DirectoryNodeTitleTvShows.cpp \
m_idMVideo = -1;
m_idAlbum = -1;
m_idSet = -1;
+ m_idTag = -1;
}
void CQueryParams::SetQueryParam(NODE_TYPE NodeType, const CStdString& strNodeName)
case NODE_TYPE_SETS:
m_idSet = idDb;
break;
+ case NODE_TYPE_TAGS:
+ m_idTag = idDb;
+ break;
default:
break;
}
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);
long m_idMVideo;
long m_idAlbum;
long m_idSet;
+ long m_idTag;
};
}
}
{
m_smsTimer.Stop();
}
+ else if (message.GetMessage() == GUI_MSG_SET_TEXT)
+ {
+ SetLabel2(message.GetLabel());
+ UpdateText();
+ }
return CGUIButtonControl::OnMessage(message);
}
*/
#define GUI_MSG_UNFOCUS_ALL 41
+#define GUI_MSG_SET_TEXT 42
+
#define GUI_MSG_USER 1000
/*!
}
#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;
#pragma once
#include <map>
+#include <vector>
#include "system.h" // for HAS_EVENT_SERVER, HAS_SDL_JOYSTICK, HAS_LIRC
#ifdef HAS_EVENT_SERVER
/// 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
using namespace std;
-CJoystick g_Joystick; // global
-
CJoystick::CJoystick()
{
- Reset();
+ Reset(true);
+ m_joystickEnabled = false;
m_NumAxes = 0;
m_AxisId = 0;
m_JoyId = 0;
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();
SDL_JoystickEventState(SDL_DISABLE);
}
-void CJoystick::Reset(bool axis)
+void CJoystick::Reset(bool axis /*=false*/)
{
if (axis)
{
void CJoystick::Update()
{
+ if (!IsEnabled())
+ return;
+
int buttonId = -1;
int axisId = -1;
int hatId = -1;
void CJoystick::Update(SDL_Event& joyEvent)
{
+ if (!IsEnabled())
+ return;
+
int buttonId = -1;
int axisId = -1;
int joyId = -1;
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)
bool CJoystick::GetButton(int &id, bool consider_repeat)
{
- if (!IsButtonActive())
+ if (!IsEnabled() || !IsButtonActive())
+ {
+ id = 0;
return false;
+ }
if (!consider_repeat)
{
id = m_ButtonId;
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;
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;
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)
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;
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();
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;
int m_JoyId;
int m_NumAxes;
int m_DeadzoneRange;
+ bool m_joystickEnabled;
uint32_t m_pressTicksButton;
uint32_t m_pressTicksHat;
uint8_t m_ActiveFlags;
using namespace std;
-CJoystick g_Joystick; // global
-
extern HWND g_hWnd;
#define MAX_AXISAMOUNT 32768
CJoystick::CJoystick()
{
- Reset();
+ Reset(true);
+ m_joystickEnabled = false;
m_NumAxes = 0;
m_AxisId = 0;
m_JoyId = 0;
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;
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 );
}
void CJoystick::Initialize()
{
+ if (!IsEnabled())
+ return;
+
HRESULT hr;
// clear old joystick names
SetDeadzone(g_advancedSettings.m_controllerDeadzone);
}
-void CJoystick::Reset(bool axis)
+void CJoystick::Reset(bool axis /*=true*/)
{
if (axis)
{
void CJoystick::Update()
{
+ if (!IsEnabled())
+ return;
+
int buttonId = -1;
int axisId = -1;
int hatId = -1;
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)
bool CJoystick::GetButton(int &id, bool consider_repeat)
{
- if (!IsButtonActive())
+ if (!IsEnabled() || !IsButtonActive())
+ {
+ id = 0;
return false;
+ }
if (!consider_repeat)
{
id = m_ButtonId;
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;
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;
void CJoystick::Acquire()
{
+ if (!IsEnabled())
+ return;
if(!m_pJoysticks.empty())
{
CLog::Log(LOGDEBUG, __FUNCTION__": Focus back, acquire Joysticks");
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();
int m_JoyId;
int m_NumAxes;
int m_DeadzoneRange;
+ bool m_joystickEnabled;
uint32_t m_pressTicksButton;
uint32_t m_pressTicksHat;
uint8_t m_ActiveFlags;
{
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
return "AudioLibrary";
case Application:
return "Application";
+ case Input:
+ return "Input";
case Other:
return "Other";
default:
#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;
}
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;
}
return ACK;
}
+JSONRPC_STATUS CInputOperations::SendText(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, 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 ¶meterObject, 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 ¶meterObject, CVariant &result)
{
return SendKey(XBMCVK_LEFT);
{
return activateWindow(WINDOW_HOME);
}
+
+JSONRPC_STATUS CInputOperations::ShowCodec(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result)
+{
+ return SendAction(ACTION_SHOW_CODEC);
+}
+
+JSONRPC_STATUS CInputOperations::ShowOSD(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result)
+{
+ return SendAction(ACTION_SHOW_OSD);
+}
*/
#include "JSONRPC.h"
+#include "guilib/Key.h"
#include "threads/CriticalSection.h"
#include "utils/StdString.h"
class CInputOperations
{
public:
- static uint32_t GetKey();
+ static CKey GetKey();
+
+ static JSONRPC_STATUS SendText(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result);
+ static JSONRPC_STATUS ExecuteAction(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result);
static JSONRPC_STATUS Left(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result);
static JSONRPC_STATUS Right(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result);
static JSONRPC_STATUS Info(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result);
static JSONRPC_STATUS Home(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result);
- static JSONRPC_STATUS SendKey(uint32_t keyCode);
+ static JSONRPC_STATUS ShowCodec(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result);
+ static JSONRPC_STATUS ShowOSD(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, 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:
static bool handleScreenSaver();
static CCriticalSection m_critSection;
- static uint32_t m_key;
+ static CKey m_key;
};
}
#include "JSONRPC.h"
#include "ServiceDescription.h"
+#include "input/ButtonTranslator.h"
#include "interfaces/AnnouncementManager.h"
#include "settings/AdvancedSettings.h"
#include "utils/log.h"
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++)
{ "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 },
{ "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 },
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 \
"\"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\","
"}"
"],"
"\"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"
"}"
};
}
"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",
}
],
"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
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");
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;
}
m_bCanInterrupt = false;
m_currentItem=0;
m_itemCount=0;
+ m_flags = 0;
}
CMusicInfoScanner::~CMusicInfoScanner()
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
// 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());
{
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);
}
}
- if (g_guiSettings.GetBool("musiclibrary.downloadinfo"))
+ if (m_flags & SCAN_ONLINE)
{
for (set<long>::iterator it = albumsToScan.begin(); it != albumsToScan.end(); ++it)
{
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
{
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;
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())
// 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);
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();
std::set<CStdString> m_pathsToCount;
std::vector<long> m_artistsScanned;
std::vector<long> m_albumsScanned;
+ int m_flags;
};
}
#include "ImusicInfoTagLoader.h"
#include "DllASAP.h"
-#include "cores/paplayer/ASAPCodec.h"
namespace MUSIC_INFO
{
#include "utils/URIUtils.h"
#include "FileItem.h"
+#ifdef HAS_ASAP_CODEC
+#include "cores/paplayer/ASAPCodec.h"
+#endif
+
using namespace MUSIC_INFO;
CMusicInfoTagLoaderFactory::CMusicInfoTagLoaderFactory()
#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"
{
}
+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"))
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
#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);
{ "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)
fields.push_back(FieldFilename);
fields.push_back(FieldPath);
fields.push_back(FieldSet);
+ fields.push_back(FieldTag);
fields.push_back(FieldDateAdded);
isVideo = true;
}
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")
{
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;
}
m_airTunesPort = 36666;
m_airPlayPort = 36667;
m_initialized = true;
+
+ m_databaseMusic.Reset();
+ m_databaseVideo.Reset();
}
bool CAdvancedSettings::Load()
class DatabaseSettings
{
public:
+ void Reset()
+ {
+ type.clear();
+ host.clear();
+ port.clear();
+ user.clear();
+ pass.clear();
+ name.clear();
+ };
CStdString type;
CStdString host;
CStdString port;
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");
#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())
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);
#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"
{
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");
#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
#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
// 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 ;
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
{
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;
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
{
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
{
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
{
// 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();
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;
FieldAudioCodec,
FieldAudioLanguage,
FieldSubtitleLanguage,
- FieldProductionCode
+ FieldProductionCode,
+ FieldTag
} Field;
typedef std::set<Field> Fields;
--- /dev/null
+/*
+ * 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]);
+}
+
*
*/
- /* Functions taken from SDL (SDL_endian.h) */
+ /* Endian_SwapXX functions taken from SDL (SDL_endian.h) */
#ifndef __ENDIAN_SWAP_H__
#define __ENDIAN_SWAP_H__
}
+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)
DatabaseUtils.cpp \
DownloadQueue.cpp \
DownloadQueueManager.cpp \
+ EndianSwap.cpp \
Fanart.cpp \
fastmemcpy.c \
fastmemcpy-arm.S \
if (videodatabase.GetRecentlyAddedEpisodesNav("videodb://5/", TVShowItems, NUM_ITEMS))
{
- std::map<int, std::string> showThumbs;
for (; i < TVShowItems.Size(); ++i)
{
CFileItemPtr item = TVShowItems.Get(i);
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"));
}
{
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;
}
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)
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();
}
{
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;
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);
}
}
-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();
}
}
+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)
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]));
}
}
+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);
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);
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;
}
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)
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)
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);
}
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));
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);
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);
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());
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);
// 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);
*/
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"; };
m_cast.clear();
m_set.clear();
m_setId.clear();
+ m_tags.clear();
m_strFile.clear();
m_strPath.clear();
m_strIMDBNumber.clear();
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);
ar << m_set;
ar << m_setId;
+ ar << m_tags;
ar << m_strRuntime;
ar << m_strFile;
ar << m_strPath;
ar >> m_set;
ar >> m_setId;
+ ar >> m_tags;
ar >> m_strRuntime;
ar >> m_strFile;
ar >> m_strPath;
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;
}
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");
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;
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();
}
}
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);
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
{
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);
}
#include "utils/URIUtils.h"
#include "utils/StringUtils.h"
#include "TextureCache.h"
+#include "dialogs/GUIDialogKeyboard.h"
using namespace XFILE;
using namespace VIDEODATABASEDIRECTORY;
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/"))
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("");
}
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;
}
{
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/") &&
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()) ||
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)
{
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
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("");
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);
}
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"))
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
}
}
}
+
+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 "";
+}
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;
};
<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>
<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>
<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>
// 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