diff options
52 files changed, 1744 insertions, 986 deletions
diff --git a/addons/game.controller.default/addon.xml b/addons/game.controller.default/addon.xml index 3dcc9ba40a..86c67770d3 100644 --- a/addons/game.controller.default/addon.xml +++ b/addons/game.controller.default/addon.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon id="game.controller.default" name="Default Controller" - version="1.0.5" + version="1.0.6" provider-name="Team Kodi"> <requires> </requires> @@ -9,7 +9,7 @@ <extension point="xbmc.addon.metadata"> <summary lang="en_GB">Default Controller</summary> <description lang="en_GB">The default media center controller is based on the Xbox 360 controller.</description> - <disclaimer>Image credit: Wikipedia (wikipedia.org)</disclaimer> + <disclaimer lang="en_GB">Image credit: Wikipedia (wikipedia.org)</disclaimer> <platform>all</platform> <assets> <icon>resources/icon.png</icon> diff --git a/addons/metadata.album.universal/addon.xml b/addons/metadata.album.universal/addon.xml index d4b6afcb13..d84aae24ec 100644 --- a/addons/metadata.album.universal/addon.xml +++ b/addons/metadata.album.universal/addon.xml @@ -1,7 +1,7 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon id="metadata.album.universal" name="Universal Album Scraper" - version="2.7.3" + version="3.1.1" provider-name="Olympia, Team Kodi"> <requires> <import addon="xbmc.metadata" version="2.1.0"/> diff --git a/addons/metadata.album.universal/albumuniversal.xml b/addons/metadata.album.universal/albumuniversal.xml index be1b5d9f92..c913d7e3d8 100644 --- a/addons/metadata.album.universal/albumuniversal.xml +++ b/addons/metadata.album.universal/albumuniversal.xml @@ -26,29 +26,11 @@ </CreateAlbumSearchUrl> <GetAlbumSearchResults dest="8"> <RegExp input="$$5" output="<results sorted="yes">\1</results>" dest="8"> - <RegExp input="$$1" output="<entity><year>\5-\4-T#\6</year><artist>\3</artist><title>\2</title><url cache="mb-\1-album.xml">$INFO[mbsite]/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings</url></entity>" dest="5"> - <expression repeat="yes">id="([^"]*)"><title>([^<]*)</title><status>Official</status>(?:<packaging>[^<]*</packaging>)?<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[^<]*</alias>)*</alias-list>)*</artist></name-credit>(?:<name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>[^<]*</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>(?:<alias[^<]*</alias>)*</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">$INFO[mbsite]/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings</url></entity>" dest="5+"> - <expression repeat="yes">id="([^"]*)"><title>([^<]*)</title><status>Official</status>(?:<packaging>[^<]*</packaging>)?<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[^<]*</alias>)*</alias-list>)*</artist></name-credit>(?:<name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>[^<]*</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>(?:<alias[^<]*</alias>)*</alias-list>)*</artist></name-credit>)*</artist-credit><release-group(?:\stype="[^"]*")*\sid="[^"]*">(?:<primary-type>[^<]*</primary-type>)*(?:<secondary-type-list>(?:<secondary-type>[^<]*</secondary-type>)+</secondary-type-list>)*</release-group>(?:<date>(\d{4})[^<]*</date>)*(?:<country>)*([^<]*)?.*?<track-list\scount="(\d+)</expression> - </RegExp> - <RegExp input="$$1" output="<entity><year>\6-\5-T#\7</year><artist>\4</artist><title>\3</title><relevance scale="100">\2</relevance><url cache="mb-\1-album.xml">$INFO[mbsite]/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings</url></entity>" dest="5+"> - <expression repeat="yes">id="([^"]*)" ext:score="(\d*)"><title>([^<]*)</title><status>Official</status>(?:<disambiguation>[^<]*</disambiguation>)*(?:<packaging>[^<]*</packaging>)?<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[^<]*</alias>)*</alias-list>)*</artist></name-credit>(?:<name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>[^<]*</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>(?:<alias[^<]*</alias>)*</alias-list>)*</artist></name-credit>)*</artist-credit><release-group\sid="[^"]*"\stype="Album">(?:<primary-type>[^<]*</primary-type>)*(?:<secondary-type-list>(?:<secondary-type>[^<]*</secondary-type>)+</secondary-type-list>)*</release-group>(?:<date>(\d{4})[^<]*</date>)*(?:<country>)*([^<]*)?.*?<track-list\scount="(\d+)</expression> - </RegExp> - <RegExp input="$$1" output="<entity><year>\6-\5-T#\7</year><artist>\4</artist><title>\3</title><relevance scale="100">\2</relevance><url cache="mb-\1-album.xml">$INFO[mbsite]/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings</url></entity>" dest="5+"> - <expression repeat="yes">id="([^"]*)" ext:score="(\d*)"><title>([^<]*)</title><status>Official</status>(?:<disambiguation>[^<]*</disambiguation>)*(?:<packaging>[^<]*</packaging>)?<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[^<]*</alias>)*</alias-list>)*</artist></name-credit>(?:<name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>[^<]*</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>(?:<alias[^<]*</alias>)*</alias-list>)*</artist></name-credit>)*</artist-credit><release-group\sid="[^"]*"(?:\stype="[^"]*")*>(?:<primary-type>[^<]*</primary-type>)*(?:<secondary-type-list>(?:<secondary-type>[^<]*</secondary-type>)+</secondary-type-list>)*</release-group>(?:<date>(\d{4})[^<]*</date>)*(?:<country>)*([^<]*)?.*?<track-list\scount="(\d+)</expression> - </RegExp> - <RegExp input="$$1" output="<entity><year>\5-\4-T#\6</year><artist>\3</artist><title>\2</title><url cache="mb-\1-album.xml">$INFO[mbsite]/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings</url></entity>" dest="5+"> - <expression repeat="yes">id="([^"]*)"><title>([^<]*)</title><status>(?!Official)[^<]*</status>(?:<disambiguation>[^<]*</disambiguation>)*(?:<packaging>[^<]*</packaging>)?<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[^<]*</alias>)*</alias-list>)*</artist></name-credit>(?:<name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>[^<]*</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>(?:<alias[^<]*</alias>)*</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">$INFO[mbsite]/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings</url></entity>" dest="5+"> - <expression repeat="yes">id="([^"]*)"><title>([^<]*)</title><status>(?!Official)[^<]*</status>(?:<disambiguation>[^<]*</disambiguation>)*(?:<packaging>[^<]*</packaging>)?<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[^<]*</alias>)*</alias-list>)*</artist></name-credit>(?:<name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>[^<]*</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>(?:<alias[^<]*</alias>)*</alias-list>)*</artist></name-credit>)*</artist-credit><release-group(?:\stype="[^"]*")*\sid="[^"]*">(?:<primary-type>[^<]*</primary-type>)*(?:<secondary-type-list>(?:<secondary-type>[^<]*</secondary-type>)+</secondary-type-list>)*</release-group>(?:<date>(\d{4})[^<]*</date>)*(?:<country>)*([^<]*)?.*?<track-list\scount="(\d+)</expression> - </RegExp> - <RegExp input="$$1" output="<entity><year>\6-\5-T#\7</year><artist>\4</artist><title>\3</title><relevance scale="100">\2</relevance><url cache="mb-\1-album.xml">$INFO[mbsite]/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings</url></entity>" dest="5+"> - <expression repeat="yes">id="([^"]*)" ext:score="(\d*)"><title>([^<]*)</title><status>(?!Official)[^<]*</status>(?:<disambiguation>[^<]*</disambiguation>)*(?:<packaging>[^<]*</packaging>)?<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[^<]*</alias>)*</alias-list>)*</artist></name-credit>(?:<name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>[^<]*</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>(?:<alias[^<]*</alias>)*</alias-list>)*</artist></name-credit>)*</artist-credit><release-group\sid="[^"]*"\stype="Album">(?:<primary-type>[^<]*</primary-type>)*(?:<secondary-type-list>(?:<secondary-type>[^<]*</secondary-type>)+</secondary-type-list>)*</release-group>(?:<date>(\d{4})[^<]*</date>)*(?:<country>)*([^<]*)?.*?<track-list\scount="(\d+)</expression> + <RegExp input="$$1" output="<entity><year>\6-\5-T#\7</year><artist>\4</artist><title>\3</title><relevance scale="100">\2</relevance><url cache="mb-\1-album.xml">$INFO[mbsite]/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings</url></entity>" dest="5"> + <expression repeat="yes">release\sid="([^"]*)"[^:]*:score="(\d*)"><title>([^<]*)</title><status>Official</status>(?:<disambiguation>[^<]*</disambiguation>)*(?:<packaging>[^<]*</packaging>)*<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[^<]*</alias>)*</alias-list>)*</artist></name-credit>(?:<name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>[^<]*</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>(?:<alias[^<]*</alias>)*</alias-list>)*</artist></name-credit>)*</artist-credit><release-group\sid="[^"]*"\stype="Album"\stype-id="[^"]*"><title>[^<]*</title>(?:<disambiguation>[^<]*</disambiguation>)*(?:<primary-type\sid="[^"]*">[^<]*</primary-type>)*(?:<secondary-type-list>(?:<secondary-type\sid="[^"]*">[^<]*</secondary-type>)+</secondary-type-list>)*</release-group>(?:<date>(\d{4})[^<]*</date>)*(?:<country>)*([^<]*)?.*?<track-list\scount="(\d+).*?</release></expression> </RegExp> <RegExp input="$$1" output="<entity><year>\6-\5-T#\7</year><artist>\4</artist><title>\3</title><relevance scale="100">\2</relevance><url cache="mb-\1-album.xml">$INFO[mbsite]/ws/2/release/\1?inc=recordings+release-groups+artists+labels+ratings</url></entity>" dest="5+"> - <expression repeat="yes">id="([^"]*)" ext:score="(\d*)"><title>([^<]*)</title><status>(?!Official)[^<]*</status>(?:<disambiguation>[^<]*</disambiguation>)*(?:<packaging>[^<]*</packaging>)?<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[^<]*</alias>)*</alias-list>)*</artist></name-credit>(?:<name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>[^<]*</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>(?:<alias[^<]*</alias>)*</alias-list>)*</artist></name-credit>)*</artist-credit><release-group\sid="[^"]*"(?:\stype="[^"]*")*>(?:<primary-type>[^<]*</primary-type>)*(?:<secondary-type-list>(?:<secondary-type>[^<]*</secondary-type>)+</secondary-type-list>)*</release-group>(?:<date>(\d{4})[^<]*</date>)*(?:<country>)*([^<]*)?.*?<track-list\scount="(\d+)</expression> + <expression repeat="yes">release\sid="([^"]*)"[^:]*:score="(\d*)"><title>([^<]*)</title><status>Official</status>(?:<disambiguation>[^<]*</disambiguation>)*(?:<packaging>[^<]*</packaging>)*<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[^<]*</alias>)*</alias-list>)*</artist></name-credit>(?:<name-credit(?:>)*(?:\sjoinphrase="[^"]*">)*(?:<name>[^<]*</name)*(?:>)*<artist\sid="[^"]*"><name>[^<]*</name>(?:<sort-name>[^<]*</sort-name>)*(?:<disambiguation>[^<]*</disambiguation>)*(?:<alias-list>(?:<alias[^<]*</alias>)*</alias-list>)*</artist></name-credit>)*</artist-credit><release-group\sid="[^"]*"\stype="[^"]*"\stype-id="[^"]*"><title>[^<]*</title>(?:<disambiguation>[^<]*</disambiguation>)*(?:<primary-type\sid="[^"]*">[^<]*</primary-type>)*(?:<secondary-type-list>(?:<secondary-type\sid="[^"]*">[^<]*</secondary-type>)+</secondary-type-list>)*</release-group>(?:<date>(\d{4})[^<]*</date>)*(?:<country>)*([^<]*)?.*?<track-list\scount="(\d+).*?</release></expression> </RegExp> <expression noclean="1" /> </RegExp> @@ -140,9 +122,21 @@ <RegExp conditional="fanarttvalbumthumbs" input="$$4" output="<chain function="GetFanartTvAlbumThumbsByMBID">\1</chain>" dest="5+"> <expression noclean="1">(.+)</expression> </RegExp> + <RegExp conditional="fanarttvalbumdiscart" input="$$4" output="<chain function="GetFanartTvAlbumDiscartByMBID">\1</chain>" dest="5+"> + <expression noclean="1">(.+)</expression> + </RegExp> <RegExp conditional="tadbalbumthumbs" input="$$4" output="<chain function="GetTADBAlbumThumbsByMBID">\1</chain>" dest="5+"> <expression noclean="1">(.+)</expression> </RegExp> + <RegExp conditional="tadbalbumdiscart" input="$$4" output="<chain function="GetTADBAlbumDiscartByMBID">\1</chain>" dest="5+"> + <expression noclean="1">(.+)</expression> + </RegExp> + <RegExp conditional="tadbalbumback" input="$$4" output="<chain function="GetTADBAlbumBackByMBID">\1</chain>" dest="5+"> + <expression noclean="1">(.+)</expression> + </RegExp> + <RegExp conditional="tadbalbumspine" input="$$4" output="<chain function="GetTADBAlbumSpineByMBID">\1</chain>" dest="5+"> + <expression noclean="1">(.+)</expression> + </RegExp> <RegExp conditional="allmusicalbumthumbs" input="$$4" output="<url function="GetAMGAlbumThumbs" cache="mb-\1-rg.xml">$INFO[mbsite]/ws/2/release-group/\1?inc=url-rels</url>" dest="5+"> <expression noclean="1">(.+)</expression> </RegExp> diff --git a/addons/metadata.album.universal/changelog.txt b/addons/metadata.album.universal/changelog.txt index a1c379dd43..6ac78241fa 100644 --- a/addons/metadata.album.universal/changelog.txt +++ b/addons/metadata.album.universal/changelog.txt @@ -1,3 +1,13 @@ +[B]3.1.1[/B] +Fixed: further fixes to search results + +[B]3.1.0[/B] +Added: scraping extra artwork from theaudiobdb.com + +[B]3.0.0[/B] +Fixed: albums won't be found on MusicBrainz +Added: scraping discart from fanart.tv + [B]2.7.3[/B] Fixed: albums without year on MusicBrainz won't be found diff --git a/addons/metadata.album.universal/resources/language/English/strings.po b/addons/metadata.album.universal/resources/language/English/strings.po index 95dc7344a8..2567910cc1 100644 --- a/addons/metadata.album.universal/resources/language/English/strings.po +++ b/addons/metadata.album.universal/resources/language/English/strings.po @@ -66,4 +66,20 @@ msgstr "" msgctxt "#30012" msgid "MusicBrainz Mirror" +msgstr "" + +msgctxt "#30013" +msgid "Grab Album Discart from fanart.tv" +msgstr "" + +msgctxt "#30014" +msgid "Grab Album Back Cover from theaudiodb.com" +msgstr "" + +msgctxt "#30015" +msgid "Grab Album Discart from theaudiodb.com" +msgstr "" + +msgctxt "#30016" +msgid "Grab Album Spine from theaudiodb.com" msgstr ""
\ No newline at end of file diff --git a/addons/metadata.album.universal/resources/settings.xml b/addons/metadata.album.universal/resources/settings.xml index 05467b8903..f52de9b10a 100644 --- a/addons/metadata.album.universal/resources/settings.xml +++ b/addons/metadata.album.universal/resources/settings.xml @@ -16,9 +16,13 @@ <setting label="30000" type="bool" id="fanarttvalbumthumbs" default="true"/> <setting label="30010" type="bool" id="tadbalbumthumbs" default="true"/> <setting label="30008" type="bool" id="allmusicalbumthumbs" default="false"/> + <setting label="30013" type="bool" id="fanarttvalbumdiscart" default="false"/> + <setting label="30015" type="bool" id="tadbalbumdiscart" default="false"/> + <setting label="30014" type="bool" id="tadbalbumback" default="false"/> + <setting label="30016" type="bool" id="tadbalbumspine" default="false"/> </category> <category label="30011"> - <setting label="30012" type="text" id="mbsite" default="http://musicbrainz.org"/> + <setting label="30012" type="text" id="mbsite" default="https://musicbrainz.org"/> </category> </settings> diff --git a/addons/metadata.artists.universal/addon.xml b/addons/metadata.artists.universal/addon.xml index 972f78d80d..0f9ab23270 100644 --- a/addons/metadata.artists.universal/addon.xml +++ b/addons/metadata.artists.universal/addon.xml @@ -1,14 +1,14 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon id="metadata.artists.universal" name="Universal Artist Scraper" - version="4.1.4" + version="4.2.1" provider-name="Olympia, Team Kodi"> <requires> <import addon="xbmc.metadata" version="2.1.0"/> <import addon="metadata.common.allmusic.com" version="3.1.0"/> <import addon="metadata.common.fanart.tv" version="3.1.0"/> <import addon="metadata.common.musicbrainz.org" version="2.1.0"/> - <import addon="metadata.common.theaudiodb.com" version="1.8.1"/> + <import addon="metadata.common.theaudiodb.com" version="2.0.0"/> </requires> <extension point="xbmc.metadata.scraper.artists" language="en" diff --git a/addons/metadata.artists.universal/artistuniversal.xml b/addons/metadata.artists.universal/artistuniversal.xml index b1d1c605f5..6131998bbc 100644 --- a/addons/metadata.artists.universal/artistuniversal.xml +++ b/addons/metadata.artists.universal/artistuniversal.xml @@ -52,6 +52,9 @@ <RegExp input="$$1" output="<musicBrainzArtistID>$$8</musicBrainzArtistID><name>\1</name>" dest="5"> <expression noclean="1"><artist.*?<name>([^<]*)</expression> </RegExp> + <RegExp input="$$1" output="<sortname>\1</sortname>" dest="5+"> + <expression noclean="1"><artist.*?<sort-name>([^<]*)</expression> + </RegExp> <RegExp input="$$1" output="<type>\1</type>" dest="5+"> <expression noclean="1"><artist.*?\stype="([Person|Group|Orchestra|Choir|Character|Other])"</expression> </RegExp> @@ -67,9 +70,24 @@ <RegExp input="$$8" conditional="fanarttvartistcl" output="<chain function="GetFanartTvArtistClearlogoByMBID">\1</chain>" dest="5+"> <expression noclean="1">(.+)</expression> </RegExp> + <RegExp input="$$8" conditional="fanarttvartistbanner" output="<chain function="GetFanartTvArtistBannerByMBID">\1</chain>" dest="5+"> + <expression noclean="1">(.+)</expression> + </RegExp> <RegExp input="$$8" conditional="tadbthumbs" output="<chain function="GetTADBArtistThumbsByMBID">$$8</chain>" dest="5+"> <expression noclean="1">(.+)</expression> </RegExp> + <RegExp input="$$8" conditional="tadbartistclearlogo" output="<chain function="GetTADBArtistClearlogoByMBID">$$8</chain>" dest="5+"> + <expression noclean="1">(.+)</expression> + </RegExp> + <RegExp input="$$8" conditional="tadbartistclearart" output="<chain function="GetTADBArtistClearartByMBID">$$8</chain>" dest="5+"> + <expression noclean="1">(.+)</expression> + </RegExp> + <RegExp input="$$8" conditional="tadbartistlandscape" output="<chain function="GetTADBArtistLandscapeByMBID">$$8</chain>" dest="5+"> + <expression noclean="1">(.+)</expression> + </RegExp> + <RegExp input="$$8" conditional="tadbartistbanner" output="<chain function="GetTADBArtistBannerByMBID">$$8</chain>" dest="5+"> + <expression noclean="1">(.+)</expression> + </RegExp> <RegExp input="$$8" conditional="fanarttvfanart" output="<chain function="GetFanartTvArtistFanartsByMBID">\1</chain>" dest="5+"> <expression noclean="1">(.+)</expression> </RegExp> diff --git a/addons/metadata.artists.universal/changelog.txt b/addons/metadata.artists.universal/changelog.txt index d08f2917dc..b29163f255 100644 --- a/addons/metadata.artists.universal/changelog.txt +++ b/addons/metadata.artists.universal/changelog.txt @@ -1,3 +1,12 @@ +[B]4.2.1[/B] +fixed: dependency error + +[B]4.2.0[/B] +added: scraping extra artwork from theaudiodb.com + +[B]4.1.5[/B] +added: artist sort name from Musicbrainz and artist banner from fanart.tv + [B]4.1.4[/B] changed: include some other valid MB artist types in the previous fix diff --git a/addons/metadata.artists.universal/resources/language/English/strings.po b/addons/metadata.artists.universal/resources/language/English/strings.po index 4a1e97a38a..9571041015 100644 --- a/addons/metadata.artists.universal/resources/language/English/strings.po +++ b/addons/metadata.artists.universal/resources/language/English/strings.po @@ -124,4 +124,24 @@ msgstr "" msgctxt "#30027" msgid "Enable Artist Clearlogo from fanart.tv" +msgstr "" + +msgctxt "#30028" +msgid "Enable Artist Banner from fanart.tv" +msgstr "" + +msgctxt "#30029" +msgid "Enable Artist Clearlogo from theaudiodb.com" +msgstr "" + +msgctxt "#30030" +msgid "Enable Artist Clearart from theaudiodb.com" +msgstr "" + +msgctxt "#30031" +msgid "Enable Artist Landscape from theaudiodb.com" +msgstr "" + +msgctxt "#30032" +msgid "Enable Artist Banner from theaudiodb.com" msgstr ""
\ No newline at end of file diff --git a/addons/metadata.artists.universal/resources/settings.xml b/addons/metadata.artists.universal/resources/settings.xml index 6a021a430d..84f7fb1e84 100644 --- a/addons/metadata.artists.universal/resources/settings.xml +++ b/addons/metadata.artists.universal/resources/settings.xml @@ -33,10 +33,15 @@ <setting label="30004" type="bool" id="fanarttvfanart" default="true"/> <setting label="30023" type="bool" id="tadbfanart" default="true"/> <setting label="30027" type="bool" id="fanarttvartistcl" default="false"/> + <setting label="30029" type="bool" id="tadbartistclearlogo" default="false"/> + <setting label="30030" type="bool" id="tadbartistclearart" default="false"/> + <setting label="30031" type="bool" id="tadbartistlandscape" default="false"/> + <setting label="30028" type="bool" id="fanarttvartistbanner" default="false"/> + <setting label="30032" type="bool" id="tadbartistbanner" default="false"/> </category> <category label="30025"> - <setting label="30026" type="text" id="mbsite" default="http://musicbrainz.org"/> + <setting label="30026" type="text" id="mbsite" default="https://musicbrainz.org"/> </category> </settings> diff --git a/addons/metadata.common.allmusic.com/addon.xml b/addons/metadata.common.allmusic.com/addon.xml index 2c2bf34bf8..3099cb809c 100644 --- a/addons/metadata.common.allmusic.com/addon.xml +++ b/addons/metadata.common.allmusic.com/addon.xml @@ -1,7 +1,7 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon id="metadata.common.allmusic.com" name="AllMusic Scraper Library" - version="3.1.1" + version="3.2.0" provider-name="Team Kodi"> <requires> <import addon="xbmc.metadata" version="2.1.0"/> diff --git a/addons/metadata.common.allmusic.com/allmusic.xml b/addons/metadata.common.allmusic.com/allmusic.xml index 20e9ee38ed..e431cf5051 100644 --- a/addons/metadata.common.allmusic.com/allmusic.xml +++ b/addons/metadata.common.allmusic.com/allmusic.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <scraperfunctions> <GetAMGDiscographyByAMGID dest="5" clearbuffers="no"> - <RegExp input="$$1" output="<details><url cache="am-\1-artist-discography.html" function="ParseAMGDiscography">http://www.allmusic.com/artist/\1/discography</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="am-\1-artist-discography.html" function="ParseAMGDiscography">https://www.allmusic.com/artist/\1/discography</url></details>" dest="5"> <expression clear="yes" noclean="1"/> </RegExp> </GetAMGDiscographyByAMGID> @@ -17,54 +17,8 @@ </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="$$1" output="\1" dest="11"> - <expression clear="yes">" itemprop="description">(.*?)div class="advertisement leaderboard"></expression> - </RegExp> - <RegExp input="$$11" output="$$12" dest="2"> - <RegExp input="$INFO[biogfbsource]" output="<chain function="GetLastFMFallbackBiographyByMBID">$$8</chain>" dest="12"> - <expression>last.fm</expression> - </RegExp> - <RegExp input="$INFO[biogfbsource]" output="<chain function="GetTADBFMFallbackBiographyByMBID">$$8</chain>" dest="12"> - <expression>TheAudioDb.com</expression> - </RegExp> - <expression>^$</expression> - </RegExp> - <RegExp input="$$11" output="<biography>\1</biography>" dest="2"> - <expression>(.+)</expression> - </RegExp> - <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> - </GetAMGFallbackBiographyByAMGID> - <ParseAMGFallbackBiography dest="5" clearbuffers="no"> - <RegExp input="$$2" output="<details>\1</details>" dest="5"> - <RegExp input="" output="" dest="2"> - <expression /> - </RegExp> - <RegExp input="$$1" output="<biography>\1</biography>" dest="2"> - <expression clear="yes">" itemprop="description">(.*?)div class="advertisement leaderboard"></expression> - </RegExp> - <expression noclean="1"/> - </RegExp> - </ParseAMGFallbackBiography> - <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"> + <RegExp input="$$1" output="<details><url cache="am-\1-artist.html" function="ParseAMGArtistLifeSpan">https://www.allmusic.com/artist/\1</url></details>" dest="5"> <expression noclean="1"/> </RegExp> </GetAMGArtistLifeSpanByAMGID> @@ -76,17 +30,17 @@ <RegExp input="" output="" dest="11"> <expression /> </RegExp> - <RegExp input="$$1" output="<born>\1 \2</born>" dest="11+"> - <expression trim="1,2"><h4>\s*Born\s*</h4>\s*<div>(.*?\d{4})\s*([^<]*)?</expression> + <RegExp input="$$1" output="<born>\1 \3</born>" dest="11+"> + <expression trim="1,2"><h4>\s.+Born.*?birthdate/[^"]+">([^<]*)(.*?"/birthplace/[^"]+">([^<]*))?</expression> </RegExp> - <RegExp input="$$1" output="<died>\1 \2</died>" dest="11+"> - <expression trim="1,2"><h4>\s*Died\s*</h4>\s*<div>(.*?\d{4})\s*([^<]*)?</expression> + <RegExp input="$$1" output="<died>\1 \3</died>" dest="11+"> + <expression trim="1,2"><h4>\s.+Died.*?deathdate/[^"]+">([^<]*)(.*?"/deathplace/[^"]+">([^<]*))?</expression> </RegExp> <RegExp input="$$1" output="<formed>\1</formed>" dest="11+"> - <expression trim="1,2"><h4>\s*Formed\s*</h4>\s*<div>(.*?\d{4})\s*([^<]*)?</expression> + <expression trim="1,2"><h4>\s.+Formed.*?birthdate/[^"]+">([^<]*)</expression> </RegExp> <RegExp input="$$1" output="<disbanded>\1</disbanded>" dest="11+"> - <expression trim="1,2"><h4>\s*Disbanded\s*</h4>\s*<div>(.*?\d{4})\s*([^<]*)?</expression> + <expression trim="1,2"><h4>\s.+Disbanded.*?deathdate/[^"]+[^"]+">([^<]*)</expression> </RegExp> <RegExp input="$$11" output="$$12" dest="2"> <RegExp input="$INFO[lifespanfbsource]" output="<chain function="GetMBFallbackLafeSpanByMBID">$$8</chain>" dest="12"> @@ -105,7 +59,7 @@ </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"> + <RegExp input="$$1" output="<details><url cache="am-\1-artist.html" function="ParseAMGFallbackArtistLifeSpan">https://www.allmusic.com/artist/\1</url></details>" dest="5"> <expression noclean="1"/> </RegExp> </GetAMGFallbackArtistLifeSpanByAMGID> @@ -131,7 +85,7 @@ </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"> + <RegExp input="$$1" output="<details><url cache="am-\1-artist.html" function="ParseAMGArtistYearsActive">https://www.allmusic.com/artist/\1</url></details>" dest="5"> <expression noclean="1"/> </RegExp> </GetAMGArtistYearsActiveByAMGID> @@ -148,7 +102,7 @@ </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"> + <RegExp input="$$1" output="<details><url cache="am-\1-artist.html" function="ParseAMGArtistGenres">https://www.allmusic.com/artist/\1</url></details>" dest="5"> <expression noclean="1"/> </RegExp> </GetAMGArtistGenresByAMGID> @@ -164,7 +118,7 @@ <expression noclean="1"><h4>Genre</h4>\s*<div>(.*?)</div></expression> </RegExp> <RegExp input="$$6" output="<genre>\1</genre>" dest="11"> - <expression repeat="yes" noclean="1"><a\shref="http://www.allmusic.com/genre/[^"]*">([^<]*)</expression> + <expression repeat="yes" noclean="1"><a\shref="https://www.allmusic.com/genre/[^"]*">([^<]*)</expression> </RegExp> <RegExp input="$$11" output="$$12" dest="2"> <RegExp input="$INFO[genresfbsource]" output="<chain function="GetLastFMFallbackArtistGenresByMBID">$$8</chain>" dest="12"> @@ -183,7 +137,7 @@ </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"> + <RegExp input="$$1" output="<details><url cache="am-\1-artist.html" function="ParseAMGFallbackArtistGenres">https://www.allmusic.com/artist/\1</url></details>" dest="5"> <expression noclean="1"/> </RegExp> </GetAMGFallbackArtistGenresByAMGID> @@ -199,14 +153,14 @@ <expression noclean="1"><h4>Genre</h4>\s*<div>(.*?)</div></expression> </RegExp> <RegExp input="$$6" output="<genre>\1</genre>" dest="2"> - <expression repeat="yes" noclean="1"><a\shref="http://www.allmusic.com/genre/[^"]*">([^<]*)</expression> + <expression repeat="yes" noclean="1"><a\shref="https://www.allmusic.com/genre/[^"]*">([^<]*)</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"> + <RegExp input="$$1" output="<details><url cache="am-\1-artist.html" function="ParseAMGArtistStyles">https://www.allmusic.com/artist/\1</url></details>" dest="5"> <expression noclean="1"/> </RegExp> </GetAMGArtistStylesByAMGID> @@ -222,7 +176,7 @@ <expression noclean="1"><h4>Styles</h4>\s*<div>(.*?)</div></expression> </RegExp> <RegExp input="$$7" output="<style>\1</style>" dest="11"> - <expression repeat="yes" noclean="1"><a\shref="http://www.allmusic.com/style/[^"]*">([^<]*)</expression> + <expression repeat="yes" noclean="1"><a\shref="https://www.allmusic.com/style/[^"]*">([^<]*)</expression> </RegExp> <RegExp input="$$11" output="$$12" dest="2"> <RegExp input="$INFO[stylesfbsource]" output="<chain function="GetLastFMFallbackArtistStylesByMBID">$$8</chain>" dest="12"> @@ -241,7 +195,7 @@ </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"> + <RegExp input="$$1" output="<details><url cache="am-\1-artist.html" function="ParseAMGFallbackArtistStyles">https://www.allmusic.com/artist/\1</url></details>" dest="5"> <expression noclean="1"/> </RegExp> </GetAMGFallbackArtistStylesByAMGID> @@ -257,14 +211,14 @@ <expression noclean="1"><h4>Styles</h4>\s*<div>(.*?)</div></expression> </RegExp> <RegExp input="$$7" output="<style>\1</style>" dest="2"> - <expression repeat="yes" noclean="1"><a\shref="http://www.allmusic.com/style/[^"]*">([^<]*)</expression> + <expression repeat="yes" noclean="1"><a\shref="https://www.allmusic.com/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"> + <RegExp input="$$1" output="<details><url cache="am-\1-artist.html" function="ParseAMGArtistMoods">https://www.allmusic.com/artist/\1</url></details>" dest="5"> <expression noclean="1"/> </RegExp> </GetAMGArtistMoodsByAMGID> @@ -296,7 +250,7 @@ </ParseAMGArtistMoods> <GetAMGFallbackArtistMoodsByAMGID dest="5" clearbuffers="no"> - <RegExp input="$$1" output="<details><url cache="am-\1-artist.html" function="ParseAMGFallbackArtistMoods">http://www.allmusic.com/artist/\1</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="am-\1-artist.html" function="ParseAMGFallbackArtistMoods">https://www.allmusic.com/artist/\1</url></details>" dest="5"> <expression noclean="1"/> </RegExp> </GetAMGFallbackArtistMoodsByAMGID> @@ -318,74 +272,9 @@ </RegExp> </ParseAMGFallbackArtistMoods> - <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="" output="" dest="4"> - <expression /> - </RegExp> - <RegExp input="$$1" output="\1" dest="4"> - <expression noclean="1"><h\d>Photo\sGallery</h\d>(.*?)<h2\sclass="artist-name"</expression> - </RegExp> - <RegExp input="$$4" 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> - <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> - </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> - <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> - <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"> + <RegExp input="$$1" output="<details><url cache="am-\1-album.html" function="ParseAMGAlbumRating">https://www.allmusic.com/album/\1</url></details>" dest="5"> <expression noclean="1"/> </RegExp> </GetAMGAlbumRatingByAMGID> @@ -398,59 +287,42 @@ </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>\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"> + <RegExp input="$$1" output="<details><url cache="am-\1-album.html" function="ParseAMGAlbumGenres">https://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"><h4>Genre</h4>\s*<div>(.*?)</div></expression> + <expression noclean="1">class="genre">(.*?)</div></expression> </RegExp> <RegExp input="$$6" output="<genre>\1</genre>" dest="2"> - <expression repeat="yes" noclean="1"><a\shref="http://www.allmusic.com/genre/[^"]*">([^<]*)</expression> + <expression repeat="yes" noclean="1"><a\shref="https://www.allmusic.com/genre/[^"]*">([^<]*)</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"> + <RegExp input="$$1" output="<details><url cache="am-\1-album.html" function="ParseAMGAlbumStyles">https://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"><h4>Styles</h4>\s*<div>(.*?)</div></expression> + <expression noclean="1">class="styles">(.*?)</div></expression> </RegExp> <RegExp input="$$7" output="<style>\1</style>" dest="2"> - <expression repeat="yes" noclean="1"><a\shref="http://www.allmusic.com/style/[^"]*">([^<]*)</expression> + <expression repeat="yes" noclean="1"><a\shref="https://www.allmusic.com/style/[^"]*">([^<]*)</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"> + <RegExp input="$$1" output="<details><url cache="am-\1-album.html" function="ParseAMGAlbumMoods">https://www.allmusic.com/album/\1</url></details>" dest="5"> <expression noclean="1"/> </RegExp> </GetAMGAlbumMoodsByAMGID> @@ -460,84 +332,41 @@ <expression trim="1" noclean="1">>\s*<h4>Album\sMoods</h4>(.*?)</section></expression> </RegExp> <RegExp input="$$8" output="<mood>\1</mood>" dest="2"> - <expression repeat="yes" noclean="1"><a\shref="http://www.allmusic.com/mood/[^"]*">([^<]*)</expression> + <expression repeat="yes" noclean="1"><a\shref="https://www.allmusic.com/mood/[^"]*">([^<]*)</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"> + <RegExp input="$$1" output="<details><url cache="am-\1-album.html" function="ParseAMGAlbumThemes">https://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="4"> - <expression trim="1" noclean="1">>\s*<h4>Themes</h4>(.*?)</ul></expression> + <expression trim="1" noclean="1"><section\sclass="themes">(.*?)</section></expression> </RegExp> <RegExp input="$$4" output="<theme>\1</theme>" dest="2"> - <expression repeat="yes" noclean="1"><a\shref="http://www.allmusic.com/theme/[^"]*">([^<]*)</expression> + <expression repeat="yes" noclean="1"><a\shref="https://www.allmusic.com/theme/[^"]*">([^<]*)</expression> </RegExp> <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> - <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"> + <RegExp input="$$1" output="<details><url cache="am-\1-album.html" function="ParseAMGAlbumThumbs">https://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">"http://cps-static.rovicorp.com/3/JPG_[^/]*/([^"]*)</expression> + <RegExp input="$$1" output="<thumb>https://cdn-s3.allmusic.com/release-covers/500/\1</thumb>" dest="2"> + <expression noclean="1"><img src="https://cdn-s3.allmusic.com/release-covers/500/([^"]*)</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> - </ParseAMGFakeAlbumReview> - </scraperfunctions> diff --git a/addons/metadata.common.fanart.tv/addon.xml b/addons/metadata.common.fanart.tv/addon.xml index 1a01b98ca4..45caf8c534 100644 --- a/addons/metadata.common.fanart.tv/addon.xml +++ b/addons/metadata.common.fanart.tv/addon.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon id="metadata.common.fanart.tv" name="fanart.tv Scraper Library" - version="3.1.5" + version="3.5.0" provider-name="Team Kodi"> <requires> <import addon="xbmc.metadata" version="2.1.0"/> diff --git a/addons/metadata.common.fanart.tv/fanarttv.xml b/addons/metadata.common.fanart.tv/fanarttv.xml index ecf02d7e86..6dffe1d0ff 100644 --- a/addons/metadata.common.fanart.tv/fanarttv.xml +++ b/addons/metadata.common.fanart.tv/fanarttv.xml @@ -16,13 +16,59 @@ <RegExp input="$$1" output="\1" dest="16"> <expression noclean="1">"artistthumb":\s\[(.*?)\}\s*\]</expression> </RegExp> - <RegExp input="$$16" output="<thumb preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13"> + <RegExp input="$$16" output="<thumb aspect="poster" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13"> <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)</expression> </RegExp> <expression noclean="1" /> </RegExp> </ParseFanartTvArtistThumbs> + <GetFanartTvArtistClearlogoByMBID dest="5" clearbuffers="no"> + <RegExp input="$$1" output="<details><url function="ParseFanartTvArtistClearlogo" cache="fanarttv-artistimages-\1.json">https://webservice.fanart.tv/v3/music/\1?api_key=ed4b784f97227358b31ca4dd966a04f1</url></details>" dest="5"> + <expression noclean="1" /> + </RegExp> + </GetFanartTvArtistClearlogoByMBID> + <ParseFanartTvArtistClearlogo dest="5" clearbuffers="no"> + <RegExp input="$$13" output="<details>\1</details>" dest="5"> + <RegExp input="" output="" dest="13"> + <expression /> + </RegExp> + <RegExp input="" output="" dest="16"> + <expression /> + </RegExp> + <RegExp input="$$1" output="\1" dest="16"> + <expression noclean="1">"hdmusiclogo":\s\[(.*?)\}\s*\]</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="clearlogo" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </ParseFanartTvArtistClearlogo> + + <GetFanartTvArtistBannerByMBID dest="5" clearbuffers="no"> + <RegExp input="$$1" output="<details><url function="ParseFanartTvArtistBanner" cache="fanarttv-artistimages-\1.json">https://webservice.fanart.tv/v3/music/\1?api_key=ed4b784f97227358b31ca4dd966a04f1</url></details>" dest="5"> + <expression noclean="1" /> + </RegExp> + </GetFanartTvArtistBannerByMBID> + <ParseFanartTvArtistBanner dest="5" clearbuffers="no"> + <RegExp input="$$13" output="<details>\1</details>" dest="5"> + <RegExp input="" output="" dest="13"> + <expression /> + </RegExp> + <RegExp input="" output="" dest="16"> + <expression /> + </RegExp> + <RegExp input="$$1" output="\1" dest="16"> + <expression noclean="1">"musicbanner":\s\[(.*?)\}\s*\]</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="banner" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </ParseFanartTvArtistBanner> + <GetFanartTvArtistFanartsByMBID dest="5" clearbuffers="no"> <RegExp input="$$1" output="<details><url function="ParseFanartTvArtistFanarts" cache="fanarttv-artistimages-\1.json">https://webservice.fanart.tv/v3/music/\1?api_key=ed4b784f97227358b31ca4dd966a04f1</url></details>" dest="5"> <expression noclean="1" /> @@ -75,6 +121,29 @@ </RegExp> </ParseFanartTvAlbumThumbs> + <GetFanartTvAlbumDiscartByMBID dest="5" clearbuffers="no"> + <RegExp input="$$1" output="<details><url function="ParseFanartTvAlbumDiscart" cache="fanarttv-albumimages-\1.json">https://webservice.fanart.tv/v3/music/albums/\1?api_key=ed4b784f97227358b31ca4dd966a04f1</url></details>" dest="5"> + <expression noclean="1" /> + </RegExp> + </GetFanartTvAlbumDiscartByMBID> + <ParseFanartTvAlbumDiscart dest="5" clearbuffers="no"> + <RegExp input="$$13" output="<details>\1</details>" dest="5"> + <RegExp input="" output="" dest="13"> + <expression /> + </RegExp> + <RegExp input="" output="" dest="16"> + <expression /> + </RegExp> + <RegExp input="$$1" output="\1" dest="16"> + <expression noclean="1">"cdart":\s\[(.*?)\}\s*\]</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="discart" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </ParseFanartTvAlbumDiscart> + <GetFanartTvFanartByIdChain dest="4"> <RegExp input="$$5" output="<details>\1</details>" dest="4"> <RegExp input="$$1" output="<url function="ParseFanartTvFanart" cache="fanarttv-\1.json">https://webservice.fanart.tv/v3/movies/\1?api_key=ed4b784f97227358b31ca4dd966a04f1</url>" dest="5"> @@ -107,15 +176,18 @@ </RegExp> </ParseFanartTvFanart> - <GetFanartTvThumbsByIdChain dest="4"> + <GetFanartTvThumbsByIdChain clearbuffers="no" dest="4"> <!-- Expected chaining format= tmdb_id::language--> <RegExp input="$$5" output="<details>\1</details>" dest="4"> - <RegExp input="$$1" output="<url function="ParseFanartTvThumbs" cache="fanarttv-\1.json">https://webservice.fanart.tv/v3/movies/\1?api_key=ed4b784f97227358b31ca4dd966a04f1</url>" dest="5"> - <expression /> + <RegExp input="$$1" output="\2" dest="11"> + <expression>(.+)::(.+)</expression> + </RegExp> + <RegExp input="$$1" output="<url function="ParseFanartTvMoviePoster" cache="fanarttv-\1.json">https://webservice.fanart.tv/v3/movies/\1?api_key=ed4b784f97227358b31ca4dd966a04f1</url>" dest="5"> + <expression>(.+)::(.+)</expression> </RegExp> <expression noclean="1" /> </RegExp> </GetFanartTvThumbsByIdChain> - <ParseFanartTvThumbs dest="5"> + <ParseFanartTvMoviePoster dest="5"> <RegExp input="$$13" output="<details>\1</details>" dest="5"> <RegExp input="" output="" dest="13"> <expression /> @@ -126,11 +198,524 @@ <RegExp input="$$1" output="\1" dest="16"> <expression noclean="1">"movieposter":\s\[(.*?)\}\s*\]</expression> </RegExp> - <RegExp input="$$16" output="<thumb preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13"> + <RegExp input="$$16" output="<thumb aspect="poster" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"$$11"</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="poster" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"en"</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="poster" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"00"</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </ParseFanartTvMoviePoster> + + <GetFanartTvMovieClearlogoByIdChain dest="4"> + <RegExp input="$$5" output="<details>\1</details>" dest="4"> + <RegExp input="$$1" output="\1" dest="18"> + <expression encode="1">.+::(.+)</expression> + </RegExp> + <RegExp input="$$1" output="<url function="ParseFanartTvMovieClearlogo" cache="fanarttv-\1.json">https://webservice.fanart.tv/v3/movies/\1?api_key=ed4b784f97227358b31ca4dd966a04f1</url>" dest="5"> + <expression encode="1">(.+)::.+</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </GetFanartTvMovieClearlogoByIdChain> + <ParseFanartTvMovieClearlogo dest="5"> + <RegExp input="$$13" output="<details>\1</details>" dest="5"> + <RegExp input="" output="" dest="13"> + <expression /> + </RegExp> + <RegExp input="" output="" dest="16"> + <expression /> + </RegExp> + <RegExp input="$$1" output="\1" dest="16"> + <expression noclean="1">"hdmovielogo":\s\[(.*?)\}\s*\]</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="clearlogo" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"$$18"</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="clearlogo" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"en"</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="clearlogo" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"00"</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </ParseFanartTvMovieClearlogo> + + <GetFanartTvMovieClearartByIdChain dest="4"> + <RegExp input="$$5" output="<details>\1</details>" dest="4"> + <RegExp input="$$1" output="\1" dest="18"> + <expression encode="1">.+::(.+)</expression> + </RegExp> + <RegExp input="$$1" output="<url function="ParseFanartTvMovieClearart" cache="fanarttv-\1.json">https://webservice.fanart.tv/v3/movies/\1?api_key=ed4b784f97227358b31ca4dd966a04f1</url>" dest="5"> + <expression encode="1">(.+)::.+</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </GetFanartTvMovieClearartByIdChain> + <ParseFanartTvMovieClearart dest="5"> + <RegExp input="$$13" output="<details>\1</details>" dest="5"> + <RegExp input="" output="" dest="13"> + <expression /> + </RegExp> + <RegExp input="" output="" dest="16"> + <expression /> + </RegExp> + <RegExp input="$$1" output="\1" dest="16"> + <expression noclean="1">"hdmovieclearart":\s\[(.*?)\}\s*\]</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="clearart" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"$$18"</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="clearart" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"en"</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="clearart" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"00"</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </ParseFanartTvMovieClearart> + + <GetFanartTvMoviebannerByIdChain dest="4"> + <RegExp input="$$5" output="<details>\1</details>" dest="4"> + <RegExp input="$$1" output="\1" dest="18"> + <expression encode="1">.+::(.+)</expression> + </RegExp> + <RegExp input="$$1" output="<url function="ParseFanartTvMoviebanner" cache="fanarttv-\1.json">https://webservice.fanart.tv/v3/movies/\1?api_key=ed4b784f97227358b31ca4dd966a04f1</url>" dest="5"> + <expression encode="1">(.+)::.+</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </GetFanartTvMoviebannerByIdChain> + <ParseFanartTvMoviebanner dest="5"> + <RegExp input="$$13" output="<details>\1</details>" dest="5"> + <RegExp input="" output="" dest="13"> + <expression /> + </RegExp> + <RegExp input="" output="" dest="16"> + <expression /> + </RegExp> + <RegExp input="$$1" output="\1" dest="16"> + <expression noclean="1">"moviebanner":\s\[(.*?)\}\s*\]</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="banner" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"$$18"</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="banner" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"en"</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="banner" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"00"</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </ParseFanartTvMoviebanner> + + <GetFanartTvMovieLandscapeByIdChain dest="4"> + <RegExp input="$$5" output="<details>\1</details>" dest="4"> + <RegExp input="$$1" output="\1" dest="18"> + <expression encode="1">.+::(.+)</expression> + </RegExp> + <RegExp input="$$1" output="<url function="ParseFanartTvMovieLandscape" cache="fanarttv-\1.json">https://webservice.fanart.tv/v3/movies/\1?api_key=ed4b784f97227358b31ca4dd966a04f1</url>" dest="5"> + <expression encode="1">(.+)::.+</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </GetFanartTvMovieLandscapeByIdChain> + <ParseFanartTvMovieLandscape dest="5"> + <RegExp input="$$13" output="<details>\1</details>" dest="5"> + <RegExp input="" output="" dest="13"> + <expression /> + </RegExp> + <RegExp input="" output="" dest="16"> + <expression /> + </RegExp> + <RegExp input="$$1" output="\1" dest="16"> + <expression noclean="1">"moviethumb":\s\[(.*?)\}\s*\]</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="landscape" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"$$18"</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="landscape" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"en"</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="landscape" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"00"</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </ParseFanartTvMovieLandscape> + + <GetFanartTvMovieDiscartByIdChain dest="4"> + <RegExp input="$$5" output="<details>\1</details>" dest="4"> + <RegExp input="$$1" output="\1" dest="18"> + <expression encode="1">.+::(.+)</expression> + </RegExp> + <RegExp input="$$1" output="<url function="ParseFanartTvMovieDiscart" cache="fanarttv-\1.json">https://webservice.fanart.tv/v3/movies/\1?api_key=ed4b784f97227358b31ca4dd966a04f1</url>" dest="5"> + <expression encode="1">(.+)::.+</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </GetFanartTvMovieDiscartByIdChain> + <ParseFanartTvMovieDiscart dest="5"> + <RegExp input="$$13" output="<details>\1</details>" dest="5"> + <RegExp input="" output="" dest="13"> + <expression /> + </RegExp> + <RegExp input="" output="" dest="16"> + <expression /> + </RegExp> + <RegExp input="$$1" output="\1" dest="16"> + <expression noclean="1">"moviedisc":\s\[(.*?)\}\s*\]</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="discart" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"$$18"</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="discart" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"en"</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="discart" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"00"</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </ParseFanartTvMovieDiscart> + + <GetFanartTvTvShowPosterByIdChain dest="4"> + <RegExp input="$$5" output="<details>\1</details>" dest="4"> + <RegExp input="$$1" output="\1" dest="18"> + <expression encode="1">.+::(.+)</expression> + </RegExp> + <RegExp input="$$1" output="<url function="ParseFanartTvTvShowPoster" cache="fanarttv-\1.json">https://webservice.fanart.tv/v3/tv/\1?api_key=ed4b784f97227358b31ca4dd966a04f1</url>" dest="5"> + <expression encode="1">(.+)::.+</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </GetFanartTvTvShowPosterByIdChain> + <ParseFanartTvTvShowPoster dest="5"> + <RegExp input="$$13" output="<details>\1</details>" dest="5"> + <RegExp input="" output="" dest="13"> + <expression /> + </RegExp> + <RegExp input="" output="" dest="16"> + <expression /> + </RegExp> + <RegExp input="$$1" output="\1" dest="16"> + <expression noclean="1">"tvposter":\s\[(.*?)\}\s*\]</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="poster" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"$$18"</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="poster" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"en"</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="poster" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"!$$18|!en"</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </ParseFanartTvTvShowPoster> + + <GetFanartTvTvShowBannerByIdChain dest="4"> + <RegExp input="$$5" output="<details>\1</details>" dest="4"> + <RegExp input="$$1" output="\1" dest="18"> + <expression encode="1">.+::(.+)</expression> + </RegExp> + <RegExp input="$$1" output="<url function="ParseFanartTvTvShowBanner" cache="fanarttv-\1.json">https://webservice.fanart.tv/v3/tv/\1?api_key=ed4b784f97227358b31ca4dd966a04f1</url>" dest="5"> + <expression encode="1">(.+)::.+</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </GetFanartTvTvShowBannerByIdChain> + <ParseFanartTvTvShowBanner dest="5"> + <RegExp input="$$13" output="<details>\1</details>" dest="5"> + <RegExp input="" output="" dest="13"> + <expression /> + </RegExp> + <RegExp input="" output="" dest="16"> + <expression /> + </RegExp> + <RegExp input="$$1" output="\1" dest="16"> + <expression noclean="1">"tvbanner":\s\[(.*?)\}\s*\]</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="banner" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"$$18"</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="banner" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"en"</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="banner" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"!$$18|!en"</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </ParseFanartTvTvShowBanner> + + <GetFanartTvTvShowLandscapeByIdChain dest="4"> + <RegExp input="$$5" output="<details>\1</details>" dest="4"> + <RegExp input="$$1" output="\1" dest="18"> + <expression encode="1">.+::(.+)</expression> + </RegExp> + <RegExp input="$$1" output="<url function="ParseFanartTvTvShowLandscape" cache="fanarttv-\1.json">https://webservice.fanart.tv/v3/tv/\1?api_key=ed4b784f97227358b31ca4dd966a04f1</url>" dest="5"> + <expression encode="1">(.+)::.+</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </GetFanartTvTvShowLandscapeByIdChain> + <ParseFanartTvTvShowLandscape dest="5"> + <RegExp input="$$13" output="<details>\1</details>" dest="5"> + <RegExp input="" output="" dest="13"> + <expression /> + </RegExp> + <RegExp input="" output="" dest="16"> + <expression /> + </RegExp> + <RegExp input="$$1" output="\1" dest="16"> + <expression noclean="1">"tvthumb":\s\[(.*?)\}\s*\]</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="landscape" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"$$18"</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="landscape" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"en"</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="landscape" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"!$$18|!en"</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </ParseFanartTvTvShowLandscape> + + <GetFanartTvTvShowClearlogoByIdChain dest="4"> + <RegExp input="$$5" output="<details>\1</details>" dest="4"> + <RegExp input="$$1" output="\1" dest="18"> + <expression encode="1">.+::(.+)</expression> + </RegExp> + <RegExp input="$$1" output="<url function="ParseFanartTvTvShowClearlogo" cache="fanarttv-\1.json">https://webservice.fanart.tv/v3/tv/\1?api_key=ed4b784f97227358b31ca4dd966a04f1</url>" dest="5"> + <expression encode="1">(.+)::.+</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </GetFanartTvTvShowClearlogoByIdChain> + <ParseFanartTvTvShowClearlogo dest="5"> + <RegExp input="$$13" output="<details>\1</details>" dest="5"> + <RegExp input="" output="" dest="13"> + <expression /> + </RegExp> + <RegExp input="" output="" dest="16"> + <expression /> + </RegExp> + <RegExp input="$$1" output="\1" dest="16"> + <expression noclean="1">"hdtvlogo":\s\[(.*?)\}\s*\]</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="clearlogo" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"$$18"</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="clearlogo" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"en"</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="clearlogo" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"!$$18|!en"</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </ParseFanartTvTvShowClearlogo> + + <GetFanartTvTvShowClearartByIdChain dest="4"> + <RegExp input="$$5" output="<details>\1</details>" dest="4"> + <RegExp input="$$1" output="\1" dest="18"> + <expression encode="1">.+::(.+)</expression> + </RegExp> + <RegExp input="$$1" output="<url function="ParseFanartTvTvShowClearart" cache="fanarttv-\1.json">https://webservice.fanart.tv/v3/tv/\1?api_key=ed4b784f97227358b31ca4dd966a04f1</url>" dest="5"> + <expression encode="1">(.+)::.+</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </GetFanartTvTvShowClearartByIdChain> + <ParseFanartTvTvShowClearart dest="5"> + <RegExp input="$$13" output="<details>\1</details>" dest="5"> + <RegExp input="" output="" dest="13"> + <expression /> + </RegExp> + <RegExp input="" output="" dest="16"> + <expression /> + </RegExp> + <RegExp input="$$1" output="\1" dest="16"> + <expression noclean="1">"hdclearart":\s\[(.*?)\}\s*\]</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="clearart" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"$$18"</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="clearart" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"en"</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="clearart" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"!$$18|!en"</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </ParseFanartTvTvShowClearart> + + <GetFanartTvTvShowFanartByIdChain dest="4"> + <RegExp input="$$5" output="<details>\1</details>" dest="4"> + <RegExp input="$$1" output="<url function="ParseFanartTvTvShowFanart" cache="fanarttv-\1.json">https://webservice.fanart.tv/v3/tv/\1?api_key=ed4b784f97227358b31ca4dd966a04f1</url>" dest="5"> + <expression /> + </RegExp> + <expression noclean="1" /> + </RegExp> + </GetFanartTvTvShowFanartByIdChain> + <ParseFanartTvTvShowFanart dest="5"> + <RegExp input="$$13" output="<details><fanart>\1</fanart></details>" dest="5"> + <RegExp input="" output="" dest="13"> + <expression /> + </RegExp> + <RegExp input="" output="" dest="16"> + <expression /> + </RegExp> + <RegExp input="$$1" output="\1" dest="16"> + <expression noclean="1">"showbackground":\s\[(.*?)\}\s*\]</expression> + </RegExp> + <RegExp input="$$16" output="<thumb preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </ParseFanartTvTvShowFanart> + + <GetFanartTvTvShowCharacterartByIdChain dest="4"> + <RegExp input="$$5" output="<details>\1</details>" dest="4"> + <RegExp input="$$1" output="<url function="ParseFanartTvTvShowCharacterart" cache="fanarttv-\1.json">https://webservice.fanart.tv/v3/tv/\1?api_key=ed4b784f97227358b31ca4dd966a04f1</url>" dest="5"> + <expression /> + </RegExp> + <expression noclean="1" /> + </RegExp> + </GetFanartTvTvShowCharacterartByIdChain> + <ParseFanartTvTvShowCharacterart dest="5"> + <RegExp input="$$13" output="<details>\1</details>" dest="5"> + <RegExp input="" output="" dest="13"> + <expression /> + </RegExp> + <RegExp input="" output="" dest="16"> + <expression /> + </RegExp> + <RegExp input="$$1" output="\1" dest="16"> + <expression noclean="1">"characterart":\s\[(.*?)\}\s*\]</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="characterart" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)</expression> </RegExp> <expression noclean="1" /> </RegExp> - </ParseFanartTvThumbs> - + </ParseFanartTvTvShowCharacterart> + + <GetFanartTvTvShowSeasonposterByIdChain clearbuffers="no" dest="4"> + <RegExp input="$$5" output="<details>\1</details>" dest="4"> + <RegExp input="$$1" output="\1" dest="18"> + <expression encode="1">.+::(.+)</expression> + </RegExp> + <RegExp input="$$1" output="<url function="ParseFanartTvTvShowSeasonposter" cache="fanarttv-\1.json">https://webservice.fanart.tv/v3/tv/\1?api_key=ed4b784f97227358b31ca4dd966a04f1</url>" dest="5"> + <expression encode="1">(.+)::.+</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </GetFanartTvTvShowSeasonposterByIdChain> + <ParseFanartTvTvShowSeasonposter dest="5"> + <RegExp input="$$13" output="<details>\1</details>" dest="5"> + <RegExp input="" output="" dest="13"> + <expression /> + </RegExp> + <RegExp input="" output="" dest="16"> + <expression /> + </RegExp> + <RegExp input="$$1" output="\1" dest="16"> + <expression noclean="1">"seasonposter":\s\[(.*?)\}\s*\]</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="poster" type="season" season="\3" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"$$18",\s*"likes[^,]*,\s*"season":\s"([0-9,]+)</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="poster" type="season" season="\3" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"en",\s*"likes[^,]*,\s*"season":\s"([0-9,]+)</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="poster" type="season" season="\3" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"!$$18|!en",\s*"likes[^,]*,\s*"season":\s"([0-9,]+)</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </ParseFanartTvTvShowSeasonposter> + + <GetFanartTvTvShowSeasonbannerByIdChain clearbuffers="no" dest="4"> + <RegExp input="$$5" output="<details>\1</details>" dest="4"> + <RegExp input="$$1" output="\1" dest="18"> + <expression encode="1">.+::(.+)</expression> + </RegExp> + <RegExp input="$$1" output="<url function="ParseFanartTvTvShowSeasonbanner" cache="fanarttv-\1.json">https://webservice.fanart.tv/v3/tv/\1?api_key=ed4b784f97227358b31ca4dd966a04f1</url>" dest="5"> + <expression encode="1">(.+)::.+</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </GetFanartTvTvShowSeasonbannerByIdChain> + <ParseFanartTvTvShowSeasonbanner dest="5"> + <RegExp input="$$13" output="<details>\1</details>" dest="5"> + <RegExp input="" output="" dest="13"> + <expression /> + </RegExp> + <RegExp input="" output="" dest="16"> + <expression /> + </RegExp> + <RegExp input="$$1" output="\1" dest="16"> + <expression noclean="1">"seasonbanner":\s\[(.*?)\}\s*\]</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="banner" type="season" season="\3" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"$$18",\s*"likes[^,]*,\s*"season":\s"([0-9,]+)</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="banner" type="season" season="\3" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"en",\s*"likes[^,]*,\s*"season":\s"([0-9,]+)</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="banner" type="season" season="\3" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"!$$18|!en",\s*"likes[^,]*,\s*"season":\s"([0-9,]+)</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </ParseFanartTvTvShowSeasonbanner> + + <GetFanartTvTvShowSeasonLandscapeByIdChain clearbuffers="no" dest="4"> + <RegExp input="$$5" output="<details>\1</details>" dest="4"> + <RegExp input="$$1" output="\1" dest="18"> + <expression encode="1">.+::(.+)</expression> + </RegExp> + <RegExp input="$$1" output="<url function="ParseFanartTvTvShowSeasonLandscape" cache="fanarttv-\1.json">https://webservice.fanart.tv/v3/tv/\1?api_key=ed4b784f97227358b31ca4dd966a04f1</url>" dest="5"> + <expression encode="1">(.+)::.+</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </GetFanartTvTvShowSeasonLandscapeByIdChain> + <ParseFanartTvTvShowSeasonLandscape dest="5"> + <RegExp input="$$13" output="<details>\1</details>" dest="5"> + <RegExp input="" output="" dest="13"> + <expression /> + </RegExp> + <RegExp input="" output="" dest="16"> + <expression /> + </RegExp> + <RegExp input="$$1" output="\1" dest="16"> + <expression noclean="1">"seasonthumb":\s\[(.*?)\}\s*\]</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="landscape" type="season" season="\3" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"$$18",\s*"likes[^,]*,\s*"season":\s"([0-9,]+)</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="landscape" type="season" season="\3" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"en",\s*"likes[^,]*,\s*"season":\s"([0-9,]+)</expression> + </RegExp> + <RegExp input="$$16" output="<thumb aspect="landscape" type="season" season="\3" preview="https://\1/preview/\2">https://\1/fanart/\2</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"id":\s"\d*",\s*"url":\s"https://([^/]*)/fanart/([^"]*)",\s*"lang":\s"!$$18|!en",\s*"likes[^,]*,\s*"season":\s"([0-9,]+)</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </ParseFanartTvTvShowSeasonLandscape> + </scraperfunctions> diff --git a/addons/metadata.common.imdb.com/addon.xml b/addons/metadata.common.imdb.com/addon.xml index b5763c2f0c..2391d124af 100644 --- a/addons/metadata.common.imdb.com/addon.xml +++ b/addons/metadata.common.imdb.com/addon.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon id="metadata.common.imdb.com" name="IMDB Scraper Library" - version="2.9.3" + version="3.1.0" provider-name="Team Kodi"> <requires> <import addon="xbmc.metadata" version="2.1.0"/> diff --git a/addons/metadata.common.imdb.com/changelog.txt b/addons/metadata.common.imdb.com/changelog.txt index b4543c7c86..be2a0c4eda 100644 --- a/addons/metadata.common.imdb.com/changelog.txt +++ b/addons/metadata.common.imdb.com/changelog.txt @@ -1,3 +1,51 @@ +[B]3.1.0[/B] +- fixed: re-write most regular expressions following IMDb site layout changes + +[B]3.0.8[/B] +- changed: another change to IMDb outline + +[B]3.0.7[/B] +- changed: removed one of the IMDb outline catch + +[B]3.0.6[/B] +- fixed: try to limit world wide English to over ride proper USA title + +[B]3.0.5[/B] +- fixed: IMDb cast and outline following IMDb layout changes + +[B]3.0.4[/B] +- fixed: IMDb plot after IMDb layout changes + +[B]3.0.3[/B] +- fixed: World-wide English title won't scraped correctly + +[B]3.0.2[/B] +- Use TV certification in the absence of MPAA ones + +[B]3.0.1[/B] +- fixed: USA Title won't scraped correctly under some circumstances, plot outline quirks, IMDB Posters + +[B]3.0.0[/B] +- fixed: IMDb plot outline under some circumstances + +[B]2.9.9[/B] +- fixed: Thumb for IMDb cast + +[B]2.9.8[/B] +- fixed: IMDb outline for some movies + +[B]2.9.7[/B] +- changed: attempt to scrape generic local title from IMDb if multiple are available + +[B]2.9.6[/B] +- fixed: movie title issues after IMDb layout changes + +[B]2.9.5[/B] +- fixed: IMDb Full credits after IMDb layout changes + +[B]2.9.4[/B] +- fixed: USA certification rating due to IMDb changes + [B]2.9.3[/B] - fixed: always get USA rating regardless of the country set @@ -55,7 +103,7 @@ - fixed: MetaCritic Score [B]2.7.3[/B] -- fixed: orginal title won't scrape in some cases +- fixed: original title won't scrape in some cases [B]2.7.2[/B] - changed: make sure to parse the intended page @@ -115,7 +163,7 @@ - fixed: fetching directors and writers due to site changes [B]2.1.3[/B] -- fixed: make sure IMDb rating is geting fetched in every region +- fixed: make sure IMDb rating is getting fetched in every region [B]2.1.2[/B] - fixed: IMDb rating after another site change @@ -145,10 +193,10 @@ - reverted: fixchars removed from cast parsing, leads to Dharma Beta2 hanging, will be added back once next Beta is out [B]2.0.2[/B] -- fixed: some more cast won't get scraped under certain circumtances +- fixed: some more cast won't get scraped under certain circumstances [B]2.0.1[/B] -- fixed: cast won't get scraped under certain circumtances +- fixed: cast won't get scraped under certain circumstances [B]2.0.0[/B] - changed: adapted new IMDb layout diff --git a/addons/metadata.common.imdb.com/imdb.xml b/addons/metadata.common.imdb.com/imdb.xml index b5a5b35efb..0797bad7a1 100644 --- a/addons/metadata.common.imdb.com/imdb.xml +++ b/addons/metadata.common.imdb.com/imdb.xml @@ -1,7 +1,7 @@ -<?xml version="1.0" encoding="UTF-8"?> +<?xml version="1.0" encoding="UTF-8"?> <scraperfunctions> <GetIMDBGenresById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBGenres">http://akas.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBGenres">http://www.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBGenresById> @@ -15,21 +15,21 @@ </ParseIMDBGenres> <GetIMDBRatingById dest="5"> <!-- Compatibility function for Pre-Krypton versions--> - <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBRating">http://akas.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBRating">http://www.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBRatingById> <ParseIMDBRating dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> - <RegExp input="$$1" output="<rating>\1</rating><votes>\2</votes>" dest="2"> - <expression><span\sitemprop="ratingValue">([0-9.]+).*?ratingCount">([0-9,]+)<</expression> + <RegExp input="$$1" output="<rating>\2</rating><votes>\1</votes>" dest="2"> + <expression>"ratingCount":\s([0-9,]+),\s*"bestRating":\s"[^"]*",\s*"worstRating":\s"[^"]*",\s*"ratingValue":\s"([0-9.]+)</expression> </RegExp> <expression noclean="1" /> </RegExp> </ParseIMDBRating> <GetIMDBRatingsById dest="5" clearbuffers="no"> - <RegExp input="$$1" output="<details><url cache="\1-main.html" function="ParseIMDBRatings">http://akas.imdb.com/title/\1/|accept-language=en-us</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="\1-main.html" function="ParseIMDBRatings">http://www.imdb.com/title/\1/|accept-language=en-us</url></details>" dest="5"> <expression noclean="1">^(tt\d+)</expression> </RegExp> <RegExp input="$$1" output="default="true"" dest="3"> @@ -38,15 +38,15 @@ </GetIMDBRatingsById> <ParseIMDBRatings dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> - <RegExp input="$$1" output="<ratings><rating name="imdb" $$3><value>\1</value><votes>\2</votes></rating></ratings>" dest="2"> - <expression><span\sitemprop="ratingValue">([0-9.]+).*?ratingCount">([0-9,]+)<</expression> + <RegExp input="$$1" output="<ratings><rating name="imdb" $$3><value>\2</value><votes>\1</votes></rating></ratings>" dest="2"> + <expression>"ratingCount":\s([0-9,]+),\s*"bestRating":\s"[^"]*",\s*"worstRating":\s"[^"]*",\s*"ratingValue":\s"([0-9.]+)</expression> </RegExp> <expression noclean="1" /> </RegExp> </ParseIMDBRatings> <GetIMDBTOP250ById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBTOP250">http://akas.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBTOP250">http://www.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBTOP250ById> @@ -60,21 +60,21 @@ </ParseIMDBTOP250> <GetIMDBStudioById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBStudio">http://akas.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBStudio">http://www.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBStudioById> <ParseIMDBStudio dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="$$1" output="<studio>\1</studio>" dest="2"> - <expression>"/company/[^>]+>[^<]*<[^>]*>([^<]+)</span></expression> + <expression>"/company/[^"]+"\s*>([^<]+)</a></expression> </RegExp> <expression noclean="1" /> </RegExp> </ParseIMDBStudio> <GetIMDBCountryById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBCountry">http://akas.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBCountry">http://www.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBCountryById> @@ -84,34 +84,34 @@ <expression clear="yes" noclean="1">Country:[^>]+>(.*?)</div></expression> </RegExp> <RegExp input="$$6" output="<country>\1</country>" dest="2"> - <expression repeat="yes">itemprop='url'>([^<]+)</expression> + <expression repeat="yes">>([^<]+)</a></expression> </RegExp> <expression noclean="1" /> </RegExp> </ParseIMDBCountry> <GetMetaCriticRatingById dest="5"> <!-- Compatibility function for Pre-Krypton versions--> - <RegExp input="$$1" output="<details><url cache="$$1-criticreviews.html" function="ParseMetaCriticRating">http://akas.imdb.com/title/$$1/criticreviews|accept-language=en-us</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-criticreviews.html" function="ParseMetaCriticRating">http://www.imdb.com/title/$$1/criticreviews|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetMetaCriticRatingById> <ParseMetaCriticRating dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="$$1" output="\1" dest="6"> - <expression noclean="1">(<div class="metascore_block".*)</expression> + <expression clear="yes" noclean="1"><div\sclass="metacriticScore\sscore_mixed\stitleReviewBarSubItem"(.*?)<span\sclass="ghostText"</expression> </RegExp> <RegExp input="$$6" output="<rating max="100">\1</value>" dest="2"> - <expression clear="yes"><span itemprop="ratingValue">(\d+)</span></expression> + <expression clear="yes"><span>(\d+)</span></expression> </RegExp> <RegExp input="$$6" output="<votes>\1</votes>" dest="2+"> - <expression><span itemprop="ratingCount">(\d+)</span></expression> + <expression>>(\d+)\suser</a></expression> </RegExp> <expression noclean="1" /> </RegExp> </ParseMetaCriticRating> <GetMetaCriticRatingsById dest="5" clearbuffers="no"> - <RegExp input="$$1" output="<details><url cache="\1-criticreviews.html" function="ParseMetaCriticRatings">http://akas.imdb.com/title/\1/criticreviews|accept-language=en-us</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="\1-criticreviews.html" function="ParseMetaCriticRatings">http://www.imdb.com/title/\1/criticreviews|accept-language=en-us</url></details>" dest="5"> <expression noclean="1">(tt\d+)</expression> </RegExp> <RegExp input="$$1" output="default="true"" dest="3"> @@ -122,13 +122,13 @@ <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="$$4" output="<ratings><rating name="metacritic" max="100" $$3>\1</rating></ratings>" dest="2"> <RegExp input="$$1" output="\1" dest="6"> - <expression clear="yes" noclean="1">(<div class="metascore_block".*)</expression> + <expression clear="yes" noclean="1"><div\sclass="metacriticScore\sscore_mixed\stitleReviewBarSubItem"(.*?)<span\sclass="ghostText"</expression> </RegExp> <RegExp input="$$6" output="<value>\1</value>" dest="4"> - <expression clear="yes"><span itemprop="ratingValue">(\d+)</span></expression> + <expression clear="yes"><span>(\d+)</span></expression> </RegExp> <RegExp input="$$6" output="<votes>\1</votes>" dest="4+"> - <expression><span itemprop="ratingCount">(\d+)</span></expression> + <expression>>(\d+)\suser</a></expression> </RegExp> <expression noclean="1" clear="yes"/> </RegExp> @@ -137,21 +137,21 @@ </ParseMetaCriticRatings> <GetIMDBPlotById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBPlot">http://akas.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBPlot">http://www.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBPlotById> <ParseIMDBPlot dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="$$1" output="<plot>\1</plot>" dest="2"> - <expression fixchars="1" trim="1"><h2>Storyline</h2>\s+<div\sclass="inline\scanwrap"\sitemprop="description">\s+<p>(.*?)<[^a/]</expression> + <expression fixchars="1" trim="1"><h2>Storyline</h2>\s+<div\sclass="inline\scanwrap">\s+<p>\s+<span>(.*?)</span></expression> </RegExp> <expression noclean="1" /> </RegExp> </ParseIMDBPlot> <GetIMDBTaglineById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBTagline">http://akas.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBTagline">http://www.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBTaglineById> @@ -165,38 +165,47 @@ </ParseIMDBTagline> <GetIMDBOutlineById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBOutline">http://akas.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBOutline">http://www.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBOutlineById> <ParseIMDBOutline dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="$$1" output="<outline>\1</outline>" dest="2"> - <expression fixchars="1" trim="1">itemprop="description">(.+?)</div></expression> + <expression fixchars="1" trim="1"><div class="summary_text">(.+?)<div\sclass</expression> </RegExp> <RegExp input="$$1" output="<outline>\1</outline>" dest="2"> - <expression fixchars="1" trim="1">itemprop="description">(.+?)See\sfull\ssummary</expression> + <expression fixchars="1" trim="1"><div class="summary_text">(.+?)<a\shref="(.+?)=tt_ov_pl"</expression> + </RegExp> + <RegExp input="$$1" output="<outline>\1</outline>" dest="2"> + <expression fixchars="1" trim="1"><div class="summary_text">(.+?)<a\shref="[^"]*"\s*>Add\sa\sPlot</expression> </RegExp> <expression noclean="1" /> </RegExp> </ParseIMDBOutline> <GetIMDBOutlineToPlotById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBOutlineToPlot">http://akas.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBOutlineToPlot">http://www.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBOutlineToPlotById> <ParseIMDBOutlineToPlot dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> - <RegExp input="$$1" output="<plot>\1</plot>" dest="2"> - <expression fixchars="1" trim="1">itemprop="description">([^<]+)<</expression> + <RegExp input="$$1" output="<outline>\1</outline>" dest="2"> + <expression fixchars="1" trim="1"><div class="summary_text">(.+?)<div\sclass</expression> + </RegExp> + <RegExp input="$$1" output="<outline>\1</outline>" dest="2"> + <expression fixchars="1" trim="1"><div class="summary_text">(.+?)<a\shref="(.+?)=tt_ov_pl"</expression> + </RegExp> + <RegExp input="$$1" output="<outline>\1</outline>" dest="2"> + <expression fixchars="1" trim="1"><div class="summary_text">(.+?)<a\shref="[^"]*"\s*>Add\sa\sPlot</expression> </RegExp> <expression noclean="1" /> </RegExp> </ParseIMDBOutlineToPlot> <GetIMDBCastById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBCast">http://akas.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBCast">http://www.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBCastById> @@ -206,10 +215,10 @@ <expression noclean="1"><table\sclass="cast_list">(.*?)</table></expression> </RegExp> <RegExp input="$$6" output="<actor><thumb>\2\3SX1024_SY1024_.jpg</thumb><name>\1</name><role>\5</role></actor>" dest="7"> - <expression repeat="yes" clear="yes" trim="3,4" noclean="1,2"><img[^a]*alt="([^"]*)"[^"]*"[^"]*"[^s]*src="(?:[^"]*\.[^"]*"class="loadlate\shidden\s"\sloadlate="([^"]*)(_V._))[^>]*.*?ter">[^>]*>\n\s*(<[^>]*>)?([^<\(]*)?</expression> + <expression repeat="yes" clear="yes" trim="3,4" noclean="1,2"><img[^a]*alt="([^"]*)"[^"]*"[^"]*"[^s]*src="(?:[^"]*\.[^"]*"\sclass="loadlate\shidden\s"\sloadlate="([^"]*)(_V..?_))[^>]*.*?ter">[^>]*>(<[^>]*>)?([^<\(]*)?</expression> </RegExp> <RegExp input="$$6" output="<actor><thumb></thumb><name>\1</name><role>\3</role></actor>" dest="7+"> - <expression repeat="yes" trim="1,2,3" fixchars="3" noclean="1,2"><img[^a]*alt="([^"]*)"[^"]*"[^"]*"[^s]*src="(?:[^"]*\.[^"]*\.png)"\sclass=".*?"\s/>*.*?ter">[^>]*>\n\s*(<[^>]*>)?([^<\(]*)?</expression> + <expression repeat="yes" trim="1,2,3" fixchars="3" noclean="1,2"><img[^a]*alt="([^"]*)"[^"]*"[^"]*"[^s]*src="(?:[^"]*\.[^"]*\.png)"\sclass=".*?"\s/>*.*?ter">[^>]*>(<[^>]*>)?([^<\(]*)?</expression> </RegExp> <RegExp input="$$7" output="<actor><thumb>\1</thumb>\2</actor>" dest="2+"> <expression repeat="yes" clear="yes" noclean="1,2,3"><actor><thumb>(?:(http.*?)|_SX[0-9]+_SY[0-9]+_)?</thumb>(.*?)</actor></expression> @@ -219,7 +228,7 @@ </ParseIMDBCast> <GetIMDBDirectorsById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBDirectors">http://akas.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBDirectors">http://www.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBDirectorsById> @@ -229,14 +238,14 @@ <expression clear="yes" noclean="1">Director(?:s)?:.*?</h4>(.*?)<div class</expression> </RegExp> <RegExp input="$$6" output="<director>\1</director>" dest="2"> - <expression repeat="yes" fixchars="1" clear="yes">href="/name[^>]*>[^<]*<[^>]*>([^<]*)<</expression> + <expression repeat="yes" fixchars="yes" clear="yes">href="/name[^>]*>([^<]*)</expression> </RegExp> <expression noclean="1" /> </RegExp> </ParseIMDBDirectors> <GetIMDBWritersById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBWriters">http://akas.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBWriters">http://www.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBWritersById> @@ -246,41 +255,44 @@ <expression clear="yes" noclean="1">Writer(?:s)?:.*?</h4>(.*?)<div class</expression> </RegExp> <RegExp input="$$6" output="<credits>\1</credits>" dest="2"> - <expression repeat="yes" fixchars="1" clear="yes">href="/name[^>]*>[^<]*<[^>]*>([^<]*)<</expression> + <expression repeat="yes" fixchars="yes" clear="yes">href="/name[^>]*>([^<]*)</expression> </RegExp> <expression noclean="1" /> </RegExp> </ParseIMDBWriters> <GetIMDBFullCastById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-combined.html" function="ParseIMDBFullCast">http://akas.imdb.com/title/$$1/combined|accept-language=en-us</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-reference.html" function="ParseIMDBFullCast">http://www.imdb.com/title/$$1/reference|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBFullCastById> <ParseIMDBFullCast dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="$$1" output="\1" dest="6"> - <expression noclean="1"><table class="cast">(.*?)</table></expression> + <expression noclean="1"><table\sclass="cast_list">(.*?)</table></expression> </RegExp> - <RegExp input="$$6" output="<actor><thumb>\1_SX1024_SY1024_\2</thumb><name>\3</name><role>\5</role></actor>" dest="7"> - <expression repeat="yes" clear="yes" fixchars="3,5" trim="3,5" noclean="1,2"><img src="(?:([^"]*\.)[^"]*(\.jpg))?[^>]*[^"]*"nm"><a href="[^"]*[^>]*>([^<]*)<[^"]*"ddd">([^<]<)?[^"]*"char">(.*?)</td></expression> + <RegExp input="$$6" output="<actor><thumb>\2\3SX1024_SY1024_.jpg</thumb><name>\1</name><role>\5</role></actor>" dest="7"> + <expression repeat="yes" clear="yes" trim="3,4" noclean="1,2"><img[^a]*alt="([^"]*)"[^"]*"[^"]*"[^s]*src="(?:[^"]*\.[^"]*"\sclass="loadlate\shidden\s"\sloadlate="([^"]*)(_V..?_))[^>]*.*?ter">[^>]*>\n\s*(<[^>]*>)?([^<\(]*)?</expression> + </RegExp> + <RegExp input="$$6" output="<actor><thumb></thumb><name>\1</name><role>\3</role></actor>" dest="7+"> + <expression repeat="yes" trim="1,2,3" fixchars="3" noclean="1,2"><img[^a]*alt="([^"]*)"[^"]*"[^"]*"[^s]*src="(?:[^"]*\.[^"]*\.png)"\sclass=".*?"\s/>*.*?ter">[^>]*>\n\s*(<[^>]*>)?([^<\(]*)?</expression> </RegExp> <RegExp input="$$7" output="<actor><thumb>\1</thumb>\2</actor>" dest="2+"> - <expression repeat="yes" clear="yes" noclean="1,2,3"><actor><thumb>(?:(http.*?)|_SX[0-9]+_SY[0-9]+_)</thumb>(.*?)</actor></expression> + <expression repeat="yes" clear="yes" noclean="1,2,3"><actor><thumb>(?:(http.*?)|_SX[0-9]+_SY[0-9]+_)?</thumb>(.*?)</actor></expression> </RegExp> <expression noclean="1" /> </RegExp> </ParseIMDBFullCast> <GetIMDBFullDirectorsById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-combined.html" function="ParseIMDBFullDirectors">http://akas.imdb.com/title/$$1/combined|accept-language=en-us</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-reference.html" function="ParseIMDBFullDirectors">http://www.imdb.com/title/$$1/reference|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBFullDirectorsById> <ParseIMDBFullDirectors dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="$$1" output="\1" dest="6"> - <expression clear="yes" noclean="1">Director(?:s)?:.*?</h5>[^>]*>(.*?)</div</expression> + <expression clear="yes" noclean="1">Director(?:s)?:.*?ipl-inline-list[^>]*>(.*?)</div</expression> </RegExp> <RegExp input="$$6" output="<director>\1</director>" dest="2"> <expression repeat="yes" fixchars="1"><a href="/name/[^>]*>([^<]*)<</expression> @@ -290,14 +302,14 @@ </ParseIMDBFullDirectors> <GetIMDBFullWritersById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-combined.html" function="ParseIMDBFullWriters">http://akas.imdb.com/title/$$1/combined|accept-language=en-us</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-reference.html" function="ParseIMDBFullWriters">http://www.imdb.com/title/$$1/reference|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBFullWritersById> <ParseIMDBFullWriters dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="$$1" output="\1" dest="6"> - <expression noclean="1">Writing\scredits(.*?)name="</expression> + <expression noclean="1">Writer(?:s)?:.*?ipl-inline-list[^>]*>(.*?)</div</expression> </RegExp> <RegExp input="$$6" output="<credits>\1</credits>" dest="2"> <expression repeat="yes" fixchars="1"><a href="/name/[^>]*>([^<]*)<</expression> @@ -307,30 +319,30 @@ </ParseIMDBFullWriters> <GetIMDBThumbsById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-posters.html" function="ParseIMDBThumbs">http://akas.imdb.com/title/$$1/posters|accept-language=en-us</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-main.html" function="ParseIMDBThumbs">http://www.imdb.com/title/$$1/|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBThumbsById> <ParseIMDBThumbs dest="5"> <RegExp input="$$6" output="<details>\1</details>" dest="5"> - <RegExp input="$$1" output="\1_SX1024_SY1024_\2" dest="4"> - <expression noclean="1,2"><a\sname="poster".*?src="(.*?)_S.*?(.jpg)".*?</a></expression> - </RegExp> - <RegExp input="$$4" output="<thumb aspect="poster">\1</thumb>" dest="6"> - <expression noclean="1">(.*?_SX[0-9]+_SY[0-9]+_.jpg)</expression> + <RegExp input="$$1" output="<thumb aspect="poster">\1\2.jpg</thumb>" dest="6"> + <expression noclean="1">Poster"\s*src="(.*?)(_V._)</expression> </RegExp> <expression noclean="1" /> </RegExp> </ParseIMDBThumbs> <GetIMDBUSACert dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-combined.html" function="ParseIMDBUSACert">http://akas.imdb.com/title/$$1/combined|accept-language=en-us</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-reference.html" function="ParseIMDBUSACert">http://www.imdb.com/title/$$1/reference|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBUSACert> <ParseIMDBUSACert dest="5"> <RegExp input="$$1" output="<details><mpaa>$INFO[certprefix]\1</mpaa></details>" dest="5"> - <expression>>\s*USA:(P?G|PG-13|R|NC-17)</a></expression> + <expression>>\s*United\sStates:(TV-(Y7?|P?G|14|MA))</a></expression> + </RegExp> + <RegExp input="$$1" output="<details><mpaa>$INFO[certprefix]\1</mpaa></details>" dest="5"> + <expression>>\s*United\sStates:(P?G|PG-13|R|NC-17)</a></expression> </RegExp> <RegExp input="$$1" output="<details><mpaa>$INFO[certprefix]\1</mpaa></details>" dest="5"> <expression>MPAA</a>:</h5><div\sclass="info-content">Rated\s(P?G|PG-13|R|NC-17)</expression> @@ -338,14 +350,14 @@ </ParseIMDBUSACert> <GetIMDBCountryCert dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-combined.html" function="ParseIMDBCountryCert">http://akas.imdb.com/title/$$1/combined|accept-language=en-us</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-reference.html" function="ParseIMDBCountryCert">http://www.imdb.com/title/$$1/reference|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> <RegExp input="$INFO[imdbcertcountry]" output="$$2" dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-combined.html" function="ParseIMDBUSACert">http://akas.imdb.com/title/$$1/combined|accept-language=en-us</url></details>" dest="2"> + <RegExp input="$$1" output="<details><url cache="$$1-reference.html" function="ParseIMDBUSACert">http://www.imdb.com/title/$$1/reference|accept-language=en-us</url></details>" dest="2"> <expression noclean="1"/> </RegExp> - <expression>USA</expression> + <expression>United States</expression> </RegExp> </GetIMDBCountryCert> <ParseIMDBCountryCert dest="5"> @@ -355,81 +367,57 @@ </ParseIMDBCountryCert> <GetIMDBAKATitlesById dest="5"> - <RegExp input="$$1" output="<details><url cache="$$1-combined.html" function="ParseIMDBAKATitles">http://akas.imdb.com/title/$$1/combined|accept-language=en-us</url></details>" dest="5"> + <RegExp input="$$1" output="<details><url cache="$$1-releaseinfo.html" function="ParseIMDBAKATitles">http://www.imdb.com/title/$$1/releaseinfo|accept-language=en-us</url></details>" dest="5"> <expression noclean="1" /> </RegExp> </GetIMDBAKATitlesById> <ParseIMDBAKATitles dest="5"> <RegExp input="$$2" output="<details><title>\1</title></details>" dest="5"> - <RegExp input="$$1" output="\1" dest="2"> - <expression fixchars="1"><h1>([^<]*)</expression> + <RegExp input="$$1" output="\2" dest="2"> + <expression>'og:title'\scontent="(IMDb\s-\s)?(?:&#x22;)?([^"]*?)(?:&#x22;)? \([^\(]*?([0-9]{4})(?:–\s)?\)</expression> </RegExp> <RegExp input="$$10" output="\1" dest="4"> - <RegExp input="$$1" output="\2" dest="9"> - <expression fixchars="2"><meta\sname="title"\scontent="(IMDb\s-\s)?(?:&#x22;)?([^"]*?)(?:&#x22;)? \([^\(]*?([0-9]{4})(?:–\s)?\)</expression> + <RegExp input="$$1" output="\1" dest="9"> + <expression><td>\(original\stitle\)[^>]+>[^>]+>([^<]+)</expression> </RegExp> <RegExp input="$$1" output="\1" dest="9"> - <expression fixchars="1">class="originalTitle">([^<]*)</expression> + <expression>class="originalTitle">([^<]*)</expression> </RegExp> <RegExp input="$$9" output="\1" dest="10"> <expression /> </RegExp> <RegExp input="$$1" output="\1" dest="11"> - <expression fixchars="1" clear="yes">>\s*?"([^<]+)"[^<]+[<em>]?[^"]+Hong Kong\s[<em>][^"]+English</expression> - </RegExp> - <RegExp input="$$11" output="\1" dest="10"> - <expression>(.+)</expression> - </RegExp> - <RegExp input="$$1" output="\1" dest="11"> - <expression fixchars="1" clear="yes">>\s*?"([^<]+)"[^<]+[<em>]?[^"]+((Canada)\s(<em>)?\((English|imdb))</expression> - </RegExp> - <RegExp input="$$11" output="\1" dest="10"> - <expression>(.+)</expression> - </RegExp> - <RegExp input="$$1" output="\1" dest="11"> - <expression fixchars="1" clear="yes">>\s*?"([^<]+)"[^<]+[<em>]?[^"]+(UK(<em>)?<br>)</expression> + <expression>'og:title'\scontent="(IMDb\s-\s)?(?:&#x22;)?([^"]*?)(?:&#x22;)? \([^\(]*?([0-9]{4})(?:–\s)?\)</expression> </RegExp> <RegExp input="$$11" output="\1" dest="10"> <expression>(.+)</expression> </RegExp> <RegExp input="$$1" output="\1" dest="11"> - <expression fixchars="1" clear="yes">>\s*?"([^<]+)"[^"]+International\s(<em>)?\(English\stitle\)(</em>)?(,|<)( |b)</expression> + <expression clear="yes"><td>Hong Kong\s\(English[^>]+>[^>]+>([^<]+)</expression> </RegExp> <RegExp input="$$11" output="\1" dest="10"> <expression>(.+)</expression> </RegExp> <RegExp input="$$1" output="\1" dest="11"> - <expression fixchars="1" clear="yes">>\s*?"([^<]+)"[^"]+International\s(<em>)?\(English\stitle\)(</em>)? (<em>)?\(imdb</expression> + <expression clear="yes"><td>Canada\s\(English[^>]+>[^>]+>([^<]+)</expression> </RegExp> <RegExp input="$$11" output="\1" dest="10"> <expression>(.+)</expression> </RegExp> - <RegExp input="$$1" output="\1" dest="12"> - <expression fixchars="1" clear="yes"><a\shref="/country/[^>]+>(UK</a></div>)</expression> - </RegExp> - <RegExp input="$$12" output="$$9" dest="10"> - <expression>(.+)</expression> - </RegExp> - <RegExp input="$$1" output="\1" dest="12"> - <expression clear="yes"><a\shref="/country/[^>]+>(USA</a></div>)</expression> - </RegExp> - <RegExp input="$$12" output="$$9" dest="10"> - <expression>(.+)</expression> - </RegExp> <RegExp input="$$1" output="\1" dest="11"> - <expression fixchars="1" clear="yes">>\s*?"([^<]+)"[^<]+[<em>]?[^"]+(USA(<em>)?<br>)</expression> + <expression clear="yes"><td>UK<[^>]+>[^>]+>([^<]+)</expression> </RegExp> <RegExp input="$$11" output="\1" dest="10"> <expression>(.+)</expression> </RegExp> <RegExp input="$$1" output="\1" dest="11"> - <expression fixchars="1" clear="yes">>\s*?"([^<]+)"[^<]+[<em>]?[^"]+((USA)\s(<em>)?\((English|imdb))</expression> + <expression clear="yes"><td>World-wide\s\(English\stitle\)<[^>]+>[^>]+>([^<]+)</expression> </RegExp> <RegExp input="$$11" output="\1" dest="10"> <expression>(.+)</expression> </RegExp> <RegExp input="$$1" output="\1" dest="11"> - <expression fixchars="1" clear="yes">>\s*?"([^<]+)"[^<]+[<em>]?[^"]+((USA)\s(<em>)?\((new\stitle))</expression> + <expression clear="yes"><td>USA<[^>]+>[^>]+>([^<]+)</expression> </RegExp> <RegExp input="$$11" output="\1" dest="10"> <expression>(.+)</expression> @@ -440,23 +428,14 @@ <expression>(.+)</expression> </RegExp> <RegExp input="$$1" output="\1" dest="4"> - <expression fixchars="1">>\s*?"([^<]+)"[^<]+[<em>]?[^"]+$INFO[imdbakatitles]</expression> - </RegExp> - <RegExp input="$$4" output="\1" dest="2"> - <expression>(.+)</expression> + <expression><td>$INFO[imdbakatitles][^>]+>[^>]+>([^<]+)</expression> </RegExp> <RegExp input="$$1" output="\1" dest="4"> - <expression fixchars="1">>\s*?"([^<]+)"[^<]+[<em>]?[^"]+$INFO[imdbakatitles]\s(<em>)?\((imdb\sdisplay)</expression> + <expression><td>$INFO[imdbakatitles]<[^>]+>[^>]+>([^<]+)</expression> </RegExp> <RegExp input="$$4" output="\1" dest="2"> <expression>(.+)</expression> </RegExp> - <RegExp input="$$1" output="\1" dest="5"> - <expression><a\shref="/country/[^>]+>($INFO[imdbakatitles])</expression> - </RegExp> - <RegExp input="$$5" output="$$9" dest="4"> - <expression>($INFO[imdbakatitles])</expression> - </RegExp> <RegExp input="$INFO[imdbakatitles]" output="$$9" dest="4"> <expression>Keep Original</expression> </RegExp> diff --git a/addons/metadata.common.musicbrainz.org/addon.xml b/addons/metadata.common.musicbrainz.org/addon.xml index b73d251fc1..70d133adc2 100644 --- a/addons/metadata.common.musicbrainz.org/addon.xml +++ b/addons/metadata.common.musicbrainz.org/addon.xml @@ -1,7 +1,7 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon id="metadata.common.musicbrainz.org" name="MusicBrainz Scraper Library" - version="2.1.2" + version="2.2.0" provider-name="Team Kodi"> <requires> <import addon="xbmc.metadata" version="2.1.0"/> diff --git a/addons/metadata.common.musicbrainz.org/musicbrainz.xml b/addons/metadata.common.musicbrainz.org/musicbrainz.xml index 3aba73676a..bdc4221676 100644 --- a/addons/metadata.common.musicbrainz.org/musicbrainz.xml +++ b/addons/metadata.common.musicbrainz.org/musicbrainz.xml @@ -91,19 +91,19 @@ </GetMBAlbumTitleByMBID> <ParseMBAlbumTitle dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> - <RegExp input="$$1" output="<musicBrainzAlbumID>\1</musicBrainzAlbumID><title>\2</title>" dest="2"> + <RegExp input="$$1" output="<musicbrainzalbumid>\1</musicbrainzalbumid><title>\2</title>" dest="2"> <expression noclean="1"><release id="([^"]*)"><title>([^<]*)<</expression> </RegExp> - <!--MBID - release group--> + <!--MBID - release group--> <RegExp input="$$1" output="<musicbrainzreleasegroupid>\1</musicbrainzreleasegroupid>" dest="2+"> <expression noclean="1"><release-group\stype="[^"]*"\sid="([^"]*)"</expression> </RegExp> <RegExp input="$$1" output="<musicbrainzreleasegroupid>\1</musicbrainzreleasegroupid>" dest="2+"> <expression noclean="1"><release-group\stype="[^"]*"\stype-id="[^"]*"\sid="([^"]*)"</expression> - </RegExp> + </RegExp> <RegExp input="$$1" output="<musicbrainzreleasegroupid>\1</musicbrainzreleasegroupid>" dest="2+"> <expression noclean="1"><release-group\sid="([^"]*)"\stype="[^"]*"</expression> - </RegExp> + </RegExp> <RegExp input="$$1" output="<musicbrainzreleasegroupid>\1</musicbrainzreleasegroupid>" dest="2+"> <expression noclean="1"><release-group\sid="([^"]*)"\stype-id="[^"]*"</expression> </RegExp> @@ -112,7 +112,10 @@ </RegExp> <RegExp input="$$1" output="<musicbrainzreleasegroupid>\1</musicbrainzreleasegroupid>" dest="2+"> <expression noclean="1"><release-group\stype-id="[^"]*"\stype="[^"]*"\sid="([^"]*)"</expression> - </RegExp> + </RegExp> + <RegExp input="$$1" output="<scrapedmbid>\1</scrapedmbid>" dest="2+"> + <expression noclean="1" /> + </RegExp> <expression noclean="1">(.+)</expression> </RegExp> </ParseMBAlbumTitle> diff --git a/addons/metadata.common.theaudiodb.com/addon.xml b/addons/metadata.common.theaudiodb.com/addon.xml index b25f09b14c..0969e65f2b 100644 --- a/addons/metadata.common.theaudiodb.com/addon.xml +++ b/addons/metadata.common.theaudiodb.com/addon.xml @@ -1,7 +1,7 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon id="metadata.common.theaudiodb.com" name="TheAudioDb Scraper Library" - version="1.9.1" + version="2.0.0" provider-name="Team Kodi"> <requires> <import addon="xbmc.metadata" version="2.1.0"/> diff --git a/addons/metadata.common.theaudiodb.com/tadb.xml b/addons/metadata.common.theaudiodb.com/tadb.xml index 5538b21f4e..60912060a7 100644 --- a/addons/metadata.common.theaudiodb.com/tadb.xml +++ b/addons/metadata.common.theaudiodb.com/tadb.xml @@ -50,6 +50,118 @@ </RegExp> </ParseTADBArtistFanarts> + <GetTADBArtistClearlogoByID dest="5" clearbuffers="no"> + <RegExp input="$$1" output="<details><url function="ParseTADBArtistClearlogo" cache="tadb-\1-artist.json">http://www.theaudiodb.com/api/v1/json/58424d43204d6564696120/artist.php?i=\1</url></details>" dest="5"> + <expression noclean="1" /> + </RegExp> + </GetTADBArtistClearlogoByID> + <GetTADBArtistClearlogoByMBID dest="5" clearbuffers="no"> + <RegExp input="$$1" output="<details><url function="ParseTADBArtistClearlogo" cache="tadb-\1-artist.json">http://www.theaudiodb.com/api/v1/json/58424d43204d6564696120/artist-mb.php?i=\1</url></details>" dest="5"> + <expression noclean="1"/> + </RegExp> + </GetTADBArtistClearlogoByMBID> + <ParseTADBArtistClearlogo dest="5" clearbuffers="no"> + <RegExp input="$$13" output="<details>\1</details>" dest="5"> + <RegExp input="" output="" dest="13"> + <expression /> + </RegExp> + <RegExp input="" output="" dest="14"> + <expression /> + </RegExp> + <RegExp input="$$1" output="<thumb aspect="clearlogo" preview="\1/preview">\1</thumb>" dest="14"> + <expression repeat="yes">strArtistLogo\d?":"([^"]*)</expression> + </RegExp> + <RegExp input="$$14" output="\1" dest="13"> + <expression noclean="1">(.+)</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </ParseTADBArtistClearlogo> + + <GetTADBArtistClearartByID dest="5" clearbuffers="no"> + <RegExp input="$$1" output="<details><url function="ParseTADBArtistClearart" cache="tadb-\1-artist.json">http://www.theaudiodb.com/api/v1/json/58424d43204d6564696120/artist.php?i=\1</url></details>" dest="5"> + <expression noclean="1" /> + </RegExp> + </GetTADBArtistClearartByID> + <GetTADBArtistClearartByMBID dest="5" clearbuffers="no"> + <RegExp input="$$1" output="<details><url function="ParseTADBArtistClearart" cache="tadb-\1-artist.json">http://www.theaudiodb.com/api/v1/json/58424d43204d6564696120/artist-mb.php?i=\1</url></details>" dest="5"> + <expression noclean="1"/> + </RegExp> + </GetTADBArtistClearartByMBID> + <ParseTADBArtistClearart dest="5" clearbuffers="no"> + <RegExp input="$$13" output="<details>\1</details>" dest="5"> + <RegExp input="" output="" dest="13"> + <expression /> + </RegExp> + <RegExp input="" output="" dest="14"> + <expression /> + </RegExp> + <RegExp input="$$1" output="<thumb aspect="clearart" preview="\1/preview">\1</thumb>" dest="14"> + <expression repeat="yes">strArtistClearart\d?":"([^"]*)</expression> + </RegExp> + <RegExp input="$$14" output="\1" dest="13"> + <expression noclean="1">(.+)</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </ParseTADBArtistClearart> + + <GetTADBArtistLandscapeByID dest="5" clearbuffers="no"> + <RegExp input="$$1" output="<details><url function="ParseTADBArtistLandscape" cache="tadb-\1-artist.json">http://www.theaudiodb.com/api/v1/json/58424d43204d6564696120/artist.php?i=\1</url></details>" dest="5"> + <expression noclean="1" /> + </RegExp> + </GetTADBArtistLandscapeByID> + <GetTADBArtistLandscapeByMBID dest="5" clearbuffers="no"> + <RegExp input="$$1" output="<details><url function="ParseTADBArtistLandscape" cache="tadb-\1-artist.json">http://www.theaudiodb.com/api/v1/json/58424d43204d6564696120/artist-mb.php?i=\1</url></details>" dest="5"> + <expression noclean="1"/> + </RegExp> + </GetTADBArtistLandscapeByMBID> + <ParseTADBArtistLandscape dest="5" clearbuffers="no"> + <RegExp input="$$13" output="<details>\1</details>" dest="5"> + <RegExp input="" output="" dest="13"> + <expression /> + </RegExp> + <RegExp input="" output="" dest="14"> + <expression /> + </RegExp> + <RegExp input="$$1" output="<thumb aspect="landscape" preview="\1/preview">\1</thumb>" dest="14"> + <expression repeat="yes">strArtistWideThumb\d?":"([^"]*)</expression> + </RegExp> + <RegExp input="$$14" output="\1" dest="13"> + <expression noclean="1">(.+)</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </ParseTADBArtistLandscape> + + <GetTADBArtistBannerByID dest="5" clearbuffers="no"> + <RegExp input="$$1" output="<details><url function="ParseTADBArtistBanner" cache="tadb-\1-artist.json">http://www.theaudiodb.com/api/v1/json/58424d43204d6564696120/artist.php?i=\1</url></details>" dest="5"> + <expression noclean="1" /> + </RegExp> + </GetTADBArtistBannerByID> + <GetTADBArtistBannerByMBID dest="5" clearbuffers="no"> + <RegExp input="$$1" output="<details><url function="ParseTADBArtistBanner" cache="tadb-\1-artist.json">http://www.theaudiodb.com/api/v1/json/58424d43204d6564696120/artist-mb.php?i=\1</url></details>" dest="5"> + <expression noclean="1"/> + </RegExp> + </GetTADBArtistBannerByMBID> + <ParseTADBArtistBanner dest="5" clearbuffers="no"> + <RegExp input="$$13" output="<details>\1</details>" dest="5"> + <RegExp input="" output="" dest="13"> + <expression /> + </RegExp> + <RegExp input="" output="" dest="14"> + <expression /> + </RegExp> + <RegExp input="$$1" output="<thumb aspect="banner" preview="\1/preview">\1</thumb>" dest="14"> + <expression repeat="yes">strArtistBanner\d?":"([^"]*)</expression> + </RegExp> + <RegExp input="$$14" output="\1" dest="13"> + <expression noclean="1">(.+)</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </ParseTADBArtistBanner> + <GetTADBBiographyByID dest="5" clearbuffers="no"> <RegExp input="$$1" output="<details><url function="ParseTADBBiography" cache="tadb-\1-artist.json">http://www.theaudiodb.com/api/v1/json/58424d43204d6564696120/artist.php?i=\1</url></details>" dest="5"> <expression noclean="1"/> @@ -575,4 +687,61 @@ </RegExp> </ParseTADBAlbumThumbs> + <GetTADBAlbumBackByID dest="5"> + <RegExp input="$$1" output="<details><url function="ParseTADBAlbumBack" cache="tadb-\1-album.json">http://www.theaudiodb.com/api/v1/json/58424d43204d6564696120/album.php?m=\1</url></details>" dest="5"> + <expression noclean="1"/> + </RegExp> + </GetTADBAlbumBackByID> + <GetTADBAlbumBackByMBID dest="5"> + <RegExp input="$$1" output="<details><url function="ParseTADBAlbumBack" cache="tadb-\1-album.json">http://www.theaudiodb.com/api/v1/json/58424d43204d6564696120/album-mb.php?i=\1</url></details>" dest="5"> + <expression noclean="1"/> + </RegExp> + </GetTADBAlbumBackByMBID> + <ParseTADBAlbumBack dest="5"> + <RegExp input="$$2" output="<details>\1</details>" dest="5"> + <RegExp input="$$1" output="<thumb aspect="back" preview="\1/preview">\1</thumb>" dest="2"> + <expression repeat="yes">strAlbumThumbBack\d?":"([^"]*)</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </ParseTADBAlbumBack> + + <GetTADBAlbumDiscartByID dest="5"> + <RegExp input="$$1" output="<details><url function="ParseTADBAlbumDiscart" cache="tadb-\1-album.json">http://www.theaudiodb.com/api/v1/json/58424d43204d6564696120/album.php?m=\1</url></details>" dest="5"> + <expression noclean="1"/> + </RegExp> + </GetTADBAlbumDiscartByID> + <GetTADBAlbumDiscartByMBID dest="5"> + <RegExp input="$$1" output="<details><url function="ParseTADBAlbumDiscart" cache="tadb-\1-album.json">http://www.theaudiodb.com/api/v1/json/58424d43204d6564696120/album-mb.php?i=\1</url></details>" dest="5"> + <expression noclean="1"/> + </RegExp> + </GetTADBAlbumDiscartByMBID> + <ParseTADBAlbumDiscart dest="5"> + <RegExp input="$$2" output="<details>\1</details>" dest="5"> + <RegExp input="$$1" output="<thumb aspect="discart" preview="\1/preview">\1</thumb>" dest="2"> + <expression repeat="yes">strAlbumCDart\d?":"([^"]*)</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </ParseTADBAlbumDiscart> + + <GetTADBAlbumSpineByID dest="5"> + <RegExp input="$$1" output="<details><url function="ParseTADBAlbumSpine" cache="tadb-\1-album.json">http://www.theaudiodb.com/api/v1/json/58424d43204d6564696120/album.php?m=\1</url></details>" dest="5"> + <expression noclean="1"/> + </RegExp> + </GetTADBAlbumSpineByID> + <GetTADBAlbumSpineByMBID dest="5"> + <RegExp input="$$1" output="<details><url function="ParseTADBAlbumSpine" cache="tadb-\1-album.json">http://www.theaudiodb.com/api/v1/json/58424d43204d6564696120/album-mb.php?i=\1</url></details>" dest="5"> + <expression noclean="1"/> + </RegExp> + </GetTADBAlbumSpineByMBID> + <ParseTADBAlbumSpine dest="5"> + <RegExp input="$$2" output="<details>\1</details>" dest="5"> + <RegExp input="$$1" output="<thumb aspect="spine" preview="\1/preview">\1</thumb>" dest="2"> + <expression repeat="yes">strAlbumSpine\d?":"([^"]*)</expression> + </RegExp> + <expression noclean="1" /> + </RegExp> + </ParseTADBAlbumSpine> + </scraperfunctions> diff --git a/addons/metadata.common.themoviedb.org/addon.xml b/addons/metadata.common.themoviedb.org/addon.xml index 0f5b905349..8000a309f4 100644 --- a/addons/metadata.common.themoviedb.org/addon.xml +++ b/addons/metadata.common.themoviedb.org/addon.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon id="metadata.common.themoviedb.org" name="The Movie Database Scraper Library" - version="2.17.6" + version="3.1.7" provider-name="Team Kodi"> <requires> <import addon="xbmc.metadata" version="2.1.0"/> diff --git a/addons/metadata.common.themoviedb.org/tmdb.xml b/addons/metadata.common.themoviedb.org/tmdb.xml index ed637830c8..722fa466b4 100644 --- a/addons/metadata.common.themoviedb.org/tmdb.xml +++ b/addons/metadata.common.themoviedb.org/tmdb.xml @@ -1,88 +1,81 @@ <?xml version="1.0" encoding="UTF-8"?> <scraperfunctions> - <GetTMDBCertificationsByIdChain dest="4"> + <GetTMDBCertificationsByIdChain clearbuffers="no" dest="4"> <!-- Expected chaining format= tmdb_id::certification_country::certification_prefix--> <RegExp input="$$5" output="<details>\1</details>" dest="4"> - <RegExp input="$$1" output="<url function="ParseTMDBCertifications" cache="tmdb-cert-\1.json">https://api.tmdb.org/3/movie/\1/releases?api_key=ecbc86c92da237cb9faff6d3ddc4be6d&amp;language=$INFO[tmdbcertcountry]</url>" dest="5"> - <expression /> + <RegExp input="$$1" output="\1" dest="16"> + <expression>.+::(.+)::(.+)?</expression> + </RegExp> + <RegExp input="$$1" output="\1" dest="17"> + <expression>.+::.+::(.+)?</expression> + </RegExp> + <RegExp input="$$1" output="<url function="ParseTMDBCertifications" cache="tmdb-cert-\1.json">https://api.tmdb.org/3/movie/\1/releases?api_key=45ab4cebe57ae11c2ee50c87005ddfe8</url>" dest="5"> + <expression>(.+)::(.+)::(.+)?</expression> </RegExp> <expression noclean="1" /> </RegExp> </GetTMDBCertificationsByIdChain> <ParseTMDBCertifications dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> - <RegExp input="$$1" output="<mpaa>$INFO[certprefix]\1</mpaa>" dest="2"> - <expression fixchars="1">certification":"([^"]*)","[^"]*":"$INFO[tmdbcertcountry]"(.*?),"</expression> + <RegExp input="$$1" output="\1" dest="15"> + <expression fixchars="1">certification":"([^"]*)","[^"]*":"$$16"(.*?),"</expression> + </RegExp> + <RegExp input="$$15" output="<mpaa>$$17 \1</mpaa>" dest="2"> + <expression>(.+)</expression> </RegExp> <expression noclean="1" /> </RegExp> </ParseTMDBCertifications> - <GetTMDBTitleByIdChain dest="4"> + <GetTMDBTitleByIdChain clearbuffers="no" dest="4"> <!-- Expected chaining format= tmdb_id::language--> <RegExp input="$$5" output="<details>\1</details>" dest="4"> - <RegExp input="$$1" output="<url function="ParseTMDBTitle" cache="tmdb-$INFO[language]-\1.json">https://api.tmdb.org/3/movie/\1?api_key=ecbc86c92da237cb9faff6d3ddc4be6d&amp;language=$INFO[language]</url>" dest="5"> - <expression /> + <RegExp input="$$1" output="\1::\2" dest="16"> + <expression>(.+)::(.+)</expression> </RegExp> - <expression noclean="1" /> - </RegExp> - </GetTMDBTitleByIdChain> - <GetTMDBLangTitleByIdChain dest="4"> - <RegExp input="$$5" output="<details>\1</details>" dest="4"> - <RegExp input="$$1" output="<url function="ParseTMDBTitle" cache="tmdb-$INFO[tmdbtitlelanguage]-\1.json">https://api.tmdb.org/3/movie/\1?api_key=ecbc86c92da237cb9faff6d3ddc4be6d&amp;language=$INFO[tmdbtitlelanguage]</url>" dest="5"> - <expression /> + <RegExp input="$$1" output="<url function="ParseTMDBTitle" cache="tmdb-\2-\1.json">https://api.tmdb.org/3/movie/\1?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=\2</url>" dest="5"> + <expression>(.+)::(.+)</expression> </RegExp> - <RegExp input="$INFO[tmdbtitlelanguage]" output="$$2" dest="5"> - <RegExp input="$$1" output="<url function="ParseTMDBTitle" cache="tmdb-$INFO[tmdbsearchlanguage]-\1.json">https://api.tmdb.org/3/movie/\1?api_key=ecbc86c92da237cb9faff6d3ddc4be6d&amp;language=$INFO[tmdbsearchlanguage]</url>" dest="2"> - <expression/> + <RegExp input="$$1" output="$$2" dest="5"> + <RegExp input="$$1" output="<url function="ParseTMDBTitle" cache="tmdb-en-\1.json">https://api.tmdb.org/3/movie/\1?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=en</url>" dest="2"> + <expression>(.+)::</expression> </RegExp> - <expression>Keep Original</expression> + <expression>(.+)::Keep Original</expression> </RegExp> <expression noclean="1"/> </RegExp> - </GetTMDBLangTitleByIdChain> + </GetTMDBTitleByIdChain> <ParseTMDBTitle dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="$$1" output="<title>\1</title>" dest="2"> <expression fixchars="1">"title":"([^"]*)</expression> </RegExp> - <RegExp input="$INFO[tmdbtitlelanguage]" output="$$3" dest="2"> + <RegExp input="$$16" output="$$3" dest="2"> <RegExp input="$$1" output="<title>\1</title>" dest="3"> <expression fixchars="1">"original_title":"([^"]*)</expression> </RegExp> - <expression>Keep Original</expression> + <expression>(.+)::Keep Original</expression> </RegExp> <expression noclean="1" /> </RegExp> </ParseTMDBTitle> - <GetTMDBPlotByIdChain clearbuffers="no" dest="4"> + <GetTMDBPlotByIdChain clearbuffers="no" dest="4"> <!-- Expected chaining format= tmdb_id::language--> <RegExp input="$$5" output="<details>\1</details>" dest="4"> <RegExp input="$$1" output="\1" dest="8"> - <expression clear="yes" noclean="1" /> + <expression encode="1">(.+)::.+</expression> </RegExp> - <RegExp input="$$8" output="<url function="ParseTMDBPlot" cache="tmdb-$INFO[language]-\1.json">https://api.tmdb.org/3/movie/\1?api_key=ecbc86c92da237cb9faff6d3ddc4be6d&amp;language=$INFO[language]</url>" dest="5"> - <expression /> + <RegExp input="$$1" output="<url function="ParseTMDBPlot" cache="tmdb-\2-\1.json">https://api.tmdb.org/3/movie/\1?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=\2</url>" dest="5"> + <expression>(.+)::(.+)</expression> </RegExp> <expression noclean="1" /> </RegExp> </GetTMDBPlotByIdChain> - <GetTMDBLangPlotByIdChain clearbuffers="no" dest="4"> - <RegExp input="$$5" output="<details>\1</details>" dest="4"> - <RegExp input="$$1" output="\1" dest="8"> - <expression clear="yes" noclean="1" /> - </RegExp> - <RegExp input="$$8" output="<url function="ParseTMDBPlot" cache="tmdb-$INFO[tmdbplotlanguage]-\1.json">https://api.tmdb.org/3/movie/\1?api_key=ecbc86c92da237cb9faff6d3ddc4be6d&amp;language=$INFO[tmdbplotlanguage]</url>" dest="5"> - <expression /> - </RegExp> - <expression noclean="1" /> - </RegExp> - </GetTMDBLangPlotByIdChain> <ParseTMDBPlot dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="$$1" output="\1" dest="9"> <expression clear="yes" fixchars="1">"overview":"(.*?)","</expression> </RegExp> - <RegExp input="$$9" output="<url function="ParseFallbackTMDBPlot" cache="tmdb-en-$$8.json">https://api.tmdb.org/3/movie/$$8?api_key=ecbc86c92da237cb9faff6d3ddc4be6d&amp;language=en</url>" dest="2"> + <RegExp input="$$9" output="<url function="ParseFallbackTMDBPlot" cache="tmdb-en-$$8.json">https://api.tmdb.org/3/movie/$$8?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=en</url>" dest="2"> <expression>^$</expression> </RegExp> <RegExp input="$$9" output="<plot>\1</plot>" dest="2"> @@ -100,34 +93,23 @@ </RegExp> </ParseFallbackTMDBPlot> - <GetTMDBTaglineByIdChain clearbuffers="no" dest="4"> + <GetTMDBTaglineByIdChain clearbuffers="no" dest="4"> <!-- Expected chaining format= tmdb_id::language--> <RegExp input="$$5" output="<details>\1</details>" dest="4"> <RegExp input="$$1" output="\1" dest="8"> - <expression clear="yes" noclean="1" /> + <expression>(.+)::.+</expression> </RegExp> - <RegExp input="$$8" output="<url function="ParseTMDBTagline" cache="tmdb-$INFO[language]-\1.json">https://api.tmdb.org/3/movie/\1?api_key=ecbc86c92da237cb9faff6d3ddc4be6d&amp;language=$INFO[language]</url>" dest="5"> - <expression /> + <RegExp input="$$1" output="<url function="ParseTMDBTagline" cache="tmdb-\2-\1.json">https://api.tmdb.org/3/movie/\1?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=\2</url>" dest="5"> + <expression>(.+)::(.+)</expression> </RegExp> <expression noclean="1" /> </RegExp> </GetTMDBTaglineByIdChain> - <GetTMDBLangTaglineByIdChain clearbuffers="no" dest="4"> - <RegExp input="$$5" output="<details>\1</details>" dest="4"> - <RegExp input="$$1" output="\1" dest="8"> - <expression clear="yes" noclean="1" /> - </RegExp> - <RegExp input="$$8" output="<url function="ParseTMDBTagline" cache="tmdb-$INFO[tmdbtaglinelanguage]-\1.json">https://api.tmdb.org/3/movie/\1?api_key=ecbc86c92da237cb9faff6d3ddc4be6d&amp;language=$INFO[tmdbtaglinelanguage]</url>" dest="5"> - <expression /> - </RegExp> - <expression noclean="1" /> - </RegExp> - </GetTMDBLangTaglineByIdChain> <ParseTMDBTagline dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="$$1" output="\1" dest="9"> - <expression clear="yes" fixchars="1">"tagline":"([^"]*)</expression> + <expression clear="yes" fixchars="1">"tagline":"(.*?)","</expression> </RegExp> - <RegExp input="$$9" output="<url function="ParseFallbackTMDBTagline" cache="tmdb-en-$$8.json">https://api.tmdb.org/3/movie/$$8?api_key=ecbc86c92da237cb9faff6d3ddc4be6d&amp;language=en</url>" dest="2"> + <RegExp input="$$9" output="<url function="ParseFallbackTMDBTagline" cache="tmdb-en-$$8.json">https://api.tmdb.org/3/movie/$$8?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=en</url>" dest="2"> <expression>^$</expression> </RegExp> <RegExp input="$$9" output="<tagline>\1</tagline>" dest="2"> @@ -139,18 +121,18 @@ <ParseFallbackTMDBTagline dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="$$1" output="<tagline>\1</tagline>" dest="2"> - <expression clear="yes" fixchars="1">"tagline":"([^"]*)</expression> + <expression clear="yes" fixchars="1">"tagline":"(.*?)","</expression> </RegExp> <expression noclean="1" /> </RegExp> </ParseFallbackTMDBTagline> - <GetTMDBTagsByIdChain clearbuffers="no" dest="4"> + <GetTMDBTagsByIdChain clearbuffers="no" dest="4"> <!-- Expected chaining format= tmdb_id--> <RegExp input="$$5" output="<details>\1</details>" dest="4"> <RegExp input="$$1" output="\1" dest="8"> <expression clear="yes" noclean="1" /> </RegExp> - <RegExp input="$$8" output="<url function="ParseTMDBTags" >https://api.tmdb.org/3/movie/\1/keywords?api_key=ecbc86c92da237cb9faff6d3ddc4be6d</url>" dest="5"> + <RegExp input="$$8" output="<url function="ParseTMDBTags" >https://api.tmdb.org/3/movie/\1/keywords?api_key=45ab4cebe57ae11c2ee50c87005ddfe8</url>" dest="5"> <expression /> </RegExp> <expression noclean="1" /> @@ -165,57 +147,114 @@ </RegExp> </ParseTMDBTags> - <GetTMDBSetByIdChain clearbuffers="no" dest="4"> + <GetTMDBSetByIdChain clearbuffers="no" dest="4"> <!-- Expected chaining format= tmdb_id::language--> <RegExp input="$$5" output="<details>\1</details>" dest="4"> <RegExp input="$$1" output="\1" dest="8"> - <expression clear="yes" noclean="1" /> + <expression>(.+)::(.+)</expression> + </RegExp> + <RegExp input="$$1" output="\2" dest="10"> + <expression>(.+)::(.+)</expression> </RegExp> - <RegExp input="$$8" output="<url function="ParseTMDBSet" cache="tmdb-$INFO[language]-\1.json">https://api.tmdb.org/3/movie/\1?api_key=ecbc86c92da237cb9faff6d3ddc4be6d&amp;language=$INFO[language]</url>" dest="5"> + <RegExp input="$$8" output="<url function="GetTMDBSetID" cache="tmdb-$$10-\1.json">https://api.tmdb.org/3/movie/\1?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=$$10</url>" dest="5"> <expression /> </RegExp> <expression noclean="1" /> </RegExp> </GetTMDBSetByIdChain> - <GetTMDBLangSetByIdChain clearbuffers="no" dest="4"> - <RegExp input="$$5" output="<details>\1</details>" dest="4"> - <RegExp input="$$1" output="\1" dest="8"> - <expression clear="yes" noclean="1" /> + <GetTMDBSetID dest="5" clearbuffers="no"> + <RegExp input="$$2" output="<details>\1</details>" dest="5"> + <RegExp input="$$1" output="\1" dest="9"> + <expression clear="yes" noclean="1">"belongs_to_collection":\{"id":([0-9]+),"name":"([^"]*)</expression> </RegExp> - <RegExp input="$$8" output="<url function="ParseTMDBSet" cache="tmdb-$INFO[tmdbsetlanguage]-\1.json">https://api.tmdb.org/3/movie/\1?api_key=ecbc86c92da237cb9faff6d3ddc4be6d&amp;language=$INFO[tmdbsetlanguage]</url>" dest="5"> - <expression /> + <RegExp input="$$9" output="<url function="ParseTMDBBaseImageURL" cache="tmdb-config.json">https://api.tmdb.org/3/configuration?api_key=45ab4cebe57ae11c2ee50c87005ddfe8</url>" dest="2"> + <expression>(.+)</expression> + </RegExp> + <RegExp input="$$9" output="<url function="ParseTMDBSetOutline" cache="tmdbset-$$10-\1.json">https://api.tmdb.org/3/collection/\1?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=$$10&amp;append_to_response=images&amp;include_image_language=$$10,en,null</url>" dest="2+"> + <expression>(.+)</expression> </RegExp> <expression noclean="1" /> </RegExp> - </GetTMDBLangSetByIdChain> - <ParseTMDBSet dest="5"> + </GetTMDBSetID> + <ParseTMDBSetOutline dest="5" clearbuffers="no"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> - <RegExp input="$$1" output="\1" dest="9"> - <expression clear="yes" noclean="1">"belongs_to_collection":\{"id":[0-9]+,"name":"([^"]*)</expression> + <RegExp input="$$4" output="<set>\1</set>$$13$$14" dest="2"> + <RegExp input="$$1" output="\1" dest="11"> + <expression noclean="1">"id":[0-9]+,"name":"([^"]*)</expression> + </RegExp> + <RegExp input="$$11" output="<name>\1</name>" dest="4"> + <expression>(.+)</expression> + </RegExp> + <RegExp input="$$1" output="\1" dest="6"> + <expression noclean="1">"id":([0-9]+)</expression> + </RegExp> + <RegExp input="$$1" output="\1" dest="9"> + <expression fixchars="1">"id":[0-9]+,"name":"[^"]*","overview":"(.*?)","</expression> + </RegExp> + <RegExp input="$$9" output="<overview>\1</overview>" dest="4+"> + <expression>(.+)</expression> + </RegExp> + <RegExp input="$$1" output="\1" dest="7"> + <expression clear="yes" noclean="1">"posters":\[\{([^\]]*)</expression> + </RegExp> + <RegExp input="$$7" output="<thumb aspect="set" preview="$$20w500\1">$$20original\1</thumb>" dest="13"> + <expression repeat="yes" clear="yes" noclean="1">"file_path":"([^"]*)[^:]*:[^:]*:"$$10</expression> + </RegExp> + <RegExp input="$$7" output="<thumb aspect="set" preview="$$20w500\1">$$20original\1</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"file_path":"([^"]*)[^:]*:[^:]*:"en</expression> + </RegExp> + <RegExp input="$$7" output="<thumb aspect="set" preview="$$20w500\1">$$20original\1</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"file_path":"([^"]*)[^:]*:[^:]*:null</expression> + </RegExp> + <RegExp input="$$1" output="\1" dest="7"> + <expression clear="yes" noclean="1">"backdrops":\[\{([^\]]*)</expression> + </RegExp> + <RegExp input="$$7" output="<thumb aspect="setfanart" preview="$$20w500\1">$$20original\1</thumb>" dest="14"> + <expression clear="yes" repeat="yes" noclean="1">"file_path":"([^"]*)</expression> + </RegExp> + <expression noclean="1" /> </RegExp> - <RegExp input="$$9" output="<url function="ParseFallbackTMDBSet" cache="tmdb-en-$$8.json">https://api.tmdb.org/3/movie/$$8?api_key=ecbc86c92da237cb9faff6d3ddc4be6d&amp;language=en</url>" dest="2"> + <RegExp input="$$9" output="<url function="ParseFallbackTMDBSetOutline" cache="tmdbset-en-$$6.json">https://api.tmdb.org/3/collection/$$6?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=en&amp;append_to_response=images&amp;include_image_language=$$10,en,null</url>" dest="2"> <expression>^$</expression> </RegExp> - <RegExp input="$$9" output="<set>\1</set>" dest="2"> - <expression>(.+)</expression> - </RegExp> <expression noclean="1" /> </RegExp> - </ParseTMDBSet> - <ParseFallbackTMDBSet dest="5"> - <RegExp input="$$2" output="<details>\1</details>" dest="5"> - <RegExp input="$$1" output="<set>\1</set>" dest="2"> - <expression noclean="1">"belongs_to_collection":\{"id":[0-9]+,"name":"([^"]*)</expression> + </ParseTMDBSetOutline> + <ParseFallbackTMDBSetOutline dest="5"> + <RegExp input="$$2" output="<details><set>\1</set>$$13$$14</details>" dest="5"> + <RegExp input="$$11" output="<name>\1</name>" dest="2"> + <expression>(.+)</expression> </RegExp> + <RegExp input="$$1" output="<overview>\1</overview>" dest="2+"> + <expression noclean="1">"id":[0-9]+,"name":"[^"]*","overview":"(.*?)","</expression> + </RegExp> + <RegExp input="$$1" output="\1" dest="7"> + <expression clear="yes" noclean="1">"posters":\[\{([^\]]*)</expression> + </RegExp> + <RegExp input="$$7" output="<thumb aspect="set" preview="$$20w500\1">$$20original\1</thumb>" dest="13"> + <expression repeat="yes" clear="yes" noclean="1">"file_path":"([^"]*)[^:]*:[^:]*:"$$10</expression> + </RegExp> + <RegExp input="$$7" output="<thumb aspect="set" preview="$$20w500\1">$$20original\1</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"file_path":"([^"]*)[^:]*:[^:]*:"en</expression> + </RegExp> + <RegExp input="$$7" output="<thumb aspect="set" preview="$$20w500\1">$$20original\1</thumb>" dest="13+"> + <expression repeat="yes" noclean="1">"file_path":"([^"]*)[^:]*:[^:]*:null</expression> + </RegExp> + <RegExp input="$$1" output="\1" dest="7"> + <expression clear="yes" noclean="1">"backdrops":\[\{([^\]]*)</expression> + </RegExp> + <RegExp input="$$7" output="<thumb aspect="setfanart" preview="$$20w500\1">$$20original\1</thumb>" dest="14"> + <expression clear="yes" repeat="yes" noclean="1">"file_path":"([^"]*)</expression> + </RegExp> <expression noclean="1" /> </RegExp> - </ParseFallbackTMDBSet> + </ParseFallbackTMDBSetOutline> - <GetTMDBCastByIdChain dest="4"> + <GetTMDBCastByIdChain dest="4"> <!-- Expected chaining format= tmdb_id--> <RegExp input="$$5" output="<details>\1</details>" dest="4"> - <RegExp input="$$1" output="<url function="ParseTMDBBaseImageURL" cache="tmdb-config.json">https://api.tmdb.org/3/configuration?api_key=ecbc86c92da237cb9faff6d3ddc4be6d</url>" dest="5"> + <RegExp input="$$1" output="<url function="ParseTMDBBaseImageURL" cache="tmdb-config.json">https://api.tmdb.org/3/configuration?api_key=45ab4cebe57ae11c2ee50c87005ddfe8</url>" dest="5"> <expression /> </RegExp> - <RegExp input="$$1" output="<url function="ParseTMDBCast" cache="tmdb-cast-\1.json">https://api.tmdb.org/3/movie/\1/casts?api_key=ecbc86c92da237cb9faff6d3ddc4be6d</url>" dest="5+"> + <RegExp input="$$1" output="<url function="ParseTMDBCast" cache="tmdb-cast-\1.json">https://api.tmdb.org/3/movie/\1/casts?api_key=45ab4cebe57ae11c2ee50c87005ddfe8</url>" dest="5+"> <expression /> </RegExp> <expression noclean="1" /> @@ -236,9 +275,9 @@ </RegExp> </ParseTMDBCast> - <GetTMDBDirectorsByIdChain dest="4"> + <GetTMDBDirectorsByIdChain dest="4"> <!-- Expected chaining format= tmdb_id--> <RegExp input="$$5" output="<details>\1</details>" dest="4"> - <RegExp input="$$1" output="<url function="ParseTMDBDirectors" cache="tmdb-cast-\1.json">https://api.tmdb.org/3/movie/\1/casts?api_key=ecbc86c92da237cb9faff6d3ddc4be6d</url>" dest="5"> + <RegExp input="$$1" output="<url function="ParseTMDBDirectors" cache="tmdb-cast-\1.json">https://api.tmdb.org/3/movie/\1/casts?api_key=45ab4cebe57ae11c2ee50c87005ddfe8</url>" dest="5"> <expression /> </RegExp> <expression noclean="1" /> @@ -256,9 +295,9 @@ </RegExp> </ParseTMDBDirectors> - <GetTMDBWitersByIdChain dest="4"> + <GetTMDBWitersByIdChain dest="4"> <!-- Expected chaining format= tmdb_id--> <RegExp input="$$5" output="<details>\1</details>" dest="4"> - <RegExp input="$$1" output="<url function="ParseTMDBWriters" cache="tmdb-cast-\1.json">https://api.tmdb.org/3/movie/\1/casts?api_key=ecbc86c92da237cb9faff6d3ddc4be6d</url>" dest="5"> + <RegExp input="$$1" output="<url function="ParseTMDBWriters" cache="tmdb-cast-\1.json">https://api.tmdb.org/3/movie/\1/casts?api_key=45ab4cebe57ae11c2ee50c87005ddfe8</url>" dest="5"> <expression /> </RegExp> <expression noclean="1" /> @@ -276,22 +315,14 @@ </RegExp> </ParseTMDBWriters> - <GetTMDBGenresByIdChain dest="4"> + <GetTMDBGenresByIdChain dest="4"> <!-- Expected chaining format= tmdb_id::language--> <RegExp input="$$5" output="<details>\1</details>" dest="4"> - <RegExp input="$$1" output="<url function="ParseTMDBGenres" cache="tmdb-$INFO[language]-\1.json">https://api.tmdb.org/3/movie/\1?api_key=ecbc86c92da237cb9faff6d3ddc4be6d&amp;language=$INFO[language]</url>" dest="5"> - <expression /> + <RegExp input="$$1" output="<url function="ParseTMDBGenres" cache="tmdb-\2-\1.json">https://api.tmdb.org/3/movie/\1?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=\2</url>" dest="5"> + <expression>(.+)::(.+)</expression> </RegExp> <expression noclean="1" /> </RegExp> </GetTMDBGenresByIdChain> - <GetTMDBLangGenresByIdChain dest="4"> - <RegExp input="$$5" output="<details>\1</details>" dest="4"> - <RegExp input="$$1" output="<url function="ParseTMDBGenres" cache="tmdb-$INFO[tmdbgenreslanguage]-\1.json">https://api.tmdb.org/3/movie/\1?api_key=ecbc86c92da237cb9faff6d3ddc4be6d&amp;language=$INFO[tmdbgenreslanguage]</url>" dest="5"> - <expression /> - </RegExp> - <expression noclean="1" /> - </RegExp> - </GetTMDBLangGenresByIdChain> <ParseTMDBGenres dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="$$1" output="\1" dest="7"> @@ -306,8 +337,14 @@ <GetTMDBRatingByIdChain dest="4"> <!-- Compatibility function for Pre-Krypton versions--> <RegExp input="$$5" output="<details>\1</details>" dest="4"> - <RegExp input="$$1" output="<url function="ParseTMDBRating" cache="tmdb-$INFO[language]-\1.json">https://api.tmdb.org/3/movie/\1?api_key=ecbc86c92da237cb9faff6d3ddc4be6d&amp;language=$INFO[language]</url>" dest="5"> - <expression /> + <RegExp input="$$1" output="\2" dest="11"> + <expression>(.+)::(..)</expression> + </RegExp> + <RegExp input="$$1" output="\2" dest="11"> + <expression>(.+)::([^\|]*)</expression> + </RegExp> + <RegExp input="$$1" output="<url function="ParseTMDBRating" cache="tmdb-$$11-\1.json">https://api.tmdb.org/3/movie/\1?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=$$11</url>" dest="5"> + <expression>^(.+)::</expression> </RegExp> <expression noclean="1" /> </RegExp> @@ -324,9 +361,15 @@ </RegExp> </ParseTMDBRating> - <GetTMDBRatingsByIdChain dest="4" clearbuffers="no"> + <GetTMDBRatingsByIdChain dest="4" clearbuffers="no"> <!-- Expected chaining format= tmdb_id::language_for_caching--> <RegExp input="$$5" output="<details>\1</details>" dest="4"> - <RegExp input="$$1" output="<url function="ParseTMDBRatings" cache="tmdb-$INFO[language]-\1.json">https://api.tmdb.org/3/movie/\1?api_key=ecbc86c92da237cb9faff6d3ddc4be6d&amp;language=$INFO[language]</url>" dest="5"> + <RegExp input="$$1" output="\2" dest="11"> + <expression>(.+)::(..)</expression> + </RegExp> + <RegExp input="$$1" output="\2" dest="11"> + <expression>(.+)::([^\|]*)</expression> + </RegExp> + <RegExp input="$$1" output="<url function="ParseTMDBRatings" cache="tmdb-$$11-\1.json">https://api.tmdb.org/3/movie/\1?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=$$11</url>" dest="5"> <expression noclean="1">^((tt)?\d+)</expression> </RegExp> <RegExp input="$$1" output="default="true"" dest="3"> @@ -347,10 +390,10 @@ </RegExp> </ParseTMDBRatings> - <GetTMDBStudioByIdChain dest="4"> + <GetTMDBStudioByIdChain dest="4"> <!-- Expected chaining format= tmdb_id::language_for_caching--> <RegExp input="$$5" output="<details>\1</details>" dest="4"> - <RegExp input="$$1" output="<url function="ParseTMDBStudio" cache="tmdb-en-\1.json">https://api.tmdb.org/3/movie/\1?api_key=ecbc86c92da237cb9faff6d3ddc4be6d&amp;language=en</url>" dest="5"> - <expression /> + <RegExp input="$$1" output="<url function="ParseTMDBStudio" cache="tmdb-\2-\1.json">https://api.tmdb.org/3/movie/\1?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=\2</url>" dest="5"> + <expression>(.+)::(.+)</expression> </RegExp> <expression noclean="1" /> </RegExp> @@ -367,10 +410,10 @@ </RegExp> </ParseTMDBStudio> - <GetTMDBCountryByIdChain dest="4"> + <GetTMDBCountryByIdChain dest="4"> <!-- Expected chaining format= tmdb_id::language_for_caching--> <RegExp input="$$5" output="<details>\1</details>" dest="4"> - <RegExp input="$$1" output="<url function="ParseTMDBCountry" cache="tmdb-en-\1.json">https://api.tmdb.org/3/movie/\1?api_key=ecbc86c92da237cb9faff6d3ddc4be6d&amp;language=en</url>" dest="5"> - <expression /> + <RegExp input="$$1" output="<url function="ParseTMDBCountry" cache="tmdb-\2-\1.json">https://api.tmdb.org/3/movie/\1?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=\2</url>" dest="5"> + <expression>(.+)::(.+)</expression> </RegExp> <expression noclean="1" /> </RegExp> @@ -387,22 +430,14 @@ </RegExp> </ParseTMDBCountry> - <GetTMDBTrailerByIdChain dest="4"> + <GetTMDBTrailerByIdChain dest="4"> <!-- Expected chaining format= tmdb_id::language--> <RegExp input="$$5" output="<details>\1</details>" dest="4"> - <RegExp input="$$1" output="<url function="ParseTMDBTrailer" cache="tmdb-trailer-$INFO[language]-\1.json">https://api.tmdb.org/3/movie/\1/trailers?api_key=ecbc86c92da237cb9faff6d3ddc4be6d&amp;language=$INFO[language]</url>" dest="5"> - <expression /> + <RegExp input="$$1" output="<url function="ParseTMDBTrailer" cache="tmdb-trailer-\2-\1.json">https://api.tmdb.org/3/movie/\1/trailers?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=\2</url>" dest="5"> + <expression>(.+)::(.+)</expression> </RegExp> <expression noclean="1" /> </RegExp> </GetTMDBTrailerByIdChain> - <GetTMDBLangTrailerByIdChain dest="4"> - <RegExp input="$$5" output="<details>\1</details>" dest="4"> - <RegExp input="$$1" output="<url function="ParseTMDBTrailer" cache="tmdb-trailer-$INFO[tmdbtrailerlanguage]-\1.json">https://api.tmdb.org/3/movie/\1/trailers?api_key=ecbc86c92da237cb9faff6d3ddc4be6d&amp;language=$INFO[tmdbtrailerlanguage]</url>" dest="5"> - <expression /> - </RegExp> - <expression noclean="1" /> - </RegExp> - </GetTMDBLangTrailerByIdChain> <ParseTMDBTrailer dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="$$1" output="\1" dest="8"> @@ -414,7 +449,7 @@ <RegExp input="$$7" output="<trailer>plugin://plugin.video.youtube/?action=play_video&amp;videoid=\1</trailer>" dest="9"> <expression noclean="1">"source":"([^"]*)</expression> </RegExp> - <RegExp input="$$9" output="<url function="ParseTMDBEnTrailer" cache="tmdb-trailer-en-$$8.json">https://api.tmdb.org/3/movie/$$8/trailers?api_key=ecbc86c92da237cb9faff6d3ddc4be6d&amp;language=en</url>" dest="2"> + <RegExp input="$$9" output="<url function="ParseTMDBEnTrailer" cache="tmdb-trailer-en-$$8.json">https://api.tmdb.org/3/movie/$$8/trailers?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=en</url>" dest="2"> <expression>^$</expression> </RegExp> <RegExp input="$$9" output="$$9" dest="2"> @@ -434,7 +469,7 @@ <RegExp input="$$7" output="<trailer>plugin://plugin.video.youtube/?action=play_video&amp;videoid=\1</trailer>" dest="9"> <expression noclean="1">"source":"([^"]*)</expression> </RegExp> - <RegExp input="$$9" output="<url function="ParseTMDBAllTrailer" cache="tmdb-trailer-$$8.json">https://api.tmdb.org/3/movie/$$8/trailers?api_key=ecbc86c92da237cb9faff6d3ddc4be6d</url>" dest="5"> + <RegExp input="$$9" output="<url function="ParseTMDBAllTrailer" cache="tmdb-trailer-$$8.json">https://api.tmdb.org/3/movie/$$8/trailers?api_key=45ab4cebe57ae11c2ee50c87005ddfe8</url>" dest="2"> <expression>^$</expression> </RegExp> <RegExp input="$$9" output="$$9" dest="2"> @@ -455,14 +490,17 @@ </RegExp> </ParseTMDBAllTrailer> - <GetTMDBFanartByIdChain dest="4"> + <GetTMDBFanartByIdChain dest="4"> <!-- Expected chaining format= tmdb_id::poster_language--> <RegExp input="$$5" output="<details>\1</details>" dest="4"> - <RegExp input="$$1" output="<url function="ParseTMDBBaseImageURL" cache="tmdb-config.json">https://api.tmdb.org/3/configuration?api_key=ecbc86c92da237cb9faff6d3ddc4be6d</url>" dest="5"> - <expression /> + <RegExp input="$$1" output="\2" dest="11"> + <expression>(.+)::(.+)</expression> </RegExp> - <RegExp input="$$1" output="<url function="ParseTMDBFanart" cache="tmdb-images-\1.json">https://api.tmdb.org/3/movie/\1/images?api_key=ecbc86c92da237cb9faff6d3ddc4be6d</url>" dest="5+"> + <RegExp input="$$1" output="<url function="ParseTMDBBaseImageURL" cache="tmdb-config.json">https://api.tmdb.org/3/configuration?api_key=45ab4cebe57ae11c2ee50c87005ddfe8</url>" dest="5"> <expression /> </RegExp> + <RegExp input="$$1" output="<url function="ParseTMDBFanart" cache="tmdb-images-\1.json">https://api.tmdb.org/3/movie/\1/images?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=$$11&amp;include_image_language=$$11,en,null</url>" dest="5+"> + <expression>(.+)::(.+)</expression> + </RegExp> <expression noclean="1" /> </RegExp> </GetTMDBFanartByIdChain> @@ -478,116 +516,66 @@ </RegExp> </ParseTMDBFanart> - <GetTMDBThumbsByIdChain dest="4"> + <GetTMDBThumbsByIdChain clearbuffers="no" dest="4"> <!-- Expected chaining format= tmdb_id::language--> <RegExp input="$$5" output="<details>\1</details>" dest="4"> - <RegExp input="$$1" output="<url function="ParseTMDBBaseImageURL" cache="tmdb-config.json">https://api.tmdb.org/3/configuration?api_key=ecbc86c92da237cb9faff6d3ddc4be6d</url>" dest="5"> - <expression /> + <RegExp input="$$1" output="\2" dest="11"> + <expression>(.+)::(.+)</expression> </RegExp> - <RegExp input="$$1" output="<url function="ParseTMDBThumbs" cache="tmdb-images-$INFO[language]-\1.json">https://api.tmdb.org/3/movie/\1/images?api_key=ecbc86c92da237cb9faff6d3ddc4be6d&amp;language=$INFO[language]</url>" dest="5+"> - <expression /> + <RegExp input="$$1" output="\1" dest="13"> + <expression>(.+)::(.+)</expression> </RegExp> - <expression noclean="1" /> - </RegExp> - </GetTMDBThumbsByIdChain> - <GetTMDBLangThumbsByIdChain dest="4"> - <RegExp input="$$5" output="<details>\1</details>" dest="4"> - <RegExp input="$$1" output="<url function="ParseTMDBBaseImageURL" cache="tmdb-config.json">https://api.tmdb.org/3/configuration?api_key=ecbc86c92da237cb9faff6d3ddc4be6d</url>" dest="5"> + <RegExp input="$$1" output="<url function="ParseTMDBBaseImageURL" cache="tmdb-config.json">https://api.tmdb.org/3/configuration?api_key=45ab4cebe57ae11c2ee50c87005ddfe8</url>" dest="5"> <expression /> </RegExp> - <RegExp input="$$1" output="<url function="ParseTMDBLangThumbs" cache="tmdb-images-$INFO[tmdbthumblanguage]-\1.json">https://api.tmdb.org/3/movie/\1/images?api_key=ecbc86c92da237cb9faff6d3ddc4be6d&amp;language=$INFO[tmdbthumblanguage]</url>" dest="5+"> - <expression /> + <RegExp input="$$1" output="<url function="ParseTMDBThumbs" cache="tmdb-images-\1.json">https://api.tmdb.org/3/movie/\1/images?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=$$11&amp;include_image_language=$$11,en,null</url>" dest="5+"> + <expression>(.+)::(.+)</expression> </RegExp> <expression noclean="1" /> </RegExp> - </GetTMDBLangThumbsByIdChain> + </GetTMDBThumbsByIdChain> <ParseTMDBThumbs clearbuffers="no" dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> - <RegExp input="$$1" output="\1" dest="8"> - <expression noclean="1">"id":([0-9]*),</expression> - </RegExp> <RegExp input="$$1" output="\1" dest="7"> <expression clear="yes" noclean="1">"posters":\[\{([^\]]*)</expression> </RegExp> <RegExp input="$$7" output="<thumb aspect="poster" preview="$$20w500\1">$$20original\1</thumb>" dest="9"> - <expression clear="yes" repeat="yes" noclean="1">"file_path":"([^"]*)</expression> + <expression repeat="yes" clear="yes" noclean="1">"file_path":"([^"]*)[^:]*:[^:]*:"$$11</expression> </RegExp> - <RegExp input="$$9" output="$$9" dest="2"> - <expression clear="yes">(.+)</expression> + <RegExp input="$$7" output="<thumb aspect="poster" preview="$$20w500\1">$$20original\1</thumb>" dest="9+"> + <expression repeat="yes" noclean="1">"file_path":"([^"]*)[^:]*:[^:]*:"en</expression> </RegExp> - <RegExp input="$$9" output="$$12" dest="2+"> - <RegExp input="$INFO[language]" output="<url function="ParseTMDBAllThumbs" cache="tmdb-images-$$8.json">https://api.tmdb.org/3/movie/$$8/images?api_key=ecbc86c92da237cb9faff6d3ddc4be6d</url>" dest="12"> - <expression>en</expression> - </RegExp> - <expression>^$</expression> - </RegExp> - <RegExp input="$INFO[language]" output="<url function="ParseTMDBEnThumbs" cache="tmdb-images-en-$$8.json">https://api.tmdb.org/3/movie/$$8/images?api_key=ecbc86c92da237cb9faff6d3ddc4be6d&amp;language=en</url>" dest="2+"> - <expression>^((?!en).)*$</expression> - </RegExp> - <expression noclean="1">(.+)</expression> - </RegExp> - </ParseTMDBThumbs> - <ParseTMDBLangThumbs clearbuffers="no" dest="5"> - <RegExp input="$$2" output="<details>\1</details>" dest="5"> - <RegExp input="$$1" output="\1" dest="8"> - <expression noclean="1">"id":([0-9]*),</expression> - </RegExp> - <RegExp input="$$1" output="\1" dest="7"> - <expression clear="yes" noclean="1">"posters":\[\{([^\]]*)</expression> - </RegExp> - <RegExp input="$$7" output="<thumb aspect="poster" preview="$$20w500\1">$$20original\1</thumb>" dest="9"> - <expression clear="yes" repeat="yes" noclean="1">"file_path":"([^"]*)</expression> + <RegExp input="$$7" output="<thumb aspect="poster" preview="$$20w500\1">$$20original\1</thumb>" dest="10"> + <expression repeat="yes" clear="yes" noclean="1">"file_path":"([^"]*)[^:]*:[^:]*:null</expression> </RegExp> <RegExp input="$$9" output="$$9" dest="2"> - <expression clear="yes">(.+)</expression> + <expression>(.+)</expression> </RegExp> - <RegExp input="$$9" output="$$12" dest="2+"> - <RegExp input="$INFO[tmdbthumblanguage]" output="<url function="ParseTMDBAllThumbs" cache="tmdb-images-$$8.json">https://api.tmdb.org/3/movie/$$8/images?api_key=ecbc86c92da237cb9faff6d3ddc4be6d</url>" dest="12"> - <expression>en</expression> - </RegExp> + <RegExp input="$$9" output="$$10" dest="2"> <expression>^$</expression> </RegExp> - <RegExp input="$INFO[tmdbthumblanguage]" output="<url function="ParseTMDBEnThumbs" cache="tmdb-images-en-$$8.json">https://api.tmdb.org/3/movie/$$8/images?api_key=ecbc86c92da237cb9faff6d3ddc4be6d&amp;language=en</url>" dest="2+"> - <expression>^((?!en).)*$</expression> - </RegExp> - <expression noclean="1">(.+)</expression> - </RegExp> - </ParseTMDBLangThumbs> - <ParseTMDBEnThumbs clearbuffers="no" dest="5"> - <RegExp input="$$2" output="<details>\1</details>" dest="5"> - <RegExp input="$$1" output="\1" dest="8"> - <expression noclean="1">"id":([0-9]*),</expression> - </RegExp> - <RegExp input="$$1" output="\1" dest="7"> - <expression clear="yes" noclean="1">"posters":\[\{([^\]]*)</expression> - </RegExp> - <RegExp input="$$7" output="<thumb aspect="poster" preview="$$20w500\1">$$20original\1</thumb>" dest="9"> - <expression repeat="yes" noclean="1">"file_path":"([^"]*)</expression> - </RegExp> - <RegExp input="$$9" output="$$9" dest="2"> - <expression clear="yes">(.+)</expression> - </RegExp> - <RegExp input="$$9" output="<url function="ParseTMDBAllThumbs" cache="tmdb-images-$$8.json">https://api.tmdb.org/3/movie/$$8/images?api_key=ecbc86c92da237cb9faff6d3ddc4be6d</url>" dest="2"> + <RegExp input="$$2" output="<url function="ParseFallbackTMDBThumbs">https://api.tmdb.org/3/movie/$$13/images?api_key=45ab4cebe57ae11c2ee50c87005ddfe8</url>" dest="2"> <expression>^$</expression> </RegExp> - <expression noclean="1">(.+)</expression> + <expression noclean="1" /> </RegExp> - </ParseTMDBEnThumbs> - <ParseTMDBAllThumbs dest="5"> + </ParseTMDBThumbs> + + <ParseFallbackTMDBThumbs dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="$$1" output="\1" dest="7"> <expression clear="yes" noclean="1">"posters":\[\{([^\]]*)</expression> </RegExp> <RegExp input="$$7" output="<thumb aspect="poster" preview="$$20w500\1">$$20original\1</thumb>" dest="2"> - <expression repeat="yes" noclean="1">"file_path":"([^"]*)</expression> + <expression repeat="yes" noclean="1">"file_path":"([^"]*)[^:]*:[^:]*:"[^"]*</expression> </RegExp> - <expression noclean="1">(.+)</expression> + <expression noclean="1" /> </RegExp> - </ParseTMDBAllThumbs> + </ParseFallbackTMDBThumbs> <ParseTMDBBaseImageURL clearbuffers="no" dest="4"> <RegExp input="$$5" output="<details>$$20</details>" dest="4"> <RegExp input="$$1" output="\1" dest="20"> - <expression>"images":\{"base_url":"([^"]*)"</expression> + <expression>"images":\{"base_url":"([^"]*)"</expression> </RegExp> <expression noclean="1" /> </RegExp> @@ -595,8 +583,17 @@ <GetTMDBPremieredByIdChain dest="4"> <RegExp input="$$5" output="<details>\1</details>" dest="4"> - <RegExp input="$$1" output="<url function="ParseTMDBPremiered" cache="tmdb-$INFO[tmdbtitlelanguage]-\1.json">https://api.tmdb.org/3/movie/\1?api_key=ecbc86c92da237cb9faff6d3ddc4be6d&amp;language=$INFO[tmdbtitlelanguage]</url>" dest="5"> - <expression /> + <RegExp input="$$1" output="\2" dest="16"> + <expression>(.+)::(.+)</expression> + </RegExp> + <RegExp input="$$1" output="<url function="ParseTMDBPremiered" cache="tmdb-\2-\1.json">https://api.tmdb.org/3/movie/\1?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=\2</url>" dest="5"> + <expression>(.+)::(.+)</expression> + </RegExp> + <RegExp input="$$16" output="$$2" dest="5"> + <RegExp input="$$1" output="<url function="ParseTMDBPremiered" cache="tmdb-$INFO[tmdbcertcountry]-\1.json">https://api.tmdb.org/3/movie/\1?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=$INFO[tmdbcertcountry]</url>" dest="2"> + <expression/> + </RegExp> + <expression>Keep Original</expression> </RegExp> <expression noclean="1" /> </RegExp> diff --git a/addons/metadata.tvdb.com/addon.xml b/addons/metadata.tvdb.com/addon.xml index f8faed97af..b39891ef14 100644 --- a/addons/metadata.tvdb.com/addon.xml +++ b/addons/metadata.tvdb.com/addon.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon id="metadata.tvdb.com" name="The TVDB" - version="3.0.7" + version="3.0.9" provider-name="Team Kodi"> <requires> <import addon="xbmc.metadata" version="2.1.0"/> diff --git a/addons/metadata.tvdb.com/changelog.txt b/addons/metadata.tvdb.com/changelog.txt index b7eb058965..7066da2f46 100644 --- a/addons/metadata.tvdb.com/changelog.txt +++ b/addons/metadata.tvdb.com/changelog.txt @@ -1,3 +1,9 @@ +[B]3.0.9[/B] +- Fixed: Character encoding fixes (part 2) + +[B]3.0.8[/B] +- Fixed: Character encoding fixes + [B]3.0.7[/B] - Fixed: Episode list changes diff --git a/addons/metadata.tvdb.com/tvdb.xml b/addons/metadata.tvdb.com/tvdb.xml index acd90c6d71..6fc8144d7d 100644 --- a/addons/metadata.tvdb.com/tvdb.xml +++ b/addons/metadata.tvdb.com/tvdb.xml @@ -145,6 +145,9 @@ </xsl:stylesheet> </XSLT> + <RegExp input="$$6" output="\1" dest="6"> + <expression noclean="1" fixchars="1"/> + </RegExp> </GetSearchResultsAuth> <!-- input : $$1=series html --> @@ -237,7 +240,7 @@ <RegExp input="$$1" output="<episodeguide><url post="yes" cache="auth.json">https://api.thetvdb.com/login?{"apikey":"439DFEBA9D3059C6","id":\1}|Content-Type=application/json</url></episodeguide>" dest="4+"> <expression noclean="1">"id":\s*?(\d+),</expression> </RegExp> - <expression noclean="1"/> + <expression noclean="1" fixchars="1"/> </RegExp> </GetDetails> <GetFallbackDetails dest="3" clearbuffers="no"> @@ -260,7 +263,7 @@ </RegExp> <expression>missingplot</expression> </RegExp> - <expression noclean="1"/> + <expression noclean="1" fixchars="1"/> </RegExp> </GetFallbackDetails> <GetActors dest="3" clearbuffers="no"> @@ -276,7 +279,7 @@ <RegExp input="$$1" output="<actor><name>\1</name><role>\2</role><order>\3</order></actor>" dest="5+"> <expression repeat="yes" fixchars="1,2">"name":\s*?"([^}]+)",\s*?"role":\s*?"([^}]+)",\s*?"sortOrder":\s*?(\d+),\s*?"image":\s*?(?:""|null),</expression> </RegExp> - <expression noclean="1"/> + <expression noclean="1" fixchars="1"/> </RegExp> </ParseActors> <GetArt dest="3" clearbuffers="no"> @@ -443,7 +446,7 @@ <RegExp input="$$2" output="https://api.thetvdb.com/login?{"apikey":"439DFEBA9D3059C6","id":\1}|Content-Type=application/json" dest="2"> <expression>http://(?:www\.)?thetvdb\.com/api/.+/series/(\d+)/all/</expression> </RegExp> - <expression noclean="1"/> + <expression noclean="1" fixchars="1"/> </RegExp> </GetEpisodeList> <GetEpisodeListAuth dest="3" clearbuffers="no"> @@ -483,7 +486,7 @@ </xsl:stylesheet> </XSLT> - <expression noclean="1"/> + <expression noclean="1" fixchars="1"/> </RegExp> </GetEpisodeListAuth> <LoadEpisodeList dest="4" clearbuffers="no"> @@ -771,7 +774,7 @@ </RegExp> <expression>(?!^\Q$INFO[fallbacklanguage]\E$)</expression> </RegExp> - <expression noclean="1"/> + <expression noclean="1" fixchars="1"/> </RegExp> </GetEpisodeDetailsAuth> <GetFallbackEpisodeDetails dest="3" clearbuffers="no"> @@ -797,7 +800,7 @@ <RegExp input="$$10" output="<Episode>\1</Episode>" dest="13+"> <expression noclean="1"/> </RegExp> - <expression noclean="1"/> + <expression noclean="1" fixchars="1"/> </RegExp> </GetFallbackEpisodeDetails> <ParseEpisodeDetails dest="4" clearbuffers="no"> @@ -1099,7 +1102,7 @@ </xsl:stylesheet> </XSLT> - <expression noclean="1"/> + <expression noclean="1" fixchars="1"/> </RegExp> </ParseEpisodeDetails> </scraper> diff --git a/tools/EventClients/Clients/OSXRemote/HIDRemote/HIDRemote.h b/tools/EventClients/Clients/OSXRemote/HIDRemote/HIDRemote.h index 5c3aed373e..9a589e608a 100644 --- a/tools/EventClients/Clients/OSXRemote/HIDRemote/HIDRemote.h +++ b/tools/EventClients/Clients/OSXRemote/HIDRemote/HIDRemote.h @@ -1,16 +1,16 @@ // -// HIDRemote.h -// HIDRemote V1.4 (18th February 2015) +// HIDRemote.m +// HIDRemote V1.7 (5th September 2018) // // Created by Felix Schwarz on 06.04.07. -// Copyright 2007-2015 IOSPIRIT GmbH. All rights reserved. +// Copyright 2007-2018 IOSPIRIT GmbH. All rights reserved. // // The latest version of this class is available at // http://www.iospirit.com/developers/hidremote/ // // ** LICENSE ************************************************************************* // -// Copyright (c) 2007-2014 IOSPIRIT GmbH (http://www.iospirit.com/) +// Copyright (c) 2007-2017 IOSPIRIT GmbH (http://www.iospirit.com/) // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, @@ -40,7 +40,6 @@ // // ************************************************************************************ - // ************************************************************************************ // ********************************** DOCUMENTATION *********************************** // ************************************************************************************ @@ -67,6 +66,15 @@ #include <Carbon/Carbon.h> #endif +#ifndef HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING + #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + // Enable thread-safe notification handling by default if deploying to OS X >= 10.5 + #define HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING 1 + #else + #define HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING 0 + #endif +#endif + #include <unistd.h> #include <mach/mach.h> #include <sys/types.h> @@ -81,12 +89,14 @@ #include <IOKit/hidsystem/IOHIDParameter.h> #include <IOKit/hidsystem/IOHIDShared.h> -#pragma mark -- Enums / Codes -- +#pragma mark - Enums / Codes +#ifndef HID_REMOTE_MODE_ENUM +#define HID_REMOTE_MODE_ENUM 1 typedef enum { kHIDRemoteModeNone = 0L, - kHIDRemoteModeShared, // Share the remote with others - let's you listen to the remote control events as long as no one has an exclusive lock on it + kHIDRemoteModeShared, // Share the remote with others - let's you listen to the remote control events as long as noone has an exclusive lock on it // (RECOMMENDED ONLY FOR SPECIAL PURPOSES) kHIDRemoteModeExclusive, // Try to acquire an exclusive lock on the remote (NOT RECOMMENDED) @@ -94,6 +104,7 @@ typedef enum kHIDRemoteModeExclusiveAuto // Try to acquire an exclusive lock on the remote whenever the application has focus. Temporarily release control over the // remote when another application has focus (RECOMMENDED) } HIDRemoteMode; +#endif /* HID_REMOTE_MODE_ENUM */ typedef enum { @@ -161,7 +172,7 @@ typedef enum @class HIDRemote; -#pragma mark -- Delegate protocol (mandatory) -- +#pragma mark - Delegate protocol (mandatory) @protocol HIDRemoteDelegate // Notification of button events @@ -178,7 +189,7 @@ typedef enum newID:(SInt32)newID forHardwareWithAttributes:(NSMutableDictionary *)attributes; -// Notification about hardware additions/removals +// Notification about hardware additions/removals - (void)hidRemote:(HIDRemote *)hidRemote // Invoked when new hardware was found / added to HIDRemote's pool foundNewHardwareWithAttributes:(NSMutableDictionary *)attributes; @@ -192,11 +203,11 @@ typedef enum // Matching of newly found receiver hardware - (BOOL)hidRemote:(HIDRemote *)hidRemote // Invoked when new hardware is inspected - inspectNewHardwareWithService:(io_service_t)service // + inspectNewHardwareWithService:(io_service_t)service // prematchResult:(BOOL)prematchResult; // Return YES if HIDRemote should go on with this hardware and try - // to use it, or NO if it should not be pursued further. + // to use it, or NO if it should not be persued further. -// Exclusive lock lending +// Exlusive lock lending - (BOOL)hidRemote:(HIDRemote *)hidRemote lendExclusiveLockToApplicationWithInfo:(NSDictionary *)applicationInfo; @@ -206,11 +217,10 @@ typedef enum - (BOOL)hidRemote:(HIDRemote *)hidRemote shouldRetryExclusiveLockWithInfo:(NSDictionary *)applicationInfo; -@end - +@end -#pragma mark -- Actual header file for class -- +#pragma mark - Actual header file for class @interface HIDRemote : NSObject { // IOMasterPort @@ -219,73 +229,73 @@ typedef enum // Notification ports IONotificationPortRef _notifyPort; CFRunLoopSourceRef _notifyRLSource; - + // Matching iterator io_iterator_t _matchingServicesIterator; - + // SecureInput notification io_object_t _secureInputNotification; - + // Service attributes NSMutableDictionary *_serviceAttribMap; - + // Mode HIDRemoteMode _mode; BOOL _autoRecover; NSTimer *_autoRecoveryTimer; - + // Delegate NSObject <HIDRemoteDelegate> *_delegate; - + // Last seen ID and remote model SInt32 _lastSeenRemoteID; HIDRemoteModel _lastSeenModel; SInt32 _lastSeenModelRemoteID; - + // Unused button codes NSArray *_unusedButtonCodes; - + // Simulate Plus/Minus Hold BOOL _simulateHoldEvents; - + // SecureEventInput workaround BOOL _secureEventInputWorkAround; UInt64 _lastSecureEventInputPIDSum; uid_t _lastFrontUserSession; BOOL _lastScreenIsLocked; - + // Exclusive lock lending BOOL _exclusiveLockLending; BOOL _sendExclusiveResourceReuseNotification; NSNumber *_waitForReturnByPID; NSNumber *_returnToPID; BOOL _isRestarting; - + // Status notifications BOOL _sendStatusNotifications; NSString *_pidString; - + // Status BOOL _applicationIsTerminating; BOOL _isStopping; - + // Thread safety - #ifdef HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING /* #define HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING if you're running your HIDRemote instance on a background thread (requires OS X 10.5 or later) */ + #if HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING /* #define HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING if you're running your HIDRemote instance on a background thread (requires OS X 10.5 or later) */ NSThread *_runOnThread; #endif } -#pragma mark -- PUBLIC: Shared HID Remote -- +#pragma mark - PUBLIC: Shared HID Remote + (HIDRemote *)sharedHIDRemote; -#pragma mark -- PUBLIC: System Information -- +#pragma mark - PUBLIC: System Information + (BOOL)isCandelairInstalled; + (BOOL)isCandelairInstallationRequiredForRemoteMode:(HIDRemoteMode)remoteMode; + (SInt32)OSXVersion; - (HIDRemoteAluminumRemoteSupportLevel)aluminiumRemoteSystemSupportLevel; -#pragma mark -- PUBLIC: Interface / API -- -- (BOOL)startRemoteControl:(HIDRemoteMode)hidRemoteMode; +#pragma mark - PUBLIC: Interface / API +- (BOOL)startRemoteControl:(HIDRemoteMode)hidRemoteMode; - (void)stopRemoteControl; - (BOOL)isStarted; @@ -307,7 +317,7 @@ typedef enum - (void)setUnusedButtonCodes:(NSArray *)newArrayWithUnusedButtonCodesAsNSNumbers; - (NSArray *)unusedButtonCodes; -#pragma mark -- PUBLIC: Expert APIs -- +#pragma mark - PUBLIC: Expert APIs - (void)setEnableSecureEventInputWorkaround:(BOOL)newEnableSecureEventInputWorkaround; - (BOOL)enableSecureEventInputWorkaround; @@ -317,28 +327,28 @@ typedef enum - (BOOL)isApplicationTerminating; - (BOOL)isStopping; -#pragma mark -- PRIVATE: HID Event handling -- +#pragma mark - PRIVATE: HID Event handling - (void)_handleButtonCode:(HIDRemoteButtonCode)buttonCode isPressed:(BOOL)isPressed hidAttribsDict:(NSMutableDictionary *)hidAttribsDict; - (void)_sendButtonCode:(HIDRemoteButtonCode)buttonCode isPressed:(BOOL)isPressed hidAttribsDict:(NSMutableDictionary *)hidAttribsDict; - (void)_hidEventFor:(io_service_t)hidDevice from:(IOHIDQueueInterface **)interface withResult:(IOReturn)result; -#pragma mark -- PRIVATE: Service setup and destruction -- +#pragma mark - PRIVATE: Service setup and destruction - (BOOL)_prematchService:(io_object_t)service; - (HIDRemoteButtonCode)buttonCodeForUsage:(unsigned int)usage usagePage:(unsigned int)usagePage; - (BOOL)_setupService:(io_object_t)service; - (void)_destructService:(io_object_t)service; -#pragma mark -- PRIVATE: Distributed notifications handling -- +#pragma mark - PRIVATE: Distributed notifiations handling - (void)_postStatusWithAction:(NSString *)action; - (void)_handleNotifications:(NSNotification *)notification; - (void)_setSendStatusNotifications:(BOOL)doSend; - (BOOL)_sendStatusNotifications; -#pragma mark -- PRIVATE: Application becomes active / inactive handling for kHIDRemoteModeExclusiveAuto -- +#pragma mark - PRIVATE: Application becomes active / inactive handling for kHIDRemoteModeExclusiveAuto - (void)_appStatusChanged:(NSNotification *)notification; - (void)_delayedAutoRecovery:(NSTimer *)aTimer; -#pragma mark -- PRIVATE: Notification handling -- +#pragma mark - PRIVATE: Notification handling - (void)_serviceMatching:(io_iterator_t)iterator; - (void)_serviceNotificationFor:(io_service_t)service messageType:(natural_t)messageType messageArgument:(void *)messageArgument; - (void)_updateSessionInformation; @@ -346,12 +356,12 @@ typedef enum @end -#pragma mark -- Information attribute keys -- +#pragma mark - Information attribute keys extern NSString *kHIDRemoteManufacturer; extern NSString *kHIDRemoteProduct; extern NSString *kHIDRemoteTransport; -#pragma mark -- Internal/Expert attribute keys (AKA: don't touch these unless you really, really, REALLY know what you do) -- +#pragma mark - Internal/Expert attribute keys (AKA: don't touch these unless you really, really, REALLY know what you do) extern NSString *kHIDRemoteCFPluginInterface; extern NSString *kHIDRemoteHIDDeviceInterface; extern NSString *kHIDRemoteCookieButtonCodeLUT; @@ -365,14 +375,14 @@ extern NSString *kHIDRemoteSimulateHoldEventsOriginButtonCode; extern NSString *kHIDRemoteAluminumRemoteSupportLevel; extern NSString *kHIDRemoteAluminumRemoteSupportOnDemand; -#pragma mark -- Distributed notifications -- +#pragma mark - Distributed notifications extern NSString *kHIDRemoteDNHIDRemotePing; extern NSString *kHIDRemoteDNHIDRemoteRetry; extern NSString *kHIDRemoteDNHIDRemoteStatus; extern NSString *kHIDRemoteDNHIDRemoteRetryGlobalObject; -#pragma mark -- Distributed notifications userInfo keys and values -- +#pragma mark - Distributed notifications userInfo keys and values extern NSString *kHIDRemoteDNStatusHIDRemoteVersionKey; extern NSString *kHIDRemoteDNStatusPIDKey; extern NSString *kHIDRemoteDNStatusModeKey; @@ -385,8 +395,11 @@ extern NSString *kHIDRemoteDNStatusActionStop; extern NSString *kHIDRemoteDNStatusActionUpdate; extern NSString *kHIDRemoteDNStatusActionNoNeed; -#pragma mark -- Driver compatibility flags -- +#pragma mark - Driver compatibility flags +#ifndef HID_REMOTE_COMPATIBILITY_FLAGS_ENUM +#define HID_REMOTE_COMPATIBILITY_FLAGS_ENUM 1 typedef enum { kHIDRemoteCompatibilityFlagsStandardHIDRemoteDevice = 1L, } HIDRemoteCompatibilityFlags; +#endif /* HID_REMOTE_COMPATIBILITY_FLAGS_ENUM */ diff --git a/tools/EventClients/Clients/OSXRemote/HIDRemote/HIDRemote.m b/tools/EventClients/Clients/OSXRemote/HIDRemote/HIDRemote.m index 216c3adf6c..acbd16c7f2 100644 --- a/tools/EventClients/Clients/OSXRemote/HIDRemote/HIDRemote.m +++ b/tools/EventClients/Clients/OSXRemote/HIDRemote/HIDRemote.m @@ -1,32 +1,32 @@ // // HIDRemote.m -// HIDRemote V1.4 (18th February 2015) +// HIDRemote V1.7 (5th September 2018) // // Created by Felix Schwarz on 06.04.07. -// Copyright 2007-2015 IOSPIRIT GmbH. All rights reserved. +// Copyright 2007-2018 IOSPIRIT GmbH. All rights reserved. // // The latest version of this class is available at // http://www.iospirit.com/developers/hidremote/ // // ** LICENSE ************************************************************************* // -// Copyright (c) 2007-2014 IOSPIRIT GmbH (http://www.iospirit.com/) +// Copyright (c) 2007-2017 IOSPIRIT GmbH (http://www.iospirit.com/) // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without modification, // are permitted provided that the following conditions are met: -// +// // * Redistributions of source code must retain the above copyright notice, this list // of conditions and the following disclaimer. -// +// // * Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or other // materials provided with the distribution. -// +// // * Neither the name of IOSPIRIT GmbH nor the names of its contributors may be used to // endorse or promote products derived from this software without specific prior // written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT @@ -51,8 +51,39 @@ #import "HIDRemote.h" +// ARC support +#if !__has_feature(objc_arc) + #define HIDRemoteRetain(object) [object retain] + #define HIDRemoteRetained(object) [object retain] + #define HIDRemoteRelease(object) [object release] + #define HIDRemoteReleaseNil(object) [object release]; object=nil + #define HIDRemoteAutoreleased(object) [object autorelease] + #define HIDRemoteSuperDealloc(object) [super dealloc] + + #define HIDRemoteAutoreleasePoolOpen() NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + #define HIDRemoteAutoreleasePoolClose() [pool release]; + + #define __HIDRemoteBridge + #define HIDRemoteBridgingRelease + #define HIDRemoteBridgingRetain +#else /* !__has_feature(objc_arc) */ + #define HIDRemoteRetain(object) + #define HIDRemoteRetained(object) object + #define HIDRemoteRelease(object) + #define HIDRemoteReleaseNil(object) object=nil + #define HIDRemoteAutoreleased(object) object + #define HIDRemoteSuperDealloc(object) + + #define HIDRemoteAutoreleasePoolOpen() @autoreleasepool { + #define HIDRemoteAutoreleasePoolClose() } + + #define __HIDRemoteBridge __bridge + #define HIDRemoteBridgingRelease CFBridgingRelease + #define HIDRemoteBridgingRetain CFBridgingRetain +#endif + // Callback Prototypes -static void HIDEventCallback( void * target, +static void HIDEventCallback( void * target, IOReturn result, void * refcon, void * sender); @@ -83,7 +114,7 @@ static HIDRemote *sHIDRemote = nil; { sHIDRemote = [[HIDRemote alloc] init]; } - + return (sHIDRemote); } @@ -91,10 +122,10 @@ static HIDRemote *sHIDRemote = nil; { if ((self = [super init]) != nil) { - #ifdef HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING - _runOnThread = [[NSThread currentThread] retain]; + #if HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING + _runOnThread = HIDRemoteRetained([NSThread currentThread]); #endif - + // Detect application becoming active/inactive [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appStatusChanged:) name:NSApplicationDidBecomeActiveNotification object:[NSApplication sharedApplication]]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appStatusChanged:) name:NSApplicationWillResignActiveNotification object:[NSApplication sharedApplication]]; @@ -102,18 +133,18 @@ static HIDRemote *sHIDRemote = nil; // Handle distributed notifications _pidString = [[NSString alloc] initWithFormat:@"%d", getpid()]; - + [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleNotifications:) name:kHIDRemoteDNHIDRemotePing object:nil]; [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleNotifications:) name:kHIDRemoteDNHIDRemoteRetry object:kHIDRemoteDNHIDRemoteRetryGlobalObject]; [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleNotifications:) name:kHIDRemoteDNHIDRemoteRetry object:_pidString]; // Enabled by default: simulate hold events for plus/minus _simulateHoldEvents = YES; - + // Enabled by default: work around for a locking issue introduced with Security Update 2008-004 / 10.4.9 and beyond (credit for finding this workaround goes to Martin Kahr) _secureEventInputWorkAround = YES; _secureInputNotification = 0; - + // Initialize instance variables _lastSeenRemoteID = -1; _lastSeenModel = kHIDRemoteModelUndetermined; @@ -121,7 +152,7 @@ static HIDRemote *sHIDRemote = nil; _exclusiveLockLending = NO; _sendExclusiveResourceReuseNotification = YES; _applicationIsTerminating = NO; - + // Send status notifications _sendStatusNotifications = YES; } @@ -139,7 +170,7 @@ static HIDRemote *sHIDRemote = nil; [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:kHIDRemoteDNHIDRemoteRetry object:kHIDRemoteDNHIDRemoteRetryGlobalObject]; [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:kHIDRemoteDNHIDRemoteRetry object:_pidString]; [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:nil object:nil]; /* As demanded by the documentation for -[NSDistributedNotificationCenter removeObserver:name:object:] */ - + [self stopRemoteControl]; [self setExclusiveLockLendingEnabled:NO]; @@ -148,19 +179,16 @@ static HIDRemote *sHIDRemote = nil; if (_unusedButtonCodes != nil) { - [_unusedButtonCodes release]; - _unusedButtonCodes = nil; + HIDRemoteReleaseNil(_unusedButtonCodes); } - #ifdef HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING - [_runOnThread release]; - _runOnThread = nil; + #if HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING + HIDRemoteReleaseNil(_runOnThread); #endif - [_pidString release]; - _pidString = nil; + HIDRemoteReleaseNil(_pidString); - [super dealloc]; + HIDRemoteSuperDealloc(); } #pragma mark - PUBLIC: System Information @@ -205,14 +233,14 @@ static HIDRemote *sHIDRemote = nil; return (YES); } break; - + default: return (NO); break; } break; } - + return (NO); } @@ -228,7 +256,7 @@ static HIDRemote *sHIDRemote = nil; NSOperatingSystemVersion osVersion; osVersion = [[NSProcessInfo processInfo] operatingSystemVersion]; - + sHRGestaltOSXVersion = (SInt32)(0x01000 | ((osVersion.majorVersion-10)<<8) | (osVersion.minorVersion<<4) | osVersion.patchVersion); #else #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_9 @@ -238,7 +266,7 @@ static HIDRemote *sHIDRemote = nil; if ([[NSProcessInfo processInfo] respondsToSelector:@selector(operatingSystemVersion)]) { osVersion = [[NSProcessInfo processInfo] operatingSystemVersion]; - + sHRGestaltOSXVersion = (SInt32)(0x01000 | ((osVersion.majorVersion-10)<<8) | (osVersion.minorVersion<<4) | osVersion.patchVersion); } else @@ -257,7 +285,7 @@ static HIDRemote *sHIDRemote = nil; #endif /* MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_9 */ #endif /* MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_9 */ } - + return (sHRGestaltOSXVersion); } @@ -266,13 +294,13 @@ static HIDRemote *sHIDRemote = nil; HIDRemoteAluminumRemoteSupportLevel supportLevel = kHIDRemoteAluminumRemoteSupportLevelNone; NSEnumerator *attribDictsEnum; NSDictionary *hidAttribsDict; - + attribDictsEnum = [_serviceAttribMap objectEnumerator]; - + while ((hidAttribsDict = [attribDictsEnum nextObject]) != nil) { NSNumber *deviceSupportLevel; - + if ((deviceSupportLevel = [hidAttribsDict objectForKey:kHIDRemoteAluminumRemoteSupportLevel]) != nil) { if ([deviceSupportLevel intValue] > (int)supportLevel) @@ -281,7 +309,7 @@ static HIDRemote *sHIDRemote = nil; } } } - + return (supportLevel); } @@ -293,16 +321,16 @@ static HIDRemote *sHIDRemote = nil; kern_return_t kernReturn; CFMutableDictionaryRef matchDict=NULL; io_service_t rootService; - + do { // Get IOKit master port kernReturn = IOMasterPort(bootstrap_port, &_masterPort); if ((kernReturn!=kIOReturnSuccess) || (_masterPort==0)) { break; } - + // Setup notification port _notifyPort = IONotificationPortCreate(_masterPort); - + if ((_notifyRLSource = IONotificationPortGetRunLoopSource(_notifyPort)) != NULL) { CFRunLoopAddSource( CFRunLoopGetCurrent(), @@ -313,7 +341,7 @@ static HIDRemote *sHIDRemote = nil; { break; } - + // Setup SecureInput notification if ((hidRemoteMode == kHIDRemoteModeExclusive) || (hidRemoteMode == kHIDRemoteModeExclusiveAuto)) { @@ -323,10 +351,10 @@ static HIDRemote *sHIDRemote = nil; rootService, kIOBusyInterest, SecureInputNotificationCallback, - (void *)self, + (__HIDRemoteBridge void *)self, &_secureInputNotification); if (kernReturn != kIOReturnSuccess) { break; } - + [self _updateSessionInformation]; } else @@ -344,39 +372,39 @@ static HIDRemote *sHIDRemote = nil; kIOFirstMatchNotification, matchDict, // one reference count consumed by this call ServiceMatchingCallback, - (void *) self, + (__HIDRemoteBridge void *) self, &_matchingServicesIterator); if (kernReturn != kIOReturnSuccess) { break; } - // Setup serviceAttribMap + // Setup serviceAttribMap _serviceAttribMap = [[NSMutableDictionary alloc] init]; if (_serviceAttribMap==nil) { break; } - + // Phew .. everything went well! _mode = hidRemoteMode; CFRelease(matchDict); - + [self _serviceMatching:_matchingServicesIterator]; - + [self _postStatusWithAction:kHIDRemoteDNStatusActionStart]; - + // Register for system wake notifications [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(_computerDidWake:) name:NSWorkspaceDidWakeNotification object:nil]; - + return (YES); }while(0); - + // An error occured. Do necessary clean up. if (matchDict!=NULL) { CFRelease(matchDict); matchDict = NULL; } - + [self stopRemoteControl]; } - + return (NO); } @@ -390,31 +418,28 @@ static HIDRemote *sHIDRemote = nil; if (_autoRecoveryTimer!=nil) { [_autoRecoveryTimer invalidate]; - [_autoRecoveryTimer release]; - _autoRecoveryTimer = nil; + HIDRemoteReleaseNil(_autoRecoveryTimer); } if (_serviceAttribMap!=nil) { NSDictionary *cloneDict = [[NSDictionary alloc] initWithDictionary:_serviceAttribMap]; - + if (cloneDict!=nil) { NSEnumerator *mapKeyEnum = [cloneDict keyEnumerator]; NSNumber *serviceValue; - + while ((serviceValue = [mapKeyEnum nextObject]) != nil) { [self _destructService:(io_object_t)[serviceValue unsignedIntValue]]; serviceCount++; }; - - [cloneDict release]; - cloneDict = nil; + + HIDRemoteReleaseNil(cloneDict); } - - [_serviceAttribMap release]; - _serviceAttribMap = nil; + + HIDRemoteReleaseNil(_serviceAttribMap); } if (_matchingServicesIterator!=0) @@ -422,7 +447,7 @@ static HIDRemote *sHIDRemote = nil; IOObjectRelease((io_object_t) _matchingServicesIterator); _matchingServicesIterator = 0; } - + if (_secureInputNotification!=0) { IOObjectRelease((io_object_t) _secureInputNotification); @@ -449,8 +474,7 @@ static HIDRemote *sHIDRemote = nil; if (_returnToPID!=nil) { - [_returnToPID release]; - _returnToPID = nil; + HIDRemoteReleaseNil(_returnToPID); } if (_mode!=kHIDRemoteModeNone) @@ -464,7 +488,7 @@ static HIDRemote *sHIDRemote = nil; if (((_mode==kHIDRemoteModeExclusive) || (_mode==kHIDRemoteModeExclusiveAuto)) && (_sendExclusiveResourceReuseNotification==YES) && (_exclusiveLockLending==NO) && (serviceCount>0)) { _mode = kHIDRemoteModeNone; - + if (!_isRestarting) { [[NSDistributedNotificationCenter defaultCenter] postNotificationName:kHIDRemoteDNHIDRemoteRetry @@ -481,7 +505,7 @@ static HIDRemote *sHIDRemote = nil; // Unregister from system wake notifications [[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self name:NSWorkspaceDidWakeNotification object:nil]; } - + _mode = kHIDRemoteModeNone; _isStopping = NO; } @@ -498,7 +522,7 @@ static HIDRemote *sHIDRemote = nil; - (unsigned)activeRemoteControlCount { - return ([_serviceAttribMap count]); + return ((unsigned)[_serviceAttribMap count]); } - (SInt32)lastSeenRemoteControlID @@ -533,9 +557,9 @@ static HIDRemote *sHIDRemote = nil; - (void)setUnusedButtonCodes:(NSArray *)newArrayWithUnusedButtonCodesAsNSNumbers { - [newArrayWithUnusedButtonCodesAsNSNumbers retain]; - [_unusedButtonCodes release]; - + HIDRemoteRetain(newArrayWithUnusedButtonCodesAsNSNumbers); + HIDRemoteRelease(_unusedButtonCodes); + _unusedButtonCodes = newArrayWithUnusedButtonCodesAsNSNumbers; [self _postStatusWithAction:kHIDRemoteDNStatusActionUpdate]; @@ -567,7 +591,7 @@ static HIDRemote *sHIDRemote = nil; if (newExclusiveLockLendingEnabled != _exclusiveLockLending) { _exclusiveLockLending = newExclusiveLockLendingEnabled; - + if (_exclusiveLockLending) { [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleNotifications:) name:kHIDRemoteDNHIDRemoteStatus object:nil]; @@ -575,9 +599,8 @@ static HIDRemote *sHIDRemote = nil; else { [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:kHIDRemoteDNHIDRemoteStatus object:nil]; - - [_waitForReturnByPID release]; - _waitForReturnByPID = nil; + + HIDRemoteReleaseNil(_waitForReturnByPID); } } } @@ -610,7 +633,7 @@ static HIDRemote *sHIDRemote = nil; #pragma mark - PRIVATE: Application becomes active / inactive handling for kHIDRemoteModeExclusiveAuto - (void)_appStatusChanged:(NSNotification *)notification { - #ifdef HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING + #if HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING if ([self respondsToSelector:@selector(performSelector:onThread:withObject:waitUntilDone:)]) // OS X 10.5+ only { if ([NSThread currentThread] != _runOnThread) @@ -622,7 +645,7 @@ static HIDRemote *sHIDRemote = nil; return; } } - + if ([[notification name] isEqual:NSApplicationWillResignActiveNotification]) { if (_mode != kHIDRemoteModeExclusiveAuto) @@ -630,7 +653,7 @@ static HIDRemote *sHIDRemote = nil; return; } } - + [self performSelector:@selector(_appStatusChanged:) onThread:_runOnThread withObject:notification waitUntilDone:[[notification name] isEqual:NSApplicationWillTerminateNotification]]; return; } @@ -642,8 +665,7 @@ static HIDRemote *sHIDRemote = nil; if (_autoRecoveryTimer!=nil) { [_autoRecoveryTimer invalidate]; - [_autoRecoveryTimer release]; - _autoRecoveryTimer = nil; + HIDRemoteReleaseNil(_autoRecoveryTimer); } if ([[notification name] isEqual:NSApplicationDidBecomeActiveNotification]) @@ -669,11 +691,11 @@ static HIDRemote *sHIDRemote = nil; _autoRecover = YES; } } - + if ([[notification name] isEqual:NSApplicationWillTerminateNotification]) { _applicationIsTerminating = YES; - + if ([self isStarted]) { [self stopRemoteControl]; @@ -685,8 +707,7 @@ static HIDRemote *sHIDRemote = nil; - (void)_delayedAutoRecovery:(NSTimer *)aTimer { [_autoRecoveryTimer invalidate]; - [_autoRecoveryTimer release]; - _autoRecoveryTimer = nil; + HIDRemoteReleaseNil(_autoRecoveryTimer); if (_autoRecover) { @@ -696,7 +717,7 @@ static HIDRemote *sHIDRemote = nil; } -#pragma mark - PRIVATE: Distributed notifications handling +#pragma mark - PRIVATE: Distributed notifiations handling - (void)_postStatusWithAction:(NSString *)action { if (_sendStatusNotifications) @@ -722,7 +743,7 @@ static HIDRemote *sHIDRemote = nil; { NSString *notificationName; - #ifdef HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING + #if HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING if ([self respondsToSelector:@selector(performSelector:onThread:withObject:waitUntilDone:)]) // OS X 10.5+ only { if ([NSThread currentThread] != _runOnThread) @@ -745,7 +766,7 @@ static HIDRemote *sHIDRemote = nil; if ([self isStarted]) { BOOL retry = YES; - + // Ignore our own global retry broadcasts if ([[notification object] isEqual:kHIDRemoteDNHIDRemoteRetryGlobalObject]) { @@ -759,7 +780,7 @@ static HIDRemote *sHIDRemote = nil; } } } - + if (retry) { if (([self delegate] != nil) && @@ -768,25 +789,24 @@ static HIDRemote *sHIDRemote = nil; retry = [[self delegate] hidRemote:self shouldRetryExclusiveLockWithInfo:[notification userInfo]]; } } - + if (retry) { HIDRemoteMode restartInMode = _mode; - + if (restartInMode != kHIDRemoteModeNone) { _isRestarting = YES; [self stopRemoteControl]; - - [_returnToPID release]; - _returnToPID = nil; - + + HIDRemoteReleaseNil(_returnToPID); + [self startRemoteControl:restartInMode]; _isRestarting = NO; - + if (restartInMode != kHIDRemoteModeShared) { - _returnToPID = [[[notification userInfo] objectForKey:kHIDRemoteDNStatusPIDKey] retain]; + _returnToPID = HIDRemoteRetained([[notification userInfo] objectForKey:kHIDRemoteDNStatusPIDKey]); } } } @@ -794,21 +814,21 @@ static HIDRemote *sHIDRemote = nil; { NSNumber *cacheReturnPID = _returnToPID; - _returnToPID = [[[notification userInfo] objectForKey:kHIDRemoteDNStatusPIDKey] retain]; + _returnToPID = HIDRemoteRetained([[notification userInfo] objectForKey:kHIDRemoteDNStatusPIDKey]); [self _postStatusWithAction:kHIDRemoteDNStatusActionNoNeed]; - [_returnToPID release]; - + HIDRemoteRelease(_returnToPID); + _returnToPID = cacheReturnPID; } } } - + if (_exclusiveLockLending) { if ([notificationName isEqual:kHIDRemoteDNHIDRemoteStatus]) { NSString *action; - + if ((action = [[notification userInfo] objectForKey:kHIDRemoteDNStatusActionKey]) != nil) { if ((_mode == kHIDRemoteModeNone) && (_waitForReturnByPID!=nil)) @@ -818,13 +838,13 @@ static HIDRemote *sHIDRemote = nil; if ((pidNumber = [[notification userInfo] objectForKey:kHIDRemoteDNStatusPIDKey]) != nil) { returnToPIDNumber = [[notification userInfo] objectForKey:kHIDRemoteDNStatusReturnToPIDKey]; - + if ([action isEqual:kHIDRemoteDNStatusActionStart]) { if ([pidNumber isEqual:_waitForReturnByPID]) { NSNumber *startMode; - + if ((startMode = [[notification userInfo] objectForKey:kHIDRemoteDNStatusModeKey]) != nil) { if ([startMode intValue] == kHIDRemoteModeShared) @@ -842,9 +862,8 @@ static HIDRemote *sHIDRemote = nil; { if ([pidNumber isEqual:_waitForReturnByPID] && ([returnToPIDNumber intValue] == getpid())) { - [_waitForReturnByPID release]; - _waitForReturnByPID = nil; - + HIDRemoteReleaseNil(_waitForReturnByPID); + if (([self delegate] != nil) && ([[self delegate] respondsToSelector:@selector(hidRemote:exclusiveLockReleasedByApplicationWithInfo:)])) { @@ -866,7 +885,7 @@ static HIDRemote *sHIDRemote = nil; { NSNumber *originPID = [[notification userInfo] objectForKey:kHIDRemoteDNStatusPIDKey]; BOOL lendLock = YES; - + if ([originPID intValue] != getpid()) { if (([self delegate] != nil) && @@ -874,16 +893,16 @@ static HIDRemote *sHIDRemote = nil; { lendLock = [[self delegate] hidRemote:self lendExclusiveLockToApplicationWithInfo:[notification userInfo]]; } - + if (lendLock) { - [_waitForReturnByPID release]; - _waitForReturnByPID = [originPID retain]; - + HIDRemoteRelease(_waitForReturnByPID); + _waitForReturnByPID = HIDRemoteRetained(originPID); + if (_waitForReturnByPID != nil) { [self stopRemoteControl]; - + [[NSDistributedNotificationCenter defaultCenter] postNotificationName:kHIDRemoteDNHIDRemoteRetry object:[NSString stringWithFormat:@"%d", [_waitForReturnByPID intValue]] userInfo:[NSDictionary dictionaryWithObjectsAndKeys: @@ -918,11 +937,11 @@ static HIDRemote *sHIDRemote = nil; BOOL serviceMatches = NO; NSString *ioClass; NSNumber *candelairHIDRemoteCompatibilityMask; - + if (service != 0) { // IOClass matching - if ((ioClass = (NSString *)IORegistryEntryCreateCFProperty((io_registry_entry_t)service, + if ((ioClass = (__HIDRemoteBridge NSString *)IORegistryEntryCreateCFProperty((io_registry_entry_t)service, CFSTR(kIOClassKey), kCFAllocatorDefault, 0)) != nil) @@ -933,14 +952,14 @@ static HIDRemote *sHIDRemote = nil; CFTypeRef candelairHIDRemoteCompatibilityDevice; serviceMatches = YES; - + if ((candelairHIDRemoteCompatibilityDevice = IORegistryEntryCreateCFProperty((io_registry_entry_t)service, CFSTR("CandelairHIDRemoteCompatibilityDevice"), kCFAllocatorDefault, 0)) != NULL) { if (CFEqual(kCFBooleanTrue, candelairHIDRemoteCompatibilityDevice)) { serviceMatches = NO; } - + CFRelease (candelairHIDRemoteCompatibilityDevice); } } @@ -950,12 +969,12 @@ static HIDRemote *sHIDRemote = nil; { serviceMatches = YES; } - + CFRelease((CFTypeRef)ioClass); } // Match on services that claim compatibility with the HID Remote class (Candelair or third-party) by having a property of CandelairHIDRemoteCompatibilityMask = 1 <Type: Number> - if ((candelairHIDRemoteCompatibilityMask = (NSNumber *)IORegistryEntryCreateCFProperty((io_registry_entry_t)service, CFSTR("CandelairHIDRemoteCompatibilityMask"), kCFAllocatorDefault, 0)) != nil) + if ((candelairHIDRemoteCompatibilityMask = (__HIDRemoteBridge NSNumber *)IORegistryEntryCreateCFProperty((io_registry_entry_t)service, CFSTR("CandelairHIDRemoteCompatibilityMask"), kCFAllocatorDefault, 0)) != nil) { if ([candelairHIDRemoteCompatibilityMask isKindOfClass:[NSNumber class]]) { @@ -968,7 +987,7 @@ static HIDRemote *sHIDRemote = nil; serviceMatches = NO; } } - + CFRelease((CFTypeRef)candelairHIDRemoteCompatibilityMask); } } @@ -978,7 +997,7 @@ static HIDRemote *sHIDRemote = nil; { serviceMatches = [((NSObject <HIDRemoteDelegate> *)[self delegate]) hidRemote:self inspectNewHardwareWithService:service prematchResult:serviceMatches]; } - + return (serviceMatches); } @@ -995,7 +1014,7 @@ static HIDRemote *sHIDRemote = nil; // Aluminum Remote: Center buttonCode = (kHIDRemoteButtonCodeCenter|kHIDRemoteButtonCodeAluminumMask); break; - + case kHIDUsage_Csmr_ModeStep: // Aluminium Remote: Center Hold buttonCode = (kHIDRemoteButtonCodeCenterHold|kHIDRemoteButtonCodeAluminumMask); @@ -1005,11 +1024,11 @@ static HIDRemote *sHIDRemote = nil; // Aluminum Remote: Play/Pause buttonCode = (kHIDRemoteButtonCodePlay|kHIDRemoteButtonCodeAluminumMask); break; - + case kHIDUsage_Csmr_Rewind: buttonCode = kHIDRemoteButtonCodeLeftHold; break; - + case kHIDUsage_Csmr_FastForward: buttonCode = kHIDRemoteButtonCodeRightHold; break; @@ -1017,7 +1036,7 @@ static HIDRemote *sHIDRemote = nil; case kHIDUsage_Csmr_Menu: buttonCode = kHIDRemoteButtonCodeMenuHold; break; - + case kHIDUsage_Csmr_VolumeIncrement: buttonCode = kHIDRemoteButtonCodeUp; break; @@ -1027,7 +1046,7 @@ static HIDRemote *sHIDRemote = nil; break; } break; - + case kHIDPage_GenericDesktop: switch (usage) { @@ -1048,15 +1067,27 @@ static HIDRemote *sHIDRemote = nil; break; case kHIDUsage_GD_SystemMenuUp: - buttonCode = kHIDRemoteButtonCodeUp; + // macOS 10.13.6 posts kHIDUsage_GD_SystemMenuUp alongside kHIDUsage_Csmr_VolumeIncrement, + // which ends up being interpreted as a double press. To avoid this, this usage is ignored + // when running under 10.13.6 and later. + if ([HIDRemote OSXVersion] < 0x10d6) + { + buttonCode = kHIDRemoteButtonCodeUp; + } break; case kHIDUsage_GD_SystemMenuDown: - buttonCode = kHIDRemoteButtonCodeDown; + // macOS 10.13.6 posts kHIDUsage_GD_SystemMenuDown alongside kHIDUsage_Csmr_VolumeDecrement, + // which ends up being interpreted as a double press. To avoid this, this usage is ignored + // when running under 10.13.6 and later. + if ([HIDRemote OSXVersion] < 0x10d6) + { + buttonCode = kHIDRemoteButtonCodeDown; + } break; } break; - + case 0x06: /* Reserved */ switch (usage) { @@ -1065,7 +1096,7 @@ static HIDRemote *sHIDRemote = nil; break; } break; - + case 0xFF01: /* Vendor specific */ switch (usage) { @@ -1081,7 +1112,7 @@ static HIDRemote *sHIDRemote = nil; } break; } - + return (buttonCode); } @@ -1115,52 +1146,52 @@ static HIDRemote *sHIDRemote = nil; kIOCFPlugInInterfaceID, &cfPluginInterface, &score); - + if (kernResult != kIOReturnSuccess) { error = [NSError errorWithDomain:NSMachErrorDomain code:kernResult userInfo:nil]; errorCode = 1; - break; + break; } - + // .. use it to get the HID interface .. - hResult = (*cfPluginInterface)->QueryInterface( cfPluginInterface, + hResult = (*cfPluginInterface)->QueryInterface( cfPluginInterface, CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID122), (LPVOID)&hidDeviceInterface); - + if ((hResult!=S_OK) || (hidDeviceInterface==NULL)) { error = [NSError errorWithDomain:NSMachErrorDomain code:hResult userInfo:nil]; errorCode = 2; - break; + break; } - + // .. then open it .. switch (_mode) { case kHIDRemoteModeShared: hResult = (*hidDeviceInterface)->open(hidDeviceInterface, kIOHIDOptionsTypeNone); break; - + case kHIDRemoteModeExclusive: case kHIDRemoteModeExclusiveAuto: hResult = (*hidDeviceInterface)->open(hidDeviceInterface, kIOHIDOptionsTypeSeizeDevice); break; - + default: goto cleanUp; // Ugh! But there are no "double breaks" available in C AFAIK .. break; } - + if (hResult!=S_OK) { error = [NSError errorWithDomain:NSMachErrorDomain code:hResult userInfo:nil]; errorCode = 3; break; } - + opened = YES; // .. query the HID elements .. @@ -1171,7 +1202,7 @@ static HIDRemote *sHIDRemote = nil; { error = [NSError errorWithDomain:NSMachErrorDomain code:returnCode userInfo:nil]; errorCode = 4; - + break; } @@ -1203,37 +1234,34 @@ static HIDRemote *sHIDRemote = nil; nil]; { - UInt32 i, hidElementCnt = CFArrayGetCount(hidElements); + UInt32 i, hidElementCnt = (UInt32)CFArrayGetCount(hidElements); NSMutableDictionary *cookieButtonCodeLUT = [[NSMutableDictionary alloc] init]; NSMutableDictionary *cookieCount = [[NSMutableDictionary alloc] init]; - + if ((cookieButtonCodeLUT==nil) || (cookieCount==nil)) { - [cookieButtonCodeLUT release]; - cookieButtonCodeLUT = nil; - - [cookieCount release]; - cookieCount = nil; + HIDRemoteReleaseNil(cookieButtonCodeLUT); + HIDRemoteReleaseNil(cookieCount); error = [NSError errorWithDomain:NSMachErrorDomain code:kIOReturnError userInfo:nil]; errorCode = 7; break; } - + // Analyze the HID elements and find matching elements for (i=0;i<hidElementCnt;i++) { CFDictionaryRef hidDict; NSNumber *usage, *usagePage, *cookie; HIDRemoteButtonCode buttonCode = kHIDRemoteButtonCodeNone; - + hidDict = CFArrayGetValueAtIndex(hidElements, i); - + usage = (NSNumber *) CFDictionaryGetValue(hidDict, CFSTR(kIOHIDElementUsageKey)); usagePage = (NSNumber *) CFDictionaryGetValue(hidDict, CFSTR(kIOHIDElementUsagePageKey)); cookie = (NSNumber *) CFDictionaryGetValue(hidDict, CFSTR(kIOHIDElementCookieKey)); - + if ((usage!=nil) && (usagePage!=nil) && (cookie!=nil)) { // Find the button codes for the ID combos @@ -1245,23 +1273,23 @@ static HIDRemote *sHIDRemote = nil; #include "HIDRemoteAdditions.h" #undef _HIDREMOTE_EXTENSIONS_SECTION #endif /* _HIDREMOTE_EXTENSIONS */ - + // Did record match? if (buttonCode != kHIDRemoteButtonCodeNone) { NSString *pairString = [[NSString alloc] initWithFormat:@"%u_%u", [usagePage unsignedIntValue], [usage unsignedIntValue]]; NSNumber *buttonCodeNumber = [[NSNumber alloc] initWithUnsignedInt:(unsigned int)buttonCode]; - + #ifdef _HIDREMOTE_EXTENSIONS // Debug logging code #define _HIDREMOTE_EXTENSIONS_SECTION 4 #include "HIDRemoteAdditions.h" #undef _HIDREMOTE_EXTENSIONS_SECTION #endif /* _HIDREMOTE_EXTENSIONS */ - + [cookieCount setObject:buttonCodeNumber forKey:pairString]; [cookieButtonCodeLUT setObject:buttonCodeNumber forKey:cookie]; - + (*hidQueueInterface)->addElement(hidQueueInterface, (IOHIDElementCookie) [cookie unsignedIntValue], 0); @@ -1273,20 +1301,17 @@ static HIDRemote *sHIDRemote = nil; #undef _HIDREMOTE_EXTENSIONS_SECTION #endif /* _HIDREMOTE_EXTENSIONS */ - [buttonCodeNumber release]; - [pairString release]; + HIDRemoteRelease(buttonCodeNumber); + HIDRemoteRelease(pairString); } } } - + // Compare number of *unique* matches (thus the cookieCount dictionary) with required minimum if ([cookieCount count] < 10) { - [cookieButtonCodeLUT release]; - cookieButtonCodeLUT = nil; - - [cookieCount release]; - cookieCount = nil; + HIDRemoteReleaseNil(cookieButtonCodeLUT); + HIDRemoteReleaseNil(cookieCount); error = [NSError errorWithDomain:NSMachErrorDomain code:kIOReturnError userInfo:nil]; errorCode = 8; @@ -1296,35 +1321,32 @@ static HIDRemote *sHIDRemote = nil; [hidAttribsDict setObject:cookieButtonCodeLUT forKey:kHIDRemoteCookieButtonCodeLUT]; - [cookieButtonCodeLUT release]; - cookieButtonCodeLUT = nil; - - [cookieCount release]; - cookieCount = nil; + HIDRemoteReleaseNil(cookieButtonCodeLUT); + HIDRemoteReleaseNil(cookieCount); } - + // Finish setup of IOHIDQueueInterface with CFRunLoop returnCode = (*hidQueueInterface)->createAsyncEventSource(hidQueueInterface, &queueEventSource); if ((returnCode != kIOReturnSuccess) || (queueEventSource == NULL)) { error = [NSError errorWithDomain:NSMachErrorDomain code:returnCode userInfo:nil]; errorCode = 9; - break; + break; } - - returnCode = (*hidQueueInterface)->setEventCallout(hidQueueInterface, HIDEventCallback, (void *)((intptr_t)service), (void *)self); + + returnCode = (*hidQueueInterface)->setEventCallout(hidQueueInterface, HIDEventCallback, (void *)((intptr_t)service), (__HIDRemoteBridge void *)self); if (returnCode != kIOReturnSuccess) { error = [NSError errorWithDomain:NSMachErrorDomain code:returnCode userInfo:nil]; errorCode = 10; break; } - + CFRunLoopAddSource( CFRunLoopGetCurrent(), queueEventSource, kCFRunLoopCommonModes); [hidAttribsDict setObject:[NSValue valueWithPointer:(const void *)queueEventSource] forKey:kHIDRemoteCFRunLoopSource]; - + returnCode = (*hidQueueInterface)->start(hidQueueInterface); if (returnCode != kIOReturnSuccess) { @@ -1332,7 +1354,7 @@ static HIDRemote *sHIDRemote = nil; errorCode = 11; break; } - + queueStarted = YES; // Setup device notifications @@ -1340,7 +1362,7 @@ static HIDRemote *sHIDRemote = nil; service, kIOGeneralInterest, ServiceNotificationCallback, - self, + (__HIDRemoteBridge void *)(self), &serviceNotification); if ((returnCode != kIOReturnSuccess) || (serviceNotification==0)) { @@ -1350,7 +1372,7 @@ static HIDRemote *sHIDRemote = nil; } [hidAttribsDict setObject:[NSNumber numberWithUnsignedInt:(unsigned int)serviceNotification] forKey:kHIDRemoteServiceNotification]; - + // Retain service if (IOObjectRetain(service) != kIOReturnSuccess) { @@ -1358,13 +1380,13 @@ static HIDRemote *sHIDRemote = nil; errorCode = 13; break; } - + [hidAttribsDict setObject:[NSNumber numberWithUnsignedInt:(unsigned int)service] forKey:kHIDRemoteService]; - + // Get some (somewhat optional) infos on the device { CFStringRef product, manufacturer, transport; - + if ((product = IORegistryEntryCreateCFProperty( (io_registry_entry_t)service, (CFStringRef) @"Product", kCFAllocatorDefault, @@ -1372,9 +1394,9 @@ static HIDRemote *sHIDRemote = nil; { if (CFGetTypeID(product) == CFStringGetTypeID()) { - [hidAttribsDict setObject:(NSString *)product forKey:kHIDRemoteProduct]; + [hidAttribsDict setObject:(__HIDRemoteBridge NSString *)product forKey:kHIDRemoteProduct]; } - + CFRelease(product); } @@ -1385,9 +1407,9 @@ static HIDRemote *sHIDRemote = nil; { if (CFGetTypeID(manufacturer) == CFStringGetTypeID()) { - [hidAttribsDict setObject:(NSString *)manufacturer forKey:kHIDRemoteManufacturer]; + [hidAttribsDict setObject:(__HIDRemoteBridge NSString *)manufacturer forKey:kHIDRemoteManufacturer]; } - + CFRelease(manufacturer); } @@ -1398,18 +1420,18 @@ static HIDRemote *sHIDRemote = nil; { if (CFGetTypeID(transport) == CFStringGetTypeID()) { - [hidAttribsDict setObject:(NSString *)transport forKey:kHIDRemoteTransport]; + [hidAttribsDict setObject:(__HIDRemoteBridge NSString *)transport forKey:kHIDRemoteTransport]; } - + CFRelease(transport); } } - + // Determine Aluminum Remote support { CFNumberRef aluSupport; HIDRemoteAluminumRemoteSupportLevel supportLevel = kHIDRemoteAluminumRemoteSupportLevelNone; - + if ((_mode == kHIDRemoteModeExclusive) || (_mode == kHIDRemoteModeExclusiveAuto)) { // Determine if this driver offers on-demand support for the Aluminum Remote (only relevant under OS versions < 10.6.2) @@ -1421,23 +1443,23 @@ static HIDRemote *sHIDRemote = nil; // There is => request the driver to enable it for us if (IORegistryEntrySetCFProperty((io_registry_entry_t)service, CFSTR("EnableAluminumRemoteSupportForMe"), - [NSDictionary dictionaryWithObjectsAndKeys: + (__HIDRemoteBridge CFTypeRef)([NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithLongLong:(long long)getpid()], @"pid", [NSNumber numberWithLongLong:(long long)getuid()], @"uid", - nil]) == kIOReturnSuccess) + nil])) == kIOReturnSuccess) { if (CFGetTypeID(aluSupport) == CFNumberGetTypeID()) { - supportLevel = (HIDRemoteAluminumRemoteSupportLevel) [(NSNumber *)aluSupport intValue]; + supportLevel = (HIDRemoteAluminumRemoteSupportLevel) [(__HIDRemoteBridge NSNumber *)aluSupport intValue]; } [hidAttribsDict setObject:[NSNumber numberWithBool:YES] forKey:kHIDRemoteAluminumRemoteSupportOnDemand]; } - + CFRelease(aluSupport); } } - + if (supportLevel == kHIDRemoteAluminumRemoteSupportLevelNone) { if ((aluSupport = IORegistryEntryCreateCFProperty((io_registry_entry_t)service, @@ -1447,26 +1469,26 @@ static HIDRemote *sHIDRemote = nil; { if (CFGetTypeID(aluSupport) == CFNumberGetTypeID()) { - supportLevel = (HIDRemoteAluminumRemoteSupportLevel) [(NSNumber *)aluSupport intValue]; + supportLevel = (HIDRemoteAluminumRemoteSupportLevel) [(__HIDRemoteBridge NSNumber *)aluSupport intValue]; } - + CFRelease(aluSupport); } else { CFStringRef ioKitClassName; - + if ((ioKitClassName = IORegistryEntryCreateCFProperty( (io_registry_entry_t)service, CFSTR(kIOClassKey), kCFAllocatorDefault, 0)) != nil) { - if ([(NSString *)ioKitClassName isEqual:@"AppleIRController"]) + if ([(__HIDRemoteBridge NSString *)ioKitClassName isEqual:@"AppleIRController"]) { if ([HIDRemote OSXVersion] >= 0x1062) { // Support for the Aluminum Remote was added only with OS 10.6.2. Previous versions can not distinguish - // between the Center and the new, separate Play/Pause button. They'll recognize both as presses of the + // between the Center and the new, seperate Play/Pause button. They'll recognize both as presses of the // "Center" button. // // You CAN, however, receive Aluminum Remote button presses even under OS 10.5 when using Remote Buddy's @@ -1476,7 +1498,7 @@ static HIDRemote *sHIDRemote = nil; supportLevel = kHIDRemoteAluminumRemoteSupportLevelNative; } } - + CFRelease(ioKitClassName); } } @@ -1484,24 +1506,23 @@ static HIDRemote *sHIDRemote = nil; [hidAttribsDict setObject:(NSNumber *)[NSNumber numberWithInt:(int)supportLevel] forKey:kHIDRemoteAluminumRemoteSupportLevel]; } - + // Add it to the serviceAttribMap [_serviceAttribMap setObject:hidAttribsDict forKey:[NSNumber numberWithUnsignedInt:(unsigned int)service]]; - + // And we're done with setup .. if (([self delegate]!=nil) && ([[self delegate] respondsToSelector:@selector(hidRemote:foundNewHardwareWithAttributes:)])) { [((NSObject <HIDRemoteDelegate> *)[self delegate]) hidRemote:self foundNewHardwareWithAttributes:hidAttribsDict]; } - - [hidAttribsDict release]; - hidAttribsDict = nil; - + + HIDRemoteReleaseNil(hidAttribsDict); + return(YES); }while(0); - + cleanUp: if (([self delegate]!=nil) && @@ -1509,7 +1530,7 @@ static HIDRemote *sHIDRemote = nil; { if (error!=nil) { - error = [NSError errorWithDomain:[error domain] + error = [NSError errorWithDomain:[error domain] code:[error code] userInfo:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:errorCode] forKey:@"InternalErrorCode"] ]; @@ -1517,7 +1538,7 @@ static HIDRemote *sHIDRemote = nil; [((NSObject <HIDRemoteDelegate> *)[self delegate]) hidRemote:self failedNewHardwareWithError:error]; } - + // An error occured or this device is not of interest .. cleanup .. if (serviceNotification!=0) { @@ -1530,7 +1551,7 @@ static HIDRemote *sHIDRemote = nil; CFRunLoopSourceInvalidate(queueEventSource); queueEventSource=NULL; } - + if (hidQueueInterface!=NULL) { if (queueStarted) @@ -1544,16 +1565,15 @@ static HIDRemote *sHIDRemote = nil; if (hidAttribsDict!=nil) { - [hidAttribsDict release]; - hidAttribsDict = nil; + HIDRemoteReleaseNil(hidAttribsDict); } - + if (hidElements!=NULL) { CFRelease(hidElements); hidElements = NULL; } - + if (hidDeviceInterface!=NULL) { if (opened) @@ -1564,13 +1584,13 @@ static HIDRemote *sHIDRemote = nil; // opened = NO; hidDeviceInterface = NULL; } - + if (cfPluginInterface!=NULL) { IODestroyPlugInInterface(cfPluginInterface); cfPluginInterface = NULL; } - + return (NO); } @@ -1578,14 +1598,14 @@ static HIDRemote *sHIDRemote = nil; { NSNumber *serviceValue; NSMutableDictionary *serviceDict = NULL; - + if ((serviceValue = [NSNumber numberWithUnsignedInt:(unsigned int)service]) == nil) { return; } - + serviceDict = [_serviceAttribMap objectForKey:serviceValue]; - + if (serviceDict!=nil) { IOHIDDeviceInterface122 **hidDeviceInterface = NULL; @@ -1605,8 +1625,8 @@ static HIDRemote *sHIDRemote = nil; cfPluginInterface = (IOCFPlugInInterface **) ([serviceDict objectForKey:kHIDRemoteCFPluginInterface] ? [[serviceDict objectForKey:kHIDRemoteCFPluginInterface] pointerValue] : NULL); cookieButtonMap = (NSMutableDictionary *) [serviceDict objectForKey:kHIDRemoteCookieButtonCodeLUT]; simulateHoldTimer = (NSTimer *) [serviceDict objectForKey:kHIDRemoteSimulateHoldEventsTimer]; - - [serviceDict retain]; + + HIDRemoteRetain(serviceDict); [_serviceAttribMap removeObjectForKey:serviceValue]; if (([serviceDict objectForKey:kHIDRemoteAluminumRemoteSupportOnDemand]!=nil) && [[serviceDict objectForKey:kHIDRemoteAluminumRemoteSupportOnDemand] boolValue] && (theService != 0)) @@ -1614,10 +1634,10 @@ static HIDRemote *sHIDRemote = nil; // We previously requested the driver to enable Aluminum Remote support for us. Tell it to turn it off again - now that we no longer need it IORegistryEntrySetCFProperty( (io_registry_entry_t)theService, CFSTR("DisableAluminumRemoteSupportForMe"), - [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithLongLong:(long long)getpid()], @"pid", - [NSNumber numberWithLongLong:(long long)getuid()], @"uid", - nil]); + (__HIDRemoteBridge CFTypeRef)([NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithLongLong:(long long)getpid()], @"pid", + [NSNumber numberWithLongLong:(long long)getuid()], @"uid", + nil])); } if (([self delegate]!=nil) && @@ -1625,7 +1645,7 @@ static HIDRemote *sHIDRemote = nil; { [((NSObject <HIDRemoteDelegate> *)[self delegate]) hidRemote:self releasedHardwareWithAttributes:serviceDict]; } - + if (simulateHoldTimer!=nil) { [simulateHoldTimer invalidate]; @@ -1642,12 +1662,12 @@ static HIDRemote *sHIDRemote = nil; queueEventSource, kCFRunLoopCommonModes); } - + if ((hidQueueInterface!=NULL) && (cookieButtonMap!=nil)) { NSEnumerator *cookieEnum = [cookieButtonMap keyEnumerator]; NSNumber *cookie; - + while ((cookie = [cookieEnum nextObject]) != nil) { if ((*hidQueueInterface)->hasElement(hidQueueInterface, (IOHIDElementCookie) [cookie unsignedIntValue])) @@ -1657,31 +1677,31 @@ static HIDRemote *sHIDRemote = nil; } }; } - + if (hidQueueInterface!=NULL) { (*hidQueueInterface)->stop(hidQueueInterface); (*hidQueueInterface)->dispose(hidQueueInterface); (*hidQueueInterface)->Release(hidQueueInterface); } - + if (hidDeviceInterface!=NULL) { (*hidDeviceInterface)->close(hidDeviceInterface); (*hidDeviceInterface)->Release(hidDeviceInterface); } - + if (cfPluginInterface!=NULL) { IODestroyPlugInInterface(cfPluginInterface); } - + if (theService!=0) { IOObjectRelease(theService); } - [serviceDict release]; + HIDRemoteRelease(serviceDict); } } @@ -1692,11 +1712,11 @@ static HIDRemote *sHIDRemote = nil; NSMutableDictionary *hidAttribsDict; NSTimer *shTimer; NSNumber *shButtonCode; - + if ((hidAttribsDict = (NSMutableDictionary *)[aTimer userInfo]) != nil) { if (((shTimer = [hidAttribsDict objectForKey:kHIDRemoteSimulateHoldEventsTimer]) != nil) && - ((shButtonCode = [hidAttribsDict objectForKey:kHIDRemoteSimulateHoldEventsOriginButtonCode]) != nil)) + ((shButtonCode = [hidAttribsDict objectForKey:kHIDRemoteSimulateHoldEventsOriginButtonCode]) != nil)) { [shTimer invalidate]; [hidAttribsDict removeObjectForKey:kHIDRemoteSimulateHoldEventsTimer]; @@ -1711,7 +1731,7 @@ static HIDRemote *sHIDRemote = nil; switch (buttonCode) { case kHIDRemoteButtonCodeIDChanged: - // Do nothing, this is handled separately + // Do nothing, this is handled seperately break; case kHIDRemoteButtonCodeUp: @@ -1726,17 +1746,17 @@ static HIDRemote *sHIDRemote = nil; if (isPressed) { [hidAttribsDict setObject:[NSNumber numberWithUnsignedInt:buttonCode] forKey:kHIDRemoteSimulateHoldEventsOriginButtonCode]; - + if ((shTimer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:0.7] interval:0.1 target:self selector:@selector(_simulateHoldEvent:) userInfo:hidAttribsDict repeats:NO]) != nil) { [hidAttribsDict setObject:shTimer forKey:kHIDRemoteSimulateHoldEventsTimer]; - + // Using CFRunLoopAddTimer instead of [[NSRunLoop currentRunLoop] addTimer:.. for consistency with run loop modes. // The kCFRunLoopCommonModes counterpart NSRunLoopCommonModes is only available in 10.5 and later, whereas this code // is designed to be also compatible with 10.4. CFRunLoopTimerRef is "toll-free-bridged" with NSTimer since 10.0. CFRunLoopAddTimer(CFRunLoopGetCurrent(), (CFRunLoopTimerRef)shTimer, kCFRunLoopCommonModes); - - [shTimer release]; + + HIDRemoteRelease(shTimer); break; } @@ -1745,7 +1765,7 @@ static HIDRemote *sHIDRemote = nil; { shTimer = [hidAttribsDict objectForKey:kHIDRemoteSimulateHoldEventsTimer]; shButtonCode = [hidAttribsDict objectForKey:kHIDRemoteSimulateHoldEventsOriginButtonCode]; - + if ((shTimer!=nil) && (shButtonCode!=nil)) { [self _sendButtonCode:(HIDRemoteButtonCode)[shButtonCode unsignedIntValue] isPressed:YES hidAttribsDict:hidAttribsDict]; @@ -1762,10 +1782,10 @@ static HIDRemote *sHIDRemote = nil; [hidAttribsDict removeObjectForKey:kHIDRemoteSimulateHoldEventsTimer]; [hidAttribsDict removeObjectForKey:kHIDRemoteSimulateHoldEventsOriginButtonCode]; - + break; } - + default: [self _sendButtonCode:buttonCode isPressed:isPressed hidAttribsDict:hidAttribsDict]; break; @@ -1807,34 +1827,34 @@ static HIDRemote *sHIDRemote = nil; } break; } - + // As soon as we have received a code that's unique to the Aluminum Remote, we can tell kHIDRemoteButtonCodePlayHold and kHIDRemoteButtonCodeCenterHold apart. // Prior to that, a long press of the new "Play" button will be submitted as a "kHIDRemoteButtonCodeCenterHold", not a "kHIDRemoteButtonCodePlayHold" code. if ((buttonCode == kHIDRemoteButtonCodeCenterHold) && (_lastSeenModel == kHIDRemoteModelAluminum)) { buttonCode = kHIDRemoteButtonCodePlayHold; } - + [((NSObject <HIDRemoteDelegate> *)[self delegate]) hidRemote:self eventWithButton:(buttonCode & (~kHIDRemoteButtonCodeAluminumMask)) isPressed:isPressed fromHardwareWithAttributes:hidAttribsDict]; } } - (void)_hidEventFor:(io_service_t)hidDevice from:(IOHIDQueueInterface **)interface withResult:(IOReturn)result { - NSMutableDictionary *hidAttribsDict = [[[_serviceAttribMap objectForKey:[NSNumber numberWithUnsignedInt:(unsigned int)hidDevice]] retain] autorelease]; - + NSMutableDictionary *hidAttribsDict = HIDRemoteAutoreleased(HIDRemoteRetained([_serviceAttribMap objectForKey:[NSNumber numberWithUnsignedInt:(unsigned int)hidDevice]])); + if (hidAttribsDict!=nil) { IOHIDQueueInterface **queueInterface = NULL; - + queueInterface = [[hidAttribsDict objectForKey:kHIDRemoteHIDQueueInterface] pointerValue]; - + if (interface == queueInterface) { NSNumber *lastButtonPressedNumber = nil; HIDRemoteButtonCode lastButtonPressed = kHIDRemoteButtonCodeNone; NSMutableDictionary *cookieButtonMap = nil; - + cookieButtonMap = [hidAttribsDict objectForKey:kHIDRemoteCookieButtonCodeLUT]; if ((lastButtonPressedNumber = [hidAttribsDict objectForKey:kHIDRemoteLastButtonPressed]) != nil) @@ -1846,27 +1866,27 @@ static HIDRemote *sHIDRemote = nil; { IOHIDEventStruct hidEvent; AbsoluteTime supportedTime = { 0,0 }; - + result = (*queueInterface)->getNextEvent( queueInterface, &hidEvent, supportedTime, 0); - + if (result == kIOReturnSuccess) { NSNumber *buttonCodeNumber = [cookieButtonMap objectForKey:[NSNumber numberWithUnsignedInt:(unsigned int) hidEvent.elementCookie]]; - + #ifdef _HIDREMOTE_EXTENSIONS // Debug logging code #define _HIDREMOTE_EXTENSIONS_SECTION 5 #include "HIDRemoteAdditions.h" #undef _HIDREMOTE_EXTENSIONS_SECTION #endif /* _HIDREMOTE_EXTENSIONS */ - + if (buttonCodeNumber!=nil) { HIDRemoteButtonCode buttonCode = [buttonCodeNumber unsignedIntValue]; - + if (hidEvent.value == 0) { if (buttonCode == lastButtonPressed) @@ -1891,21 +1911,21 @@ static HIDRemote *sHIDRemote = nil; { [((NSObject <HIDRemoteDelegate> *)[self delegate]) hidRemote:self remoteIDChangedOldID:_lastSeenRemoteID newID:hidEvent.value forHardwareWithAttributes:hidAttribsDict]; } - + _lastSeenRemoteID = hidEvent.value; _lastSeenModel = kHIDRemoteModelUndetermined; } - + [self _handleButtonCode:buttonCode isPressed:YES hidAttribsDict:hidAttribsDict]; lastButtonPressed = buttonCode; } } } }; - + [hidAttribsDict setObject:[NSNumber numberWithUnsignedInt:lastButtonPressed] forKey:kHIDRemoteLastButtonPressed]; } - + #ifdef _HIDREMOTE_EXTENSIONS // Debug logging code #define _HIDREMOTE_EXTENSIONS_SECTION 6 @@ -1940,24 +1960,24 @@ static HIDRemote *sHIDRemote = nil; { NSArray *consoleUsersArray; io_service_t rootService; - + if (_masterPort==0) { return; } - + if ((rootService = IORegistryGetRootEntry(_masterPort)) != 0) { - if ((consoleUsersArray = (NSArray *)IORegistryEntryCreateCFProperty((io_registry_entry_t)rootService, CFSTR("IOConsoleUsers"), kCFAllocatorDefault, 0)) != nil) + if ((consoleUsersArray = (__HIDRemoteBridge NSArray *)IORegistryEntryCreateCFProperty((io_registry_entry_t)rootService, CFSTR("IOConsoleUsers"), kCFAllocatorDefault, 0)) != nil) { if ([consoleUsersArray isKindOfClass:[NSArray class]]) // Be careful - ensure this really is an array { NSEnumerator *consoleUsersEnum; // I *love* Obj-C2's fast enumerators, but we need to stay compatible with 10.4 :-/ - + if ((consoleUsersEnum = [consoleUsersArray objectEnumerator]) != nil) { UInt64 secureEventInputPIDSum = 0; uid_t frontUserSession = 0; BOOL screenIsLocked = NO; NSDictionary *consoleUserDict; - + while ((consoleUserDict = [consoleUsersEnum nextObject]) != nil) { if ([consoleUserDict isKindOfClass:[NSDictionary class]]) // Be careful - ensure this really is a dictionary @@ -1966,7 +1986,7 @@ static HIDRemote *sHIDRemote = nil; NSNumber *onConsole; NSNumber *userID; NSNumber *screenIsLockedBool; - + if ((secureInputPID = [consoleUserDict objectForKey:@"kCGSSessionSecureInputPID"]) != nil) { if ([secureInputPID isKindOfClass:[NSNumber class]]) @@ -1974,7 +1994,7 @@ static HIDRemote *sHIDRemote = nil; secureEventInputPIDSum += ((UInt64) [secureInputPID intValue]); } } - + if (((onConsole = [consoleUserDict objectForKey:@"kCGSSessionOnConsoleKey"]) != nil) && ((userID = [consoleUserDict objectForKey:@"kCGSSessionUserIDKey"]) != nil)) { @@ -1986,7 +2006,7 @@ static HIDRemote *sHIDRemote = nil; } } } - + if ((screenIsLockedBool = [consoleUserDict objectForKey:@"CGSSessionScreenIsLocked"]) != nil) { if ([screenIsLockedBool isKindOfClass:[NSNumber class]]) @@ -2002,10 +2022,10 @@ static HIDRemote *sHIDRemote = nil; _lastScreenIsLocked = screenIsLocked; } } - + CFRelease((CFTypeRef)consoleUsersArray); } - + IOObjectRelease((io_object_t) rootService); } } @@ -2016,7 +2036,7 @@ static HIDRemote *sHIDRemote = nil; { HIDRemoteMode restartInMode = _mode; unsigned checkActiveRemoteControlCount = [self activeRemoteControlCount]; - + // Only restart when we already have active remote controls - to avoid race conditions with other applications using kHIDRemoteModeExclusive mode (new in V1.2.1) if (checkActiveRemoteControlCount > 0) { @@ -2024,7 +2044,7 @@ static HIDRemote *sHIDRemote = nil; [self stopRemoteControl]; [self startRemoteControl:restartInMode]; _isRestarting = NO; - + // Check whether we lost a remote control due to restarting/secure input change notification handling (new in V1.2.1) if (checkActiveRemoteControlCount != [self activeRemoteControlCount]) { @@ -2042,9 +2062,9 @@ static HIDRemote *sHIDRemote = nil; UInt64 old_lastSecureEventInputPIDSum = _lastSecureEventInputPIDSum; uid_t old_lastFrontUserSession = _lastFrontUserSession; BOOL old_lastScreenIsLocked = _lastScreenIsLocked; - + [self _updateSessionInformation]; - + if (((old_lastSecureEventInputPIDSum != _lastSecureEventInputPIDSum) || (old_lastFrontUserSession != _lastFrontUserSession) || (old_lastScreenIsLocked != _lastScreenIsLocked)) && _secureEventInputWorkAround) @@ -2063,7 +2083,7 @@ static HIDRemote *sHIDRemote = nil; if (NSAppKitVersionNumber >= 1187) #endif { - #ifdef HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING + #if HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING if ([self respondsToSelector:@selector(performSelector:onThread:withObject:waitUntilDone:)]) // OS X 10.5+ only { if ([NSThread currentThread] != _runOnThread) @@ -2082,29 +2102,31 @@ static HIDRemote *sHIDRemote = nil; #pragma mark - PRIVATE: IOKitLib Callbacks -static void HIDEventCallback( void * target, +static void HIDEventCallback( void * target, IOReturn result, void * refCon, void * sender) { - HIDRemote *hidRemote = (HIDRemote *)refCon; - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + HIDRemote *hidRemote = (__HIDRemoteBridge HIDRemote *)refCon; + + HIDRemoteAutoreleasePoolOpen(); [hidRemote _hidEventFor:(io_service_t)((intptr_t)target) from:(IOHIDQueueInterface**)sender withResult:(IOReturn)result]; - [pool release]; + HIDRemoteAutoreleasePoolClose(); } static void ServiceMatchingCallback( void *refCon, io_iterator_t iterator) { - HIDRemote *hidRemote = (HIDRemote *)refCon; - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + HIDRemote *hidRemote = (__HIDRemoteBridge HIDRemote *)refCon; + + HIDRemoteAutoreleasePoolOpen(); [hidRemote _serviceMatching:iterator]; - [pool release]; + HIDRemoteAutoreleasePoolClose(); } static void ServiceNotificationCallback(void * refCon, @@ -2112,14 +2134,15 @@ static void ServiceNotificationCallback(void * refCon, natural_t messageType, void * messageArgument) { - HIDRemote *hidRemote = (HIDRemote *)refCon; - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + HIDRemote *hidRemote = (__HIDRemoteBridge HIDRemote *)refCon; + HIDRemoteAutoreleasePoolOpen(); + [hidRemote _serviceNotificationFor:service messageType:messageType messageArgument:messageArgument]; - [pool release]; + HIDRemoteAutoreleasePoolClose(); } static void SecureInputNotificationCallback( void * refCon, @@ -2127,14 +2150,15 @@ static void SecureInputNotificationCallback( void * refCon, natural_t messageType, void * messageArgument) { - HIDRemote *hidRemote = (HIDRemote *)refCon; - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + HIDRemote *hidRemote = (__HIDRemoteBridge HIDRemote *)refCon; + HIDRemoteAutoreleasePoolOpen(); + [hidRemote _secureInputNotificationFor:service messageType:messageType messageArgument:messageArgument]; - [pool release]; + HIDRemoteAutoreleasePoolClose(); } // Attribute dictionary keys diff --git a/xbmc/cores/ExternalPlayer/ExternalPlayer.cpp b/xbmc/cores/ExternalPlayer/ExternalPlayer.cpp index feb01bc898..d2f08b8be5 100644 --- a/xbmc/cores/ExternalPlayer/ExternalPlayer.cpp +++ b/xbmc/cores/ExternalPlayer/ExternalPlayer.cpp @@ -89,7 +89,7 @@ bool CExternalPlayer::OpenFile(const CFileItem& file, const CPlayerOptions &opti m_bIsPlaying = true; m_time = 0; m_playbackStartTime = XbmcThreads::SystemClockMillis(); - m_launchFilename = file.GetPath(); + m_launchFilename = file.GetDynPath(); CLog::Log(LOGNOTICE, "%s: %s", __FUNCTION__, m_launchFilename.c_str()); Create(); diff --git a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp index 8c5ea25223..fde83a051f 100644 --- a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp +++ b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp @@ -292,6 +292,15 @@ DemuxPacket* CDVDDemuxClient::Read() } } + if (!IsVideoReady()) + { + m_packet.reset(); + DemuxPacket *pPacket = CDVDDemuxUtils::AllocateDemuxPacket(0); + pPacket->demuxerId = m_demuxerId; + return pPacket; + } + + //! @todo drop this block CDVDInputStream::IDisplayTime *inputStream = m_pInput->GetIDisplayTime(); if (inputStream) { @@ -310,6 +319,7 @@ DemuxPacket* CDVDDemuxClient::Read() m_packet->dispTime += DVD_TIME_TO_MSEC(m_packet->dts - m_dtsAtDisplayTime); } } + return m_packet.release(); } @@ -554,6 +564,17 @@ int CDVDDemuxClient::GetNrOfStreams() const return m_streams.size(); } +bool CDVDDemuxClient::IsVideoReady() +{ + for (const auto& stream : m_streams) + { + if (stream.second->type == STREAM_VIDEO && + stream.second->ExtraData == nullptr) + return false; + } + return true; +} + std::string CDVDDemuxClient::GetFileName() { if (m_pInput) diff --git a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.h b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.h index 692fe1dd43..d41f354a44 100644 --- a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.h +++ b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.h @@ -47,6 +47,7 @@ protected: bool ParsePacket(DemuxPacket* pPacket); void DisposeStreams(); std::shared_ptr<CDemuxStream> GetStreamInternal(int iStreamId); + bool IsVideoReady(); std::shared_ptr<CDVDInputStream> m_pInput; std::shared_ptr<CDVDInputStream::IDemux> m_IDemux; diff --git a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp index 7bca2e90bc..1663f0c809 100644 --- a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +++ b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp @@ -1394,7 +1394,7 @@ void CDVDDemuxFFmpeg::DisposeStreams() CDemuxStream* CDVDDemuxFFmpeg::AddStream(int streamIdx) { AVStream* pStream = m_pFormatContext->streams[streamIdx]; - if (pStream) + if (pStream && pStream->discard != AVDISCARD_ALL) { // Video (mp4) from GoPro cameras can have a 'meta' track used for a file repair containing // 'fdsc' data, this is also called the SOS track. @@ -1630,8 +1630,24 @@ CDemuxStream* CDVDDemuxFFmpeg::AddStream(int streamIdx) #ifdef HAVE_LIBBLURAY if (m_pInput->IsStreamType(DVDSTREAM_TYPE_BLURAY)) { - std::static_pointer_cast<CDVDInputStreamBluray>(m_pInput)->GetStreamInfo(pStream->id, stream->language); stream->dvdNavId = pStream->id; + + auto it = std::find_if(m_streams.begin(), m_streams.end(), + [&stream](const std::pair<int, CDemuxStream*>& v) + {return (v.second->dvdNavId == stream->dvdNavId) && (v.second->type == stream->type); }); + + if (it != m_streams.end()) + { + if (stream->codec == AV_CODEC_ID_AC3 && it->second->codec == AV_CODEC_ID_TRUEHD) + CLog::Log(LOGDEBUG, "CDVDDemuxFFmpeg::AddStream - discarding duplicated bluray stream (truehd ac3 core)"); + else + CLog::Log(LOGDEBUG, "CDVDDemuxFFmpeg::AddStream - discarding duplicate bluray stream %s", stream->codecName); + + pStream->discard = AVDISCARD_ALL; + delete stream; + return nullptr; + } + std::static_pointer_cast<CDVDInputStreamBluray>(m_pInput)->GetStreamInfo(pStream->id, stream->language); } #endif if( m_pInput->IsStreamType(DVDSTREAM_TYPE_DVD) ) diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStream.h b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStream.h index 4e2343b090..8dc39442c9 100644 --- a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStream.h +++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStream.h @@ -155,8 +155,8 @@ public: virtual ENextStream NextStream() { return NEXTSTREAM_NONE; } virtual void Abort() {} virtual int GetBlockSize() { return 0; } - virtual bool CanSeek() { return true; } - virtual bool CanPause() { return true; } + virtual bool CanSeek() { return true; } //! @todo drop this + virtual bool CanPause() { return false; } /*! \brief Indicate expected read rate in bytes per second. * This could be used to throttle caching rate. Should diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamFFmpeg.cpp b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamFFmpeg.cpp index 21fa6f5f23..26e1824fed 100644 --- a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamFFmpeg.cpp +++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamFFmpeg.cpp @@ -22,9 +22,6 @@ using PLAYLIST::CPlayListM3U; CDVDInputStreamFFmpeg::CDVDInputStreamFFmpeg(const CFileItem& fileitem) : CDVDInputStream(DVDSTREAM_TYPE_FFMPEG, fileitem) - , m_can_pause(false) - , m_can_seek(false) - , m_aborted(false) { } @@ -47,23 +44,14 @@ bool CDVDInputStreamFFmpeg::Open() if (!CDVDInputStream::Open()) return false; - m_can_pause = true; - m_can_seek = true; - m_aborted = false; + m_aborted = false; if(strnicmp(m_item.GetDynPath().c_str(), "udp://", 6) == 0 || strnicmp(m_item.GetDynPath().c_str(), "rtp://", 6) == 0) { - m_can_pause = false; - m_can_seek = false; m_realtime = true; } - if(strnicmp(m_item.GetDynPath().c_str(), "tcp://", 6) == 0) - { - m_can_pause = true; - m_can_seek = false; - } return true; } diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamFFmpeg.h b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamFFmpeg.h index 6e7a299f07..e34855ebb0 100644 --- a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamFFmpeg.h +++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamFFmpeg.h @@ -30,9 +30,6 @@ public: const CFileItem& GetItem() const { return m_item; } - bool CanSeek() override { return m_can_seek; } - bool CanPause() override { return m_can_pause; } - std::string GetProxyType() const; std::string GetProxyHost() const; uint16_t GetProxyPort() const; @@ -40,7 +37,5 @@ public: std::string GetProxyPassword() const; protected: - bool m_can_pause; - bool m_can_seek; - bool m_aborted; + bool m_aborted = false; }; diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.h b/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.h index bf800938ac..e215953ab2 100644 --- a/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.h +++ b/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.h @@ -53,7 +53,7 @@ public: bool Pause(double dTime) override; int64_t GetLength() override; bool IsEOF() override; - bool CanSeek() override; + bool CanSeek() override; //! @todo drop this bool CanPause() override; // IDisplayTime diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamPVRBase.h b/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamPVRBase.h index ee48c9e63f..c339599ccd 100644 --- a/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamPVRBase.h +++ b/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamPVRBase.h @@ -46,7 +46,7 @@ public: CDVDInputStream::ITimes* GetITimes() override { return this; } bool GetTimes(Times ×) override; - bool CanSeek() override; + bool CanSeek() override; //! @todo drop this bool CanPause() override; void Pause(bool bPaused); diff --git a/xbmc/cores/VideoPlayer/VideoPlayer.cpp b/xbmc/cores/VideoPlayer/VideoPlayer.cpp index 60221e0b6b..2b51c80e5a 100644 --- a/xbmc/cores/VideoPlayer/VideoPlayer.cpp +++ b/xbmc/cores/VideoPlayer/VideoPlayer.cpp @@ -1989,9 +1989,11 @@ void CVideoPlayer::HandlePlaySpeed() threshold = 40; bool video = m_CurrentVideo.id < 0 || (m_CurrentVideo.syncState == IDVDStreamPlayer::SYNC_WAITSYNC) || - (m_CurrentVideo.packets == 0 && m_CurrentAudio.packets > threshold); + (m_CurrentVideo.packets == 0 && m_CurrentAudio.packets > threshold) || + (!m_VideoPlayerAudio->AcceptsData() && m_processInfo->GetLevelVQ() < 10); bool audio = m_CurrentAudio.id < 0 || (m_CurrentAudio.syncState == IDVDStreamPlayer::SYNC_WAITSYNC) || - (m_CurrentAudio.packets == 0 && m_CurrentVideo.packets > threshold); + (m_CurrentAudio.packets == 0 && m_CurrentVideo.packets > threshold) || + (!m_VideoPlayerVideo->AcceptsData() && m_VideoPlayerAudio->GetLevel() < 10); if (m_CurrentAudio.syncState == IDVDStreamPlayer::SYNC_WAITSYNC && (m_CurrentAudio.avsync == CCurrentStream::AV_SYNC_CONT || @@ -4672,8 +4674,9 @@ void CVideoPlayer::UpdatePlayState(double timeout) state.timeMax = m_pDemuxer->GetStreamLength(); } - state.canpause = true; - state.canseek = true; + state.canpause = false; + state.canseek = false; + state.cantempo = false; state.isInMenu = false; state.hasMenu = false; @@ -4732,7 +4735,6 @@ void CVideoPlayer::UpdatePlayState(double timeout) } state.canpause = m_pInputStream->CanPause(); - state.canseek = m_pInputStream->CanSeek(); bool realtime = m_pInputStream->IsRealtime(); @@ -4794,9 +4796,13 @@ void CVideoPlayer::UpdatePlayState(double timeout) if (state.timeMin == state.timeMax) { state.canseek = false; - state.canpause = false; state.cantempo = false; } + else + { + state.canseek = true; + state.canpause = true; + } m_processInfo->SetPlayTimes(state.startTime, state.time, state.timeMin, state.timeMax); diff --git a/xbmc/cores/playercorefactory/PlayerCoreFactory.cpp b/xbmc/cores/playercorefactory/PlayerCoreFactory.cpp index 665d3fcd99..5ea7d37d9f 100644 --- a/xbmc/cores/playercorefactory/PlayerCoreFactory.cpp +++ b/xbmc/cores/playercorefactory/PlayerCoreFactory.cpp @@ -96,9 +96,9 @@ void CPlayerCoreFactory::GetPlayers(std::vector<std::string>&players, const bool void CPlayerCoreFactory::GetPlayers(const CFileItem& item, std::vector<std::string>&players) const { - CURL url(item.GetPath()); + CURL url(item.GetDynPath()); - CLog::Log(LOGDEBUG, "CPlayerCoreFactory::GetPlayers(%s)", CURL::GetRedacted(item.GetPath()).c_str()); + CLog::Log(LOGDEBUG, "CPlayerCoreFactory::GetPlayers(%s)", CURL::GetRedacted(item.GetDynPath()).c_str()); std::vector<std::string>validPlayers; GetPlayers(validPlayers); diff --git a/xbmc/cores/playercorefactory/PlayerSelectionRule.cpp b/xbmc/cores/playercorefactory/PlayerSelectionRule.cpp index 31de65da82..28a4ca22bc 100644 --- a/xbmc/cores/playercorefactory/PlayerSelectionRule.cpp +++ b/xbmc/cores/playercorefactory/PlayerSelectionRule.cpp @@ -157,7 +157,7 @@ void CPlayerSelectionRule::GetPlayers(const CFileItem& item, std::vector<std::st return; } - CURL url(item.GetPath()); + CURL url(item.GetDynPath()); if (CompileRegExp(m_fileTypes, regExp) && !MatchesRegExp(url.GetFileType(), regExp)) return; @@ -168,7 +168,7 @@ void CPlayerSelectionRule::GetPlayers(const CFileItem& item, std::vector<std::st if (CompileRegExp(m_mimeTypes, regExp) && !MatchesRegExp(item.GetMimeType(), regExp)) return; - if (CompileRegExp(m_fileName, regExp) && !MatchesRegExp(item.GetPath(), regExp)) + if (CompileRegExp(m_fileName, regExp) && !MatchesRegExp(item.GetDynPath(), regExp)) return; CLog::Log(LOGDEBUG, "CPlayerSelectionRule::GetPlayers: matches rule: %s", m_name.c_str()); diff --git a/xbmc/input/InputManager.cpp b/xbmc/input/InputManager.cpp index 6acd88c0e6..7d9c0d208b 100644 --- a/xbmc/input/InputManager.cpp +++ b/xbmc/input/InputManager.cpp @@ -219,6 +219,8 @@ bool CInputManager::ProcessEventServer(int windowId, float frameTime) m_Mouse.SetActive(false); + CLog::Log(LOGDEBUG, "EventServer: key %d translated to action %s", wKeyID, actionName); + return ExecuteInputAction(CAction(actionID, fAmount, 0.0f, actionName)); } else diff --git a/xbmc/messaging/ThreadMessage.h b/xbmc/messaging/ThreadMessage.h index 538007df9e..e79237a25c 100644 --- a/xbmc/messaging/ThreadMessage.h +++ b/xbmc/messaging/ThreadMessage.h @@ -53,6 +53,7 @@ public: : dwMessage{ messageId } , param1{ p1 } , param2{ p2 } + , param3{ 0 } , lpVoid{ payload } , strParam( param ) , params( vecParams ) diff --git a/xbmc/music/windows/GUIWindowMusicBase.cpp b/xbmc/music/windows/GUIWindowMusicBase.cpp index 812f0b5afc..a2b865e208 100644 --- a/xbmc/music/windows/GUIWindowMusicBase.cpp +++ b/xbmc/music/windows/GUIWindowMusicBase.cpp @@ -58,6 +58,7 @@ #include "cores/playercorefactory/PlayerCoreFactory.h" #include "CueDocument.h" #include "Autorun.h" +#include "video/dialogs/GUIDialogVideoInfo.h" #ifdef TARGET_POSIX #include "platform/linux/XTimeUtils.h" @@ -274,9 +275,9 @@ void CGUIWindowMusicBase::OnItemInfo(int iItem) CFileItemPtr item = m_vecItems->Get(iItem); - if (item->IsVideoDb()) + if (item->IsVideo()) { // Music video on a mixed current playlist - OnContextButton(iItem, CONTEXT_BUTTON_INFO); + CGUIDialogVideoInfo::ShowFor(*item); return; } @@ -316,7 +317,7 @@ void CGUIWindowMusicBase::RetrieveMusicInfo() for (int i = 0; i < m_vecItems->Size(); ++i) { CFileItemPtr pItem = (*m_vecItems)[i]; - if (pItem->m_bIsFolder || pItem->IsPlayList() || pItem->IsPicture() || pItem->IsLyrics()) + if (pItem->m_bIsFolder || pItem->IsPlayList() || pItem->IsPicture() || pItem->IsLyrics() || pItem->IsVideo()) continue; CMusicInfoTag& tag = *pItem->GetMusicInfoTag(); diff --git a/xbmc/network/EventClient.cpp b/xbmc/network/EventClient.cpp index 4f073ff081..7e5a60ccda 100644 --- a/xbmc/network/EventClient.cpp +++ b/xbmc/network/EventClient.cpp @@ -26,6 +26,7 @@ #include "guilib/LocalizeStrings.h" #include "utils/StringUtils.h" #include "ServiceBroker.h" +#include "utils/log.h" using namespace EVENTCLIENT; using namespace EVENTPACKET; @@ -388,6 +389,8 @@ bool CEventClient::OnPacketBUTTON(CEventPacket *packet) float famount = 0; bool active = (flags & PTB_DOWN) ? true : false; + + CLog::Log(LOGDEBUG, "EventClient: button code %d %s", bcode, active ? "pressed" : "released"); if(flags & PTB_USE_AMOUNT) { @@ -437,15 +440,22 @@ bool CEventClient::OnPacketBUTTON(CEventPacket *packet) /* if last event had an amount, we must resend without amount */ if(it2->m_bUseAmount && it2->m_fAmount != 0.0) + { m_buttonQueue.push_back(state); + } /* if the last event was waiting for a repeat interval, it has executed already.*/ if(it2->m_bRepeat) { if(it2->m_iNextRepeat > 0) + { m_buttonQueue.erase(it2); + } else + { it2->m_bRepeat = false; + it2->m_bActive = false; + } } } diff --git a/xbmc/platform/linux/input/LibInputTouch.cpp b/xbmc/platform/linux/input/LibInputTouch.cpp index 7e186df62b..fb771cfb1d 100644 --- a/xbmc/platform/linux/input/LibInputTouch.cpp +++ b/xbmc/platform/linux/input/LibInputTouch.cpp @@ -55,7 +55,7 @@ void CLibInputTouch::SetPosition(int slot, CPoint point) void CLibInputTouch::ProcessTouchDown(libinput_event_touch *e) { - int slot = libinput_event_touch_get_slot(e); + int slot = libinput_event_touch_get_seat_slot(e); SetPosition(slot, GetPos(e)); SetEvent(slot, TouchInputDown); @@ -64,7 +64,7 @@ void CLibInputTouch::ProcessTouchDown(libinput_event_touch *e) void CLibInputTouch::ProcessTouchMotion(libinput_event_touch *e) { - int slot = libinput_event_touch_get_slot(e); + int slot = libinput_event_touch_get_seat_slot(e); uint64_t nanotime = libinput_event_touch_get_time_usec(e) * 1000LL; SetPosition(slot, GetPos(e)); @@ -78,7 +78,7 @@ void CLibInputTouch::ProcessTouchMotion(libinput_event_touch *e) void CLibInputTouch::ProcessTouchUp(libinput_event_touch *e) { - int slot = libinput_event_touch_get_slot(e); + int slot = libinput_event_touch_get_seat_slot(e); SetEvent(slot, TouchInputUp); CLog::Log(LOGDEBUG, "CLibInputTouch::%s - touch input up", __FUNCTION__); @@ -86,7 +86,7 @@ void CLibInputTouch::ProcessTouchUp(libinput_event_touch *e) void CLibInputTouch::ProcessTouchCancel(libinput_event_touch *e) { - int slot = libinput_event_touch_get_slot(e); + int slot = libinput_event_touch_get_seat_slot(e); uint64_t nanotime = libinput_event_touch_get_time_usec(e) * 1000LL; CLog::Log(LOGDEBUG, "CLibInputTouch::%s - touch input cancel", __FUNCTION__); diff --git a/xbmc/pvr/windows/GUIEPGGridContainer.cpp b/xbmc/pvr/windows/GUIEPGGridContainer.cpp index 79c5e8df8c..88fe9737ca 100644 --- a/xbmc/pvr/windows/GUIEPGGridContainer.cpp +++ b/xbmc/pvr/windows/GUIEPGGridContainer.cpp @@ -143,7 +143,6 @@ CGUIEPGGridContainer::CGUIEPGGridContainer(const CGUIEPGGridContainer &other) m_channelScrollOffset(other.m_channelScrollOffset), m_gridModel(new CGUIEPGGridContainerModel(*other.m_gridModel)), m_updatedGridModel(other.m_updatedGridModel ? new CGUIEPGGridContainerModel(*other.m_updatedGridModel) : nullptr), - m_outdatedGridModel(other.m_outdatedGridModel ? new CGUIEPGGridContainerModel(*other.m_outdatedGridModel) : nullptr), m_item(GetItem(m_channelCursor)) // pointer to grid model internal data. { } @@ -736,7 +735,6 @@ void CGUIEPGGridContainer::UpdateItems() m_lastChannel = nullptr; // always use asynchronously precalculated grid data. - m_outdatedGridModel = std::move(m_gridModel); // destructing grid data can be very expensive, thus this will be done asynchronously, not here. m_gridModel = std::move(m_updatedGridModel); if (prevSelectedEpgTag) @@ -1726,18 +1724,16 @@ void CGUIEPGGridContainer::SetTimelineItems(const std::unique_ptr<CFileItemList> fBlockSize = m_blockSize; } - std::unique_ptr<CGUIEPGGridContainerModel> oldOutdatedGridModel; std::unique_ptr<CGUIEPGGridContainerModel> oldUpdatedGridModel; std::unique_ptr<CGUIEPGGridContainerModel> newUpdatedGridModel(new CGUIEPGGridContainerModel); // can be very expensive. never call with lock acquired. - newUpdatedGridModel->Refresh(items, gridStart, gridEnd, iRulerUnit, iBlocksPerPage, fBlockSize); + newUpdatedGridModel->Initialize(items, gridStart, gridEnd, iRulerUnit, iBlocksPerPage, fBlockSize); { CSingleLock lock(m_critSection); // grid contains CFileItem instances. CFileItem dtor locks global graphics mutex. // by increasing its refcount make sure, old data are not deleted while we're holding own mutex. - oldOutdatedGridModel = std::move(m_outdatedGridModel); oldUpdatedGridModel = std::move(m_updatedGridModel); m_updatedGridModel = std::move(newUpdatedGridModel); diff --git a/xbmc/pvr/windows/GUIEPGGridContainer.h b/xbmc/pvr/windows/GUIEPGGridContainer.h index aeacd0a117..db78ed711a 100644 --- a/xbmc/pvr/windows/GUIEPGGridContainer.h +++ b/xbmc/pvr/windows/GUIEPGGridContainer.h @@ -225,7 +225,6 @@ namespace PVR mutable CCriticalSection m_critSection; std::unique_ptr<CGUIEPGGridContainerModel> m_gridModel; std::unique_ptr<CGUIEPGGridContainerModel> m_updatedGridModel; - std::unique_ptr<CGUIEPGGridContainerModel> m_outdatedGridModel; GridItem *m_item; }; diff --git a/xbmc/pvr/windows/GUIEPGGridContainerModel.cpp b/xbmc/pvr/windows/GUIEPGGridContainerModel.cpp index a77529be5d..e6d5c65176 100644 --- a/xbmc/pvr/windows/GUIEPGGridContainerModel.cpp +++ b/xbmc/pvr/windows/GUIEPGGridContainerModel.cpp @@ -14,6 +14,7 @@ #include "ServiceBroker.h" #include "settings/Settings.h" #include "utils/Variant.h" +#include "utils/log.h" #include "pvr/PVRManager.h" #include "pvr/channels/PVRChannel.h" @@ -36,28 +37,13 @@ void CGUIEPGGridContainerModel::SetInvalid() ruler->SetInvalid(); } -void CGUIEPGGridContainerModel::Reset() +void CGUIEPGGridContainerModel::Initialize(const std::unique_ptr<CFileItemList> &items, const CDateTime &gridStart, const CDateTime &gridEnd, int iRulerUnit, int iBlocksPerPage, float fBlockSize) { - for (auto &channel : m_gridIndex) + if (!m_channelItems.empty()) { - for (const auto &block : channel) - { - if (block.item) - block.item->ClearProperties(); - } - channel.clear(); + CLog::LogF(LOGERROR, "Already initialized!"); + return; } - m_gridIndex.clear(); - - m_channelItems.clear(); - m_programmeItems.clear(); - m_rulerItems.clear(); - m_epgItemsPtr.clear(); -} - -void CGUIEPGGridContainerModel::Refresh(const std::unique_ptr<CFileItemList> &items, const CDateTime &gridStart, const CDateTime &gridEnd, int iRulerUnit, int iBlocksPerPage, float fBlockSize) -{ - Reset(); //////////////////////////////////////////////////////////////////////// // Create programme & channel items diff --git a/xbmc/pvr/windows/GUIEPGGridContainerModel.h b/xbmc/pvr/windows/GUIEPGGridContainerModel.h index 04ddd45157..146ecbe2fe 100644 --- a/xbmc/pvr/windows/GUIEPGGridContainerModel.h +++ b/xbmc/pvr/windows/GUIEPGGridContainerModel.h @@ -36,9 +36,10 @@ namespace PVR static const int MINSPERBLOCK = 5; // minutes static const int MAXBLOCKS = 33 * 24 * 60 / MINSPERBLOCK; //! 33 days of 5 minute blocks (31 days for upcoming data + 1 day for past data + 1 day for fillers) - virtual ~CGUIEPGGridContainerModel() { Reset(); } + CGUIEPGGridContainerModel() = default; + virtual ~CGUIEPGGridContainerModel() = default; - void Refresh(const std::unique_ptr<CFileItemList> &items, const CDateTime &gridStart, const CDateTime &gridEnd, int iRulerUnit, int iBlocksPerPage, float fBlockSize); + void Initialize(const std::unique_ptr<CFileItemList> &items, const CDateTime &gridStart, const CDateTime &gridEnd, int iRulerUnit, int iBlocksPerPage, float fBlockSize); void SetInvalid(); static const int INVALID_INDEX = -1; @@ -83,7 +84,6 @@ namespace PVR private: void FreeItemsMemory(); - void Reset(); struct ItemsPtr { diff --git a/xbmc/windowing/gbm/DRMUtils.cpp b/xbmc/windowing/gbm/DRMUtils.cpp index 94512a308a..84f869877b 100644 --- a/xbmc/windowing/gbm/DRMUtils.cpp +++ b/xbmc/windowing/gbm/DRMUtils.cpp @@ -428,6 +428,8 @@ bool CDRMUtils::FindPlanes() if (!FindModifiersForPlane(m_overlay_plane)) { CLog::Log(LOGDEBUG, "CDRMUtils::%s - no drm modifiers present for the overlay plane", __FUNCTION__); + m_overlay_plane->modifiers_map.emplace(DRM_FORMAT_ARGB8888, std::vector<uint64_t>{DRM_FORMAT_MOD_LINEAR}); + m_overlay_plane->modifiers_map.emplace(DRM_FORMAT_XRGB8888, std::vector<uint64_t>{DRM_FORMAT_MOD_LINEAR}); } return true; diff --git a/xbmc/windowing/gbm/GBMUtils.cpp b/xbmc/windowing/gbm/GBMUtils.cpp index 118b99f947..a48d6cc4f8 100644 --- a/xbmc/windowing/gbm/GBMUtils.cpp +++ b/xbmc/windowing/gbm/GBMUtils.cpp @@ -48,13 +48,15 @@ bool CGBMUtils::CreateSurface(int width, int height, const uint64_t *modifiers, GBM_FORMAT_ARGB8888, modifiers, modifiers_count); -#else - m_surface = gbm_surface_create(m_device, - width, - height, - GBM_FORMAT_ARGB8888, - GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); #endif + if (!m_surface) + { + m_surface = gbm_surface_create(m_device, + width, + height, + GBM_FORMAT_ARGB8888, + GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); + } if (!m_surface) { |