diff options
343 files changed, 2582 insertions, 1360 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 911560e4e8..d297716029 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -226,6 +226,7 @@ add_custom_command(OUTPUT ${CORE_BUILD_DIR}/xbmc/CompileInfo.cpp -DCMAKE_BINARY_DIR=${CMAKE_BINARY_DIR} -DARCH_DEFINES="${ARCH_DEFINES}" -DAPP_SCMID=${APP_SCMID} + -DAPP_COPYRIGHT_YEARS=${APP_COPYRIGHT_YEARS} -Dprefix=${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR} -P ${CMAKE_SOURCE_DIR}/cmake/scripts/common/GenerateVersionedFiles.cmake DEPENDS ${CMAKE_SOURCE_DIR}/version.txt diff --git a/addons/metadata.common.imdb.com/addon.xml b/addons/metadata.common.imdb.com/addon.xml index 2391d124af..1e0f87b42c 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="3.1.0" + version="3.1.3" 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 be2a0c4eda..5fa40b1009 100644 --- a/addons/metadata.common.imdb.com/changelog.txt +++ b/addons/metadata.common.imdb.com/changelog.txt @@ -1,3 +1,12 @@ +[B]3.1.3[/B] +- fixed: IMDb Genres for single genre movies + +[B]3.1.2[/B] +- fixed: IMDb Genres + +[B]3.1.1[/B] +- fixed: MetaCritic rating from IMDb + [B]3.1.0[/B] - fixed: re-write most regular expressions following IMDb site layout changes diff --git a/addons/metadata.common.imdb.com/imdb.xml b/addons/metadata.common.imdb.com/imdb.xml index 0797bad7a1..74d4f42422 100644 --- a/addons/metadata.common.imdb.com/imdb.xml +++ b/addons/metadata.common.imdb.com/imdb.xml @@ -7,8 +7,14 @@ </GetIMDBGenresById> <ParseIMDBGenres dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> - <RegExp input="$$1" output="<genre>\1</genre>" dest="2"> - <expression repeat="yes">tt_stry_gnr"\s>\s([^<]+)</expression> + <RegExp input="$$1" output="\1" dest="6"> + <expression noclean="1">,\s*"genre":\s("[^"]+"),</expression> + </RegExp> + <RegExp input="$$1" output="\1" dest="6"> + <expression noclean="1">"genre":\s\[(.*?)\]</expression> + </RegExp> + <RegExp input="$$6" output="<genre>\1</genre>" dest="2"> + <expression repeat="yes">"([^"]+)"</expression> </RegExp> <expression noclean="1" /> </RegExp> @@ -98,13 +104,13 @@ <ParseMetaCriticRating dest="5"> <RegExp input="$$2" output="<details>\1</details>" dest="5"> <RegExp input="$$1" output="\1" dest="6"> - <expression clear="yes" noclean="1"><div\sclass="metacriticScore\sscore_mixed\stitleReviewBarSubItem"(.*?)<span\sclass="ghostText"</expression> + <expression clear="yes" noclean="1"><div\sclass="metascore_block"(.*?)Metacritic.com</a></expression> </RegExp> <RegExp input="$$6" output="<rating max="100">\1</value>" dest="2"> - <expression clear="yes"><span>(\d+)</span></expression> + <expression clear="yes"><span\sitemprop="ratingValue">(\d+)</span></expression> </RegExp> <RegExp input="$$6" output="<votes>\1</votes>" dest="2+"> - <expression>>(\d+)\suser</a></expression> + <expression><span\sitemprop="ratingCount">(\d+)</span></expression> </RegExp> <expression noclean="1" /> </RegExp> @@ -122,13 +128,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\sclass="metacriticScore\sscore_mixed\stitleReviewBarSubItem"(.*?)<span\sclass="ghostText"</expression> + <expression clear="yes" noclean="1"><div\sclass="metascore_block"(.*?)Metacritic.com</a></expression> </RegExp> <RegExp input="$$6" output="<value>\1</value>" dest="4"> - <expression clear="yes"><span>(\d+)</span></expression> + <expression clear="yes"><span\sitemprop="ratingValue">(\d+)</span></expression> </RegExp> <RegExp input="$$6" output="<votes>\1</votes>" dest="4+"> - <expression>>(\d+)\suser</a></expression> + <expression><span\sitemprop="ratingCount">(\d+)</span></expression> </RegExp> <expression noclean="1" clear="yes"/> </RegExp> diff --git a/addons/metadata.common.themoviedb.org/addon.xml b/addons/metadata.common.themoviedb.org/addon.xml index 8000a309f4..dbc8930b92 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="3.1.7" + version="3.1.8" 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 722fa466b4..443a13afb7 100644 --- a/addons/metadata.common.themoviedb.org/tmdb.xml +++ b/addons/metadata.common.themoviedb.org/tmdb.xml @@ -9,7 +9,7 @@ <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"> + <RegExp input="$$1" output="<url function="ParseTMDBCertifications" cache="tmdb-cert-\1.json">https://api.tmdb.org/3/movie/\1/releases?api_key=f090bb54758cabf231fb605d3e3e0468</url>" dest="5"> <expression>(.+)::(.+)::(.+)?</expression> </RegExp> <expression noclean="1" /> @@ -32,11 +32,11 @@ <RegExp input="$$1" output="\1::\2" dest="16"> <expression>(.+)::(.+)</expression> </RegExp> - <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"> + <RegExp input="$$1" output="<url function="ParseTMDBTitle" cache="tmdb-\2-\1.json">https://api.tmdb.org/3/movie/\1?api_key=f090bb54758cabf231fb605d3e3e0468&amp;language=\2</url>" dest="5"> <expression>(.+)::(.+)</expression> </RegExp> <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"> + <RegExp input="$$1" output="<url function="ParseTMDBTitle" cache="tmdb-en-\1.json">https://api.tmdb.org/3/movie/\1?api_key=f090bb54758cabf231fb605d3e3e0468&amp;language=en</url>" dest="2"> <expression>(.+)::</expression> </RegExp> <expression>(.+)::Keep Original</expression> @@ -64,7 +64,7 @@ <RegExp input="$$1" output="\1" dest="8"> <expression encode="1">(.+)::.+</expression> </RegExp> - <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"> + <RegExp input="$$1" output="<url function="ParseTMDBPlot" cache="tmdb-\2-\1.json">https://api.tmdb.org/3/movie/\1?api_key=f090bb54758cabf231fb605d3e3e0468&amp;language=\2</url>" dest="5"> <expression>(.+)::(.+)</expression> </RegExp> <expression noclean="1" /> @@ -75,7 +75,7 @@ <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=45ab4cebe57ae11c2ee50c87005ddfe8&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=f090bb54758cabf231fb605d3e3e0468&amp;language=en</url>" dest="2"> <expression>^$</expression> </RegExp> <RegExp input="$$9" output="<plot>\1</plot>" dest="2"> @@ -98,7 +98,7 @@ <RegExp input="$$1" output="\1" dest="8"> <expression>(.+)::.+</expression> </RegExp> - <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"> + <RegExp input="$$1" output="<url function="ParseTMDBTagline" cache="tmdb-\2-\1.json">https://api.tmdb.org/3/movie/\1?api_key=f090bb54758cabf231fb605d3e3e0468&amp;language=\2</url>" dest="5"> <expression>(.+)::(.+)</expression> </RegExp> <expression noclean="1" /> @@ -109,7 +109,7 @@ <RegExp input="$$1" output="\1" dest="9"> <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=45ab4cebe57ae11c2ee50c87005ddfe8&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=f090bb54758cabf231fb605d3e3e0468&amp;language=en</url>" dest="2"> <expression>^$</expression> </RegExp> <RegExp input="$$9" output="<tagline>\1</tagline>" dest="2"> @@ -132,7 +132,7 @@ <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=45ab4cebe57ae11c2ee50c87005ddfe8</url>" dest="5"> + <RegExp input="$$8" output="<url function="ParseTMDBTags" >https://api.tmdb.org/3/movie/\1/keywords?api_key=f090bb54758cabf231fb605d3e3e0468</url>" dest="5"> <expression /> </RegExp> <expression noclean="1" /> @@ -155,7 +155,7 @@ <RegExp input="$$1" output="\2" dest="10"> <expression>(.+)::(.+)</expression> </RegExp> - <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"> + <RegExp input="$$8" output="<url function="GetTMDBSetID" cache="tmdb-$$10-\1.json">https://api.tmdb.org/3/movie/\1?api_key=f090bb54758cabf231fb605d3e3e0468&amp;language=$$10</url>" dest="5"> <expression /> </RegExp> <expression noclean="1" /> @@ -166,10 +166,10 @@ <RegExp input="$$1" output="\1" dest="9"> <expression clear="yes" noclean="1">"belongs_to_collection":\{"id":([0-9]+),"name":"([^"]*)</expression> </RegExp> - <RegExp input="$$9" output="<url function="ParseTMDBBaseImageURL" cache="tmdb-config.json">https://api.tmdb.org/3/configuration?api_key=45ab4cebe57ae11c2ee50c87005ddfe8</url>" dest="2"> + <RegExp input="$$9" output="<url function="ParseTMDBBaseImageURL" cache="tmdb-config.json">https://api.tmdb.org/3/configuration?api_key=f090bb54758cabf231fb605d3e3e0468</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+"> + <RegExp input="$$9" output="<url function="ParseTMDBSetOutline" cache="tmdbset-$$10-\1.json">https://api.tmdb.org/3/collection/\1?api_key=f090bb54758cabf231fb605d3e3e0468&amp;language=$$10&amp;append_to_response=images&amp;include_image_language=$$10,en,null</url>" dest="2+"> <expression>(.+)</expression> </RegExp> <expression noclean="1" /> @@ -213,7 +213,7 @@ </RegExp> <expression noclean="1" /> </RegExp> - <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"> + <RegExp input="$$9" output="<url function="ParseFallbackTMDBSetOutline" cache="tmdbset-en-$$6.json">https://api.tmdb.org/3/collection/$$6?api_key=f090bb54758cabf231fb605d3e3e0468&amp;language=en&amp;append_to_response=images&amp;include_image_language=$$10,en,null</url>" dest="2"> <expression>^$</expression> </RegExp> <expression noclean="1" /> @@ -251,10 +251,10 @@ <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=45ab4cebe57ae11c2ee50c87005ddfe8</url>" dest="5"> + <RegExp input="$$1" output="<url function="ParseTMDBBaseImageURL" cache="tmdb-config.json">https://api.tmdb.org/3/configuration?api_key=f090bb54758cabf231fb605d3e3e0468</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=45ab4cebe57ae11c2ee50c87005ddfe8</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=f090bb54758cabf231fb605d3e3e0468</url>" dest="5+"> <expression /> </RegExp> <expression noclean="1" /> @@ -277,7 +277,7 @@ <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=45ab4cebe57ae11c2ee50c87005ddfe8</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=f090bb54758cabf231fb605d3e3e0468</url>" dest="5"> <expression /> </RegExp> <expression noclean="1" /> @@ -297,7 +297,7 @@ <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=45ab4cebe57ae11c2ee50c87005ddfe8</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=f090bb54758cabf231fb605d3e3e0468</url>" dest="5"> <expression /> </RegExp> <expression noclean="1" /> @@ -317,7 +317,7 @@ <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-\2-\1.json">https://api.tmdb.org/3/movie/\1?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=\2</url>" dest="5"> + <RegExp input="$$1" output="<url function="ParseTMDBGenres" cache="tmdb-\2-\1.json">https://api.tmdb.org/3/movie/\1?api_key=f090bb54758cabf231fb605d3e3e0468&amp;language=\2</url>" dest="5"> <expression>(.+)::(.+)</expression> </RegExp> <expression noclean="1" /> @@ -343,7 +343,7 @@ <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"> + <RegExp input="$$1" output="<url function="ParseTMDBRating" cache="tmdb-$$11-\1.json">https://api.tmdb.org/3/movie/\1?api_key=f090bb54758cabf231fb605d3e3e0468&amp;language=$$11</url>" dest="5"> <expression>^(.+)::</expression> </RegExp> <expression noclean="1" /> @@ -369,7 +369,7 @@ <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"> + <RegExp input="$$1" output="<url function="ParseTMDBRatings" cache="tmdb-$$11-\1.json">https://api.tmdb.org/3/movie/\1?api_key=f090bb54758cabf231fb605d3e3e0468&amp;language=$$11</url>" dest="5"> <expression noclean="1">^((tt)?\d+)</expression> </RegExp> <RegExp input="$$1" output="default="true"" dest="3"> @@ -392,7 +392,7 @@ <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-\2-\1.json">https://api.tmdb.org/3/movie/\1?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=\2</url>" dest="5"> + <RegExp input="$$1" output="<url function="ParseTMDBStudio" cache="tmdb-\2-\1.json">https://api.tmdb.org/3/movie/\1?api_key=f090bb54758cabf231fb605d3e3e0468&amp;language=\2</url>" dest="5"> <expression>(.+)::(.+)</expression> </RegExp> <expression noclean="1" /> @@ -412,7 +412,7 @@ <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-\2-\1.json">https://api.tmdb.org/3/movie/\1?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=\2</url>" dest="5"> + <RegExp input="$$1" output="<url function="ParseTMDBCountry" cache="tmdb-\2-\1.json">https://api.tmdb.org/3/movie/\1?api_key=f090bb54758cabf231fb605d3e3e0468&amp;language=\2</url>" dest="5"> <expression>(.+)::(.+)</expression> </RegExp> <expression noclean="1" /> @@ -432,7 +432,7 @@ <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-\2-\1.json">https://api.tmdb.org/3/movie/\1/trailers?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=\2</url>" dest="5"> + <RegExp input="$$1" output="<url function="ParseTMDBTrailer" cache="tmdb-trailer-\2-\1.json">https://api.tmdb.org/3/movie/\1/trailers?api_key=f090bb54758cabf231fb605d3e3e0468&amp;language=\2</url>" dest="5"> <expression>(.+)::(.+)</expression> </RegExp> <expression noclean="1" /> @@ -449,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=45ab4cebe57ae11c2ee50c87005ddfe8&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=f090bb54758cabf231fb605d3e3e0468&amp;language=en</url>" dest="2"> <expression>^$</expression> </RegExp> <RegExp input="$$9" output="$$9" dest="2"> @@ -469,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=45ab4cebe57ae11c2ee50c87005ddfe8</url>" dest="2"> + <RegExp input="$$9" output="<url function="ParseTMDBAllTrailer" cache="tmdb-trailer-$$8.json">https://api.tmdb.org/3/movie/$$8/trailers?api_key=f090bb54758cabf231fb605d3e3e0468</url>" dest="2"> <expression>^$</expression> </RegExp> <RegExp input="$$9" output="$$9" dest="2"> @@ -495,10 +495,10 @@ <RegExp input="$$1" output="\2" dest="11"> <expression>(.+)::(.+)</expression> </RegExp> - <RegExp input="$$1" output="<url function="ParseTMDBBaseImageURL" cache="tmdb-config.json">https://api.tmdb.org/3/configuration?api_key=45ab4cebe57ae11c2ee50c87005ddfe8</url>" dest="5"> + <RegExp input="$$1" output="<url function="ParseTMDBBaseImageURL" cache="tmdb-config.json">https://api.tmdb.org/3/configuration?api_key=f090bb54758cabf231fb605d3e3e0468</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+"> + <RegExp input="$$1" output="<url function="ParseTMDBFanart" cache="tmdb-images-\1.json">https://api.tmdb.org/3/movie/\1/images?api_key=f090bb54758cabf231fb605d3e3e0468&amp;language=$$11&amp;include_image_language=$$11,en,null</url>" dest="5+"> <expression>(.+)::(.+)</expression> </RegExp> <expression noclean="1" /> @@ -524,10 +524,10 @@ <RegExp input="$$1" output="\1" dest="13"> <expression>(.+)::(.+)</expression> </RegExp> - <RegExp input="$$1" output="<url function="ParseTMDBBaseImageURL" cache="tmdb-config.json">https://api.tmdb.org/3/configuration?api_key=45ab4cebe57ae11c2ee50c87005ddfe8</url>" dest="5"> + <RegExp input="$$1" output="<url function="ParseTMDBBaseImageURL" cache="tmdb-config.json">https://api.tmdb.org/3/configuration?api_key=f090bb54758cabf231fb605d3e3e0468</url>" dest="5"> <expression /> </RegExp> - <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+"> + <RegExp input="$$1" output="<url function="ParseTMDBThumbs" cache="tmdb-images-\1.json">https://api.tmdb.org/3/movie/\1/images?api_key=f090bb54758cabf231fb605d3e3e0468&amp;language=$$11&amp;include_image_language=$$11,en,null</url>" dest="5+"> <expression>(.+)::(.+)</expression> </RegExp> <expression noclean="1" /> @@ -553,7 +553,7 @@ <RegExp input="$$9" output="$$10" dest="2"> <expression>^$</expression> </RegExp> - <RegExp input="$$2" output="<url function="ParseFallbackTMDBThumbs">https://api.tmdb.org/3/movie/$$13/images?api_key=45ab4cebe57ae11c2ee50c87005ddfe8</url>" dest="2"> + <RegExp input="$$2" output="<url function="ParseFallbackTMDBThumbs">https://api.tmdb.org/3/movie/$$13/images?api_key=f090bb54758cabf231fb605d3e3e0468</url>" dest="2"> <expression>^$</expression> </RegExp> <expression noclean="1" /> @@ -586,11 +586,11 @@ <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"> + <RegExp input="$$1" output="<url function="ParseTMDBPremiered" cache="tmdb-\2-\1.json">https://api.tmdb.org/3/movie/\1?api_key=f090bb54758cabf231fb605d3e3e0468&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"> + <RegExp input="$$1" output="<url function="ParseTMDBPremiered" cache="tmdb-$INFO[tmdbcertcountry]-\1.json">https://api.tmdb.org/3/movie/\1?api_key=f090bb54758cabf231fb605d3e3e0468&amp;language=$INFO[tmdbcertcountry]</url>" dest="2"> <expression/> </RegExp> <expression>Keep Original</expression> diff --git a/addons/metadata.themoviedb.org/addon.xml b/addons/metadata.themoviedb.org/addon.xml index 7ddf041e14..b13291f201 100644 --- a/addons/metadata.themoviedb.org/addon.xml +++ b/addons/metadata.themoviedb.org/addon.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon id="metadata.themoviedb.org" name="The Movie Database" - version="5.1.3" + version="5.1.4" provider-name="Team Kodi"> <requires> <import addon="xbmc.metadata" version="2.1.0"/> diff --git a/addons/metadata.themoviedb.org/resources/settings.xml b/addons/metadata.themoviedb.org/resources/settings.xml index 5425952108..52b299a769 100644 --- a/addons/metadata.themoviedb.org/resources/settings.xml +++ b/addons/metadata.themoviedb.org/resources/settings.xml @@ -3,7 +3,7 @@ <setting label="30005" type="bool" id="keeporiginaltitle" default="false"/> <setting label="30000" type="bool" id="fanart" default="true"/> <setting label="30004" type="bool" id="trailer" default="true"/> - <setting label="30002" type="select" values="ar-AE|ar-SA|bg|bn-BD|ca-ES|ch-GU|cs|da|de|el|en|eo-EO|es|es-MX|eu-ES|fa|fa-ir|fi|fr|fr-CA|he|hi-IN|hr|hu|id-ID|it|ja|ka-GE|ko|lt-LT|lv-LV|ml-IN|nb|nl|no|pl|pt|pt-br|ro|ru|sk|sl|sr|sv|ta-IN|th|tr|uk|vi-VN|zh-cn|zh-tw" id="language" default="en"/> + <setting label="30002" type="select" values="ar-AE|ar-SA|bg|bn-BD|ca-ES|ch-GU|cs|da|de|el|en|eo-EO|es|es-MX|eu-ES|fa|fa-ir|fi|fr|fr-CA|gl|he|hi-IN|hr|hu|id-ID|it|ja|ka-GE|ko|lt-LT|lv-LV|ml-IN|nb|nl|no|pl|pt|pt-br|ro|ru|sk|sl|sr|sv|ta-IN|th|tr|uk|vi-VN|zh-cn|zh-tw" id="language" default="en"/> <setting label="30006" type="select" values="au|bg|br|ca|cz|ge|de|dk|ee|es|fi|fr|gb|gr|hr|hu|id|il|in|it|ir|jp|kr|lt|lv|mx|nl|no|pl|pt|ru|si|sv|th|tr|ua|us|vn|zh" id="tmdbcertcountry" default="us"/> <setting label="30003" type="labelenum" values="TMDb|IMDb" id="RatingS" default="TMDb"/> <setting label="30007" type="bool" id="imdbanyway" visible="eq(-1,0)" default="false"/> diff --git a/addons/metadata.themoviedb.org/tmdb.xml b/addons/metadata.themoviedb.org/tmdb.xml index 6156043167..f37bfce1bb 100644 --- a/addons/metadata.themoviedb.org/tmdb.xml +++ b/addons/metadata.themoviedb.org/tmdb.xml @@ -1,7 +1,7 @@ -<?xml version="1.0" encoding="UTF-8"?> +<?xml version="1.0" encoding="UTF-8"?> <scraper framework="1.1" date="2012-01-16"> <CreateSearchUrl dest="3"> - <RegExp input="$$1" output="<url>https://api.tmdb.org/3/search/movie?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;query=\1&amp;year=$$4&amp;language=$INFO[language]</url>" dest="3"> + <RegExp input="$$1" output="<url>https://api.tmdb.org/3/search/movie?api_key=f090bb54758cabf231fb605d3e3e0468&amp;query=\1&amp;year=$$4&amp;language=$INFO[language]</url>" dest="3"> <RegExp input="$$2" output="\1" dest="4"> <expression clear="yes">(.+)</expression> </RegExp> @@ -9,34 +9,34 @@ </RegExp> </CreateSearchUrl> <NfoUrl dest="3"> - <RegExp input="$$1" output="<details><url>https://api.tmdb.org/3/movie/\2?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=$INFO[language]</url><id>\2</id></details>" dest="3"> + <RegExp input="$$1" output="<details><url>https://api.tmdb.org/3/movie/\2?api_key=f090bb54758cabf231fb605d3e3e0468&amp;language=$INFO[language]</url><id>\2</id></details>" dest="3"> <expression clear="yes" noclean="1">(themoviedb.org/movie/)([0-9]*)</expression> </RegExp> - <RegExp input="$$1" output="<details><url cache="tmdb-$INFO[language]-tt\1.json">https://api.tmdb.org/3/movie/tt\1?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=$INFO[language]</url><id>tt\1</id></details>" dest="3"> + <RegExp input="$$1" output="<details><url cache="tmdb-$INFO[language]-tt\1.json">https://api.tmdb.org/3/movie/tt\1?api_key=f090bb54758cabf231fb605d3e3e0468&amp;language=$INFO[language]</url><id>tt\1</id></details>" dest="3"> <expression>imdb....?/title/tt([0-9]+)</expression> </RegExp> - <RegExp input="$$1" output="<details><url cache="tmdb-$INFO[language]-tt\1.json">https://api.tmdb.org/3/movie/tt\1?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=$INFO[language]</url><id>tt\1</id></details>" dest="3"> + <RegExp input="$$1" output="<details><url cache="tmdb-$INFO[language]-tt\1.json">https://api.tmdb.org/3/movie/tt\1?api_key=f090bb54758cabf231fb605d3e3e0468&amp;language=$INFO[language]</url><id>tt\1</id></details>" dest="3"> <expression>imdb....?/Title\?t{0,2}([0-9]+)</expression> </RegExp> </NfoUrl> <GetSearchResults dest="8"> <RegExp input="$$3" output="<results>\1</results>" dest="8"> - <RegExp input="$$1" output="<entity><title>\3</title><id>\2</id><year>\1</year><url cache="tmdb-$INFO[language]-\2.json">https://api.tmdb.org/3/movie/\2?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=$INFO[language]</url></entity>" dest="3"> + <RegExp input="$$1" output="<entity><title>\3</title><id>\2</id><year>\1</year><url cache="tmdb-$INFO[language]-\2.json">https://api.tmdb.org/3/movie/\2?api_key=f090bb54758cabf231fb605d3e3e0468&amp;language=$INFO[language]</url></entity>" dest="3"> <expression repeat="yes">"release_date":"([0-9]+)-.*?"id":([0-9]*),"original_title":"[^"]*","original_language":"[^"]*","title":"([^"]*)"</expression> </RegExp> - <RegExp input="$$1" output="<entity><title>\3</title><id>\2</id><year>\1</year><url cache="tmdb-$INFO[language]-\2.json">https://api.tmdb.org/3/movie/\2?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=$INFO[language]</url></entity>" dest="3+"> + <RegExp input="$$1" output="<entity><title>\3</title><id>\2</id><year>\1</year><url cache="tmdb-$INFO[language]-\2.json">https://api.tmdb.org/3/movie/\2?api_key=f090bb54758cabf231fb605d3e3e0468&amp;language=$INFO[language]</url></entity>" dest="3+"> <expression repeat="yes">"release_date":"([0-9]+)-.*?"id":([0-9]*),"original_title":"([^"]*)","original_language":"[^"]*"</expression> </RegExp> - <RegExp input="$$1" output="<entity><title>\2</title><id>\1</id><url cache="tmdb-$INFO[language]-\1.json">https://api.tmdb.org/3/movie/\1?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=$INFO[language]</url></entity>" dest="3+"> + <RegExp input="$$1" output="<entity><title>\2</title><id>\1</id><url cache="tmdb-$INFO[language]-\1.json">https://api.tmdb.org/3/movie/\1?api_key=f090bb54758cabf231fb605d3e3e0468&amp;language=$INFO[language]</url></entity>" dest="3+"> <expression repeat="yes">"release_date":null.*?"id":([0-9]*),"original_title":"([^"]*)","original_language":"[^"]*"</expression> </RegExp> - <RegExp input="$$1" output="<entity><title>\2</title><id>\1</id><year>\3</year><url cache="tmdb-$INFO[language]-\1.json">https://api.tmdb.org/3/movie/\1?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=$INFO[language]</url></entity>" dest="3+"> + <RegExp input="$$1" output="<entity><title>\2</title><id>\1</id><year>\3</year><url cache="tmdb-$INFO[language]-\1.json">https://api.tmdb.org/3/movie/\1?api_key=f090bb54758cabf231fb605d3e3e0468&amp;language=$INFO[language]</url></entity>" dest="3+"> <expression repeat="yes">"id":([0-9]*).*?title":"[^"]*".*?original_title":"([^"]*)".*?"release_date":"([0-9]+)-</expression> </RegExp> - <RegExp input="$$1" output="<entity><title>\2</title><id>\1</id><year>\3</year><url cache="tmdb-$INFO[language]-\1.json">https://api.tmdb.org/3/movie/\1?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=$INFO[language]</url></entity>" dest="3+"> + <RegExp input="$$1" output="<entity><title>\2</title><id>\1</id><year>\3</year><url cache="tmdb-$INFO[language]-\1.json">https://api.tmdb.org/3/movie/\1?api_key=f090bb54758cabf231fb605d3e3e0468&amp;language=$INFO[language]</url></entity>" dest="3+"> <expression repeat="yes">"id":([0-9]*).*?title":"([^"]*)".*?original_title":"[^"]*".*?"release_date":"([0-9]+)-</expression> </RegExp> - <RegExp input="$$1" output="<entity><title>\2</title><id>\1</id><url cache="tmdb-$INFO[language]-\1.json">https://api.tmdb.org/3/movie/\1?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=$INFO[language]</url></entity>" dest="3+"> + <RegExp input="$$1" output="<entity><title>\2</title><id>\1</id><url cache="tmdb-$INFO[language]-\1.json">https://api.tmdb.org/3/movie/\1?api_key=f090bb54758cabf231fb605d3e3e0468&amp;language=$INFO[language]</url></entity>" dest="3+"> <expression repeat="yes">"id":([0-9]*).*?title":"([^"]*)".*?original_title":"[^"]*".*?"release_date":null</expression> </RegExp> <expression noclean="1" /> @@ -74,7 +74,7 @@ <RegExp input="$$1" output="\1" dest="10"> <expression clear="yes" noclean="1">"runtime":([0-9]+)</expression> </RegExp> - <RegExp input="$$10" output="<url function="ParseFallbackTMDBRuntime" cache="tmdb-en-$$2.json">https://api.tmdb.org/3/movie/$$2?api_key=45ab4cebe57ae11c2ee50c87005ddfe8&amp;language=en</url>" dest="5+"> + <RegExp input="$$10" output="<url function="ParseFallbackTMDBRuntime" cache="tmdb-en-$$2.json">https://api.tmdb.org/3/movie/$$2?api_key=f090bb54758cabf231fb605d3e3e0468&amp;language=en</url>" dest="5+"> <expression>^$</expression> </RegExp> <RegExp input="$$10" output="<runtime>\1</runtime>" dest="5+"> diff --git a/addons/metadata.tvdb.com/addon.xml b/addons/metadata.tvdb.com/addon.xml index b39891ef14..ad186db03d 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.9" + version="3.0.12" 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 7066da2f46..6418f6b457 100644 --- a/addons/metadata.tvdb.com/changelog.txt +++ b/addons/metadata.tvdb.com/changelog.txt @@ -1,3 +1,12 @@ +[B]3.0.12[/B] +- Fixed: DVD and Absolute episode ordering fixes + +[B]3.0.11[/B] +- Fixed: Use first aired episode date when firstAired field is missing (thx to Smeulf) + +[B]3.0.10[/B] +- Fixed: Use the year in the title as fallback when no firstAired field, to reduce mismatches + [B]3.0.9[/B] - Fixed: Character encoding fixes (part 2) diff --git a/addons/metadata.tvdb.com/tvdb.xml b/addons/metadata.tvdb.com/tvdb.xml index 6fc8144d7d..763fda8933 100644 --- a/addons/metadata.tvdb.com/tvdb.xml +++ b/addons/metadata.tvdb.com/tvdb.xml @@ -84,8 +84,8 @@ <!-- input : $$2=search url --> <!-- output: <results><entity><title>*</title><year>*</year><language>*</language><url>*</url><id>*</id></entity>*</results> --> <GetSearchResultsAuth dest="6" clearbuffers="no"> - <RegExp input="$$1" output="<series><id>\3</id><seriesName>\4</seriesName><aliases>\1</aliases><firstAired>\2</firstAired></series>" dest="4"> - <expression repeat="yes" fixchars="1,4">"aliases":\s*?\[([^]]*)\],\s*?"banner":\s*?"[^"]*",\s*?"firstAired":\s*?"([^"]*)",\s*?"id":\s*?(\d+),\s*?"network":\s*?"[^"]*",\s*?"overview":\s*?(?:"[^}]*"|null),\s*?"seriesName":\s*?"([^}]*)",\s*?"slug":\s*?"[^"]*"</expression> + <RegExp input="$$1" output="<series><id>\3</id><seriesName>\4</seriesName><aliases>\1</aliases><firstAired>\2</firstAired><year>\5</year></series>" dest="4"> + <expression repeat="yes" fixchars="1,4">"aliases":\s*?\[([^]]*)\],\s*?"banner":\s*?"[^"]*",\s*?"firstAired":\s*?"([^"]*)",\s*?"id":\s*?(\d+),\s*?"network":\s*?"[^"]*",\s*?"overview":\s*?(?:"[^}]*"|null),\s*?"seriesName":\s*?"([^}]*?(?:\(([0-9]{4})\))?)",\s*?"slug":\s*?"[^"]*"</expression> </RegExp> <RegExp input="" output="" dest="6"> <expression/> @@ -136,7 +136,12 @@ <xsl:param name="title"/> <entity> <title><xsl:value-of select="$title"/></title> - <year><xsl:value-of select="substring(firstAired,1,4)"/></year> + <year> + <xsl:choose> + <xsl:when test="firstAired!=''"><xsl:value-of select="substring(firstAired,1,4)"/></xsl:when> + <xsl:otherwise><xsl:value-of select="year"/></xsl:otherwise> + </xsl:choose> + </year> <language>$$16</language> <url><xsl:attribute name="cache"><xsl:value-of select="id"/>-$INFO[language].json</xsl:attribute>https://api.thetvdb.com/series/<xsl:value-of select="id"/>|Authorization=Bearer%20$$19&accept-language=$INFO[language]</url> <id><xsl:value-of select="id"/></id> @@ -175,7 +180,10 @@ <expression clear="yes">"seriesName":\s*?null,\s*?"aliases"</expression> </RegExp> <RegExp input="$$1" output="<premiered>\1</premiered>" dest="4+"> - <expression>"firstAired":\s*?"([^"]*)",</expression> + <expression>"firstAired":\s*?"([^"]+)",</expression> + </RegExp> + <RegExp input="$$1" output="<url function="GetPremieredFromFirstEp">https://api.thetvdb.com/series/$$2/episodes/query?airedSeason=1&airedEpisode=1|Authorization=Bearer%20$$19&amp;accept-language=$INFO[language]</url>" dest="4+"> + <expression>"firstAired":\s*?"",</expression> </RegExp> <RegExp input="$$1" output="<runtime>\1</runtime>" dest="4+"> <expression>"runtime":\s*?"([^"]*)",</expression> @@ -243,6 +251,14 @@ <expression noclean="1" fixchars="1"/> </RegExp> </GetDetails> + <GetPremieredFromFirstEp dest="3" clearbuffers="no"> + <RegExp input="$$4" output="<details>\1</details>" dest="3"> + <RegExp input="$$1" output="<premiered>\1</premiered>" dest="4"> + <expression clear="yes">"firstAired":\s*?"([^"]+)"</expression> + </RegExp> + <expression noclean="1"/> + </RegExp> + </GetPremieredFromFirstEp> <GetFallbackDetails dest="3" clearbuffers="no"> <RegExp input="$$4" output="<details>\1</details>" dest="3"> <RegExp input="$$14" output="$$5" dest="4"> @@ -549,7 +565,7 @@ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*"/> - <xsl:key name="EpisodesByDVDnumber" match="Episode" use="concat(DVD_season,',',substring-before(DVD_episodenumber,'.'))"/> + <xsl:key name="EpisodesByDVDnumber" match="Episode" use="concat(DVD_season,',',substring-before(concat(DVD_episodenumber,'.'),'.'))"/> <xsl:key name="EpisodesBySeason" match="Episode" use="SeasonNumber"/> <xsl:variable name="title-divider" select="' / '"/> @@ -575,10 +591,10 @@ <xsl:choose> <xsl:when test="'$INFO[dvdorder]'!='true'"> <xsl:choose> - <xsl:when test="('$INFO[absolutenumber]'='true') and ((SeasonNumber>0) or (absolute_number!=''))"> + <xsl:when test="('$INFO[absolutenumber]'='true') and ((SeasonNumber>0) or ((absolute_number!='') and (absolute_number!=0)))"> <epnum> <xsl:choose> - <xsl:when test="absolute_number!=''"><xsl:value-of select="absolute_number"/></xsl:when> + <xsl:when test="(absolute_number!='') and (absolute_number!=0)"><xsl:value-of select="absolute_number"/></xsl:when> <xsl:otherwise><xsl:value-of select="substring-before(substring-after($SeasonCounts, concat('|S', SeasonNumber, '|')), '|') + EpisodeNumber"/></xsl:otherwise> </xsl:choose> </epnum> @@ -590,12 +606,12 @@ </xsl:when> <xsl:otherwise> <xsl:choose> - <xsl:when test="(DVD_episodenumber!='') and (DVD_season!='')"> + <xsl:when test="((DVD_episodenumber!='') and (DVD_season!='')) and ((DVD_episodenumber!=0) or (DVD_season!=0))"> <epnum><xsl:value-of select="DVD_episodenumber"/></epnum> <season><xsl:value-of select="DVD_season"/></season> </xsl:when> <xsl:otherwise> - <epnum><xsl:value-of select="EpisodeNumber"/><xsl:if test="key('EpisodesByDVDnumber', concat(SeasonNumber,',',EpisodeNumber))">.<xsl:value-of select="count(key('EpisodesByDVDnumber', concat(SeasonNumber,',',EpisodeNumber))[(DVD_episodenumber!='') and (substring-after(DVD_episodenumber,'.')!='0')])+1"/></xsl:if></epnum> + <epnum><xsl:value-of select="EpisodeNumber"/><xsl:if test="key('EpisodesByDVDnumber', concat(SeasonNumber,',',EpisodeNumber))">.<xsl:value-of select="count(key('EpisodesByDVDnumber', concat(SeasonNumber,',',EpisodeNumber))[(DVD_episodenumber!='') and number(substring-after(concat(DVD_episodenumber,'.0'),'.'))>0])+1"/></xsl:if></epnum> <season><xsl:value-of select="SeasonNumber"/></season> </xsl:otherwise> </xsl:choose> @@ -715,7 +731,7 @@ <expression>"dvdSeason":\s*?(?:(\d+)|null),</expression> </RegExp> <RegExp input="$$1" output="<dvdEpisodeNumber>\1</dvdEpisodeNumber>" dest="10+"> - <expression>"dvdEpisodeNumber":\s*?(?:(\d+)|null),</expression> + <expression>"dvdEpisodeNumber":\s*?(?:([\d\.]+)|null),</expression> </RegExp> <RegExp input="$$1" output="<absoluteNumber>\1</absoluteNumber>" dest="10+"> <expression>"absoluteNumber":\s*?(?:(\d+)|null),</expression> @@ -813,7 +829,7 @@ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output indent="yes"/> <xsl:strip-space elements="*"/> - <xsl:key name="EpisodesByDVDnumber" match="current/Episode" use="concat(dvdSeason,',',substring-before(dvdEpisodeNumber,'.'))"/> + <xsl:key name="EpisodesByDVDnumber" match="current/Episode" use="concat(dvdSeason,',',substring-before(concat(dvdEpisodeNumber,'.'),'.'))"/> <xsl:variable name="SeasonCounts"> <xsl:if test="'$INFO[absolutenumber]'='true'">$$12</xsl:if> </xsl:variable> @@ -875,10 +891,10 @@ <xsl:choose> <xsl:when test="'$INFO[dvdorder]'!='true'"> <xsl:choose> - <xsl:when test="('$INFO[absolutenumber]'='true') and (($FirstEpisode/airedSeason>0) or ($FirstEpisode/absoluteNumber!=''))"> + <xsl:when test="('$INFO[absolutenumber]'='true') and (($FirstEpisode/airedSeason>0) or (($FirstEpisode/absoluteNumber!='') and ($FirstEpisode/absoluteNumber!=0)))"> <episode> <xsl:choose> - <xsl:when test="$FirstEpisode/absoluteNumber!=''"><xsl:value-of select="$FirstEpisode/absoluteNumber"/></xsl:when> + <xsl:when test="($FirstEpisode/absoluteNumber!='') and ($FirstEpisode/absoluteNumber!=0)"><xsl:value-of select="$FirstEpisode/absoluteNumber"/></xsl:when> <xsl:otherwise><xsl:value-of select="substring-before(substring-after($SeasonCounts, concat('|S', $FirstEpisode/airedSeason, '|')), '|') + $FirstEpisode/airedEpisodeNumber"/></xsl:otherwise> </xsl:choose> </episode> @@ -896,8 +912,8 @@ </xsl:when> <xsl:otherwise> <xsl:choose> - <xsl:when test="($FirstEpisode/dvdEpisodeNumber='') or ($FirstEpisode/dvdSeason='')"> - <episode><xsl:value-of select="$FirstEpisode/airedEpisodeNumber"/><xsl:if test="key('EpisodesByDVDnumber', concat($FirstEpisode/airedSeason,',',$FirstEpisode/airedEpisodeNumber))">.<xsl:value-of select="count(key('EpisodesByDVDnumber', concat($FirstEpisode/airedSeason,',',$FirstEpisode/airedEpisodeNumber))[(dvdEpisodeNumber!='') and (substring-after(dvdEpisodeNumber,'.')!='0')])+1"/></xsl:if></episode> + <xsl:when test="(($FirstEpisode/dvdEpisodeNumber='') or ($FirstEpisode/dvdSeason='')) or (($FirstEpisode/dvdEpisodeNumber=0) and ($FirstEpisode/dvdSeason=0))"> + <episode><xsl:value-of select="$FirstEpisode/airedEpisodeNumber"/><xsl:if test="key('EpisodesByDVDnumber', concat($FirstEpisode/airedSeason,',',$FirstEpisode/airedEpisodeNumber))">.<xsl:value-of select="count(key('EpisodesByDVDnumber', concat($FirstEpisode/airedSeason,',',$FirstEpisode/airedEpisodeNumber))[(dvdEpisodeNumber!='') and number(substring-after(concat(dvdEpisodeNumber,'.0'),'.'))>0])+1"/></xsl:if></episode> <season><xsl:value-of select="$FirstEpisode/airedSeason"/></season> </xsl:when> <xsl:otherwise> @@ -1105,4 +1121,20 @@ <expression noclean="1" fixchars="1"/> </RegExp> </ParseEpisodeDetails> + <GetIMDBRatingsById dest="5" clearbuffers="no"> + <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"> + <expression clear="yes">\|default$</expression> + </RegExp> + </GetIMDBRatingsById> + <ParseIMDBRatings dest="5" clearbuffers="no"> + <RegExp input="$$2" output="<details>\1</details>" dest="5"> + <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> </scraper> diff --git a/addons/repository.xbmc.org/addon.xml b/addons/repository.xbmc.org/addon.xml index 964bc9681f..66dce54571 100644 --- a/addons/repository.xbmc.org/addon.xml +++ b/addons/repository.xbmc.org/addon.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon id="repository.xbmc.org" name="Kodi Add-on repository" - version="3.1.2" + version="3.1.4" provider-name="Team Kodi"> <requires> <import addon="xbmc.addon" version="12.0.0"/> diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po index e53ad89714..1f862ceaa9 100644 --- a/addons/resource.language.en_gb/resources/strings.po +++ b/addons/resource.language.en_gb/resources/strings.po @@ -10277,11 +10277,7 @@ msgctxt "#19194" msgid "Continue?" msgstr "" -#. label for a context menu entry for pvr client specific actions -#: xbmc/pvr/PVRContextMenus.cpp -msgctxt "#19195" -msgid "Client actions" -msgstr "" +#empty string with id 19195 #. value for "pvr client specific actions" dialog headers #: xbmc/pvr/PVRGUIActions.cpp diff --git a/addons/service.xbmc.versioncheck/.gitignore b/addons/service.xbmc.versioncheck/.gitignore deleted file mode 100644 index dd5a590e7c..0000000000 --- a/addons/service.xbmc.versioncheck/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -*.pyo -.project -.pydevproject -pysrc -*.pyc -.settings -.idea diff --git a/addons/service.xbmc.versioncheck/addon.xml b/addons/service.xbmc.versioncheck/addon.xml index d34201075a..1184bd71c5 100644 --- a/addons/service.xbmc.versioncheck/addon.xml +++ b/addons/service.xbmc.versioncheck/addon.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon id="service.xbmc.versioncheck" name="Version Check" - version="0.3.26" + version="0.3.27" provider-name="Team Kodi"> <requires> <import addon="xbmc.python" version="2.1.0"/> diff --git a/addons/service.xbmc.versioncheck/changelog.txt b/addons/service.xbmc.versioncheck/changelog.txt index d453632c42..89e88d9bed 100644 --- a/addons/service.xbmc.versioncheck/changelog.txt +++ b/addons/service.xbmc.versioncheck/changelog.txt @@ -1,4 +1,4 @@ -v0.3.256 +v0.3.27 - Update version list v0.3.25 diff --git a/addons/service.xbmc.versioncheck/resources/versions.txt b/addons/service.xbmc.versioncheck/resources/versions.txt index a813f13f49..6dea1f5242 100644 --- a/addons/service.xbmc.versioncheck/resources/versions.txt +++ b/addons/service.xbmc.versioncheck/resources/versions.txt @@ -394,6 +394,30 @@ ], "beta": [ { + "major": "18", + "minor": "0", + "tag": "beta", + "tagversion":"3", + "revision": "20181002-c2e1b316f5", + "addon_support": "yes" + }, + { + "major": "18", + "minor": "0", + "tag": "beta", + "tagversion":"2", + "revision": "20180909-7868a27c6a", + "addon_support": "yes" + }, + { + "major": "18", + "minor": "0", + "tag": "beta", + "tagversion":"1", + "revision": "20180826-f21b477993", + "addon_support": "yes" + }, + { "major": "17", "minor": "0", "tag": "beta", diff --git a/addons/skin.estouchy/xml/DialogConfirm.xml b/addons/skin.estouchy/xml/DialogConfirm.xml index 84d938f75d..226b2dc497 100644 --- a/addons/skin.estouchy/xml/DialogConfirm.xml +++ b/addons/skin.estouchy/xml/DialogConfirm.xml @@ -52,33 +52,7 @@ <height>10</height> <info>System.Progressbar</info> </control> - <control type="grouplist" id="9000"> - <posx>20</posx> - <posy>240</posy> - <width>660</width> - <height>60</height> - <itemgap>10</itemgap> - <align>center</align> - <orientation>horizontal</orientation> - <onleft>9000</onleft> - <onright>9000</onright> - <onup>9000</onup> - <ondown>9000</ondown> - <control type="button" id="10"> - <description>OK button</description> - <width>200</width> - <include>ButtonInfoDialogsCommonValues</include> - </control> - <control type="button" id="11"> - <description>Cancel button</description> - <width>200</width> - <include>ButtonInfoDialogsCommonValues</include> - </control> - <control type="button" id="12"> - <description>Custom button</description> - <width>200</width> - <include>ButtonInfoDialogsCommonValues</include> - </control> - </control> + <include condition="!Window.IsVisible(yesnodialog)">YesNoExtendedButtons</include> + <include condition="Window.IsVisible(yesnodialog)">YesNoDefaultButtons</include> </controls> </window> diff --git a/addons/skin.estouchy/xml/Home.xml b/addons/skin.estouchy/xml/Home.xml index 0e5412fe98..9979e08a59 100644 --- a/addons/skin.estouchy/xml/Home.xml +++ b/addons/skin.estouchy/xml/Home.xml @@ -146,8 +146,8 @@ <height>120</height> <onleft>9002</onleft> <onright>9002</onright> - <onup>9001</onup> - <ondown>20</ondown> + <onup>9000</onup> + <ondown>9000</ondown> <pagecontrol></pagecontrol> <scrolltime>300</scrolltime> <orientation>Horizontal</orientation> diff --git a/addons/skin.estouchy/xml/Includes.xml b/addons/skin.estouchy/xml/Includes.xml index 4a63cc6015..5a714b9054 100644 --- a/addons/skin.estouchy/xml/Includes.xml +++ b/addons/skin.estouchy/xml/Includes.xml @@ -792,8 +792,8 @@ <height>760</height> <onleft>9000</onleft> <onright>9003</onright> - <onup>10</onup> - <ondown>10</ondown> + <onup>9002</onup> + <ondown>9002</ondown> <scrolltime>300</scrolltime> <orientation>vertical</orientation> <focusposition>1</focusposition> @@ -2521,6 +2521,61 @@ <include>MenuButtonCommonValues</include> </control> </include> + <include name="YesNoDefaultButtons"> + <control type="group"> + <posx>145</posx> + <posy>240</posy> + <width>660</width> + <height>60</height> + <visible>Window.IsVisible(yesnodialog)</visible> + <control type="button" id="11"> + <description>Yes button</description> + <posx>0</posx> + <posy>0</posy> + <width>200</width> + <include>ButtonInfoDialogsCommonValues</include> + </control> + <control type="button" id="10"> + <description>No button</description> + <posx>210</posx> + <posy>0</posy> + <width>200</width> + <include>ButtonInfoDialogsCommonValues</include> + </control> + </control> + </include> + <include name="YesNoExtendedButtons"> + <control type="grouplist" id="9000"> + <posx>20</posx> + <posy>240</posy> + <width>660</width> + <height>60</height> + <itemgap>10</itemgap> + <align>center</align> + <orientation>horizontal</orientation> + <onleft>9000</onleft> + <onright>9000</onright> + <onup>9000</onup> + <ondown>9000</ondown> + <visible>!Window.IsVisible(yesnodialog)</visible> + <control type="button" id="10"> + <description>OK button</description> + <width>200</width> + <include>ButtonInfoDialogsCommonValues</include> + </control> + <control type="button" id="11"> + <description>Cancel button</description> + <width>200</width> + <include>ButtonInfoDialogsCommonValues</include> + </control> + <control type="button" id="12"> + <description>Custom button</description> + <width>200</width> + <include>ButtonInfoDialogsCommonValues</include> + </control> + </control> + </include> + <include name="16x9_xPos_Relocation"> <animation effect="slide" start="0,0" end="213,0" time="0" condition="String.IsEqual(Skin.AspectRatio,16:9)">conditional</animation> </include> diff --git a/addons/skin.estuary/language/resource.language.en_gb/strings.po b/addons/skin.estuary/language/resource.language.en_gb/strings.po index e4dc1bc42f..40d7ed0aaf 100644 --- a/addons/skin.estuary/language/resource.language.en_gb/strings.po +++ b/addons/skin.estuary/language/resource.language.en_gb/strings.po @@ -759,3 +759,9 @@ msgstr "" msgctxt "#31166" msgid "Profile avatar" msgstr "" + +#. Label of a setting +#: /xml/SkinSettings.xml +msgctxt "#31167" +msgid "Animate background" +msgstr "" diff --git a/addons/skin.estuary/media/flags/audiocodec/alac.png b/addons/skin.estuary/media/flags/audiocodec/alac.png Binary files differindex 86cc09f837..a49527cf6a 100644 --- a/addons/skin.estuary/media/flags/audiocodec/alac.png +++ b/addons/skin.estuary/media/flags/audiocodec/alac.png diff --git a/addons/skin.estuary/media/flags/audiocodec/flac.png b/addons/skin.estuary/media/flags/audiocodec/flac.png Binary files differindex d73d635e1d..f173541ebd 100644 --- a/addons/skin.estuary/media/flags/audiocodec/flac.png +++ b/addons/skin.estuary/media/flags/audiocodec/flac.png diff --git a/addons/skin.estuary/media/flags/audiocodec/pcm.png b/addons/skin.estuary/media/flags/audiocodec/pcm.png Binary files differindex e73052768e..0c7a5bdeee 100644 --- a/addons/skin.estuary/media/flags/audiocodec/pcm.png +++ b/addons/skin.estuary/media/flags/audiocodec/pcm.png diff --git a/addons/skin.estuary/media/flags/audiocodec/pcm_bluray.png b/addons/skin.estuary/media/flags/audiocodec/pcm_bluray.png Binary files differindex e73052768e..30b4f8b138 100644 --- a/addons/skin.estuary/media/flags/audiocodec/pcm_bluray.png +++ b/addons/skin.estuary/media/flags/audiocodec/pcm_bluray.png diff --git a/addons/skin.estuary/media/flags/audiocodec/pcm_s16le.png b/addons/skin.estuary/media/flags/audiocodec/pcm_s16le.png Binary files differindex e73052768e..dc514806e3 100644 --- a/addons/skin.estuary/media/flags/audiocodec/pcm_s16le.png +++ b/addons/skin.estuary/media/flags/audiocodec/pcm_s16le.png diff --git a/addons/skin.estuary/media/flags/audiocodec/pcm_s24le.png b/addons/skin.estuary/media/flags/audiocodec/pcm_s24le.png Binary files differindex e73052768e..81ceacc06d 100644 --- a/addons/skin.estuary/media/flags/audiocodec/pcm_s24le.png +++ b/addons/skin.estuary/media/flags/audiocodec/pcm_s24le.png diff --git a/addons/skin.estuary/xml/Custom_1105_MusicOSDSettings.xml b/addons/skin.estuary/xml/Custom_1105_MusicOSDSettings.xml index 443afdefa1..a86d24f929 100644 --- a/addons/skin.estuary/xml/Custom_1105_MusicOSDSettings.xml +++ b/addons/skin.estuary/xml/Custom_1105_MusicOSDSettings.xml @@ -31,6 +31,12 @@ <onclick>Skin.ToggleSetting(hide_background_fanart)</onclick> <selected>!Skin.HasSetting(hide_background_fanart)</selected> </control> + <control type="radiobutton" id="5002"> + <label>$LOCALIZE[31167]</label> + <include>DialogSettingButton</include> + <onclick>Skin.ToggleSetting(animate_background_fanart)</onclick> + <selected>Skin.HasSetting(animate_background_fanart)</selected> + </control> <control type="button" id="5004"> <width>600</width> <include>DialogSettingButton</include> diff --git a/addons/skin.estuary/xml/DialogVideoInfo.xml b/addons/skin.estuary/xml/DialogVideoInfo.xml index 991358e1f8..283757d351 100644 --- a/addons/skin.estuary/xml/DialogVideoInfo.xml +++ b/addons/skin.estuary/xml/DialogVideoInfo.xml @@ -382,10 +382,12 @@ <align>center</align> <orientation>horizontal</orientation> <scrolltime tween="quadratic">200</scrolltime> - <include content="InfoDialogButton"> + <include content="InfoDialogToggleButton"> <param name="id" value="8" /> - <param name="icon" value="icons/infodialogs/play.png" /> - <param name="label" value="$LOCALIZE[208]" /> + <param name="icon_on" value="icons/filemanager.png" /> + <param name="icon_off" value="icons/infodialogs/play.png" /> + <param name="selected" value="String.IsEqual(ListItem.DBType,tvshow) | String.IsEqual(ListItem.DBType,season)" /> + <param name="label" value="$VAR[VideoInfoPlayButtonLabelVar]" /> </include> <include content="InfoDialogButton"> <param name="id" value="11" /> diff --git a/addons/skin.estuary/xml/Home.xml b/addons/skin.estuary/xml/Home.xml index 18fc6b22dd..3867952497 100644 --- a/addons/skin.estuary/xml/Home.xml +++ b/addons/skin.estuary/xml/Home.xml @@ -427,7 +427,7 @@ <include content="ImageWidget" condition="!System.HasPVRAddon"> <param name="text_label" value="$LOCALIZE[31143]" /> <param name="button_label" value="$LOCALIZE[31144]" /> - <param name="button_onclick" value="ActivateWindow(addonbrowser,addons://user/xbmc.pvrclient,return)"/> + <param name="button_onclick" value="ActivateWindow(addonbrowser,addons://all/xbmc.pvrclient,return)"/> <param name="button_id" value="12400"/> <param name="button2_onclick" value="Skin.SetBool(HomeMenuNoTVButton)"/> </include> @@ -500,7 +500,7 @@ <include content="ImageWidget" condition="!System.HasPVRAddon"> <param name="text_label" value="$LOCALIZE[31143]" /> <param name="button_label" value="$LOCALIZE[31144]" /> - <param name="button_onclick" value="ActivateWindow(addonbrowser,addons://user/xbmc.pvrclient,return)"/> + <param name="button_onclick" value="ActivateWindow(addonbrowser,addons://all/xbmc.pvrclient,return)"/> <param name="button_id" value="13400"/> <param name="button2_onclick" value="Skin.SetBool(HomeMenuNoRadioButton)"/> </include> @@ -744,6 +744,7 @@ <param name="widget_header" value="$LOCALIZE[20094]"/> <param name="widget_target" value="pictures"/> <param name="list_id" value="4100"/> + <param name="icon_height" value="110"/> </include> </control> </control> @@ -767,8 +768,8 @@ </control> <include content="ImageWidget"> <param name="text_label" value="$LOCALIZE[31162]" /> - <param name="button_label" value="$LOCALIZE[31110]" /> - <param name="button_onclick" value="ActivateWindow(games)"/> + <param name="button_label" value="$LOCALIZE[31144]" /> + <param name="button_onclick" value="ActivateWindow(addonbrowser,addons://all/category.gameaddons,return)"/> <param name="button_id" value="17100"/> <param name="visible" value="!Integer.IsGreater(Container(17001).NumItems,0)"/> <param name="button2_onclick" value="Skin.SetBool(HomeMenuNoGamesButton)"/> diff --git a/addons/skin.estuary/xml/MusicVisualisation.xml b/addons/skin.estuary/xml/MusicVisualisation.xml index ca3d6ef094..0df345c39f 100644 --- a/addons/skin.estuary/xml/MusicVisualisation.xml +++ b/addons/skin.estuary/xml/MusicVisualisation.xml @@ -2,25 +2,37 @@ <window> <defaultcontrol></defaultcontrol> <backgroundcolor>background</backgroundcolor> + <onload condition="System.HasAddon(script.artistslideshow) + !Skin.HasSetting(hide_background_fanart)">RunScript(script.artistslideshow)</onload> <controls> <control type="visualisation" id="2"> <include>FullScreenDimensions</include> <visible>Player.HasAudio</visible> </control> - <control type="image"> - <left>0</left> - <top>0</top> - <width>100%</width> - <height>100%</height> - <aspectratio>scale</aspectratio> - <fadetime>400</fadetime> - <animation effect="fade" start="0" end="100" time="400">WindowOpen</animation> - <animation effect="fade" start="100" end="0" time="300">WindowClose</animation> - <texture background="true" colordiffuse="88FFFFFF">$INFO[Player.Art(fanart)]</texture> + <control type="group"> + <depth>DepthBackground</depth> + <include>FullScreenDimensions</include> <visible>!Skin.HasSetting(hide_background_fanart)</visible> + <animation effect="zoom" start="105" end="130" center="auto" time="10000" tween="sine" easing="inout" pulse="true" condition="Skin.HasSetting(animate_background_fanart)">Conditional</animation> + <animation effect="slide" start="-30,-30" end="30,30" time="6000" tween="sine" easing="inout" pulse="true" condition="Skin.HasSetting(animate_background_fanart)">Conditional</animation> + <control type="image"> + <aspectratio>scale</aspectratio> + <fadetime>400</fadetime> + <animation effect="fade" start="0" end="100" time="400">WindowOpen</animation> + <animation effect="fade" start="100" end="0" time="300">WindowClose</animation> + <texture background="true" colordiffuse="88FFFFFF">$INFO[Player.Art(fanart)]</texture> + </control> + <control type="multiimage"> + <aspectratio>scale</aspectratio> + <timeperimage>10000</timeperimage> + <randomize>true</randomize> + <fadetime>600</fadetime> + <loop>yes</loop> + <imagepath background="true">$INFO[Window(Visualisation).Property(ArtistSlideshow)]</imagepath> + <visible>System.HasAddon(script.artistslideshow)</visible> + </control> </control> <control type="group"> - <animation effect="fade" start="100" end="30" time="0" condition="!String.IsEmpty(Player.Art(fanart)) | Visualisation.Enabled">Conditional</animation> + <animation effect="fade" start="100" end="30" time="0" condition="!Skin.HasSetting(hide_background_fanart) + [!String.IsEmpty(Player.Art(fanart)) | Visualisation.Enabled | System.HasAddon(script.artistslideshow)]">Conditional</animation> <include>ColoredBackgroundImages</include> </control> <control type="group"> diff --git a/addons/skin.estuary/xml/Variables.xml b/addons/skin.estuary/xml/Variables.xml index 5771750885..bee39ed5b5 100644 --- a/addons/skin.estuary/xml/Variables.xml +++ b/addons/skin.estuary/xml/Variables.xml @@ -251,6 +251,10 @@ <value condition="!String.IsEmpty(ListItem.Title)">$INFO[ListItem.Title]$INFO[ListItem.Year, ([COLOR grey],[/COLOR])]</value> <value>$INFO[ListItem.Label]$INFO[ListItem.Year, ([COLOR grey],[/COLOR])]</value> </variable> + <variable name="VideoInfoPlayButtonLabelVar"> + <value condition="String.IsEqual(ListItem.DBType,tvshow) | String.IsEqual(ListItem.DBType,season)">$LOCALIZE[1024]</value> + <value>$LOCALIZE[208]</value> + </variable> <variable name="VideoInfoSubLabelVar"> <value condition="String.IsEqual(ListItem.DBType,episode)">$INFO[ListItem.Season]$INFO[ListItem.Episode,[COLOR grey]x[/COLOR],: ]$INFO[ListItem.TVShowTitle]</value> <value condition="String.IsEqual(ListItem.DBType,movie)">$INFO[ListItem.Tagline,[I],[/I]]</value> diff --git a/cmake/modules/FindMariaDBClient.cmake b/cmake/modules/FindMariaDBClient.cmake index 8a28670be8..7530ab5021 100644 --- a/cmake/modules/FindMariaDBClient.cmake +++ b/cmake/modules/FindMariaDBClient.cmake @@ -21,15 +21,25 @@ else() set(EXTRA_FIND_ARGS) endif() -find_path(MARIADBCLIENT_INCLUDE_DIR NAMES mariadb/mysql.h mariadb/server/mysql.h) -find_library(MARIADBCLIENT_LIBRARY_RELEASE NAMES mariadbclient libmariadb +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_MARIADBCLIENT mariadb QUIET) +endif() + + +find_path(MARIADBCLIENT_INCLUDE_DIR NAMES mariadb/mysql.h mariadb/server/mysql.h + PATHS ${PC_MARIADBCLIENT_INCLUDEDIR}) +find_library(MARIADBCLIENT_LIBRARY_RELEASE NAMES mariadbclient mariadb + PATHS ${PC_MARIADBCLIENT_LIBDIR} PATH_SUFFIXES mariadb ${EXTRA_FIND_ARGS}) -find_library(MARIADBCLIENT_LIBRARY_DEBUG NAMES mariadbclient libmariadb +find_library(MARIADBCLIENT_LIBRARY_DEBUG NAMES mariadbclient mariadb + PATHS ${PC_MARIADBCLIENT_LIBDIR} PATH_SUFFIXES mariadb ${EXTRA_FIND_ARGS}) -if(MARIADBCLIENT_INCLUDE_DIR AND EXISTS "${MARIADBCLIENT_INCLUDE_DIR}/mariadb/mariadb_version.h") +if(PC_MARIADBCLIENT_VERSION) + set(MARIADBCLIENT_VERSION_STRING ${PC_MARIADBCLIENT_VERSION}) +elseif(MARIADBCLIENT_INCLUDE_DIR AND EXISTS "${MARIADBCLIENT_INCLUDE_DIR}/mariadb/mariadb_version.h") file(STRINGS "${MARIADBCLIENT_INCLUDE_DIR}/mariadb/mariadb_version.h" mariadb_version_str REGEX "^#define[\t ]+MARIADB_CLIENT_VERSION_STR[\t ]+\".*\".*") string(REGEX REPLACE "^#define[\t ]+MARIADB_CLIENT_VERSION_STR[\t ]+\"([^\"]+)\".*" "\\1" MARIADBCLIENT_VERSION_STRING "${mariadb_version_str}") unset(mariadb_version_str) diff --git a/cmake/scripts/common/AddonHelpers.cmake b/cmake/scripts/common/AddonHelpers.cmake index a91e3666fa..d90cc8ae37 100644 --- a/cmake/scripts/common/AddonHelpers.cmake +++ b/cmake/scripts/common/AddonHelpers.cmake @@ -289,10 +289,12 @@ macro (build_addon target prefix libs) COMPONENT ${target}-${${prefix}_VERSION}-${PLATFORM_TAG}) endif() if(${prefix}_CUSTOM_DATA) - install(DIRECTORY ${${prefix}_CUSTOM_DATA} DESTINATION ${target}/resources) + install(DIRECTORY ${${prefix}_CUSTOM_DATA} DESTINATION ${target}/resources + COMPONENT ${target}-${${prefix}_VERSION}-${PLATFORM_TAG}) endif() if(${prefix}_ADDITIONAL_BINARY) - install(FILES ${${prefix}_ADDITIONAL_BINARY} DESTINATION ${target}) + install(FILES ${${prefix}_ADDITIONAL_BINARY} DESTINATION ${target} + COMPONENT ${target}-${${prefix}_VERSION}-${PLATFORM_TAG}) endif() endif() add_cpack_workaround(${target} ${${prefix}_VERSION} ${ext}) @@ -341,10 +343,11 @@ macro (build_addon target prefix libs) if(${APP_NAME_UC}_BUILD_DIR) file(GLOB_RECURSE files ${CMAKE_CURRENT_SOURCE_DIR}/${target}/*) if(${prefix}_CUSTOM_DATA) + get_filename_component(dname ${${prefix}_CUSTOM_DATA} NAME) add_custom_command(TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${${prefix}_CUSTOM_DATA} - ${${APP_NAME_UC}_BUILD_DIR}/addons/${target}/resources) + ${${APP_NAME_UC}_BUILD_DIR}/addons/${target}/resources/${dname}) endif() foreach(file ${files}) string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/${target}/" "" name "${file}") diff --git a/cmake/scripts/common/Macros.cmake b/cmake/scripts/common/Macros.cmake index 0d89dd3257..89a20e5759 100644 --- a/cmake/scripts/common/Macros.cmake +++ b/cmake/scripts/common/Macros.cmake @@ -721,6 +721,7 @@ macro(core_find_versions) APP_NAME APP_PACKAGE COMPANY_NAME + COPYRIGHT_YEARS JSONRPC_VERSION PACKAGE_DESCRIPTION PACKAGE_IDENTITY diff --git a/docs/doxygen/Doxyfile.doxy b/docs/doxygen/Doxyfile.doxy index 170c3c4200..514e942d6d 100644 --- a/docs/doxygen/Doxyfile.doxy +++ b/docs/doxygen/Doxyfile.doxy @@ -249,6 +249,7 @@ ALIASES = "table_start=<table width= 100% style= border bgcolor= "python_class{1}=\htmlonly <h4><code><span style=\"font-style: italic;\">Class: </span><span style=\"font-style: bold;\"><font color=31363b><big>\1</big></font></span></code></h4> \endhtmlonly" \ "python_class_with_rev{2}=\htmlonly <h4><code><span style=\"font-style: italic;\">Class: </span><span style=\"font-style: bold;\"><font color=31363b><big>\1</big></font></span></code><span style="float:right;"><small>\2</small></span></h4> \endhtmlonly" \ "doc_header{1}=\htmlonly <h3><span style=\"text-decoration: underline;\"><span style=\"font-style: italic;\"><span style=\"color: rgb(102, 102, 102);\">\1</span></span></span></h3> \endhtmlonly" \ + "python_removed_function{3}=\htmlonly <dl class=\"reflist\"><dt>Member <a class="el" href=\"\2\">\1</a> (...)</dt><dd>\3</dd></dl>\endhtmlonly" \ "python_v12=\xrefitem python_v12 \"v12 Python API changes\" \"\"" \ "python_v13=\xrefitem python_v13 \"v13 Python API changes\" \"\"" \ "python_v14=\xrefitem python_v14 \"v14 Python API changes\" \"\"" \ diff --git a/project/BuildDependencies/scripts/0_package.target-win10-arm.list b/project/BuildDependencies/scripts/0_package.target-win10-arm.list index 5dff2891da..3b3ebc4bee 100644 --- a/project/BuildDependencies/scripts/0_package.target-win10-arm.list +++ b/project/BuildDependencies/scripts/0_package.target-win10-arm.list @@ -22,7 +22,7 @@ libcdio-0.94-win10-ARM-v140.7z libfribidi-0.19.7-win10-ARM-v140.7z libiconv-1.15-win10-ARM-v141.7z libmicrohttpd-0.9.55-win10-ARM-v140.7z -libnfs-1.11.0-win10-ARM-v140.7z +libnfs-3.0.0-win10-ARM-v141.7z libplist-1.12-win10-ARM-v140.7z libxml2-2.9.4-win10-ARM-v141.7z libxslt-1.1.29-win10-ARM-v140.7z diff --git a/project/BuildDependencies/scripts/0_package.target-win10-win32.list b/project/BuildDependencies/scripts/0_package.target-win10-win32.list index 60b34ac594..d4a5115d08 100644 --- a/project/BuildDependencies/scripts/0_package.target-win10-win32.list +++ b/project/BuildDependencies/scripts/0_package.target-win10-win32.list @@ -22,7 +22,7 @@ libcdio-0.94-win10-Win32-v140.7z libfribidi-0.19.7-win10-Win32-v140.7z libiconv-1.15-win10-Win32-v141.7z libmicrohttpd-0.9.55-win10-Win32-v140.7z -libnfs-1.11.0-win10-Win32-v140.7z +libnfs-3.0.0-win10-Win32-v141.7z libplist-1.12-win10-Win32-v140.7z libxml2-2.9.4-win10-Win32-v141.7z libxslt-1.1.29-win10-Win32-v140.7z diff --git a/project/BuildDependencies/scripts/0_package.target-win10-x64.list b/project/BuildDependencies/scripts/0_package.target-win10-x64.list index a73be23111..9642427c14 100644 --- a/project/BuildDependencies/scripts/0_package.target-win10-x64.list +++ b/project/BuildDependencies/scripts/0_package.target-win10-x64.list @@ -22,7 +22,7 @@ libcdio-0.94-win10-x64-v140.7z libfribidi-0.19.7-win10-x64-v140.7z libiconv-1.15-win10-x64-v141.7z libmicrohttpd-0.9.55-win10-x64-v140.7z -libnfs-1.11.0-win10-x64-v140.7z +libnfs-3.0.0-win10-x64-v141.7z libplist-1.12-win10-x64-v140.7z libxml2-2.9.4-win10-x64-v141.7z libxslt-1.1.29-win10-x64-v140.7z diff --git a/project/BuildDependencies/scripts/0_package.target-win32.list b/project/BuildDependencies/scripts/0_package.target-win32.list index f201d4ebe7..1abe21cd5b 100644 --- a/project/BuildDependencies/scripts/0_package.target-win32.list +++ b/project/BuildDependencies/scripts/0_package.target-win32.list @@ -26,7 +26,7 @@ libfribidi-0.19.2-win32.7z libiconv-1.14-win32-vc140-v2.7z libjpeg-turbo-1.4.90-win32-vc140.7z libmicrohttpd-0.9.55-win32-vc140.7z -libnfs-1.10.0-win32.7z +libnfs-3.0.0-Win32-v141.7z libplist-1.13.0-win32-vc140.7z libpng-1.6.21-win32-vc140.7z libxml2-2.9.4-win32-vc140-v2.7z diff --git a/project/BuildDependencies/scripts/0_package.target-x64.list b/project/BuildDependencies/scripts/0_package.target-x64.list index 8e57512819..14eeb0a8b6 100644 --- a/project/BuildDependencies/scripts/0_package.target-x64.list +++ b/project/BuildDependencies/scripts/0_package.target-x64.list @@ -24,7 +24,7 @@ libcec-4.0.2-x64-vc140.7z libfribidi-0.19.7-x64-vc140.7z libiconv-1.15-x64-vc140.7z libmicrohttpd-0.9.55-x64-vc140.7z -libnfs-1.11.0-x64-vc140-v2.7z +libnfs-3.0.0-x64-v141.7z libplist-1.12-x64-vc140.7z libxml2-2.9.4-x64-vc140.7z libxslt-1.1.29-x64-vc140.7z diff --git a/project/Win32BuildSetup/genNsisInstaller.nsi b/project/Win32BuildSetup/genNsisInstaller.nsi index 1693c58d71..bba7eea574 100644 --- a/project/Win32BuildSetup/genNsisInstaller.nsi +++ b/project/Win32BuildSetup/genNsisInstaller.nsi @@ -143,6 +143,7 @@ Function HandleKodiInDestDir StrCpy $CleanDestDir "0" Abort done: + MessageBox MB_OK|MB_ICONINFORMATION "All binary add-ons (e.g. pvr, visualizations, inputstream, etc) that were previously included by default in the installer have been moved to the Kodi repository. You will have to install the ones you previously used from the repository.$\nYour add-on settings are kept intact and will be used again after installing the add-on." ${EndIf} FunctionEnd diff --git a/system/addon-manifest.xml b/system/addon-manifest.xml index e5ea2ed425..f0edcddbc1 100644 --- a/system/addon-manifest.xml +++ b/system/addon-manifest.xml @@ -3,10 +3,6 @@ <addon>audioencoder.kodi.builtin.wma</addon> <addon>game.controller.default</addon> <addon>game.controller.snes</addon> - <!-- TODO: Remove game add-ons when no longer applicable --> - <addon optional="true">game.libretro</addon> - <addon optional="true">game.libretro.2048</addon> - <addon optional="true">game.libretro.mrboom</addon> <addon>kodi.binary.global.audioengine</addon> <addon>kodi.binary.global.main</addon> <addon>kodi.binary.global.general</addon> diff --git a/tools/buildsteps/defaultenv b/tools/buildsteps/defaultenv index 4310a1405c..82bbcd24b1 100644 --- a/tools/buildsteps/defaultenv +++ b/tools/buildsteps/defaultenv @@ -119,12 +119,6 @@ function pathChanged () local ret local checkPath ret="0" - #no optims in release builds! - if [ "$Configuration" == "Release" ] - then - echo "1" - return - fi checkPath="$1" if [ -e $checkPath/$PATH_CHANGE_REV_FILENAME ] diff --git a/tools/buildsteps/windows/arm-uwp/BuildSetup.bat b/tools/buildsteps/windows/arm-uwp/BuildSetup.bat index 018be71a6c..49bb5961e9 100644 --- a/tools/buildsteps/windows/arm-uwp/BuildSetup.bat +++ b/tools/buildsteps/windows/arm-uwp/BuildSetup.bat @@ -3,6 +3,11 @@ PUSHD %~dp0\.. CALL vswhere.bat arm store +IF ERRORLEVEL 1 ( + ECHO ERROR! BuildSetup.bat: Something went wrong when calling vswhere.bat + POPD + EXIT /B 1 +) SET cmakeGenerator=Visual Studio %vsver% ARM SET TARGET_ARCHITECTURE=arm diff --git a/tools/buildsteps/windows/arm-uwp/bootstrap-addons.bat b/tools/buildsteps/windows/arm-uwp/bootstrap-addons.bat index e07f8d5195..0e672f0fbe 100644 --- a/tools/buildsteps/windows/arm-uwp/bootstrap-addons.bat +++ b/tools/buildsteps/windows/arm-uwp/bootstrap-addons.bat @@ -1,6 +1,11 @@ @ECHO OFF PUSHD %~dp0\.. -call vswhere.bat arm store +CALL vswhere.bat arm store +IF ERRORLEVEL 1 ( + ECHO ERROR! bootstrap-addons.bat: Something went wrong when calling vswhere.bat + POPD + EXIT /B 1 +) CALL bootstrap-addons %* POPD diff --git a/tools/buildsteps/windows/arm-uwp/make-addons.bat b/tools/buildsteps/windows/arm-uwp/make-addons.bat index bc70eaa892..6c23384b01 100644 --- a/tools/buildsteps/windows/arm-uwp/make-addons.bat +++ b/tools/buildsteps/windows/arm-uwp/make-addons.bat @@ -1,6 +1,11 @@ @ECHO OFF PUSHD %~dp0\.. -call vswhere.bat arm store +CALL vswhere.bat arm store +IF ERRORLEVEL 1 ( + ECHO ERROR! make-addons.bat: Something went wrong when calling vswhere.bat + POPD + EXIT /B 1 +) CALL make-addons.bat win10 %* POPD diff --git a/tools/buildsteps/windows/arm-uwp/make-mingwlibs.bat b/tools/buildsteps/windows/arm-uwp/make-mingwlibs.bat index c7bddcf1d0..6a59615548 100644 --- a/tools/buildsteps/windows/arm-uwp/make-mingwlibs.bat +++ b/tools/buildsteps/windows/arm-uwp/make-mingwlibs.bat @@ -1,6 +1,11 @@ @ECHO OFF PUSHD %~dp0\.. -call vswhere.bat arm store +CALL vswhere.bat arm store +IF ERRORLEVEL 1 ( + ECHO ERROR! make-mingwlibs.bat: Something went wrong when calling vswhere.bat + POPD + EXIT /B 1 +) CALL make-mingwlibs.bat buildArm win10 %* POPD diff --git a/tools/buildsteps/windows/make-addons.bat b/tools/buildsteps/windows/make-addons.bat index c4ddc8f90e..b8e0ac59ac 100644 --- a/tools/buildsteps/windows/make-addons.bat +++ b/tools/buildsteps/windows/make-addons.bat @@ -10,16 +10,16 @@ SET store= SETLOCAL EnableDelayedExpansion FOR %%b IN (%*) DO ( - IF %%b == install ( + IF %%~b == install ( SET install=true - ) ELSE ( IF %%b == clean ( + ) ELSE ( IF %%~b == clean ( SET clean=true - ) ELSE ( IF %%b == package ( + ) ELSE ( IF %%~b == package ( SET package=true - ) ELSE ( IF %%b == win10 ( + ) ELSE ( IF %%~b == win10 ( SET store=store ) ELSE ( - SET addon=!addon! %%b + SET addon=!addon! %%~b )))) ) SETLOCAL DisableDelayedExpansion @@ -35,7 +35,6 @@ SET SCRIPTS_PATH=%BASE_PATH%\scripts\windows%store% SET ADDONS_PATH=%BASE_PATH%\addons SET ADDON_DEPENDS_PATH=%ADDONS_PATH%\output SET ADDONS_BUILD_PATH=%ADDONS_PATH%\build -SET ADDONS_DEFINITION_PATH=%ADDONS_PATH%\addons SET ADDONS_SUCCESS_FILE=%ADDONS_PATH%\.success SET ADDONS_FAILURE_FILE=%ADDONS_PATH%\.failure @@ -82,19 +81,20 @@ ECHO -------------------------------------------------- ECHO Building addons ECHO -------------------------------------------------- -SET ADDONS_TO_BUILD= IF "%addon%" NEQ "" ( - SET ADDONS_TO_BUILD=%addon% -) ELSE ( - SETLOCAL EnableDelayedExpansion - FOR /D %%a IN (%ADDONS_DEFINITION_PATH%\*) DO ( - SET ADDONS_TO_BUILD=!ADDONS_TO_BUILD! %%~nxa - ) - SETLOCAL DisableDelayedExpansion + SET CMAKE_EXTRA=%CMAKE_EXTRA% -DADDONS_TO_BUILD="%addon%" +) + +IF "%ADDON_SRC_PREFIX%" NEQ "" ( + SET CMAKE_EXTRA=%CMAKE_EXTRA% -DADDON_SRC_PREFIX=%ADDON_SRC_PREFIX% +) + +IF "%ADDONS_DEFINITION_DIR" NEQ "" ( + SET CMAKE_EXTRA=%CMAKE_EXTRA% -DADDONS_DEFINITION_DIR=%ADDONS_DEFINITION_DIR% ) IF "%store%" NEQ "" ( -SET STORE_ARGS=-DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION=%UCRTVersion% + SET CMAKE_EXTRA=%CMAKE_EXTRA% -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION=%UCRTVersion% ) rem execute cmake to generate makefiles processable by nmake @@ -107,8 +107,7 @@ cmake "%ADDONS_PATH%" -G "NMake Makefiles" ^ -DBUILD_DIR=%ADDONS_BUILD_PATH% ^ -DADDON_DEPENDS_PATH=%ADDON_DEPENDS_PATH% ^ -DPACKAGE_ZIP=ON ^ - %STORE_ARGS% ^ - -DADDONS_TO_BUILD="%ADDONS_TO_BUILD%" + %CMAKE_EXTRA% IF ERRORLEVEL 1 ( ECHO cmake error level: %ERRORLEVEL% > %ERRORFILE% diff --git a/tools/buildsteps/windows/vswhere.bat b/tools/buildsteps/windows/vswhere.bat index 7c8e7c0133..e717373b4a 100644 --- a/tools/buildsteps/windows/vswhere.bat +++ b/tools/buildsteps/windows/vswhere.bat @@ -1,5 +1,19 @@ @ECHO OFF +IF "%1"=="" ( + ECHO ERROR! vswhere.bat: architecture not specified + EXIT /B 1 +) + +REM running vcvars more than once can cause problems; exit early if using the same configuration, error if different +IF "%VSWHERE_SET%"=="%*" ( + ECHO vswhere.bat: VC vars already configured for %VSWHERE_SET% + GOTO :EOF +) +IF "%VSWHERE_SET%" NEQ "" ( + ECHO ERROR! vswhere.bat: VC vars are configured for %VSWHERE_SET% + EXIT /B 1 +) REM Trick to make the path absolute PUSHD %~dp0\..\..\..\project\BuildDependencies @@ -63,4 +77,6 @@ IF ERRORLEVEL 1 ( ECHO "ERROR! something went wrong when calling" ECHO %vcvars% %vcarch% %vcstore% %sdkver% EXIT /B 1 -)
\ No newline at end of file +) + +SET VSWHERE_SET=%* diff --git a/tools/buildsteps/windows/win32-uwp/BuildSetup.bat b/tools/buildsteps/windows/win32-uwp/BuildSetup.bat index e5bc3c7316..545f0d7a48 100644 --- a/tools/buildsteps/windows/win32-uwp/BuildSetup.bat +++ b/tools/buildsteps/windows/win32-uwp/BuildSetup.bat @@ -2,6 +2,11 @@ PUSHD %~dp0\.. CALL vswhere.bat x86 store +IF ERRORLEVEL 1 ( + ECHO ERROR! BuildSetup.bat: Something went wrong when calling vswhere.bat + POPD + EXIT /B 1 +) SET cmakeGenerator=Visual Studio %vsver% SET TARGET_ARCHITECTURE=x86 diff --git a/tools/buildsteps/windows/win32-uwp/bootstrap-addons.bat b/tools/buildsteps/windows/win32-uwp/bootstrap-addons.bat index 7b9db758ac..0f67ddb510 100644 --- a/tools/buildsteps/windows/win32-uwp/bootstrap-addons.bat +++ b/tools/buildsteps/windows/win32-uwp/bootstrap-addons.bat @@ -2,5 +2,10 @@ PUSHD %~dp0\.. CALL vswhere.bat x86 store +IF ERRORLEVEL 1 ( + ECHO ERROR! bootstrap-addons.bat: Something went wrong when calling vswhere.bat + POPD + EXIT /B 1 +) CALL bootstrap-addons %* POPD diff --git a/tools/buildsteps/windows/win32-uwp/make-addons.bat b/tools/buildsteps/windows/win32-uwp/make-addons.bat index 08ad473f25..0893cee0ad 100644 --- a/tools/buildsteps/windows/win32-uwp/make-addons.bat +++ b/tools/buildsteps/windows/win32-uwp/make-addons.bat @@ -2,5 +2,10 @@ PUSHD %~dp0\.. CALL vswhere.bat x86 store +IF ERRORLEVEL 1 ( + ECHO ERROR! make-addons.bat: Something went wrong when calling vswhere.bat + POPD + EXIT /B 1 +) CALL make-addons.bat win10 %* POPD diff --git a/tools/buildsteps/windows/win32-uwp/make-mingwlibs.bat b/tools/buildsteps/windows/win32-uwp/make-mingwlibs.bat index 4e5c7a7772..f47434eb33 100644 --- a/tools/buildsteps/windows/win32-uwp/make-mingwlibs.bat +++ b/tools/buildsteps/windows/win32-uwp/make-mingwlibs.bat @@ -2,5 +2,10 @@ PUSHD %~dp0\.. CALL vswhere.bat x86 store +IF ERRORLEVEL 1 ( + ECHO ERROR! make-mingwlibs.bat: Something went wrong when calling vswhere.bat + POPD + EXIT /B 1 +) CALL make-mingwlibs.bat win10 %* POPD diff --git a/tools/buildsteps/windows/win32/BuildSetup.bat b/tools/buildsteps/windows/win32/BuildSetup.bat index 2857e8d9d1..ecfb42ff76 100644 --- a/tools/buildsteps/windows/win32/BuildSetup.bat +++ b/tools/buildsteps/windows/win32/BuildSetup.bat @@ -3,6 +3,11 @@ PUSHD %~dp0\.. CALL vswhere.bat x86 +IF ERRORLEVEL 1 ( + ECHO ERROR! BuildSetup.bat: Something went wrong when calling vswhere.bat + POPD + EXIT /B 1 +) SET cmakeGenerator=Visual Studio %vsver% SET TARGET_ARCHITECTURE=x86 diff --git a/tools/buildsteps/windows/win32/bootstrap-addons.bat b/tools/buildsteps/windows/win32/bootstrap-addons.bat index 76613c85ea..5918ad978f 100644 --- a/tools/buildsteps/windows/win32/bootstrap-addons.bat +++ b/tools/buildsteps/windows/win32/bootstrap-addons.bat @@ -2,5 +2,10 @@ PUSHD %~dp0\.. CALL vswhere.bat x86 +IF ERRORLEVEL 1 ( + ECHO ERROR! bootstrap-addons.bat: Something went wrong when calling vswhere.bat + POPD + EXIT /B 1 +) CALL bootstrap-addons %* POPD diff --git a/tools/buildsteps/windows/win32/make-addons.bat b/tools/buildsteps/windows/win32/make-addons.bat index 3faef544c3..7efc4cad27 100644 --- a/tools/buildsteps/windows/win32/make-addons.bat +++ b/tools/buildsteps/windows/win32/make-addons.bat @@ -2,5 +2,10 @@ PUSHD %~dp0\.. CALL vswhere.bat x86 +IF ERRORLEVEL 1 ( + ECHO ERROR! make-addons.bat: Something went wrong when calling vswhere.bat + POPD + EXIT /B 1 +) CALL make-addons.bat %* POPD diff --git a/tools/buildsteps/windows/win32/make-mingwlibs.bat b/tools/buildsteps/windows/win32/make-mingwlibs.bat index 5572aa90e8..889b27ede3 100644 --- a/tools/buildsteps/windows/win32/make-mingwlibs.bat +++ b/tools/buildsteps/windows/win32/make-mingwlibs.bat @@ -2,5 +2,10 @@ PUSHD %~dp0\.. CALL vswhere.bat x86 +IF ERRORLEVEL 1 ( + ECHO ERROR! make-mingwlibs.bat: Something went wrong when calling vswhere.bat + POPD + EXIT /B 1 +) CALL make-mingwlibs.bat %* POPD diff --git a/tools/buildsteps/windows/x64-uwp/BuildSetup.bat b/tools/buildsteps/windows/x64-uwp/BuildSetup.bat index 65e39e52de..8ef44c3ade 100644 --- a/tools/buildsteps/windows/x64-uwp/BuildSetup.bat +++ b/tools/buildsteps/windows/x64-uwp/BuildSetup.bat @@ -2,6 +2,11 @@ PUSHD %~dp0\.. CALL vswhere.bat x64 store +IF ERRORLEVEL 1 ( + ECHO ERROR! BuildSetup.bat: Something went wrong when calling vswhere.bat + POPD + EXIT /B 1 +) SET cmakeGenerator=Visual Studio %vsver% Win64 SET TARGET_ARCHITECTURE=x64 diff --git a/tools/buildsteps/windows/x64-uwp/bootstrap-addons.bat b/tools/buildsteps/windows/x64-uwp/bootstrap-addons.bat index 43161644d4..83eed238cf 100644 --- a/tools/buildsteps/windows/x64-uwp/bootstrap-addons.bat +++ b/tools/buildsteps/windows/x64-uwp/bootstrap-addons.bat @@ -2,5 +2,10 @@ PUSHD %~dp0\.. CALL vswhere.bat x64 store +IF ERRORLEVEL 1 ( + ECHO ERROR! bootstrap-addons.bat: Something went wrong when calling vswhere.bat + POPD + EXIT /B 1 +) CALL bootstrap-addons %* POPD diff --git a/tools/buildsteps/windows/x64-uwp/make-addons.bat b/tools/buildsteps/windows/x64-uwp/make-addons.bat index 6fe9d983e3..82bd1af057 100644 --- a/tools/buildsteps/windows/x64-uwp/make-addons.bat +++ b/tools/buildsteps/windows/x64-uwp/make-addons.bat @@ -2,5 +2,10 @@ PUSHD %~dp0\.. CALL vswhere.bat x64 store +IF ERRORLEVEL 1 ( + ECHO ERROR! make-addons.bat: Something went wrong when calling vswhere.bat + POPD + EXIT /B 1 +) CALL make-addons.bat win10 %* POPD diff --git a/tools/buildsteps/windows/x64-uwp/make-mingwlibs.bat b/tools/buildsteps/windows/x64-uwp/make-mingwlibs.bat index 46643ac6ce..9e1ef90eaf 100644 --- a/tools/buildsteps/windows/x64-uwp/make-mingwlibs.bat +++ b/tools/buildsteps/windows/x64-uwp/make-mingwlibs.bat @@ -2,5 +2,10 @@ PUSHD %~dp0\.. CALL vswhere.bat x64 store +IF ERRORLEVEL 1 ( + ECHO ERROR! make-mingwlibs.bat: Something went wrong when calling vswhere.bat + POPD + EXIT /B 1 +) CALL make-mingwlibs.bat build64 win10 %* POPD diff --git a/tools/buildsteps/windows/x64/BuildSetup.bat b/tools/buildsteps/windows/x64/BuildSetup.bat index d2b6f4f696..4ff91a8891 100644 --- a/tools/buildsteps/windows/x64/BuildSetup.bat +++ b/tools/buildsteps/windows/x64/BuildSetup.bat @@ -2,6 +2,11 @@ PUSHD %~dp0\.. CALL vswhere.bat x64 +IF ERRORLEVEL 1 ( + ECHO ERROR! BuildSetup.bat: Something went wrong when calling vswhere.bat + POPD + EXIT /B 1 +) SET cmakeGenerator=Visual Studio %vsver% Win64 SET TARGET_ARCHITECTURE=x64 diff --git a/tools/buildsteps/windows/x64/bootstrap-addons.bat b/tools/buildsteps/windows/x64/bootstrap-addons.bat index ac10bab6b8..45c5de69e2 100644 --- a/tools/buildsteps/windows/x64/bootstrap-addons.bat +++ b/tools/buildsteps/windows/x64/bootstrap-addons.bat @@ -2,5 +2,10 @@ PUSHD %~dp0\.. CALL vswhere.bat x64 +IF ERRORLEVEL 1 ( + ECHO ERROR! bootstrap-addons.bat: Something went wrong when calling vswhere.bat + POPD + EXIT /B 1 +) CALL bootstrap-addons %* POPD diff --git a/tools/buildsteps/windows/x64/make-addons.bat b/tools/buildsteps/windows/x64/make-addons.bat index 4bdd4d80c4..ec9803f59c 100644 --- a/tools/buildsteps/windows/x64/make-addons.bat +++ b/tools/buildsteps/windows/x64/make-addons.bat @@ -2,5 +2,10 @@ PUSHD %~dp0\.. CALL vswhere.bat x64 +IF ERRORLEVEL 1 ( + ECHO ERROR! make-addons.bat: Something went wrong when calling vswhere.bat + POPD + EXIT /B 1 +) CALL make-addons.bat %* POPD diff --git a/tools/buildsteps/windows/x64/make-mingwlibs.bat b/tools/buildsteps/windows/x64/make-mingwlibs.bat index d741500f39..41471e5fa3 100644 --- a/tools/buildsteps/windows/x64/make-mingwlibs.bat +++ b/tools/buildsteps/windows/x64/make-mingwlibs.bat @@ -2,5 +2,10 @@ PUSHD %~dp0\.. CALL vswhere.bat x64 +IF ERRORLEVEL 1 ( + ECHO ERROR! make-mingwlibs.bat: Something went wrong when calling vswhere.bat + POPD + EXIT /B 1 +) CALL make-mingwlibs.bat build64 %* POPD diff --git a/tools/depends/configure.ac b/tools/depends/configure.ac index ed6d2468ab..979819d752 100644 --- a/tools/depends/configure.ac +++ b/tools/depends/configure.ac @@ -620,8 +620,8 @@ else fi # add user supplied flags to the end, so they override our defaults -platform_cflags_release="$tmp_cflags $relase_cflags $optimize_flags $target_cflags" -platform_cxxflags_release="$tmp_cxxflags $relase_cflags $optimize_flags $target_cxxflags" +platform_cflags_release="$tmp_cflags $release_cflags $optimize_flags $target_cflags" +platform_cxxflags_release="$tmp_cxxflags $release_cflags $optimize_flags $target_cxxflags" platform_cflags_debug="$tmp_cflags $debug_cflags $target_cflags" platform_cxxflags_debug="$tmp_cxxflags $debug_cflags $target_cxxflags" platform_ldflags+=" $target_ldflags $LIBS" diff --git a/tools/depends/target/binary-addons/Makefile b/tools/depends/target/binary-addons/Makefile index 56f7fee484..421839b2f0 100644 --- a/tools/depends/target/binary-addons/Makefile +++ b/tools/depends/target/binary-addons/Makefile @@ -1,5 +1,5 @@ BUILDDIR := $(shell pwd) -ADDONS := all +ADDONS ?= all ADDON_SRC_PREFIX := -include ../../Makefile.include diff --git a/tools/depends/target/ffmpeg/Makefile b/tools/depends/target/ffmpeg/Makefile index af9f956bdb..47acb73bdd 100644 --- a/tools/depends/target/ffmpeg/Makefile +++ b/tools/depends/target/ffmpeg/Makefile @@ -38,6 +38,7 @@ ifeq ($(OS), android) ffmpg_config += --cpu=cortex-a9 else ffmpg_config += --cpu=i686 --disable-mmx + ffmpg_config += --extra-cflags=-no-integrated-as --extra-cflags=-mno-stackrealign endif endif ffmpg_config += --target-os=linux --extra-libs=-liconv --disable-linux-perf diff --git a/tools/depends/xbmc-addons.include b/tools/depends/xbmc-addons.include index 63046be4f3..9ed0e27e37 100644 --- a/tools/depends/xbmc-addons.include +++ b/tools/depends/xbmc-addons.include @@ -38,7 +38,19 @@ ifneq ($(TARBALLS_LOCATION),) endif ifneq ($(ADDON_SRC_PREFIX),) - SRC_OVERRIDE = -DADDON_SRC_PREFIX=$(ADDON_SRC_PREFIX) + CMAKE_EXTRA += -DADDON_SRC_PREFIX=$(ADDON_SRC_PREFIX) +endif + +ifneq ($(ADDONS_DEFINITION_DIR),) + CMAKE_EXTRA += -DADDONS_DEFINITION_DIR=$(ADDONS_DEFINITION_DIR) +endif + +ifneq ($(EXTRA_CMAKE_ARGS),) + CMAKE_EXTRA += $(EXTRA_CMAKE_ARGS) +endif + +ifeq ($(PACKAGE),1) + MAKE_PACKAGE = package- endif all: .installed-$(PLATFORM) @@ -64,10 +76,10 @@ ifeq ($(CROSS_COMPILING),yes) endif cd $(PLATFORM); \ $(CMAKE) -DCMAKE_INSTALL_PREFIX=$(INSTALL_PREFIX) $(CMAKE_EXTRA) \ - $(TOOLCHAIN) $(SRC_OVERRIDE) \ + $(TOOLCHAIN) \ -DADDONS_TO_BUILD="$(ADDONS)" $(ADDON_PROJECT_DIR) -DBUILD_DIR=$(BUILDDIR)/$(PLATFORM)/build ;\ for addon in $$($(MAKE) supported_addons | awk '/^ALL_ADDONS_BUILDING: .*$$/ { first = $$1; $$1 = ""; print $$0 }'); do \ - $(MAKE) $$addon && echo $$addon >> $(ADDON_PROJECT_DIR)/.success || echo $$addon >> $(ADDON_PROJECT_DIR)/.failure ;\ + $(MAKE) $(MAKE_PACKAGE)$$addon && echo $$addon >> $(ADDON_PROJECT_DIR)/.success || echo $$addon >> $(ADDON_PROJECT_DIR)/.failure ;\ done ifneq ($(CROSS_COMPILING),yes) @[ -f $(ADDON_PROJECT_DIR)/.failure ] && echo "Following Addons failed to build:" $(shell cat $(ADDON_PROJECT_DIR)/.failure) || : diff --git a/version.txt b/version.txt index c27a42c834..dff2507c93 100644 --- a/version.txt +++ b/version.txt @@ -1,5 +1,6 @@ APP_NAME Kodi COMPANY_NAME XBMC Foundation +COPYRIGHT_YEARS 2005-2018 WEBSITE http://kodi.tv VERSION_MAJOR 18 VERSION_MINOR 0 diff --git a/xbmc/AppParamParser.cpp b/xbmc/AppParamParser.cpp index 20f3c819b8..63920101d0 100644 --- a/xbmc/AppParamParser.cpp +++ b/xbmc/AppParamParser.cpp @@ -7,6 +7,7 @@ */ #include "AppParamParser.h" +#include "CompileInfo.h" #include "FileItem.h" #include "settings/AdvancedSettings.h" #include "utils/log.h" @@ -40,7 +41,8 @@ void CAppParamParser::Parse(const char* const* argv, int nArgs) void CAppParamParser::DisplayVersion() { printf("%s Media Center %s\n", CSysInfo::GetVersion().c_str(), CSysInfo::GetAppName().c_str()); - printf("Copyright (C) 2005-2013 Team %s - http://kodi.tv\n", CSysInfo::GetAppName().c_str()); + printf("Copyright (C) %s Team %s - http://kodi.tv\n", + CCompileInfo::GetCopyrightYears(), CSysInfo::GetAppName().c_str()); exit(0); } diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp index 93b6cc3f18..e536f3c4a9 100644 --- a/xbmc/Application.cpp +++ b/xbmc/Application.cpp @@ -1374,22 +1374,26 @@ void CApplication::UnloadSkin(bool forReload /* = false */) else if (!m_saveSkinOnUnloading) m_saveSkinOnUnloading = true; - CServiceBroker::GetGUI()->GetAudioManager().Enable(false); + CGUIComponent *gui = CServiceBroker::GetGUI(); + if (gui) + { + gui->GetAudioManager().Enable(false); - CServiceBroker::GetGUI()->GetWindowManager().DeInitialize(); - CTextureCache::GetInstance().Deinitialize(); + gui->GetWindowManager().DeInitialize(); + CTextureCache::GetInstance().Deinitialize(); - // remove the skin-dependent window - CServiceBroker::GetGUI()->GetWindowManager().Delete(WINDOW_DIALOG_FULLSCREEN_INFO); + // remove the skin-dependent window + gui->GetWindowManager().Delete(WINDOW_DIALOG_FULLSCREEN_INFO); - CServiceBroker::GetGUI()->GetTextureManager().Cleanup(); - CServiceBroker::GetGUI()->GetLargeTextureManager().CleanupUnusedImages(true); + gui->GetTextureManager().Cleanup(); + gui->GetLargeTextureManager().CleanupUnusedImages(true); - g_fontManager.Clear(); + g_fontManager.Clear(); - CServiceBroker::GetGUI()->GetColorManager().Clear(); + gui->GetColorManager().Clear(); - CServiceBroker::GetGUI()->GetInfoManager().Clear(); + gui->GetInfoManager().Clear(); + } // The g_SkinInfo shared_ptr ought to be reset here // but there are too many places it's used without checking for NULL @@ -2435,10 +2439,19 @@ bool CApplication::Cleanup() m_globalScreensaverInhibitor.Release(); m_screensaverInhibitor.Release(); - CServiceBroker::GetRenderSystem()->DestroyRenderSystem(); - CServiceBroker::GetWinSystem()->DestroyWindow(); - CServiceBroker::GetWinSystem()->DestroyWindowSystem(); - CServiceBroker::GetGUI()->GetWindowManager().DestroyWindows(); + CRenderSystemBase *renderSystem = CServiceBroker::GetRenderSystem(); + if (renderSystem) + renderSystem->DestroyRenderSystem(); + + CWinSystemBase *winSystem = CServiceBroker::GetWinSystem(); + if (winSystem) + { + winSystem->DestroyWindow(); + winSystem->DestroyWindowSystem(); + } + + if (m_pGUI) + m_pGUI->GetWindowManager().DestroyWindows(); CLog::Log(LOGNOTICE, "unload sections"); @@ -2473,8 +2486,11 @@ bool CApplication::Cleanup() while(1); // execution ends #endif - m_pGUI->Deinit(); - m_pGUI.reset(); + if (m_pGUI) + { + m_pGUI->Deinit(); + m_pGUI.reset(); + } // Cleanup was called more than once on exit during my tests if (m_ServiceManager) @@ -2483,6 +2499,7 @@ bool CApplication::Cleanup() m_ServiceManager.reset(); } + m_pAnnouncementManager->Deinitialize(); m_pAnnouncementManager.reset(); m_pSettingsComponent->Deinit(); @@ -3294,19 +3311,24 @@ bool CApplication::IsFullScreen() void CApplication::StopPlaying() { - int iWin = CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow(); - if (m_appPlayer.IsPlaying()) + CGUIComponent *gui = CServiceBroker::GetGUI(); + + if (gui) { - m_appPlayer.ClosePlayer(); + int iWin = gui->GetWindowManager().GetActiveWindow(); + if (m_appPlayer.IsPlaying()) + { + m_appPlayer.ClosePlayer(); - // turn off visualisation window when stopping - if ((iWin == WINDOW_VISUALISATION || - iWin == WINDOW_FULLSCREEN_VIDEO || - iWin == WINDOW_FULLSCREEN_GAME) && - !m_bStop) - CServiceBroker::GetGUI()->GetWindowManager().PreviousWindow(); + // turn off visualisation window when stopping + if ((iWin == WINDOW_VISUALISATION || + iWin == WINDOW_FULLSCREEN_VIDEO || + iWin == WINDOW_FULLSCREEN_GAME) && + !m_bStop) + gui->GetWindowManager().PreviousWindow(); - g_partyModeManager.Disable(); + g_partyModeManager.Disable(); + } } } diff --git a/xbmc/Application.h b/xbmc/Application.h index 38be160f4a..47c35504de 100644 --- a/xbmc/Application.h +++ b/xbmc/Application.h @@ -351,6 +351,8 @@ public: */ void UnlockFrameMoveGuard(); + void SetRenderGUI(bool renderGUI); + protected: bool OnSettingsSaving() const override; bool Load(const TiXmlNode *settings) override; @@ -366,7 +368,6 @@ protected: // inbound protocol bool OnEvent(XBMC_Event& newEvent); - void SetRenderGUI(bool renderGUI); /*! \brief Delegates the action to all registered action handlers. diff --git a/xbmc/CompileInfo.cpp.in b/xbmc/CompileInfo.cpp.in index e0e15a90e4..eef78ba052 100644 --- a/xbmc/CompileInfo.cpp.in +++ b/xbmc/CompileInfo.cpp.in @@ -54,3 +54,8 @@ const char* CCompileInfo::GetSCMID() { return "@APP_SCMID@"; } + +const char* CCompileInfo::GetCopyrightYears() +{ + return "@APP_COPYRIGHT_YEARS@"; +} diff --git a/xbmc/CompileInfo.h b/xbmc/CompileInfo.h index 4104141563..855711e5f7 100644 --- a/xbmc/CompileInfo.h +++ b/xbmc/CompileInfo.h @@ -18,4 +18,5 @@ public: static const char* GetAppName(); static const char *GetSuffix(); // Git "Tag", e.g. alpha1 static const char* GetSCMID(); // Git Revision + static const char* GetCopyrightYears(); }; diff --git a/xbmc/ContextMenuManager.cpp b/xbmc/ContextMenuManager.cpp index 721af94256..20c6cec52a 100644 --- a/xbmc/ContextMenuManager.cpp +++ b/xbmc/ContextMenuManager.cpp @@ -40,6 +40,7 @@ CContextMenuManager::~CContextMenuManager() void CContextMenuManager::Deinit() { + CPVRContextMenuManager::GetInstance().Events().Unsubscribe(this); m_addonMgr.Events().Unsubscribe(this); m_items.clear(); } @@ -47,6 +48,7 @@ void CContextMenuManager::Deinit() void CContextMenuManager::Init() { m_addonMgr.Events().Subscribe(this, &CContextMenuManager::OnEvent); + CPVRContextMenuManager::GetInstance().Events().Subscribe(this, &CContextMenuManager::OnPVREvent); CSingleLock lock(m_criticalSection); m_items = { @@ -136,6 +138,30 @@ void CContextMenuManager::OnEvent(const ADDON::AddonEvent& event) } } +void CContextMenuManager::OnPVREvent(const PVRContextMenuEvent& event) +{ + switch (event.action) + { + case PVRContextMenuEventAction::ADD_ITEM: + { + CSingleLock lock(m_criticalSection); + m_items.emplace_back(event.item); + break; + } + case PVRContextMenuEventAction::REMOVE_ITEM: + { + CSingleLock lock(m_criticalSection); + auto it = std::find(m_items.begin(), m_items.end(), event.item); + if (it != m_items.end()) + m_items.erase(it); + break; + } + + default: + break; + } +} + bool CContextMenuManager::IsVisible( const CContextMenuItem& menuItem, const CContextMenuItem& root, const CFileItem& fileItem) const { diff --git a/xbmc/ContextMenuManager.h b/xbmc/ContextMenuManager.h index 5e124298e0..21e0e70578 100644 --- a/xbmc/ContextMenuManager.h +++ b/xbmc/ContextMenuManager.h @@ -14,6 +14,10 @@ #include "addons/ContextMenuAddon.h" #include "ContextMenuItem.h" +namespace PVR +{ + struct PVRContextMenuEvent; +} using ContextMenuView = std::vector<std::shared_ptr<const IContextMenuItem>>; @@ -45,6 +49,8 @@ private: void ReloadAddonItems(); void OnEvent(const ADDON::AddonEvent& event); + void OnPVREvent(const PVR::PVRContextMenuEvent& event); + ADDON::CAddonMgr& m_addonMgr; mutable CCriticalSection m_criticalSection; diff --git a/xbmc/CueDocument.cpp b/xbmc/CueDocument.cpp index ce7856c68f..f2112de72b 100644 --- a/xbmc/CueDocument.cpp +++ b/xbmc/CueDocument.cpp @@ -135,6 +135,11 @@ public: line.push_back(ch); } } + + StringUtils::Trim(line); + if (!line.empty()) + return true; + return false; } bool ready() const override @@ -282,10 +287,8 @@ bool CCueDocument::Parse(CueReader& reader, const std::string& strFile) int numberFiles = -1; // Run through the .CUE file and extract the tracks... - while (true) + while (reader.ReadLine(strLine)) { - if (!reader.ReadLine(strLine)) - break; if (StringUtils::StartsWithNoCase(strLine, "INDEX 01")) { if (bCurrentFileChanged) diff --git a/xbmc/addons/AddonInstaller.h b/xbmc/addons/AddonInstaller.h index 35822b77fe..e738d398d8 100644 --- a/xbmc/addons/AddonInstaller.h +++ b/xbmc/addons/AddonInstaller.h @@ -146,12 +146,11 @@ public: bool DoWork() override; - /*! \brief Find the add-on and itshash for the given add-on ID + /*! \brief Find the add-on and its repository for the given add-on ID * \param addonID ID of the add-on to find - * \param repoID ID of the repo to use - * \param addon Add-on with the given add-on ID - * \param hash Hash of the add-on - * \return True if the add-on and its hash were found, false otherwise. + * \param[out] repo the repository to use + * \param[out] addon Add-on with the given add-on ID + * \return True if the add-on and its repository were found, false otherwise. */ static bool GetAddon(const std::string& addonID, ADDON::RepositoryPtr& repo, ADDON::AddonPtr& addon); diff --git a/xbmc/addons/AddonManager.h b/xbmc/addons/AddonManager.h index 70c46284c2..d2c822a991 100644 --- a/xbmc/addons/AddonManager.h +++ b/xbmc/addons/AddonManager.h @@ -222,8 +222,7 @@ namespace ADDON /*! \brief Retrieve an element from a given configuration element \param base the base configuration element. \param path the path to the configuration element from the base element. - \param element [out] returned element. - \return true if the configuration element is present + \return a pointer to the retrieved element if it was found, nullptr otherwise */ cp_cfg_element_t *GetExtElement(cp_cfg_element_t *base, const char *path); diff --git a/xbmc/addons/CMakeLists.txt b/xbmc/addons/CMakeLists.txt index f4130e494d..3bed5a412d 100644 --- a/xbmc/addons/CMakeLists.txt +++ b/xbmc/addons/CMakeLists.txt @@ -23,6 +23,7 @@ set(SOURCES Addon.cpp LanguageResource.cpp PluginSource.cpp PVRClient.cpp + PVRClientMenuHooks.cpp Repository.cpp RepositoryUpdater.cpp Scraper.cpp @@ -62,6 +63,7 @@ set(HEADERS Addon.h LanguageResource.h PluginSource.h PVRClient.h + PVRClientMenuHooks.h Repository.h RepositoryUpdater.h Resource.h diff --git a/xbmc/addons/PVRClient.cpp b/xbmc/addons/PVRClient.cpp index 128ea66ff1..434382bff0 100644 --- a/xbmc/addons/PVRClient.cpp +++ b/xbmc/addons/PVRClient.cpp @@ -17,6 +17,7 @@ extern "C" { } #include "ServiceBroker.h" +#include "addons/PVRClientMenuHooks.h" #include "cores/VideoPlayer/DVDDemuxers/DVDDemuxUtils.h" #include "dialogs/GUIDialogKaiToast.h" #include "events/EventLog.h" @@ -110,7 +111,7 @@ void CPVRClient::ResetProperties(int iClientId /* = PVR_INVALID_CLIENT_ID */) m_strFriendlyName = DEFAULT_INFO_STRING_VALUE; m_strBackendName = DEFAULT_INFO_STRING_VALUE; m_strBackendHostname.clear(); - m_menuhooks.clear(); + m_menuhooks.reset(); m_timertypes.clear(); m_clientCapabilities.clear(); @@ -177,6 +178,9 @@ void CPVRClient::Destroy(void) /* destroy the add-on */ CAddonDll::Destroy(); + if (m_menuhooks) + m_menuhooks->Clear(); + /* reset all properties to defaults */ ResetProperties(); } @@ -265,22 +269,31 @@ void CPVRClient::WriteClientRecordingInfo(const CPVRRecording &xbmcRecording, PV xbmcRecording.RecordingTimeAsUTC().GetAsTime(recTime); addonRecording = {{0}}; - addonRecording.recordingTime = recTime - CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_iPVRTimeCorrection; strncpy(addonRecording.strRecordingId, xbmcRecording.m_strRecordingId.c_str(), sizeof(addonRecording.strRecordingId) - 1); strncpy(addonRecording.strTitle, xbmcRecording.m_strTitle.c_str(), sizeof(addonRecording.strTitle) - 1); + strncpy(addonRecording.strEpisodeName, xbmcRecording.m_strShowTitle.c_str(), sizeof(addonRecording.strEpisodeName) - 1); + addonRecording.iSeriesNumber = xbmcRecording.m_iSeason; + addonRecording.iEpisodeNumber = xbmcRecording.m_iEpisode; + addonRecording.iYear = xbmcRecording.GetYear(); + strncpy(addonRecording.strDirectory, xbmcRecording.m_strDirectory.c_str(), sizeof(addonRecording.strDirectory) - 1); strncpy(addonRecording.strPlotOutline, xbmcRecording.m_strPlotOutline.c_str(), sizeof(addonRecording.strPlotOutline) - 1); strncpy(addonRecording.strPlot, xbmcRecording.m_strPlot.c_str(), sizeof(addonRecording.strPlot) - 1); + strncpy(addonRecording.strGenreDescription, xbmcRecording.GetGenresLabel().c_str(), sizeof(addonRecording.strGenreDescription) - 1); strncpy(addonRecording.strChannelName, xbmcRecording.m_strChannelName.c_str(), sizeof(addonRecording.strChannelName) - 1); - addonRecording.iDuration = xbmcRecording.GetDuration(); - addonRecording.iPriority = xbmcRecording.m_iPriority; - addonRecording.iLifetime = xbmcRecording.m_iLifetime; - addonRecording.iPlayCount = xbmcRecording.GetLocalPlayCount(); - addonRecording.iLastPlayedPosition = lrint(xbmcRecording.GetLocalResumePoint().timeInSeconds); - addonRecording.bIsDeleted = xbmcRecording.IsDeleted(); - strncpy(addonRecording.strDirectory, xbmcRecording.m_strDirectory.c_str(), sizeof(addonRecording.strDirectory) - 1); strncpy(addonRecording.strIconPath, xbmcRecording.m_strIconPath.c_str(), sizeof(addonRecording.strIconPath) - 1); strncpy(addonRecording.strThumbnailPath, xbmcRecording.m_strThumbnailPath.c_str(), sizeof(addonRecording.strThumbnailPath) - 1); strncpy(addonRecording.strFanartPath, xbmcRecording.m_strFanartPath.c_str(), sizeof(addonRecording.strFanartPath) - 1); + addonRecording.recordingTime = recTime - CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_iPVRTimeCorrection; + addonRecording.iDuration = xbmcRecording.GetDuration(); + addonRecording.iPriority = xbmcRecording.m_iPriority; + addonRecording.iLifetime = xbmcRecording.m_iLifetime; + addonRecording.iGenreType = xbmcRecording.GenreType(); + addonRecording.iGenreSubType = xbmcRecording.GenreSubType(); + addonRecording.iPlayCount = xbmcRecording.GetLocalPlayCount(); + addonRecording.iLastPlayedPosition = lrint(xbmcRecording.GetLocalResumePoint().timeInSeconds); + addonRecording.bIsDeleted = xbmcRecording.IsDeleted(); + addonRecording.iChannelUid = xbmcRecording.ChannelUid(); + addonRecording.channelType = xbmcRecording.IsRadio() ? PVR_RECORDING_CHANNEL_TYPE_RADIO : PVR_RECORDING_CHANNEL_TYPE_TV; } /*! @@ -595,45 +608,6 @@ PVR_ERROR CPVRClient::RenameChannel(const CPVRChannelPtr &channel) }, m_clientCapabilities.SupportsChannelSettings()); } -PVR_ERROR CPVRClient::CallMenuHook(const PVR_MENUHOOK &hook, const CFileItemPtr item) -{ - return DoAddonCall(__FUNCTION__, [&hook, item](const AddonInstance* addon) { - PVR_MENUHOOK_DATA hookData; - hookData.cat = PVR_MENUHOOK_UNKNOWN; - - if (item) - { - if (item->IsEPG()) - { - hookData.cat = PVR_MENUHOOK_EPG; - hookData.data.iEpgUid = item->GetEPGInfoTag()->UniqueBroadcastID(); - } - else if (item->IsPVRChannel()) - { - hookData.cat = PVR_MENUHOOK_CHANNEL; - WriteClientChannelInfo(item->GetPVRChannelInfoTag(), hookData.data.channel); - } - else if (item->IsUsablePVRRecording()) - { - hookData.cat = PVR_MENUHOOK_RECORDING; - WriteClientRecordingInfo(*item->GetPVRRecordingInfoTag(), hookData.data.recording); - } - else if (item->IsDeletedPVRRecording()) - { - hookData.cat = PVR_MENUHOOK_DELETED_RECORDING; - WriteClientRecordingInfo(*item->GetPVRRecordingInfoTag(), hookData.data.recording); - } - else if (item->IsPVRTimer()) - { - hookData.cat = PVR_MENUHOOK_TIMER; - WriteClientTimerInfo(*item->GetPVRTimerInfoTag(), hookData.data.timer); - } - } - - return addon->MenuHook(hook, hookData); - }); -} - PVR_ERROR CPVRClient::GetEPGForChannel(const CPVRChannelPtr &channel, CPVREpg *epg, time_t start /* = 0 */, time_t end /* = 0 */, bool bSaveInDb /* = false*/) { return DoAddonCall(__FUNCTION__, [this, channel, epg, start, end, bSaveInDb](const AddonInstance* addon) { @@ -682,7 +656,8 @@ public: m_strIMDBNumber(kodiTag->IMDBNumber()), m_strEpisodeName(kodiTag->EpisodeName(true)), m_strIconPath(kodiTag->Icon()), - m_strSeriesLink(kodiTag->SeriesLink()) + m_strSeriesLink(kodiTag->SeriesLink()), + m_strGenreDescription(kodiTag->GetGenresLabel()) { time_t t; kodiTag->StartAsUTC().GetAsTime(t); @@ -714,6 +689,7 @@ public: strEpisodeName = m_strEpisodeName.c_str(); strIconPath = m_strIconPath.c_str(); strSeriesLink = m_strSeriesLink.c_str(); + strGenreDescription = m_strGenreDescription.c_str(); } virtual ~CAddonEpgTag() = default; @@ -730,6 +706,7 @@ private: std::string m_strEpisodeName; std::string m_strIconPath; std::string m_strSeriesLink; + std::string m_strGenreDescription; }; PVR_ERROR CPVRClient::IsRecordable(const CConstPVREpgInfoTagPtr &tag, bool &bIsRecordable) const @@ -1183,28 +1160,6 @@ PVR_ERROR CPVRClient::DemuxRead(DemuxPacket* &packet) }, m_clientCapabilities.HandlesDemuxing()); } -bool CPVRClient::HasMenuHooks(PVR_MENUHOOK_CAT cat) const -{ - bool bReturn(false); - if (m_bReadyToUse && !m_menuhooks.empty()) - { - for (auto hook : m_menuhooks) - { - if (hook.category == cat || hook.category == PVR_MENUHOOK_ALL) - { - bReturn = true; - break; - } - } - } - return bReturn; -} - -PVR_MENUHOOKS& CPVRClient::GetMenuHooks(void) -{ - return m_menuhooks; -} - const char *CPVRClient::ToString(const PVR_ERROR error) { switch (error) @@ -1392,6 +1347,67 @@ PVR_ERROR CPVRClient::OnPowerSavingDeactivated() }); } +std::shared_ptr<CPVRClientMenuHooks> CPVRClient::GetMenuHooks() +{ + if (!m_menuhooks) + m_menuhooks.reset(new CPVRClientMenuHooks(ID())); + + return m_menuhooks; +} + +PVR_ERROR CPVRClient::CallMenuHook(const CPVRClientMenuHook &hook, const CFileItemPtr &item) +{ + return DoAddonCall(__FUNCTION__, [&hook, &item](const AddonInstance* addon) { + PVR_MENUHOOK_DATA hookData; + hookData.cat = PVR_MENUHOOK_UNKNOWN; + + if (item) + { + if (item->IsEPG()) + { + hookData.cat = PVR_MENUHOOK_EPG; + hookData.data.iEpgUid = item->GetEPGInfoTag()->UniqueBroadcastID(); + } + else if (item->IsPVRChannel()) + { + hookData.cat = PVR_MENUHOOK_CHANNEL; + WriteClientChannelInfo(item->GetPVRChannelInfoTag(), hookData.data.channel); + } + else if (item->IsUsablePVRRecording()) + { + hookData.cat = PVR_MENUHOOK_RECORDING; + WriteClientRecordingInfo(*item->GetPVRRecordingInfoTag(), hookData.data.recording); + } + else if (item->IsDeletedPVRRecording()) + { + hookData.cat = PVR_MENUHOOK_DELETED_RECORDING; + WriteClientRecordingInfo(*item->GetPVRRecordingInfoTag(), hookData.data.recording); + } + else if (item->IsPVRTimer()) + { + hookData.cat = PVR_MENUHOOK_TIMER; + WriteClientTimerInfo(*item->GetPVRTimerInfoTag(), hookData.data.timer); + } + else + { + CLog::LogF(LOGERROR, "Unhandled item type."); + return PVR_ERROR_INVALID_PARAMETERS; + } + } + else + { + hookData.cat = PVR_MENUHOOK_SETTING; + } + + PVR_MENUHOOK menuHook = {0}; + menuHook.category = hookData.cat; + menuHook.iHookId = hook.GetId(); + menuHook.iLocalizedStringId = hook.GetLabelId(); + + return addon->MenuHook(menuHook, hookData); + }); +} + void CPVRClient::SetPriority(int iPriority) { CSingleLock lock(m_critSection); @@ -1566,15 +1582,7 @@ void CPVRClient::cb_add_menu_hook(void *kodiInstance, PVR_MENUHOOK *hook) return; } - PVR_MENUHOOKS& hooks = client->GetMenuHooks(); - - PVR_MENUHOOK hookInt; - hookInt.iHookId = hook->iHookId; - hookInt.iLocalizedStringId = hook->iLocalizedStringId; - hookInt.category = hook->category; - - /* add this new hook */ - hooks.emplace_back(hookInt); + client->GetMenuHooks()->AddHook(*hook); } void CPVRClient::cb_recording(void *kodiInstance, const char *strName, const char *strFileName, bool bOnOff) diff --git a/xbmc/addons/PVRClient.h b/xbmc/addons/PVRClient.h index e1cadaf779..5a5670cdd1 100644 --- a/xbmc/addons/PVRClient.h +++ b/xbmc/addons/PVRClient.h @@ -23,8 +23,8 @@ namespace PVR { class CPVRChannelGroups; class CPVRTimersContainer; - - typedef std::vector<PVR_MENUHOOK> PVR_MENUHOOKS; + class CPVRClientMenuHook; + class CPVRClientMenuHooks; class CPVRClient; typedef std::shared_ptr<CPVRClient> CPVRClientPtr; @@ -394,24 +394,6 @@ namespace PVR */ PVR_ERROR FillEpgTagStreamFileItem(CFileItem &fileItem); - /*! - * @return True if this add-on has menu hooks, false otherwise. - */ - bool HasMenuHooks(PVR_MENUHOOK_CAT cat) const; - - /*! - * @return The menu hooks for this add-on. - */ - PVR_MENUHOOKS& GetMenuHooks(); - - /*! - * @brief Call one of the menu hooks of this client. - * @param hook The hook to call. - * @param item The selected file item for which the hook was called. - * @return PVR_ERROR_NO_ERROR on success, respective error code otherwise. - */ - PVR_ERROR CallMenuHook(const PVR_MENUHOOK &hook, const CFileItemPtr item); - //@} /** @name PVR EPG methods */ //@{ @@ -456,7 +438,7 @@ namespace PVR /*! * @brief Request the list of all group members from the backend. - * @param groups The group to get the members for. + * @param group The group to get the members for. * @return PVR_ERROR_NO_ERROR if the list has been fetched successfully. */ PVR_ERROR GetChannelGroupMembers(CPVRChannelGroup *group); @@ -545,7 +527,7 @@ namespace PVR /*! * @brief Set the last watched position of a recording on the backend. * @param recording The recording. - * @param position The last watched position in seconds + * @param lastplayedposition The last watched position in seconds * @return PVR_ERROR_NO_ERROR if the position has been stored successfully. */ PVR_ERROR SetRecordingLastPlayedPosition(const CPVRRecording &recording, int lastplayedposition); @@ -679,7 +661,7 @@ namespace PVR /*! * @brief Get the descramble information of the stream that's currently open. - * @param qualityinfo The descramble information. + * @param descrambleinfo The descramble information. * @return PVR_ERROR_NO_ERROR on success, respective error code otherwise. */ PVR_ERROR GetDescrambleInfo(PVR_DESCRAMBLE_INFO &descrambleinfo) const; @@ -824,6 +806,20 @@ namespace PVR bool GetAddonProperties(void); /*! + * @brief Get the client's menu hooks. + * @return The hooks. Guaranteed never to be null. + */ + std::shared_ptr<CPVRClientMenuHooks> GetMenuHooks(); + + /*! + * @brief Call one of the menu hooks of the client. + * @param hook The hook to call. + * @param item The item associated with the hook to be called. + * @return PVR_ERROR_NO_ERROR on success, respective error code otherwise. + */ + PVR_ERROR CallMenuHook(const CPVRClientMenuHook &hook, const CFileItemPtr &item); + + /*! * @brief Propagate power management events to this add-on * @return PVR_ERROR_NO_ERROR on success, respective error code otherwise. */ @@ -1071,7 +1067,6 @@ namespace PVR PVR_CONNECTION_STATE m_connectionState; /*!< the backend connection state */ PVR_CONNECTION_STATE m_prevConnectionState; /*!< the previous backend connection state */ bool m_ignoreClient; /*!< signals to PVRManager to ignore this client until it has been connected */ - PVR_MENUHOOKS m_menuhooks; /*!< the menu hooks for this add-on */ CPVRTimerTypes m_timertypes; /*!< timer types supported by this backend */ int m_iClientId; /*!< unique ID of the client */ mutable int m_iPriority; /*!< priority of the client */ @@ -1084,6 +1079,7 @@ namespace PVR std::string m_strFriendlyName; /*!< the cached friendly name */ std::string m_strBackendHostname; /*!< the cached backend hostname */ CPVRClientCapabilities m_clientCapabilities; /*!< the cached add-on's capabilities */ + std::shared_ptr<CPVRClientMenuHooks> m_menuhooks; /*!< the menu hooks for this add-on */ /* stored strings to make sure const char* members in PVR_PROPERTIES stay valid */ std::string m_strUserPath; /*!< @brief translated path to the user profile */ diff --git a/xbmc/addons/PVRClientMenuHooks.cpp b/xbmc/addons/PVRClientMenuHooks.cpp new file mode 100644 index 0000000000..dfabdc7d5a --- /dev/null +++ b/xbmc/addons/PVRClientMenuHooks.cpp @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2012-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "PVRClientMenuHooks.h" + +#include "pvr/PVRContextMenus.h" + +#include "addons/kodi-addon-dev-kit/include/kodi/xbmc_pvr_types.h" +#include "guilib/LocalizeStrings.h" +#include "utils/log.h" + +namespace PVR +{ + +CPVRClientMenuHook::CPVRClientMenuHook(const std::string &addonId, const PVR_MENUHOOK &hook) +: m_addonId(addonId), + m_hook(new PVR_MENUHOOK(hook)) +{ + if (hook.category != PVR_MENUHOOK_UNKNOWN && + hook.category != PVR_MENUHOOK_ALL && + hook.category != PVR_MENUHOOK_CHANNEL && + hook.category != PVR_MENUHOOK_TIMER && + hook.category != PVR_MENUHOOK_EPG && + hook.category != PVR_MENUHOOK_RECORDING && + hook.category != PVR_MENUHOOK_RECORDING && + hook.category != PVR_MENUHOOK_SETTING) + CLog::LogF(LOGERROR, "Unknown PVR_MENUHOOK_CAT value: %d", hook.category); +} + +bool CPVRClientMenuHook::operator ==(const CPVRClientMenuHook& right) const +{ + if (this == &right) + return true; + + return m_addonId == right.m_addonId && + m_hook->iHookId == right.m_hook->iHookId && + m_hook->iLocalizedStringId == right.m_hook->iLocalizedStringId && + m_hook->category == right.m_hook->category; +} + +bool CPVRClientMenuHook::IsAllHook() const +{ + return m_hook->category == PVR_MENUHOOK_ALL; +} + +bool CPVRClientMenuHook::IsChannelHook() const +{ + return m_hook->category == PVR_MENUHOOK_CHANNEL; +} + +bool CPVRClientMenuHook::IsTimerHook() const +{ + return m_hook->category == PVR_MENUHOOK_TIMER; +} + +bool CPVRClientMenuHook::IsEpgHook() const +{ + return m_hook->category == PVR_MENUHOOK_EPG; +} + +bool CPVRClientMenuHook::IsRecordingHook() const +{ + return m_hook->category == PVR_MENUHOOK_RECORDING; +} + +bool CPVRClientMenuHook::IsDeletedRecordingHook() const +{ + return m_hook->category == PVR_MENUHOOK_DELETED_RECORDING; +} + +bool CPVRClientMenuHook::IsSettingsHook() const +{ + return m_hook->category == PVR_MENUHOOK_SETTING; +} + +unsigned int CPVRClientMenuHook::GetId() const +{ + return m_hook->iHookId; +} + +unsigned int CPVRClientMenuHook::GetLabelId() const +{ + return m_hook->iLocalizedStringId; +} + +std::string CPVRClientMenuHook::GetLabel() const +{ + return g_localizeStrings.GetAddonString(m_addonId, m_hook->iLocalizedStringId); +} + +void CPVRClientMenuHooks::AddHook(const PVR_MENUHOOK &addonHook) +{ + if (!m_hooks) + m_hooks.reset(new std::vector<CPVRClientMenuHook>()); + + const CPVRClientMenuHook hook(m_addonId, addonHook); + m_hooks->emplace_back(hook); + CPVRContextMenuManager::GetInstance().AddMenuHook(hook); +} + +void CPVRClientMenuHooks::Clear() +{ + if (!m_hooks) + return; + + for (const auto& hook : *m_hooks) + CPVRContextMenuManager::GetInstance().RemoveMenuHook(hook); + + m_hooks.reset(); +} + +std::vector<CPVRClientMenuHook> CPVRClientMenuHooks::GetHooks(std::function<bool(const CPVRClientMenuHook& hook)> function) const +{ + std::vector<CPVRClientMenuHook> hooks; + + if (!m_hooks) + return hooks; + + for (const CPVRClientMenuHook& hook : *m_hooks) + { + if (function(hook) || hook.IsAllHook()) + hooks.emplace_back(hook); + } + return hooks; +} + +std::vector<CPVRClientMenuHook> CPVRClientMenuHooks::GetChannelHooks() const +{ + return GetHooks([](const CPVRClientMenuHook& hook) + { + return hook.IsChannelHook(); + }); +} + +std::vector<CPVRClientMenuHook> CPVRClientMenuHooks::GetTimerHooks() const +{ + return GetHooks([](const CPVRClientMenuHook& hook) + { + return hook.IsTimerHook(); + }); +} + +std::vector<CPVRClientMenuHook> CPVRClientMenuHooks::GetEpgHooks() const +{ + return GetHooks([](const CPVRClientMenuHook& hook) + { + return hook.IsEpgHook(); + }); +} + +std::vector<CPVRClientMenuHook> CPVRClientMenuHooks::GetRecordingHooks() const +{ + return GetHooks([](const CPVRClientMenuHook& hook) + { + return hook.IsRecordingHook(); + }); +} + +std::vector<CPVRClientMenuHook> CPVRClientMenuHooks::GetDeletedRecordingHooks() const +{ + return GetHooks([](const CPVRClientMenuHook& hook) + { + return hook.IsDeletedRecordingHook(); + }); +} + +std::vector<CPVRClientMenuHook> CPVRClientMenuHooks::GetSettingsHooks() const +{ + return GetHooks([](const CPVRClientMenuHook& hook) + { + return hook.IsSettingsHook(); + }); +} + +} // namespace PVR diff --git a/xbmc/addons/PVRClientMenuHooks.h b/xbmc/addons/PVRClientMenuHooks.h new file mode 100644 index 0000000000..cae91fe1f7 --- /dev/null +++ b/xbmc/addons/PVRClientMenuHooks.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2012-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include <functional> +#include <memory> +#include <string> +#include <vector> + +struct PVR_MENUHOOK; + +namespace PVR +{ + class CPVRClientMenuHook + { + public: + CPVRClientMenuHook() = delete; + virtual ~CPVRClientMenuHook() = default; + + CPVRClientMenuHook(const std::string &addonId, const PVR_MENUHOOK &hook); + + bool operator ==(const CPVRClientMenuHook& right) const; + + bool IsAllHook() const; + bool IsChannelHook() const; + bool IsTimerHook() const; + bool IsEpgHook() const; + bool IsRecordingHook() const; + bool IsDeletedRecordingHook() const; + bool IsSettingsHook() const; + + unsigned int GetId() const; + unsigned int GetLabelId() const; + std::string GetLabel() const; + + private: + std::string m_addonId; + std::shared_ptr<PVR_MENUHOOK> m_hook; + }; + + class CPVRClientMenuHooks + { + public: + CPVRClientMenuHooks() = default; + virtual ~CPVRClientMenuHooks() = default; + + explicit CPVRClientMenuHooks(const std::string &addonId) : m_addonId(addonId) {} + + void AddHook(const PVR_MENUHOOK &addonHook); + void Clear(); + + std::vector<CPVRClientMenuHook> GetChannelHooks() const; + std::vector<CPVRClientMenuHook> GetTimerHooks() const; + std::vector<CPVRClientMenuHook> GetEpgHooks() const; + std::vector<CPVRClientMenuHook> GetRecordingHooks() const; + std::vector<CPVRClientMenuHook> GetDeletedRecordingHooks() const; + std::vector<CPVRClientMenuHook> GetSettingsHooks() const; + + private: + std::vector<CPVRClientMenuHook> GetHooks(std::function<bool(const CPVRClientMenuHook& hook)> function) const; + + std::string m_addonId; + std::unique_ptr<std::vector<CPVRClientMenuHook>> m_hooks; + }; +} diff --git a/xbmc/addons/Repository.cpp b/xbmc/addons/Repository.cpp index dd5e27525b..2d50e57b93 100644 --- a/xbmc/addons/Repository.cpp +++ b/xbmc/addons/Repository.cpp @@ -286,6 +286,10 @@ bool CRepositoryUpdateJob::DoWork() if (database.GetRepoChecksum(m_repo->ID(), oldChecksum) == -1) oldChecksum = ""; + std::pair<CDateTime, ADDON::AddonVersion> lastCheck = database.LastChecked(m_repo->ID()); + if (lastCheck.second != m_repo->Version()) + oldChecksum = ""; + std::string newChecksum; VECADDONS addons; auto status = m_repo->FetchIfChanged(oldChecksum, newChecksum, addons); diff --git a/xbmc/addons/Repository.h b/xbmc/addons/Repository.h index 6fe7731f82..6f61a25a1b 100644 --- a/xbmc/addons/Repository.h +++ b/xbmc/addons/Repository.h @@ -41,11 +41,6 @@ namespace ADDON explicit CRepository(CAddonInfo addonInfo) : CAddon(std::move(addonInfo)) {}; CRepository(CAddonInfo addonInfo, DirList dirs); - /*! \brief Get the md5 hash for an addon. - \param the addon in question. - */ - bool GetAddonHash(const AddonPtr& addon, std::string& checksum) const; - enum FetchStatus { STATUS_OK, diff --git a/xbmc/addons/VFSEntry.h b/xbmc/addons/VFSEntry.h index ec7a029680..b1140c25e0 100644 --- a/xbmc/addons/VFSEntry.h +++ b/xbmc/addons/VFSEntry.h @@ -87,7 +87,7 @@ namespace ADDON void ClearOutIdle(); void DisconnectAll(); - bool ContainsFiles(const CURL& path, CFileItemList& items); + bool ContainsFiles(const CURL& url, CFileItemList& items); const std::string& GetProtocols() const { return m_protocols; } const std::string& GetExtensions() const { return m_extensions; } @@ -208,19 +208,19 @@ namespace ADDON //! \param[in] url URL to file to list. //! \param items List of items in file. //! \return True if listing succeeded, false otherwise. - bool GetDirectory(const CURL& strPath, CFileItemList& items) override; + bool GetDirectory(const CURL& url, CFileItemList& items) override; //! \brief Check if directory exists. //! \param[in] url URL to check. - bool Exists(const CURL& strPath) override; + bool Exists(const CURL& url) override; //! \brief Delete directory. //! \param[in] url URL to delete. - bool Remove(const CURL& strPath) override; + bool Remove(const CURL& url) override; //! \brief Create directory. //! \param[in] url URL to delete. - bool Create(const CURL& strPath) override; + bool Create(const CURL& url) override; //! \brief Static helper for doing a keyboard callback. static bool DoGetKeyboardInput(void* context, const char* heading, @@ -262,7 +262,7 @@ namespace ADDON ~CVFSEntryIFileDirectoryWrapper() override = default; //! \brief Check if the given file should be treated as a directory. - //! \param[in] URL URL for file to probe. + //! \param[in] url URL for file to probe. bool ContainsFiles(const CURL& url) override { return m_addon->ContainsFiles(url, m_items); diff --git a/xbmc/addons/kodi-addon-dev-kit/doxygen/Modules/modules_python.dox b/xbmc/addons/kodi-addon-dev-kit/doxygen/Modules/modules_python.dox index 18d28435ad..eb79674b48 100644 --- a/xbmc/addons/kodi-addon-dev-kit/doxygen/Modules/modules_python.dox +++ b/xbmc/addons/kodi-addon-dev-kit/doxygen/Modules/modules_python.dox @@ -151,6 +151,16 @@ web applications or frameworks for the Python programming language. */ /*! @page python_v17 Python API v17 +\python_removed_function{ + getCaptureState, + http://mirrors.kodi.tv/docs/python-docs/16.x-jarvis/xbmc.html#RenderCapture-getCaptureState, + <b>xbmc.RenderCapture().getCaptureState()</b> function was removed completely. +} +\python_removed_function{ + waitForCaptureStateChangeEvent, + http://mirrors.kodi.tv/docs/python-docs/16.x-jarvis/xbmc.html#RenderCapture-waitForCaptureStateChangeEvent, + <b>xbmc.RenderCapture().waitForCaptureStateChangeEvent()</b> function was removed completely. +} */ /*! @page python_v16 Python API v16 diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Peripheral.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Peripheral.h index 78e572b638..2df8a3678d 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Peripheral.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Peripheral.h @@ -531,8 +531,7 @@ namespace addon virtual void FreeEvents(unsigned int event_count, PERIPHERAL_EVENT* events) { } /*! - * @brief Send an input event to the specified peripheral - * @param peripheralIndex The index of the device receiving the input event + * @brief Send an input event to the peripheral * @param event The input event * @return true if the event was handled, false otherwise */ @@ -677,9 +676,9 @@ namespace addon * @param[optional] deviceName The name of the device to refresh, or empty/null for all devices * @param[optional] controllerId The controller ID to refresh, or empty/null for all controllers */ - void RefreshButtonMaps(const std::string& strDeviceName = "", const std::string& strControllerId = "") + void RefreshButtonMaps(const std::string& deviceName = "", const std::string& controllerId = "") { - return m_instanceData->toKodi.refresh_button_maps(m_instanceData->toKodi.kodiInstance, strDeviceName.c_str(), strControllerId.c_str()); + return m_instanceData->toKodi.refresh_button_maps(m_instanceData->toKodi.kodiInstance, deviceName.c_str(), controllerId.c_str()); } /*! @@ -690,9 +689,9 @@ namespace addon * * @return The number of features matching the request parameters */ - unsigned int FeatureCount(const std::string& strControllerId, JOYSTICK_FEATURE_TYPE type = JOYSTICK_FEATURE_TYPE_UNKNOWN) + unsigned int FeatureCount(const std::string& controllerId, JOYSTICK_FEATURE_TYPE type = JOYSTICK_FEATURE_TYPE_UNKNOWN) { - return m_instanceData->toKodi.feature_count(m_instanceData->toKodi.kodiInstance, strControllerId.c_str(), type); + return m_instanceData->toKodi.feature_count(m_instanceData->toKodi.kodiInstance, controllerId.c_str(), type); } /*! @@ -704,9 +703,9 @@ namespace addon * @return The type of the specified feature, or JOYSTICK_FEATURE_TYPE_UNKNOWN * if unknown */ - JOYSTICK_FEATURE_TYPE FeatureType(const std::string& strControllerId, const std::string &featureName) + JOYSTICK_FEATURE_TYPE FeatureType(const std::string& controllerId, const std::string &featureName) { - return m_instanceData->toKodi.feature_type(m_instanceData->toKodi.kodiInstance, strControllerId.c_str(), featureName.c_str()); + return m_instanceData->toKodi.feature_type(m_instanceData->toKodi.kodiInstance, controllerId.c_str(), featureName.c_str()); } private: diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_game_dll.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_game_dll.h index 40979e5e6c..4338606f42 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_game_dll.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_game_dll.h @@ -59,7 +59,7 @@ GAME_ERROR UnloadGame(void); /*! * \brief Get timing information about the loaded game * - * \param info The info structure to fill + * \param[out] timing_info The info structure to fill * * \return the error, or GAME_ERROR_NO_ERROR if info was filled */ @@ -153,31 +153,43 @@ game_input_topology* GetTopology(); void FreeTopology(game_input_topology* topology); /*! + * \brief Set the layouts for known controllers + * + * \param controllers The controller layouts + * \param controller_count The number of items in the array + * + * After loading the input topology, the frontend will call this with + * controller layouts for all controllers discovered in the topology. + */ +void SetControllerLayouts(const game_controller_layout* controllers, unsigned int controller_count); + +/*! * \brief Enable/disable keyboard input using the specified controller * * \param enable True to enable input, false otherwise - * \param controller The controller info if enabling, or unused if disabling + * \param controller_id The controller ID if enabling, or unused if disabling * * \return True if keyboard input was enabled, false otherwise */ -bool EnableKeyboard(bool enable, const game_controller* controller); +bool EnableKeyboard(bool enable, const char* controller_id); /*! * \brief Enable/disable mouse input using the specified controller * * \param enable True to enable input, false otherwise - * \param controller The controller info if enabling, or unused if disabling + * \param controller_id The controller ID if enabling, or unused if disabling * * \return True if mouse input was enabled, false otherwise */ -bool EnableMouse(bool enable, const game_controller* controller); +bool EnableMouse(bool enable, const char* controller_id); /*! * \brief Connect/disconnect a controller to a port on the virtual game console * * \param connect True to connect a controller, false to disconnect - * \param address The address of the port - * \param controller The controller info if connecting, or unused if disconnecting + * \param port_address The address of the port + * \param controller_id The controller ID if connecting, or unused if disconnecting + * \return True if the \p controller was (dis-)connected to the port, false otherwise * * The address is a string that allows traversal of the controller topology. * It is formed by alternating port IDs and controller IDs separated by "/". @@ -202,17 +214,17 @@ bool EnableMouse(bool enable, const game_controller* controller); * To connect a multitap to the console's first port, the multitap's controller * info is set using the port address: * - * 1 + * /1 * * To connect a SNES controller to the second port of the multitap, the * controller info is next set using the address: * - * 1/game.controller.multitap/2 + * /1/game.controller.multitap/2 * * Any attempts to connect a controller to a port on a disconnected multitap * will return false. */ -bool ConnectController(bool connect, const char* port_address, const game_controller* controller); +bool ConnectController(bool connect, const char* port_address, const char* controller_id); /*! * \brief Notify the add-on of an input event @@ -309,6 +321,7 @@ void __declspec(dllexport) get_addon(void* ptr) pClient->toAddon.HasFeature = HasFeature; pClient->toAddon.GetTopology = GetTopology; pClient->toAddon.FreeTopology = FreeTopology; + pClient->toAddon.SetControllerLayouts = SetControllerLayouts; pClient->toAddon.EnableKeyboard = EnableKeyboard; pClient->toAddon.EnableMouse = EnableMouse; pClient->toAddon.ConnectController = ConnectController; diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_game_types.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_game_types.h index e3187d2d78..ec9d472dea 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_game_types.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_game_types.h @@ -446,19 +446,27 @@ typedef enum GAME_PORT_TYPE GAME_PORT_CONTROLLER, } GAME_PORT_TYPE; -typedef struct game_controller +typedef struct game_controller_layout { - const char* controller_id; + char* controller_id; bool provides_input; // False for multitaps + char** digital_buttons; unsigned int digital_button_count; + char** analog_buttons; unsigned int analog_button_count; + char** analog_sticks; unsigned int analog_stick_count; + char** accelerometers; unsigned int accelerometer_count; + char** keys; unsigned int key_count; + char** rel_pointers; unsigned int rel_pointer_count; + char** abs_pointers; unsigned int abs_pointer_count; + char** motors; unsigned int motor_count; -} ATTRIBUTE_PACKED game_controller; +} ATTRIBUTE_PACKED game_controller_layout; struct game_input_port; @@ -680,9 +688,10 @@ typedef struct KodiToAddonFuncTable_Game bool (__cdecl* HasFeature)(const char*, const char*); game_input_topology* (__cdecl* GetTopology)(); void (__cdecl* FreeTopology)(game_input_topology*); - bool (__cdecl* EnableKeyboard)(bool, const game_controller*); - bool (__cdecl* EnableMouse)(bool, const game_controller*); - bool (__cdecl* ConnectController)(bool, const char*, const game_controller*); + void (__cdecl* SetControllerLayouts)(const game_controller_layout*, unsigned int); + bool (__cdecl* EnableKeyboard)(bool, const char*); + bool (__cdecl* EnableMouse)(bool, const char*); + bool (__cdecl* ConnectController)(bool, const char*, const char*); bool (__cdecl* InputEvent)(const game_input_event*); size_t (__cdecl* SerializeSize)(void); GAME_ERROR (__cdecl* Serialize)(uint8_t*, size_t); diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_game.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_game.h index ca8cba9804..2e6459b486 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_game.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_game.h @@ -123,7 +123,7 @@ public: /*! * \brief Get a symbol from the hardware context * - * \param symbol The symbol's name + * \param sym The symbol's name * * \return A function pointer for the specified symbol */ @@ -135,15 +135,15 @@ public: // --- Input callbacks ------------------------------------------------------- /*! - * \brief Notify the port of an input event - * - * \param event The input event - * - * Input events can arrive for the following sources: - * - GAME_INPUT_EVENT_MOTOR - * - * \return true if the event was handled, false otherwise - */ + * \brief Notify the port of an input event + * + * \param event The input event + * + * Input events can arrive for the following sources: + * - GAME_INPUT_EVENT_MOTOR + * + * \return true if the event was handled, false otherwise + */ bool InputEvent(const game_input_event& event) { return m_callbacks->toKodi.InputEvent(m_callbacks->toKodi.kodiInstance, &event); diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h index 5127f7edca..1c706514ef 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h @@ -75,8 +75,8 @@ #define ADDON_INSTANCE_VERSION_AUDIOENCODER_XML_ID "kodi.binary.instance.audioencoder" #define ADDON_INSTANCE_VERSION_AUDIOENCODER_DEPENDS "addon-instance/AudioEncoder.h" -#define ADDON_INSTANCE_VERSION_GAME "1.0.38" -#define ADDON_INSTANCE_VERSION_GAME_MIN "1.0.38" +#define ADDON_INSTANCE_VERSION_GAME "1.1.0" +#define ADDON_INSTANCE_VERSION_GAME_MIN "1.1.0" #define ADDON_INSTANCE_VERSION_GAME_XML_ID "kodi.binary.instance.game" #define ADDON_INSTANCE_VERSION_GAME_DEPENDS "kodi_game_dll.h" \ "kodi_game_types.h" \ diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_pvr_dll.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_pvr_dll.h index 870f8c3f7d..27fa800af9 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_pvr_dll.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_pvr_dll.h @@ -316,7 +316,7 @@ extern "C" /*! * Set the last watched position of a recording on the backend. * @param recording The recording. - * @param position The last watched position in seconds + * @param lastplayedposition The last watched position in seconds * @return PVR_ERROR_NO_ERROR if the position has been stored successfully. * @remarks Required if bSupportsLastPlayedPosition is set to true. * Return PVR_ERROR_NOT_IMPLEMENTED if this add-on won't provide this function. @@ -483,7 +483,7 @@ extern "C" /*! * Get the stream properties for a recording from the backend. - * @param[in] channel The recording to get the stream properties for. + * @param[in] recording The recording to get the stream properties for. * @param[inout] properties in: an array for the properties to return, out: the properties required to play the stream. * @param[inout] iPropertiesCount in: the size of the properties array, out: the number of properties returned. * @return PVR_ERROR_NO_ERROR if the stream is available. diff --git a/xbmc/cores/AudioEngine/CMakeLists.txt b/xbmc/cores/AudioEngine/CMakeLists.txt index af0d552d7c..060c6a960d 100644 --- a/xbmc/cores/AudioEngine/CMakeLists.txt +++ b/xbmc/cores/AudioEngine/CMakeLists.txt @@ -48,11 +48,14 @@ set(HEADERS AEResampleFactory.h if(ALSA_FOUND) list(APPEND SOURCES Sinks/AESinkALSA.cpp - Sinks/alsa/ALSAHControlMonitor.cpp Utils/AEELDParser.cpp) list(APPEND HEADERS Sinks/AESinkALSA.h - Sinks/alsa/ALSAHControlMonitor.h Utils/AEELDParser.h) + + if(NOT CORE_PLATFORM_NAME_LC STREQUAL x11) + list(APPEND SOURCES Sinks/alsa/ALSAHControlMonitor.cpp) + list(APPEND HEADERS Sinks/alsa/ALSAHControlMonitor.h) + endif() if(UDEV_FOUND) list(APPEND SOURCES Sinks/alsa/ALSADeviceMonitor.cpp) diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp index f6ea9ca88e..7f6a9de479 100644 --- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp +++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp @@ -2932,6 +2932,9 @@ bool CActiveAE::CompareFormat(AEAudioFormat &lhs, AEAudioFormat &rhs) lhs.m_dataFormat != rhs.m_dataFormat || lhs.m_sampleRate != rhs.m_sampleRate) return false; + else if (lhs.m_dataFormat == AE_FMT_RAW && rhs.m_dataFormat == AE_FMT_RAW && + lhs.m_streamInfo.m_type != rhs.m_streamInfo.m_type) + return false; else return true; } diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp index b1494a2722..44b5d5e326 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp @@ -1087,7 +1087,7 @@ bool CAESinkALSA::OpenPCMDevice(const std::string &name, const std::string ¶ void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) { -#if HAVE_LIBUDEV +#if defined(HAVE_LIBUDEV) m_deviceMonitor.Start(); #endif @@ -1104,7 +1104,9 @@ void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) snd_config_t *config; snd_config_copy(&config, snd_config); +#if !defined(HAVE_X11) m_controlMonitor.Clear(); +#endif /* Always enumerate the default device. * Note: If "default" is a stereo device, EnumerateDevice() @@ -1183,7 +1185,9 @@ void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list, bool force) } snd_device_name_free_hint(hints); +#if !defined(HAVE_X11) m_controlMonitor.Start(); +#endif /* set the displayname for default device */ if (!list.empty() && list[0].m_deviceName == "default") @@ -1366,8 +1370,10 @@ void CAESinkALSA::EnumerateDevice(AEDeviceInfoList &list, const std::string &dev snd_hctl_load(hctl); bool badHDMI = false; +#if !defined(HAVE_X11) /* add ELD to monitoring */ m_controlMonitor.Add(strHwName, SND_CTL_ELEM_IFACE_PCM, dev, "ELD"); +#endif if (!GetELD(hctl, dev, info, badHDMI)) CLog::Log(LOGDEBUG, "CAESinkALSA - Unable to obtain ELD information for device \"%s\" (not supported by device, or kernel older than 3.2)", @@ -1616,11 +1622,17 @@ void CAESinkALSA::Cleanup() #if HAVE_LIBUDEV m_deviceMonitor.Stop(); #endif + +#if !defined(HAVE_X11) m_controlMonitor.Clear(); +#endif } #if HAVE_LIBUDEV CALSADeviceMonitor CAESinkALSA::m_deviceMonitor; // ARGH #endif + +#if !defined(HAVE_X11) CALSAHControlMonitor CAESinkALSA::m_controlMonitor; // ARGH +#endif diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp index db3d5b47ca..8362851119 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp @@ -1005,7 +1005,10 @@ void CAESinkAUDIOTRACK::UpdateAvailablePCMCapabilities() int encoding = CJNIAudioFormat::ENCODING_PCM_16BIT; m_sinkSupportsFloat = VerifySinkConfiguration(native_sampleRate, CJNIAudioFormat::CHANNEL_OUT_STEREO, CJNIAudioFormat::ENCODING_PCM_FLOAT); - m_sinkSupportsMultiChannelFloat = VerifySinkConfiguration(native_sampleRate, CJNIAudioFormat::CHANNEL_OUT_7POINT1_SURROUND, CJNIAudioFormat::ENCODING_PCM_FLOAT); + // Only try for Android 7 or later - there are a lot of old devices that open successfully + // but won't work correctly under the hood (famouse example: old FireTV) + if (CJNIAudioManager::GetSDKVersion() > 23) + m_sinkSupportsMultiChannelFloat = VerifySinkConfiguration(native_sampleRate, CJNIAudioFormat::CHANNEL_OUT_7POINT1_SURROUND, CJNIAudioFormat::ENCODING_PCM_FLOAT); if (m_sinkSupportsFloat) { diff --git a/xbmc/cores/AudioEngine/Utils/AEStreamInfo.cpp b/xbmc/cores/AudioEngine/Utils/AEStreamInfo.cpp index 1089f7e98f..3e3912fada 100644 --- a/xbmc/cores/AudioEngine/Utils/AEStreamInfo.cpp +++ b/xbmc/cores/AudioEngine/Utils/AEStreamInfo.cpp @@ -216,6 +216,8 @@ int CAEStreamParser::AddData(uint8_t *data, unsigned int size, uint8_t **buffer/ if (!m_needBytes) GetPacket(buffer, bufferSize); + else if (bufferSize) + *bufferSize = 0; return consumed; } @@ -284,7 +286,7 @@ unsigned int CAEStreamParser::DetectType(uint8_t *data, unsigned int size) if (data[0] == 0x0b && data[1] == 0x77) { unsigned int skip = SyncAC3(data, size); - if (m_hasSync) + if (m_hasSync || m_needBytes) return skipped + skip; else possible = skipped; @@ -309,155 +311,168 @@ unsigned int CAEStreamParser::DetectType(uint8_t *data, unsigned int size) return possible ? possible : skipped; } -unsigned int CAEStreamParser::SyncAC3(uint8_t *data, unsigned int size) +bool CAEStreamParser::TrySyncAC3(uint8_t *data, unsigned int size, bool resyncing, bool wantEAC3dependent) { - unsigned int skip = 0; + if (size < 8) + return false; - // handle substreams - if (m_fsizeMain) - { - data += m_fsizeMain; - } + /* look for an ac3 sync word */ + if (data[0] != 0x0b || data[1] != 0x77) + return false; - for (; size - skip > 7; ++skip, ++data) - { - /* search for an ac3 sync word */ - if (data[0] != 0x0b || data[1] != 0x77) - continue; + uint8_t bsid = data[5] >> 3; + uint8_t acmod = data[6] >> 5; + uint8_t lfeon; + + int8_t pos = 4; + if ((acmod & 0x1) && (acmod != 0x1)) + pos -= 2; + if (acmod & 0x4 ) + pos -= 2; + if (acmod == 0x2) + pos -= 2; + if (pos < 0) + lfeon = (data[7] & 0x64) ? 1 : 0; + else + lfeon = ((data[6] >> pos) & 0x1) ? 1 : 0; - uint8_t bsid = data[5] >> 3; - uint8_t acmod = data[6] >> 5; - uint8_t lfeon; - - int8_t pos = 4; - if ((acmod & 0x1) && (acmod != 0x1)) - pos -= 2; - if (acmod & 0x4 ) - pos -= 2; - if (acmod == 0x2) - pos -= 2; - if (pos < 0) - lfeon = (data[7] & 0x64) ? 1 : 0; - else - lfeon = ((data[6] >> pos) & 0x1) ? 1 : 0; + if (bsid > 0x11 || acmod > 7) + return false; - if (bsid > 0x11 || acmod > 7) - continue; + if (bsid <= 10) + { + /* Normal AC-3 */ - if (bsid <= 10) - { - /* Normal AC-3 */ + if (wantEAC3dependent) + return false; - uint8_t fscod = data[4] >> 6; - uint8_t frmsizecod = data[4] & 0x3F; - if (fscod == 3 || frmsizecod > 37) - continue; + uint8_t fscod = data[4] >> 6; + uint8_t frmsizecod = data[4] & 0x3F; + if (fscod == 3 || frmsizecod > 37) + return false; - /* get the details we need to check crc1 and framesize */ - unsigned int bitRate = AC3Bitrates[frmsizecod >> 1]; - unsigned int framesize = 0; - switch (fscod) - { - case 0: framesize = bitRate * 2; break; - case 1: framesize = (320 * bitRate / 147 + (frmsizecod & 1 ? 1 : 0)); break; - case 2: framesize = bitRate * 4; break; - } + /* get the details we need to check crc1 and framesize */ + unsigned int bitRate = AC3Bitrates[frmsizecod >> 1]; + unsigned int framesize = 0; + switch (fscod) + { + case 0: framesize = bitRate * 2; break; + case 1: framesize = (320 * bitRate / 147 + (frmsizecod & 1 ? 1 : 0)); break; + case 2: framesize = bitRate * 4; break; + } - m_fsize = framesize << 1; - m_info.m_sampleRate = AC3FSCod[fscod]; + m_fsize = framesize << 1; + m_info.m_sampleRate = AC3FSCod[fscod]; + + /* dont do extensive testing if we have not lost sync */ + if (m_info.m_type == CAEStreamInfo::STREAM_TYPE_AC3 && !resyncing) + return true; + + /* this may be the main stream of EAC3 */ + unsigned int fsizeMain = m_fsize; + unsigned int reqBytes = fsizeMain + 8; + if (size < reqBytes) { + /* not enough data to check for E-AC3 dependent frame, request more */ + m_needBytes = reqBytes; + m_fsize = 0; + /* no need to resync => return true */ + return true; + } + if (TrySyncAC3(data + fsizeMain, size - fsizeMain, resyncing, /*wantEAC3dependent*/ true)) { + /* concatenate the main and dependent frames */ + m_fsize += fsizeMain; + return true; + } - /* dont do extensive testing if we have not lost sync */ - /* this may be the main stream of EAC3 */ - if (m_info.m_type == CAEStreamInfo::STREAM_TYPE_EAC3 && skip == 0) - { - m_fsizeMain = m_fsize; - m_fsize = 0; - return 0; - } - else if (m_info.m_type == CAEStreamInfo::STREAM_TYPE_AC3 && skip == 0) - return 0; + unsigned int crc_size; + /* if we have enough data, validate the entire packet, else try to validate crc2 (5/8 of the packet) */ + if (framesize <= size) + crc_size = framesize - 1; + else + crc_size = (framesize >> 1) + (framesize >> 3) - 1; + + if (crc_size <= size) + if (av_crc(av_crc_get_table(AV_CRC_16_ANSI), 0, &data[2], crc_size * 2)) + return false; + + /* if we get here, we can sync */ + m_hasSync = true; + m_info.m_channels = AC3Channels[acmod] + lfeon; + m_syncFunc = &CAEStreamParser::SyncAC3; + m_info.m_type = CAEStreamInfo::STREAM_TYPE_AC3; + m_info.m_ac3FrameSize = m_fsize; + m_info.m_repeat = 1; + + CLog::Log(LOGINFO, "CAEStreamParser::TrySyncAC3 - AC3 stream detected (%d channels, %dHz)", m_info.m_channels, m_info.m_sampleRate); + return true; + } + else + { + // Enhanced AC-3 + uint8_t strmtyp = data[2] >> 6; + if (strmtyp == 3) + return false; - unsigned int crc_size; - /* if we have enough data, validate the entire packet, else try to validate crc2 (5/8 of the packet) */ - if (framesize <= size - skip) - crc_size = framesize - 1; - else - crc_size = (framesize >> 1) + (framesize >> 3) - 1; + if (strmtyp != 1 && wantEAC3dependent) + { + CLog::Log(LOGDEBUG, "CAEStreamParser::TrySyncAC3 - Unexpected stream type: %d (wantEAC3dependent: %d)", + strmtyp, wantEAC3dependent); + return false; + } - if (crc_size <= size - skip) - if (av_crc(av_crc_get_table(AV_CRC_16_ANSI), 0, &data[2], crc_size * 2)) - continue; + unsigned int framesize = (((data[2] & 0x7) << 8) | data[3]) + 1; + uint8_t fscod = (data[4] >> 6) & 0x3; + uint8_t cod = (data[4] >> 4) & 0x3; + uint8_t acmod = (data[4] >> 1) & 0x7; + uint8_t lfeon = data[4] & 0x1; + uint8_t blocks; - /* if we get here, we can sync */ - m_hasSync = true; - m_info.m_channels = AC3Channels[acmod] + lfeon; - m_syncFunc = &CAEStreamParser::SyncAC3; - m_info.m_type = CAEStreamInfo::STREAM_TYPE_AC3; - m_info.m_ac3FrameSize = m_fsize; - m_info.m_repeat = 1; + if (fscod == 0x3) + { + if (cod == 0x3) + return false; - CLog::Log(LOGINFO, "CAEStreamParser::SyncAC3 - AC3 stream detected (%d channels, %dHz)", m_info.m_channels, m_info.m_sampleRate); - return skip; + blocks = 6; + m_info.m_sampleRate = AC3FSCod[cod] >> 1; } else { - // Enhanced AC-3 - uint8_t strmtyp = data[2] >> 6; - if (strmtyp == 3) - continue; - - unsigned int framesize = (((data[2] & 0x7) << 8) | data[3]) + 1; - uint8_t fscod = (data[4] >> 6) & 0x3; - uint8_t cod = (data[4] >> 4) & 0x3; - uint8_t acmod = (data[4] >> 1) & 0x7; - uint8_t lfeon = data[4] & 0x1; - uint8_t blocks; - - if (fscod == 0x3) - { - if (cod == 0x3) - continue; - - blocks = 6; - m_info.m_sampleRate = AC3FSCod[cod] >> 1; - } - else - { - blocks = AC3BlkCod[cod]; - m_info.m_sampleRate = AC3FSCod[fscod]; - } + blocks = AC3BlkCod[cod]; + m_info.m_sampleRate = AC3FSCod[fscod]; + } - m_fsize = framesize << 1; + m_fsize = framesize << 1; + m_info.m_repeat = MAX_EAC3_BLOCKS / blocks; - // concatenate substream to independent stream - if (strmtyp == 1 && m_fsizeMain) - { - m_fsize += m_fsizeMain; - } - m_fsizeMain = 0; + if (m_info.m_type == CAEStreamInfo::STREAM_TYPE_EAC3 && m_hasSync && !resyncing) + return true; - m_info.m_repeat = MAX_EAC3_BLOCKS / blocks; + // if we get here, we can sync + m_hasSync = true; + m_info.m_channels = AC3Channels[acmod] + lfeon; + m_syncFunc = &CAEStreamParser::SyncAC3; + m_info.m_type = CAEStreamInfo::STREAM_TYPE_EAC3; + m_info.m_ac3FrameSize = m_fsize; - if (m_info.m_type == CAEStreamInfo::STREAM_TYPE_EAC3 && m_hasSync && skip == 0) - return 0; + CLog::Log(LOGINFO, "CAEStreamParser::TrySyncAC3 - E-AC3 stream detected (%d channels, %dHz)", m_info.m_channels, m_info.m_sampleRate); + return true; + } +} - // if we get here, we can sync - m_hasSync = true; - m_info.m_channels = AC3Channels[acmod] + lfeon; - m_syncFunc = &CAEStreamParser::SyncAC3; - m_info.m_type = CAEStreamInfo::STREAM_TYPE_EAC3; - m_info.m_ac3FrameSize = m_fsize; - m_fsizeMain = 0; +unsigned int CAEStreamParser::SyncAC3(uint8_t *data, unsigned int size) +{ + unsigned int skip = 0; - CLog::Log(LOGINFO, "CAEStreamParser::SyncAC3 - E-AC3 stream detected (%d channels, %dHz)", m_info.m_channels, m_info.m_sampleRate); + for (; size - skip > 7; ++skip, ++data) + { + bool resyncing = (skip != 0); + if (TrySyncAC3(data, size - skip, resyncing, /*wantEAC3dependent*/ false)) return skip; - } } // if we get here, the entire packet is invalid and we have lost sync CLog::Log(LOGINFO, "CAEStreamParser::SyncAC3 - AC3 sync lost"); m_hasSync = false; - m_fsizeMain = 0; return skip; } diff --git a/xbmc/cores/AudioEngine/Utils/AEStreamInfo.h b/xbmc/cores/AudioEngine/Utils/AEStreamInfo.h index 849a8f4ba4..941344a08e 100644 --- a/xbmc/cores/AudioEngine/Utils/AEStreamInfo.h +++ b/xbmc/cores/AudioEngine/Utils/AEStreamInfo.h @@ -87,12 +87,12 @@ private: unsigned int m_coreSize = 0; /* core size for dtsHD */ unsigned int m_dtsBlocks = 0; unsigned int m_fsize = 0; - unsigned int m_fsizeMain = 0; /* used for EAC3 substreams */ int m_substreams = 0; /* used for TrueHD */ AVCRC m_crcTrueHD[1024]; /* TrueHD crc table */ void GetPacket(uint8_t **buffer, unsigned int *bufferSize); unsigned int DetectType(uint8_t *data, unsigned int size); + bool TrySyncAC3(uint8_t *data, unsigned int size, bool resyncing, bool wantEAC3dependent); unsigned int SyncAC3(uint8_t *data, unsigned int size); unsigned int SyncDTS(uint8_t *data, unsigned int size); unsigned int SyncTrueHD(uint8_t *data, unsigned int size); diff --git a/xbmc/cores/VideoPlayer/AudioSinkAE.cpp b/xbmc/cores/VideoPlayer/AudioSinkAE.cpp index e03766328c..2bff6724ce 100644 --- a/xbmc/cores/VideoPlayer/AudioSinkAE.cpp +++ b/xbmc/cores/VideoPlayer/AudioSinkAE.cpp @@ -15,7 +15,6 @@ #include "cores/AudioEngine/Interfaces/AE.h" #include "cores/AudioEngine/Utils/AEAudioFormat.h" #include "cores/AudioEngine/Utils/AEStreamData.h" -#include "settings/MediaSettings.h" #ifdef TARGET_POSIX #include "platform/linux/XTimeUtils.h" #endif @@ -69,6 +68,7 @@ bool CAudioSinkAE::Create(const DVDAudioFrame &audioframe, AVCodecID codec, bool m_iBitsPerSample = audioframe.bits_per_sample; m_bPassthrough = audioframe.passthrough; m_channelLayout = audioframe.format.m_channelLayout; + m_dataType = audioframe.format.m_streamInfo.m_type; return true; } @@ -241,6 +241,10 @@ bool CAudioSinkAE::IsValidFormat(const DVDAudioFrame &audioframe) m_channelLayout != audioframe.format.m_channelLayout) return false; + if (m_bPassthrough && + m_dataType != audioframe.format.m_streamInfo.m_type) + return false; + return true; } diff --git a/xbmc/cores/VideoPlayer/AudioSinkAE.h b/xbmc/cores/VideoPlayer/AudioSinkAE.h index 667094fc88..8a863e614c 100644 --- a/xbmc/cores/VideoPlayer/AudioSinkAE.h +++ b/xbmc/cores/VideoPlayer/AudioSinkAE.h @@ -76,6 +76,7 @@ protected: int m_iBitsPerSample; bool m_bPassthrough; CAEChannelInfo m_channelLayout; + CAEStreamInfo::DataType m_dataType; bool m_bPaused; std::atomic_bool m_bAbort; diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodec.h b/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodec.h index 3bf5e57e61..d0b3f3e6cd 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodec.h +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodec.h @@ -9,10 +9,8 @@ #pragma once #include "cores/AudioEngine/Utils/AEAudioFormat.h" -#include "cores/AudioEngine/Utils/AEUtil.h" #include "cores/VideoPlayer/Process/ProcessInfo.h" #include "cores/VideoPlayer/Interface/Addon/DemuxPacket.h" -#include "cores/VideoPlayer/Interface/Addon/TimingConstants.h" #include <vector> @@ -40,7 +38,6 @@ typedef struct stDVDAudioFrame AEAudioFormat format; int bits_per_sample; bool passthrough; - AEAudioFormat audioFormat; enum AVAudioServiceType audio_service_type; enum AVMatrixEncoding matrix_encoding; int profile; diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecAndroidMediaCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecAndroidMediaCodec.cpp index f3b8540ce8..41c4fae6c7 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecAndroidMediaCodec.cpp +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecAndroidMediaCodec.cpp @@ -24,6 +24,7 @@ #include "settings/AdvancedSettings.h" #include "settings/SettingsComponent.h" #include "cores/AudioEngine/Interfaces/AE.h" +#include "cores/AudioEngine/Utils/AEUtil.h" #include "cores/VideoPlayer/Interface/Addon/DemuxCrypto.h" #include "ServiceBroker.h" diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp index 3cec80bfca..9ffb93e07c 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp @@ -14,6 +14,7 @@ #include "settings/Settings.h" #include "settings/SettingsComponent.h" #include "DVDCodecs/DVDCodecs.h" +#include "cores/AudioEngine/Utils/AEUtil.h" extern "C" { #include "libavutil/opt.h" diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecPassthrough.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecPassthrough.cpp index a2e703139f..3f368c7ee7 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecPassthrough.cpp +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecPassthrough.cpp @@ -12,8 +12,6 @@ #include "utils/log.h" #include <algorithm> -#include "ServiceBroker.h" -#include "cores/AudioEngine/Interfaces/AE.h" extern "C" { #include "libavcodec/avcodec.h" @@ -111,15 +109,17 @@ bool CDVDAudioCodecPassthrough::AddData(const DemuxPacket &packet) if (m_nextPts != DVD_NOPTS_VALUE) { m_currentPts = m_nextPts; - m_nextPts = DVD_NOPTS_VALUE; + m_nextPts = packet.pts; } else if (packet.pts != DVD_NOPTS_VALUE) { m_currentPts = packet.pts; } } - - m_nextPts = packet.pts; + else + { + m_nextPts = packet.pts; + } } if (pData && !m_backlogSize) diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/DVDCodecUtils.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/DVDCodecUtils.cpp index 1290b94eb3..7b5fa44633 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/DVDCodecUtils.cpp +++ b/xbmc/cores/VideoPlayer/DVDCodecs/DVDCodecUtils.cpp @@ -8,9 +8,7 @@ #include "DVDCodecUtils.h" #include "cores/VideoPlayer/Interface/Addon/TimingConstants.h" -#include "utils/log.h" #include "cores/FFmpeg.h" -#include "cores/VideoPlayer/Process/VideoBuffer.h" #include "Util.h" extern "C" { diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/DVDCodecUtils.h b/xbmc/cores/VideoPlayer/DVDCodecs/DVDCodecUtils.h index 59fc5d68bc..37872d1624 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/DVDCodecUtils.h +++ b/xbmc/cores/VideoPlayer/DVDCodecs/DVDCodecUtils.h @@ -8,12 +8,11 @@ #pragma once -#include "Video/DVDVideoCodec.h" class CDVDCodecUtils { public: static bool IsVP3CompatibleWidth(int width); - static double NormalizeFrameduration(double frameduration, bool *match = NULL); + static double NormalizeFrameduration(double frameduration, bool *match = nullptr); }; diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.cpp index 951e931dab..67960fa964 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.cpp +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.cpp @@ -8,8 +8,6 @@ #include "DVDVideoCodec.h" #include "cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.h" -#include "rendering/RenderSystem.h" -#include "windowing/WinSystem.h" #include <string> #include <vector> diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp index 2af5f0dd4c..a7e4b86396 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp @@ -8,11 +8,9 @@ #include "system.h" #include "DVDVideoCodecFFmpeg.h" -#include "DVDDemuxers/DVDDemux.h" #include "DVDStreamInfo.h" #include "cores/VideoPlayer/Interface/Addon/TimingConstants.h" #include "DVDCodecs/DVDCodecs.h" -#include "DVDCodecs/DVDCodecUtils.h" #include "DVDCodecs/DVDFactoryCodec.h" #include "ServiceBroker.h" #include "utils/CPUInfo.h" @@ -22,7 +20,6 @@ #include "cores/VideoSettings.h" #include "utils/log.h" #include "cores/VideoPlayer/VideoRenderers/RenderManager.h" -#include "cores/VideoPlayer/VideoRenderers/RenderInfo.h" #include "utils/StringUtils.h" #include <memory> diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h index d6fea742c3..dfd11a17dc 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h @@ -11,7 +11,6 @@ #include "cores/VideoPlayer/DVDCodecs/DVDCodecs.h" #include "cores/VideoPlayer/DVDStreamInfo.h" #include "DVDVideoCodec.h" -#include "DVDResource.h" #include "DVDVideoPPFFmpeg.h" #include <string> #include <vector> diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoPPFFmpeg.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoPPFFmpeg.h index 7696f1a095..34b2968dfa 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoPPFFmpeg.h +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoPPFFmpeg.h @@ -9,7 +9,6 @@ #pragma once #include "DVDVideoCodec.h" -#include "cores/VideoPlayer/Process/VideoBuffer.h" #include <string> class CProcessInfo; diff --git a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxUtils.cpp b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxUtils.cpp index 42a3af82ee..fdac56e318 100644 --- a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxUtils.cpp +++ b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxUtils.cpp @@ -7,7 +7,6 @@ */ #include "DVDDemuxUtils.h" -#include "cores/VideoPlayer/Interface/Addon/TimingConstants.h" #include "cores/VideoPlayer/Interface/Addon/DemuxCrypto.h" #include "utils/log.h" diff --git a/xbmc/cores/VideoPlayer/DVDFileInfo.cpp b/xbmc/cores/VideoPlayer/DVDFileInfo.cpp index ed12e1ee1d..9c326d83b1 100644 --- a/xbmc/cores/VideoPlayer/DVDFileInfo.cpp +++ b/xbmc/cores/VideoPlayer/DVDFileInfo.cpp @@ -27,8 +27,6 @@ #include "DVDDemuxers/DVDDemux.h" #include "DVDDemuxers/DVDDemuxUtils.h" #include "DVDDemuxers/DVDFactoryDemuxer.h" -#include "DVDDemuxers/DVDDemuxFFmpeg.h" -#include "DVDCodecs/DVDCodecs.h" #include "DVDCodecs/DVDFactoryCodec.h" #include "DVDCodecs/Video/DVDVideoCodec.h" #include "DVDCodecs/Video/DVDVideoCodecFFmpeg.h" diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStream.cpp b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStream.cpp index 648f7e84fc..c3c5dfa531 100644 --- a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStream.cpp +++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStream.cpp @@ -8,7 +8,6 @@ #include "DVDInputStream.h" #include "URL.h" -#include "DVDStreamInfo.h" CDVDInputStream::CDVDInputStream(DVDStreamType streamType, const CFileItem& fileitem) { diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamFFmpeg.cpp b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamFFmpeg.cpp index 775c1c94a6..5cfdd2d11e 100644 --- a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamFFmpeg.cpp +++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamFFmpeg.cpp @@ -8,15 +8,9 @@ #include "DVDInputStreamFFmpeg.h" -#include "filesystem/CurlFile.h" #include "playlists/PlayListM3U.h" -#include "settings/Settings.h" -#include "settings/SettingsComponent.h" -#include "utils/log.h" #include "utils/StringUtils.h" -#include "utils/URIUtils.h" -#include <limits.h> using namespace XFILE; using PLAYLIST::CPlayListM3U; diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.cpp b/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.cpp index 14a8ae8f8f..8829572f75 100644 --- a/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.cpp +++ b/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.cpp @@ -11,7 +11,6 @@ #include "addons/binary-addons/AddonDll.h" #include "addons/binary-addons/BinaryAddonBase.h" #include "addons/kodi-addon-dev-kit/include/kodi/addon-instance/VideoCodec.h" -#include "cores/VideoPlayer/DVDClock.h" #include "cores/VideoPlayer/DVDDemuxers/DVDDemux.h" #include "cores/VideoPlayer/DVDDemuxers/DVDDemuxUtils.h" #include "cores/VideoPlayer/Interface/Addon/DemuxCrypto.h" diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamMultiSource.cpp b/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamMultiSource.cpp index d223e54267..d2034a7c4e 100644 --- a/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamMultiSource.cpp +++ b/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamMultiSource.cpp @@ -9,8 +9,6 @@ #include "InputStreamMultiSource.h" #include "DVDFactoryInputStream.h" #include "filesystem/File.h" -#include "filesystem/IFile.h" -#include "settings/AdvancedSettings.h" #include "utils/log.h" #include "utils/StringUtils.h" #include<map> diff --git a/xbmc/cores/VideoPlayer/PTSTracker.cpp b/xbmc/cores/VideoPlayer/PTSTracker.cpp index 7aed0bb54c..207a55259f 100644 --- a/xbmc/cores/VideoPlayer/PTSTracker.cpp +++ b/xbmc/cores/VideoPlayer/PTSTracker.cpp @@ -7,12 +7,12 @@ */ #include "PTSTracker.h" -#include "DVDClock.h" #include "DVDCodecs/DVDCodecUtils.h" #include "cores/VideoPlayer/Interface/Addon/TimingConstants.h" #include "utils/log.h" #include "utils/StringUtils.h" #include <cmath> +#include <algorithm> #define MAXERR DVD_MSEC_TO_TIME(2.5) diff --git a/xbmc/cores/VideoPlayer/Process/ProcessInfo.h b/xbmc/cores/VideoPlayer/Process/ProcessInfo.h index f3c7049fd7..e8042c2bc2 100644 --- a/xbmc/cores/VideoPlayer/Process/ProcessInfo.h +++ b/xbmc/cores/VideoPlayer/Process/ProcessInfo.h @@ -9,7 +9,6 @@ #pragma once #include "VideoBuffer.h" -#include "cores/IPlayer.h" #include "cores/VideoSettings.h" #include "cores/VideoPlayer/VideoRenderers/RenderInfo.h" #include "threads/CriticalSection.h" diff --git a/xbmc/cores/VideoPlayer/VideoPlayer.h b/xbmc/cores/VideoPlayer/VideoPlayer.h index 79fe22a24c..237c48c51d 100644 --- a/xbmc/cores/VideoPlayer/VideoPlayer.h +++ b/xbmc/cores/VideoPlayer/VideoPlayer.h @@ -26,8 +26,6 @@ #include "Edl.h" #include "FileItem.h" #include "threads/SystemClock.h" -#include "threads/Thread.h" -#include "utils/StreamDetails.h" #include "guilib/DispResource.h" #include <unordered_map> diff --git a/xbmc/cores/VideoPlayer/VideoPlayerRadioRDS.cpp b/xbmc/cores/VideoPlayer/VideoPlayerRadioRDS.cpp index db159f8034..24c17ec162 100644 --- a/xbmc/cores/VideoPlayer/VideoPlayerRadioRDS.cpp +++ b/xbmc/cores/VideoPlayer/VideoPlayerRadioRDS.cpp @@ -25,22 +25,16 @@ #include "GUIUserMessages.h" #include "ServiceBroker.h" #include "DVDCodecs/DVDCodecs.h" -#include "DVDCodecs/DVDFactoryCodec.h" #include "DVDCodecs/Video/DVDVideoCodecFFmpeg.h" #include "DVDDemuxers/DVDDemuxUtils.h" #include "DVDDemuxers/DVDFactoryDemuxer.h" #include "DVDInputStreams/DVDInputStream.h" -#include "DVDInputStreams/DVDFactoryInputStream.h" #include "cores/FFmpeg.h" #include "dialogs/GUIDialogKaiToast.h" -#include "filesystem/Directory.h" -#include "filesystem/File.h" -#include "filesystem/SpecialProtocol.h" #include "guilib/GUIComponent.h" #include "guilib/GUIWindowManager.h" #include "guilib/LocalizeStrings.h" #include "interfaces/AnnouncementManager.h" -#include "messaging/ApplicationMessenger.h" #include "music/tags/MusicInfoTag.h" #include "pictures/Picture.h" #include "pvr/channels/PVRChannel.h" diff --git a/xbmc/cores/VideoPlayer/VideoPlayerSubtitle.cpp b/xbmc/cores/VideoPlayer/VideoPlayerSubtitle.cpp index 8068255631..d98e42e2e6 100644 --- a/xbmc/cores/VideoPlayer/VideoPlayerSubtitle.cpp +++ b/xbmc/cores/VideoPlayer/VideoPlayerSubtitle.cpp @@ -10,7 +10,6 @@ #include "DVDCodecs/Overlay/DVDOverlay.h" #include "DVDCodecs/Overlay/DVDOverlaySpu.h" #include "DVDCodecs/Overlay/DVDOverlayCodec.h" -#include "DVDClock.h" #include "DVDSubtitles/DVDSubtitleParser.h" #include "DVDCodecs/DVDFactoryCodec.h" #include "cores/VideoPlayer/Interface/Addon/DemuxPacket.h" diff --git a/xbmc/cores/VideoPlayer/VideoPlayerVideo.cpp b/xbmc/cores/VideoPlayer/VideoPlayerVideo.cpp index 6df3c04017..4f057e6fac 100644 --- a/xbmc/cores/VideoPlayer/VideoPlayerVideo.cpp +++ b/xbmc/cores/VideoPlayer/VideoPlayerVideo.cpp @@ -9,14 +9,12 @@ #include "ServiceBroker.h" #include "windowing/WinSystem.h" #include "settings/AdvancedSettings.h" -#include "settings/Settings.h" #include "settings/SettingsComponent.h" #include "utils/MathUtils.h" #include "VideoPlayerVideo.h" #include "DVDCodecs/DVDFactoryCodec.h" #include "DVDCodecs/DVDCodecUtils.h" #include "DVDCodecs/Video/DVDVideoCodecFFmpeg.h" -#include "DVDDemuxers/DVDDemux.h" #include "cores/VideoPlayer/Interface/Addon/DemuxPacket.h" #include "cores/VideoPlayer/Interface/Addon/TimingConstants.h" #include "windowing/GraphicContext.h" diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.cpp index 787266f7fc..e4900f4649 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.cpp @@ -19,8 +19,6 @@ #include "guilib/LocalizeStrings.h" #include "utils/log.h" #include "utils/MathUtils.h" -#include "utils/SystemInfo.h" -#include "settings/AdvancedSettings.h" #include "cores/VideoPlayer/VideoRenderers/RenderFlags.h" diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.h b/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.h index f8d7701d46..7282fddf1a 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.h +++ b/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.h @@ -12,7 +12,6 @@ #include <vector> #include "RenderInfo.h" -#include "windowing/Resolution.h" #include "utils/Geometry.h" #include "VideoShaders/ShaderFormats.h" #include "cores/IPlayer.h" diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.cpp index b424ac3fa3..7750b51644 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.cpp @@ -33,6 +33,7 @@ #include "utils/StringUtils.h" #include "RenderCapture.h" #include "cores/IPlayer.h" +#include "cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.h" #include "cores/VideoPlayer/DVDCodecs/DVDCodecUtils.h" #include "cores/FFmpeg.h" diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/RenderCapture.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/RenderCapture.cpp index 34051d02b1..e9d07a1250 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/RenderCapture.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/RenderCapture.cpp @@ -13,10 +13,11 @@ #include "settings/AdvancedSettings.h" #include "settings/SettingsComponent.h" #include "cores/IPlayer.h" -#include "rendering/RenderSystem.h" #ifdef TARGET_WINDOWS #include "rendering/dx/DeviceResources.h" #include "rendering/dx/RenderContext.h" +#else +#include "rendering/RenderSystem.h" #endif extern "C" { diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.cpp index 99120aa9a1..003baf2b21 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.cpp @@ -34,7 +34,6 @@ /* to use the same as player */ #include "../VideoPlayer/DVDClock.h" #include "../VideoPlayer/DVDCodecs/Video/DVDVideoCodec.h" -#include "../VideoPlayer/DVDCodecs/DVDCodecUtils.h" using namespace KODI::MESSAGING; diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.h b/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.h index cc90c6263d..6fb45a692f 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.h +++ b/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.h @@ -16,7 +16,6 @@ #include "windowing/Resolution.h" #include "threads/CriticalSection.h" #include "cores/VideoSettings.h" -#include "OverlayRenderer.h" #include "DebugRenderer.h" #include <deque> #include <map> diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderBuffer.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderBuffer.cpp index f2662fe379..7fdafe2f2d 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderBuffer.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderBuffer.cpp @@ -10,7 +10,6 @@ #include <ppltasks.h> #include "WinRenderBuffer.h" -#include "cores/VideoPlayer/VideoRenderers/RenderFlags.h" #include "cores/VideoPlayer/VideoRenderers/WinRenderer.h" #include "rendering/dx/DeviceResources.h" #include "rendering/dx/RenderContext.h" diff --git a/xbmc/events/windows/GUIViewStateEventLog.cpp b/xbmc/events/windows/GUIViewStateEventLog.cpp index 5e929a9359..80427c2784 100644 --- a/xbmc/events/windows/GUIViewStateEventLog.cpp +++ b/xbmc/events/windows/GUIViewStateEventLog.cpp @@ -8,10 +8,8 @@ #include "GUIViewStateEventLog.h" #include "FileItem.h" -#include "filesystem/File.h" #include "windowing/GraphicContext.h" #include "guilib/WindowIDs.h" -#include "utils/StringUtils.h" #include "view/ViewState.h" CGUIViewStateEventLog::CGUIViewStateEventLog(const CFileItemList& items) : CGUIViewState(items) diff --git a/xbmc/events/windows/GUIWindowEventLog.cpp b/xbmc/events/windows/GUIWindowEventLog.cpp index 8b3431ff52..2184bfbfd7 100644 --- a/xbmc/events/windows/GUIWindowEventLog.cpp +++ b/xbmc/events/windows/GUIWindowEventLog.cpp @@ -20,7 +20,6 @@ #include "settings/Settings.h" #include "settings/SettingsComponent.h" #include "utils/StringUtils.h" -#include "utils/URIUtils.h" #include "view/ViewStateSettings.h" #define CONTROL_BUTTON_CLEAR 20 diff --git a/xbmc/favourites/GUIDialogFavourites.cpp b/xbmc/favourites/GUIDialogFavourites.cpp index a324f89469..27c4657bf6 100644 --- a/xbmc/favourites/GUIDialogFavourites.cpp +++ b/xbmc/favourites/GUIDialogFavourites.cpp @@ -16,7 +16,6 @@ #include "guilib/GUIWindowManager.h" #include "guilib/GUIKeyboardFactory.h" #include "input/Key.h" -#include "filesystem/File.h" #include "FileItem.h" #include "guilib/LocalizeStrings.h" #include "storage/MediaManager.h" diff --git a/xbmc/filesystem/AddonsDirectory.cpp b/xbmc/filesystem/AddonsDirectory.cpp index 6f9cb11c16..46326cf292 100644 --- a/xbmc/filesystem/AddonsDirectory.cpp +++ b/xbmc/filesystem/AddonsDirectory.cpp @@ -18,17 +18,14 @@ #include "interfaces/generic/ScriptInvocationManager.h" #include "FileItem.h" #include "addons/AddonInstaller.h" -#include "addons/BinaryAddonCache.h" #include "addons/PluginSource.h" #include "addons/RepositoryUpdater.h" #include "games/addons/GameClient.h" #include "games/GameUtils.h" #include "guilib/TextureManager.h" -#include "File.h" #include "messaging/helpers/DialogOKHelper.h" #include "settings/Settings.h" #include "settings/SettingsComponent.h" -#include "SpecialProtocol.h" #include "utils/URIUtils.h" #include "utils/StringUtils.h" #include "URL.h" diff --git a/xbmc/filesystem/CurlFile.cpp b/xbmc/filesystem/CurlFile.cpp index 53f4644bd2..6770fdf2a7 100644 --- a/xbmc/filesystem/CurlFile.cpp +++ b/xbmc/filesystem/CurlFile.cpp @@ -8,7 +8,6 @@ #include "CurlFile.h" #include "ServiceBroker.h" -#include "utils/URIUtils.h" #include "Util.h" #include "URL.h" #include "settings/AdvancedSettings.h" @@ -33,7 +32,6 @@ #include "DllLibCurl.h" #include "ShoutcastFile.h" -#include "SpecialProtocol.h" #include "utils/CharsetConverter.h" #include "utils/log.h" #include "utils/StringUtils.h" @@ -625,14 +623,6 @@ void CCurlFile::SetCommonOptions(CReadState* state, bool failOnError /* = true * // Set the lowspeed time very low as it seems Curl takes much longer to detect a lowspeed condition g_curlInterface.easy_setopt(h, CURLOPT_LOW_SPEED_TIME, m_lowspeedtime); - if (m_skipshout) - //! @todo - //! For shoutcast file, content-length should not be set, and in libcurl there is a bug, if the - //! cast file was 302 redirected then getinfo of CURLINFO_CONTENT_LENGTH_DOWNLOAD will return - //! the 302 response's body length, which cause the next read request failed, so we ignore - //! content-length for shoutcast file to workaround this. - g_curlInterface.easy_setopt(h, CURLOPT_IGNORE_CONTENT_LENGTH, 1); - // Setup allowed TLS/SSL ciphers. New versions of cURL may deprecate things that are still in use. if (!m_cipherlist.empty()) g_curlInterface.easy_setopt(h, CURLOPT_SSL_CIPHER_LIST, m_cipherlist.c_str()); @@ -1220,7 +1210,7 @@ bool CCurlFile::Exists(const CURL& url) SetCommonOptions(m_state); SetRequestHeaders(m_state); - g_curlInterface.easy_setopt(m_state->m_easyHandle, CURLOPT_TIMEOUT, 5); + g_curlInterface.easy_setopt(m_state->m_easyHandle, CURLOPT_TIMEOUT, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_curlconnecttimeout); g_curlInterface.easy_setopt(m_state->m_easyHandle, CURLOPT_NOBODY, 1); g_curlInterface.easy_setopt(m_state->m_easyHandle, CURLOPT_WRITEDATA, NULL); /* will cause write failure*/ @@ -1235,16 +1225,49 @@ bool CCurlFile::Exists(const CURL& url) } CURLcode result = g_curlInterface.easy_perform(m_state->m_easyHandle); - g_curlInterface.easy_release(&m_state->m_easyHandle, NULL); if (result == CURLE_WRITE_ERROR || result == CURLE_OK) + { + g_curlInterface.easy_release(&m_state->m_easyHandle, NULL); return true; + } if (result == CURLE_HTTP_RETURNED_ERROR) { long code; if(g_curlInterface.easy_getinfo(m_state->m_easyHandle, CURLINFO_RESPONSE_CODE, &code) == CURLE_OK && code != 404 ) - CLog::Log(LOGERROR, "CCurlFile::Exists - Failed: HTTP returned error %ld for %s", code, url.GetRedacted().c_str()); + { + if (code == 405) + { + // If we get a Method Not Allowed response, retry with a GET Request + g_curlInterface.easy_setopt(m_state->m_easyHandle, CURLOPT_NOBODY, 0); + + g_curlInterface.easy_setopt(m_state->m_easyHandle, CURLOPT_FILETIME, 1); + g_curlInterface.easy_setopt(m_state->m_easyHandle, CURLOPT_XFERINFOFUNCTION, transfer_abort_callback); + g_curlInterface.easy_setopt(m_state->m_easyHandle, CURLOPT_NOPROGRESS, 0); + + curl_slist *list = NULL; + list = g_curlInterface.slist_append(list, "Range: bytes=0-1"); /* try to only request 1 byte */ + g_curlInterface.easy_setopt(m_state->m_easyHandle, CURLOPT_HTTPHEADER, list); + + CURLcode result = g_curlInterface.easy_perform(m_state->m_easyHandle); + g_curlInterface.slist_free_all(list); + + if (result == CURLE_WRITE_ERROR || result == CURLE_OK) + { + g_curlInterface.easy_release(&m_state->m_easyHandle, NULL); + return true; + } + + if (result == CURLE_HTTP_RETURNED_ERROR) + { + if (g_curlInterface.easy_getinfo(m_state->m_easyHandle, CURLINFO_RESPONSE_CODE, &code) == CURLE_OK && code != 404 ) + CLog::Log(LOGERROR, "CCurlFile::Exists - Failed: HTTP returned error %ld for %s", code, url.GetRedacted().c_str()); + } + } + else + CLog::Log(LOGERROR, "CCurlFile::Exists - Failed: HTTP returned error %ld for %s", code, url.GetRedacted().c_str()); + } } else if (result != CURLE_REMOTE_FILE_NOT_FOUND && result != CURLE_FTP_COULDNT_RETR_FILE) { @@ -1252,6 +1275,7 @@ bool CCurlFile::Exists(const CURL& url) } errno = ENOENT; + g_curlInterface.easy_release(&m_state->m_easyHandle, NULL); return false; } @@ -1408,7 +1432,11 @@ int CCurlFile::Stat(const CURL& url, struct __stat64* buffer) { long code; if(g_curlInterface.easy_getinfo(m_state->m_easyHandle, CURLINFO_RESPONSE_CODE, &code) == CURLE_OK && code == 404 ) + { + g_curlInterface.easy_release(&m_state->m_easyHandle, NULL); + errno = ENOENT; return -1; + } } if(result == CURLE_GOT_NOTHING diff --git a/xbmc/filesystem/Directory.cpp b/xbmc/filesystem/Directory.cpp index c92829e0c1..a392c0f74f 100644 --- a/xbmc/filesystem/Directory.cpp +++ b/xbmc/filesystem/Directory.cpp @@ -21,7 +21,6 @@ #include "Application.h" #include "guilib/GUIWindowManager.h" #include "dialogs/GUIDialogBusy.h" -#include "threads/SingleLock.h" #include "utils/URIUtils.h" #include "URL.h" #include "PasswordManager.h" diff --git a/xbmc/filesystem/DirectoryCache.cpp b/xbmc/filesystem/DirectoryCache.cpp index 71c617a0e1..1cc6e0ceea 100644 --- a/xbmc/filesystem/DirectoryCache.cpp +++ b/xbmc/filesystem/DirectoryCache.cpp @@ -6,6 +6,7 @@ * See LICENSES/README.md for more information. */ +#include "Directory.h" #include "DirectoryCache.h" #include "FileItem.h" #include "threads/SingleLock.h" diff --git a/xbmc/filesystem/DirectoryCache.h b/xbmc/filesystem/DirectoryCache.h index 0fbd967d70..9b03966a29 100644 --- a/xbmc/filesystem/DirectoryCache.h +++ b/xbmc/filesystem/DirectoryCache.h @@ -9,7 +9,6 @@ #pragma once #include "IDirectory.h" -#include "Directory.h" #include "threads/CriticalSection.h" #include <map> diff --git a/xbmc/filesystem/EventsDirectory.h b/xbmc/filesystem/EventsDirectory.h index 8eec7b3ef9..0112f2cd5a 100644 --- a/xbmc/filesystem/EventsDirectory.h +++ b/xbmc/filesystem/EventsDirectory.h @@ -9,7 +9,6 @@ #pragma once #include "FileItem.h" -#include "events/IEvent.h" #include "filesystem/IDirectory.h" #define PROPERTY_EVENT_IDENTIFIER "Event.ID" diff --git a/xbmc/filesystem/FavouritesDirectory.cpp b/xbmc/filesystem/FavouritesDirectory.cpp index be4192ba66..86802c4b4a 100644 --- a/xbmc/filesystem/FavouritesDirectory.cpp +++ b/xbmc/filesystem/FavouritesDirectory.cpp @@ -10,7 +10,6 @@ #include "favourites/FavouritesService.h" #include "File.h" #include "Directory.h" -#include "Util.h" #include "profiles/ProfileManager.h" #include "ServiceBroker.h" #include "utils/URIUtils.h" diff --git a/xbmc/filesystem/FileDirectoryFactory.cpp b/xbmc/filesystem/FileDirectoryFactory.cpp index b20834f25f..dd0cacdbbb 100644 --- a/xbmc/filesystem/FileDirectoryFactory.cpp +++ b/xbmc/filesystem/FileDirectoryFactory.cpp @@ -20,14 +20,12 @@ #include "PlaylistFileDirectory.h" #include "playlists/PlayListFactory.h" #include "Directory.h" -#include "File.h" #include "FileItem.h" #include "utils/StringUtils.h" #include "URL.h" #include "ServiceBroker.h" #include "addons/AudioDecoder.h" #include "addons/VFSEntry.h" -#include "addons/BinaryAddonCache.h" #include "addons/binary-addons/BinaryAddonBase.h" #include "AudioBookFileDirectory.h" diff --git a/xbmc/filesystem/IDirectory.cpp b/xbmc/filesystem/IDirectory.cpp index c3ec048061..4a1d67f104 100644 --- a/xbmc/filesystem/IDirectory.cpp +++ b/xbmc/filesystem/IDirectory.cpp @@ -13,7 +13,6 @@ #include "PasswordManager.h" #include "utils/URIUtils.h" #include "utils/StringUtils.h" -#include "ServiceBroker.h" using namespace KODI::MESSAGING; using namespace XFILE; diff --git a/xbmc/filesystem/MusicDatabaseDirectory.cpp b/xbmc/filesystem/MusicDatabaseDirectory.cpp index ba9cb3ee25..15a81bc7fb 100644 --- a/xbmc/filesystem/MusicDatabaseDirectory.cpp +++ b/xbmc/filesystem/MusicDatabaseDirectory.cpp @@ -13,6 +13,7 @@ #include "filesystem/File.h" #include "FileItem.h" #include "utils/Crc32.h" +#include "ServiceBroker.h" #include "guilib/TextureManager.h" #include "guilib/LocalizeStrings.h" #include "utils/LegacyPathTranslation.h" diff --git a/xbmc/filesystem/PluginDirectory.cpp b/xbmc/filesystem/PluginDirectory.cpp index ccea3d3bc1..f6334bd635 100644 --- a/xbmc/filesystem/PluginDirectory.cpp +++ b/xbmc/filesystem/PluginDirectory.cpp @@ -25,7 +25,6 @@ #include "FileItem.h" #include "video/VideoInfoTag.h" #include "utils/log.h" -#include "utils/JobManager.h" #include "utils/StringUtils.h" #include "utils/URIUtils.h" #include "messaging/ApplicationMessenger.h" diff --git a/xbmc/filesystem/ResourceDirectory.cpp b/xbmc/filesystem/ResourceDirectory.cpp index 96ba07617b..8a8b4e44fc 100644 --- a/xbmc/filesystem/ResourceDirectory.cpp +++ b/xbmc/filesystem/ResourceDirectory.cpp @@ -11,7 +11,6 @@ #include "URL.h" #include "filesystem/Directory.h" #include "filesystem/ResourceFile.h" -#include "utils/StringUtils.h" #include "utils/URIUtils.h" using namespace XFILE; diff --git a/xbmc/filesystem/ResourceFile.cpp b/xbmc/filesystem/ResourceFile.cpp index 36fe435ebc..9304d02169 100644 --- a/xbmc/filesystem/ResourceFile.cpp +++ b/xbmc/filesystem/ResourceFile.cpp @@ -12,7 +12,6 @@ #include "ServiceBroker.h" #include "addons/AddonManager.h" #include "addons/Resource.h" -#include "utils/URIUtils.h" using namespace ADDON; using namespace XFILE; diff --git a/xbmc/filesystem/SourcesDirectory.cpp b/xbmc/filesystem/SourcesDirectory.cpp index c6061728a8..702b2cd629 100644 --- a/xbmc/filesystem/SourcesDirectory.cpp +++ b/xbmc/filesystem/SourcesDirectory.cpp @@ -6,6 +6,7 @@ * See LICENSES/README.md for more information. */ +#include "ServiceBroker.h" #include "SourcesDirectory.h" #include "utils/URIUtils.h" #include "URL.h" diff --git a/xbmc/filesystem/SpecialProtocolDirectory.cpp b/xbmc/filesystem/SpecialProtocolDirectory.cpp index 37b0fcf478..afec3d6025 100644 --- a/xbmc/filesystem/SpecialProtocolDirectory.cpp +++ b/xbmc/filesystem/SpecialProtocolDirectory.cpp @@ -9,7 +9,6 @@ #include "SpecialProtocolDirectory.h" #include "SpecialProtocol.h" #include "Directory.h" -#include "utils/StringUtils.h" #include "utils/URIUtils.h" #include "FileItem.h" #include "URL.h" diff --git a/xbmc/filesystem/XbtFile.cpp b/xbmc/filesystem/XbtFile.cpp index 85fa246715..d8441ab895 100644 --- a/xbmc/filesystem/XbtFile.cpp +++ b/xbmc/filesystem/XbtFile.cpp @@ -27,7 +27,6 @@ #include "filesystem/XbtManager.h" #include "guilib/TextureBundleXBT.h" #include "guilib/XBTFReader.h" -#include "utils/log.h" #include "utils/StringUtils.h" namespace XFILE diff --git a/xbmc/games/addons/GameClient.h b/xbmc/games/addons/GameClient.h index 018518934f..9024c1c278 100644 --- a/xbmc/games/addons/GameClient.h +++ b/xbmc/games/addons/GameClient.h @@ -11,7 +11,6 @@ #include "GameClientSubsystem.h" #include "addons/binary-addons/AddonDll.h" #include "addons/kodi-addon-dev-kit/include/kodi/kodi_game_types.h" -#include "games/GameTypes.h" #include "threads/CriticalSection.h" #include <atomic> diff --git a/xbmc/games/addons/input/CMakeLists.txt b/xbmc/games/addons/input/CMakeLists.txt index 9927ceb90d..69cc342581 100644 --- a/xbmc/games/addons/input/CMakeLists.txt +++ b/xbmc/games/addons/input/CMakeLists.txt @@ -1,4 +1,5 @@ -set(SOURCES GameClientDevice.cpp +set(SOURCES GameClientController.cpp + GameClientDevice.cpp GameClientHardware.cpp GameClientInput.cpp GameClientJoystick.cpp @@ -8,7 +9,8 @@ set(SOURCES GameClientDevice.cpp GameClientTopology.cpp ) -set(HEADERS GameClientDevice.h +set(HEADERS GameClientController.h + GameClientDevice.h GameClientHardware.h GameClientInput.h GameClientJoystick.h diff --git a/xbmc/games/addons/input/GameClientController.cpp b/xbmc/games/addons/input/GameClientController.cpp new file mode 100644 index 0000000000..fad1feed13 --- /dev/null +++ b/xbmc/games/addons/input/GameClientController.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2018 Team Kodi + * http://kodi.tv + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this Program; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include "GameClientController.h" +#include "GameClientInput.h" +#include "games/controllers/Controller.h" +#include "games/controllers/ControllerFeature.h" +#include "games/controllers/ControllerLayout.h" +#include "games/controllers/ControllerTopology.h" + +#include <algorithm> +#include <vector> + +using namespace KODI; +using namespace GAME; + +CGameClientController::CGameClientController(CGameClientInput &input, ControllerPtr controller) : + m_input(input), + m_controller(std::move(controller)), + m_controllerId(m_controller->ID()) +{ + // Generate arrays of features + for (const CControllerFeature &feature : m_controller->Features()) + { + // Skip feature if not supported by the game client + if (!m_input.HasFeature(m_controller->ID(), feature.Name())) + continue; + + // Add feature to array of the appropriate type + switch (feature.Type()) + { + case FEATURE_TYPE::SCALAR: + { + switch (feature.InputType()) + { + case JOYSTICK::INPUT_TYPE::DIGITAL: + m_digitalButtons.emplace_back(const_cast<char*>(feature.Name().c_str())); + break; + case JOYSTICK::INPUT_TYPE::ANALOG: + m_analogButtons.emplace_back(const_cast<char*>(feature.Name().c_str())); + break; + default: + break; + } + break; + } + case FEATURE_TYPE::ANALOG_STICK: + m_analogSticks.emplace_back(const_cast<char*>(feature.Name().c_str())); + break; + case FEATURE_TYPE::ACCELEROMETER: + m_accelerometers.emplace_back(const_cast<char*>(feature.Name().c_str())); + break; + case FEATURE_TYPE::KEY: + m_keys.emplace_back(const_cast<char*>(feature.Name().c_str())); + break; + case FEATURE_TYPE::RELPOINTER: + m_relPointers.emplace_back(const_cast<char*>(feature.Name().c_str())); + break; + case FEATURE_TYPE::ABSPOINTER: + m_absPointers.emplace_back(const_cast<char*>(feature.Name().c_str())); + break; + case FEATURE_TYPE::MOTOR: + m_motors.emplace_back(const_cast<char*>(feature.Name().c_str())); + break; + default: + break; + } + } + + //! @todo Sort vectors +} + +game_controller_layout CGameClientController::TranslateController() const +{ + game_controller_layout controllerStruct{}; + + controllerStruct.controller_id = const_cast<char*>(m_controllerId.c_str()); + controllerStruct.provides_input = m_controller->Layout().Topology().ProvidesInput(); + + if (!m_digitalButtons.empty()) + { + controllerStruct.digital_buttons = const_cast<char**>(m_digitalButtons.data()); + controllerStruct.digital_button_count = m_digitalButtons.size(); + } + if (!m_analogButtons.empty()) + { + controllerStruct.analog_buttons = const_cast<char**>(m_analogButtons.data()); + controllerStruct.analog_button_count = m_analogButtons.size(); + } + if (!m_analogSticks.empty()) + { + controllerStruct.analog_sticks = const_cast<char**>(m_analogSticks.data()); + controllerStruct.analog_stick_count = m_analogSticks.size(); + } + if (!m_accelerometers.empty()) + { + controllerStruct.accelerometers = const_cast<char**>(m_accelerometers.data()); + controllerStruct.accelerometer_count = m_accelerometers.size(); + } + if (!m_keys.empty()) + { + controllerStruct.keys = const_cast<char**>(m_keys.data()); + controllerStruct.key_count = m_keys.size(); + } + if (!m_relPointers.empty()) + { + controllerStruct.rel_pointers = const_cast<char**>(m_relPointers.data()); + controllerStruct.rel_pointer_count = m_relPointers.size(); + } + if (!m_absPointers.empty()) + { + controllerStruct.abs_pointers = const_cast<char**>(m_absPointers.data()); + controllerStruct.abs_pointer_count = m_absPointers.size(); + } + if (!m_motors.empty()) + { + controllerStruct.motors = const_cast<char**>(m_motors.data()); + controllerStruct.motor_count = m_motors.size(); + } + + return controllerStruct; +} diff --git a/xbmc/games/addons/input/GameClientController.h b/xbmc/games/addons/input/GameClientController.h new file mode 100644 index 0000000000..68d649dbb1 --- /dev/null +++ b/xbmc/games/addons/input/GameClientController.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2018 Team Kodi + * http://kodi.tv + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this Program; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#pragma once + +#include "addons/kodi-addon-dev-kit/include/kodi/kodi_game_types.h" +#include "games/controllers/ControllerTypes.h" + +#include <vector> + +namespace KODI +{ +namespace GAME +{ + class CGameClientInput; + + /*! + * \brief A container for the layout of a controller connected to a game + * client input port + */ + class CGameClientController + { + public: + /*! + * \brief Construct a controller layout + * + * \brief controller The controller add-on + */ + CGameClientController(CGameClientInput &input, ControllerPtr controller); + + /*! + * \brief Get a controller layout for the Game API + */ + game_controller_layout TranslateController() const; + + private: + // Construction parameters + CGameClientInput &m_input; + const ControllerPtr m_controller; + + // Buffer parameters + std::string m_controllerId; + std::vector<char*> m_digitalButtons; + std::vector<char*> m_analogButtons; + std::vector<char*> m_analogSticks; + std::vector<char*> m_accelerometers; + std::vector<char*> m_keys; + std::vector<char*> m_relPointers; + std::vector<char*> m_absPointers; + std::vector<char*> m_motors; + }; +} // namespace GAME +} // namespace KODI diff --git a/xbmc/games/addons/input/GameClientDevice.cpp b/xbmc/games/addons/input/GameClientDevice.cpp index 68b0fb2692..0faf74908b 100644 --- a/xbmc/games/addons/input/GameClientDevice.cpp +++ b/xbmc/games/addons/input/GameClientDevice.cpp @@ -11,7 +11,6 @@ #include "addons/kodi-addon-dev-kit/include/kodi/kodi_game_types.h" #include "games/controllers/Controller.h" #include "games/controllers/ControllerTopology.h" -#include "games/controllers/ControllerTranslator.h" #include "games/GameServices.h" #include "utils/StringUtils.h" #include "ServiceBroker.h" diff --git a/xbmc/games/addons/input/GameClientInput.cpp b/xbmc/games/addons/input/GameClientInput.cpp index ed0e8b96d8..d8b90ff94b 100644 --- a/xbmc/games/addons/input/GameClientInput.cpp +++ b/xbmc/games/addons/input/GameClientInput.cpp @@ -7,6 +7,7 @@ */ #include "GameClientInput.h" +#include "GameClientController.h" #include "GameClientHardware.h" #include "GameClientJoystick.h" #include "GameClientKeyboard.h" @@ -49,6 +50,8 @@ void CGameClientInput::Initialize() LoadTopology(); ActivateControllers(m_topology->ControllerTree()); + + SetControllerLayouts(m_topology->ControllerTree().GetControllers()); } void CGameClientInput::Start(IGameInputCallback *input) @@ -106,6 +109,7 @@ void CGameClientInput::Deinitialize() Stop(); m_topology->Clear(); + m_controllerLayouts.clear(); } void CGameClientInput::Stop() @@ -215,11 +219,38 @@ void CGameClientInput::ActivateControllers(CControllerHub &hub) { for (auto &port : hub.Ports()) { + port.SetConnected(true); port.SetActiveController(0); ActivateControllers(port.ActiveController().Hub()); } } +void CGameClientInput::SetControllerLayouts(const ControllerVector &controllers) +{ + if (controllers.empty()) + return; + + for (const auto &controller : controllers) + { + const std::string controllerId = controller->ID(); + if (m_controllerLayouts.find(controllerId) == m_controllerLayouts.end()) + m_controllerLayouts[controllerId].reset(new CGameClientController(*this, controller)); + } + + std::vector<game_controller_layout> controllerStructs; + for (const auto &it : m_controllerLayouts) + controllerStructs.emplace_back(it.second->TranslateController()); + + try + { + m_struct.toAddon.SetControllerLayouts(controllerStructs.data(), controllerStructs.size()); + } + catch (...) + { + m_gameClient.LogException("SetControllerLayouts()"); + } +} + const CControllerTree &CGameClientInput::GetControllerTree() const { return m_topology->ControllerTree(); @@ -267,20 +298,6 @@ bool CGameClientInput::OpenKeyboard(const ControllerPtr &controller) if (keyboards.empty()) return false; - std::string controllerId = controller->ID(); - - game_controller controllerStruct{}; - - controllerStruct.controller_id = controllerId.c_str(); - controllerStruct.digital_button_count = controller->FeatureCount(FEATURE_TYPE::SCALAR, INPUT_TYPE::DIGITAL); - controllerStruct.analog_button_count = controller->FeatureCount(FEATURE_TYPE::SCALAR, INPUT_TYPE::ANALOG); - controllerStruct.analog_stick_count = controller->FeatureCount(FEATURE_TYPE::ANALOG_STICK); - controllerStruct.accelerometer_count = controller->FeatureCount(FEATURE_TYPE::ACCELEROMETER); - controllerStruct.key_count = controller->FeatureCount(FEATURE_TYPE::KEY); - controllerStruct.rel_pointer_count = controller->FeatureCount(FEATURE_TYPE::RELPOINTER); - controllerStruct.abs_pointer_count = controller->FeatureCount(FEATURE_TYPE::ABSPOINTER); - controllerStruct.motor_count = controller->FeatureCount(FEATURE_TYPE::MOTOR); - bool bSuccess = false; { @@ -290,7 +307,7 @@ bool CGameClientInput::OpenKeyboard(const ControllerPtr &controller) { try { - bSuccess = m_struct.toAddon.EnableKeyboard(true, &controllerStruct); + bSuccess = m_struct.toAddon.EnableKeyboard(true, controller->ID().c_str()); } catch (...) { @@ -301,7 +318,7 @@ bool CGameClientInput::OpenKeyboard(const ControllerPtr &controller) if (bSuccess) { - m_keyboard.reset(new CGameClientKeyboard(m_gameClient, controllerId, keyboards.at(0).get())); + m_keyboard.reset(new CGameClientKeyboard(m_gameClient, controller->ID(), keyboards.at(0).get())); return true; } @@ -345,20 +362,6 @@ bool CGameClientInput::OpenMouse(const ControllerPtr &controller) if (mice.empty()) return false; - std::string controllerId = controller->ID(); - - game_controller controllerStruct{}; - - controllerStruct.controller_id = controllerId.c_str(); - controllerStruct.digital_button_count = controller->FeatureCount(FEATURE_TYPE::SCALAR, INPUT_TYPE::DIGITAL); - controllerStruct.analog_button_count = controller->FeatureCount(FEATURE_TYPE::SCALAR, INPUT_TYPE::ANALOG); - controllerStruct.analog_stick_count = controller->FeatureCount(FEATURE_TYPE::ANALOG_STICK); - controllerStruct.accelerometer_count = controller->FeatureCount(FEATURE_TYPE::ACCELEROMETER); - controllerStruct.key_count = controller->FeatureCount(FEATURE_TYPE::KEY); - controllerStruct.rel_pointer_count = controller->FeatureCount(FEATURE_TYPE::RELPOINTER); - controllerStruct.abs_pointer_count = controller->FeatureCount(FEATURE_TYPE::ABSPOINTER); - controllerStruct.motor_count = controller->FeatureCount(FEATURE_TYPE::MOTOR); - bool bSuccess = false; { @@ -368,7 +371,7 @@ bool CGameClientInput::OpenMouse(const ControllerPtr &controller) { try { - bSuccess = m_struct.toAddon.EnableMouse(true, &controllerStruct); + bSuccess = m_struct.toAddon.EnableMouse(true, controller->ID().c_str()); } catch (...) { @@ -379,7 +382,7 @@ bool CGameClientInput::OpenMouse(const ControllerPtr &controller) if (bSuccess) { - m_mouse.reset(new CGameClientMouse(m_gameClient, controllerId, mice.at(0).get())); + m_mouse.reset(new CGameClientMouse(m_gameClient, controller->ID(), mice.at(0).get())); return true; } @@ -427,21 +430,6 @@ bool CGameClientInput::OpenJoystick(const std::string &portAddress, const Contro return false; } - std::string strId = controller->ID(); - - game_controller controllerStruct{}; - - controllerStruct.controller_id = strId.c_str(); - controllerStruct.provides_input = controller->Topology().ProvidesInput(); - controllerStruct.digital_button_count = controller->FeatureCount(FEATURE_TYPE::SCALAR, INPUT_TYPE::DIGITAL); - controllerStruct.analog_button_count = controller->FeatureCount(FEATURE_TYPE::SCALAR, INPUT_TYPE::ANALOG); - controllerStruct.analog_stick_count = controller->FeatureCount(FEATURE_TYPE::ANALOG_STICK); - controllerStruct.accelerometer_count = controller->FeatureCount(FEATURE_TYPE::ACCELEROMETER); - controllerStruct.key_count = controller->FeatureCount(FEATURE_TYPE::KEY); - controllerStruct.rel_pointer_count = controller->FeatureCount(FEATURE_TYPE::RELPOINTER); - controllerStruct.abs_pointer_count = controller->FeatureCount(FEATURE_TYPE::ABSPOINTER); - controllerStruct.motor_count = controller->FeatureCount(FEATURE_TYPE::MOTOR); - bool bSuccess = false; { @@ -451,7 +439,7 @@ bool CGameClientInput::OpenJoystick(const std::string &portAddress, const Contro { try { - bSuccess = m_struct.toAddon.ConnectController(true, portAddress.c_str(), &controllerStruct); + bSuccess = m_struct.toAddon.ConnectController(true, portAddress.c_str(), controller->ID().c_str()); } catch (...) { diff --git a/xbmc/games/addons/input/GameClientInput.h b/xbmc/games/addons/input/GameClientInput.h index 08dc040dff..4e57be415b 100644 --- a/xbmc/games/addons/input/GameClientInput.h +++ b/xbmc/games/addons/input/GameClientInput.h @@ -31,6 +31,7 @@ namespace JOYSTICK namespace GAME { class CGameClient; + class CGameClientController; class CGameClientHardware; class CGameClientJoystick; class CGameClientKeyboard; @@ -91,6 +92,7 @@ namespace GAME // Private input helpers void LoadTopology(); + void SetControllerLayouts(const ControllerVector &controllers); void ProcessJoysticks(); PortMap MapJoysticks(const PERIPHERALS::PeripheralVector &peripheralJoysticks, const JoystickMap &gameClientjoysticks) const; @@ -105,6 +107,8 @@ namespace GAME // Input properties IGameInputCallback *m_inputCallback = nullptr; std::unique_ptr<CGameClientTopology> m_topology; + using ControllerLayoutMap = std::map<std::string, std::unique_ptr<CGameClientController>>; + ControllerLayoutMap m_controllerLayouts; JoystickMap m_joysticks; PortMap m_portMap; std::unique_ptr<CGameClientKeyboard> m_keyboard; diff --git a/xbmc/games/addons/input/GameClientKeyboard.cpp b/xbmc/games/addons/input/GameClientKeyboard.cpp index 604c27e26d..cb031289c3 100644 --- a/xbmc/games/addons/input/GameClientKeyboard.cpp +++ b/xbmc/games/addons/input/GameClientKeyboard.cpp @@ -12,7 +12,6 @@ #include "games/addons/GameClient.h" #include "games/addons/GameClientTranslator.h" #include "input/keyboard/interfaces/IKeyboardInputProvider.h" -#include "input/Key.h" #include "utils/log.h" #include <utility> diff --git a/xbmc/games/addons/input/GameClientMouse.cpp b/xbmc/games/addons/input/GameClientMouse.cpp index 6085880ba4..3da3ea26d0 100644 --- a/xbmc/games/addons/input/GameClientMouse.cpp +++ b/xbmc/games/addons/input/GameClientMouse.cpp @@ -11,8 +11,6 @@ #include "addons/kodi-addon-dev-kit/include/kodi/kodi_game_types.h" #include "games/addons/GameClient.h" #include "input/mouse/interfaces/IMouseInputProvider.h" -#include "input/Key.h" -#include "utils/log.h" #include <utility> diff --git a/xbmc/games/addons/input/GameClientPort.cpp b/xbmc/games/addons/input/GameClientPort.cpp index af2f579bf3..c490ebb2c0 100644 --- a/xbmc/games/addons/input/GameClientPort.cpp +++ b/xbmc/games/addons/input/GameClientPort.cpp @@ -12,7 +12,6 @@ #include "games/addons/GameClientTranslator.h" #include "games/controllers/Controller.h" #include "games/controllers/ControllerTopology.h" -#include "games/controllers/ControllerTranslator.h" #include "utils/StringUtils.h" #include <algorithm> diff --git a/xbmc/games/addons/input/GameClientTopology.cpp b/xbmc/games/addons/input/GameClientTopology.cpp index c613e15ce6..9469475bfa 100644 --- a/xbmc/games/addons/input/GameClientTopology.cpp +++ b/xbmc/games/addons/input/GameClientTopology.cpp @@ -98,9 +98,9 @@ std::string CGameClientTopology::MakeAddress(const std::string &baseAddress, con std::ostringstream address; if (!baseAddress.empty()) - address << baseAddress << CONTROLLER_ADDRESS_SEPARATOR; + address << baseAddress; - address << nodeId; + address << CONTROLLER_ADDRESS_SEPARATOR << nodeId; return address.str(); } diff --git a/xbmc/games/controllers/Controller.cpp b/xbmc/games/controllers/Controller.cpp index fc7562911b..b92f0591ae 100644 --- a/xbmc/games/controllers/Controller.cpp +++ b/xbmc/games/controllers/Controller.cpp @@ -11,7 +11,6 @@ #include "ControllerLayout.h" #include "ControllerTopology.h" #include "utils/log.h" -#include "utils/URIUtils.h" #include "utils/XBMCTinyXML.h" #include "utils/XMLUtils.h" #include "URL.h" diff --git a/xbmc/games/controllers/ControllerTopology.cpp b/xbmc/games/controllers/ControllerTopology.cpp index 4cc2152661..402eaffb49 100644 --- a/xbmc/games/controllers/ControllerTopology.cpp +++ b/xbmc/games/controllers/ControllerTopology.cpp @@ -8,11 +8,8 @@ #include "ControllerTopology.h" #include "ControllerDefinitions.h" -#include "games/controllers/Controller.h" -#include "games/GameServices.h" #include "utils/log.h" #include "utils/XMLUtils.h" -#include "ServiceManager.h" #include <algorithm> using namespace KODI; diff --git a/xbmc/games/controllers/ControllerTopology.h b/xbmc/games/controllers/ControllerTopology.h index 4ecf82cf9f..f691d3035c 100644 --- a/xbmc/games/controllers/ControllerTopology.h +++ b/xbmc/games/controllers/ControllerTopology.h @@ -8,8 +8,6 @@ #pragma once -#include "games/GameTypes.h" - #include <string> #include <vector> diff --git a/xbmc/games/controllers/dialogs/GUIDialogButtonCapture.cpp b/xbmc/games/controllers/dialogs/GUIDialogButtonCapture.cpp index 45c35b3aa3..02e50aa6a9 100644 --- a/xbmc/games/controllers/dialogs/GUIDialogButtonCapture.cpp +++ b/xbmc/games/controllers/dialogs/GUIDialogButtonCapture.cpp @@ -8,10 +8,7 @@ #include "GUIDialogButtonCapture.h" #include "games/controllers/ControllerIDs.h" -#include "guilib/GUIWindowManager.h" -#include "guilib/WindowIDs.h" #include "input/joysticks/interfaces/IButtonMap.h" -#include "input/joysticks/interfaces/IButtonMapCallback.h" #include "input/joysticks/JoystickUtils.h" #include "input/IKeymap.h" #include "input/ActionIDs.h" diff --git a/xbmc/games/controllers/guicontrols/GUICardinalFeatureButton.cpp b/xbmc/games/controllers/guicontrols/GUICardinalFeatureButton.cpp index 565c75fbc3..897c70660e 100644 --- a/xbmc/games/controllers/guicontrols/GUICardinalFeatureButton.cpp +++ b/xbmc/games/controllers/guicontrols/GUICardinalFeatureButton.cpp @@ -8,7 +8,6 @@ #include "GUICardinalFeatureButton.h" #include "guilib/LocalizeStrings.h" -#include "utils/StringUtils.h" #include <string> diff --git a/xbmc/games/controllers/guicontrols/GUIScalarFeatureButton.cpp b/xbmc/games/controllers/guicontrols/GUIScalarFeatureButton.cpp index 9117b8282c..1a30fa5c6e 100644 --- a/xbmc/games/controllers/guicontrols/GUIScalarFeatureButton.cpp +++ b/xbmc/games/controllers/guicontrols/GUIScalarFeatureButton.cpp @@ -8,7 +8,6 @@ #include "GUIScalarFeatureButton.h" #include "guilib/LocalizeStrings.h" -#include "utils/StringUtils.h" #include <string> diff --git a/xbmc/games/controllers/guicontrols/GUISelectKeyButton.cpp b/xbmc/games/controllers/guicontrols/GUISelectKeyButton.cpp index 3248cbd3ac..533a0d4a2c 100644 --- a/xbmc/games/controllers/guicontrols/GUISelectKeyButton.cpp +++ b/xbmc/games/controllers/guicontrols/GUISelectKeyButton.cpp @@ -8,7 +8,6 @@ #include "GUISelectKeyButton.h" #include "guilib/LocalizeStrings.h" -#include "utils/StringUtils.h" #include <string> diff --git a/xbmc/games/controllers/guicontrols/GUIThrottleButton.cpp b/xbmc/games/controllers/guicontrols/GUIThrottleButton.cpp index 81e9fef9c4..28c6b848f9 100644 --- a/xbmc/games/controllers/guicontrols/GUIThrottleButton.cpp +++ b/xbmc/games/controllers/guicontrols/GUIThrottleButton.cpp @@ -8,7 +8,6 @@ #include "GUIThrottleButton.h" #include "guilib/LocalizeStrings.h" -#include "utils/StringUtils.h" #include <string> diff --git a/xbmc/games/controllers/guicontrols/GUIWheelButton.cpp b/xbmc/games/controllers/guicontrols/GUIWheelButton.cpp index 0c60ccba26..571315cb90 100644 --- a/xbmc/games/controllers/guicontrols/GUIWheelButton.cpp +++ b/xbmc/games/controllers/guicontrols/GUIWheelButton.cpp @@ -8,7 +8,6 @@ #include "GUIWheelButton.h" #include "guilib/LocalizeStrings.h" -#include "utils/StringUtils.h" #include <string> diff --git a/xbmc/games/controllers/types/ControllerGrid.cpp b/xbmc/games/controllers/types/ControllerGrid.cpp index 244ea5c335..1f7821ec37 100644 --- a/xbmc/games/controllers/types/ControllerGrid.cpp +++ b/xbmc/games/controllers/types/ControllerGrid.cpp @@ -8,7 +8,6 @@ #include "ControllerGrid.h" #include "games/controllers/Controller.h" -#include "games/controllers/ControllerTranslator.h" #include "utils/log.h" #include <algorithm> diff --git a/xbmc/games/controllers/types/ControllerTree.cpp b/xbmc/games/controllers/types/ControllerTree.cpp index 637b260cfa..16b9fd81f0 100644 --- a/xbmc/games/controllers/types/ControllerTree.cpp +++ b/xbmc/games/controllers/types/ControllerTree.cpp @@ -49,6 +49,22 @@ void CControllerNode::SetController(ControllerPtr controller) m_controller = std::move(controller); } +void CControllerNode::GetControllers(ControllerVector &controllers) const +{ + const ControllerPtr &myController = m_controller; + + auto it = std::find_if(controllers.begin(), controllers.end(), + [&myController](const ControllerPtr &controller) + { + return myController->ID() == controller->ID(); + }); + + if (it == controllers.end()) + controllers.emplace_back(m_controller); + + m_hub->GetControllers(controllers); +} + void CControllerNode::SetAddress(std::string address) { m_address = std::move(address); @@ -263,6 +279,22 @@ bool CControllerHub::IsControllerAccepted(const std::string &portAddress, return bAccepted; } +ControllerVector CControllerHub::GetControllers() const +{ + ControllerVector controllers; + GetControllers(controllers); + return controllers; +} + +void CControllerHub::GetControllers(ControllerVector &controllers) const +{ + for (const CControllerPortNode &port : m_ports) + { + for (const CControllerNode &node : port.CompatibleControllers()) + node.GetControllers(controllers); + } +} + const CControllerPortNode &CControllerHub::GetPort(const std::string &address) const { return GetPort(m_ports, address); diff --git a/xbmc/games/controllers/types/ControllerTree.h b/xbmc/games/controllers/types/ControllerTree.h index e1d81d7f79..c46952894c 100644 --- a/xbmc/games/controllers/types/ControllerTree.h +++ b/xbmc/games/controllers/types/ControllerTree.h @@ -49,6 +49,8 @@ namespace GAME const ControllerPtr &Controller() const { return m_controller; } void SetController(ControllerPtr controller); + void GetControllers(ControllerVector &controllers) const; + /*! * \brief Address given to the node by the implementation */ @@ -222,6 +224,8 @@ namespace GAME bool IsControllerAccepted(const std::string &controllerId) const; bool IsControllerAccepted(const std::string &portAddress, const std::string &controllerId) const; + ControllerVector GetControllers() const; + void GetControllers(ControllerVector &controllers) const; const CControllerPortNode &GetPort(const std::string &address) const; diff --git a/xbmc/games/controllers/windows/GUIConfigurationWizard.cpp b/xbmc/games/controllers/windows/GUIConfigurationWizard.cpp index 44c0216ef8..c41bf83f9c 100644 --- a/xbmc/games/controllers/windows/GUIConfigurationWizard.cpp +++ b/xbmc/games/controllers/windows/GUIConfigurationWizard.cpp @@ -11,7 +11,6 @@ #include "games/controllers/guicontrols/GUIFeatureButton.h" #include "games/controllers/Controller.h" #include "games/controllers/ControllerFeature.h" -#include "games/controllers/ControllerTranslator.h" #include "input/joysticks/interfaces/IButtonMap.h" #include "input/joysticks/interfaces/IButtonMapCallback.h" #include "input/joysticks/JoystickUtils.h" diff --git a/xbmc/games/controllers/windows/GUIControllerList.cpp b/xbmc/games/controllers/windows/GUIControllerList.cpp index 0293914629..43770f8f1b 100644 --- a/xbmc/games/controllers/windows/GUIControllerList.cpp +++ b/xbmc/games/controllers/windows/GUIControllerList.cpp @@ -22,7 +22,6 @@ #include "games/controllers/types/ControllerTree.h" #include "games/controllers/Controller.h" #include "games/controllers/ControllerIDs.h" -#include "games/controllers/ControllerFeature.h" #include "games/controllers/ControllerLayout.h" #include "games/controllers/guicontrols/GUIControllerButton.h" #include "games/controllers/guicontrols/GUIGameController.h" @@ -31,7 +30,6 @@ #include "guilib/GUIButtonControl.h" #include "guilib/GUIControlGroupList.h" #include "guilib/GUIWindow.h" -#include "guilib/WindowIDs.h" #include "messaging/ApplicationMessenger.h" #include "peripherals/Peripherals.h" #include "utils/StringUtils.h" diff --git a/xbmc/games/controllers/windows/GUIControllerList.h b/xbmc/games/controllers/windows/GUIControllerList.h index 21d219bd3b..c78ca25f87 100644 --- a/xbmc/games/controllers/windows/GUIControllerList.h +++ b/xbmc/games/controllers/windows/GUIControllerList.h @@ -10,7 +10,6 @@ #include "IConfigurationWindow.h" #include "addons/AddonEvents.h" -#include "addons/Addon.h" #include "games/GameTypes.h" #include "games/controllers/ControllerTypes.h" diff --git a/xbmc/games/controllers/windows/GUIFeatureList.cpp b/xbmc/games/controllers/windows/GUIFeatureList.cpp index ecaeeafd85..68e363a05a 100644 --- a/xbmc/games/controllers/windows/GUIFeatureList.cpp +++ b/xbmc/games/controllers/windows/GUIFeatureList.cpp @@ -21,10 +21,8 @@ #include "guilib/GUIControlGroupList.h" #include "guilib/GUIImage.h" #include "guilib/GUILabelControl.h" -#include "guilib/GUIMessage.h" #include "guilib/GUIWindow.h" #include "guilib/LocalizeStrings.h" -#include "messaging/ApplicationMessenger.h" using namespace KODI; using namespace GAME; diff --git a/xbmc/games/controllers/windows/IConfigurationWindow.h b/xbmc/games/controllers/windows/IConfigurationWindow.h index 5989ada7e7..86b7d52577 100644 --- a/xbmc/games/controllers/windows/IConfigurationWindow.h +++ b/xbmc/games/controllers/windows/IConfigurationWindow.h @@ -36,8 +36,6 @@ class CEvent; * and the prompt for input ends. */ -#include "input/joysticks/JoystickTypes.h" - namespace KODI { namespace GAME diff --git a/xbmc/games/dialogs/GUIDialogSelectGameClient.cpp b/xbmc/games/dialogs/GUIDialogSelectGameClient.cpp index 2f422493de..9269e92dff 100644 --- a/xbmc/games/dialogs/GUIDialogSelectGameClient.cpp +++ b/xbmc/games/dialogs/GUIDialogSelectGameClient.cpp @@ -23,7 +23,6 @@ #include "utils/StringUtils.h" #include "utils/URIUtils.h" #include "ServiceBroker.h" -#include "URL.h" using namespace KODI; using namespace KODI::MESSAGING; diff --git a/xbmc/games/dialogs/osd/DialogGameVideoFilter.h b/xbmc/games/dialogs/osd/DialogGameVideoFilter.h index 00ff9861ec..1ba7eebc39 100644 --- a/xbmc/games/dialogs/osd/DialogGameVideoFilter.h +++ b/xbmc/games/dialogs/osd/DialogGameVideoFilter.h @@ -9,7 +9,6 @@ #pragma once #include "DialogGameVideoSelect.h" -#include "cores/GameSettings.h" #include "FileItem.h" namespace KODI diff --git a/xbmc/games/dialogs/osd/DialogGameVideoSelect.cpp b/xbmc/games/dialogs/osd/DialogGameVideoSelect.cpp index fe2dc500c7..2779e15298 100644 --- a/xbmc/games/dialogs/osd/DialogGameVideoSelect.cpp +++ b/xbmc/games/dialogs/osd/DialogGameVideoSelect.cpp @@ -14,7 +14,6 @@ #include "guilib/GUIMessage.h" #include "guilib/GUIComponent.h" #include "guilib/GUIWindowManager.h" -#include "guilib/WindowIDs.h" #include "input/ActionIDs.h" #include "settings/GameSettings.h" #include "settings/MediaSettings.h" @@ -23,7 +22,6 @@ #include "view/GUIViewControl.h" #include "view/ViewState.h" #include "Application.h" -#include "ApplicationPlayer.h" #include "FileItem.h" #include "ServiceBroker.h" diff --git a/xbmc/games/dialogs/osd/DialogGameVolume.cpp b/xbmc/games/dialogs/osd/DialogGameVolume.cpp index 4332d6561a..72c83b8197 100644 --- a/xbmc/games/dialogs/osd/DialogGameVolume.cpp +++ b/xbmc/games/dialogs/osd/DialogGameVolume.cpp @@ -9,7 +9,6 @@ #include "DialogGameVolume.h" #include "dialogs/GUIDialogVolumeBar.h" #include "guilib/GUIComponent.h" -#include "guilib/GUIComponent.h" #include "guilib/GUIDialog.h" #include "guilib/GUIMessage.h" #include "guilib/GUISliderControl.h" @@ -17,7 +16,6 @@ #include "guilib/LocalizeStrings.h" #include "guilib/WindowIDs.h" #include "interfaces/AnnouncementManager.h" -#include "utils/log.h" #include "utils/Variant.h" #include "Application.h" #include "ServiceBroker.h" diff --git a/xbmc/games/ports/Port.cpp b/xbmc/games/ports/Port.cpp index bbcc817b95..a698516e8c 100644 --- a/xbmc/games/ports/Port.cpp +++ b/xbmc/games/ports/Port.cpp @@ -9,7 +9,6 @@ #include "Port.h" #include "InputSink.h" #include "games/addons/GameClient.h" -#include "games/addons/input/GameClientInput.h" #include "guilib/WindowIDs.h" #include "input/joysticks/keymaps/KeymapHandling.h" #include "peripherals/devices/Peripheral.h" diff --git a/xbmc/games/windows/GUIViewStateWindowGames.cpp b/xbmc/games/windows/GUIViewStateWindowGames.cpp index 19cf559ce4..2a509e56a8 100644 --- a/xbmc/games/windows/GUIViewStateWindowGames.cpp +++ b/xbmc/games/windows/GUIViewStateWindowGames.cpp @@ -7,13 +7,10 @@ */ #include "GUIViewStateWindowGames.h" -#include "addons/BinaryAddonCache.h" -#include "games/addons/GameClient.h" #include "games/GameUtils.h" #include "windowing/GraphicContext.h" // include before ViewState.h #include "guilib/LocalizeStrings.h" #include "guilib/WindowIDs.h" -#include "input/Key.h" #include "settings/MediaSourceSettings.h" #include "utils/StringUtils.h" #include "view/ViewState.h" diff --git a/xbmc/games/windows/GUIWindowGames.cpp b/xbmc/games/windows/GUIWindowGames.cpp index e1e6aa176f..355442386f 100644 --- a/xbmc/games/windows/GUIWindowGames.cpp +++ b/xbmc/games/windows/GUIWindowGames.cpp @@ -13,13 +13,11 @@ #include "dialogs/GUIDialogMediaSource.h" #include "dialogs/GUIDialogProgress.h" #include "FileItem.h" -#include "games/tags/GameInfoTag.h" #include "games/addons/GameClient.h" #include "guilib/GUIComponent.h" #include "guilib/GUIWindowManager.h" #include "guilib/WindowIDs.h" #include "GUIPassword.h" -#include "input/Key.h" #include "PlayListPlayer.h" #include "ServiceBroker.h" #include "settings/MediaSourceSettings.h" diff --git a/xbmc/games/windows/GUIWindowGames.h b/xbmc/games/windows/GUIWindowGames.h index 3087c73719..ff735635cf 100644 --- a/xbmc/games/windows/GUIWindowGames.h +++ b/xbmc/games/windows/GUIWindowGames.h @@ -8,7 +8,6 @@ #pragma once -#include "games/GameTypes.h" #include "windows/GUIMediaWindow.h" class CGUIDialogProgress; diff --git a/xbmc/guilib/GUIAudioManager.h b/xbmc/guilib/GUIAudioManager.h index 3e8891bbee..a21f83551f 100644 --- a/xbmc/guilib/GUIAudioManager.h +++ b/xbmc/guilib/GUIAudioManager.h @@ -12,7 +12,6 @@ #include <string> #include "GUIComponent.h" -#include "ServiceBroker.h" #include "cores/AudioEngine/Interfaces/AESound.h" #include "settings/lib/ISettingCallback.h" #include "threads/CriticalSection.h" diff --git a/xbmc/guilib/GUIColorManager.h b/xbmc/guilib/GUIColorManager.h index 9680b17cc2..ea11cd0edd 100644 --- a/xbmc/guilib/GUIColorManager.h +++ b/xbmc/guilib/GUIColorManager.h @@ -21,8 +21,6 @@ #include <map> #include <string> -#include "GUIComponent.h" -#include "ServiceBroker.h" #include "utils/Color.h" class CXBMCTinyXML; diff --git a/xbmc/guilib/GUIControlGroup.cpp b/xbmc/guilib/GUIControlGroup.cpp index 57041b5cae..4219e50b96 100644 --- a/xbmc/guilib/GUIControlGroup.cpp +++ b/xbmc/guilib/GUIControlGroup.cpp @@ -12,8 +12,6 @@ #include <cassert> #include <utility> -#include "guilib/guiinfo/GUIInfoLabels.h" - CGUIControlGroup::CGUIControlGroup() { m_defaultControl = 0; diff --git a/xbmc/guilib/GUIMultiImage.cpp b/xbmc/guilib/GUIMultiImage.cpp index 948192d15c..46967b5bc5 100644 --- a/xbmc/guilib/GUIMultiImage.cpp +++ b/xbmc/guilib/GUIMultiImage.cpp @@ -14,7 +14,6 @@ #include "utils/URIUtils.h" #include "utils/JobManager.h" #include "FileItem.h" -#include "settings/AdvancedSettings.h" #include "input/Key.h" #include "TextureCache.h" #include "WindowIDs.h" diff --git a/xbmc/guilib/GUIStaticItem.h b/xbmc/guilib/GUIStaticItem.h index 74c545a2fb..980b1c33f3 100644 --- a/xbmc/guilib/GUIStaticItem.h +++ b/xbmc/guilib/GUIStaticItem.h @@ -20,7 +20,6 @@ #include "guilib/guiinfo/GUIInfoLabel.h" #include "interfaces/info/InfoBool.h" #include "FileItem.h" -#include "GUIAction.h" class TiXmlElement; diff --git a/xbmc/guilib/GUITextLayout.cpp b/xbmc/guilib/GUITextLayout.cpp index bb1959ebf7..0482b78630 100644 --- a/xbmc/guilib/GUITextLayout.cpp +++ b/xbmc/guilib/GUITextLayout.cpp @@ -8,6 +8,7 @@ #include "GUITextLayout.h" #include "GUIFont.h" +#include "GUIComponent.h" #include "GUIControl.h" #include "GUIColorManager.h" #include "utils/CharsetConverter.h" diff --git a/xbmc/guilib/GUIWindowManager.cpp b/xbmc/guilib/GUIWindowManager.cpp index 8a33123e0d..652aa4d9f7 100644 --- a/xbmc/guilib/GUIWindowManager.cpp +++ b/xbmc/guilib/GUIWindowManager.cpp @@ -16,7 +16,6 @@ #include "GUIInfoManager.h" #include "threads/SingleLock.h" #include "utils/URIUtils.h" -#include "SeekHandler.h" #include "settings/AdvancedSettings.h" #include "settings/SettingsComponent.h" #include "addons/Skin.h" diff --git a/xbmc/guilib/GUIWindowManager.h b/xbmc/guilib/GUIWindowManager.h index a7567a1f5d..b8e27227fd 100644 --- a/xbmc/guilib/GUIWindowManager.h +++ b/xbmc/guilib/GUIWindowManager.h @@ -19,7 +19,6 @@ #include "IMsgTargetCallback.h" #include "IWindowManagerCallback.h" #include "messaging/IMessageTarget.h" -#include "utils/GlobalsHandling.h" class CGUIDialog; class CGUIMediaWindow; diff --git a/xbmc/guilib/LocalizeStrings.cpp b/xbmc/guilib/LocalizeStrings.cpp index 273ca9b5a7..b085323406 100644 --- a/xbmc/guilib/LocalizeStrings.cpp +++ b/xbmc/guilib/LocalizeStrings.cpp @@ -15,7 +15,6 @@ #include "utils/POUtils.h" #include "filesystem/Directory.h" #include "threads/SharedSection.h" -#include "threads/SingleLock.h" #include "utils/StringUtils.h" diff --git a/xbmc/guilib/LocalizeStrings.h b/xbmc/guilib/LocalizeStrings.h index 7f828ef6f0..79569349ec 100644 --- a/xbmc/guilib/LocalizeStrings.h +++ b/xbmc/guilib/LocalizeStrings.h @@ -13,7 +13,6 @@ \brief */ -#include "threads/CriticalSection.h" #include "threads/SharedSection.h" #include <map> diff --git a/xbmc/guilib/StereoscopicsManager.cpp b/xbmc/guilib/StereoscopicsManager.cpp index 8a9d171da3..89c9a69e0b 100644 --- a/xbmc/guilib/StereoscopicsManager.cpp +++ b/xbmc/guilib/StereoscopicsManager.cpp @@ -35,7 +35,6 @@ #include "utils/RegExp.h" #include "utils/StringUtils.h" #include "utils/Variant.h" -#include "guilib/guiinfo/GUIInfoLabels.h" #include "cores/DataCacheCore.h" using namespace KODI::MESSAGING; diff --git a/xbmc/guilib/TextureManager.h b/xbmc/guilib/TextureManager.h index 9351c01f63..34de1b1960 100644 --- a/xbmc/guilib/TextureManager.h +++ b/xbmc/guilib/TextureManager.h @@ -16,7 +16,6 @@ #include "threads/CriticalSection.h" #include "GUIComponent.h" -#include "ServiceBroker.h" /************************************************************************/ /* */ diff --git a/xbmc/input/InputManager.cpp b/xbmc/input/InputManager.cpp index 972bea9d55..a4a4325c63 100644 --- a/xbmc/input/InputManager.cpp +++ b/xbmc/input/InputManager.cpp @@ -21,7 +21,6 @@ #include "input/mouse/interfaces/IMouseDriverHandler.h" #include "input/mouse/MouseTranslator.h" #include "input/Key.h" -#include "input/WindowTranslator.h" #include "messaging/ApplicationMessenger.h" #include "guilib/GUIComponent.h" #include "guilib/GUIAudioManager.h" @@ -32,7 +31,6 @@ #include "network/EventServer.h" #include "ButtonTranslator.h" #include "peripherals/Peripherals.h" -#include "peripherals/devices/PeripheralImon.h" #include "XBMC_vkeys.h" #include "utils/Geometry.h" #include "utils/log.h" diff --git a/xbmc/input/InputManager.h b/xbmc/input/InputManager.h index 2d858bed9b..68ff6ea88b 100644 --- a/xbmc/input/InputManager.h +++ b/xbmc/input/InputManager.h @@ -15,7 +15,6 @@ #include "Action.h" #include "windowing/XBMC_events.h" -#include "input/mouse/interfaces/IMouseInputProvider.h" #include "input/mouse/MouseStat.h" #include "input/KeyboardStat.h" #include "interfaces/IActionListener.h" diff --git a/xbmc/input/KeymapEnvironment.cpp b/xbmc/input/KeymapEnvironment.cpp index a10e77b2c7..69a03ec0ea 100644 --- a/xbmc/input/KeymapEnvironment.cpp +++ b/xbmc/input/KeymapEnvironment.cpp @@ -8,8 +8,6 @@ #include "KeymapEnvironment.h" #include "WindowTranslator.h" -#include "guilib/GUIWindowManager.h" -#include "Application.h" int CKeymapEnvironment::GetFallthrough(int windowId) const { diff --git a/xbmc/input/joysticks/JoystickTranslator.cpp b/xbmc/input/joysticks/JoystickTranslator.cpp index c7d23b045c..e6a40ba196 100644 --- a/xbmc/input/joysticks/JoystickTranslator.cpp +++ b/xbmc/input/joysticks/JoystickTranslator.cpp @@ -9,7 +9,6 @@ #include "JoystickTranslator.h" #include "guilib/LocalizeStrings.h" #include "input/joysticks/DriverPrimitive.h" -#include "input/mouse/MouseStat.h" #include "utils/StringUtils.h" using namespace KODI; diff --git a/xbmc/input/joysticks/JoystickTranslator.h b/xbmc/input/joysticks/JoystickTranslator.h index 640a430309..86e9528cb3 100644 --- a/xbmc/input/joysticks/JoystickTranslator.h +++ b/xbmc/input/joysticks/JoystickTranslator.h @@ -9,7 +9,6 @@ #pragma once #include "JoystickTypes.h" -#include "input/mouse/MouseTypes.h" namespace KODI { diff --git a/xbmc/input/joysticks/interfaces/IKeyHandler.h b/xbmc/input/joysticks/interfaces/IKeyHandler.h index 56768e962e..2858c328f7 100644 --- a/xbmc/input/joysticks/interfaces/IKeyHandler.h +++ b/xbmc/input/joysticks/interfaces/IKeyHandler.h @@ -8,8 +8,6 @@ #pragma once -#include "input/joysticks/JoystickTypes.h" - namespace KODI { namespace JOYSTICK diff --git a/xbmc/input/joysticks/keymaps/KeyHandler.cpp b/xbmc/input/joysticks/keymaps/KeyHandler.cpp index 0be51467a6..c3b3448d10 100644 --- a/xbmc/input/joysticks/keymaps/KeyHandler.cpp +++ b/xbmc/input/joysticks/keymaps/KeyHandler.cpp @@ -12,7 +12,6 @@ #include "input/ActionIDs.h" #include "input/ActionTranslator.h" #include "input/IKeymap.h" -#include "input/IKeymapEnvironment.h" #include "interfaces/IActionListener.h" #include <algorithm> diff --git a/xbmc/input/joysticks/keymaps/KeymapHandler.cpp b/xbmc/input/joysticks/keymaps/KeymapHandler.cpp index cea8514f8f..39e18e6189 100644 --- a/xbmc/input/joysticks/keymaps/KeymapHandler.cpp +++ b/xbmc/input/joysticks/keymaps/KeymapHandler.cpp @@ -9,7 +9,6 @@ #include "KeymapHandler.h" #include "KeyHandler.h" #include "games/controllers/Controller.h" -#include "games/GameServices.h" #include "input/joysticks/interfaces/IKeyHandler.h" #include "input/joysticks/JoystickEasterEgg.h" #include "input/joysticks/JoystickTranslator.h" diff --git a/xbmc/input/touch/generic/GenericTouchActionHandler.cpp b/xbmc/input/touch/generic/GenericTouchActionHandler.cpp index 35dde504ea..3821abe23b 100644 --- a/xbmc/input/touch/generic/GenericTouchActionHandler.cpp +++ b/xbmc/input/touch/generic/GenericTouchActionHandler.cpp @@ -12,7 +12,6 @@ #include "AppInboundProtocol.h" #include "ServiceBroker.h" -#include "messaging/ApplicationMessenger.h" #include "guilib/GUIComponent.h" #include "guilib/GUIWindowManager.h" #include "input/Key.h" diff --git a/xbmc/interfaces/builtins/ApplicationBuiltins.cpp b/xbmc/interfaces/builtins/ApplicationBuiltins.cpp index c134d4da40..f8114a07ae 100644 --- a/xbmc/interfaces/builtins/ApplicationBuiltins.cpp +++ b/xbmc/interfaces/builtins/ApplicationBuiltins.cpp @@ -12,7 +12,6 @@ #include "ServiceBroker.h" #include "filesystem/ZipManager.h" #include "messaging/ApplicationMessenger.h" -#include "input/Key.h" #include "interfaces/AnnouncementManager.h" #include "network/Network.h" #include "settings/AdvancedSettings.h" diff --git a/xbmc/interfaces/builtins/GUIBuiltins.cpp b/xbmc/interfaces/builtins/GUIBuiltins.cpp index e14da34de8..089801d482 100644 --- a/xbmc/interfaces/builtins/GUIBuiltins.cpp +++ b/xbmc/interfaces/builtins/GUIBuiltins.cpp @@ -15,7 +15,6 @@ #include "dialogs/GUIDialogNumeric.h" #include "filesystem/Directory.h" #include "input/ActionTranslator.h" -#include "input/Key.h" #include "input/WindowTranslator.h" #include "guilib/GUIComponent.h" #include "guilib/GUIWindowManager.h" @@ -23,7 +22,6 @@ #include "guilib/StereoscopicsManager.h" #include "input/ButtonTranslator.h" #include "settings/AdvancedSettings.h" -#include "settings/DisplaySettings.h" #include "settings/SettingsComponent.h" #include "utils/log.h" #include "utils/StringUtils.h" diff --git a/xbmc/interfaces/builtins/LibraryBuiltins.cpp b/xbmc/interfaces/builtins/LibraryBuiltins.cpp index dcf4f01642..dbda3d9fec 100644 --- a/xbmc/interfaces/builtins/LibraryBuiltins.cpp +++ b/xbmc/interfaces/builtins/LibraryBuiltins.cpp @@ -18,13 +18,11 @@ #include "GUIUserMessages.h" #include "MediaSource.h" #include "messaging/helpers/DialogHelper.h" -#include "music/MusicDatabase.h" #include "music/MusicLibraryQueue.h" #include "settings/LibExportSettings.h" #include "storage/MediaManager.h" #include "utils/log.h" #include "utils/StringUtils.h" -#include "utils/URIUtils.h" #include "video/VideoDatabase.h" using namespace KODI::MESSAGING; diff --git a/xbmc/interfaces/builtins/PlayerBuiltins.cpp b/xbmc/interfaces/builtins/PlayerBuiltins.cpp index 542268be32..567f4edc1a 100644 --- a/xbmc/interfaces/builtins/PlayerBuiltins.cpp +++ b/xbmc/interfaces/builtins/PlayerBuiltins.cpp @@ -18,7 +18,6 @@ #include "PartyModeManager.h" #include "PlayListPlayer.h" #include "SeekHandler.h" -#include "settings/AdvancedSettings.h" #include "settings/MediaSettings.h" #include "settings/Settings.h" #include "settings/SettingsComponent.h" diff --git a/xbmc/interfaces/builtins/SkinBuiltins.cpp b/xbmc/interfaces/builtins/SkinBuiltins.cpp index 8eb183a123..03692c430a 100644 --- a/xbmc/interfaces/builtins/SkinBuiltins.cpp +++ b/xbmc/interfaces/builtins/SkinBuiltins.cpp @@ -9,7 +9,6 @@ #include "SkinBuiltins.h" #include "ServiceBroker.h" -#include "addons/Addon.h" #include "addons/GUIWindowAddonBrowser.h" #include "Application.h" #include "dialogs/GUIDialogFileBrowser.h" @@ -20,7 +19,6 @@ #include "guilib/GUIWindowManager.h" #include "guilib/LocalizeStrings.h" #include "MediaSource.h" -#include "settings/MediaSourceSettings.h" #include "settings/Settings.h" #include "settings/SettingsComponent.h" #include "settings/SkinSettings.h" diff --git a/xbmc/interfaces/json-rpc/ApplicationOperations.cpp b/xbmc/interfaces/json-rpc/ApplicationOperations.cpp index 237778a068..6444b40f0e 100644 --- a/xbmc/interfaces/json-rpc/ApplicationOperations.cpp +++ b/xbmc/interfaces/json-rpc/ApplicationOperations.cpp @@ -9,7 +9,6 @@ #include "ApplicationOperations.h" #include "Application.h" #include "CompileInfo.h" -#include "FileItem.h" #include "GUIInfoManager.h" #include "InputOperations.h" #include "LangInfo.h" diff --git a/xbmc/interfaces/json-rpc/GUIOperations.cpp b/xbmc/interfaces/json-rpc/GUIOperations.cpp index c75ff737a6..953285055b 100644 --- a/xbmc/interfaces/json-rpc/GUIOperations.cpp +++ b/xbmc/interfaces/json-rpc/GUIOperations.cpp @@ -15,7 +15,6 @@ #include "guilib/GUIWindowManager.h" #include "input/Key.h" #include "input/WindowTranslator.h" -#include "interfaces/builtins/Builtins.h" #include "dialogs/GUIDialogKaiToast.h" #include "addons/AddonManager.h" #include "settings/Settings.h" diff --git a/xbmc/interfaces/json-rpc/InputOperations.cpp b/xbmc/interfaces/json-rpc/InputOperations.cpp index a60ee0e0df..c866a12a58 100644 --- a/xbmc/interfaces/json-rpc/InputOperations.cpp +++ b/xbmc/interfaces/json-rpc/InputOperations.cpp @@ -16,9 +16,6 @@ #include "input/ActionTranslator.h" #include "input/Key.h" #include "utils/Variant.h" -#include "input/XBMC_keyboard.h" -#include "input/XBMC_vkeys.h" -#include "threads/SingleLock.h" using namespace JSONRPC; using namespace KODI::MESSAGING; diff --git a/xbmc/interfaces/json-rpc/PVROperations.cpp b/xbmc/interfaces/json-rpc/PVROperations.cpp index 0608d4ec14..964ef456d6 100644 --- a/xbmc/interfaces/json-rpc/PVROperations.cpp +++ b/xbmc/interfaces/json-rpc/PVROperations.cpp @@ -8,7 +8,6 @@ #include "PVROperations.h" -#include "messaging/ApplicationMessenger.h" #include "ServiceBroker.h" #include "pvr/PVRGUIActions.h" diff --git a/xbmc/interfaces/json-rpc/VideoLibrary.cpp b/xbmc/interfaces/json-rpc/VideoLibrary.cpp index 3861e99dc3..073dd0ad19 100644 --- a/xbmc/interfaces/json-rpc/VideoLibrary.cpp +++ b/xbmc/interfaces/json-rpc/VideoLibrary.cpp @@ -644,6 +644,8 @@ JSONRPC_STATUS CVideoLibrary::SetSeasonDetails(const std::string &method, ITrans std::set<std::string> removedArtwork; std::set<std::string> updatedDetails; UpdateVideoTag(parameterObject, infos, artwork, removedArtwork, updatedDetails); + if (ParameterNotNull(parameterObject, "title")) + infos.SetSortTitle(parameterObject["title"].asString()); if (videodatabase.SetDetailsForSeason(infos, artwork, infos.m_iIdShow, id) <= 0) return InternalError; diff --git a/xbmc/interfaces/json-rpc/schema/methods.json b/xbmc/interfaces/json-rpc/schema/methods.json index 686d5a9477..4884a0c909 100644 --- a/xbmc/interfaces/json-rpc/schema/methods.json +++ b/xbmc/interfaces/json-rpc/schema/methods.json @@ -1540,7 +1540,8 @@ "params": [ { "name": "setid", "$ref": "Library.Id", "required": true }, { "name": "title", "$ref": "Optional.String" }, - { "name": "art", "type": [ "null", { "$ref": "Media.Artwork.Set", "required": true } ], "default": null } + { "name": "art", "type": [ "null", { "$ref": "Media.Artwork.Set", "required": true } ], "default": null }, + { "name": "plot", "$ref": "Optional.String" } ], "returns": "string" }, @@ -1586,7 +1587,8 @@ "params": [ { "name": "seasonid", "$ref": "Library.Id", "required": true }, { "name": "art", "type": [ "null", { "$ref": "Media.Artwork.Set", "required": true } ], "default": null }, - { "name": "userrating", "$ref": "Optional.Integer" } + { "name": "userrating", "$ref": "Optional.Integer" }, + { "name": "title", "$ref": "Optional.String" } ], "returns": "string" }, diff --git a/xbmc/interfaces/json-rpc/schema/types.json b/xbmc/interfaces/json-rpc/schema/types.json index 78280af2a1..d8afcfebf7 100644 --- a/xbmc/interfaces/json-rpc/schema/types.json +++ b/xbmc/interfaces/json-rpc/schema/types.json @@ -689,7 +689,7 @@ "extends": "Item.Fields.Base", "items": { "type": "string", "enum": [ "season", "showtitle", "playcount", "episode", "fanart", "thumbnail", "tvshowid", - "watchedepisodes", "art", "userrating" ] + "watchedepisodes", "art", "userrating", "title" ] } }, "Video.Fields.Episode": { @@ -884,7 +884,8 @@ "episode": { "type": "integer" }, "watchedepisodes": { "type": "integer" }, "tvshowid": { "$ref": "Library.Id" }, - "userrating": { "type": "integer" } + "userrating": { "type": "integer" }, + "title": { "type": "string" } } }, "Video.Details.Episode": { diff --git a/xbmc/interfaces/json-rpc/schema/version.txt b/xbmc/interfaces/json-rpc/schema/version.txt index e32fb7aaff..73a62eb02d 100644 --- a/xbmc/interfaces/json-rpc/schema/version.txt +++ b/xbmc/interfaces/json-rpc/schema/version.txt @@ -1 +1 @@ -JSONRPC_VERSION 9.6.1 +JSONRPC_VERSION 9.7.0 diff --git a/xbmc/interfaces/legacy/Dialog.cpp b/xbmc/interfaces/legacy/Dialog.cpp index 397ff0ccf1..7ea6b7dbcb 100644 --- a/xbmc/interfaces/legacy/Dialog.cpp +++ b/xbmc/interfaces/legacy/Dialog.cpp @@ -27,7 +27,6 @@ #include "utils/StringUtils.h" #include "utils/Variant.h" #include "WindowException.h" -#include "messaging/ApplicationMessenger.h" #include "messaging/helpers/DialogOKHelper.h" #include "Dialog.h" #include "ListItem.h" diff --git a/xbmc/interfaces/legacy/Dialog.h b/xbmc/interfaces/legacy/Dialog.h index 8977beb1e1..501577206e 100644 --- a/xbmc/interfaces/legacy/Dialog.h +++ b/xbmc/interfaces/legacy/Dialog.h @@ -17,7 +17,6 @@ #include "ListItem.h" #include "dialogs/GUIDialogProgress.h" #include "dialogs/GUIDialogExtendedProgressBar.h" -#include "dialogs/GUIDialogBusy.h" #define INPUT_ALPHANUM 0 #define INPUT_NUMERIC 1 diff --git a/xbmc/interfaces/legacy/ModuleXbmc.cpp b/xbmc/interfaces/legacy/ModuleXbmc.cpp index 38f651dd0d..8e194e59bf 100644 --- a/xbmc/interfaces/legacy/ModuleXbmc.cpp +++ b/xbmc/interfaces/legacy/ModuleXbmc.cpp @@ -15,7 +15,6 @@ #include "Application.h" #include "ServiceBroker.h" #include "messaging/ApplicationMessenger.h" -#include "utils/URIUtils.h" #include "aojsonrpc.h" #ifndef TARGET_WINDOWS #include "XTimeUtils.h" @@ -30,7 +29,6 @@ #include "FileItem.h" #include "LangInfo.h" #include "PlayListPlayer.h" -#include "settings/AdvancedSettings.h" #include "settings/Settings.h" #include "settings/SettingsComponent.h" #include "guilib/TextureManager.h" diff --git a/xbmc/interfaces/legacy/RenderCapture.h b/xbmc/interfaces/legacy/RenderCapture.h index bfa467634c..886d602f10 100644 --- a/xbmc/interfaces/legacy/RenderCapture.h +++ b/xbmc/interfaces/legacy/RenderCapture.h @@ -9,7 +9,6 @@ #pragma once #include "AddonClass.h" -#include "LanguageHook.h" #include "Exception.h" #include "commons/Buffer.h" #include "Application.h" @@ -109,6 +108,8 @@ namespace XBMCAddon /// Get image format /// /// @return Format of captured image: 'BGRA' + /// + /// ///----------------------------------------------------------------------- /// @python_v17 Image will now always be returned in BGRA /// @@ -132,6 +133,8 @@ namespace XBMCAddon /// @return Captured image as a bytearray /// /// @note The size of the image is m_width * m_height * 4 + /// + /// ///----------------------------------------------------------------------- /// @python_v17 Added the option to specify wait time in msec. /// @@ -156,6 +159,8 @@ namespace XBMCAddon /// /// @param width Width capture image should be rendered to /// @param height Height capture image should should be rendered to + /// + /// ///----------------------------------------------------------------------- /// @python_v17 Removed the option to pass **flags** /// @@ -176,24 +181,6 @@ namespace XBMCAddon g_application.GetAppPlayer().RenderCapture(m_captureId, m_width, m_height, CAPTUREFLAG_CONTINUOUS); } -#ifdef DOXYGEN_SHOULD_USE_THIS - /// - /// \ingroup python_xbmc_RenderCapture - /// @brief \python_func{ getCaptureState() } - ///----------------------------------------------------------------------- - /// @python_v17 Removed function completely. - /// -#endif - -#ifdef DOXYGEN_SHOULD_USE_THIS - /// - /// \ingroup python_xbmc_RenderCapture - /// @brief \python_func{ waitForCaptureStateChangeEvent() } - ///----------------------------------------------------------------------- - /// @python_v17 Removed function completely. - /// -#endif - // hide these from swig #ifndef SWIG inline bool GetPixels(unsigned int msec) diff --git a/xbmc/interfaces/python/XBPython.cpp b/xbmc/interfaces/python/XBPython.cpp index c223e14ba1..81e0d7c55e 100644 --- a/xbmc/interfaces/python/XBPython.cpp +++ b/xbmc/interfaces/python/XBPython.cpp @@ -12,7 +12,6 @@ #include <algorithm> #include "cores/DllLoader/DllLoaderContainer.h" -#include "GUIPassword.h" #include "XBPython.h" #include "filesystem/File.h" #include "filesystem/SpecialProtocol.h" diff --git a/xbmc/listproviders/DirectoryProvider.cpp b/xbmc/listproviders/DirectoryProvider.cpp index b9d259950a..dcbe061fec 100644 --- a/xbmc/listproviders/DirectoryProvider.cpp +++ b/xbmc/listproviders/DirectoryProvider.cpp @@ -19,7 +19,6 @@ #include "guilib/GUIComponent.h" #include "guilib/GUIWindowManager.h" #include "interfaces/AnnouncementManager.h" -#include "messaging/ApplicationMessenger.h" #include "music/dialogs/GUIDialogMusicInfo.h" #include "music/MusicThumbLoader.h" #include "pictures/PictureThumbLoader.h" diff --git a/xbmc/music/MusicDatabase.cpp b/xbmc/music/MusicDatabase.cpp index 3fb1d216b3..907262231d 100644 --- a/xbmc/music/MusicDatabase.cpp +++ b/xbmc/music/MusicDatabase.cpp @@ -21,10 +21,10 @@ #include "dialogs/GUIDialogProgress.h" #include "dialogs/GUIDialogSelect.h" #include "FileItem.h" +#include "filesystem/Directory.h" #include "filesystem/DirectoryCache.h" #include "filesystem/File.h" #include "filesystem/MusicDatabaseDirectory/DirectoryNode.h" -#include "filesystem/MusicDatabaseDirectory/QueryParams.h" #include "guilib/GUIComponent.h" #include "guilib/guiinfo/GUIInfoLabels.h" #include "GUIInfoManager.h" diff --git a/xbmc/music/MusicUtils.cpp b/xbmc/music/MusicUtils.cpp index 54a5fbcd45..38d925a807 100644 --- a/xbmc/music/MusicUtils.cpp +++ b/xbmc/music/MusicUtils.cpp @@ -13,13 +13,11 @@ #include "guilib/GUIComponent.h" #include "guilib/GUIWindowManager.h" #include "guilib/LocalizeStrings.h" -#include "input/Key.h" #include "music/MusicDatabase.h" #include "music/tags/MusicInfoTag.h" #include "PlayListPlayer.h" #include "playlists/PlayList.h" #include "ServiceBroker.h" -#include "Util.h" #include "utils/JobManager.h" using namespace MUSIC_INFO; diff --git a/xbmc/music/dialogs/GUIDialogInfoProviderSettings.cpp b/xbmc/music/dialogs/GUIDialogInfoProviderSettings.cpp index d023ced817..d481b960d2 100644 --- a/xbmc/music/dialogs/GUIDialogInfoProviderSettings.cpp +++ b/xbmc/music/dialogs/GUIDialogInfoProviderSettings.cpp @@ -23,22 +23,18 @@ #include "filesystem/Directory.h" #include "dialogs/GUIDialogFileBrowser.h" #include "dialogs/GUIDialogKaiToast.h" -#include "dialogs/GUIDialogSelect.h" #include "guilib/GUIComponent.h" #include "guilib/GUIWindowManager.h" #include "guilib/LocalizeStrings.h" #include "interfaces/builtins/Builtins.h" #include "ServiceBroker.h" #include "settings/lib/Setting.h" -#include "settings/lib/SettingsManager.h" -#include "settings/SettingUtils.h" #include "settings/Settings.h" #include "settings/SettingsComponent.h" #include "settings/windows/GUIControlSettings.h" #include "storage/MediaManager.h" #include "Util.h" #include "utils/log.h" -#include "utils/StringUtils.h" #include "utils/URIUtils.h" using namespace ADDON; diff --git a/xbmc/music/dialogs/GUIDialogSongInfo.cpp b/xbmc/music/dialogs/GUIDialogSongInfo.cpp index f96c48935e..55aff776db 100644 --- a/xbmc/music/dialogs/GUIDialogSongInfo.cpp +++ b/xbmc/music/dialogs/GUIDialogSongInfo.cpp @@ -9,7 +9,6 @@ #include "GUIDialogSongInfo.h" #include "dialogs/GUIDialogBusy.h" #include "dialogs/GUIDialogFileBrowser.h" -#include "dialogs/GUIDialogSelect.h" #include "filesystem/File.h" #include "guilib/GUIComponent.h" #include "guilib/GUIWindowManager.h" @@ -18,7 +17,6 @@ #include "GUIUserMessages.h" #include "GUIPassword.h" #include "input/Key.h" -#include "music/Album.h" #include "music/MusicDatabase.h" #include "music/MusicUtils.h" #include "music/tags/MusicInfoTag.h" diff --git a/xbmc/music/infoscanner/MusicAlbumInfo.h b/xbmc/music/infoscanner/MusicAlbumInfo.h index 022b6de8af..fc64737aab 100644 --- a/xbmc/music/infoscanner/MusicAlbumInfo.h +++ b/xbmc/music/infoscanner/MusicAlbumInfo.h @@ -8,7 +8,6 @@ #pragma once -#include "music/Song.h" #include "music/Album.h" #include "addons/Scraper.h" #include "utils/ScraperUrl.h" diff --git a/xbmc/music/tags/MusicInfoTagLoaderFFmpeg.cpp b/xbmc/music/tags/MusicInfoTagLoaderFFmpeg.cpp index 27097578bb..70bf653310 100644 --- a/xbmc/music/tags/MusicInfoTagLoaderFFmpeg.cpp +++ b/xbmc/music/tags/MusicInfoTagLoaderFFmpeg.cpp @@ -10,7 +10,6 @@ #include "MusicInfoTag.h" #include "filesystem/File.h" #include "cores/FFmpeg.h" -#include "utils/URIUtils.h" #include "utils/StringUtils.h" using namespace MUSIC_INFO; diff --git a/xbmc/music/tags/TagLoaderTagLib.cpp b/xbmc/music/tags/TagLoaderTagLib.cpp index 4fd92e3f3e..6e7fada382 100644 --- a/xbmc/music/tags/TagLoaderTagLib.cpp +++ b/xbmc/music/tags/TagLoaderTagLib.cpp @@ -55,11 +55,14 @@ #include "utils/URIUtils.h" #include "utils/log.h" #include "utils/StringUtils.h" -#include "utils/Base64.h" #include "ServiceBroker.h" #include "settings/AdvancedSettings.h" #include "settings/SettingsComponent.h" +#if TAGLIB_MAJOR_VERSION <= 1 && TAGLIB_MINOR_VERSION < 11 +#include "utils/Base64.h" +#endif + using namespace TagLib; using namespace MUSIC_INFO; diff --git a/xbmc/music/windows/GUIWindowMusicBase.cpp b/xbmc/music/windows/GUIWindowMusicBase.cpp index ce921244c4..1ae068deae 100644 --- a/xbmc/music/windows/GUIWindowMusicBase.cpp +++ b/xbmc/music/windows/GUIWindowMusicBase.cpp @@ -37,13 +37,11 @@ #include "dialogs/GUIDialogYesNo.h" #include "dialogs/GUIDialogProgress.h" #include "FileItem.h" -#include "filesystem/File.h" #include "messaging/helpers/DialogHelper.h" #include "messaging/helpers/DialogOKHelper.h" #include "profiles/ProfileManager.h" #include "storage/MediaManager.h" #include "settings/AdvancedSettings.h" -#include "settings/MediaSettings.h" #include "settings/MediaSourceSettings.h" #include "settings/Settings.h" #include "settings/SettingsComponent.h" @@ -57,7 +55,6 @@ #include "guilib/guiinfo/GUIInfoLabels.h" #include "cores/IPlayer.h" #include "cores/playercorefactory/PlayerCoreFactory.h" -#include "CueDocument.h" #include "Autorun.h" #include "video/dialogs/GUIDialogVideoInfo.h" diff --git a/xbmc/music/windows/GUIWindowMusicNav.cpp b/xbmc/music/windows/GUIWindowMusicNav.cpp index 65d12290cf..325e67d847 100644 --- a/xbmc/music/windows/GUIWindowMusicNav.cpp +++ b/xbmc/music/windows/GUIWindowMusicNav.cpp @@ -12,7 +12,6 @@ #include "addons/AddonSystemSettings.h" #include "utils/FileUtils.h" #include "utils/URIUtils.h" -#include "PlayListPlayer.h" #include "GUIPassword.h" #include "music/dialogs/GUIDialogInfoProviderSettings.h" #include "filesystem/MusicDatabaseDirectory.h" @@ -47,7 +46,6 @@ #include "Util.h" #include "URL.h" #include "storage/MediaManager.h" -#include "ContextMenuManager.h" using namespace XFILE; using namespace PLAYLIST; diff --git a/xbmc/music/windows/GUIWindowMusicPlaylist.h b/xbmc/music/windows/GUIWindowMusicPlaylist.h index 893d3b6c61..e3fc00ab75 100644 --- a/xbmc/music/windows/GUIWindowMusicPlaylist.h +++ b/xbmc/music/windows/GUIWindowMusicPlaylist.h @@ -9,7 +9,6 @@ #pragma once #include "GUIWindowMusicBase.h" -#include "BackgroundInfoLoader.h" class CGUIWindowMusicPlayList : public CGUIWindowMusicBase { diff --git a/xbmc/music/windows/GUIWindowVisualisation.cpp b/xbmc/music/windows/GUIWindowVisualisation.cpp index 32bfd083d9..b63bc1e71b 100644 --- a/xbmc/music/windows/GUIWindowVisualisation.cpp +++ b/xbmc/music/windows/GUIWindowVisualisation.cpp @@ -8,8 +8,6 @@ #include "GUIWindowVisualisation.h" #include "Application.h" -#include "messaging/ApplicationMessenger.h" -#include "FileItem.h" #include "ServiceBroker.h" #include "music/dialogs/GUIDialogMusicOSD.h" #include "GUIUserMessages.h" diff --git a/xbmc/network/AirPlayServer.cpp b/xbmc/network/AirPlayServer.cpp index 80be8e6383..81b0987732 100644 --- a/xbmc/network/AirPlayServer.cpp +++ b/xbmc/network/AirPlayServer.cpp @@ -16,7 +16,6 @@ #include <arpa/inet.h> #include "DllLibPlist.h" #include "utils/log.h" -#include "utils/URIUtils.h" #include "utils/StringUtils.h" #include "threads/SingleLock.h" #include "filesystem/File.h" diff --git a/xbmc/network/AirTunesServer.h b/xbmc/network/AirTunesServer.h index ad2d6a4d58..5c5b8e7b0b 100644 --- a/xbmc/network/AirTunesServer.h +++ b/xbmc/network/AirTunesServer.h @@ -21,7 +21,6 @@ #include <list> #include "threads/Thread.h" #include "threads/CriticalSection.h" -#include "utils/HttpParser.h" #include "filesystem/PipeFile.h" #include "interfaces/IAnnouncer.h" #include "interfaces/IActionListener.h" diff --git a/xbmc/network/EventClient.cpp b/xbmc/network/EventClient.cpp index 7e5a60ccda..0670682401 100644 --- a/xbmc/network/EventClient.cpp +++ b/xbmc/network/EventClient.cpp @@ -12,7 +12,6 @@ #include "EventPacket.h" #include "threads/SingleLock.h" #include "input/GamepadTranslator.h" -#include "input/InputManager.h" #include "input/IRTranslator.h" #include "input/KeyboardTranslator.h" #include <map> @@ -26,7 +25,6 @@ #include "guilib/LocalizeStrings.h" #include "utils/StringUtils.h" #include "ServiceBroker.h" -#include "utils/log.h" using namespace EVENTCLIENT; using namespace EVENTPACKET; diff --git a/xbmc/network/EventServer.cpp b/xbmc/network/EventServer.cpp index 4b85198387..5a31aeca0f 100644 --- a/xbmc/network/EventServer.cpp +++ b/xbmc/network/EventServer.cpp @@ -10,7 +10,6 @@ #include "EventPacket.h" #include "EventClient.h" #include "Socket.h" -#include "threads/CriticalSection.h" #include "Application.h" #include "ServiceBroker.h" #include "interfaces/builtins/Builtins.h" @@ -21,7 +20,6 @@ #include "input/Key.h" #include "utils/log.h" #include "utils/SystemInfo.h" -#include "Util.h" #include <map> #include <queue> #include <cassert> diff --git a/xbmc/network/Network.cpp b/xbmc/network/Network.cpp index 6406b76939..8b7fe93a56 100644 --- a/xbmc/network/Network.cpp +++ b/xbmc/network/Network.cpp @@ -19,7 +19,6 @@ #include "settings/SettingsComponent.h" #include "utils/log.h" #ifdef TARGET_WINDOWS -#include "utils/SystemInfo.h" #include "platform/win32/WIN32Util.h" #include "utils/CharsetConverter.h" #endif diff --git a/xbmc/network/WebServer.cpp b/xbmc/network/WebServer.cpp index f3e8d4124e..685fe6d972 100644 --- a/xbmc/network/WebServer.cpp +++ b/xbmc/network/WebServer.cpp @@ -25,9 +25,8 @@ #include "settings/SettingsComponent.h" #include "ServiceBroker.h" #include "threads/SingleLock.h" -#include "URL.h" #include "Util.h" -#include "utils/Base64.h" +#include "utils/FileUtils.h" #include "utils/log.h" #include "utils/Mime.h" #include "utils/StringUtils.h" @@ -734,6 +733,10 @@ int CWebServer::CreateFileDownloadResponse(const std::shared_ptr<IHTTPRequestHan std::shared_ptr<XFILE::CFile> file = std::make_shared<XFILE::CFile>(); std::string filePath = handler->GetResponseFile(); + // access check + if (!CFileUtils::CheckFileAccessAllowed(filePath)) + return SendErrorResponse(request, MHD_HTTP_NOT_FOUND, request.method); + if (!file->Open(filePath, XFILE::READ_NO_CACHE)) { CLog::Log(LOGERROR, "CWebServer[%hu]: Failed to open %s", m_port, filePath.c_str()); diff --git a/xbmc/network/httprequesthandler/HTTPImageHandler.cpp b/xbmc/network/httprequesthandler/HTTPImageHandler.cpp index a0417e6037..75e89b1997 100644 --- a/xbmc/network/httprequesthandler/HTTPImageHandler.cpp +++ b/xbmc/network/httprequesthandler/HTTPImageHandler.cpp @@ -10,6 +10,8 @@ #include "URL.h" #include "filesystem/ImageFile.h" #include "network/WebServer.h" +#include "utils/FileUtils.h" + CHTTPImageHandler::CHTTPImageHandler(const HTTPRequest &request) : CHTTPFileHandler(request) @@ -24,7 +26,7 @@ CHTTPImageHandler::CHTTPImageHandler(const HTTPRequest &request) XFILE::CImageFile imageFile; const CURL pathToUrl(file); - if (imageFile.Exists(pathToUrl)) + if (imageFile.Exists(pathToUrl) && CFileUtils::CheckFileAccessAllowed(file)) { responseStatus = MHD_HTTP_OK; struct __stat64 statBuffer; diff --git a/xbmc/network/httprequesthandler/HTTPWebinterfaceHandler.cpp b/xbmc/network/httprequesthandler/HTTPWebinterfaceHandler.cpp index 32edaefabb..6c091783ab 100644 --- a/xbmc/network/httprequesthandler/HTTPWebinterfaceHandler.cpp +++ b/xbmc/network/httprequesthandler/HTTPWebinterfaceHandler.cpp @@ -13,6 +13,7 @@ #include "addons/Webinterface.h" #include "filesystem/Directory.h" #include "filesystem/File.h" +#include "utils/FileUtils.h" #include "utils/StringUtils.h" #include "utils/URIUtils.h" @@ -61,6 +62,9 @@ int CHTTPWebinterfaceHandler::ResolveUrl(const std::string &url, std::string &pa } } + if (!CFileUtils::CheckFileAccessAllowed(path)) + return MHD_HTTP_NOT_FOUND; + if (!XFILE::CFile::Exists(path)) return MHD_HTTP_NOT_FOUND; diff --git a/xbmc/network/httprequesthandler/python/HTTPPythonInvoker.h b/xbmc/network/httprequesthandler/python/HTTPPythonInvoker.h index d11d965272..806c9030e0 100644 --- a/xbmc/network/httprequesthandler/python/HTTPPythonInvoker.h +++ b/xbmc/network/httprequesthandler/python/HTTPPythonInvoker.h @@ -11,7 +11,6 @@ #include <string> #include "interfaces/python/PythonInvoker.h" -#include "network/httprequesthandler/IHTTPRequestHandler.h" #include "network/httprequesthandler/python/HTTPPythonRequest.h" class CHTTPPythonInvoker : public CPythonInvoker diff --git a/xbmc/network/httprequesthandler/python/HTTPPythonWsgiInvoker.h b/xbmc/network/httprequesthandler/python/HTTPPythonWsgiInvoker.h index 324bf467d8..ae0ab922f2 100644 --- a/xbmc/network/httprequesthandler/python/HTTPPythonWsgiInvoker.h +++ b/xbmc/network/httprequesthandler/python/HTTPPythonWsgiInvoker.h @@ -12,7 +12,6 @@ #include <string> #include "interfaces/python/PythonInvoker.h" -#include "network/httprequesthandler/IHTTPRequestHandler.h" #include "network/httprequesthandler/python/HTTPPythonInvoker.h" #include "network/httprequesthandler/python/HTTPPythonRequest.h" diff --git a/xbmc/network/upnp/UPnP.cpp b/xbmc/network/upnp/UPnP.cpp index 53a04f86d9..d6d09bccdd 100644 --- a/xbmc/network/upnp/UPnP.cpp +++ b/xbmc/network/upnp/UPnP.cpp @@ -13,7 +13,6 @@ #include <set> #include <Platinum/Source/Platinum/Platinum.h> -#include "threads/SystemClock.h" #include "UPnP.h" #include "UPnPInternal.h" #include "UPnPRenderer.h" @@ -35,7 +34,6 @@ #include "guilib/GUIWindowManager.h" #include "utils/TimeUtils.h" #include "video/VideoInfoTag.h" -#include "input/Key.h" #include "Util.h" #include "utils/SystemInfo.h" diff --git a/xbmc/network/upnp/UPnPRenderer.cpp b/xbmc/network/upnp/UPnPRenderer.cpp index ce33ec9a9c..1e703547b7 100644 --- a/xbmc/network/upnp/UPnPRenderer.cpp +++ b/xbmc/network/upnp/UPnPRenderer.cpp @@ -30,7 +30,6 @@ #include "utils/URIUtils.h" #include "utils/Variant.h" #include "utils/StringUtils.h" -#include "playlists/PlayList.h" #include "GUIUserMessages.h" #include "guilib/guiinfo/GUIInfoLabels.h" diff --git a/xbmc/network/upnp/UPnPServer.cpp b/xbmc/network/upnp/UPnPServer.cpp index c4365c2935..39712ccded 100644 --- a/xbmc/network/upnp/UPnPServer.cpp +++ b/xbmc/network/upnp/UPnPServer.cpp @@ -24,7 +24,6 @@ #include "guilib/WindowIDs.h" #include "guilib/LocalizeStrings.h" #include "music/tags/MusicInfoTag.h" -#include "settings/AdvancedSettings.h" #include "settings/Settings.h" #include "settings/SettingsComponent.h" #include "utils/Digest.h" diff --git a/xbmc/network/websocket/WebSocket.cpp b/xbmc/network/websocket/WebSocket.cpp index 6aa9bb872a..37765008eb 100644 --- a/xbmc/network/websocket/WebSocket.cpp +++ b/xbmc/network/websocket/WebSocket.cpp @@ -13,9 +13,7 @@ #include "utils/EndianSwap.h" #include "utils/log.h" #include "utils/HttpParser.h" -#include "utils/Base64.h" #include "utils/StringUtils.h" -#include "utils/HttpResponse.h" #define MASK_FIN 0x80 #define MASK_RSV1 0x40 diff --git a/xbmc/network/websocket/WebSocketV13.cpp b/xbmc/network/websocket/WebSocketV13.cpp index 4686c1dc94..39d662c34e 100644 --- a/xbmc/network/websocket/WebSocketV13.cpp +++ b/xbmc/network/websocket/WebSocketV13.cpp @@ -12,7 +12,6 @@ #include "WebSocketV13.h" #include "WebSocket.h" -#include "utils/Base64.h" #include "utils/HttpParser.h" #include "utils/HttpResponse.h" #include "utils/log.h" diff --git a/xbmc/peripherals/Peripherals.cpp b/xbmc/peripherals/Peripherals.cpp index a817bbf05b..00346e1c98 100644 --- a/xbmc/peripherals/Peripherals.cpp +++ b/xbmc/peripherals/Peripherals.cpp @@ -11,7 +11,6 @@ #include <utility> #include "EventScanner.h" -#include "addons/PeripheralAddon.h" #include "addons/AddonButtonMap.h" #include "addons/AddonManager.h" #include "addons/settings/GUIDialogAddonSettings.h" @@ -33,7 +32,6 @@ #include "devices/PeripheralNIC.h" #include "devices/PeripheralNyxboard.h" #include "devices/PeripheralTuner.h" -#include "dialogs/GUIDialogKaiToast.h" #include "FileItem.h" #include "bus/virtual/PeripheralBusApplication.h" #include "input/joysticks/interfaces/IButtonMapper.h" @@ -41,7 +39,6 @@ #include "filesystem/Directory.h" #include "guilib/GUIComponent.h" #include "guilib/GUIWindowManager.h" -#include "guilib/LocalizeStrings.h" #include "guilib/WindowIDs.h" #include "GUIUserMessages.h" #include "input/Key.h" @@ -61,6 +58,9 @@ #if defined(HAVE_LIBCEC) #include "bus/virtual/PeripheralBusCEC.h" +#else +#include "dialogs/GUIDialogKaiToast.h" +#include "guilib/LocalizeStrings.h" #endif using namespace KODI; diff --git a/xbmc/peripherals/addons/AddonInputHandling.cpp b/xbmc/peripherals/addons/AddonInputHandling.cpp index 8faa98d17a..feac3b529d 100644 --- a/xbmc/peripherals/addons/AddonInputHandling.cpp +++ b/xbmc/peripherals/addons/AddonInputHandling.cpp @@ -16,7 +16,6 @@ #include "input/mouse/generic/MouseInputHandling.h" #include "input/mouse/interfaces/IMouseInputHandler.h" #include "peripherals/addons/AddonButtonMap.h" -#include "peripherals/devices/PeripheralJoystick.h" #include "peripherals/Peripherals.h" #include "utils/log.h" diff --git a/xbmc/peripherals/addons/PeripheralAddon.cpp b/xbmc/peripherals/addons/PeripheralAddon.cpp index b753cd9ac2..07750c7059 100644 --- a/xbmc/peripherals/addons/PeripheralAddon.cpp +++ b/xbmc/peripherals/addons/PeripheralAddon.cpp @@ -8,18 +8,13 @@ #include "PeripheralAddon.h" #include "PeripheralAddonTranslator.h" -#include "AddonButtonMap.h" -#include "PeripheralAddonTranslator.h" #include "addons/AddonManager.h" #include "filesystem/Directory.h" #include "filesystem/SpecialProtocol.h" #include "games/controllers/Controller.h" #include "games/controllers/ControllerManager.h" #include "input/joysticks/interfaces/IButtonMap.h" -#include "input/joysticks/interfaces/IDriverHandler.h" #include "input/joysticks/DriverPrimitive.h" -#include "input/joysticks/JoystickTranslator.h" -#include "input/joysticks/JoystickUtils.h" #include "peripherals/Peripherals.h" #include "peripherals/bus/virtual/PeripheralBusAddon.h" #include "peripherals/devices/PeripheralJoystick.h" diff --git a/xbmc/peripherals/bus/virtual/PeripheralBusAddon.cpp b/xbmc/peripherals/bus/virtual/PeripheralBusAddon.cpp index c953fbf5bc..388370a435 100644 --- a/xbmc/peripherals/bus/virtual/PeripheralBusAddon.cpp +++ b/xbmc/peripherals/bus/virtual/PeripheralBusAddon.cpp @@ -7,7 +7,6 @@ */ #include "PeripheralBusAddon.h" -#include "addons/Addon.h" #include "addons/AddonManager.h" #include "addons/binary-addons/BinaryAddonManager.h" #include "messaging/helpers/DialogHelper.h" diff --git a/xbmc/peripherals/bus/virtual/PeripheralBusAddon.h b/xbmc/peripherals/bus/virtual/PeripheralBusAddon.h index 988a2aadb2..a99dacb78a 100644 --- a/xbmc/peripherals/bus/virtual/PeripheralBusAddon.h +++ b/xbmc/peripherals/bus/virtual/PeripheralBusAddon.h @@ -9,13 +9,9 @@ #pragma once #include "addons/AddonManager.h" -#include "addons/IAddon.h" #include "addons/binary-addons/BinaryAddonBase.h" -#include "guilib/IWindowManagerCallback.h" #include "peripherals/PeripheralTypes.h" #include "peripherals/bus/PeripheralBus.h" -#include "threads/CriticalSection.h" -#include "utils/Observer.h" #include <memory> #include <string> diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp index af3ee5a4c7..e65bf729b3 100644 --- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp +++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp @@ -11,7 +11,6 @@ #include "Application.h" #include "ServiceBroker.h" #include "messaging/ApplicationMessenger.h" -#include "DynamicDll.h" #include "threads/SingleLock.h" #include "dialogs/GUIDialogKaiToast.h" #include "guilib/GUIComponent.h" diff --git a/xbmc/pictures/GUIDialogPictureInfo.cpp b/xbmc/pictures/GUIDialogPictureInfo.cpp index 489aabab53..a4191718ac 100644 --- a/xbmc/pictures/GUIDialogPictureInfo.cpp +++ b/xbmc/pictures/GUIDialogPictureInfo.cpp @@ -14,7 +14,6 @@ #include "ServiceBroker.h" #include "input/Key.h" #include "guilib/LocalizeStrings.h" -#include "PictureInfoTag.h" #include "guilib/guiinfo/GUIInfoLabels.h" #define CONTROL_PICTURE_INFO 5 diff --git a/xbmc/pictures/GUIViewStatePictures.cpp b/xbmc/pictures/GUIViewStatePictures.cpp index c891c5cf55..06c9871f3a 100644 --- a/xbmc/pictures/GUIViewStatePictures.cpp +++ b/xbmc/pictures/GUIViewStatePictures.cpp @@ -10,7 +10,6 @@ #include "FileItem.h" #include "ServiceBroker.h" #include "view/ViewState.h" -#include "settings/AdvancedSettings.h" #include "settings/MediaSourceSettings.h" #include "settings/Settings.h" #include "settings/SettingsComponent.h" diff --git a/xbmc/pictures/GUIWindowPictures.cpp b/xbmc/pictures/GUIWindowPictures.cpp index 66cb837d38..8448b509f3 100644 --- a/xbmc/pictures/GUIWindowPictures.cpp +++ b/xbmc/pictures/GUIWindowPictures.cpp @@ -21,7 +21,6 @@ #include "PictureInfoLoader.h" #include "guilib/GUIComponent.h" #include "guilib/GUIWindowManager.h" -#include "input/Key.h" #include "view/GUIViewState.h" #include "messaging/helpers/DialogOKHelper.h" #include "PlayListPlayer.h" diff --git a/xbmc/pictures/GUIWindowSlideShow.cpp b/xbmc/pictures/GUIWindowSlideShow.cpp index c3be39ff73..ef8a4eaf1c 100644 --- a/xbmc/pictures/GUIWindowSlideShow.cpp +++ b/xbmc/pictures/GUIWindowSlideShow.cpp @@ -30,7 +30,6 @@ #include "rendering/RenderSystem.h" #include "guilib/LocalizeStrings.h" #include "TextureDatabase.h" -#include "threads/SingleLock.h" #include "utils/log.h" #include "utils/Random.h" #include "utils/Variant.h" diff --git a/xbmc/pictures/GUIWindowSlideShow.h b/xbmc/pictures/GUIWindowSlideShow.h index a246243a65..ca68784841 100644 --- a/xbmc/pictures/GUIWindowSlideShow.h +++ b/xbmc/pictures/GUIWindowSlideShow.h @@ -12,7 +12,6 @@ #include <set> #include "guilib/GUIDialog.h" #include "threads/Thread.h" -#include "threads/CriticalSection.h" #include "threads/Event.h" #include "SlideShowPicture.h" #include "utils/SortUtils.h" diff --git a/xbmc/pictures/Picture.cpp b/xbmc/pictures/Picture.cpp index cfbf70c014..4ff33113f5 100644 --- a/xbmc/pictures/Picture.cpp +++ b/xbmc/pictures/Picture.cpp @@ -20,7 +20,6 @@ #include "utils/URIUtils.h" #include "guilib/Texture.h" #include "guilib/imagefactory.h" -#include "cores/FFmpeg.h" #if defined(TARGET_RASPBERRY_PI) #include "cores/omxplayer/OMXImage.h" #endif diff --git a/xbmc/platform/android/activity/XBMCApp.cpp b/xbmc/platform/android/activity/XBMCApp.cpp index 5e3432d213..55aaa03e1a 100644 --- a/xbmc/platform/android/activity/XBMCApp.cpp +++ b/xbmc/platform/android/activity/XBMCApp.cpp @@ -128,6 +128,7 @@ std::vector<androidPackage> CXBMCApp::m_applications; CVideoSyncAndroid* CXBMCApp::m_syncImpl = NULL; CEvent CXBMCApp::m_vsyncEvent; std::vector<CActivityResultEvent*> CXBMCApp::m_activityResultEvents; + int64_t CXBMCApp::m_frameTimeNanos = 0; float CXBMCApp::m_refreshRate = 0.0f; @@ -237,6 +238,8 @@ void CXBMCApp::onResume() // Re-request Visible Behind if ((m_playback_state & PLAYBACK_STATE_PLAYING) && (m_playback_state & PLAYBACK_STATE_VIDEO)) RequestVisibleBehind(true); + + g_application.SetRenderGUI(true); } void CXBMCApp::onPause() @@ -256,6 +259,7 @@ void CXBMCApp::onPause() g_application.SwitchToFullScreen(true); EnableWakeLock(false); + g_application.SetRenderGUI(false); m_hasReqVisible = false; } @@ -1183,12 +1187,23 @@ void CXBMCApp::doFrame(int64_t frameTimeNanos) // Calculate the time, when next surface buffer should be rendered m_frameTimeNanos = frameTimeNanos; - if (m_refreshRate) - m_frameTimeNanos += static_cast<int64_t>(1500000000ll / m_refreshRate); m_vsyncEvent.Set(); } +int64_t CXBMCApp::GetNextFrameTime() +{ + if (m_refreshRate > 0.0001f) + return m_frameTimeNanos + static_cast<int64_t>(1500000000ll / m_refreshRate); + else + return m_frameTimeNanos; +} + +float CXBMCApp::GetFrameLatencyMs() +{ + return (CurrentHostCounter() - m_frameTimeNanos) * 0.000001; +} + bool CXBMCApp::WaitVSync(unsigned int milliSeconds) { return m_vsyncEvent.WaitMSec(milliSeconds); diff --git a/xbmc/platform/android/activity/XBMCApp.h b/xbmc/platform/android/activity/XBMCApp.h index 16845357fe..8ccd1d18af 100644 --- a/xbmc/platform/android/activity/XBMCApp.h +++ b/xbmc/platform/android/activity/XBMCApp.h @@ -191,7 +191,8 @@ public: void ProcessSlow(); static bool WaitVSync(unsigned int milliSeconds); - static int64_t GetNextFrameTime(){ return m_frameTimeNanos; }; + static int64_t GetNextFrameTime(); + static float GetFrameLatencyMs(); bool getVideosurfaceInUse(); void setVideosurfaceInUse(bool videosurfaceInUse); diff --git a/xbmc/platform/win10/Win10App.cpp b/xbmc/platform/win10/Win10App.cpp index 0d42351e3c..65f76310ac 100644 --- a/xbmc/platform/win10/Win10App.cpp +++ b/xbmc/platform/win10/Win10App.cpp @@ -53,8 +53,6 @@ void App::Initialize(const CoreApplicationView& applicationView) // At this point we have access to the device. // We can create the device-dependent resources. - CWinEventsWin10::InitOSKeymap(); - // Initialise Winsock WSADATA wd; WSAStartup(MAKEWORD(2, 2), &wd); diff --git a/xbmc/platform/win32/WIN32Util.h b/xbmc/platform/win32/WIN32Util.h index d9d1dbc596..618a31f4ad 100644 --- a/xbmc/platform/win32/WIN32Util.h +++ b/xbmc/platform/win32/WIN32Util.h @@ -11,7 +11,6 @@ #include <vector> #include "URL.h" -#include "MediaSource.h" #include "utils/Geometry.h" #define BONJOUR_EVENT ( WM_USER + 0x100 ) // Message sent to the Window when a Bonjour event occurs. diff --git a/xbmc/platform/win32/filesystem/Win32File.cpp b/xbmc/platform/win32/filesystem/Win32File.cpp index db84a35160..71ce719d9e 100644 --- a/xbmc/platform/win32/filesystem/Win32File.cpp +++ b/xbmc/platform/win32/filesystem/Win32File.cpp @@ -11,7 +11,6 @@ #include "platform/win32/WIN32Util.h" #include "platform/win32/CharsetConverter.h" #include "utils/log.h" -#include "utils/SystemInfo.h" #include "utils/auto_buffer.h" #include <Windows.h> diff --git a/xbmc/platform/win32/filesystem/Win32SMBDirectory.cpp b/xbmc/platform/win32/filesystem/Win32SMBDirectory.cpp index 97189b58b8..3d2e8064db 100644 --- a/xbmc/platform/win32/filesystem/Win32SMBDirectory.cpp +++ b/xbmc/platform/win32/filesystem/Win32SMBDirectory.cpp @@ -10,7 +10,6 @@ #include "FileItem.h" #include "platform/win32/WIN32Util.h" #include "platform/win32/CharsetConverter.h" -#include "utils/SystemInfo.h" #include "utils/CharsetConverter.h" #include "URL.h" #include "utils/log.h" diff --git a/xbmc/platform/win32/network/NetworkWin32.cpp b/xbmc/platform/win32/network/NetworkWin32.cpp index e7a8fa99e1..00c31d927a 100644 --- a/xbmc/platform/win32/network/NetworkWin32.cpp +++ b/xbmc/platform/win32/network/NetworkWin32.cpp @@ -74,7 +74,7 @@ void CNetworkInterfaceWin32::GetMacAddressRaw(char rawMac[6]) const std::string CNetworkInterfaceWin32::GetCurrentIPAddress(void) const { - return CNetworkBase::GetIpStr(m_adapter.FirstUnicastAddress->Address.lpSockaddr); + return m_adapter.FirstUnicastAddress != nullptr ? CNetworkBase::GetIpStr(m_adapter.FirstUnicastAddress->Address.lpSockaddr) : ""; } std::string CNetworkInterfaceWin32::GetCurrentNetmask(void) const diff --git a/xbmc/platform/xbmc.cpp b/xbmc/platform/xbmc.cpp index 591fca53d4..e9f39178ca 100644 --- a/xbmc/platform/xbmc.cpp +++ b/xbmc/platform/xbmc.cpp @@ -47,6 +47,8 @@ extern "C" int XBMC_Run(bool renderGUI, const CAppParamParser ¶ms) if (renderGUI && !g_application.CreateGUI()) { CMessagePrinter::DisplayError("ERROR: Unable to create GUI. Exiting"); + g_application.Stop(EXITCODE_QUIT); + g_application.Cleanup(); return status; } if (!g_application.Initialize()) diff --git a/xbmc/playlists/PlayList.cpp b/xbmc/playlists/PlayList.cpp index 8bdb7a217b..a9ad0d1063 100644 --- a/xbmc/playlists/PlayList.cpp +++ b/xbmc/playlists/PlayList.cpp @@ -8,7 +8,6 @@ #include "PlayList.h" #include "PlayListFactory.h" -#include "video/VideoInfoTag.h" #include "music/tags/MusicInfoTag.h" #include "filesystem/File.h" #include "utils/log.h" diff --git a/xbmc/profiles/dialogs/GUIDialogLockSettings.h b/xbmc/profiles/dialogs/GUIDialogLockSettings.h index 4e5a50460f..39c3a13198 100644 --- a/xbmc/profiles/dialogs/GUIDialogLockSettings.h +++ b/xbmc/profiles/dialogs/GUIDialogLockSettings.h @@ -8,7 +8,6 @@ #pragma once -#include "GUIPassword.h" #include "profiles/Profile.h" #include "settings/dialogs/GUIDialogSettingsManualBase.h" diff --git a/xbmc/profiles/windows/GUIWindowSettingsProfile.cpp b/xbmc/profiles/windows/GUIWindowSettingsProfile.cpp index 5548c1a1af..2d9f8fb51e 100644 --- a/xbmc/profiles/windows/GUIWindowSettingsProfile.cpp +++ b/xbmc/profiles/windows/GUIWindowSettingsProfile.cpp @@ -15,7 +15,6 @@ #include "profiles/dialogs/GUIDialogProfileSettings.h" #include "messaging/ApplicationMessenger.h" #include "utils/URIUtils.h" -#include "GUIPassword.h" #include "guilib/GUIComponent.h" #include "guilib/GUIMessage.h" #include "guilib/GUIWindowManager.h" diff --git a/xbmc/pvr/PVRActionListener.cpp b/xbmc/pvr/PVRActionListener.cpp index ac805d6995..7774a2b897 100644 --- a/xbmc/pvr/PVRActionListener.cpp +++ b/xbmc/pvr/PVRActionListener.cpp @@ -314,7 +314,7 @@ void CPVRActionListener::OnSettingAction(std::shared_ptr<const CSetting> setting } else if (settingId == CSettings::SETTING_PVRCLIENT_MENUHOOK) { - CServiceBroker::GetPVRManager().GUIActions()->ProcessMenuHooks(CFileItemPtr()); + CServiceBroker::GetPVRManager().GUIActions()->ProcessSettingsMenuHooks(); } } diff --git a/xbmc/pvr/PVRContextMenus.cpp b/xbmc/pvr/PVRContextMenus.cpp index cb7ca55ad5..84ae000194 100644 --- a/xbmc/pvr/PVRContextMenus.cpp +++ b/xbmc/pvr/PVRContextMenus.cpp @@ -11,6 +11,7 @@ #include "ContextMenuItem.h" #include "ServiceBroker.h" #include "addons/PVRClient.h" +#include "addons/PVRClientMenuHooks.h" #include "guilib/GUIWindowManager.h" #include "utils/URIUtils.h" @@ -62,7 +63,21 @@ namespace PVR DECL_STATICCONTEXTMENUITEM(UndeleteRecording); DECL_CONTEXTMENUITEM(ToggleTimerState); DECL_STATICCONTEXTMENUITEM(RenameTimer); - DECL_STATICCONTEXTMENUITEM(PVRClientMenuHook); + + class PVRClientMenuHook : public IContextMenuItem + { + public: + PVRClientMenuHook(const CPVRClientMenuHook& hook) : m_hook(hook) {}; + + std::string GetLabel(const CFileItem &item) const override; + bool IsVisible(const CFileItem &item) const override; + bool Execute(const CFileItemPtr &item) const override; + + const CPVRClientMenuHook& GetHook() const { return m_hook; } + + private: + const CPVRClientMenuHook m_hook; + }; CPVRTimerInfoTagPtr GetTimerInfoTagFromItem(const CFileItem &item) { @@ -537,39 +552,36 @@ namespace PVR /////////////////////////////////////////////////////////////////////////////// // PVR Client menu hook - bool PVRClientMenuHook::IsVisible(const CFileItem &item) const + std::string PVRClientMenuHook::GetLabel(const CFileItem &item) const { - const CPVRClientPtr client = CServiceBroker::GetPVRManager().GetClient(item); - if (!client) - return false; - - PVR_MENUHOOK_CAT cat = PVR_MENUHOOK_UNKNOWN; - - if (item.HasPVRChannelInfoTag()) - cat = PVR_MENUHOOK_CHANNEL; - else if (item.HasEPGInfoTag()) - cat = PVR_MENUHOOK_EPG; - else if (item.HasPVRTimerInfoTag() && - !URIUtils::PathEquals(item.GetPath(), CPVRTimersPath::PATH_ADDTIMER)) - cat = PVR_MENUHOOK_TIMER; - else if (item.HasPVRRecordingInfoTag()) - { - const CPVRRecordingPtr recording = item.GetPVRRecordingInfoTag(); - if (recording->IsDeleted()) - cat = PVR_MENUHOOK_DELETED_RECORDING; - else - cat = PVR_MENUHOOK_RECORDING; - } + return m_hook.GetLabel(); + } - if (cat == PVR_MENUHOOK_UNKNOWN) + bool PVRClientMenuHook::IsVisible(const CFileItem &item) const + { + if (m_hook.IsAllHook()) + return !item.m_bIsFolder && !URIUtils::PathEquals(item.GetPath(), CPVRTimersPath::PATH_ADDTIMER); + else if (m_hook.IsEpgHook()) + return item.IsEPG(); + else if (m_hook.IsChannelHook()) + return item.IsPVRChannel(); + else if (m_hook.IsDeletedRecordingHook()) + return item.IsDeletedPVRRecording(); + else if (m_hook.IsRecordingHook()) + return item.IsUsablePVRRecording(); + else if (m_hook.IsTimerHook()) + return item.IsPVRTimer(); + else return false; - - return client->HasMenuHooks(cat); } bool PVRClientMenuHook::Execute(const CFileItemPtr &item) const { - return CServiceBroker::GetPVRManager().GUIActions()->ProcessMenuHooks(item); + const CPVRClientPtr client = CServiceBroker::GetPVRManager().GetClient(*item); + if (!client) + return false; + + return client->CallMenuHook(m_hook, item) == PVR_ERROR_NO_ERROR; } } // namespace CONEXTMENUITEM @@ -602,8 +614,34 @@ namespace PVR std::make_shared<CONTEXTMENUITEM::RenameRecording>(118), /* Rename */ std::make_shared<CONTEXTMENUITEM::DeleteRecording>(), std::make_shared<CONTEXTMENUITEM::UndeleteRecording>(19290), /* Undelete */ - std::make_shared<CONTEXTMENUITEM::PVRClientMenuHook>(19195), /* PVR client specific action */ }; } + void CPVRContextMenuManager::AddMenuHook(const CPVRClientMenuHook& hook) + { + if (hook.IsSettingsHook()) + return; // settings hooks are not handled using context menus + + const auto item = std::make_shared<CONTEXTMENUITEM::PVRClientMenuHook>(hook); + m_items.emplace_back(item); + m_events.Publish(PVRContextMenuEvent(PVRContextMenuEventAction::ADD_ITEM, item)); + } + + void CPVRContextMenuManager::RemoveMenuHook(const CPVRClientMenuHook& hook) + { + if (hook.IsSettingsHook()) + return; // settings hooks are not handled using context menus + + for (auto it = m_items.begin(); it < m_items.end(); ++it) + { + const CONTEXTMENUITEM::PVRClientMenuHook* cmh = dynamic_cast<const CONTEXTMENUITEM::PVRClientMenuHook*>((*it).get()); + if (cmh && cmh->GetHook() == hook) + { + m_events.Publish(PVRContextMenuEvent(PVRContextMenuEventAction::REMOVE_ITEM, *it)); + m_items.erase(it); + return; + } + } + } + } // namespace PVR diff --git a/xbmc/pvr/PVRContextMenus.h b/xbmc/pvr/PVRContextMenus.h index 60014f4090..40af6076a3 100644 --- a/xbmc/pvr/PVRContextMenus.h +++ b/xbmc/pvr/PVRContextMenus.h @@ -11,10 +11,29 @@ #include <memory> #include <vector> +#include "utils/EventStream.h" + class IContextMenuItem; namespace PVR { + enum class PVRContextMenuEventAction + { + ADD_ITEM, + REMOVE_ITEM + }; + + struct PVRContextMenuEvent + { + PVRContextMenuEvent(const PVRContextMenuEventAction& a, const std::shared_ptr<IContextMenuItem>& i) + : action(a), item(i) {} + + PVRContextMenuEventAction action; + std::shared_ptr<IContextMenuItem> item; + }; + + class CPVRClientMenuHook; + class CPVRContextMenuManager { public: @@ -22,6 +41,14 @@ namespace PVR std::vector<std::shared_ptr<IContextMenuItem>> GetMenuItems() const { return m_items; } + void AddMenuHook(const CPVRClientMenuHook& hook); + void RemoveMenuHook(const CPVRClientMenuHook& hook); + + /*! + * @brief Query the events available for CEventStream + */ + CEventStream<PVRContextMenuEvent>& Events() { return m_events; } + private: CPVRContextMenuManager(); CPVRContextMenuManager(const CPVRContextMenuManager&) = delete; @@ -29,6 +56,7 @@ namespace PVR virtual ~CPVRContextMenuManager() = default; std::vector<std::shared_ptr<IContextMenuItem>> m_items; + CEventSource<PVRContextMenuEvent> m_events; }; } // namespace PVR diff --git a/xbmc/pvr/PVRGUIActions.cpp b/xbmc/pvr/PVRGUIActions.cpp index ab2af32fdc..1ab35b086b 100644 --- a/xbmc/pvr/PVRGUIActions.cpp +++ b/xbmc/pvr/PVRGUIActions.cpp @@ -12,6 +12,7 @@ #include "FileItem.h" #include "ServiceBroker.h" #include "addons/PVRClient.h" +#include "addons/PVRClientMenuHooks.h" #include "cores/DataCacheCore.h" #include "dialogs/GUIDialogBusy.h" #include "dialogs/GUIDialogKaiToast.h" @@ -1377,93 +1378,27 @@ namespace PVR return true; } - bool CPVRGUIActions::ProcessMenuHooks(const CFileItemPtr &item) + bool CPVRGUIActions::ProcessSettingsMenuHooks() { - if (!CServiceBroker::GetPVRManager().IsStarted()) - return false; - - int iClientID = -1; - PVR_MENUHOOK_CAT menuCategory = PVR_MENUHOOK_SETTING; + CPVRClientMap clients; + CServiceBroker::GetPVRManager().Clients()->GetCreatedClients(clients); - if (item) + std::vector<std::pair<CPVRClientPtr, CPVRClientMenuHook>> settingsHooks; + for (const auto& client : clients) { - if (item->IsEPG()) - { - if (item->GetEPGInfoTag()->HasChannel()) - { - iClientID = item->GetEPGInfoTag()->Channel()->ClientID(); - menuCategory = PVR_MENUHOOK_EPG; - } - else - return false; - } - else if (item->IsPVRChannel()) - { - iClientID = item->GetPVRChannelInfoTag()->ClientID(); - menuCategory = PVR_MENUHOOK_CHANNEL; - } - else if (item->IsDeletedPVRRecording()) - { - iClientID = item->GetPVRRecordingInfoTag()->m_iClientId; - menuCategory = PVR_MENUHOOK_DELETED_RECORDING; - } - else if (item->IsUsablePVRRecording()) - { - iClientID = item->GetPVRRecordingInfoTag()->m_iClientId; - menuCategory = PVR_MENUHOOK_RECORDING; - } - else if (item->IsPVRTimer()) + for (const auto& hook : client.second->GetMenuHooks()->GetSettingsHooks()) { - iClientID = item->GetPVRTimerInfoTag()->m_iClientId; - menuCategory = PVR_MENUHOOK_TIMER; + settingsHooks.emplace_back(std::make_pair(client.second, hook)); } } - // get client id - if (iClientID < 0 && menuCategory == PVR_MENUHOOK_SETTING) - { - CPVRClientMap clients; - CServiceBroker::GetPVRManager().Clients()->GetCreatedClients(clients); - - if (clients.size() == 1) - { - iClientID = clients.begin()->first; - } - else if (clients.size() > 1) - { - // have user select client - CGUIDialogSelect* pDialog= CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogSelect>(WINDOW_DIALOG_SELECT); - if (!pDialog) - { - CLog::LogF(LOGERROR, "Unable to get WINDOW_DIALOG_SELECT!"); - return false; - } + if (settingsHooks.empty()) + return true; // no settings hooks, no error - pDialog->Reset(); - pDialog->SetHeading(CVariant{19196}); // "PVR client specific actions" + auto selectedHook = settingsHooks.begin(); - for (const auto client : clients) - { - pDialog->Add(client.second->GetBackendName()); - } - - pDialog->Open(); - - int selection = pDialog->GetSelectedItem(); - if (selection >= 0) - { - auto client = clients.begin(); - std::advance(client, selection); - iClientID = client->first; - } - } - } - - if (iClientID < 0) - iClientID = CServiceBroker::GetPVRManager().GetPlayingClientID(); - - CPVRClientPtr client; - if (CServiceBroker::GetPVRManager().Clients()->GetCreatedClient(iClientID, client) && client->HasMenuHooks(menuCategory)) + // if there is only one settings hook, execute it directly, otherwise let the user select + if (settingsHooks.size() > 1) { CGUIDialogSelect* pDialog= CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogSelect>(WINDOW_DIALOG_SELECT); if (!pDialog) @@ -1475,34 +1410,23 @@ namespace PVR pDialog->Reset(); pDialog->SetHeading(CVariant{19196}); // "PVR client specific actions" - PVR_MENUHOOKS& hooks = client->GetMenuHooks(); - std::vector<int> hookIDs; - unsigned int i = 0; - - for (const auto& hook : hooks) + for (const auto& hook : settingsHooks) { - if (hook.category == menuCategory || hook.category == PVR_MENUHOOK_ALL) - { - pDialog->Add(g_localizeStrings.GetAddonString(client->ID(), hook.iLocalizedStringId)); - hookIDs.emplace_back(i); - } - ++i; + if (clients.size() == 1) + pDialog->Add(hook.second.GetLabel()); + else + pDialog->Add(hook.first->GetBackendName() + ": " + hook.second.GetLabel()); } - int selection = 0; - if (!hookIDs.empty()) - { - pDialog->Open(); - selection = pDialog->GetSelectedItem(); - } + pDialog->Open(); - if (selection >= 0) - client->CallMenuHook(hooks.at(hookIDs.at(selection)), item); - else - return false; - } + int selection = pDialog->GetSelectedItem(); + if (selection < 0) + return true; // cancelled - return true; + std::advance(selectedHook, selection); + } + return selectedHook->first->CallMenuHook(selectedHook->second, CFileItemPtr()) == PVR_ERROR_NO_ERROR; } bool CPVRGUIActions::ResetPVRDatabase(bool bResetEPGOnly) diff --git a/xbmc/pvr/PVRGUIActions.h b/xbmc/pvr/PVRGUIActions.h index 33b53f3f30..52e34979a9 100644 --- a/xbmc/pvr/PVRGUIActions.h +++ b/xbmc/pvr/PVRGUIActions.h @@ -306,11 +306,10 @@ namespace PVR bool IsRunningChannelScan() const { return m_bChannelScanRunning; } /*! - * @brief Open selection and progress PVR actions. - * @param item The selected file item for which the hook was called. + * @brief Select and invoke client-specific settings actions * @return true on success, false otherwise. */ - bool ProcessMenuHooks(const CFileItemPtr &item); + bool ProcessSettingsMenuHooks(); /*! * @brief Reset the TV database to it's initial state and delete all the data. diff --git a/xbmc/pvr/addons/PVRClients.h b/xbmc/pvr/addons/PVRClients.h index 8c461c777e..9cc52c9f40 100644 --- a/xbmc/pvr/addons/PVRClients.h +++ b/xbmc/pvr/addons/PVRClients.h @@ -160,6 +160,8 @@ namespace PVR */ int EnabledClientAmount(void) const; + //@} + /*! @name general methods */ //@{ diff --git a/xbmc/pvr/recordings/PVRRecording.cpp b/xbmc/pvr/recordings/PVRRecording.cpp index 615d49f8cf..871da80593 100644 --- a/xbmc/pvr/recordings/PVRRecording.cpp +++ b/xbmc/pvr/recordings/PVRRecording.cpp @@ -153,7 +153,10 @@ bool CPVRRecording::operator ==(const CPVRRecording& right) const m_bIsDeleted == right.m_bIsDeleted && m_iEpgEventId == right.m_iEpgEventId && m_iChannelUid == right.m_iChannelUid && - m_bRadio == right.m_bRadio); + m_bRadio == right.m_bRadio && + m_genre == right.m_genre && + m_iGenreType == right.m_iGenreType && + m_iGenreSubType == right.m_iGenreSubType); } bool CPVRRecording::operator !=(const CPVRRecording& right) const @@ -176,6 +179,7 @@ void CPVRRecording::Serialize(CVariant& value) const value["epgeventid"] = m_iEpgEventId; value["channeluid"] = m_iChannelUid; value["radio"] = m_bRadio; + value["genre"] = m_genre; if (!value.isMember("art")) value["art"] = CVariant(CVariant::VariantTypeObject); @@ -374,6 +378,17 @@ void CPVRRecording::Update(const CPVRRecording &tag) CVideoInfoTag::SetResumePoint(tag.GetLocalResumePoint()); SetDuration(tag.GetDuration()); + if (m_iGenreType == EPG_GENRE_USE_STRING) + { + /* No type/subtype. Use the provided description */ + m_genre = tag.m_genre; + } + else + { + /* Determine genre description by type/subtype */ + m_genre = StringUtils::Split(CPVREpg::ConvertGenreIdToString(tag.m_iGenreType, tag.m_iGenreSubType), CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoItemSeparator); + } + //Old Method of identifying TV show title and subtitle using m_strDirectory and strPlotOutline (deprecated) std::string strShow = StringUtils::Format("%s - ", g_localizeStrings.Get(20364).c_str()); if (StringUtils::StartsWithNoCase(m_strPlotOutline, strShow)) @@ -475,6 +490,9 @@ bool CPVRRecording::IsInProgress() const void CPVRRecording::SetGenre(int iGenreType, int iGenreSubType, const std::string &strGenre) { + m_iGenreType = iGenreType; + m_iGenreSubType = iGenreSubType; + if ((iGenreType == EPG_GENRE_USE_STRING) && !strGenre.empty()) { /* Type and sub type are not given. Use the provided genre description if available. */ @@ -486,3 +504,8 @@ void CPVRRecording::SetGenre(int iGenreType, int iGenreSubType, const std::strin m_genre = StringUtils::Split(CPVREpg::ConvertGenreIdToString(iGenreType, iGenreSubType), CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoItemSeparator); } } + +const std::string CPVRRecording::GetGenresLabel() const +{ + return StringUtils::Join(m_genre, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoItemSeparator); +} diff --git a/xbmc/pvr/recordings/PVRRecording.h b/xbmc/pvr/recordings/PVRRecording.h index eead37e021..90ae6f521d 100644 --- a/xbmc/pvr/recordings/PVRRecording.h +++ b/xbmc/pvr/recordings/PVRRecording.h @@ -287,6 +287,30 @@ namespace PVR */ void SetGenre(int iGenreType, int iGenreSubType, const std::string &strGenre); + /*! + * @brief Get the genre type ID of this event. + * @return The genre type ID. + */ + int GenreType(void) const { return m_iGenreType; } + + /*! + * @brief Get the genre subtype ID of this event. + * @return The genre subtype ID. + */ + int GenreSubType(void) const { return m_iGenreSubType; } + + /*! + * @brief Get the genre as human readable string. + * @return The genre. + */ + const std::vector<std::string> Genre(void) const { return m_genre; } + + /*! + * @brief Get the genre(s) of this event as formatted string. + * @return The genres label. + */ + const std::string GetGenresLabel() const; + private: CDateTime m_recordingTime; /*!< start time of the recording */ bool m_bGotMetaData; @@ -294,6 +318,8 @@ namespace PVR unsigned int m_iEpgEventId; /*!< epg broadcast id associated with this recording */ int m_iChannelUid; /*!< channel uid associated with this recording */ bool m_bRadio; /*!< radio or tv recording */ + int m_iGenreType = 0; /*!< genre type */ + int m_iGenreSubType = 0; /*!< genre subtype */ void UpdatePath(void); }; diff --git a/xbmc/rendering/gl/RenderSystemGL.cpp b/xbmc/rendering/gl/RenderSystemGL.cpp index 21003d8a3b..0d83f858e5 100644 --- a/xbmc/rendering/gl/RenderSystemGL.cpp +++ b/xbmc/rendering/gl/RenderSystemGL.cpp @@ -24,7 +24,6 @@ CRenderSystemGL::CRenderSystemGL() : CRenderSystemBase() { - m_pShader.reset(new CGLShader*[SM_MAX]); } CRenderSystemGL::~CRenderSystemGL() = default; @@ -124,6 +123,9 @@ bool CRenderSystemGL::ResetRenderSystem(int width, int height) glBindVertexArray(m_vertexArray); } + ReleaseShaders(); + InitialiseShaders(); + glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); CalculateMaxTexturesize(); @@ -612,66 +614,59 @@ void CRenderSystemGL::InitialiseShaders() defines += "#define KODI_LIMITED_RANGE 1\n"; } - m_pShader[SM_DEFAULT] = new CGLShader("gl_shader_vert_default.glsl", "gl_shader_frag_default.glsl", defines); + m_pShader[SM_DEFAULT].reset(new CGLShader("gl_shader_vert_default.glsl", "gl_shader_frag_default.glsl", defines)); if (!m_pShader[SM_DEFAULT]->CompileAndLink()) { m_pShader[SM_DEFAULT]->Free(); - delete m_pShader[SM_DEFAULT]; - m_pShader[SM_DEFAULT] = nullptr; + m_pShader[SM_DEFAULT].reset(); CLog::Log(LOGERROR, "GUI Shader gl_shader_frag_default.glsl - compile and link failed"); } - m_pShader[SM_TEXTURE] = new CGLShader("gl_shader_frag_texture.glsl", defines); + m_pShader[SM_TEXTURE].reset(new CGLShader("gl_shader_frag_texture.glsl", defines)); if (!m_pShader[SM_TEXTURE]->CompileAndLink()) { m_pShader[SM_TEXTURE]->Free(); - delete m_pShader[SM_TEXTURE]; - m_pShader[SM_TEXTURE] = nullptr; + m_pShader[SM_TEXTURE].reset(); CLog::Log(LOGERROR, "GUI Shader gl_shader_frag_texture.glsl - compile and link failed"); } - m_pShader[SM_TEXTURE_LIM] = new CGLShader("gl_shader_frag_texture_lim.glsl", defines); + m_pShader[SM_TEXTURE_LIM].reset(new CGLShader("gl_shader_frag_texture_lim.glsl", defines)); if (!m_pShader[SM_TEXTURE_LIM]->CompileAndLink()) { m_pShader[SM_TEXTURE_LIM]->Free(); - delete m_pShader[SM_TEXTURE_LIM]; - m_pShader[SM_TEXTURE_LIM] = nullptr; + m_pShader[SM_TEXTURE_LIM].reset(); CLog::Log(LOGERROR, "GUI Shader gl_shader_frag_texture_lim.glsl - compile and link failed"); } - m_pShader[SM_MULTI] = new CGLShader("gl_shader_frag_multi.glsl", defines); + m_pShader[SM_MULTI].reset(new CGLShader("gl_shader_frag_multi.glsl", defines)); if (!m_pShader[SM_MULTI]->CompileAndLink()) { m_pShader[SM_MULTI]->Free(); - delete m_pShader[SM_MULTI]; - m_pShader[SM_MULTI] = nullptr; + m_pShader[SM_MULTI].reset(); CLog::Log(LOGERROR, "GUI Shader gl_shader_frag_multi.glsl - compile and link failed"); } - m_pShader[SM_FONTS] = new CGLShader("gl_shader_frag_fonts.glsl", defines); + m_pShader[SM_FONTS].reset(new CGLShader("gl_shader_frag_fonts.glsl", defines)); if (!m_pShader[SM_FONTS]->CompileAndLink()) { m_pShader[SM_FONTS]->Free(); - delete m_pShader[SM_FONTS]; - m_pShader[SM_FONTS] = nullptr; + m_pShader[SM_FONTS].reset(); CLog::Log(LOGERROR, "GUI Shader gl_shader_frag_fonts.glsl - compile and link failed"); } - m_pShader[SM_TEXTURE_NOBLEND] = new CGLShader("gl_shader_frag_texture_noblend.glsl", defines); + m_pShader[SM_TEXTURE_NOBLEND].reset(new CGLShader("gl_shader_frag_texture_noblend.glsl", defines)); if (!m_pShader[SM_TEXTURE_NOBLEND]->CompileAndLink()) { m_pShader[SM_TEXTURE_NOBLEND]->Free(); - delete m_pShader[SM_TEXTURE_NOBLEND]; - m_pShader[SM_TEXTURE_NOBLEND] = nullptr; + m_pShader[SM_TEXTURE_NOBLEND].reset(); CLog::Log(LOGERROR, "GUI Shader gl_shader_frag_texture_noblend.glsl - compile and link failed"); } - m_pShader[SM_MULTI_BLENDCOLOR] = new CGLShader("gl_shader_frag_multi_blendcolor.glsl", defines); + m_pShader[SM_MULTI_BLENDCOLOR].reset(new CGLShader("gl_shader_frag_multi_blendcolor.glsl", defines)); if (!m_pShader[SM_MULTI_BLENDCOLOR]->CompileAndLink()) { m_pShader[SM_MULTI_BLENDCOLOR]->Free(); - delete m_pShader[SM_MULTI_BLENDCOLOR]; - m_pShader[SM_MULTI_BLENDCOLOR] = nullptr; + m_pShader[SM_MULTI_BLENDCOLOR].reset(); CLog::Log(LOGERROR, "GUI Shader gl_shader_frag_multi_blendcolor.glsl - compile and link failed"); } } @@ -680,38 +675,31 @@ void CRenderSystemGL::ReleaseShaders() { if (m_pShader[SM_DEFAULT]) m_pShader[SM_DEFAULT]->Free(); - delete m_pShader[SM_DEFAULT]; - m_pShader[SM_DEFAULT] = nullptr; + m_pShader[SM_DEFAULT].reset(); if (m_pShader[SM_TEXTURE]) m_pShader[SM_TEXTURE]->Free(); - delete m_pShader[SM_TEXTURE]; - m_pShader[SM_TEXTURE] = nullptr; + m_pShader[SM_TEXTURE].reset(); if (m_pShader[SM_TEXTURE_LIM]) m_pShader[SM_TEXTURE_LIM]->Free(); - delete m_pShader[SM_TEXTURE_LIM]; - m_pShader[SM_TEXTURE_LIM] = nullptr; + m_pShader[SM_TEXTURE_LIM].reset(); if (m_pShader[SM_MULTI]) m_pShader[SM_MULTI]->Free(); - delete m_pShader[SM_MULTI]; - m_pShader[SM_MULTI] = nullptr; + m_pShader[SM_MULTI].reset(); if (m_pShader[SM_FONTS]) m_pShader[SM_FONTS]->Free(); - delete m_pShader[SM_FONTS]; - m_pShader[SM_FONTS] = nullptr; + m_pShader[SM_FONTS].reset(); if (m_pShader[SM_TEXTURE_NOBLEND]) m_pShader[SM_TEXTURE_NOBLEND]->Free(); - delete m_pShader[SM_TEXTURE_NOBLEND]; - m_pShader[SM_TEXTURE_NOBLEND] = nullptr; + m_pShader[SM_TEXTURE_NOBLEND].reset(); if (m_pShader[SM_MULTI_BLENDCOLOR]) m_pShader[SM_MULTI_BLENDCOLOR]->Free(); - delete m_pShader[SM_MULTI_BLENDCOLOR]; - m_pShader[SM_MULTI_BLENDCOLOR] = nullptr; + m_pShader[SM_MULTI_BLENDCOLOR].reset(); } void CRenderSystemGL::EnableShader(ESHADERMETHOD method) diff --git a/xbmc/rendering/gl/RenderSystemGL.h b/xbmc/rendering/gl/RenderSystemGL.h index 6af400c8d8..b53355a8d5 100644 --- a/xbmc/rendering/gl/RenderSystemGL.h +++ b/xbmc/rendering/gl/RenderSystemGL.h @@ -13,6 +13,9 @@ #include "rendering/RenderSystem.h" #include "utils/Color.h" +#include <array> +#include <memory> + enum ESHADERMETHOD { SM_DEFAULT = 0, @@ -98,7 +101,7 @@ protected: GLint m_viewPort[4]; - std::unique_ptr<CGLShader*[]> m_pShader; + std::array<std::unique_ptr<CGLShader>, SM_MAX> m_pShader; ESHADERMETHOD m_method = SM_DEFAULT; GLuint m_vertexArray = GL_NONE; }; diff --git a/xbmc/rendering/gles/RenderSystemGLES.cpp b/xbmc/rendering/gles/RenderSystemGLES.cpp index d77c616b4b..54669aa7ca 100644 --- a/xbmc/rendering/gles/RenderSystemGLES.cpp +++ b/xbmc/rendering/gles/RenderSystemGLES.cpp @@ -23,7 +23,6 @@ CRenderSystemGLES::CRenderSystemGLES() : CRenderSystemBase() { - m_pShader.reset(new CGLESShader*[SM_MAX]); } CRenderSystemGLES::~CRenderSystemGLES() @@ -375,171 +374,144 @@ void CRenderSystemGLES::InitialiseShaders() defines += "#define KODI_LIMITED_RANGE 1\n"; } - m_pShader[SM_DEFAULT] = new CGLESShader("gles_shader.vert", "gles_shader_default.frag", defines); + m_pShader[SM_DEFAULT].reset(new CGLESShader("gles_shader.vert", "gles_shader_default.frag", defines)); if (!m_pShader[SM_DEFAULT]->CompileAndLink()) { m_pShader[SM_DEFAULT]->Free(); - delete m_pShader[SM_DEFAULT]; - m_pShader[SM_DEFAULT] = nullptr; + m_pShader[SM_DEFAULT].reset(); CLog::Log(LOGERROR, "GUI Shader gles_shader_default.frag - compile and link failed"); } - m_pShader[SM_TEXTURE] = new CGLESShader("gles_shader_texture.frag", defines); + m_pShader[SM_TEXTURE].reset(new CGLESShader("gles_shader_texture.frag", defines)); if (!m_pShader[SM_TEXTURE]->CompileAndLink()) { m_pShader[SM_TEXTURE]->Free(); - delete m_pShader[SM_TEXTURE]; - m_pShader[SM_TEXTURE] = nullptr; + m_pShader[SM_TEXTURE].reset(); CLog::Log(LOGERROR, "GUI Shader gles_shader_texture.frag - compile and link failed"); } - m_pShader[SM_MULTI] = new CGLESShader("gles_shader_multi.frag", defines); + m_pShader[SM_MULTI].reset(new CGLESShader("gles_shader_multi.frag", defines)); if (!m_pShader[SM_MULTI]->CompileAndLink()) { m_pShader[SM_MULTI]->Free(); - delete m_pShader[SM_MULTI]; - m_pShader[SM_MULTI] = nullptr; + m_pShader[SM_MULTI].reset(); CLog::Log(LOGERROR, "GUI Shader gles_shader_multi.frag - compile and link failed"); } - m_pShader[SM_FONTS] = new CGLESShader("gles_shader_fonts.frag", defines); + m_pShader[SM_FONTS].reset(new CGLESShader("gles_shader_fonts.frag", defines)); if (!m_pShader[SM_FONTS]->CompileAndLink()) { m_pShader[SM_FONTS]->Free(); - delete m_pShader[SM_FONTS]; - m_pShader[SM_FONTS] = nullptr; + m_pShader[SM_FONTS].reset(); CLog::Log(LOGERROR, "GUI Shader gles_shader_fonts.frag - compile and link failed"); } - m_pShader[SM_TEXTURE_NOBLEND] = new CGLESShader("gles_shader_texture_noblend.frag", defines); + m_pShader[SM_TEXTURE_NOBLEND].reset(new CGLESShader("gles_shader_texture_noblend.frag", defines)); if (!m_pShader[SM_TEXTURE_NOBLEND]->CompileAndLink()) { m_pShader[SM_TEXTURE_NOBLEND]->Free(); - delete m_pShader[SM_TEXTURE_NOBLEND]; - m_pShader[SM_TEXTURE_NOBLEND] = nullptr; + m_pShader[SM_TEXTURE_NOBLEND].reset(); CLog::Log(LOGERROR, "GUI Shader gles_shader_texture_noblend.frag - compile and link failed"); } - m_pShader[SM_MULTI_BLENDCOLOR] = new CGLESShader("gles_shader_multi_blendcolor.frag", defines); + m_pShader[SM_MULTI_BLENDCOLOR].reset(new CGLESShader("gles_shader_multi_blendcolor.frag", defines)); if (!m_pShader[SM_MULTI_BLENDCOLOR]->CompileAndLink()) { m_pShader[SM_MULTI_BLENDCOLOR]->Free(); - delete m_pShader[SM_MULTI_BLENDCOLOR]; - m_pShader[SM_MULTI_BLENDCOLOR] = nullptr; + m_pShader[SM_MULTI_BLENDCOLOR].reset(); CLog::Log(LOGERROR, "GUI Shader gles_shader_multi_blendcolor.frag - compile and link failed"); } - m_pShader[SM_TEXTURE_RGBA] = new CGLESShader("gles_shader_rgba.frag", defines); + m_pShader[SM_TEXTURE_RGBA].reset(new CGLESShader("gles_shader_rgba.frag", defines)); if (!m_pShader[SM_TEXTURE_RGBA]->CompileAndLink()) { m_pShader[SM_TEXTURE_RGBA]->Free(); - delete m_pShader[SM_TEXTURE_RGBA]; - m_pShader[SM_TEXTURE_RGBA] = nullptr; + m_pShader[SM_TEXTURE_RGBA].reset(); CLog::Log(LOGERROR, "GUI Shader gles_shader_rgba.frag - compile and link failed"); } - m_pShader[SM_TEXTURE_RGBA_BLENDCOLOR] = new CGLESShader("gles_shader_rgba_blendcolor.frag", defines); + m_pShader[SM_TEXTURE_RGBA_BLENDCOLOR].reset(new CGLESShader("gles_shader_rgba_blendcolor.frag", defines)); if (!m_pShader[SM_TEXTURE_RGBA_BLENDCOLOR]->CompileAndLink()) { m_pShader[SM_TEXTURE_RGBA_BLENDCOLOR]->Free(); - delete m_pShader[SM_TEXTURE_RGBA_BLENDCOLOR]; - m_pShader[SM_TEXTURE_RGBA_BLENDCOLOR] = nullptr; + m_pShader[SM_TEXTURE_RGBA_BLENDCOLOR].reset(); CLog::Log(LOGERROR, "GUI Shader gles_shader_rgba_blendcolor.frag - compile and link failed"); } - m_pShader[SM_TEXTURE_RGBA_BOB] = new CGLESShader("gles_shader_rgba_bob.frag", defines); + m_pShader[SM_TEXTURE_RGBA_BOB].reset(new CGLESShader("gles_shader_rgba_bob.frag", defines)); if (!m_pShader[SM_TEXTURE_RGBA_BOB]->CompileAndLink()) { m_pShader[SM_TEXTURE_RGBA_BOB]->Free(); - delete m_pShader[SM_TEXTURE_RGBA_BOB]; - m_pShader[SM_TEXTURE_RGBA_BOB] = nullptr; + m_pShader[SM_TEXTURE_RGBA_BOB].reset(); CLog::Log(LOGERROR, "GUI Shader gles_shader_rgba_bob.frag - compile and link failed"); } if (IsExtSupported("GL_OES_EGL_image_external")) { - m_pShader[SM_TEXTURE_RGBA_OES] = new CGLESShader("gles_shader_rgba_oes.frag", defines); + m_pShader[SM_TEXTURE_RGBA_OES].reset(new CGLESShader("gles_shader_rgba_oes.frag", defines)); if (!m_pShader[SM_TEXTURE_RGBA_OES]->CompileAndLink()) { m_pShader[SM_TEXTURE_RGBA_OES]->Free(); - delete m_pShader[SM_TEXTURE_RGBA_OES]; - m_pShader[SM_TEXTURE_RGBA_OES] = nullptr; + m_pShader[SM_TEXTURE_RGBA_OES].reset(); CLog::Log(LOGERROR, "GUI Shader gles_shader_rgba_oes.frag - compile and link failed"); } - m_pShader[SM_TEXTURE_RGBA_BOB_OES] = new CGLESShader("gles_shader_rgba_bob_oes.frag", defines); + m_pShader[SM_TEXTURE_RGBA_BOB_OES].reset(new CGLESShader("gles_shader_rgba_bob_oes.frag", defines)); if (!m_pShader[SM_TEXTURE_RGBA_BOB_OES]->CompileAndLink()) { m_pShader[SM_TEXTURE_RGBA_BOB_OES]->Free(); - delete m_pShader[SM_TEXTURE_RGBA_BOB_OES]; - m_pShader[SM_TEXTURE_RGBA_BOB_OES] = nullptr; + m_pShader[SM_TEXTURE_RGBA_BOB_OES].reset(); CLog::Log(LOGERROR, "GUI Shader gles_shader_rgba_bob_oes.frag - compile and link failed"); } } - else - { - m_pShader[SM_TEXTURE_RGBA_OES] = nullptr; - m_pShader[SM_TEXTURE_RGBA_BOB_OES] = nullptr; - } } void CRenderSystemGLES::ReleaseShaders() { if (m_pShader[SM_DEFAULT]) m_pShader[SM_DEFAULT]->Free(); - delete m_pShader[SM_DEFAULT]; - m_pShader[SM_DEFAULT] = nullptr; + m_pShader[SM_DEFAULT].reset(); if (m_pShader[SM_TEXTURE]) m_pShader[SM_TEXTURE]->Free(); - delete m_pShader[SM_TEXTURE]; - m_pShader[SM_TEXTURE] = nullptr; + m_pShader[SM_TEXTURE].reset(); if (m_pShader[SM_MULTI]) m_pShader[SM_MULTI]->Free(); - delete m_pShader[SM_MULTI]; - m_pShader[SM_MULTI] = nullptr; + m_pShader[SM_MULTI].reset(); if (m_pShader[SM_FONTS]) m_pShader[SM_FONTS]->Free(); - delete m_pShader[SM_FONTS]; - m_pShader[SM_FONTS] = nullptr; + m_pShader[SM_FONTS].reset(); if (m_pShader[SM_TEXTURE_NOBLEND]) m_pShader[SM_TEXTURE_NOBLEND]->Free(); - delete m_pShader[SM_TEXTURE_NOBLEND]; - m_pShader[SM_TEXTURE_NOBLEND] = nullptr; + m_pShader[SM_TEXTURE_NOBLEND].reset(); if (m_pShader[SM_MULTI_BLENDCOLOR]) m_pShader[SM_MULTI_BLENDCOLOR]->Free(); - delete m_pShader[SM_MULTI_BLENDCOLOR]; - m_pShader[SM_MULTI_BLENDCOLOR] = nullptr; + m_pShader[SM_MULTI_BLENDCOLOR].reset(); if (m_pShader[SM_TEXTURE_RGBA]) m_pShader[SM_TEXTURE_RGBA]->Free(); - delete m_pShader[SM_TEXTURE_RGBA]; - m_pShader[SM_TEXTURE_RGBA] = nullptr; + m_pShader[SM_TEXTURE_RGBA].reset(); if (m_pShader[SM_TEXTURE_RGBA_BLENDCOLOR]) m_pShader[SM_TEXTURE_RGBA_BLENDCOLOR]->Free(); - delete m_pShader[SM_TEXTURE_RGBA_BLENDCOLOR]; - m_pShader[SM_TEXTURE_RGBA_BLENDCOLOR] = nullptr; + m_pShader[SM_TEXTURE_RGBA_BLENDCOLOR].reset(); if (m_pShader[SM_TEXTURE_RGBA_BOB]) m_pShader[SM_TEXTURE_RGBA_BOB]->Free(); - delete m_pShader[SM_TEXTURE_RGBA_BOB]; - m_pShader[SM_TEXTURE_RGBA_BOB] = nullptr; + m_pShader[SM_TEXTURE_RGBA_BOB].reset(); if (m_pShader[SM_TEXTURE_RGBA_OES]) m_pShader[SM_TEXTURE_RGBA_OES]->Free(); - delete m_pShader[SM_TEXTURE_RGBA_OES]; - m_pShader[SM_TEXTURE_RGBA_OES] = nullptr; + m_pShader[SM_TEXTURE_RGBA_OES].reset(); if (m_pShader[SM_TEXTURE_RGBA_BOB_OES]) m_pShader[SM_TEXTURE_RGBA_BOB_OES]->Free(); - delete m_pShader[SM_TEXTURE_RGBA_BOB_OES]; - m_pShader[SM_TEXTURE_RGBA_BOB_OES] = nullptr; + m_pShader[SM_TEXTURE_RGBA_BOB_OES].reset(); } void CRenderSystemGLES::EnableGUIShader(ESHADERMETHOD method) diff --git a/xbmc/rendering/gles/RenderSystemGLES.h b/xbmc/rendering/gles/RenderSystemGLES.h index 1326328982..c7ddbc606d 100644 --- a/xbmc/rendering/gles/RenderSystemGLES.h +++ b/xbmc/rendering/gles/RenderSystemGLES.h @@ -13,6 +13,8 @@ #include "utils/Color.h" #include "GLESShader.h" +#include <array> + enum ESHADERMETHOD { SM_DEFAULT, @@ -97,7 +99,7 @@ protected: std::string m_RenderExtensions; - std::unique_ptr<CGLESShader*[]> m_pShader; + std::array<std::unique_ptr<CGLESShader>, SM_MAX> m_pShader; ESHADERMETHOD m_method = SM_DEFAULT; GLint m_viewPort[4]; diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp index e6bfc51cee..4e66fc55e9 100644 --- a/xbmc/settings/AdvancedSettings.cpp +++ b/xbmc/settings/AdvancedSettings.cpp @@ -317,6 +317,12 @@ void CAdvancedSettings::Initialize() m_bVideoScannerIgnoreErrors = false; m_iVideoLibraryDateAdded = 1; // prefer mtime over ctime and current time + m_videoEpisodeExtraArt = {}; + m_videoTvShowExtraArt = {}; + m_videoTvSeasonExtraArt = {}; + m_videoMovieExtraArt = {}; + m_videoMusicVideoExtraArt = {}; + m_iEpgUpdateCheckInterval = 300; /* check if tables need to be updated every 5 minutes */ m_iEpgCleanupInterval = 900; /* remove old entries from the EPG every 15 minutes */ m_iEpgActiveTagCheckInterval = 60; /* check for updated active tags every minute */ @@ -772,32 +778,9 @@ void CAdvancedSettings::ParseSettingsFile(const std::string &file) separator = separator->NextSibling("separator"); } } - // Music extra artist art - TiXmlElement* arttypes = pElement->FirstChildElement("artistextraart"); - if (arttypes) - { - m_musicArtistExtraArt.clear(); - TiXmlNode* arttype = arttypes->FirstChild("arttype"); - while (arttype) - { - if (arttype->FirstChild()) - m_musicArtistExtraArt.push_back(arttype->FirstChild()->ValueStr()); - arttype = arttype->NextSibling("arttype"); - } - } - // Music extra album art - arttypes = pElement->FirstChildElement("albumextraart"); - if (arttypes) - { - m_musicAlbumExtraArt.clear(); - TiXmlNode* arttype = arttypes->FirstChild("arttype"); - while (arttype) - { - if (arttype->FirstChild()) - m_musicAlbumExtraArt.push_back(arttype->FirstChild()->ValueStr()); - arttype = arttype->NextSibling("arttype"); - } - } + + SetExtraArtwork(pElement->FirstChildElement("artistextraart"), m_musicArtistExtraArt); + SetExtraArtwork(pElement->FirstChildElement("albumextraart"), m_musicAlbumExtraArt); } pElement = pRootElement->FirstChildElement("videolibrary"); @@ -812,6 +795,12 @@ void CAdvancedSettings::ParseSettingsFile(const std::string &file) XMLUtils::GetBoolean(pElement, "importwatchedstate", m_bVideoLibraryImportWatchedState); XMLUtils::GetBoolean(pElement, "importresumepoint", m_bVideoLibraryImportResumePoint); XMLUtils::GetInt(pElement, "dateadded", m_iVideoLibraryDateAdded); + + SetExtraArtwork(pElement->FirstChildElement("episodeextraart"), m_videoEpisodeExtraArt); + SetExtraArtwork(pElement->FirstChildElement("tvshowextraart"), m_videoTvShowExtraArt); + SetExtraArtwork(pElement->FirstChildElement("tvseasonextraart"), m_videoTvSeasonExtraArt); + SetExtraArtwork(pElement->FirstChildElement("movieextraart"), m_videoMovieExtraArt); + SetExtraArtwork(pElement->FirstChildElement("musicvideoextraart"), m_videoMusicVideoExtraArt); } pElement = pRootElement->FirstChildElement("videoscanner"); @@ -1462,3 +1451,17 @@ void CAdvancedSettings::SetExtraLogLevel(const std::vector<CVariant> &components m_extraLogLevels |= static_cast<int>(it->asInteger()); } } + +void CAdvancedSettings::SetExtraArtwork(const TiXmlElement* arttypes, std::vector<std::string>& artworkMap) +{ + if (!arttypes) + return + artworkMap.clear(); + const TiXmlNode* arttype = arttypes->FirstChild("arttype"); + while (arttype) + { + if (arttype->FirstChild()) + artworkMap.push_back(arttype->FirstChild()->ValueStr()); + arttype = arttype->NextSibling("arttype"); + } +} diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h index 1850bbd72d..d74575a8c9 100644 --- a/xbmc/settings/AdvancedSettings.h +++ b/xbmc/settings/AdvancedSettings.h @@ -265,6 +265,11 @@ class CAdvancedSettings : public ISettingCallback, public ISettingsHandler bool m_bVideoLibraryExportAutoThumbs; bool m_bVideoLibraryImportWatchedState; bool m_bVideoLibraryImportResumePoint; + std::vector<std::string> m_videoEpisodeExtraArt; + std::vector<std::string> m_videoTvShowExtraArt; + std::vector<std::string> m_videoTvSeasonExtraArt; + std::vector<std::string> m_videoMovieExtraArt; + std::vector<std::string> m_videoMusicVideoExtraArt; bool m_bVideoScannerIgnoreErrors; int m_iVideoLibraryDateAdded; @@ -381,4 +386,5 @@ class CAdvancedSettings : public ISettingCallback, public ISettingsHandler void SetExtraLogLevel(const std::vector<CVariant> &components); void Initialize(); void Clear(); + void SetExtraArtwork(const TiXmlElement* arttypes, std::vector<std::string>& artworkMap); }; diff --git a/xbmc/settings/DisplaySettings.cpp b/xbmc/settings/DisplaySettings.cpp index 9fc3c9b86c..b24940cf3b 100644 --- a/xbmc/settings/DisplaySettings.cpp +++ b/xbmc/settings/DisplaySettings.cpp @@ -22,7 +22,6 @@ #include "guilib/GUIComponent.h" #include "guilib/LocalizeStrings.h" #include "guilib/StereoscopicsManager.h" -#include "messaging/ApplicationMessenger.h" #include "messaging/helpers/DialogHelper.h" #include "settings/AdvancedSettings.h" #include "settings/lib/Setting.h" diff --git a/xbmc/settings/MediaSettings.cpp b/xbmc/settings/MediaSettings.cpp index 33e8294a81..015b3ab3a0 100644 --- a/xbmc/settings/MediaSettings.cpp +++ b/xbmc/settings/MediaSettings.cpp @@ -13,7 +13,6 @@ #include "MediaSettings.h" #include "Application.h" #include "PlayListPlayer.h" -#include "dialogs/GUIDialogContextMenu.h" #include "dialogs/GUIDialogFileBrowser.h" #include "settings/dialogs/GUIDialogLibExportSettings.h" #include "guilib/LocalizeStrings.h" diff --git a/xbmc/settings/SettingConditions.cpp b/xbmc/settings/SettingConditions.cpp index 6c36812ea0..6d9890f7c0 100644 --- a/xbmc/settings/SettingConditions.cpp +++ b/xbmc/settings/SettingConditions.cpp @@ -12,7 +12,6 @@ #include "Util.h" #include "addons/AddonManager.h" #include "addons/binary-addons/BinaryAddonManager.h" -#include "addons/BinaryAddonCache.h" #include "addons/Skin.h" #if defined(TARGET_ANDROID) #include "platform/android/activity/AndroidFeatures.h" diff --git a/xbmc/settings/dialogs/GUIDialogContentSettings.cpp b/xbmc/settings/dialogs/GUIDialogContentSettings.cpp index 4b7ca0862d..49a6b30095 100644 --- a/xbmc/settings/dialogs/GUIDialogContentSettings.cpp +++ b/xbmc/settings/dialogs/GUIDialogContentSettings.cpp @@ -29,7 +29,6 @@ #include "settings/lib/SettingsManager.h" #include "settings/windows/GUIControlSettings.h" #include "utils/log.h" -#include "utils/StringUtils.h" #include "video/VideoInfoScanner.h" #define SETTING_CONTENT_TYPE "contenttype" diff --git a/xbmc/test/TestFileItem.cpp b/xbmc/test/TestFileItem.cpp index a876267fe6..7d9e9608f7 100644 --- a/xbmc/test/TestFileItem.cpp +++ b/xbmc/test/TestFileItem.cpp @@ -69,8 +69,8 @@ const TestFileData MovieFiles[] = {{ "c:\\dir\\filename.avi", false, "c:\\dir\\f { "stack:///path/to/movie_name/cd1/some_file1.avi , /path/to/movie_name/cd2/some_file2.avi", true, "/path/to/movie_name/art.jpg" }, { "/home/user/TV Shows/Dexter/S1/1x01.avi", false, "/home/user/TV Shows/Dexter/S1/1x01-art.jpg" }, { "/home/user/TV Shows/Dexter/S1/1x01.avi", true, "/home/user/TV Shows/Dexter/S1/art.jpg" }, - { "rar://g%3a%5cmultimedia%5cmovies%5cSphere%2erar/Sphere.avi", false, "g:\\multimedia\\movies\\Sphere-art.jpg" }, - { "rar://g%3a%5cmultimedia%5cmovies%5cSphere%2erar/Sphere.avi", true, "g:\\multimedia\\movies\\art.jpg" }, + { "zip://g%3a%5cmultimedia%5cmovies%5cSphere%2ezip/Sphere.avi", false, "g:\\multimedia\\movies\\Sphere-art.jpg" }, + { "zip://g%3a%5cmultimedia%5cmovies%5cSphere%2ezip/Sphere.avi", true, "g:\\multimedia\\movies\\art.jpg" }, { "/home/user/movies/movie_name/video_ts/VIDEO_TS.IFO", false, "/home/user/movies/movie_name/art.jpg" }, { "/home/user/movies/movie_name/video_ts/VIDEO_TS.IFO", true, "/home/user/movies/movie_name/art.jpg" }, { "/home/user/movies/movie_name/BDMV/index.bdmv", false, "/home/user/movies/movie_name/art.jpg" }, @@ -96,7 +96,7 @@ const TestFileData NoArtFiles[] = {{ "c:\\dir\\filename.avi", false, "c:\\dir\\f { "/dir/filename.avi", false, "/dir/filename.tbn" }, { "smb://somepath/file.avi", false, "smb://somepath/file.tbn" }, { "/home/user/TV Shows/Dexter/S1/1x01.avi", false, "/home/user/TV Shows/Dexter/S1/1x01.tbn" }, - { "rar://g%3a%5cmultimedia%5cmovies%5cSphere%2erar/Sphere.avi", false, "g:\\multimedia\\movies\\Sphere.tbn" }}; + { "zip://g%3a%5cmultimedia%5cmovies%5cSphere%2ezip/Sphere.avi", false, "g:\\multimedia\\movies\\Sphere.tbn" }}; INSTANTIATE_TEST_CASE_P(NoArt, TestFileItemFallbackArt, ValuesIn(NoArtFiles)); @@ -124,7 +124,7 @@ const TestFileData BaseMovies[] = {{ "c:\\dir\\filename.avi", false, "c:\\dir\\f { "stack:///path/to/movie_name/cd1/some_file1.avi , /path/to/movie_name/cd2/some_file2.avi", true, "/path/to/movie_name/" }, { "/home/user/TV Shows/Dexter/S1/1x01.avi", false, "/home/user/TV Shows/Dexter/S1/1x01.avi" }, { "/home/user/TV Shows/Dexter/S1/1x01.avi", true, "/home/user/TV Shows/Dexter/S1/" }, - { "rar://g%3a%5cmultimedia%5cmovies%5cSphere%2erar/Sphere.avi", true, "g:\\multimedia\\movies\\" }, + { "zip://g%3a%5cmultimedia%5cmovies%5cSphere%2ezip/Sphere.avi", true, "g:\\multimedia\\movies\\" }, { "/home/user/movies/movie_name/video_ts/VIDEO_TS.IFO", false, "/home/user/movies/movie_name/" }, { "/home/user/movies/movie_name/video_ts/VIDEO_TS.IFO", true, "/home/user/movies/movie_name/" }, { "/home/user/movies/movie_name/BDMV/index.bdmv", false, "/home/user/movies/movie_name/" }, diff --git a/xbmc/threads/Condition.h b/xbmc/threads/Condition.h index 63da1f55b7..b249f2babd 100644 --- a/xbmc/threads/Condition.h +++ b/xbmc/threads/Condition.h @@ -9,7 +9,6 @@ #pragma once #include "threads/SingleLock.h" -#include "threads/Helpers.h" #include "threads/SystemClock.h" #include <condition_variable> diff --git a/xbmc/threads/Lockables.h b/xbmc/threads/Lockables.h index 1a4b59963b..485bd3a8fb 100644 --- a/xbmc/threads/Lockables.h +++ b/xbmc/threads/Lockables.h @@ -8,8 +8,6 @@ #pragma once -#include "threads/Helpers.h" - namespace XbmcThreads { diff --git a/xbmc/utils/CryptThreading.cpp b/xbmc/utils/CryptThreading.cpp index 0343c97190..c0a2c3e02c 100644 --- a/xbmc/utils/CryptThreading.cpp +++ b/xbmc/utils/CryptThreading.cpp @@ -55,6 +55,7 @@ CryptThreadingInitializer::~CryptThreadingInitializer() { #if KODI_OPENSSL_NEEDS_LOCK_CALLBACK CSingleLock l(m_locksLock); + CRYPTO_set_id_callback(nullptr); CRYPTO_set_locking_callback(nullptr); m_locks.clear(); #endif diff --git a/xbmc/utils/EGLUtils.cpp b/xbmc/utils/EGLUtils.cpp index d80b1fba43..0eccb9c44a 100644 --- a/xbmc/utils/EGLUtils.cpp +++ b/xbmc/utils/EGLUtils.cpp @@ -23,6 +23,15 @@ namespace #ifndef EGL_NO_CONFIG_KHR #define EGL_NO_CONFIG_KHR static_cast<EGLConfig>(0) #endif +#ifndef EGL_CONTEXT_PRIORITY_LEVEL_IMG +#define EGL_CONTEXT_PRIORITY_LEVEL_IMG 0x3100 +#endif +#ifndef EGL_CONTEXT_PRIORITY_HIGH_IMG +#define EGL_CONTEXT_PRIORITY_HIGH_IMG 0x3101 +#endif +#ifndef EGL_CONTEXT_PRIORITY_MEDIUM_IMG +#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG 0x3102 +#endif #define X(VAL) std::make_pair(VAL, #VAL) std::array<std::pair<EGLint, const char*>, 32> eglAttributes = @@ -281,7 +290,7 @@ bool CEGLContextUtils::ChooseConfig(EGLint renderableType, EGLint visualId) return true; } -bool CEGLContextUtils::CreateContext(const EGLint* contextAttribs) +bool CEGLContextUtils::CreateContext(CEGLAttributesVec contextAttribs) { if (m_eglContext != EGL_NO_CONTEXT) { @@ -293,8 +302,22 @@ bool CEGLContextUtils::CreateContext(const EGLint* contextAttribs) if (CEGLUtils::HasExtension(m_eglDisplay, "EGL_KHR_no_config_context")) eglConfig = EGL_NO_CONFIG_KHR; + if (CEGLUtils::HasExtension(m_eglDisplay, "EGL_IMG_context_priority")) + contextAttribs.Add({{EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_HIGH_IMG}}); + m_eglContext = eglCreateContext(m_eglDisplay, eglConfig, - EGL_NO_CONTEXT, contextAttribs); + EGL_NO_CONTEXT, contextAttribs.Get()); + + if (CEGLUtils::HasExtension(m_eglDisplay, "EGL_IMG_context_priority")) + { + EGLint value{EGL_CONTEXT_PRIORITY_MEDIUM_IMG}; + + if (eglQueryContext(m_eglDisplay, m_eglContext, EGL_CONTEXT_PRIORITY_LEVEL_IMG, &value) != EGL_TRUE) + CEGLUtils::LogError("failed to query EGL context attribute EGL_CONTEXT_PRIORITY_LEVEL_IMG"); + + if (value != EGL_CONTEXT_PRIORITY_HIGH_IMG) + CLog::Log(LOGDEBUG, "Failed to obtain a high priority EGL context"); + } if (m_eglContext == EGL_NO_CONTEXT) { diff --git a/xbmc/utils/EGLUtils.h b/xbmc/utils/EGLUtils.h index 9337ce11aa..2abbc6cd48 100644 --- a/xbmc/utils/EGLUtils.h +++ b/xbmc/utils/EGLUtils.h @@ -12,6 +12,7 @@ #include <set> #include <string> #include <stdexcept> +#include <vector> #include <EGL/egl.h> @@ -39,6 +40,54 @@ private: }; /** + * Convenience wrapper for heap-allocated EGL attribute arrays + * + * The wrapper makes sure that the key/value pairs are always written in actual + * pairs and that the array is always terminated with EGL_NONE. + */ +class CEGLAttributesVec +{ +public: + struct EGLAttribute + { + EGLint key; + EGLint value; + }; + + /** + * Add multiple attributes + * + * The array is automatically terminated with EGL_NONE + */ + void Add(std::initializer_list<EGLAttribute> const& attributes) + { + for (auto const& attribute : attributes) + { + m_attributes.insert(m_attributes.begin(), attribute.value); + m_attributes.insert(m_attributes.begin(), attribute.key); + } + } + + /** + * Add one attribute + * + * The array is automatically terminated with EGL_NONE + */ + void Add(EGLAttribute const& attribute) + { + Add({attribute}); + } + + EGLint const * Get() const + { + return m_attributes.data(); + } + +private: + std::vector<EGLint> m_attributes{EGL_NONE}; +}; + +/** * Convenience wrapper for stack-allocated EGL attribute arrays * * The wrapper makes sure that the key/value pairs are always written in actual @@ -135,7 +184,7 @@ public: bool CreateSurface(EGLNativeWindowType nativeWindow); bool CreatePlatformSurface(void* nativeWindow, EGLNativeWindowType nativeWindowLegacy); - bool CreateContext(const EGLint* contextAttribs); + bool CreateContext(CEGLAttributesVec contextAttribs); bool BindContext(); void Destroy(); void DestroySurface(); diff --git a/xbmc/utils/FileExtensionProvider.cpp b/xbmc/utils/FileExtensionProvider.cpp index e09c93b3de..532b46592d 100644 --- a/xbmc/utils/FileExtensionProvider.cpp +++ b/xbmc/utils/FileExtensionProvider.cpp @@ -140,6 +140,16 @@ void CFileExtensionProvider::SetAddonExtensions(const TYPE& type) if (addonInfo->Type(type)->GetValue(info2).asBoolean()) fileFolderExtensions.push_back(ext); } + if (type == ADDON_VFS) + { + if (addonInfo->Type(type)->GetValue("@encodedhostname").asBoolean()) + { + std::string prot = addonInfo->Type(type)->GetValue("@protocols").asString(); + auto prots = StringUtils::Split(prot, "|"); + for (const std::string& it : prots) + m_encoded.push_back(it); + } + } } } @@ -168,3 +178,8 @@ void CFileExtensionProvider::OnAddonEvent(const AddonEvent& event) SetAddonExtensions(); } } + +bool CFileExtensionProvider::EncodedHostName(const std::string& protocol) const +{ + return std::find(m_encoded.begin(),m_encoded.end(),protocol) != m_encoded.end(); +} diff --git a/xbmc/utils/FileExtensionProvider.h b/xbmc/utils/FileExtensionProvider.h index 5135c97080..4a23a0d7b5 100644 --- a/xbmc/utils/FileExtensionProvider.h +++ b/xbmc/utils/FileExtensionProvider.h @@ -55,6 +55,11 @@ public: */ std::string GetFileFolderExtensions() const; + /*! + * @brief Returns whether a url protocol from add-ons use encoded hostnames + */ + bool EncodedHostName(const std::string& protocol) const; + private: std::string GetAddonExtensions(const ADDON::TYPE &type) const; std::string GetAddonFileFolderExtensions(const ADDON::TYPE &type) const; @@ -71,4 +76,7 @@ private: // File extension properties std::map<ADDON::TYPE, std::string> m_addonExtensions; std::map<ADDON::TYPE, std::string> m_addonFileFolderExtensions; + + // Protocols from add-ons with encoded host names + std::vector<std::string> m_encoded; }; diff --git a/xbmc/utils/FileUtils.cpp b/xbmc/utils/FileUtils.cpp index 771864d6de..9036e912a9 100644 --- a/xbmc/utils/FileUtils.cpp +++ b/xbmc/utils/FileUtils.cpp @@ -5,6 +5,7 @@ * SPDX-License-Identifier: GPL-2.0-or-later * See LICENSES/README.md for more information. */ + #include "FileUtils.h" #include "ServiceBroker.h" #include "guilib/GUIKeyboardFactory.h" @@ -13,9 +14,9 @@ #include "JobManager.h" #include "FileOperationJob.h" #include "URIUtils.h" -#include "filesystem/StackDirectory.h" #include "filesystem/MultiPathDirectory.h" -#include <vector> +#include "filesystem/SpecialProtocol.h" +#include "filesystem/StackDirectory.h" #include "settings/MediaSourceSettings.h" #include "Util.h" #include "StringUtils.h" @@ -24,6 +25,13 @@ #include "settings/SettingsComponent.h" #include "utils/Variant.h" +#if defined(TARGET_WINDOWS) +#include "platform/win32/WIN32Util.h" +#include "utils/CharsetConverter.h" +#endif + +#include <vector> + using namespace XFILE; bool CFileUtils::DeleteItem(const std::string &strPath) @@ -202,3 +210,100 @@ CDateTime CFileUtils::GetModificationDate(const std::string& strFileNameAndPath, } return dateAdded; } + +bool CFileUtils::CheckFileAccessAllowed(const std::string &filePath) +{ + // DENY access to paths matching + const std::vector<std::string> blacklist = { + "passwords.xml", + "sources.xml", + "guisettings.xml", + "advancedsettings.xml", + "server.key", + "/.ssh/", + }; + // ALLOW kodi paths + const std::vector<std::string> whitelist = { + CSpecialProtocol::TranslatePath("special://home"), + CSpecialProtocol::TranslatePath("special://xbmc") + }; + + // image urls come in the form of image://... sometimes with a / appended at the end + // strip this off to get the real file path + bool isImage = false; + std::string decodePath = CURL::Decode(filePath); + size_t pos = decodePath.find("image://"); + if (pos != std::string::npos) + { + isImage = true; + decodePath.erase(pos, 8); + URIUtils::RemoveSlashAtEnd(decodePath); + } + + // check blacklist + for (const auto &b : blacklist) + { + if (decodePath.find(b) != std::string::npos) + { + CLog::Log(LOGERROR,"%s denied access to %s", __FUNCTION__, decodePath.c_str()); + return false; + } + } + +#if defined(TARGET_POSIX) + std::string whiteEntry; + char *fullpath = realpath(decodePath.c_str(), nullptr); + + // if this is a locally existing file, check access permissions + if (fullpath) + { + const std::string realPath = fullpath; + free(fullpath); + + // check whitelist + for (const auto &w : whitelist) + { + char *realtemp = realpath(w.c_str(), nullptr); + if (realtemp) + { + whiteEntry = realtemp; + free(realtemp); + } + if (StringUtils::StartsWith(realPath, whiteEntry)) + return true; + } + // check sources with realPath + return CFileUtils::RemoteAccessAllowed(realPath); + } +#elif defined(TARGET_WINDOWS) + CURL url(decodePath); + if (url.GetProtocol().empty()) + { + std::wstring decodePathW; + g_charsetConverter.utf8ToW(decodePath, decodePathW, false); + CWIN32Util::AddExtraLongPathPrefix(decodePathW); + DWORD bufSize = GetFullPathNameW(decodePathW.c_str(), 0, nullptr, nullptr); + if (bufSize > 0) + { + std::wstring fullpathW; + fullpathW.resize(bufSize); + if (GetFullPathNameW(decodePathW.c_str(), bufSize, const_cast<wchar_t*>(fullpathW.c_str()), nullptr) <= bufSize - 1) + { + CWIN32Util::RemoveExtraLongPathPrefix(fullpathW); + std::string fullpath; + g_charsetConverter.wToUTF8(fullpathW, fullpath, false); + for (const std::string& whiteEntry : whitelist) + { + if (StringUtils::StartsWith(fullpath, whiteEntry)) + return true; + } + return CFileUtils::RemoteAccessAllowed(fullpath); + } + } + } +#endif + // if it isn't a local file, it must be a vfs entry + if (! isImage) + return CFileUtils::RemoteAccessAllowed(decodePath); + return true; +} diff --git a/xbmc/utils/FileUtils.h b/xbmc/utils/FileUtils.h index 13bb162065..fe76e6aef7 100644 --- a/xbmc/utils/FileUtils.h +++ b/xbmc/utils/FileUtils.h @@ -14,6 +14,7 @@ class CFileUtils { public: + static bool CheckFileAccessAllowed(const std::string &filePath); static bool DeleteItem(const CFileItemPtr &item); static bool DeleteItem(const std::string &strPath); static bool RenameFile(const std::string &strFile); diff --git a/xbmc/utils/LangCodeExpander.cpp b/xbmc/utils/LangCodeExpander.cpp index 8a5fa02e42..7edcd7567f 100644 --- a/xbmc/utils/LangCodeExpander.cpp +++ b/xbmc/utils/LangCodeExpander.cpp @@ -10,7 +10,6 @@ #include <array> #include "LangCodeExpander.h" -#include "Util.h" #include "utils/StringUtils.h" #include "utils/XBMCTinyXML.h" diff --git a/xbmc/utils/RssManager.cpp b/xbmc/utils/RssManager.cpp index 19023e05b4..a44e33016b 100644 --- a/xbmc/utils/RssManager.cpp +++ b/xbmc/utils/RssManager.cpp @@ -15,7 +15,6 @@ #include "ServiceBroker.h" #include "filesystem/File.h" #include "interfaces/builtins/Builtins.h" -#include "messaging/ApplicationMessenger.h" #include "messaging/helpers/DialogHelper.h" #include "profiles/ProfileManager.h" #include "settings/lib/Setting.h" diff --git a/xbmc/utils/ScraperUrl.cpp b/xbmc/utils/ScraperUrl.cpp index b1d88cac7b..9561680d82 100644 --- a/xbmc/utils/ScraperUrl.cpp +++ b/xbmc/utils/ScraperUrl.cpp @@ -22,6 +22,7 @@ #include "utils/Mime.h" #include "utils/log.h" +#include <algorithm> #include <cstring> #include <sstream> @@ -372,7 +373,7 @@ std::string CScraperUrl::GetThumbURL(const CScraperUrl::SUrlEntry &entry) return entry.m_url + "|Referer=" + CURL::Encode(entry.m_spoof); } -void CScraperUrl::GetThumbURLs(std::vector<std::string> &thumbs, const std::string &type, int season) const +void CScraperUrl::GetThumbURLs(std::vector<std::string> &thumbs, const std::string &type, int season, bool unique) const { for (std::vector<SUrlEntry>::const_iterator iter = m_url.begin(); iter != m_url.end(); ++iter) { @@ -381,7 +382,9 @@ void CScraperUrl::GetThumbURLs(std::vector<std::string> &thumbs, const std::stri if ((iter->m_type == CScraperUrl::URL_TYPE_GENERAL && season == -1) || (iter->m_type == CScraperUrl::URL_TYPE_SEASON && iter->m_season == season)) { - thumbs.push_back(GetThumbURL(*iter)); + std::string url = GetThumbURL(*iter); + if (!unique || std::find(thumbs.begin(), thumbs.end(), url) == thumbs.end()) + thumbs.push_back(url); } } } diff --git a/xbmc/utils/ScraperUrl.h b/xbmc/utils/ScraperUrl.h index a8bfbac51f..d7a5d700e4 100644 --- a/xbmc/utils/ScraperUrl.h +++ b/xbmc/utils/ScraperUrl.h @@ -61,8 +61,9 @@ public: \param thumbs [out] vector of thumb URLs to fill \param type the type of thumb URLs to fetch, if empty (the default) picks any \param season number of season that we want thumbs for, -1 indicates no season (the default) + \param unique avoid adding duplicate URLs when adding to a thumbs vector with existing items */ - void GetThumbURLs(std::vector<std::string> &thumbs, const std::string &type = "", int season = -1) const; + void GetThumbURLs(std::vector<std::string> &thumbs, const std::string &type = "", int season = -1, bool unique = false) const; void Clear(); static bool Get(const SUrlEntry&, std::string&, XFILE::CCurlFile& http, const std::string& cacheContext); diff --git a/xbmc/utils/URIUtils.cpp b/xbmc/utils/URIUtils.cpp index 000bb93fa2..db0ececd30 100644 --- a/xbmc/utils/URIUtils.cpp +++ b/xbmc/utils/URIUtils.cpp @@ -275,12 +275,12 @@ void URIUtils::GetCommonPath(std::string& strParent, const std::string& strPath) bool URIUtils::HasParentInHostname(const CURL& url) { return url.IsProtocol("zip") - || url.IsProtocol("rar") - || url.IsProtocol("archive") || url.IsProtocol("apk") || url.IsProtocol("bluray") || url.IsProtocol("udf") - || url.IsProtocol("xbt"); + || url.IsProtocol("xbt") + || (CServiceBroker::IsBinaryAddonCacheUp() && + CServiceBroker::GetFileExtensionProvider().EncodedHostName(url.GetProtocol())); } bool URIUtils::HasEncodedHostname(const CURL& url) diff --git a/xbmc/utils/test/TestURIUtils.cpp b/xbmc/utils/test/TestURIUtils.cpp index 6696d94f72..0631900075 100644 --- a/xbmc/utils/test/TestURIUtils.cpp +++ b/xbmc/utils/test/TestURIUtils.cpp @@ -284,13 +284,11 @@ TEST_F(TestURIUtils, IsHD) EXPECT_TRUE(URIUtils::IsHD("special://path/to/file")); EXPECT_TRUE(URIUtils::IsHD("stack://path/to/file")); EXPECT_TRUE(URIUtils::IsHD("zip://path/to/file")); - EXPECT_TRUE(URIUtils::IsHD("rar://path/to/file")); } TEST_F(TestURIUtils, IsInArchive) { EXPECT_TRUE(URIUtils::IsInArchive("zip://path/to/file")); - EXPECT_TRUE(URIUtils::IsInArchive("rar://path/to/file")); } TEST_F(TestURIUtils, IsInRAR) @@ -477,14 +475,12 @@ TEST_F(TestURIUtils, AddFileToFolder) TEST_F(TestURIUtils, HasParentInHostname) { EXPECT_TRUE(URIUtils::HasParentInHostname(CURL("zip://"))); - EXPECT_TRUE(URIUtils::HasParentInHostname(CURL("rar://"))); EXPECT_TRUE(URIUtils::HasParentInHostname(CURL("bluray://"))); } TEST_F(TestURIUtils, HasEncodedHostname) { EXPECT_TRUE(URIUtils::HasEncodedHostname(CURL("zip://"))); - EXPECT_TRUE(URIUtils::HasEncodedHostname(CURL("rar://"))); EXPECT_TRUE(URIUtils::HasEncodedHostname(CURL("bluray://"))); EXPECT_TRUE(URIUtils::HasEncodedHostname(CURL("musicsearch://"))); } @@ -538,34 +534,34 @@ TEST_F(TestURIUtils, GetRealPath) #endif // test rar/zip paths - ref = "rar://%2fpath%2fto%2frar/subpath/to/file"; + ref = "zip://%2fpath%2fto%2fzip/subpath/to/file"; EXPECT_STRCASEEQ(ref.c_str(), URIUtils::GetRealPath(ref).c_str()); // test rar/zip paths - ref = "rar://%2fpath%2fto%2frar/subpath/to/file"; - EXPECT_STRCASEEQ(ref.c_str(), URIUtils::GetRealPath("rar://%2fpath%2fto%2frar/../subpath/to/file").c_str()); - EXPECT_STRCASEEQ(ref.c_str(), URIUtils::GetRealPath("rar://%2fpath%2fto%2frar/./subpath/to/file").c_str()); - EXPECT_STRCASEEQ(ref.c_str(), URIUtils::GetRealPath("rar://%2fpath%2fto%2frar/subpath/to/./file").c_str()); - EXPECT_STRCASEEQ(ref.c_str(), URIUtils::GetRealPath("rar://%2fpath%2fto%2frar/subpath/to/some/../file").c_str()); + ref = "zip://%2fpath%2fto%2fzip/subpath/to/file"; + EXPECT_STRCASEEQ(ref.c_str(), URIUtils::GetRealPath("zip://%2fpath%2fto%2fzip/../subpath/to/file").c_str()); + EXPECT_STRCASEEQ(ref.c_str(), URIUtils::GetRealPath("zip://%2fpath%2fto%2fzip/./subpath/to/file").c_str()); + EXPECT_STRCASEEQ(ref.c_str(), URIUtils::GetRealPath("zip://%2fpath%2fto%2fzip/subpath/to/./file").c_str()); + EXPECT_STRCASEEQ(ref.c_str(), URIUtils::GetRealPath("zip://%2fpath%2fto%2fzip/subpath/to/some/../file").c_str()); - EXPECT_STRCASEEQ(ref.c_str(), URIUtils::GetRealPath("rar://%2fpath%2fto%2f.%2frar/subpath/to/file").c_str()); - EXPECT_STRCASEEQ(ref.c_str(), URIUtils::GetRealPath("rar://%2fpath%2fto%2fsome%2f..%2frar/subpath/to/file").c_str()); + EXPECT_STRCASEEQ(ref.c_str(), URIUtils::GetRealPath("zip://%2fpath%2fto%2f.%2fzip/subpath/to/file").c_str()); + EXPECT_STRCASEEQ(ref.c_str(), URIUtils::GetRealPath("zip://%2fpath%2fto%2fsome%2f..%2fzip/subpath/to/file").c_str()); - // test rar/zip path in rar/zip path - ref ="zip://rar%3a%2f%2f%252Fpath%252Fto%252Frar%2fpath%2fto%2fzip/subpath/to/file"; - EXPECT_STRCASEEQ(ref.c_str(), URIUtils::GetRealPath("zip://rar%3a%2f%2f%252Fpath%252Fto%252Fsome%252F..%252Frar%2fpath%2fto%2fsome%2f..%2fzip/subpath/to/some/../file").c_str()); + // test zip/zip path + ref ="zip://zip%3a%2f%2f%252Fpath%252Fto%252Fzip%2fpath%2fto%2fzip/subpath/to/file"; + EXPECT_STRCASEEQ(ref.c_str(), URIUtils::GetRealPath("zip://zip%3a%2f%2f%252Fpath%252Fto%252Fsome%252F..%252Fzip%2fpath%2fto%2fsome%2f..%2fzip/subpath/to/some/../file").c_str()); } TEST_F(TestURIUtils, UpdateUrlEncoding) { - std::string oldUrl = "stack://rar://%2fpath%2fto%2farchive%2fsome%2darchive%2dfile%2eCD1%2erar/video.avi , rar://%2fpath%2fto%2farchive%2fsome%2darchive%2dfile%2eCD2%2erar/video.avi"; - std::string newUrl = "stack://rar://%2fpath%2fto%2farchive%2fsome-archive-file.CD1.rar/video.avi , rar://%2fpath%2fto%2farchive%2fsome-archive-file.CD2.rar/video.avi"; + std::string oldUrl = "stack://zip://%2fpath%2fto%2farchive%2fsome%2darchive%2dfile%2eCD1%2ezip/video.avi , zip://%2fpath%2fto%2farchive%2fsome%2darchive%2dfile%2eCD2%2ezip/video.avi"; + std::string newUrl = "stack://zip://%2fpath%2fto%2farchive%2fsome-archive-file.CD1.zip/video.avi , zip://%2fpath%2fto%2farchive%2fsome-archive-file.CD2.zip/video.avi"; EXPECT_TRUE(URIUtils::UpdateUrlEncoding(oldUrl)); EXPECT_STRCASEEQ(newUrl.c_str(), oldUrl.c_str()); - oldUrl = "rar://%2fpath%2fto%2farchive%2fsome%2darchive%2efile%2erar/video.avi"; - newUrl = "rar://%2fpath%2fto%2farchive%2fsome-archive.file.rar/video.avi"; + oldUrl = "zip://%2fpath%2fto%2farchive%2fsome%2darchive%2efile%2ezip/video.avi"; + newUrl = "zip://%2fpath%2fto%2farchive%2fsome-archive.file.zip/video.avi"; EXPECT_TRUE(URIUtils::UpdateUrlEncoding(oldUrl)); EXPECT_STRCASEEQ(newUrl.c_str(), oldUrl.c_str()); diff --git a/xbmc/video/ContextMenus.h b/xbmc/video/ContextMenus.h index b68aa46c0a..e5eace22f6 100644 --- a/xbmc/video/ContextMenus.h +++ b/xbmc/video/ContextMenus.h @@ -9,7 +9,6 @@ #pragma once #include "ContextMenuItem.h" -#include "guilib/GUIWindowManager.h" #include "VideoLibraryQueue.h" namespace CONTEXTMENU diff --git a/xbmc/video/VideoDatabase.cpp b/xbmc/video/VideoDatabase.cpp index baf8f27d8a..668547a79f 100644 --- a/xbmc/video/VideoDatabase.cpp +++ b/xbmc/video/VideoDatabase.cpp @@ -2346,9 +2346,16 @@ int CVideoDatabase::SetDetailsForMovie(const std::string& strFilenameAndPath, CV { idSet = AddSet(details.m_set.title, details.m_set.overview); // add art if not available - std::map<std::string, std::string> setArt; - if (!GetArtForItem(idSet, MediaTypeVideoCollection, setArt)) - SetArtForItem(idSet, MediaTypeVideoCollection, artwork); + if (!HasArtForItem(idSet, MediaTypeVideoCollection)) + { + std::map<std::string, std::string> setArt; + for (const auto &it : artwork) + { + if (StringUtils::StartsWith(it.first, "set.")) + setArt[it.first.substr(4)] = it.second; + } + SetArtForItem(idSet, MediaTypeVideoCollection, setArt.empty() ? artwork : setArt); + } } if (details.HasStreamDetails()) @@ -2460,9 +2467,8 @@ int CVideoDatabase::UpdateDetailsForMovie(int idMovie, CVideoInfoTag& details, c { idSet = AddSet(details.m_set.title, details.m_set.overview); // add art if not available - std::map<std::string, std::string> setArt; - if (!GetArtForItem(idSet, "set", setArt)) - SetArtForItem(idSet, "set", artwork); + if (!HasArtForItem(idSet, MediaTypeVideoCollection)) + SetArtForItem(idSet, MediaTypeVideoCollection, artwork); } } @@ -4502,6 +4508,26 @@ bool CVideoDatabase::RemoveArtForItem(int mediaId, const MediaType &mediaType, c return result; } +bool CVideoDatabase::HasArtForItem(int mediaId, const MediaType &mediaType) +{ + try + { + if (NULL == m_pDB.get()) return false; + if (NULL == m_pDS2.get()) return false; // using dataset 2 as we're likely called in loops on dataset 1 + + std::string sql = PrepareSQL("SELECT count(*) FROM art WHERE media_id=%i AND media_type='%s'", mediaId, mediaType.c_str()); + m_pDS2->query(sql); + bool result = !m_pDS2->eof(); + m_pDS2->close(); + return result; + } + catch (...) + { + CLog::Log(LOGERROR, "%s(%d) failed", __FUNCTION__, mediaId); + } + return false; +} + bool CVideoDatabase::GetTvShowSeasons(int showId, std::map<int, int> &seasons) { try diff --git a/xbmc/video/VideoDatabase.h b/xbmc/video/VideoDatabase.h index 23b7692c6e..b4d75424fe 100644 --- a/xbmc/video/VideoDatabase.h +++ b/xbmc/video/VideoDatabase.h @@ -836,6 +836,7 @@ public: void SetArtForItem(int mediaId, const MediaType &mediaType, const std::map<std::string, std::string> &art); bool GetArtForItem(int mediaId, const MediaType &mediaType, std::map<std::string, std::string> &art); std::string GetArtForItem(int mediaId, const MediaType &mediaType, const std::string &artType); + bool HasArtForItem(int mediaId, const MediaType &mediaType); bool RemoveArtForItem(int mediaId, const MediaType &mediaType, const std::string &artType); bool RemoveArtForItem(int mediaId, const MediaType &mediaType, const std::set<std::string> &artTypes); bool GetTvShowSeasons(int showId, std::map<int, int> &seasons); diff --git a/xbmc/video/VideoInfoScanner.cpp b/xbmc/video/VideoInfoScanner.cpp index f624277e79..7f96553d49 100644 --- a/xbmc/video/VideoInfoScanner.cpp +++ b/xbmc/video/VideoInfoScanner.cpp @@ -8,6 +8,7 @@ #include "VideoInfoScanner.h" +#include <algorithm> #include <utility> #include "ServiceBroker.h" @@ -16,6 +17,7 @@ #include "events/EventLog.h" #include "events/MediaLibraryEvent.h" #include "FileItem.h" +#include "filesystem/Directory.h" #include "filesystem/DirectoryCache.h" #include "filesystem/File.h" #include "filesystem/MultiPathDirectory.h" @@ -1439,9 +1441,6 @@ namespace VIDEO // get and cache thumb images std::vector<std::string> artTypes = CVideoThumbLoader::GetArtTypes(ContentToMediaType(content, pItem->m_bIsFolder)); - std::vector<std::string>::iterator i = find(artTypes.begin(), artTypes.end(), "fanart"); - if (i != artTypes.end()) - artTypes.erase(i); // fanart is handled below bool lookForThumb = find(artTypes.begin(), artTypes.end(), "thumb") == artTypes.end() && art.find("thumb") == art.end(); // find local art @@ -1478,7 +1477,7 @@ namespace VIDEO { for (auto& it : pItem->GetVideoInfoTag()->m_coverArt) { - if (art.find(it.m_type) == art.end()) + if (std::find(artTypes.begin(), artTypes.end(), it.m_type) != artTypes.end() && art.find(it.m_type) == art.end()) { std::string thumb = CTextureUtils::GetWrappedImageURL(pItem->GetPath(), "video_" + it.m_type); @@ -1487,11 +1486,10 @@ namespace VIDEO } } - // get & save fanart image (treated separately due to it being stored in m_fanart) - bool isEpisode = (content == CONTENT_TVSHOWS && !pItem->m_bIsFolder); - if (!isEpisode && art.find("fanart") == art.end()) + // add online fanart (treated separately due to it being stored in m_fanart) + if (find(artTypes.begin(), artTypes.end(), "fanart") != artTypes.end() && art.find("fanart") == art.end()) { - std::string fanart = GetFanart(pItem, useLocal); + std::string fanart = pItem->GetVideoInfoTag()->m_fanart.GetImageURL(); if (!fanart.empty()) art.insert(std::make_pair("fanart", fanart)); } @@ -1505,7 +1503,7 @@ namespace VIDEO if (aspect.empty()) // temporary support for XML music video scrapers that share music album scraper bits aspect = content == CONTENT_MUSICVIDEOS ? "poster" : "thumb"; - if (art.find(aspect) != art.end()) + if (find(artTypes.begin(), artTypes.end(), aspect) == artTypes.end() || art.find(aspect) != art.end()) continue; std::string image = GetImage(url, pItem->GetPath()); if (!image.empty()) @@ -1538,18 +1536,6 @@ namespace VIDEO return thumb; } - std::string CVideoInfoScanner::GetFanart(CFileItem *pItem, bool useLocal) - { - if (!pItem) - return ""; - std::string fanart = pItem->GetArt("fanart"); - if (fanart.empty() && useLocal) - fanart = pItem->FindLocalArt("fanart.jpg", true); - if (fanart.empty()) - fanart = pItem->GetVideoInfoTag()->m_fanart.GetImageURL(); - return fanart; - } - CInfoScanner::INFO_RET CVideoInfoScanner::OnProcessSeriesFolder(EPISODELIST& files, const ADDON::ScraperPtr &scraper, @@ -1990,7 +1976,7 @@ namespace VIDEO if (aspect.empty()) aspect = "thumb"; std::map<std::string, std::string>& art = seasonArt[url.m_season]; - if (art.find(aspect) != art.end()) + if (find(artTypes.begin(), artTypes.end(), aspect) == artTypes.end() || art.find(aspect) != art.end()) continue; std::string image = CScraperUrl::GetThumbURL(url); if (!image.empty()) diff --git a/xbmc/video/VideoInfoScanner.h b/xbmc/video/VideoInfoScanner.h index 76d6dca51b..7e683511ad 100644 --- a/xbmc/video/VideoInfoScanner.h +++ b/xbmc/video/VideoInfoScanner.h @@ -98,7 +98,6 @@ namespace VIDEO */ static void GetSeasonThumbs(const CVideoInfoTag &show, std::map<int, std::map<std::string, std::string> > &art, const std::vector<std::string> &artTypes, bool useLocal = true); static std::string GetImage(const CScraperUrl::SUrlEntry &image, const std::string& itemPath); - static std::string GetFanart(CFileItem *pItem, bool useLocal); bool EnumerateEpisodeItem(const CFileItem *item, EPISODELIST& episodeList); diff --git a/xbmc/video/VideoThumbLoader.cpp b/xbmc/video/VideoThumbLoader.cpp index cd2f9f5d60..211cfa3de9 100644 --- a/xbmc/video/VideoThumbLoader.cpp +++ b/xbmc/video/VideoThumbLoader.cpp @@ -14,6 +14,7 @@ #include "cores/VideoPlayer/DVDFileInfo.h" #include "FileItem.h" #include "ServiceBroker.h" +#include "filesystem/Directory.h" #include "filesystem/DirectoryCache.h" #include "filesystem/StackDirectory.h" #include "guilib/GUIComponent.h" @@ -186,16 +187,14 @@ CVideoThumbLoader::~CVideoThumbLoader() void CVideoThumbLoader::OnLoaderStart() { m_videoDatabase->Open(); - m_showArt.clear(); - m_seasonArt.clear(); + m_artCache.clear(); CThumbLoader::OnLoaderStart(); } void CVideoThumbLoader::OnLoaderFinish() { m_videoDatabase->Close(); - m_showArt.clear(); - m_seasonArt.clear(); + m_artCache.clear(); CThumbLoader::OnLoaderFinish(); } @@ -222,27 +221,38 @@ static void SetupRarOptions(CFileItem& item, const std::string& path) std::vector<std::string> CVideoThumbLoader::GetArtTypes(const std::string &type) { + const std::shared_ptr<CAdvancedSettings> advancedSettings = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings(); std::vector<std::string> ret; + std::vector<std::string> extraart; if (type == MediaTypeEpisode) - ret.push_back("thumb"); - else if (type == MediaTypeTvShow || type == MediaTypeSeason) { - ret.push_back("banner"); - ret.push_back("poster"); - ret.push_back("fanart"); + ret = { "thumb" }; + extraart = advancedSettings->m_videoEpisodeExtraArt; } - else if (type == MediaTypeMovie || type == MediaTypeMusicVideo || type == MediaTypeVideoCollection) + else if (type == MediaTypeTvShow) { - ret.push_back("poster"); - ret.push_back("fanart"); + ret = { "poster", "fanart", "banner" }; + extraart = advancedSettings->m_videoTvShowExtraArt; } - else if (type.empty()) // unknown - just throw everything in + else if (type == MediaTypeSeason) { - ret.push_back("poster"); - ret.push_back("banner"); - ret.push_back("thumb"); - ret.push_back("fanart"); + ret = { "poster", "fanart", "banner" }; + extraart = advancedSettings->m_videoTvSeasonExtraArt; } + else if (type == MediaTypeMovie || type == MediaTypeVideoCollection) + { + ret = { "poster", "fanart" }; + extraart = advancedSettings->m_videoMovieExtraArt; + } + else if (type == MediaTypeMusicVideo) + { + ret = { "poster", "fanart" }; + extraart = advancedSettings->m_videoMusicVideoExtraArt; + } + else if (type.empty()) // unknown, just the basics + ret = { "poster", "fanart", "banner", "thumb" }; + + ret.insert(ret.end(), extraart.begin(), extraart.end()); return ret; } @@ -473,35 +483,28 @@ bool CVideoThumbLoader::FillLibraryArt(CFileItem &item) // For episodes and seasons, we want to set fanart for that of the show if (!item.HasArt("tvshow.fanart") && tag.m_iIdShow >= 0) { - ArtCache::const_iterator i = m_showArt.find(tag.m_iIdShow); - if (i == m_showArt.end()) + const ArtMap& artmap = GetArtFromCache(MediaTypeTvShow, tag.m_iIdShow); + if (!artmap.empty()) { - std::map<std::string, std::string> showArt; - m_videoDatabase->GetArtForItem(tag.m_iIdShow, MediaTypeTvShow, showArt); - i = m_showArt.insert(std::make_pair(tag.m_iIdShow, showArt)).first; - } - if (i != m_showArt.end()) - { - item.AppendArt(i->second, "tvshow"); + item.AppendArt(artmap, MediaTypeTvShow); item.SetArtFallback("fanart", "tvshow.fanart"); item.SetArtFallback("tvshow.thumb", "tvshow.poster"); } } - if (!item.HasArt("season.poster") && tag.m_iSeason > -1) + if (tag.m_type == MediaTypeEpisode && !item.HasArt("season.poster") && tag.m_iSeason > -1) { - ArtCache::const_iterator i = m_seasonArt.find(tag.m_iIdSeason); - if (i == m_seasonArt.end()) - { - std::map<std::string, std::string> seasonArt; - m_videoDatabase->GetArtForItem(tag.m_iIdSeason, MediaTypeSeason, seasonArt); - i = m_seasonArt.insert(std::make_pair(tag.m_iIdSeason, seasonArt)).first; - } - - if (i != m_seasonArt.end()) - item.AppendArt(i->second, MediaTypeSeason); + const ArtMap& artmap = GetArtFromCache(MediaTypeSeason, tag.m_iIdSeason); + if (!artmap.empty()) + item.AppendArt(artmap, MediaTypeSeason); } } + else if (tag.m_type == MediaTypeMovie && tag.m_set.id >= 0 && !item.HasArt("set.fanart")) + { + const ArtMap& artmap = GetArtFromCache(MediaTypeVideoCollection, tag.m_set.id); + if (!artmap.empty()) + item.AppendArt(artmap, MediaTypeVideoCollection); + } m_videoDatabase->Close(); } return !item.GetArt().empty(); @@ -684,3 +687,16 @@ void CVideoThumbLoader::DetectAndAddMissingItemData(CFileItem &item) if (!stereoMode.empty()) item.SetProperty("stereomode", CStereoscopicsManager::NormalizeStereoMode(stereoMode)); } + +const ArtMap& CVideoThumbLoader::GetArtFromCache(const std::string &mediaType, const int id) +{ + std::pair<MediaType, int> key = std::make_pair(mediaType, id); + auto it = m_artCache.find(key); + if (it == m_artCache.end()) + { + ArtMap newart; + m_videoDatabase->GetArtForItem(id, mediaType, newart); + it = m_artCache.insert(std::make_pair(key, std::move(newart))).first; + } + return it->second; +} diff --git a/xbmc/video/VideoThumbLoader.h b/xbmc/video/VideoThumbLoader.h index 58c193c0bb..c3b4296b8a 100644 --- a/xbmc/video/VideoThumbLoader.h +++ b/xbmc/video/VideoThumbLoader.h @@ -18,6 +18,9 @@ class CStreamDetails; class CVideoDatabase; class EmbeddedArt; +using ArtMap = std::map<std::string, std::string>; +using ArtCache = std::map<std::pair<MediaType, int>, ArtMap>; + /*! \ingroup thumbs,jobs \brief Thumb extractor job class @@ -122,13 +125,13 @@ public: protected: CVideoDatabase *m_videoDatabase; - typedef std::map<int, std::map<std::string, std::string> > ArtCache; - ArtCache m_showArt; - ArtCache m_seasonArt; + ArtCache m_artCache; /*! \brief Tries to detect missing data/info from a file and adds those \param item The CFileItem to process \return void */ void DetectAndAddMissingItemData(CFileItem &item); + + const ArtMap& GetArtFromCache(const std::string &mediaType, const int id); }; diff --git a/xbmc/video/ViewModeSettings.cpp b/xbmc/video/ViewModeSettings.cpp index 1152afd6df..7e2b29c9a8 100644 --- a/xbmc/video/ViewModeSettings.cpp +++ b/xbmc/video/ViewModeSettings.cpp @@ -8,7 +8,6 @@ #include "ViewModeSettings.h" -#include "cores/IPlayer.h" #include "guilib/LocalizeStrings.h" #include "cores/VideoSettings.h" diff --git a/xbmc/video/dialogs/GUIDialogSubtitleSettings.cpp b/xbmc/video/dialogs/GUIDialogSubtitleSettings.cpp index b09796459f..80d0a95c90 100644 --- a/xbmc/video/dialogs/GUIDialogSubtitleSettings.cpp +++ b/xbmc/video/dialogs/GUIDialogSubtitleSettings.cpp @@ -11,6 +11,7 @@ #include <string> #include <vector> +#include "addons/VFSEntry.h" #include "addons/Skin.h" #include "Application.h" #include "ServiceBroker.h" @@ -105,15 +106,26 @@ void CGUIDialogSubtitleSettings::OnSettingChanged(std::shared_ptr<const CSetting std::string CGUIDialogSubtitleSettings::BrowseForSubtitle() { + std::string extras; + for (const auto& vfsAddon : CServiceBroker::GetVFSAddonCache().GetAddonInstances()) + { + if (vfsAddon->ID() == "vfs.rar" || vfsAddon->ID() == "vfs.libarchive") + extras += '|' + vfsAddon->GetExtensions(); + } + std::string strPath; if (URIUtils::IsInRAR(g_application.CurrentFileItem().GetPath()) || URIUtils::IsInZIP(g_application.CurrentFileItem().GetPath())) strPath = CURL(g_application.CurrentFileItem().GetPath()).GetHostName(); else strPath = g_application.CurrentFileItem().GetPath(); - std::string strMask = ".utf|.utf8|.utf-8|.sub|.srt|.smi|.rt|.txt|.ssa|.aqt|.jss|.ass|.idx|.rar|.zip"; + std::string strMask = ".utf|.utf8|.utf-8|.sub|.srt|.smi|.rt|.txt|.ssa|.aqt|.jss|.ass|.idx|.zip"; + if (g_application.GetCurrentPlayer() == "VideoPlayer") - strMask = ".srt|.rar|.zip|.ifo|.smi|.sub|.idx|.ass|.ssa|.txt"; + strMask = ".srt|.zip|.ifo|.smi|.sub|.idx|.ass|.ssa|.txt"; + + strMask += extras; + VECSOURCES shares(*CMediaSourceSettings::GetInstance().GetSources("video")); if (CMediaSettings::GetInstance().GetAdditionalSubtitleDirectoryChecked() != -1 && !CServiceBroker::GetSettingsComponent()->GetSettings()->GetString(CSettings::SETTING_SUBTITLES_CUSTOMPATH).empty()) { diff --git a/xbmc/video/dialogs/GUIDialogVideoInfo.cpp b/xbmc/video/dialogs/GUIDialogVideoInfo.cpp index cdbbcde179..dc4eb84b19 100644 --- a/xbmc/video/dialogs/GUIDialogVideoInfo.cpp +++ b/xbmc/video/dialogs/GUIDialogVideoInfo.cpp @@ -51,6 +51,7 @@ #include "messaging/helpers/DialogOKHelper.h" #include <iterator> +#include <string> using namespace XFILE::VIDEODATABASEDIRECTORY; using namespace XFILE; @@ -1832,12 +1833,15 @@ bool CGUIDialogVideoInfo::ManageVideoItemArtwork(const CFileItemPtr &item, const std::string baseDir = StringUtils::Format("videodb://movies/sets/%d", item->GetVideoInfoTag()->m_iDbId); if (videodb.GetMoviesNav(baseDir, items)) { + std::vector<std::string> allMovieThumbs; for (int i=0; i < items.Size(); i++) { CVideoInfoTag* pTag = items[i]->GetVideoInfoTag(); pTag->m_strPictureURL.Parse(); - pTag->m_strPictureURL.GetThumbURLs(thumbs, artType); + pTag->m_strPictureURL.GetThumbURLs(allMovieThumbs, artType); + pTag->m_strPictureURL.GetThumbURLs(thumbs, "set." + artType, -1, true); } + std::copy(allMovieThumbs.begin(), allMovieThumbs.end(), std::back_inserter(thumbs)); } } else @@ -2094,6 +2098,19 @@ bool CGUIDialogVideoInfo::OnGetFanart(const CFileItemPtr &videoItem) int iFanart = 0; for (int i=0; i < movies.Size(); i++) { + movies[i]->GetVideoInfoTag()->m_strPictureURL.Parse(); + movies[i]->GetVideoInfoTag()->m_strPictureURL.GetThumbURLs(thumbs, "set.fanart", -1, true); + } + for (auto &fanart : thumbs) + { + CFileItemPtr item(new CFileItem(StringUtils::Format("fanart://Remote{0}", iFanart++), false)); + item->SetArt("thumb", fanart); + item->SetIconImage("DefaultPicture.png"); + item->SetLabel(g_localizeStrings.Get(20441)); // "Remote fanart" + items.Add(item); + } + for (int i=0; i < movies.Size(); i++) + { // ensure the fanart is unpacked movies[i]->GetVideoInfoTag()->m_fanart.Unpack(); diff --git a/xbmc/weather/WeatherManager.cpp b/xbmc/weather/WeatherManager.cpp index 2adf8b4a38..b6285f6854 100644 --- a/xbmc/weather/WeatherManager.cpp +++ b/xbmc/weather/WeatherManager.cpp @@ -39,7 +39,15 @@ CWeatherManager::CWeatherManager(void) : CInfoLoader(30 * 60 * 1000) // 30 minut CWeatherManager::~CWeatherManager(void) { - CServiceBroker::GetSettingsComponent()->GetSettings()->GetSettingsManager()->UnregisterCallback(this); + CSettingsComponent *settingsComponent = CServiceBroker::GetSettingsComponent(); + if (!settingsComponent) + return; + + const std::shared_ptr<CSettings> settings = settingsComponent->GetSettings(); + if (!settings) + return; + + settings->GetSettingsManager()->UnregisterCallback(this); } std::string CWeatherManager::BusyInfo(int info) const diff --git a/xbmc/windowing/X11/GLContext.h b/xbmc/windowing/X11/GLContext.h index a3df57acd7..fdb17e5f76 100644 --- a/xbmc/windowing/X11/GLContext.h +++ b/xbmc/windowing/X11/GLContext.h @@ -20,6 +20,7 @@ public: } virtual ~CGLContext() = default; virtual bool Refresh(bool force, int screen, Window glWindow, bool &newContext) = 0; + virtual bool CreatePB() { return false; }; virtual void Destroy() = 0; virtual void Detach() = 0; virtual void SetVSync(bool enable) = 0; diff --git a/xbmc/windowing/X11/GLContextEGL.cpp b/xbmc/windowing/X11/GLContextEGL.cpp index 01f94b81f2..7a767770af 100644 --- a/xbmc/windowing/X11/GLContextEGL.cpp +++ b/xbmc/windowing/X11/GLContextEGL.cpp @@ -28,6 +28,8 @@ CGLContextEGL::CGLContextEGL(Display *dpy) : CGLContext(dpy) m_eglSurface = EGL_NO_SURFACE; m_eglContext = EGL_NO_CONTEXT; m_eglConfig = EGL_NO_CONFIG; + + eglGetPlatformDisplayEXT = (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT"); } CGLContextEGL::~CGLContextEGL() @@ -58,23 +60,42 @@ bool CGLContextEGL::Refresh(bool force, int screen, Window glWindow, bool &newCo return true; } - // create context - bool retVal = false; + Destroy(); + newContext = true; - if (m_eglDisplay == EGL_NO_DISPLAY) + if (eglGetPlatformDisplayEXT) { - m_eglDisplay = eglGetDisplay((EGLNativeDisplayType)m_dpy); - if (m_eglDisplay == EGL_NO_DISPLAY) + EGLint attribs[] = { - CLog::Log(LOGERROR, "failed to get egl display\n"); - return false; - } - if (!eglInitialize(m_eglDisplay, NULL, NULL)) - { - CLog::Log(LOGERROR, "failed to initialize egl display\n"); - return false; - } + EGL_PLATFORM_X11_SCREEN_EXT, screen, + EGL_NONE + }; + m_eglDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_X11_EXT,(EGLNativeDisplayType)m_dpy, + attribs); } + else + m_eglDisplay = eglGetDisplay((EGLNativeDisplayType)m_dpy); + + if (m_eglDisplay == EGL_NO_DISPLAY) + { + CLog::Log(LOGERROR, "failed to get egl display"); + return false; + } + if (!eglInitialize(m_eglDisplay, NULL, NULL)) + { + CLog::Log(LOGERROR, "failed to initialize egl\n"); + Destroy(); + return false; + } + + if (!eglBindAPI(EGL_OPENGL_API)) + { + CLog::Log(LOGERROR, "failed to initialize egl"); + Destroy(); + return false; + } + + // create context XVisualInfo vMask; XVisualInfo *vInfo = nullptr; @@ -82,130 +103,161 @@ bool CGLContextEGL::Refresh(bool force, int screen, Window glWindow, bool &newCo vMask.screen = screen; XWindowAttributes winAttr; - if (XGetWindowAttributes(m_dpy, glWindow, &winAttr)) + if (!XGetWindowAttributes(m_dpy, glWindow, &winAttr)) { - vMask.visualid = XVisualIDFromVisual(winAttr.visual); - vInfo = XGetVisualInfo(m_dpy, VisualScreenMask | VisualIDMask, &vMask, &availableVisuals); - if (!vInfo) - { - CLog::Log(LOGWARNING, "Failed to get VisualInfo of visual 0x%x", (unsigned) vMask.visualid); - } - else if(!IsSuitableVisual(vInfo)) - { - CLog::Log(LOGWARNING, "Visual 0x%x of the window is not suitable, looking for another one...", - (unsigned) vInfo->visualid); - XFree(vInfo); - vInfo = nullptr; - } - } - else CLog::Log(LOGWARNING, "Failed to get window attributes"); + Destroy(); + return false; + } - if (vInfo) + vMask.visualid = XVisualIDFromVisual(winAttr.visual); + vInfo = XGetVisualInfo(m_dpy, VisualScreenMask | VisualIDMask, &vMask, &availableVisuals); + if (!vInfo) { - CLog::Log(LOGNOTICE, "Using visual 0x%x", (unsigned) vInfo->visualid); - - if (m_eglContext) - { - eglMakeCurrent(m_eglContext, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - eglDestroyContext(m_eglDisplay, m_eglContext); - m_eglContext = EGL_NO_CONTEXT; - - if (m_eglSurface) - { - eglDestroySurface(m_eglDisplay, m_eglSurface); - m_eglSurface = EGL_NO_SURFACE; - } - eglTerminate(m_eglDisplay); - m_eglDisplay = EGL_NO_DISPLAY; - XSync(m_dpy, False); - newContext = true; - } + CLog::Log(LOGERROR, "Failed to get VisualInfo of visual 0x%x", (unsigned) vMask.visualid); + Destroy(); + return false; + } - m_eglDisplay = eglGetDisplay((EGLNativeDisplayType)m_dpy); - if (m_eglDisplay == EGL_NO_DISPLAY) - { - CLog::Log(LOGERROR, "failed to get egl display"); - return false; - } - if (!eglInitialize(m_eglDisplay, NULL, NULL)) - { - CLog::Log(LOGERROR, "failed to initialize egl\n"); - return false; - } + if (!IsSuitableVisual(vInfo)) + { + CLog::Log(LOGWARNING, "Visual 0x%x of the window is not suitable", (unsigned) vInfo->visualid); + XFree(vInfo); + Destroy(); + return false; + } - if (!eglBindAPI(EGL_OPENGL_API)) - { - CLog::Log(LOGERROR, "failed to initialize egl"); - XFree(vInfo); - return false; - } + CLog::Log(LOGNOTICE, "Using visual 0x%x", (unsigned) vInfo->visualid); - if (m_eglConfig == EGL_NO_CONFIG) - { - m_eglConfig = GetEGLConfig(m_eglDisplay, vInfo); - } + m_eglConfig = GetEGLConfig(m_eglDisplay, vInfo); + XFree(vInfo); - if (m_eglConfig == EGL_NO_CONFIG) - { - CLog::Log(LOGERROR, "failed to get eglconfig for visual id"); - XFree(vInfo); - return false; - } + if (m_eglConfig == EGL_NO_CONFIG) + { + CLog::Log(LOGERROR, "failed to get eglconfig for visual id"); + Destroy(); + return false; + } - if (m_eglSurface == EGL_NO_SURFACE) - { - m_eglSurface = eglCreateWindowSurface(m_eglDisplay, m_eglConfig, glWindow, NULL); - if (m_eglSurface == EGL_NO_SURFACE) - { - CLog::Log(LOGERROR, "failed to create EGL window surface %d", eglGetError()); - XFree(vInfo); - return false; - } - } + m_eglSurface = eglCreateWindowSurface(m_eglDisplay, m_eglConfig, glWindow, NULL); + if (m_eglSurface == EGL_NO_SURFACE) + { + CLog::Log(LOGERROR, "failed to create EGL window surface %d", eglGetError()); + Destroy(); + return false; + } - EGLint contextAttributes[] = - { + EGLint contextAttributes[] = + { EGL_CONTEXT_MAJOR_VERSION_KHR, 3, EGL_CONTEXT_MINOR_VERSION_KHR, 2, EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR, EGL_NONE + }; + m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, EGL_NO_CONTEXT, contextAttributes); + if (m_eglContext == EGL_NO_CONTEXT) + { + EGLint contextAttributes[] = + { + EGL_CONTEXT_MAJOR_VERSION_KHR, 2, + EGL_NONE }; m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, EGL_NO_CONTEXT, contextAttributes); + if (m_eglContext == EGL_NO_CONTEXT) { - EGLint contextAttributes[] = - { - EGL_CONTEXT_MAJOR_VERSION_KHR, 2, - EGL_NONE - }; - m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, EGL_NO_CONTEXT, contextAttributes); - - if (m_eglContext == EGL_NO_CONTEXT) - { - CLog::Log(LOGERROR, "failed to create EGL context\n"); - return false; - } + CLog::Log(LOGERROR, "failed to create EGL context\n"); + Destroy(); + return false; + } - CLog::Log(LOGWARNING, "Failed to get an OpenGL context supporting core profile 3.2, \ + CLog::Log(LOGWARNING, "Failed to get an OpenGL context supporting core profile 3.2, \ using legacy mode with reduced feature set"); - } + } - if (!eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext)) - { - CLog::Log(LOGERROR, "Failed to make context current %p %p %p\n", m_eglDisplay, m_eglSurface, m_eglContext); - return false; - } - XFree(vInfo); - retVal = true; + if (!eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext)) + { + CLog::Log(LOGERROR, "Failed to make context current %p %p %p\n", m_eglDisplay, m_eglSurface, m_eglContext); + Destroy(); + return false; + } + + eglGetSyncValuesCHROMIUM = (PFNEGLGETSYNCVALUESCHROMIUMPROC)eglGetProcAddress("eglGetSyncValuesCHROMIUM"); + + m_usePB = false; + return true; +} + +bool CGLContextEGL::CreatePB() +{ + const EGLint configAttribs[] = + { + EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, + EGL_BLUE_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_RED_SIZE, 8, + EGL_DEPTH_SIZE, 8, + EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, + EGL_NONE + }; + + const EGLint pbufferAttribs[] = + { + EGL_WIDTH, 9, + EGL_HEIGHT, 9, + EGL_NONE, + }; + + Destroy(); + + if (eglGetPlatformDisplayEXT) + { + m_eglDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_X11_EXT,(EGLNativeDisplayType)m_dpy, + NULL); } else + m_eglDisplay = eglGetDisplay((EGLNativeDisplayType)m_dpy); + + if (m_eglDisplay == EGL_NO_DISPLAY) + { + CLog::Log(LOGERROR, "failed to get egl display"); + return false; + } + if (!eglInitialize(m_eglDisplay, NULL, NULL)) { - CLog::Log(LOGERROR, "EGL Error: vInfo is NULL!"); + CLog::Log(LOGERROR, "failed to initialize egl\n"); + Destroy(); + return false; + } + if (!eglBindAPI(EGL_OPENGL_API)) + { + CLog::Log(LOGERROR, "failed to initialize egl"); + Destroy(); + return false; } - eglGetSyncValuesCHROMIUM = (PFNEGLGETSYNCVALUESCHROMIUMPROC)eglGetProcAddress("eglGetSyncValuesCHROMIUM"); - return retVal; + EGLint numConfigs; + + eglChooseConfig(m_eglDisplay, configAttribs, &m_eglConfig, 1, &numConfigs); + m_eglSurface = eglCreatePbufferSurface(m_eglDisplay, m_eglConfig, pbufferAttribs); + if (m_eglSurface == EGL_NO_SURFACE) + { + CLog::Log(LOGERROR, "failed to create EGL window surface %d", eglGetError()); + Destroy(); + return false; + } + + m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, EGL_NO_CONTEXT, NULL); + + if (!eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext)) + { + CLog::Log(LOGERROR, "Failed to make context current %p %p %p\n", m_eglDisplay, m_eglSurface, m_eglContext); + Destroy(); + return false; + } + + m_usePB = true; + return true; } void CGLContextEGL::Destroy() @@ -229,6 +281,8 @@ void CGLContextEGL::Destroy() eglTerminate(m_eglDisplay); m_eglDisplay = EGL_NO_DISPLAY; } + + m_eglConfig = EGL_NO_CONFIG; } void CGLContextEGL::Detach() @@ -293,7 +347,7 @@ EGLConfig CGLContextEGL::GetEGLConfig(EGLDisplay eglDisplay, XVisualInfo *vInfo) CLog::Log(LOGERROR, "Failed to query egl configs"); goto Exit; } - for (EGLint i = 0;i < numConfigs;++i) + for (EGLint i = 0; i < numConfigs; ++i) { EGLint value; if (!eglGetConfigAttrib(eglDisplay, eglConfigs[i], EGL_NATIVE_VISUAL_ID, &value)) @@ -322,6 +376,13 @@ void CGLContextEGL::SwapBuffers() if ((m_eglDisplay == EGL_NO_DISPLAY) || (m_eglSurface == EGL_NO_SURFACE)) return; + if (m_usePB) + { + eglSwapBuffers(m_eglDisplay, m_eglSurface); + usleep(20 * 1000); + return; + } + uint64_t ust1, ust2; uint64_t msc1, msc2; uint64_t sbc1, sbc2; @@ -414,7 +475,10 @@ uint64_t CGLContextEGL::GetVblankTiming(uint64_t &msc, uint64_t &interval) uint64_t ret = now - m_sync.ust2; while (ret > interval) + { ret -= interval; + msc++; + } return ret; } diff --git a/xbmc/windowing/X11/GLContextEGL.h b/xbmc/windowing/X11/GLContextEGL.h index 3e81e7fabf..9dbb4bcc3c 100644 --- a/xbmc/windowing/X11/GLContextEGL.h +++ b/xbmc/windowing/X11/GLContextEGL.h @@ -10,6 +10,7 @@ #include "GLContext.h" #include "EGL/egl.h" +#include "EGL/eglext.h" #include "EGL/eglextchromium.h" #include <X11/Xutil.h> @@ -19,6 +20,7 @@ public: explicit CGLContextEGL(Display *dpy); ~CGLContextEGL() override; bool Refresh(bool force, int screen, Window glWindow, bool &newContext) override; + bool CreatePB() override; void Destroy() override; void Detach() override; void SetVSync(bool enable) override; @@ -34,6 +36,7 @@ protected: bool IsSuitableVisual(XVisualInfo *vInfo); EGLConfig GetEGLConfig(EGLDisplay eglDisplay, XVisualInfo *vInfo); PFNEGLGETSYNCVALUESCHROMIUMPROC eglGetSyncValuesCHROMIUM = nullptr; + PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = nullptr; struct Sync { @@ -44,4 +47,6 @@ protected: uint64_t msc2 = 0; uint64_t interval = 0; } m_sync; + + bool m_usePB = false; }; diff --git a/xbmc/windowing/X11/WinEventsX11.cpp b/xbmc/windowing/X11/WinEventsX11.cpp index 09deb7e9bf..dd59d87d55 100644 --- a/xbmc/windowing/X11/WinEventsX11.cpp +++ b/xbmc/windowing/X11/WinEventsX11.cpp @@ -23,6 +23,7 @@ #include "input/mouse/MouseStat.h" #include "input/InputManager.h" #include "ServiceBroker.h" +#include "cores/AudioEngine/Interfaces/AE.h" using namespace KODI::MESSAGING; @@ -291,19 +292,36 @@ bool CWinEventsX11::MessagePump() if (m_display && (xevent.type == m_RREventBase + RRScreenChangeNotify)) { - XRRUpdateConfiguration(&xevent); - if (xevent.xgeneric.serial != serial) + if (xevent.xgeneric.serial == serial) + continue; + + if (m_xrrEventPending) + { m_winSystem.NotifyXRREvent(); - m_xrrEventPending = false; - serial = xevent.xgeneric.serial; + m_xrrEventPending = false; + serial = xevent.xgeneric.serial; + } + continue; } else if (m_display && (xevent.type == m_RREventBase + RRNotify)) { - if (xevent.xgeneric.serial != serial) - m_winSystem.NotifyXRREvent(); - m_xrrEventPending = false; - serial = xevent.xgeneric.serial; + if (xevent.xgeneric.serial == serial) + continue; + + XRRNotifyEvent* rrEvent = reinterpret_cast<XRRNotifyEvent*>(&xevent); + if (rrEvent->subtype == RRNotify_OutputChange) + { + XRROutputChangeNotifyEvent* changeEvent = reinterpret_cast<XRROutputChangeNotifyEvent*>(&xevent); + if (changeEvent->connection == RR_Connected || + changeEvent->connection == RR_Disconnected) + { + m_winSystem.NotifyXRREvent(); + CServiceBroker::GetActiveAE()->DeviceChange(); + serial = xevent.xgeneric.serial; + } + } + continue; } diff --git a/xbmc/windowing/X11/WinSystemX11GLContext.cpp b/xbmc/windowing/X11/WinSystemX11GLContext.cpp index 1980916b42..4432fa5251 100644 --- a/xbmc/windowing/X11/WinSystemX11GLContext.cpp +++ b/xbmc/windowing/X11/WinSystemX11GLContext.cpp @@ -142,6 +142,7 @@ EGLConfig CWinSystemX11GLContext::GetEGLConfig() const bool CWinSystemX11GLContext::SetWindow(int width, int height, bool fullscreen, const std::string &output, int *winstate) { int newwin = 0; + CWinSystemX11::SetWindow(width, height, fullscreen, output, &newwin); if (newwin) { @@ -249,6 +250,11 @@ bool CWinSystemX11GLContext::RefreshGLContext(bool force) if (m_pGLContext) { success = m_pGLContext->Refresh(force, m_screen, m_glWindow, m_newGlContext); + if (!success) + { + success = m_pGLContext->CreatePB(); + m_newGlContext = true; + } return success; } @@ -290,6 +296,12 @@ bool CWinSystemX11GLContext::RefreshGLContext(bool force) return true; } } + else if (gli != "EGL") + { + success = m_pGLContext->CreatePB(); + if (success) + return true; + } } delete m_pGLContext; diff --git a/xbmc/windowing/amlogic/WinSystemAmlogicGLESContext.cpp b/xbmc/windowing/amlogic/WinSystemAmlogicGLESContext.cpp index 96254cb1c7..16f9cde81e 100644 --- a/xbmc/windowing/amlogic/WinSystemAmlogicGLESContext.cpp +++ b/xbmc/windowing/amlogic/WinSystemAmlogicGLESContext.cpp @@ -31,10 +31,8 @@ bool CWinSystemAmlogicGLESContext::InitWindowSystem() return false; } - const EGLint contextAttribs[] = - { - EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE - }; + CEGLAttributesVec contextAttribs; + contextAttribs.Add({{EGL_CONTEXT_CLIENT_VERSION, 2}}); if (!m_pGLContext.CreateContext(contextAttribs)) { diff --git a/xbmc/windowing/android/WinSystemAndroidGLESContext.cpp b/xbmc/windowing/android/WinSystemAndroidGLESContext.cpp index 121900783f..3c504ce121 100644 --- a/xbmc/windowing/android/WinSystemAndroidGLESContext.cpp +++ b/xbmc/windowing/android/WinSystemAndroidGLESContext.cpp @@ -32,10 +32,8 @@ bool CWinSystemAndroidGLESContext::InitWindowSystem() return false; } - const EGLint contextAttribs[] = - { - EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE - }; + CEGLAttributesVec contextAttribs; + contextAttribs.Add({{EGL_CONTEXT_CLIENT_VERSION, 2}}); if (!m_pGLContext.CreateContext(contextAttribs)) { @@ -100,6 +98,11 @@ void CWinSystemAndroidGLESContext::PresentRenderImpl(bool rendered) CXBMCApp::get()->WaitVSync(1000); } +float CWinSystemAndroidGLESContext::GetFrameLatencyAdjustment() +{ + return CXBMCApp::GetFrameLatencyMs(); +} + EGLDisplay CWinSystemAndroidGLESContext::GetEGLDisplay() const { return m_pGLContext.GetEGLDisplay(); diff --git a/xbmc/windowing/android/WinSystemAndroidGLESContext.h b/xbmc/windowing/android/WinSystemAndroidGLESContext.h index e10be6e04d..f674e3dcd9 100644 --- a/xbmc/windowing/android/WinSystemAndroidGLESContext.h +++ b/xbmc/windowing/android/WinSystemAndroidGLESContext.h @@ -31,6 +31,8 @@ public: virtual std::unique_ptr<CVideoSync> GetVideoSync(void *clock) override; + float GetFrameLatencyAdjustment() override; + EGLDisplay GetEGLDisplay() const; EGLSurface GetEGLSurface() const; EGLContext GetEGLContext() const; diff --git a/xbmc/windowing/gbm/CMakeLists.txt b/xbmc/windowing/gbm/CMakeLists.txt index 78c788c158..d0dfd85cbd 100644 --- a/xbmc/windowing/gbm/CMakeLists.txt +++ b/xbmc/windowing/gbm/CMakeLists.txt @@ -5,6 +5,7 @@ set(SOURCES OptionalsReg.cpp DRMLegacy.cpp DRMAtomic.cpp OffScreenModeSetting.cpp + VTUtils.cpp WinSystemGbmEGLContext.cpp) set(HEADERS OptionalsReg.h @@ -14,6 +15,7 @@ set(HEADERS OptionalsReg.h DRMLegacy.h DRMAtomic.h OffScreenModeSetting.h + VTUtils.h WinSystemGbmEGLContext.h) if (OPENGL_FOUND) diff --git a/xbmc/windowing/gbm/VTUtils.cpp b/xbmc/windowing/gbm/VTUtils.cpp new file mode 100644 index 0000000000..cd57f793fb --- /dev/null +++ b/xbmc/windowing/gbm/VTUtils.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2005-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "VTUtils.h" + +#include "platform/MessagePrinter.h" +#include "utils/log.h" +#include "utils/StringUtils.h" + +#include <linux/major.h> +#include <linux/kd.h> +#include <linux/vt.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/sysmacros.h> + +using namespace KODI::WINDOWING::GBM; + +bool CVTUtils::OpenTTY() +{ + m_ttyDevice = ttyname(STDIN_FILENO); + + m_fd.attach(open(m_ttyDevice.c_str(), O_RDWR | O_CLOEXEC)); + if (m_fd < 0) + { + CMessagePrinter::DisplayError(StringUtils::Format("ERROR: failed to open tty: %s", m_ttyDevice)); + CLog::Log(LOGERROR, "CVTUtils::%s - failed to open tty: %s", __FUNCTION__, m_ttyDevice); + return false; + } + + struct stat buf; + if (fstat(m_fd, &buf) == -1 || major(buf.st_rdev) != TTY_MAJOR || minor(buf.st_rdev) == 0) + { + CMessagePrinter::DisplayError(StringUtils::Format("ERROR: %s is not a vt", m_ttyDevice)); + CLog::Log(LOGERROR, "CVTUtils::%s - %s is not a vt", __FUNCTION__, m_ttyDevice); + return false; + } + + int kdMode{-1}; + auto ret = ioctl(m_fd, KDGETMODE, &kdMode); + if (ret) + { + CLog::Log(LOGERROR, "CVTUtils::%s - failed to get VT mode: %s", __FUNCTION__, strerror(errno)); + return false; + } + + if (kdMode != KD_TEXT) + { + CMessagePrinter::DisplayError(StringUtils::Format("ERROR: %s is already in graphics mode, is another display server running?", m_ttyDevice)); + CLog::Log(LOGERROR, "CVTUtils::%s - %s is already in graphics mode, is another display server running?", __FUNCTION__, m_ttyDevice); + return false; + } + + CLog::Log(LOGNOTICE, "CVTUtils::%s - opened tty: %s", __FUNCTION__, m_ttyDevice.c_str()); + + return true; +} diff --git a/xbmc/windowing/gbm/VTUtils.h b/xbmc/windowing/gbm/VTUtils.h new file mode 100644 index 0000000000..42543e5909 --- /dev/null +++ b/xbmc/windowing/gbm/VTUtils.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2005-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "platform/posix/utils/FileHandle.h" + +namespace KODI +{ +namespace WINDOWING +{ +namespace GBM +{ + +class CVTUtils +{ +public: + CVTUtils() = default; + ~CVTUtils() = default; + + bool OpenTTY(); + +private: + KODI::UTILS::POSIX::CFileHandle m_fd; + std::string m_ttyDevice; +}; + +} +} +} diff --git a/xbmc/windowing/gbm/WinSystemGbm.cpp b/xbmc/windowing/gbm/WinSystemGbm.cpp index 800d2481d7..c20d30bff8 100644 --- a/xbmc/windowing/gbm/WinSystemGbm.cpp +++ b/xbmc/windowing/gbm/WinSystemGbm.cpp @@ -73,6 +73,11 @@ CWinSystemGbm::CWinSystemGbm() : bool CWinSystemGbm::InitWindowSystem() { + if (!m_vt.OpenTTY()) + { + return false; + } + m_DRM = std::make_shared<CDRMAtomic>(); if (!m_DRM->InitDrm()) @@ -113,6 +118,9 @@ bool CWinSystemGbm::DestroyWindowSystem() m_GBM->DestroyDevice(); CLog::Log(LOGDEBUG, "CWinSystemGbm::%s - deinitialized DRM", __FUNCTION__); + + m_libinput.reset(); + return true; } diff --git a/xbmc/windowing/gbm/WinSystemGbm.h b/xbmc/windowing/gbm/WinSystemGbm.h index 954e7737df..65119c7684 100644 --- a/xbmc/windowing/gbm/WinSystemGbm.h +++ b/xbmc/windowing/gbm/WinSystemGbm.h @@ -17,6 +17,7 @@ #include "windowing/WinSystem.h" #include "DRMUtils.h" #include "VideoLayerBridge.h" +#include "VTUtils.h" class IDispResource; @@ -79,6 +80,9 @@ protected: XbmcThreads::EndTime m_dispResetTimer; std::unique_ptr<OPTIONALS::CLircContainer, OPTIONALS::delete_CLircContainer> m_lirc; std::unique_ptr<CLibInputHandler> m_libinput; + +private: + CVTUtils m_vt; }; } diff --git a/xbmc/windowing/gbm/WinSystemGbmGLContext.cpp b/xbmc/windowing/gbm/WinSystemGbmGLContext.cpp index cd0a2cadf4..ebc13a59d1 100644 --- a/xbmc/windowing/gbm/WinSystemGbmGLContext.cpp +++ b/xbmc/windowing/gbm/WinSystemGbmGLContext.cpp @@ -123,19 +123,16 @@ bool CWinSystemGbmGLContext::CreateContext() const EGLint glMajor = 3; const EGLint glMinor = 2; - const EGLint contextAttribs[] = { - EGL_CONTEXT_MAJOR_VERSION_KHR, glMajor, - EGL_CONTEXT_MINOR_VERSION_KHR, glMinor, - EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR, - EGL_NONE - }; + CEGLAttributesVec contextAttribs; + contextAttribs.Add({{EGL_CONTEXT_MAJOR_VERSION_KHR, glMajor}, + {EGL_CONTEXT_MINOR_VERSION_KHR, glMinor}, + {EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR}}); if (!m_eglContext.CreateContext(contextAttribs)) { - const EGLint fallbackContextAttribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE - }; + CEGLAttributesVec fallbackContextAttribs; + fallbackContextAttribs.Add({{EGL_CONTEXT_CLIENT_VERSION, 2}}); + if (!m_eglContext.CreateContext(fallbackContextAttribs)) { CLog::Log(LOGERROR, "EGL context creation failed"); diff --git a/xbmc/windowing/gbm/WinSystemGbmGLESContext.cpp b/xbmc/windowing/gbm/WinSystemGbmGLESContext.cpp index b70eba8ca8..864c225e3f 100644 --- a/xbmc/windowing/gbm/WinSystemGbmGLESContext.cpp +++ b/xbmc/windowing/gbm/WinSystemGbmGLESContext.cpp @@ -132,10 +132,9 @@ void CWinSystemGbmGLESContext::PresentRender(bool rendered, bool videoLayer) bool CWinSystemGbmGLESContext::CreateContext() { - const EGLint contextAttribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE - }; + CEGLAttributesVec contextAttribs; + contextAttribs.Add({{EGL_CONTEXT_CLIENT_VERSION, 2}}); + if (!m_eglContext.CreateContext(contextAttribs)) { CLog::Log(LOGERROR, "EGL context creation failed"); diff --git a/xbmc/windowing/rpi/WinSystemRpiGLESContext.cpp b/xbmc/windowing/rpi/WinSystemRpiGLESContext.cpp index e4bb481db5..eb3732f17a 100644 --- a/xbmc/windowing/rpi/WinSystemRpiGLESContext.cpp +++ b/xbmc/windowing/rpi/WinSystemRpiGLESContext.cpp @@ -44,10 +44,8 @@ bool CWinSystemRpiGLESContext::InitWindowSystem() return false; } - const EGLint contextAttribs[] = - { - EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE - }; + CEGLAttributesVec contextAttribs; + contextAttribs.Add({{EGL_CONTEXT_CLIENT_VERSION, 2}}); if (!m_pGLContext.CreateContext(contextAttribs)) { diff --git a/xbmc/windowing/wayland/WinSystemWaylandEGLContextGL.cpp b/xbmc/windowing/wayland/WinSystemWaylandEGLContextGL.cpp index 2f0a08a9f5..9d5f0e3d9e 100644 --- a/xbmc/windowing/wayland/WinSystemWaylandEGLContextGL.cpp +++ b/xbmc/windowing/wayland/WinSystemWaylandEGLContextGL.cpp @@ -53,19 +53,16 @@ bool CWinSystemWaylandEGLContextGL::CreateContext() const EGLint glMajor = 3; const EGLint glMinor = 2; - const EGLint contextAttribs[] = { - EGL_CONTEXT_MAJOR_VERSION_KHR, glMajor, - EGL_CONTEXT_MINOR_VERSION_KHR, glMinor, - EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR, - EGL_NONE - }; + CEGLAttributesVec contextAttribs; + contextAttribs.Add({{EGL_CONTEXT_MAJOR_VERSION_KHR, glMajor}, + {EGL_CONTEXT_MINOR_VERSION_KHR, glMinor}, + {EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR}}); if (!m_eglContext.CreateContext(contextAttribs)) { - const EGLint fallbackContextAttribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE - }; + CEGLAttributesVec fallbackContextAttribs; + fallbackContextAttribs.Add({{EGL_CONTEXT_CLIENT_VERSION, 2}}); + if (!m_eglContext.CreateContext(fallbackContextAttribs)) { CLog::Log(LOGERROR, "EGL context creation failed"); diff --git a/xbmc/windowing/wayland/WinSystemWaylandEGLContextGLES.cpp b/xbmc/windowing/wayland/WinSystemWaylandEGLContextGLES.cpp index 8fff617014..dc7de3e8ab 100644 --- a/xbmc/windowing/wayland/WinSystemWaylandEGLContextGLES.cpp +++ b/xbmc/windowing/wayland/WinSystemWaylandEGLContextGLES.cpp @@ -50,10 +50,9 @@ bool CWinSystemWaylandEGLContextGLES::InitWindowSystem() bool CWinSystemWaylandEGLContextGLES::CreateContext() { - const EGLint contextAttribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE - }; + CEGLAttributesVec contextAttribs; + contextAttribs.Add({{EGL_CONTEXT_CLIENT_VERSION, 2}}); + if (!m_eglContext.CreateContext(contextAttribs)) { CLog::Log(LOGERROR, "EGL context creation failed"); diff --git a/xbmc/windowing/win10/WinEventsWin10.cpp b/xbmc/windowing/win10/WinEventsWin10.cpp index 86c83b511f..506fc7c474 100644 --- a/xbmc/windowing/win10/WinEventsWin10.cpp +++ b/xbmc/windowing/win10/WinEventsWin10.cpp @@ -109,6 +109,8 @@ size_t CWinEventsWin10::GetQueueSize() void CWinEventsWin10::InitEventHandlers(const CoreWindow& window) { + CWinEventsWin10::InitOSKeymap(); + //window->SetPointerCapture(); // window diff --git a/xbmc/windows/GUIWindowLoginScreen.cpp b/xbmc/windows/GUIWindowLoginScreen.cpp index 109ee463ce..71abcc006f 100644 --- a/xbmc/windows/GUIWindowLoginScreen.cpp +++ b/xbmc/windows/GUIWindowLoginScreen.cpp @@ -27,7 +27,6 @@ #include "pvr/PVRManager.h" #include "settings/Settings.h" #include "settings/SettingsComponent.h" -#include "utils/log.h" #include "utils/StringUtils.h" #include "utils/Variant.h" #include "view/ViewState.h" |