diff options
217 files changed, 2006 insertions, 1156 deletions
diff --git a/addons/audioencoder.kodi.builtin.aac/addon.xml b/addons/audioencoder.kodi.builtin.aac/addon.xml index 3515649aa4..14e5007382 100644 --- a/addons/audioencoder.kodi.builtin.aac/addon.xml +++ b/addons/audioencoder.kodi.builtin.aac/addon.xml @@ -13,6 +13,7 @@ <assets> <icon>icon.png</icon> </assets> + <summary lang="be_BY">Кадавальнік AAC Audio</summary> <summary lang="bs_BA">AAC Audio Enkoder</summary> <summary lang="da_DK">AAC Lydindkoder</summary> <summary lang="de_DE">AAC Audio Encoder</summary> @@ -35,8 +36,9 @@ <summary lang="sv_SE">AAC Ljud Encoder</summary> <summary lang="tr_TR">AAC Ses Kodlayıcı</summary> <summary lang="zh_CN">AAC 音频编码器</summary> + <description lang="be_BY">AAC - набор кодакаў, распрацаваны для забеспячэння сціскання, лепшага за MP3, і ёсць палепшанымі версіямі аўдыё MPEG.</description> <description lang="bs_BA">AAC je skupina kodeka dizajnirana da pruži bolje sabijanje od MP3-a, te su poboljšane verzije MPEG audia.</description> - <description lang="da_DK">AAC er et sæt codecs designet til at give bedre komprimering end MP3'er og er forbedrede versioner af MPEG-lyd.</description> + <description lang="da_DK">AAC er et sæt codecs designet til at give bedre komprimering end MP3'er og er forbedrede versioner af MPEG-lyd.</description> <description lang="de_DE">AAC ist eine Sammlung von Codecs mit einer besseren Komprimierung als MP3. Sie sind verbesserte Versionen von MPEG-Audio.</description> <description lang="en_AU">AAC is a set of codecs designed to provide better compression than MP3s, and are improved versions of MPEG audio.</description> <description lang="en_GB">AAC is a set of codecs designed to provide better compression than MP3s, and are improved versions of MPEG audio.</description> @@ -54,7 +56,7 @@ <description lang="pl_PL">AAC to zestaw kodeków zaprojektowanych w celu zapewnienia lepszej kompresji niż pliki MP3, są ulepszonymi wersjami audio MPEG.</description> <description lang="pt_BR">AAC é um conjunto de codecs projetado para fornecer melhor compactação do que MP3s e são versões aprimoradas de áudio MPEG.</description> <description lang="ru_RU">AAC - это набор кодеков, разработанных для обеспечения лучшего сжатия, чем MP3, и являющихся улучшенными версиями аудио MPEG.</description> - <description lang="tr_TR">AAC, MP3'lerden daha iyi sıkıştırma sağlamak üzere tasarlanmış bir dizi codec bileşenleridir ve MPEG sesinin geliştirilmiş sürümleridir.</description> + <description lang="tr_TR">AAC, MP3'lerden daha iyi sıkıştırma sağlamak üzere tasarlanmış bir dizi codec bileşenleridir ve MPEG sesinin geliştirilmiş sürümleridir.</description> <description lang="zh_CN">AAC 是一组编解码器,旨在提供比 MP3 更好的压缩,是 MPEG 音频的改进版本。</description> </extension> </addon> diff --git a/addons/audioencoder.kodi.builtin.aac/resources/language/resource.language.be_by/strings.po b/addons/audioencoder.kodi.builtin.aac/resources/language/resource.language.be_by/strings.po index feee8518bf..a8bc3920c0 100644 --- a/addons/audioencoder.kodi.builtin.aac/resources/language/resource.language.be_by/strings.po +++ b/addons/audioencoder.kodi.builtin.aac/resources/language/resource.language.be_by/strings.po @@ -7,23 +7,23 @@ msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: translations@kodi.tv\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: 2021-08-21 08:38+0000\n" -"Last-Translator: Christian Gade <gade@kodi.tv>\n" +"PO-Revision-Date: 2022-01-27 10:09+0000\n" +"Last-Translator: Antikruk <zmicerturok@gmail.com>\n" "Language-Team: Belarusian <https://kodi.weblate.cloud/projects/kodi-core/audioencoder-kodi-builtin-aac/be_by/>\n" "Language: be_by\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" -"X-Generator: Weblate 4.7.2\n" +"X-Generator: Weblate 4.10.1\n" msgctxt "Addon Summary" msgid "AAC Audio Encoder" -msgstr "" +msgstr "Кадавальнік AAC Audio" msgctxt "Addon Description" msgid "AAC is a set of codecs designed to provide better compression than MP3s, and are improved versions of MPEG audio." -msgstr "" +msgstr "AAC - набор кодакаў, распрацаваны для забеспячэння сціскання, лепшага за MP3, і ёсць палепшанымі версіямі аўдыё MPEG." #. Bitrate to use on for compression #: resources/settings.xml @@ -35,7 +35,7 @@ msgstr "Бітрэйт" #: resources/settings.xml msgctxt "#30001" msgid "Select which bitrate to use for the AAC audio encoder for audio compression." -msgstr "" +msgstr "Абярыце бітрэйт, які трэба выкарыстоўваць для кадавальніка AAC пры сцісканні гуку." #. Value format for with bitrate edited field #: resources/settings.xml diff --git a/addons/audioencoder.kodi.builtin.wma/addon.xml b/addons/audioencoder.kodi.builtin.wma/addon.xml index 653e43ec51..4d319964c8 100644 --- a/addons/audioencoder.kodi.builtin.wma/addon.xml +++ b/addons/audioencoder.kodi.builtin.wma/addon.xml @@ -54,7 +54,7 @@ <description lang="pl_PL">Windows Media Audio, stratny format audio firmy Microsoft.</description> <description lang="pt_BR">Windows Media Audio, o formato de áudio com perdas da Microsoft.</description> <description lang="ru_RU">Windows Media Audio, звуковой формат с потерями от Microsoft.</description> - <description lang="tr_TR">Windows Media Audio, Microsoft'un kayıplı ses biçimi.</description> + <description lang="tr_TR">Windows Media Audio, Microsoft'un kayıplı ses biçimi.</description> <description lang="zh_CN">Windows Media Audio,Microsoft 的有损压缩音频格式。</description> </extension> </addon> diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po index 2b91aa9675..40c0773c28 100644 --- a/addons/resource.language.en_gb/resources/strings.po +++ b/addons/resource.language.en_gb/resources/strings.po @@ -7356,6 +7356,17 @@ msgctxt "#13467" msgid "Unlimited / 1080 (>30Hz)" msgstr "" +#: system/settings/settings.xml +msgctxt "#13468" +msgid "Use AV1 VAAPI" +msgstr "" + +#. Description of setting with label #13468 "Use AV1 VAAPI" +#: system/settings/settings.xml +msgctxt "#13469" +msgid "Enable this option to use hardware acceleration for the AV1 codec. If disabled the CPU will be used instead." +msgstr "" + #empty strings from id 13468 to 13504 #: system/settings/settings.xml @@ -10686,11 +10697,7 @@ msgctxt "#19238" msgid "Loading recordings from clients" msgstr "" -#. label 'starting background tasks' for progress dialog text -#: xbmc/pvr/PVRManager.cpp -msgctxt "#19239" -msgid "Starting background threads" -msgstr "" +#empty string with id 19239 #. label for pvr settings client priorities control and client priorities dialog heading. #: system/settings/settings.xml diff --git a/addons/screensaver.xbmc.builtin.dim/addon.xml b/addons/screensaver.xbmc.builtin.dim/addon.xml index c970e7662e..b192f69e34 100644 --- a/addons/screensaver.xbmc.builtin.dim/addon.xml +++ b/addons/screensaver.xbmc.builtin.dim/addon.xml @@ -16,7 +16,7 @@ <summary lang="bg_BG">Скрийнсейвър, който затъмнява екрана</summary> <summary lang="ca_ES">Estalvi de pantalla que enfosqueix la pantalla</summary> <summary lang="cs_CZ">Spořič obrazovky, který ztmaví vaši obrazovku</summary> - <summary lang="cy_GB">Arbedwr sgrin sy'n pylu eich sgrin</summary> + <summary lang="cy_GB">Arbedwr sgrin sy'n pylu eich sgrin</summary> <summary lang="da_DK">Pauseskærm som dæmper din skærm</summary> <summary lang="de_DE">Bildschirmschoner zum Abdunkeln des Bildschirmes</summary> <summary lang="el_GR">Προφύλαξη οθόνης που σκιάζει την οθόνη σας</summary> @@ -32,7 +32,7 @@ <summary lang="fa_IR">محافظ صفحهای که صفحهتان را تاریک میکند</summary> <summary lang="fi_FI">Näytönsäästäjä, joka himmentää näytön</summary> <summary lang="fr_CA">Un économiseur d’écran qui baisse la luminosité de votre écran</summary> - <summary lang="fr_FR">Un économiseur qui assombrit l'écran</summary> + <summary lang="fr_FR">Un économiseur qui assombrit l'écran</summary> <summary lang="gl_ES">O protector de pantalla atenúa a súa pantalla</summary> <summary lang="he_IL">שומר מסך אשר מעמעם את המסך</summary> <summary lang="hr_HR">Čuvar zaslona koji zatamnjuje vaš zaslon</summary> @@ -69,14 +69,14 @@ <summary lang="vi_VN">Trình bảo vệ màn hình này làm mờ màn hình của bạn</summary> <summary lang="zh_CN">淡出屏幕保护程序</summary> <summary lang="zh_TW">讓螢幕變暗的螢幕保護程式</summary> - <description lang="af_ZA">Die Verdof sluimerskerm is 'n eenvoudige sluimerskerm wat jou skerm verdof (uit vaag) tot 'n stelbare waarde tussen 20 en 100%</description> + <description lang="af_ZA">Die Verdof sluimerskerm is 'n eenvoudige sluimerskerm wat jou skerm verdof (uit vaag) tot 'n stelbare waarde tussen 20 en 100%</description> <description lang="am_ET">የ መመልከቻ ማዳኛ ማደብዘዣ የ እርስዎን መመልከቻ ያፈዘዋል (ማፍዘዣ) የ እርስዎን መመልከቻ ዋጋ በ 20 እና በ 100% መካከል</description> <description lang="ar_SA">Dim عبارة عن شاشة توقف تمكن من تظليم (صورة خافتة) الشاشة إلى قيمة قابلة للتحديد بين 20 و 100%</description> <description lang="be_BY">Dim - просты ахоўнік экрана, які будзе паступова зацямняць экран. Значэнне зацямнення можа змяняцца ад 20 да 100%.</description> <description lang="bg_BG">Скрийнсейвърът "Dim" затъмнява екрана, до стойност, която Вие определяте предварително (между 20 и 100%).</description> - <description lang="ca_ES">L'estalvi de pantalla Dim és un estalvi de pantalla simple que enfosquirà (fos en negre) la seva pantalla a un valor que es pot configurar entre 20 i 100%.</description> + <description lang="ca_ES">L'estalvi de pantalla Dim és un estalvi de pantalla simple que enfosquirà (fos en negre) la seva pantalla a un valor que es pot configurar entre 20 i 100%.</description> <description lang="cs_CZ">Spořič obrazovky Dim je jednoduchý spořič obrazovky, který ztmaví (posupně) vaši obrazovku podle nastavitelné hodnoty mezi 20 a 100 %.</description> - <description lang="cy_GB">Mae arbedwr sgrin Dim yn arbedwr sgrin syml sy'n pylu (tywyllu) eich sgrin i werth gosodadwy rhwyg 20 a 100%.</description> + <description lang="cy_GB">Mae arbedwr sgrin Dim yn arbedwr sgrin syml sy'n pylu (tywyllu) eich sgrin i werth gosodadwy rhwyg 20 a 100%.</description> <description lang="da_DK">Dæmpningspauseskærmen er en simpel pauseskærm, der dæmper (nedtoner) din skærm til en valgfri værdi mellem 20 og 100%.</description> <description lang="de_DE">Der Dimmer-Bildschirmschoner ist ein einfacher Bildschirmschoner, welcher den Bildschirm auf einen benutzerdefinierten Wert zwischen 20 und 100% abdunkelt.</description> <description lang="el_GR">Η προφύλαξη οθόνης Dim είναι μία απλή προφύλαξη η οποία σκιάζει την οθόνη σας σε μία τιμή που μπορεί να ρυθμιστεί μεταξύ 20 και 100%.</description> @@ -92,7 +92,7 @@ <description lang="fa_IR">محافظ صفحهٔ تاریککننده، محافظ صفحهای ساده است که نور صفحهتان را (به صورت تدریجی) تا سطح تعریف شدهای بین ۲۰ تا ۱۰۰٪ کم خواهد کرد.</description> <description lang="fi_FI">Dim on yksinkertainen näytönsäästäjä joka himmentää ruudun valitulle tasolle välillä 20-100%.</description> <description lang="fr_CA">L’économiseur Dim est un économiseur d’écran simple qui abaissera la luminosité de votre écran à une valeur réglable entre 20 à 100 %.</description> - <description lang="fr_FR">L'économiseur Dim est un simple économiseur qui assombrira l'écran. L'assombrissement est paramétrable de 20 à 100 %.</description> + <description lang="fr_FR">L'économiseur Dim est un simple économiseur qui assombrira l'écran. L'assombrissement est paramétrable de 20 à 100 %.</description> <description lang="gl_ES">Este protector de pantalla atenuará a súa pantalla nun valor configurábel entre o 20% e o 100%.</description> <description lang="he_IL">שומר המסך Dim הוא שומר מסך פשוט אשר מעמעם את המסך לערך מוגדר בין 20% ל־100%.</description> <description lang="hr_HR">Dim čuvar zaslona je jednostavan čuvar zaslona koji će zatamniti (postepeno isčeznuti) vaš zaslon na odabranu vrijednost između 20 i 100% .</description> @@ -106,7 +106,7 @@ <description lang="lv_LV">Aptumsuma ekrānsaudzētājs ir vienkāršs ekrānsaudzētājs, kas aptumšo (padara tumšāku) jūsu ekrānu līdz uzstādāmai robežai starp 20 un 100%.</description> <description lang="mk_MK">ДИМ Заштитата на екран е едноставно стемнување на екранот, може да се одбере вредност помеѓу 20 и 100%</description> <description lang="ms_MY">Penyelamat skrin malap adapah penyelamat skrin ringkas yang memalapkan (lenyapkan) skrin anda kepada nilai boleh ditetap diantara 20 hingga 100%.</description> - <description lang="mt_MT">L-iskrinsejver Dim huwa skrinsejver sempliċi li jbaxxilek (bil-mod) il-qawwa tal-iskrin sa valur li tista' tagħżel bejn 20 u 100%.</description> + <description lang="mt_MT">L-iskrinsejver Dim huwa skrinsejver sempliċi li jbaxxilek (bil-mod) il-qawwa tal-iskrin sa valur li tista' tagħżel bejn 20 u 100%.</description> <description lang="my_MM">Dim screensaver သည် ရိုးရှင်းသော Screensaver တစ်ခုဖြစ်သည်။ ၎င်းသည် သင်၏ စခရင် ကို ၂၀% မှ ၁၀၀% အတွင်း မှေးမှိန်သွားအောင်ပြုလုပ်လိမ့်မည်</description> <description lang="nb_NO">Dim er en enkel skjermsparer som dimmer skjermen din til en justerbar verdi mellom 20-100%</description> <description lang="nl_NL">De Dim-schermbeveiliging is een eenvoudige schermbeveiliging die je scherm geleidelijk dimt. Je kunt een waarde van 20 tot 100% instellen.</description> diff --git a/addons/skin.estouchy/addon.xml b/addons/skin.estouchy/addon.xml index 7ceacd1f80..fee4bc8068 100644 --- a/addons/skin.estouchy/addon.xml +++ b/addons/skin.estouchy/addon.xml @@ -84,7 +84,7 @@ <description lang="ar_SA">مظهر للواجهة مصمم للأجهزة التي تعمل باللمس مثل الجوالات الذكية والأجهزة اللوحية</description> <description lang="be_BY">Абалонка распрацаваная для выкарыстання на сэнсарных прыладах, такіх як планшэты і смартфоны</description> <description lang="bg_BG">Обликът е разработен за ползване на устройства със сензорен екран, като таблети и телефони.</description> - <description lang="ca_ES">Aparença dissenyada perquè s'utilitzi en dispositius amb pantalla tàctil com taules i telèfons intel·ligents</description> + <description lang="ca_ES">Aparença dissenyada perquè s'utilitzi en dispositius amb pantalla tàctil com taules i telèfons intel·ligents</description> <description lang="cs_CZ">Vzhled navržený pro použití na zařízeních s dotykovou obrazovkou, jako jsou tablety a chytré telefony</description> <description lang="da_DK">Skin der er designet til brug på berøringsfølsomme enheder som f.eks. tablets og smartphones</description> <description lang="de_DE">Dieser Skin wurde für die Verwendung mit Touchscreen-Geräten, wie Tablets und Handys, entworfen</description> diff --git a/addons/skin.estouchy/language/resource.language.es_es/strings.po b/addons/skin.estouchy/language/resource.language.es_es/strings.po index cb7aa1021f..552ae2fe19 100644 --- a/addons/skin.estouchy/language/resource.language.es_es/strings.po +++ b/addons/skin.estouchy/language/resource.language.es_es/strings.po @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: translations@kodi.tv\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: 2022-01-03 13:36+0000\n" +"PO-Revision-Date: 2022-01-26 11:59+0000\n" "Last-Translator: Alfonso Cachero <alfonso.cachero@gmail.com>\n" "Language-Team: Spanish (Spain) <https://kodi.weblate.cloud/projects/kodi-add-ons-skins/skin-estouchy/es_es/>\n" "Language: es_es\n" @@ -236,7 +236,7 @@ msgstr "Cambiar la skin - Seleccionar idioma y zona - Cambiar opciones de listad msgctxt "#31405" msgid "Configure & manage media sharing services · Configure & manage the weather service" -msgstr "Configurar y gestionar los servicios para compartir contenido · Configurar y gestionar el servicio del Tiempo" +msgstr "Configurar y gestionar los servicios para compartir contenido · Configurar y gestionar el servicio meteorológico" msgctxt "#31406" msgid "Configure display · Configure audio · Configure internet access · Configure power saving· Configure logging" diff --git a/addons/skin.estouchy/media/flagging/aspectratio/1.00.png b/addons/skin.estouchy/media/flagging/aspectratio/1.00.png Binary files differnew file mode 100644 index 0000000000..eb41c15f7f --- /dev/null +++ b/addons/skin.estouchy/media/flagging/aspectratio/1.00.png diff --git a/addons/skin.estouchy/media/flagging/aspectratio/1.19.png b/addons/skin.estouchy/media/flagging/aspectratio/1.19.png Binary files differnew file mode 100644 index 0000000000..80289ae466 --- /dev/null +++ b/addons/skin.estouchy/media/flagging/aspectratio/1.19.png diff --git a/addons/skin.estouchy/media/flagging/aspectratio/2.00.png b/addons/skin.estouchy/media/flagging/aspectratio/2.00.png Binary files differnew file mode 100644 index 0000000000..cd8ff2569f --- /dev/null +++ b/addons/skin.estouchy/media/flagging/aspectratio/2.00.png diff --git a/addons/skin.estuary/addon.xml b/addons/skin.estuary/addon.xml index 9d5f80e46e..675cf67e43 100644 --- a/addons/skin.estuary/addon.xml +++ b/addons/skin.estuary/addon.xml @@ -39,9 +39,9 @@ <summary lang="da_DK">Estuary skin af phil65 (Kodis standard brugerflade)</summary> <summary lang="de_DE">Estuary Skin von phil65. (Kodi-Standardskin)</summary> <summary lang="el_GR">Το κέλυφος Estuary από τον phil65 και τον Pier. (προεπιλεγμένο κέλυφος του Kodi)</summary> - <summary lang="en_GB">Estuary skin by phil65. (Kodi's default skin)</summary> - <summary lang="en_NZ">Estuary skin by phil65 and Piers. (Kodi's default skin)</summary> - <summary lang="en_US">Estuary skin by phil65 and Piers. (Kodi's default skin)</summary> + <summary lang="en_GB">Estuary skin by phil65. (Kodi's default skin)</summary> + <summary lang="en_NZ">Estuary skin by phil65 and Piers. (Kodi's default skin)</summary> + <summary lang="en_US">Estuary skin by phil65 and Piers. (Kodi's default skin)</summary> <summary lang="es_AR">Skin Estuary por phil65 (skin por defecto de Kodi)</summary> <summary lang="es_ES">Skin Estuary, creado por phil65 and Piers (skin por defecto de Kodi).</summary> <summary lang="es_MX">Máscara Estuary por phil65 y Piers. (La máscara predeterminada de Kodi)</summary> @@ -50,7 +50,7 @@ <summary lang="fa_IR">پوستهٔ اسچوری به دست phil65. (پوستهٔ پیشگزیدهٔ کودی)</summary> <summary lang="fi_FI">Estuary on phil65:n luoma Kodin oletusulkoasu</summary> <summary lang="fr_CA">Habillage Estuary par phil65 et Piers (habillage par défaut de Kodi).</summary> - <summary lang="fr_FR">Estuary, un habillage par phil65 et Piers (habillage d'origine de Kodi)</summary> + <summary lang="fr_FR">Estuary, un habillage par phil65 et Piers (habillage d'origine de Kodi)</summary> <summary lang="gl_ES">Pel Estuary por phil65 and Piers. (Pel predefinida do Kodi)</summary> <summary lang="he_IL">מעטפת Estuary של phil65 (ברירת המחדל של קודי)</summary> <summary lang="hr_HR">Estuary presvlaka autora phil65 i Piersa. (uobičajena Kodi presvlaka)</summary> @@ -62,10 +62,10 @@ <summary lang="ko_KR">phil65가 만든 Estuary 스킨. (Kodi 기본 스킨)</summary> <summary lang="lt_LT">Estuary teminė išvaizda, kurią sukūrė phil65 ir Piers. (Numatytoji Kodi teminė išvaizda)</summary> <summary lang="lv_LV">Estuary apvalks no phil65. (Kodi noklusējuma apvalks)</summary> - <summary lang="mk_MK">Estuary skin by phil65. (Kodi's default skin)</summary> + <summary lang="mk_MK">Estuary skin by phil65. (Kodi's default skin)</summary> <summary lang="ms_MY">Kulit Estuary oleh phil65 dan rakan-rakan. (Kulit lalai Kodi)</summary> <summary lang="nb_NO">Esturay-drakt av phil65 og Piers. (Kodis forvalgte drakt)</summary> - <summary lang="nl_NL">Estuary skin door phil65 en Piers. (Kodi's standaardskin)</summary> + <summary lang="nl_NL">Estuary skin door phil65 en Piers. (Kodi's standaardskin)</summary> <summary lang="pl_PL">Skóra Eustary autorstwa phil65. (domyślna skóra Kodi)</summary> <summary lang="pt_BR">Skin Estuary por phil65 e Piers. (Skin padrão do Kodi)</summary> <summary lang="pt_PT">Visual Estuary de phil65 e Piers. (Visual por omissão do Kodi)</summary> @@ -74,10 +74,10 @@ <summary lang="sk_SK">Vzhľad Estuary, vytvorili phil65. (predvolený vzhľad pre Kodi)</summary> <summary lang="sr_RS">Маска Estuary аутора phil65 и Piers. (Подразумевана Коди маска)</summary> <summary lang="sr_RS@latin">Maska Estuary autora phil65 i Piers. (Podrazumevana Kodi maska)</summary> - <summary lang="sv_SE">Estuary, ett skal av phil65. (Kodi's standardskal)</summary> + <summary lang="sv_SE">Estuary, ett skal av phil65. (Kodi's standardskal)</summary> <summary lang="szl">Skōra Estuary ôd phil65 i Piers. (Wychodnŏ skōra Kodi)</summary> <summary lang="th_TH">สกิน Estuary โดย phil65 และ Piers (หน้าตาเริ่มต้นของKodi)</summary> - <summary lang="tr_TR">Estuary dış görünümü. phil65 (Kodi'nin varsayılan dış görünümü)</summary> + <summary lang="tr_TR">Estuary dış görünümü. phil65 (Kodi'nin varsayılan dış görünümü)</summary> <summary lang="uk_UA">Обкладинка Estuary від phil65 і Piers. (стандартна обкладинка Kodi)</summary> <summary lang="vi_VN">Giao diện Estuary của phil65. (Giao diện mặc định của Kodi)</summary> <summary lang="zh_CN">phil65 开发的 Estuary 皮肤(Kodi 的默认皮肤)。</summary> @@ -86,7 +86,7 @@ <description lang="ar_SA">Estuary هو المظهر الافتراضي ل كودي الإصدار 17.0 و أعلى. يطمح بأن يكون سهل الاستخدام والفهم لمستخدمين كودي الجدد.</description> <description lang="be_BY">Estuary - прадвызначаная абалонка для Kodi 17.0 і пазнейшых версій. Яна будзе простай і зразумелай для карыстальнікаў, якія не мелі досведу працы з Kodi.</description> <description lang="bg_BG">Estuary е стандартният облик на Kodi 17 и по-новите версии. Целта е да се улеснят хората, които се сблъскват за първи път с Kodi.</description> - <description lang="ca_ES">Estuary és l'aparença predeterminada de Kodi 17.0 i posteriors. Per als usuaris per primera vegada de Kodi, intenta ser fàcil d'entendre i d'utilitzar.</description> + <description lang="ca_ES">Estuary és l'aparença predeterminada de Kodi 17.0 i posteriors. Per als usuaris per primera vegada de Kodi, intenta ser fàcil d'entendre i d'utilitzar.</description> <description lang="cs_CZ">Estuary je výchozí vzhled pro Kodi 17.0 a vyšší. Snaží se být jednoduše pochopitelný a použitelný pro nové uživatele Kodi.</description> <description lang="da_DK">Estuary er standardbrugerfladen for Kodi 17.0 og højere. Det forenkler førstegangsbrugen af Kodi ved at gøre det nemmere at forstå og bruge.</description> <description lang="de_DE">Estuary ist der Standardskin für Kodi 17.0 und höher. Ziel war es, einen einfach zu bedienenden Skin für neue Kodi-Benutzer zu entwickeln.</description> @@ -102,7 +102,7 @@ <description lang="fa_IR">اسچوری پوستهٔ پیشگزیدهٔ کودی ۱۷٫۰ و بالاتر است. این پوسته تلاش میکند درک و استفادهاش برای کاربرانی که نخستین بار با کودی کار میکنند، ساده باشد.</description> <description lang="fi_FI">Estuary on oletusulkoasu Kodin versiosta 17.0 lähtien. Se pyrkii olemaan helppo ymmärtää ja käyttää Kodin ensikäyttäjille.</description> <description lang="fr_CA">Estuary est l’habillage par défaut pour Kodi 17.0 et ultérieure. Il s’efforce d’être facile à comprendre et à utiliser pour les utilisateurs débutants de Kodi.</description> - <description lang="fr_FR">Estuary est l'habillage d'origine pour Kodi 17.0 et supérieur. Il est facile à comprendre et à utiliser pour les utilisateurs novices de Kodi.</description> + <description lang="fr_FR">Estuary est l'habillage d'origine pour Kodi 17.0 et supérieur. Il est facile à comprendre et à utiliser pour les utilisateurs novices de Kodi.</description> <description lang="gl_ES">Estuary é a pel predefinida para Kodi 17.0 e superior. Esta tenta ser doada de entender e usar polos usuarios recen chegados a Kodi.</description> <description lang="he_IL">Estuary היא מעטפת ברירת המחדל של קודי מגרסאות 17.0 ומעלה. מטרת מעטפת זו היא להיות פשוטה לשימוש ולהכרה ראשונית על ידי משתמשים חדשים.</description> <description lang="hr_HR">Estuary je uobičajena presvlaka za Kodi 17.0 i novije inačice. To je pokušaj da se novim korisnicima olakša prvo korištenje i kasnija upotreba Kodija.</description> @@ -136,7 +136,7 @@ <disclaimer lang="ar_SA">Estuary هو المظهر الافتراضي ل كودي, إزالته قد تسبب بعض المشاكل</disclaimer> <disclaimer lang="be_BY">Estuary - прадвызначаная абалонка для Kodi. Яе выдаленне можа прывесці да праблем</disclaimer> <disclaimer lang="bg_BG">Estuary е стандартният облик на Kodi. Премахването му може да предизвика проблеми</disclaimer> - <disclaimer lang="ca_ES">Estuary és l'aparença predeterminada de Kodi, si s'elimina pot causar problemes.</disclaimer> + <disclaimer lang="ca_ES">Estuary és l'aparença predeterminada de Kodi, si s'elimina pot causar problemes.</disclaimer> <disclaimer lang="cs_CZ">Estuary je výchozí vzhled pro Kodi, jeho odebrání může způsobit problémy</disclaimer> <disclaimer lang="cy_GB">Estuary yw croen diofyn Kodi. Efallai bydd ei dynnu yn achosi problemau</disclaimer> <disclaimer lang="da_DK">Estuary er standard brugerfladen. Fjernes det kan der opstå problemer.</disclaimer> @@ -153,7 +153,7 @@ <disclaimer lang="fa_IR">اسچوری پوستهٔ پیشگزیدهٔ کودی است. ممکن است برداشتنش موجب مشکلاتی شود</disclaimer> <disclaimer lang="fi_FI">Estuary on Kodin oletusulkoasu, sen poisto voi aiheuttaa ongelmia</disclaimer> <disclaimer lang="fr_CA">Estuary est l’habillage par défaut de Kodi, le supprimer peut créer des problèmes</disclaimer> - <disclaimer lang="fr_FR">Estuary est l'habillage d'origine de Kodi, le retirer peut créer des problèmes</disclaimer> + <disclaimer lang="fr_FR">Estuary est l'habillage d'origine de Kodi, le retirer peut créer des problèmes</disclaimer> <disclaimer lang="gl_ES">Estuary é a pel predefinida para Kodi e eliminala pode causar problemas.</disclaimer> <disclaimer lang="he_IL">Estuary היא מעטפת ברירת המחדל של קודי, הסרתה עלולה לגרום לתקלות</disclaimer> <disclaimer lang="hr_HR">Estuary je uobičajena presvlaka za Kodi, njegovim uklanjanjem može uzrokovati poteškoće</disclaimer> diff --git a/addons/skin.estuary/language/resource.language.es_es/strings.po b/addons/skin.estuary/language/resource.language.es_es/strings.po index c7989441fd..e082190ce0 100644 --- a/addons/skin.estuary/language/resource.language.es_es/strings.po +++ b/addons/skin.estuary/language/resource.language.es_es/strings.po @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: translations@kodi.tv\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: 2022-01-03 13:36+0000\n" +"PO-Revision-Date: 2022-01-26 11:59+0000\n" "Last-Translator: Alfonso Cachero <alfonso.cachero@gmail.com>\n" "Language-Team: Spanish (Spain) <https://kodi.weblate.cloud/projects/kodi-add-ons-skins/skin-estuary/es_es/>\n" "Language: es_es\n" @@ -263,7 +263,7 @@ msgstr "Elementos del menú principal" msgctxt "#31062" msgid "Choose weather fanart pack" -msgstr "Elegir pack de fanart para el tiempo" +msgstr "Elegir pack de fanart para la meteorología" msgctxt "#31063" msgid "Sections" @@ -440,11 +440,11 @@ msgstr "No tiene instalado ningún add-on aún. Visite nuestro navegador de add- msgctxt "#31120" msgid "You did not set up a weather provider yet. In order to view weather information, choose a weather provider and set up your location." -msgstr "No ha configurado aún un proveedor de Tiempo. Para poder consultar el Tiempo, elija un proveedor y establezca su ubicación." +msgstr "No ha configurado aún un proveedor de meteorología. Para poder consultar la meteorología, elija un proveedor y establezca su ubicación." msgctxt "#31121" msgid "Set weather provider" -msgstr "Establecer proveedor de Tiempo" +msgstr "Establecer proveedor de meteorología" msgctxt "#31122" msgid "Unwatched TV Shows" diff --git a/addons/skin.estuary/media/flags/aspectratio/1.00.png b/addons/skin.estuary/media/flags/aspectratio/1.00.png Binary files differnew file mode 100644 index 0000000000..eb41c15f7f --- /dev/null +++ b/addons/skin.estuary/media/flags/aspectratio/1.00.png diff --git a/addons/skin.estuary/media/flags/aspectratio/1.19.png b/addons/skin.estuary/media/flags/aspectratio/1.19.png Binary files differnew file mode 100644 index 0000000000..80289ae466 --- /dev/null +++ b/addons/skin.estuary/media/flags/aspectratio/1.19.png diff --git a/addons/skin.estuary/media/flags/aspectratio/2.00.png b/addons/skin.estuary/media/flags/aspectratio/2.00.png Binary files differnew file mode 100644 index 0000000000..cd8ff2569f --- /dev/null +++ b/addons/skin.estuary/media/flags/aspectratio/2.00.png diff --git a/addons/skin.estuary/xml/Home.xml b/addons/skin.estuary/xml/Home.xml index 0a88c6c496..4192e93d67 100644 --- a/addons/skin.estuary/xml/Home.xml +++ b/addons/skin.estuary/xml/Home.xml @@ -391,8 +391,8 @@ <param name="sortorder" value="descending"/> <param name="widget_header" value="$LOCALIZE[31015]"/> <param name="list_id" value="12300"/> - <param name="label" value="$INFO[ListItem.ChannelName]"/> - <param name="label2" value="$INFO[ListItem.Title]$INFO[ListItem.EpisodeName, (,)]"/> + <param name="label" value="$INFO[ListItem.Title]$INFO[ListItem.Date, (,)]"/> + <param name="label2" value="$VAR[SeasonEpisodeLabel]$INFO[ListItem.EpisodeName]"/> </include> <include content="WidgetListPVR" condition="System.HasPVRAddon"> <param name="content_path" value="pvr://timers/tv/timers/?view=hidedisabled"/> @@ -401,8 +401,8 @@ <param name="widget_header" value="$LOCALIZE[19040]"/> <param name="widget_target" value="tvtimers"/> <param name="list_id" value="12400"/> - <param name="label" value="$INFO[ListItem.Date]"/> - <param name="label2" value="$INFO[ListItem.Title]$INFO[ListItem.EpisodeName, (,)] - $INFO[ListItem.ChannelName]"/> + <param name="label" value="$INFO[ListItem.Title]$INFO[ListItem.Date, (,)]"/> + <param name="label2" value="$VAR[SeasonEpisodeLabel]$INFO[ListItem.EpisodeName]"/> </include> <include content="WidgetListPVR" condition="System.HasPVRAddon"> <param name="content_path" value="pvr://channels/tv"/> @@ -458,8 +458,8 @@ <param name="sortorder" value="descending"/> <param name="widget_header" value="$LOCALIZE[31015]"/> <param name="list_id" value="13300"/> - <param name="label" value="$INFO[ListItem.ChannelName]"/> - <param name="label2" value="$INFO[ListItem.Title]$INFO[ListItem.EpisodeName, (,)]"/> + <param name="label" value="$INFO[ListItem.Title]$INFO[ListItem.Date, (,)]"/> + <param name="label2" value="$VAR[SeasonEpisodeLabel]$INFO[ListItem.EpisodeName]"/> </include> <include content="WidgetListPVR" condition="System.HasPVRAddon"> <param name="content_path" value="pvr://timers/radio/timers/?view=hidedisabled"/> @@ -468,8 +468,8 @@ <param name="widget_header" value="$LOCALIZE[19040]"/> <param name="widget_target" value="radiotimers"/> <param name="list_id" value="13400"/> - <param name="label" value="$INFO[ListItem.Date]"/> - <param name="label2" value="$INFO[ListItem.Title]$INFO[ListItem.EpisodeName, (,)] - $INFO[ListItem.ChannelName]"/> + <param name="label" value="$INFO[ListItem.Title]$INFO[ListItem.Date, (,)]"/> + <param name="label2" value="$VAR[SeasonEpisodeLabel]$INFO[ListItem.EpisodeName]"/> </include> <include content="WidgetListPVR" condition="System.HasPVRAddon"> <param name="content_path" value="pvr://channels/radio"/> diff --git a/cmake/modules/FindCrossGUID.cmake b/cmake/modules/FindCrossGUID.cmake index 01ec1a05f9..c8eff40b64 100644 --- a/cmake/modules/FindCrossGUID.cmake +++ b/cmake/modules/FindCrossGUID.cmake @@ -9,7 +9,7 @@ if(ENABLE_INTERNAL_CROSSGUID) if(CROSSGUID_URL) get_filename_component(CROSSGUID_URL "${CROSSGUID_URL}" ABSOLUTE) else() - set(CROSSGUID_URL http://mirrors.kodi.tv/build-deps/sources/${ARCHIVE}) + set(CROSSGUID_URL http://mirrors.kodi.tv/build-deps/sources/${CROSSGUID_ARCHIVE}) endif() if(VERBOSE) message(STATUS "CROSSGUID_URL: ${CROSSGUID_URL}") @@ -23,6 +23,7 @@ if(ENABLE_INTERNAL_CROSSGUID) set(CROSSGUID_INCLUDE_DIR ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/include) externalproject_add(crossguid URL ${CROSSGUID_URL} + URL_HASH ${CROSSGUID_HASH} DOWNLOAD_DIR ${TARBALL_DIR} PREFIX ${CORE_BUILD_DIR}/crossguid CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR} diff --git a/cmake/modules/FindDav1d.cmake b/cmake/modules/FindDav1d.cmake index a5a21b12e5..b417a536b8 100644 --- a/cmake/modules/FindDav1d.cmake +++ b/cmake/modules/FindDav1d.cmake @@ -33,7 +33,7 @@ if(ENABLE_INTERNAL_DAV1D) if(DAV1D_URL) get_filename_component(DAV1D_URL "${DAV1D_URL}" ABSOLUTE) else() - set(DAV1D_URL http://mirrors.kodi.tv/build-deps/sources/${ARCHIVE}) + set(DAV1D_URL http://mirrors.kodi.tv/build-deps/sources/${DAV1D_ARCHIVE}) endif() if(VERBOSE) @@ -46,7 +46,8 @@ if(ENABLE_INTERNAL_DAV1D) externalproject_add(dav1d URL ${DAV1D_URL} - DOWNLOAD_NAME ${ARCHIVE} + URL_HASH ${DAV1D_HASH} + DOWNLOAD_NAME ${DAV1D_ARCHIVE} DOWNLOAD_DIR ${TARBALL_DIR} PREFIX ${CORE_BUILD_DIR}/dav1d CONFIGURE_COMMAND meson diff --git a/cmake/modules/FindFFMPEG.cmake b/cmake/modules/FindFFMPEG.cmake index be77c51024..16c29e5044 100644 --- a/cmake/modules/FindFFMPEG.cmake +++ b/cmake/modules/FindFFMPEG.cmake @@ -33,7 +33,7 @@ # # required ffmpeg library versions -set(REQUIRED_FFMPEG_VERSION 4.4) +set(REQUIRED_FFMPEG_VERSION 4.4.1) set(_avcodec_ver ">=58.134.100") set(_avfilter_ver ">=7.110.100") set(_avformat_ver ">=58.76.100") @@ -250,7 +250,8 @@ if(NOT FFMPEG_FOUND) externalproject_add(ffmpeg URL ${FFMPEG_URL} - DOWNLOAD_NAME ${ARCHIVE} + URL_HASH ${FFMPEG_HASH} + DOWNLOAD_NAME ${FFMPEG_ARCHIVE} DOWNLOAD_DIR ${TARBALL_DIR} PREFIX ${CORE_BUILD_DIR}/ffmpeg CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR} diff --git a/cmake/modules/FindFlatBuffers.cmake b/cmake/modules/FindFlatBuffers.cmake index 4d7a9ba331..8397728066 100644 --- a/cmake/modules/FindFlatBuffers.cmake +++ b/cmake/modules/FindFlatBuffers.cmake @@ -20,7 +20,7 @@ if(ENABLE_INTERNAL_FLATBUFFERS) if(FLATBUFFERS_URL) get_filename_component(FLATBUFFERS_URL "${FLATBUFFERS_URL}" ABSOLUTE) else() - set(FLATBUFFERS_URL http://mirrors.kodi.tv/build-deps/sources/${ARCHIVE}) + set(FLATBUFFERS_URL http://mirrors.kodi.tv/build-deps/sources/${FLATBUFFERS_ARCHIVE}) endif() if(VERBOSE) message(STATUS "FLATBUFFERS_URL: ${FLATBUFFERS_URL}") @@ -31,6 +31,7 @@ if(ENABLE_INTERNAL_FLATBUFFERS) externalproject_add(flatbuffers URL ${FLATBUFFERS_URL} + URL_HASH ${FLATBUFFERS_HASH} DOWNLOAD_DIR ${TARBALL_DIR} PREFIX ${CORE_BUILD_DIR}/flatbuffers CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR} diff --git a/cmake/modules/FindFmt.cmake b/cmake/modules/FindFmt.cmake index d3d66820f8..53affa04e2 100644 --- a/cmake/modules/FindFmt.cmake +++ b/cmake/modules/FindFmt.cmake @@ -23,7 +23,7 @@ if(ENABLE_INTERNAL_FMT) if(FMT_URL) get_filename_component(FMT_URL "${FMT_URL}" ABSOLUTE) else() - set(FMT_URL http://mirrors.kodi.tv/build-deps/sources/${ARCHIVE}) + set(FMT_URL http://mirrors.kodi.tv/build-deps/sources/${LIBFMT_ARCHIVE}) endif() if(VERBOSE) message(STATUS "FMT_URL: ${FMT_URL}") @@ -37,6 +37,7 @@ if(ENABLE_INTERNAL_FMT) set(FMT_INCLUDE_DIR ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/include) externalproject_add(fmt URL ${FMT_URL} + URL_HASH ${FMT_HASH} DOWNLOAD_DIR ${TARBALL_DIR} PREFIX ${CORE_BUILD_DIR}/fmt CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR} diff --git a/cmake/modules/FindFstrcmp.cmake b/cmake/modules/FindFstrcmp.cmake index 038331bf5c..042b9967cc 100644 --- a/cmake/modules/FindFstrcmp.cmake +++ b/cmake/modules/FindFstrcmp.cmake @@ -22,7 +22,7 @@ if(ENABLE_INTERNAL_FSTRCMP) if(FSTRCMP_URL) get_filename_component(FSTRCMP_URL "${FSTRCMP_URL}" ABSOLUTE) else() - set(FSTRCMP_URL http://mirrors.kodi.tv/build-deps/sources/${ARCHIVE}) + set(FSTRCMP_URL http://mirrors.kodi.tv/build-deps/sources/${LIBFSTRCMP_ARCHIVE}) endif() if(VERBOSE) message(STATUS "FSTRCMPURL: ${FSTRCMP_URL}") @@ -32,6 +32,7 @@ if(ENABLE_INTERNAL_FSTRCMP) set(FSTRCMP_INCLUDE_DIR ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/include) externalproject_add(fstrcmp URL ${FSTRCMP_URL} + URL_HASH ${FSTRCMP_HASH} DOWNLOAD_DIR ${TARBALL_DIR} PREFIX ${CORE_BUILD_DIR}/fstrcmp PATCH_COMMAND autoreconf -vif diff --git a/cmake/modules/FindGtest.cmake b/cmake/modules/FindGtest.cmake index f2b7e9fe8a..d3171d1ec2 100644 --- a/cmake/modules/FindGtest.cmake +++ b/cmake/modules/FindGtest.cmake @@ -26,7 +26,7 @@ if(ENABLE_INTERNAL_GTEST) if(GTEST_URL) get_filename_component(GTEST_URL "${GTEST_URL}" ABSOLUTE) else() - set(GTEST_URL http://mirrors.kodi.tv/build-deps/sources/${ARCHIVE}) + set(GTEST_URL http://mirrors.kodi.tv/build-deps/sources/${GTEST_ARCHIVE}) endif() if(VERBOSE) @@ -38,6 +38,7 @@ if(ENABLE_INTERNAL_GTEST) externalproject_add(gtest URL ${GTEST_URL} + URL_HASH ${GTEST_HASH} DOWNLOAD_DIR ${TARBALL_DIR} PREFIX ${CORE_BUILD_DIR}/gtest INSTALL_DIR ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR} diff --git a/cmake/modules/FindLibDvd.cmake b/cmake/modules/FindLibDvd.cmake index 27dfaa2980..71f2cea3b6 100644 --- a/cmake/modules/FindLibDvd.cmake +++ b/cmake/modules/FindLibDvd.cmake @@ -1,3 +1,28 @@ +# Generic externaproject_add call for windows platforms +function(windows_externalprojectadd module_name) + string(TOUPPER ${module_name} DVDLIB) + string(PREPEND DVDLIB "LIB") + ExternalProject_Add(${module_name} + URL ${${DVDLIB}_URL} + URL_HASH ${${DVDLIB}_HASH} + DOWNLOAD_DIR ${TARBALL_DIR} + DOWNLOAD_NAME ${${DVDLIB}_ARCHIVE} + CMAKE_ARGS + ${LIBDVD_ADDITIONAL_ARGS} + -DCMAKE_PREFIX_PATH:PATH=${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd + -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd + ) +endfunction() + +# Generic autoreconf step +function(addstep_autoreconf module_name) + ExternalProject_Add_Step(${module_name} autoreconf + DEPENDEES download update patch + DEPENDERS configure + COMMAND PATH=${NATIVEPREFIX}/bin:$ENV{PATH} autoreconf -vif + WORKING_DIRECTORY <SOURCE_DIR>) +endfunction() + if(KODI_DEPENDSBUILD) set(_dvdlibs dvdread dvdnav) set(_handlevars LIBDVD_INCLUDE_DIRS DVDREAD_LIBRARY DVDNAV_LIBRARY) @@ -43,20 +68,16 @@ if(KODI_DEPENDSBUILD) mark_as_advanced(LIBDVD_INCLUDE_DIRS LIBDVD_LIBRARIES) endif() else() + include(cmake/scripts/common/ModuleHelpers.cmake) + set(dvdlibs libdvdread libdvdnav) if(ENABLE_DVDCSS) list(APPEND dvdlibs libdvdcss) endif() set(DEPENDS_TARGETS_DIR ${CMAKE_SOURCE_DIR}/tools/depends/target) foreach(dvdlib ${dvdlibs}) - file(GLOB VERSION_FILE ${DEPENDS_TARGETS_DIR}/${dvdlib}/DVD*-VERSION) - file(STRINGS ${VERSION_FILE} VER) - string(REGEX MATCH "VERSION=[^ ]*$.*" ${dvdlib}_VER "${VER}") - list(GET ${dvdlib}_VER 0 ${dvdlib}_VER) - string(SUBSTRING "${${dvdlib}_VER}" 8 -1 ${dvdlib}_VER) - string(REGEX MATCH "BASE_URL=([^ ]*)" ${dvdlib}_BASE_URL "${VER}") - list(GET ${dvdlib}_BASE_URL 0 ${dvdlib}_BASE_URL) - string(SUBSTRING "${${dvdlib}_BASE_URL}" 9 -1 ${dvdlib}_BASE_URL) + + get_archive_name(${dvdlib}) string(TOUPPER ${dvdlib} DVDLIB) # allow user to override the download URL with a local tarball @@ -68,7 +89,8 @@ else() if(${DVDLIB}_URL) get_filename_component(${DVDLIB}_URL "${${DVDLIB}_URL}" ABSOLUTE) else() - set(${DVDLIB}_URL ${${dvdlib}_BASE_URL}/archive/${${dvdlib}_VER}.tar.gz) + # github tarball format is tagname.tar.gz where tagname is VERSION in lib VERSION file + set(${DVDLIB}_URL ${${DVDLIB}_BASE_URL}/archive/${${DVDLIB}_VER}.tar.gz) endif() if(VERBOSE) message(STATUS "${DVDLIB}_URL: ${${DVDLIB}_URL}") @@ -78,7 +100,10 @@ else() set(DVDREAD_CFLAGS "${DVDREAD_CFLAGS} -I${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd/include") if(APPLE) - set(CMAKE_LD_FLAGS "-framework IOKit -framework CoreFoundation") + string(APPEND CMAKE_EXE_LINKER_FLAGS "-framework CoreFoundation") + if(NOT CORE_SYSTEM_NAME STREQUAL darwin_embedded) + string(APPEND CMAKE_EXE_LINKER_FLAGS " -framework IOKit") + endif() endif() set(HOST_ARCH ${ARCH}) @@ -110,7 +135,8 @@ else() if(NOT CORE_SYSTEM_NAME MATCHES windows) set(DVDCSS_LIBRARY ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd/lib/libdvdcss.a) ExternalProject_Add(dvdcss URL ${LIBDVDCSS_URL} - DOWNLOAD_NAME libdvdcss-${libdvdcss_VER}.tar.gz + URL_HASH ${LIBDVDCSS_HASH} + DOWNLOAD_NAME ${LIBDVDCSS_ARCHIVE} DOWNLOAD_DIR ${TARBALL_DIR} PREFIX ${CORE_BUILD_DIR}/libdvd CONFIGURE_COMMAND ac_cv_path_GIT= <SOURCE_DIR>/configure @@ -124,23 +150,12 @@ else() --libdir=<INSTALL_DIR>/lib "CC=${CMAKE_C_COMPILER}" "CFLAGS=${CMAKE_C_FLAGS} ${DVDREAD_CFLAGS}" - "LDFLAGS=${CMAKE_LD_FLAGS}" + "LDFLAGS=${CMAKE_EXE_LINKER_FLAGS}" BUILD_COMMAND ${MAKE_COMMAND} BUILD_BYPRODUCTS ${DVDCSS_LIBRARY}) - ExternalProject_Add_Step(dvdcss autoreconf - DEPENDEES download update patch - DEPENDERS configure - COMMAND PATH=${NATIVEPREFIX}/bin:$ENV{PATH} autoreconf -vif - WORKING_DIRECTORY <SOURCE_DIR>) + addstep_autoreconf("dvdcss") else() - ExternalProject_Add(dvdcss - URL ${LIBDVDCSS_URL} - DOWNLOAD_DIR ${TARBALL_DIR} - DOWNLOAD_NAME libdvdcss-${libdvdcss_VER}.tar.gz - CMAKE_ARGS - ${LIBDVD_ADDITIONAL_ARGS} - -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd - ) + windows_externalprojectadd("dvdcss") endif() set_target_properties(dvdcss PROPERTIES FOLDER "External Projects") endif() @@ -153,7 +168,8 @@ else() if(NOT CORE_SYSTEM_NAME MATCHES windows) set(DVDREAD_LIBRARY ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd/lib/libdvdread.a) ExternalProject_Add(dvdread URL ${LIBDVDREAD_URL} - DOWNLOAD_NAME libdvdread-${libdvdread_VER}.tar.gz + URL_HASH ${LIBDVDREAD_HASH} + DOWNLOAD_NAME ${LIBDVDREAD_ARCHIVE} DOWNLOAD_DIR ${TARBALL_DIR} PREFIX ${CORE_BUILD_DIR}/libdvd CONFIGURE_COMMAND ac_cv_path_GIT= <SOURCE_DIR>/configure @@ -166,24 +182,12 @@ else() --libdir=<INSTALL_DIR>/lib "CC=${CMAKE_C_COMPILER}" "CFLAGS=${CMAKE_C_FLAGS} ${DVDREAD_CFLAGS}" - "LDFLAGS=${CMAKE_LD_FLAGS}" + "LDFLAGS=${CMAKE_EXE_LINKER_FLAGS}" BUILD_COMMAND ${MAKE_COMMAND} BUILD_BYPRODUCTS ${DVDREAD_LIBRARY}) - ExternalProject_Add_Step(dvdread autoreconf - DEPENDEES download update patch - DEPENDERS configure - COMMAND PATH=${NATIVEPREFIX}/bin:$ENV{PATH} autoreconf -vif - WORKING_DIRECTORY <SOURCE_DIR>) + addstep_autoreconf("dvdread") else() - ExternalProject_Add(dvdread - URL ${LIBDVDREAD_URL} - DOWNLOAD_DIR ${TARBALL_DIR} - DOWNLOAD_NAME libdvdread-${libdvdread_VER}.tar.gz - CMAKE_ARGS - ${LIBDVD_ADDITIONAL_ARGS} - -DCMAKE_PREFIX_PATH:PATH=${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd - -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd - ) + windows_externalprojectadd("dvdread") endif() if(ENABLE_DVDCSS) add_dependencies(dvdread dvdcss) @@ -198,7 +202,8 @@ else() if(NOT CORE_SYSTEM_NAME MATCHES windows) set(DVDNAV_LIBRARY ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd/lib/libdvdnav.a) ExternalProject_Add(dvdnav URL ${LIBDVDNAV_URL} - DOWNLOAD_NAME libdvdnav-${libdvdnav_VER}.tar.gz + URL_HASH ${LIBDVDNAV_HASH} + DOWNLOAD_NAME ${LIBDVDNAV_ARCHIVE} DOWNLOAD_DIR ${TARBALL_DIR} PREFIX ${CORE_BUILD_DIR}/libdvd CONFIGURE_COMMAND ac_cv_path_GIT= <SOURCE_DIR>/configure @@ -210,29 +215,17 @@ else() --prefix=${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd --libdir=${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd/lib "CC=${CMAKE_C_COMPILER}" - "LDFLAGS=${CMAKE_LD_FLAGS} -L${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd/lib" + "LDFLAGS=${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd/lib" "CFLAGS=${CMAKE_C_FLAGS} ${DVDREAD_CFLAGS}" "DVDREAD_CFLAGS=${DVDREAD_CFLAGS}" "DVDREAD_LIBS=${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd/lib/libdvdread.la" "LIBS=${DVDNAV_LIBS}" BUILD_COMMAND ${MAKE_COMMAND} BUILD_BYPRODUCTS ${DVDNAV_LIBRARY}) - ExternalProject_Add_Step(dvdnav autoreconf - DEPENDEES download update patch - DEPENDERS configure - COMMAND PATH=${NATIVEPREFIX}/bin:$ENV{PATH} autoreconf -vif - WORKING_DIRECTORY <SOURCE_DIR>) + addstep_autoreconf("dvdnav") else() set(DVDNAV_LIBRARY ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd/lib/libdvdnav.lib) - ExternalProject_Add(dvdnav - URL ${LIBDVDNAV_URL} - DOWNLOAD_DIR ${TARBALL_DIR} - DOWNLOAD_NAME libdvdnav-${libdvdnav_VER}.tar.gz - CMAKE_ARGS - ${LIBDVD_ADDITIONAL_ARGS} - -DCMAKE_PREFIX_PATH:PATH=${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd - -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd - ) + windows_externalprojectadd("dvdnav") endif() add_dependencies(dvdnav dvdread) set_target_properties(dvdnav PROPERTIES FOLDER "External Projects") diff --git a/cmake/modules/FindRapidJSON.cmake b/cmake/modules/FindRapidJSON.cmake index 699d325d19..8dcaf658e0 100644 --- a/cmake/modules/FindRapidJSON.cmake +++ b/cmake/modules/FindRapidJSON.cmake @@ -19,7 +19,7 @@ if(ENABLE_INTERNAL_RapidJSON) if(RapidJSON_URL) get_filename_component(RapidJSON_URL "${RapidJSON_URL}" ABSOLUTE) else() - set(RapidJSON_URL http://mirrors.kodi.tv/build-deps/sources/${ARCHIVE}) + set(RapidJSON_URL http://mirrors.kodi.tv/build-deps/sources/${RAPIDJSON_ARCHIVE}) endif() if(VERBOSE) message(STATUS "RapidJSON_URL: ${RapidJSON_URL}") @@ -33,6 +33,7 @@ if(ENABLE_INTERNAL_RapidJSON) set(RapidJSON_INCLUDE_DIR ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/include) externalproject_add(rapidjson URL ${RapidJSON_URL} + URL_HASH ${RAPIDJSON_HASH} DOWNLOAD_DIR ${TARBALL_DIR} PREFIX ${CORE_BUILD_DIR}/rapidjson CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR} diff --git a/cmake/modules/FindSpdlog.cmake b/cmake/modules/FindSpdlog.cmake index aa57d87a78..158d5ff2fa 100644 --- a/cmake/modules/FindSpdlog.cmake +++ b/cmake/modules/FindSpdlog.cmake @@ -25,7 +25,7 @@ if(ENABLE_INTERNAL_SPDLOG) if(SPDLOG_URL) get_filename_component(SPDLOG_URL "${SPDLOG_URL}" ABSOLUTE) else() - set(SPDLOG_URL http://mirrors.kodi.tv/build-deps/sources/${ARCHIVE}) + set(SPDLOG_URL http://mirrors.kodi.tv/build-deps/sources/${LIBSPDLOG_ARCHIVE}) endif() if(VERBOSE) message(STATUS "SPDLOG_URL: ${SPDLOG_URL}") @@ -40,6 +40,7 @@ if(ENABLE_INTERNAL_SPDLOG) externalproject_add(spdlog URL ${SPDLOG_URL} + URL_HASH ${SPDLOG_HASH} DOWNLOAD_DIR ${TARBALL_DIR} PREFIX ${CORE_BUILD_DIR}/spdlog CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR} diff --git a/cmake/modules/FindUdfread.cmake b/cmake/modules/FindUdfread.cmake index 0223a190fc..61fe00d919 100644 --- a/cmake/modules/FindUdfread.cmake +++ b/cmake/modules/FindUdfread.cmake @@ -33,7 +33,7 @@ if(ENABLE_INTERNAL_UDFREAD) if(UDFREAD_URL) get_filename_component(UDFREAD_URL "${UDFREAD_URL}" ABSOLUTE) else() - set(UDFREAD_URL http://mirrors.kodi.tv/build-deps/sources/${ARCHIVE}) + set(UDFREAD_URL http://mirrors.kodi.tv/build-deps/sources/${UDFREAD_ARCHIVE}) endif() if(VERBOSE) @@ -46,7 +46,8 @@ if(ENABLE_INTERNAL_UDFREAD) externalproject_add(udfread URL ${UDFREAD_URL} - DOWNLOAD_NAME libudfread-${UDFREAD_VER}.tar.gz + URL_HASH ${UDFREAD_HASH} + DOWNLOAD_NAME ${UDFREAD_ARCHIVE} DOWNLOAD_DIR ${TARBALL_DIR} PREFIX ${CORE_BUILD_DIR}/libudfread CONFIGURE_COMMAND autoreconf -vif && diff --git a/cmake/scripts/common/ModuleHelpers.cmake b/cmake/scripts/common/ModuleHelpers.cmake index 6dd132fd65..03b623a0b7 100644 --- a/cmake/scripts/common/ModuleHelpers.cmake +++ b/cmake/scripts/common/ModuleHelpers.cmake @@ -23,6 +23,10 @@ function(get_archive_name module_name) file(STRINGS ${${UPPER_MODULE_NAME}_FILE} ${UPPER_MODULE_NAME}_ARCHIVE REGEX "^[ \t]*ARCHIVE=") file(STRINGS ${${UPPER_MODULE_NAME}_FILE} ${UPPER_MODULE_NAME}_BASE_URL REGEX "^[ \t]*BASE_URL=") + # Tarball Hash + file(STRINGS ${${UPPER_MODULE_NAME}_FILE} ${UPPER_MODULE_NAME}_HASH_SHA256 REGEX "^[ \t]*SHA256=") + file(STRINGS ${${UPPER_MODULE_NAME}_FILE} ${UPPER_MODULE_NAME}_HASH_SHA256 REGEX "^[ \t]*SHA512=") + string(REGEX REPLACE ".*LIBNAME=([^ \t]*).*" "\\1" ${UPPER_MODULE_NAME}_LNAME "${${UPPER_MODULE_NAME}_LNAME}") string(REGEX REPLACE ".*VERSION=([^ \t]*).*" "\\1" ${UPPER_MODULE_NAME}_VER "${${UPPER_MODULE_NAME}_VER}") string(REGEX REPLACE ".*ARCHIVE=([^ \t]*).*" "\\1" ${UPPER_MODULE_NAME}_ARCHIVE "${${UPPER_MODULE_NAME}_ARCHIVE}") @@ -31,9 +35,16 @@ function(get_archive_name module_name) string(REGEX REPLACE "\\$\\(LIBNAME\\)" "${${UPPER_MODULE_NAME}_LNAME}" ${UPPER_MODULE_NAME}_ARCHIVE "${${UPPER_MODULE_NAME}_ARCHIVE}") string(REGEX REPLACE "\\$\\(VERSION\\)" "${${UPPER_MODULE_NAME}_VER}" ${UPPER_MODULE_NAME}_ARCHIVE "${${UPPER_MODULE_NAME}_ARCHIVE}") - set(ARCHIVE ${${UPPER_MODULE_NAME}_ARCHIVE} PARENT_SCOPE) + set(${UPPER_MODULE_NAME}_ARCHIVE ${${UPPER_MODULE_NAME}_ARCHIVE} PARENT_SCOPE) set(${UPPER_MODULE_NAME}_VER ${${UPPER_MODULE_NAME}_VER} PARENT_SCOPE) if (${UPPER_MODULE_NAME}_BASE_URL) set(${UPPER_MODULE_NAME}_BASE_URL ${${UPPER_MODULE_NAME}_BASE_URL} PARENT_SCOPE) endif() + + if (${UPPER_MODULE_NAME}_HASH_SHA256) + set(${UPPER_MODULE_NAME}_HASH ${${UPPER_MODULE_NAME}_HASH_SHA256} PARENT_SCOPE) + elseif(${UPPER_MODULE_NAME}_HASH_SHA512) + set(${UPPER_MODULE_NAME}_HASH ${${UPPER_MODULE_NAME}_HASH_SHA512} PARENT_SCOPE) + endif() + endfunction() diff --git a/project/BuildDependencies/scripts/0_package.target-win10-arm.list b/project/BuildDependencies/scripts/0_package.target-win10-arm.list index d099a5ab43..3f62cbbb48 100644 --- a/project/BuildDependencies/scripts/0_package.target-win10-arm.list +++ b/project/BuildDependencies/scripts/0_package.target-win10-arm.list @@ -8,7 +8,7 @@ ;PLEASE KEEP THIS LIST IN ALPHABETICAL ORDER! crossguid-0.2.2-win10-arm-v141-20200105.7z curl-7.67.0-win10-arm-v141-20200105.7z -dav1d-0.7.0-win10-arm-v142-20200529.7z +dav1d-0.8.2-win10-arm-v142-20210314.7z flatbuffers-1.11.0-20200105.7z fmt-6.1.2-win10-arm-v141-20200105.7z freetype-2.10.1-win10-arm-v141-20200105.7z diff --git a/project/BuildDependencies/scripts/0_package.target-win10-win32.list b/project/BuildDependencies/scripts/0_package.target-win10-win32.list index aa151dcd18..9e673128f5 100644 --- a/project/BuildDependencies/scripts/0_package.target-win10-win32.list +++ b/project/BuildDependencies/scripts/0_package.target-win10-win32.list @@ -8,7 +8,7 @@ ;PLEASE KEEP THIS LIST IN ALPHABETICAL ORDER! crossguid-0.2.2-win10-win32-v141-20200105.7z curl-7.67.0-win10-win32-v141-20200105.7z -dav1d-0.7.0-win10-win32-v142-20200529.7z +dav1d-0.8.2-win10-win32-v142-20210314.7z flatbuffers-1.11.0-20200105.7z fmt-6.1.2-win10-win32-v141-20200105.7z freetype-2.10.1-win10-win32-v141-20200105.7z diff --git a/project/BuildDependencies/scripts/0_package.target-win10-x64.list b/project/BuildDependencies/scripts/0_package.target-win10-x64.list index b5fc92a00d..a872f62127 100644 --- a/project/BuildDependencies/scripts/0_package.target-win10-x64.list +++ b/project/BuildDependencies/scripts/0_package.target-win10-x64.list @@ -8,7 +8,7 @@ ;PLEASE KEEP THIS LIST IN ALPHABETICAL ORDER! crossguid-0.2.2-win10-x64-v141-20200105.7z curl-7.67.0-win10-x64-v141-20200105.7z -dav1d-0.7.0-win10-x64-v142-20200529.7z +dav1d-0.8.2-win10-x64-v142-20210314.7z flatbuffers-1.11.0-20200105.7z fmt-6.1.2-win10-x64-v141-20200105.7z freetype-2.10.1-win10-x64-v141-20200105.7z diff --git a/project/BuildDependencies/scripts/0_package.target-win32.list b/project/BuildDependencies/scripts/0_package.target-win32.list index 63908c2b08..b39ade8103 100644 --- a/project/BuildDependencies/scripts/0_package.target-win32.list +++ b/project/BuildDependencies/scripts/0_package.target-win32.list @@ -8,7 +8,7 @@ ;PLEASE KEEP THIS LIST IN ALPHABETICAL ORDER! crossguid-0.2.2-win32-v141-20200105.7z curl-7.67.0-win32-v141-20200105.7z -dav1d-0.7.0-win32-v142-20200529.7z +dav1d-0.8.2-win32-v142-20210314.7z detours-64ec13-win32-v141-20200105.7z dnssd-878.260.1-win32-v141-20200105.7z flatbuffers-1.11.0-20200105.7z diff --git a/project/BuildDependencies/scripts/0_package.target-x64.list b/project/BuildDependencies/scripts/0_package.target-x64.list index 17ad6c221d..30c72eb442 100644 --- a/project/BuildDependencies/scripts/0_package.target-x64.list +++ b/project/BuildDependencies/scripts/0_package.target-x64.list @@ -8,7 +8,7 @@ ;PLEASE KEEP THIS LIST IN ALPHABETICAL ORDER! crossguid-0.2.2-x64-v141-20200105.7z curl-7.67.0-x64-v141-20200105.7z -dav1d-0.7.0-x64-v142-20200529.7z +dav1d-0.8.2-x64-v142-20210314.7z detours-64ec13-x64-v141-20200105.7z dnssd-878.260.1-x64-v141-20200105.7z flatbuffers-1.11.0-20200105.7z diff --git a/system/settings/linux.xml b/system/settings/linux.xml index 1f729fc60f..531974f3f4 100644 --- a/system/settings/linux.xml +++ b/system/settings/linux.xml @@ -137,6 +137,18 @@ <default>true</default> <control type="toggle" /> </setting> + <setting id="videoplayer.usevaapiav1" type="boolean" parent="videoplayer.usevaapi" label="13468" help="13469"> + <requirement>HAVE_LIBVA</requirement> + <visible>false</visible> + <dependencies> + <dependency type="enable"> + <condition setting="videoplayer.usevaapi" operator="is">true</condition> + </dependency> + </dependencies> + <level>3</level> + <default>true</default> + <control type="toggle" /> + </setting> <setting id="videoplayer.prefervaapirender" type="boolean" parent="videoplayer.usevaapi" label="13457" help="36433"> <requirement>HAVE_LIBVA</requirement> <visible>false</visible> diff --git a/tools/android/packaging/xbmc/res/values-be-rby/strings.xml b/tools/android/packaging/xbmc/res/values-be-rby/strings.xml index efe0a1d8ee..98c0e7122c 100644 --- a/tools/android/packaging/xbmc/res/values-be-rby/strings.xml +++ b/tools/android/packaging/xbmc/res/values-be-rby/strings.xml @@ -1,3 +1,4 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - </resources>
\ No newline at end of file + <string name="suggestion_channel">Прапановы</string> +</resources>
\ No newline at end of file diff --git a/tools/buildsteps/windows/patches/0001-ffmpeg-windows-configure-detect-openssl.patch b/tools/buildsteps/windows/patches/0001-ffmpeg-windows-configure-detect-openssl.patch index 1c17b29491..b8e5b2f7e1 100644 --- a/tools/buildsteps/windows/patches/0001-ffmpeg-windows-configure-detect-openssl.patch +++ b/tools/buildsteps/windows/patches/0001-ffmpeg-windows-configure-detect-openssl.patch @@ -11,7 +11,7 @@ diff --git a/configure b/configure index d7a3f507e8..4b85e881b1 100755 --- a/configure +++ b/configure -@@ -6529,6 +6529,8 @@ enabled openssl && { check_pkg_config openssl openssl openssl/ssl.h OP +@@ -6530,6 +6530,8 @@ enabled openssl && { check_pkg_config openssl openssl openssl/ssl.h OP check_lib openssl openssl/ssl.h SSL_library_init -lssl -lcrypto || check_lib openssl openssl/ssl.h SSL_library_init -lssl32 -leay32 || check_lib openssl openssl/ssl.h SSL_library_init -lssl -lcrypto -lws2_32 -lgdi32 || diff --git a/tools/buildsteps/windows/patches/0003-ffmpeg-windows-configure-allow-building-static.patch b/tools/buildsteps/windows/patches/0003-ffmpeg-windows-configure-allow-building-static.patch index f6fbd3fe3e..bbb3e0a9f6 100644 --- a/tools/buildsteps/windows/patches/0003-ffmpeg-windows-configure-allow-building-static.patch +++ b/tools/buildsteps/windows/patches/0003-ffmpeg-windows-configure-allow-building-static.patch @@ -11,7 +11,7 @@ diff --git a/configure b/configure index da457705d1..e3a8f45ff4 100755 --- a/configure +++ b/configure -@@ -5439,6 +5439,8 @@ case $target_os in +@@ -5440,6 +5440,8 @@ case $target_os in enabled shared && ! enabled small && test_cmd $windres --version && enable gnu_windres enabled x86_32 && check_ldflags -Wl,--large-address-aware shlibdir_default="$bindir_default" @@ -20,7 +20,7 @@ index da457705d1..e3a8f45ff4 100755 SLIBPREF="" SLIBSUF=".dll" SLIBNAME_WITH_VERSION='$(SLIBPREF)$(FULLNAME)-$(LIBVERSION)$(SLIBSUF)' -@@ -5488,6 +5490,8 @@ case $target_os in +@@ -5489,6 +5491,8 @@ case $target_os in fi enabled x86_32 && check_ldflags -LARGEADDRESSAWARE shlibdir_default="$bindir_default" diff --git a/tools/buildsteps/windows/patches/0004-ffmpeg-windows-configure-detect-libdav1d.patch b/tools/buildsteps/windows/patches/0004-ffmpeg-windows-configure-detect-libdav1d.patch index d949b57854..617c87a8b0 100644 --- a/tools/buildsteps/windows/patches/0004-ffmpeg-windows-configure-detect-libdav1d.patch +++ b/tools/buildsteps/windows/patches/0004-ffmpeg-windows-configure-detect-libdav1d.patch @@ -11,7 +11,7 @@ diff --git a/configure b/configure index e3a8f45ff4..983d7e1078 100755 --- a/configure +++ b/configure -@@ -6357,7 +6357,7 @@ enabled libcelt && require libcelt celt/celt.h celt_decode -lcelt0 && +@@ -6358,7 +6358,7 @@ enabled libcelt && require libcelt celt/celt.h celt_decode -lcelt0 && die "ERROR: libcelt must be installed and version must be >= 0.11.0."; } enabled libcaca && require_pkg_config libcaca caca caca.h caca_create_canvas enabled libcodec2 && require libcodec2 codec2/codec2.h codec2_create -lcodec2 diff --git a/tools/depends/README.md b/tools/depends/README.md index 2e5db17886..64fb3f0aa1 100644 --- a/tools/depends/README.md +++ b/tools/depends/README.md @@ -48,9 +48,9 @@ Paths below are examples. If you want to build Kodi, follow our **[build guides] ### Linux **ARM (codesourcery/lenaro/etc)** -`./configure --with-toolchain=/opt/toolchains/my-example-toolchain/ --prefix=/opt/xbmc-deps --host=arm-linux-gnueabi` +`./configure --with-toolchain=/opt/toolchains/my-example-toolchain/ --prefix=/opt/xbmc-deps --host=arm-linux-gnueabi --with-rendersystem=gles` **Native** -`./configure --with-toolchain=/usr --prefix=/opt/xbmc-deps --host=x86_64-linux-gnu` +`./configure --with-toolchain=/usr --prefix=/opt/xbmc-deps --host=x86_64-linux-gnu --with-rendersystem=gl` Cross compiling is a PITA. diff --git a/tools/depends/configure.ac b/tools/depends/configure.ac index 0a741a187c..341fe395de 100644 --- a/tools/depends/configure.ac +++ b/tools/depends/configure.ac @@ -504,9 +504,9 @@ if test -z $use_tarballs; then use_tarballs=$prefix/xbmc-tarballs fi -if test -n "$app_rendersystem"; then +if test "$platform_os" == "linux"; then if test "$app_rendersystem" != "gl" && test "$app_rendersystem" != "gles"; then - AC_MSG_ERROR(Rendersystem must be gl or gles) + AC_MSG_ERROR(Rendersystem is required for linux - must be gl or gles) fi fi diff --git a/tools/depends/target/Toolchain_binaddons.cmake.in b/tools/depends/target/Toolchain_binaddons.cmake.in index bc2521b9ce..6b9ce80620 100644 --- a/tools/depends/target/Toolchain_binaddons.cmake.in +++ b/tools/depends/target/Toolchain_binaddons.cmake.in @@ -83,11 +83,11 @@ set(CMAKE_CXX_FLAGS_RELEASE "@platform_cxxflags_release@ @platform_includes@") set(CMAKE_C_FLAGS_DEBUG "@platform_cflags_debug@ @platform_includes@") set(CMAKE_CXX_FLAGS_DEBUG "@platform_cxxflags_debug@ @platform_includes@") set(CMAKE_CPP_FLAGS "@platform_cflags@ @platform_includes@") -set(CMAKE_LD_FLAGS "@platform_ldflags@") +set(CMAKE_EXE_LINKER_FLAGS "@platform_ldflags@") set(ENV{CFLAGS} ${CMAKE_C_FLAGS}) set(ENV{CXXFLAGS} ${CMAKE_CXX_FLAGS}) set(ENV{CPPFLAGS} ${CMAKE_CPP_FLAGS}) -set(ENV{LDFLAGS} ${CMAKE_LD_FLAGS}) +set(ENV{LDFLAGS} ${CMAKE_EXE_LINKER_FLAGS}) # search for programs in the build host directories set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # for libraries and headers in the target directories diff --git a/tools/depends/target/crossguid/CROSSGUID-VERSION b/tools/depends/target/crossguid/CROSSGUID-VERSION index dc16e8e0e5..ce42659a85 100644 --- a/tools/depends/target/crossguid/CROSSGUID-VERSION +++ b/tools/depends/target/crossguid/CROSSGUID-VERSION @@ -1,3 +1,4 @@ LIBNAME=crossguid VERSION=8f399e8bd4 ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz +SHA512=2682d63609d3dcdfcd8136be632e45df26ad88ce93b9c49745cf728bbd2e6254a7b05c8b059ab581d532372e504206a525a52564b64d076dfdae9c965a09fd16 diff --git a/tools/depends/target/dav1d/DAV1D-VERSION b/tools/depends/target/dav1d/DAV1D-VERSION index 2f9f91f2eb..ddaaa2af9e 100644 --- a/tools/depends/target/dav1d/DAV1D-VERSION +++ b/tools/depends/target/dav1d/DAV1D-VERSION @@ -1,3 +1,4 @@ LIBNAME=dav1d VERSION=0.9.2 ARCHIVE=$(LIBNAME)-$(VERSION).tar.bz2 +SHA512=adfb822734a3fc8b73e9cf5f757bfd78fb144b00d95f1e942254c5caf1d801b05438d39571486ef37a94d2226166937fc56160a862e8d6d45c4f6d790531dc3f diff --git a/tools/depends/target/ffmpeg/FFMPEG-VERSION b/tools/depends/target/ffmpeg/FFMPEG-VERSION index 6a44db8f0f..2c9eda8750 100644 --- a/tools/depends/target/ffmpeg/FFMPEG-VERSION +++ b/tools/depends/target/ffmpeg/FFMPEG-VERSION @@ -1,4 +1,5 @@ LIBNAME=ffmpeg BASE_URL=https://github.com/xbmc/FFmpeg -VERSION=4.4-N-Alpha1 +VERSION=4.4.1-Nexus-Alpha1 ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz +SHA512=8beb04d577b5251e74b0d52f4d130997a8ba94bbd488c7c8309e6b45095c27807e150212888ce3a384b23dff52f8df1a7bde5407bae924ddc363f8125c0616c5 diff --git a/tools/depends/target/flatbuffers/FLATBUFFERS-VERSION b/tools/depends/target/flatbuffers/FLATBUFFERS-VERSION index 1d983d6159..4d05761cfa 100644 --- a/tools/depends/target/flatbuffers/FLATBUFFERS-VERSION +++ b/tools/depends/target/flatbuffers/FLATBUFFERS-VERSION @@ -1,3 +1,4 @@ LIBNAME=flatbuffers VERSION=2.0.0 ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz +SHA512=26a06b572c0e4c9685743bd2d2162ac7dcd74b9324624cc3f3ef5b154c0cee7c52a04b77cdc184245d2d6ae38dfdcc4fd66001c318aa8ca001d2bf1d85d66a89 diff --git a/tools/depends/target/googletest/GOOGLETEST-VERSION b/tools/depends/target/googletest/GOOGLETEST-VERSION index af9cb9d2ae..baa73efc7f 100644 --- a/tools/depends/target/googletest/GOOGLETEST-VERSION +++ b/tools/depends/target/googletest/GOOGLETEST-VERSION @@ -1,3 +1,4 @@ LIBNAME=googletest VERSION=1.10.0 ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz +SHA512=bd52abe938c3722adc2347afad52ea3a17ecc76730d8d16b065e165bc7477d762bce0997a427131866a89f1001e3f3315198204ffa5d643a9355f1f4d0d7b1a9 diff --git a/tools/depends/target/libdvdcss/DVDCSS-VERSION b/tools/depends/target/libdvdcss/DVDCSS-VERSION deleted file mode 100644 index 43afb9b093..0000000000 --- a/tools/depends/target/libdvdcss/DVDCSS-VERSION +++ /dev/null @@ -1,4 +0,0 @@ -LIBNAME=libdvdcss -BASE_URL=https://github.com/xbmc/libdvdcss -VERSION=1.4.2-Leia-Beta-5 - diff --git a/tools/depends/target/libdvdcss/LIBDVDCSS-VERSION b/tools/depends/target/libdvdcss/LIBDVDCSS-VERSION new file mode 100644 index 0000000000..ea216b313c --- /dev/null +++ b/tools/depends/target/libdvdcss/LIBDVDCSS-VERSION @@ -0,0 +1,5 @@ +LIBNAME=libdvdcss +BASE_URL=https://github.com/xbmc/libdvdcss +VERSION=1.4.2-Leia-Beta-5 +ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz +SHA512=5185dbdbeb1bd13ea9d8723f1f4ab599d6f3102f5ba1096cd085aa1cda252c045f327c719227bba8e1b742352ade5e335106c8d0c1637a5a6b93ce661620dd7e diff --git a/tools/depends/target/libdvdcss/Makefile b/tools/depends/target/libdvdcss/Makefile index a5026227c2..caa51bb3da 100644 --- a/tools/depends/target/libdvdcss/Makefile +++ b/tools/depends/target/libdvdcss/Makefile @@ -1,6 +1,6 @@ -include ../../Makefile.include -include DVDCSS-VERSION -DEPS= DVDCSS-VERSION Makefile +include LIBDVDCSS-VERSION +DEPS= LIBDVDCSS-VERSION Makefile ifeq ($(CROSS_COMPILING), yes) DEPS += ../../Makefile.include diff --git a/tools/depends/target/libdvdnav/DVDNAV-VERSION b/tools/depends/target/libdvdnav/DVDNAV-VERSION deleted file mode 100644 index 818cf066a3..0000000000 --- a/tools/depends/target/libdvdnav/DVDNAV-VERSION +++ /dev/null @@ -1,4 +0,0 @@ -LIBNAME=libdvdnav -BASE_URL=https://github.com/xbmc/libdvdnav -VERSION=6.0.0-Leia-Alpha-3 - diff --git a/tools/depends/target/libdvdnav/LIBDVDNAV-VERSION b/tools/depends/target/libdvdnav/LIBDVDNAV-VERSION new file mode 100644 index 0000000000..bea00de9bd --- /dev/null +++ b/tools/depends/target/libdvdnav/LIBDVDNAV-VERSION @@ -0,0 +1,5 @@ +LIBNAME=libdvdnav +BASE_URL=https://github.com/xbmc/libdvdnav +VERSION=6.0.0-Leia-Alpha-3 +ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz +SHA512=11c93eaacd156f8fd7dec7c43d366438b201f31ad55b2870463a9e286912b6ada08882319a021fb7992190f87b909a49f2b83e0321cc17aedc29f7fe5898fa72 diff --git a/tools/depends/target/libdvdnav/Makefile b/tools/depends/target/libdvdnav/Makefile index eada58a160..62385a3049 100644 --- a/tools/depends/target/libdvdnav/Makefile +++ b/tools/depends/target/libdvdnav/Makefile @@ -1,6 +1,6 @@ -include ../../Makefile.include -include DVDNAV-VERSION -DEPS = DVDNAV-VERSION Makefile +include LIBDVDNAV-VERSION +DEPS = LIBDVDNAV-VERSION Makefile # configuration settings config = --prefix=$(PREFIX) --disable-shared --enable-static --with-pic diff --git a/tools/depends/target/libdvdread/DVDREAD-VERSION b/tools/depends/target/libdvdread/DVDREAD-VERSION deleted file mode 100644 index eea4c74c74..0000000000 --- a/tools/depends/target/libdvdread/DVDREAD-VERSION +++ /dev/null @@ -1,4 +0,0 @@ -LIBNAME=libdvdread -BASE_URL=https://github.com/xbmc/libdvdread -VERSION=6.0.0-Leia-Alpha-3 - diff --git a/tools/depends/target/libdvdread/LIBDVDREAD-VERSION b/tools/depends/target/libdvdread/LIBDVDREAD-VERSION new file mode 100644 index 0000000000..bf60a8c850 --- /dev/null +++ b/tools/depends/target/libdvdread/LIBDVDREAD-VERSION @@ -0,0 +1,5 @@ +LIBNAME=libdvdread +BASE_URL=https://github.com/xbmc/libdvdread +VERSION=6.0.0-Leia-Alpha-3 +ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz +SHA512=b3419ba0a1a2dd70f1bb6236afdfe1c6e88c9ad4264198b289e3bba9375e077cecf7f89848c7b09debaa445327f3507101f3d157e692f7a7163b2bb52643e1e7 diff --git a/tools/depends/target/libdvdread/Makefile b/tools/depends/target/libdvdread/Makefile index d240953fe4..2a2bf32ceb 100644 --- a/tools/depends/target/libdvdread/Makefile +++ b/tools/depends/target/libdvdread/Makefile @@ -1,6 +1,6 @@ -include ../../Makefile.include -include DVDREAD-VERSION -DEPS = DVDREAD-VERSION Makefile +include LIBDVDREAD-VERSION +DEPS = LIBDVDREAD-VERSION Makefile # configuration settings config = --prefix=$(PREFIX) --disable-shared --enable-static --with-pic --with-libdvdcss diff --git a/tools/depends/target/libfmt/LIBFMT-VERSION b/tools/depends/target/libfmt/LIBFMT-VERSION index f55e9c1f79..0a69a8a7e7 100644 --- a/tools/depends/target/libfmt/LIBFMT-VERSION +++ b/tools/depends/target/libfmt/LIBFMT-VERSION @@ -1,3 +1,4 @@ LIBNAME=fmt VERSION=8.0.1 ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz +SHA512=643e68d5b2e0e9c83231ab2b0036596a6297b1d9ed6bd7b1172bee4ff134c8af8f09174c06c94225132c1b635b0977ea4ce783748d7bd76a9a0b5ad597456c84 diff --git a/tools/depends/target/libfstrcmp/LIBFSTRCMP-VERSION b/tools/depends/target/libfstrcmp/LIBFSTRCMP-VERSION index 40ff7c4ab5..87b85918ae 100644 --- a/tools/depends/target/libfstrcmp/LIBFSTRCMP-VERSION +++ b/tools/depends/target/libfstrcmp/LIBFSTRCMP-VERSION @@ -1,3 +1,4 @@ LIBNAME=fstrcmp VERSION=0.7.D001 ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz +SHA512=aaeb0227afd5ada5955cbe6a565254ff88d2028d677d199c00e03b7cb5de1f2c69b18e6e8b032e452350a8eda7081807b01765adbeb8476eaf803d9de6e5509c diff --git a/tools/depends/target/libspdlog/LIBSPDLOG-VERSION b/tools/depends/target/libspdlog/LIBSPDLOG-VERSION index 46a5037af0..afefe203d5 100644 --- a/tools/depends/target/libspdlog/LIBSPDLOG-VERSION +++ b/tools/depends/target/libspdlog/LIBSPDLOG-VERSION @@ -1,3 +1,4 @@ LIBNAME=spdlog VERSION=1.9.2 ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz +SHA512=87b12a792cf2d740ef29db4b6055788a487b6d474662b878711b8a5534efea5f0d97b6ac357834500b66cc65e1ba8934446a695e9691fd5d4b95397b6871555c diff --git a/tools/depends/target/libudfread/LIBUDFREAD-VERSION b/tools/depends/target/libudfread/LIBUDFREAD-VERSION index 53446a22ab..b5f96528ad 100644 --- a/tools/depends/target/libudfread/LIBUDFREAD-VERSION +++ b/tools/depends/target/libudfread/LIBUDFREAD-VERSION @@ -1,3 +1,4 @@ LIBNAME=libudfread VERSION=1.1.2 ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz +SHA512=340a03fe90d26a8a5c78e1e4f558a0b448a14332a661494f44af7de3e6c98cd219125e19f69d2a611ecb4870648a5d5b55d794e665eb8ec4192c0b499a0701ed diff --git a/tools/depends/target/rapidjson/RAPIDJSON-VERSION b/tools/depends/target/rapidjson/RAPIDJSON-VERSION index 8440f69ac0..120e868fca 100644 --- a/tools/depends/target/rapidjson/RAPIDJSON-VERSION +++ b/tools/depends/target/rapidjson/RAPIDJSON-VERSION @@ -1,3 +1,4 @@ LIBNAME=rapidjson VERSION=1.1.0 ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz +SHA512=2e82a4bddcd6c4669541f5945c2d240fb1b4fdd6e239200246d3dd50ce98733f0a4f6d3daa56f865d8c88779c036099c52a9ae85d47ad263686b68a88d832dff diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp index cc517af9ce..4386f6ff7c 100644 --- a/xbmc/Application.cpp +++ b/xbmc/Application.cpp @@ -909,7 +909,7 @@ void CApplication::OnSettingAction(const std::shared_ptr<const CSetting>& settin if (CServiceBroker::GetAddonMgr().GetAddon( CServiceBroker::GetSettingsComponent()->GetSettings()->GetString( CSettings::SETTING_SCREENSAVER_MODE), - addon, ADDON_SCREENSAVER, OnlyEnabled::YES)) + addon, ADDON_SCREENSAVER, OnlyEnabled::CHOICE_YES)) CGUIDialogAddonSettings::ShowForAddon(addon); } else if (settingId == CSettings::SETTING_AUDIOCDS_SETTINGS) @@ -918,7 +918,7 @@ void CApplication::OnSettingAction(const std::shared_ptr<const CSetting>& settin if (CServiceBroker::GetAddonMgr().GetAddon( CServiceBroker::GetSettingsComponent()->GetSettings()->GetString( CSettings::SETTING_AUDIOCDS_ENCODER), - addon, ADDON_AUDIOENCODER, OnlyEnabled::YES)) + addon, ADDON_AUDIOENCODER, OnlyEnabled::CHOICE_YES)) CGUIDialogAddonSettings::ShowForAddon(addon); } else if (settingId == CSettings::SETTING_VIDEOSCREEN_GUICALIBRATION) @@ -989,8 +989,8 @@ void CApplication::ReloadSkin(bool confirm/*=false*/) user as to whether they want to keep the current skin. */ if (confirm && m_confirmSkinChange) { - if (HELPERS::ShowYesNoDialogText(CVariant{13123}, CVariant{13111}, CVariant{""}, CVariant{""}, 10000) != - DialogResponse::YES) + if (HELPERS::ShowYesNoDialogText(CVariant{13123}, CVariant{13111}, CVariant{""}, CVariant{""}, + 10000) != DialogResponse::CHOICE_YES) { m_confirmSkinChange = false; settings->SetString(CSettings::SETTING_LOOKANDFEEL_SKIN, oldSkin); @@ -1057,7 +1057,7 @@ bool CApplication::LoadSkin(const std::string& skinID) SkinPtr skin; { AddonPtr addon; - if (!CServiceBroker::GetAddonMgr().GetAddon(skinID, addon, ADDON_SKIN, OnlyEnabled::YES)) + if (!CServiceBroker::GetAddonMgr().GetAddon(skinID, addon, ADDON_SKIN, OnlyEnabled::CHOICE_YES)) return false; skin = std::static_pointer_cast<ADDON::CSkinInfo>(addon); } @@ -1316,8 +1316,16 @@ bool CApplication::LoadCustomWindows() if (StringUtils::EqualsNoCase(strType, "dialog")) { + DialogModalityType modality = DialogModalityType::MODAL; hasVisibleCondition = pRootElement->FirstChildElement("visible") != nullptr; - pWindow = new CGUIDialog(windowId, skinFile); + // By default dialogs that have visible conditions are considered modeless unless explicitly + // set to "modal" by the skinner using the "modality" attribute in the root XML element of the window + if (hasVisibleCondition && + (!pRootElement->Attribute("modality") || + !StringUtils::EqualsNoCase(pRootElement->Attribute("modality"), "modal"))) + modality = DialogModalityType::MODELESS; + + pWindow = new CGUIDialog(windowId, skinFile, modality); } else if (StringUtils::EqualsNoCase(strType, "submenu")) { @@ -2655,7 +2663,7 @@ bool CApplication::PlayMedia(CFileItem& item, const std::string &player, int iPl { AddonPtr addon; if (CServiceBroker::GetAddonMgr().GetAddon(path.GetHostName(), addon, ADDON_GAMEDLL, - OnlyEnabled::YES)) + OnlyEnabled::CHOICE_YES)) { CFileItem addonItem(addon); return PlayFile(addonItem, player, false); @@ -3618,7 +3626,7 @@ void CApplication::ActivateScreenSaver(bool forceType /*= false */) return; } else if (CServiceBroker::GetAddonMgr().GetAddon(m_screensaverIdInUse, m_pythonScreenSaver, - ADDON_SCREENSAVER, OnlyEnabled::YES)) + ADDON_SCREENSAVER, OnlyEnabled::CHOICE_YES)) { std::string libPath = m_pythonScreenSaver->LibPath(); if (CScriptInvocationManager::GetInstance().HasLanguageInvoker(libPath)) @@ -4052,7 +4060,7 @@ void CApplication::ConfigureAndEnableAddons() { if (HELPERS::ShowYesNoDialogLines(CVariant{24039}, // Disabled add-ons CVariant{24059}, // Would you like to enable this add-on? - CVariant{addon->Name()}) == DialogResponse::YES) + CVariant{addon->Name()}) == DialogResponse::CHOICE_YES) { if (addon->HasSettings()) { diff --git a/xbmc/Autorun.cpp b/xbmc/Autorun.cpp index bc2de7965c..000dc2073a 100644 --- a/xbmc/Autorun.cpp +++ b/xbmc/Autorun.cpp @@ -508,9 +508,10 @@ bool CAutorun::IsEnabled() const bool CAutorun::PlayDiscAskResume(const std::string& path) { - return PlayDisc(path, true, !CanResumePlayDVD(path) || - HELPERS::ShowYesNoDialogText(CVariant{341}, CVariant{""}, CVariant{13404}, CVariant{12021}) == - DialogResponse::YES); + return PlayDisc(path, true, + !CanResumePlayDVD(path) || + HELPERS::ShowYesNoDialogText(CVariant{341}, CVariant{""}, CVariant{13404}, + CVariant{12021}) == DialogResponse::CHOICE_YES); } bool CAutorun::CanResumePlayDVD(const std::string& path) diff --git a/xbmc/ContextMenuItem.cpp b/xbmc/ContextMenuItem.cpp index cf7794309b..a6c92657da 100644 --- a/xbmc/ContextMenuItem.cpp +++ b/xbmc/ContextMenuItem.cpp @@ -48,7 +48,7 @@ bool CContextMenuItem::Execute(const CFileItemPtr& item) const ADDON::AddonPtr addon; if (!CServiceBroker::GetAddonMgr().GetAddon(m_addonId, addon, ADDON::ADDON_UNKNOWN, - ADDON::OnlyEnabled::YES)) + ADDON::OnlyEnabled::CHOICE_YES)) return false; bool reuseLanguageInvoker = false; diff --git a/xbmc/ContextMenuManager.cpp b/xbmc/ContextMenuManager.cpp index 77ebdcc885..3b8441a49d 100644 --- a/xbmc/ContextMenuManager.cpp +++ b/xbmc/ContextMenuManager.cpp @@ -121,7 +121,7 @@ void CContextMenuManager::OnEvent(const ADDON::AddonEvent& event) else if (typeid(event) == typeid(AddonEvents::Enabled)) { AddonPtr addon; - if (m_addonMgr.GetAddon(event.id, addon, ADDON_CONTEXT_ITEM, OnlyEnabled::YES)) + if (m_addonMgr.GetAddon(event.id, addon, ADDON_CONTEXT_ITEM, OnlyEnabled::CHOICE_YES)) { CSingleLock lock(m_criticalSection); auto items = std::static_pointer_cast<CContextMenuAddon>(addon)->GetItems(); diff --git a/xbmc/GUIInfoManager.cpp b/xbmc/GUIInfoManager.cpp index c28bc0ed0d..553c91424e 100644 --- a/xbmc/GUIInfoManager.cpp +++ b/xbmc/GUIInfoManager.cpp @@ -5844,11 +5844,14 @@ const infomap container_str[] = {{ "property", CONTAINER_PROPERTY }, /// \anchor ListItem_VideoAspect /// _string_, /// @return The aspect ratio of the currently selected video. Possible values: +/// - <b>1.00</b> +/// - <b>1.19</b> /// - <b>1.33</b> /// - <b>1.37</b> /// - <b>1.66</b> /// - <b>1.78</b> /// - <b>1.85</b> +/// - <b>2.00</b> /// - <b>2.20</b> /// - <b>2.35</b> /// - <b>2.40</b> diff --git a/xbmc/LangInfo.cpp b/xbmc/LangInfo.cpp index 24f0419cfe..20a5c3e5b5 100644 --- a/xbmc/LangInfo.cpp +++ b/xbmc/LangInfo.cpp @@ -662,7 +662,7 @@ LanguageResourcePtr CLangInfo::GetLanguageAddon(const std::string& locale /* = " ADDON::AddonPtr addon; if (CServiceBroker::GetAddonMgr().GetAddon(addonId, addon, ADDON::ADDON_RESOURCE_LANGUAGE, - ADDON::OnlyEnabled::YES) && + ADDON::OnlyEnabled::CHOICE_YES) && addon != NULL) return std::dynamic_pointer_cast<ADDON::CLanguageResource>(addon); @@ -687,7 +687,8 @@ bool CLangInfo::SetLanguage(std::string language /* = "" */, bool reloadServices ADDON::AddonPtr addon; // Find the chosen language add-on if it's enabled - if (!addonMgr.GetAddon(language, addon, ADDON::ADDON_RESOURCE_LANGUAGE, ADDON::OnlyEnabled::YES)) + if (!addonMgr.GetAddon(language, addon, ADDON::ADDON_RESOURCE_LANGUAGE, + ADDON::OnlyEnabled::CHOICE_YES)) { if (!addonMgr.IsAddonInstalled(language) || (addonMgr.IsAddonDisabled(language) && !addonMgr.EnableAddon(language))) @@ -701,7 +702,7 @@ bool CLangInfo::SetLanguage(std::string language /* = "" */, bool reloadServices ->GetDefault(); if (!addonMgr.GetAddon(language, addon, ADDON::ADDON_RESOURCE_LANGUAGE, - ADDON::OnlyEnabled::NO)) + ADDON::OnlyEnabled::CHOICE_NO)) { CLog::Log(LOGFATAL, "CLangInfo::{}: could not find default language add-on '{}'", __func__, language); diff --git a/xbmc/addons/AddonInstaller.cpp b/xbmc/addons/AddonInstaller.cpp index 4a80be261c..8756329870 100644 --- a/xbmc/addons/AddonInstaller.cpp +++ b/xbmc/addons/AddonInstaller.cpp @@ -160,7 +160,7 @@ bool CAddonInstaller::InstallModal(const std::string& addonID, return false; // we assume that addons that are enabled don't get to this routine (i.e. that GetAddon() has been called) - if (CServiceBroker::GetAddonMgr().GetAddon(addonID, addon, ADDON_UNKNOWN, OnlyEnabled::NO)) + if (CServiceBroker::GetAddonMgr().GetAddon(addonID, addon, ADDON_UNKNOWN, OnlyEnabled::CHOICE_NO)) return false; // addon is installed but disabled, and the user has specifically activated something that needs // the addon - should we enable it? @@ -171,19 +171,20 @@ bool CAddonInstaller::InstallModal(const std::string& addonID, return false; // if specified ask the user if he wants it installed - if (promptForInstall == InstallModalPrompt::PROMPT) + if (promptForInstall == InstallModalPrompt::CHOICE_YES) { - if (HELPERS::ShowYesNoDialogLines(CVariant{24076}, CVariant{24100}, CVariant{addon->Name()}, CVariant{24101}) != - DialogResponse::YES) + if (HELPERS::ShowYesNoDialogLines(CVariant{24076}, CVariant{24100}, CVariant{addon->Name()}, + CVariant{24101}) != DialogResponse::CHOICE_YES) { return false; } } - if (!InstallOrUpdate(addonID, BackgroundJob::NO, ModalJob::YES)) + if (!InstallOrUpdate(addonID, BackgroundJob::CHOICE_NO, ModalJob::CHOICE_YES)) return false; - return CServiceBroker::GetAddonMgr().GetAddon(addonID, addon, ADDON_UNKNOWN, OnlyEnabled::YES); + return CServiceBroker::GetAddonMgr().GetAddon(addonID, addon, ADDON_UNKNOWN, + OnlyEnabled::CHOICE_YES); } @@ -196,22 +197,23 @@ bool CAddonInstaller::InstallOrUpdate(const std::string& addonID, if (!CAddonInstallJob::GetAddon(addonID, repo, addon)) return false; - return DoInstall(addon, repo, background, modal, AutoUpdateJob::NO, DependencyJob::NO, - AllowCheckForUpdates::YES); + return DoInstall(addon, repo, background, modal, AutoUpdateJob::CHOICE_NO, + DependencyJob::CHOICE_NO, AllowCheckForUpdates::CHOICE_YES); } bool CAddonInstaller::InstallOrUpdateDependency(const ADDON::AddonPtr& dependsId, const ADDON::RepositoryPtr& repo) { - return DoInstall(dependsId, repo, BackgroundJob::NO, ModalJob::NO, AutoUpdateJob::NO, - DependencyJob::YES, AllowCheckForUpdates::YES); + return DoInstall(dependsId, repo, BackgroundJob::CHOICE_NO, ModalJob::CHOICE_NO, + AutoUpdateJob::CHOICE_NO, DependencyJob::CHOICE_YES, + AllowCheckForUpdates::CHOICE_YES); } bool CAddonInstaller::RemoveDependency(const std::shared_ptr<IAddon>& dependsId) const { bool removeData = CDirectory::Exists("special://profile/addon_data/" + dependsId->ID()); CAddonUnInstallJob removeDependencyJob(dependsId, removeData); - removeDependencyJob.SetRecurseOrphaned(RecurseOrphaned::NO); + removeDependencyJob.SetRecurseOrphaned(RecurseOrphaned::CHOICE_NO); return removeDependencyJob.DoWork(); } @@ -256,11 +258,13 @@ bool CAddonInstaller::Install(const std::string& addonId, return false; AddonPtr repo; - if (!CServiceBroker::GetAddonMgr().GetAddon(repoId, repo, ADDON_REPOSITORY, OnlyEnabled::YES)) + if (!CServiceBroker::GetAddonMgr().GetAddon(repoId, repo, ADDON_REPOSITORY, + OnlyEnabled::CHOICE_YES)) return false; - return DoInstall(addon, std::static_pointer_cast<CRepository>(repo), BackgroundJob::YES, - ModalJob::NO, AutoUpdateJob::NO, DependencyJob::NO, AllowCheckForUpdates::YES); + return DoInstall(addon, std::static_pointer_cast<CRepository>(repo), BackgroundJob::CHOICE_YES, + ModalJob::CHOICE_NO, AutoUpdateJob::CHOICE_NO, DependencyJob::CHOICE_NO, + AllowCheckForUpdates::CHOICE_YES); } bool CAddonInstaller::DoInstall(const AddonPtr& addon, @@ -277,7 +281,7 @@ bool CAddonInstaller::DoInstall(const AddonPtr& addon, return false; CAddonInstallJob* installJob = new CAddonInstallJob(addon, repo, autoUpdate); - if (background == BackgroundJob::YES) + if (background == BackgroundJob::CHOICE_YES) { // Workaround: because CAddonInstallJob is blocking waiting for other jobs, it needs to be run // with priority dedicated. @@ -296,7 +300,7 @@ bool CAddonInstaller::DoInstall(const AddonPtr& addon, installJob->SetAllowCheckForUpdates(allowCheckForUpdates); bool result = false; - if (modal == ModalJob::YES) + if (modal == ModalJob::CHOICE_YES) result = installJob->DoModal(); else result = installJob->DoWork(); @@ -336,8 +340,9 @@ bool CAddonInstaller::InstallFromZip(const std::string &path) AddonPtr addon; if (CServiceBroker::GetAddonMgr().LoadAddonDescription(items[0]->GetPath(), addon)) - return DoInstall(addon, RepositoryPtr(), BackgroundJob::YES, ModalJob::NO, AutoUpdateJob::NO, - DependencyJob::NO, AllowCheckForUpdates::YES); + return DoInstall(addon, RepositoryPtr(), BackgroundJob::CHOICE_YES, ModalJob::CHOICE_NO, + AutoUpdateJob::CHOICE_NO, DependencyJob::CHOICE_NO, + AllowCheckForUpdates::CHOICE_YES); if (eventLog) eventLog->AddWithNotification(EventPtr( @@ -381,7 +386,7 @@ bool CAddonInstaller::CheckDependencies(const AddonPtr &addon, bool optional = it.optional; AddonPtr dep; bool haveInstalledAddon = - CServiceBroker::GetAddonMgr().GetAddon(addonID, dep, ADDON_UNKNOWN, OnlyEnabled::NO); + CServiceBroker::GetAddonMgr().GetAddon(addonID, dep, ADDON_UNKNOWN, OnlyEnabled::CHOICE_NO); if ((haveInstalledAddon && !dep->MeetsVersion(versionMin, version)) || (!haveInstalledAddon && !optional)) { @@ -491,8 +496,8 @@ void CAddonInstaller::InstallAddons(const VECADDONS& addons, AddonPtr toInstall; RepositoryPtr repo; if (CAddonInstallJob::GetAddon(addon->ID(), repo, toInstall)) - DoInstall(toInstall, repo, BackgroundJob::NO, ModalJob::NO, AutoUpdateJob::YES, - DependencyJob::NO, allowCheckForUpdates); + DoInstall(toInstall, repo, BackgroundJob::CHOICE_NO, ModalJob::CHOICE_NO, + AutoUpdateJob::CHOICE_YES, DependencyJob::CHOICE_NO, allowCheckForUpdates); } if (wait) { @@ -534,8 +539,8 @@ CAddonInstallJob::CAddonInstallJob(const AddonPtr& addon, : m_addon(addon), m_repo(repo), m_isAutoUpdate(isAutoUpdate) { AddonPtr dummy; - m_isUpdate = - CServiceBroker::GetAddonMgr().GetAddon(addon->ID(), dummy, ADDON_UNKNOWN, OnlyEnabled::NO); + m_isUpdate = CServiceBroker::GetAddonMgr().GetAddon(addon->ID(), dummy, ADDON_UNKNOWN, + OnlyEnabled::CHOICE_NO); } bool CAddonInstallJob::GetAddon(const std::string& addonID, RepositoryPtr& repo, @@ -546,7 +551,7 @@ bool CAddonInstallJob::GetAddon(const std::string& addonID, RepositoryPtr& repo, AddonPtr tmp; if (!CServiceBroker::GetAddonMgr().GetAddon(addon->Origin(), tmp, ADDON_REPOSITORY, - OnlyEnabled::YES)) + OnlyEnabled::CHOICE_YES)) return false; repo = std::static_pointer_cast<CRepository>(tmp); @@ -706,7 +711,7 @@ bool CAddonInstallJob::DoWork() if (!CServiceBroker::GetAddonMgr().LoadAddon(m_addon->ID(), m_addon->Origin(), m_addon->Version()) || !CServiceBroker::GetAddonMgr().GetAddon(m_addon->ID(), m_addon, ADDON_UNKNOWN, - OnlyEnabled::YES)) + OnlyEnabled::CHOICE_YES)) { CLog::Log(LOGERROR, "CAddonInstallJob[{}]: failed to reload addon", m_addon->ID()); return false; @@ -732,7 +737,7 @@ bool CAddonInstallJob::DoWork() // if a repository is updated during the add-on migration process, we need to skip // calling CheckForUpdates() on the repo to prevent deadlock issues during migration - if (m_allowCheckForUpdates == AllowCheckForUpdates::YES) + if (m_allowCheckForUpdates == AllowCheckForUpdates::CHOICE_YES) { if (m_isUpdate) { @@ -754,7 +759,7 @@ bool CAddonInstallJob::DoWork() CServiceBroker::GetAddonMgr().SetAddonOrigin(m_addon->ID(), origin, m_isUpdate); - if (m_dependsInstall == DependencyJob::YES) + if (m_dependsInstall == DependencyJob::CHOICE_YES) { CLog::Log(LOGDEBUG, "ADDONS: dependency [{}] will not be version checked and unpinned", m_addon->ID()); @@ -837,14 +842,14 @@ bool CAddonInstallJob::DoWork() bool notify = (CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool( CSettings::SETTING_ADDONS_NOTIFICATIONS) || - m_isAutoUpdate == AutoUpdateJob::NO) && - !IsModal() && m_dependsInstall == DependencyJob::NO; + m_isAutoUpdate == AutoUpdateJob::CHOICE_NO) && + !IsModal() && m_dependsInstall == DependencyJob::CHOICE_NO; auto eventLog = CServiceBroker::GetEventLog(); if (eventLog) eventLog->Add(EventPtr(new CAddonManagementEvent(m_addon, m_isUpdate ? 24065 : 24084)), notify, false); - if (m_isAutoUpdate == AutoUpdateJob::YES && + if (m_isAutoUpdate == AutoUpdateJob::CHOICE_YES && m_addon->LifecycleState() == AddonLifecycleState::BROKEN) { CLog::Log(LOGDEBUG, "CAddonInstallJob[{}]: auto-disabling due to being marked as broken", @@ -965,7 +970,7 @@ bool CAddonInstallJob::Install(const std::string &installFrom, const RepositoryP bool optional = it->optional; AddonPtr dependency; bool haveInstalledAddon = - addonMgr.GetAddon(addonID, dependency, ADDON_UNKNOWN, OnlyEnabled::NO); + addonMgr.GetAddon(addonID, dependency, ADDON_UNKNOWN, OnlyEnabled::CHOICE_NO); if ((haveInstalledAddon && !dependency->MeetsVersion(versionMin, version)) || (!haveInstalledAddon && !optional)) { @@ -1022,8 +1027,9 @@ bool CAddonInstallJob::Install(const std::string &installFrom, const RepositoryP if (IsModal()) { - CAddonInstallJob dependencyJob(dependencyToInstall, repoForDep, AutoUpdateJob::NO); - dependencyJob.SetDependsInstall(DependencyJob::YES); + CAddonInstallJob dependencyJob(dependencyToInstall, repoForDep, + AutoUpdateJob::CHOICE_NO); + dependencyJob.SetDependsInstall(DependencyJob::CHOICE_YES); // pass our progress indicators to the temporary job and don't allow it to // show progress or information updates (no progress, title or text changes) @@ -1086,8 +1092,8 @@ void CAddonInstallJob::ReportInstallError(const std::string& addonID, const std: if (addon != NULL) { AddonPtr addon2; - bool success = - CServiceBroker::GetAddonMgr().GetAddon(addonID, addon2, ADDON_UNKNOWN, OnlyEnabled::YES); + bool success = CServiceBroker::GetAddonMgr().GetAddon(addonID, addon2, ADDON_UNKNOWN, + OnlyEnabled::CHOICE_YES); if (msg.empty()) { msg = g_localizeStrings.Get(addon2 != nullptr && success ? 113 : 114); @@ -1156,7 +1162,7 @@ bool CAddonUnInstallJob::DoWork() ADDON::OnPostUnInstall(m_addon); - if (m_recurseOrphaned == RecurseOrphaned::YES) + if (m_recurseOrphaned == RecurseOrphaned::CHOICE_YES) { const auto removedItems = CAddonInstaller::GetInstance().RemoveOrphanedDepsRecursively(); diff --git a/xbmc/addons/AddonInstaller.h b/xbmc/addons/AddonInstaller.h index 4bd3bd8f27..8140e12239 100644 --- a/xbmc/addons/AddonInstaller.h +++ b/xbmc/addons/AddonInstaller.h @@ -28,44 +28,44 @@ class CAddonDatabase; enum class BackgroundJob : bool { - YES = true, - NO = false, + CHOICE_YES = true, + CHOICE_NO = false, }; enum class ModalJob : bool { - YES = true, - NO = false, + CHOICE_YES = true, + CHOICE_NO = false, }; enum class AutoUpdateJob : bool { - YES = true, - NO = false, + CHOICE_YES = true, + CHOICE_NO = false, }; enum class DependencyJob : bool { - YES = true, - NO = false, + CHOICE_YES = true, + CHOICE_NO = false, }; enum class InstallModalPrompt : bool { - PROMPT = true, - NO_PROMPT = false, + CHOICE_YES = true, + CHOICE_NO = false, }; enum class AllowCheckForUpdates : bool { - YES = true, - NO = false, + CHOICE_YES = true, + CHOICE_NO = false, }; enum class RecurseOrphaned : bool { - YES = true, - NO = false, + CHOICE_YES = true, + CHOICE_NO = false, }; class CAddonInstaller : public IJobCallback @@ -281,8 +281,8 @@ private: ADDON::RepositoryPtr m_repo; bool m_isUpdate; AutoUpdateJob m_isAutoUpdate; - DependencyJob m_dependsInstall = DependencyJob::NO; - AllowCheckForUpdates m_allowCheckForUpdates = AllowCheckForUpdates::YES; + DependencyJob m_dependsInstall = DependencyJob::CHOICE_NO; + AllowCheckForUpdates m_allowCheckForUpdates = AllowCheckForUpdates::CHOICE_YES; const char* m_currentType = TYPE_DOWNLOAD; }; @@ -299,7 +299,7 @@ private: ADDON::AddonPtr m_addon; bool m_removeData; - RecurseOrphaned m_recurseOrphaned = RecurseOrphaned::YES; + RecurseOrphaned m_recurseOrphaned = RecurseOrphaned::CHOICE_YES; }; }; // namespace ADDON diff --git a/xbmc/addons/AddonManager.cpp b/xbmc/addons/AddonManager.cpp index 7c25f14658..bdccec229a 100644 --- a/xbmc/addons/AddonManager.cpp +++ b/xbmc/addons/AddonManager.cpp @@ -123,7 +123,7 @@ bool CAddonMgr::Init() for (const auto& id : m_systemAddons) { AddonPtr addon; - if (!GetAddon(id, addon, ADDON_UNKNOWN, OnlyEnabled::YES)) + if (!GetAddon(id, addon, ADDON_UNKNOWN, OnlyEnabled::CHOICE_YES)) { CLog::Log(LOGFATAL, "addon '{}' not installed or not enabled.", id); return false; @@ -301,7 +301,8 @@ bool CAddonMgr::HasAvailableUpdates() std::vector<std::shared_ptr<IAddon>> CAddonMgr::GetOrphanedDependencies() const { std::vector<std::shared_ptr<IAddon>> allAddons; - GetAddonsInternal(ADDON_UNKNOWN, allAddons, OnlyEnabled::YES, CheckIncompatible::YES); + GetAddonsInternal(ADDON_UNKNOWN, allAddons, OnlyEnabled::CHOICE_YES, + CheckIncompatible::CHOICE_YES); std::vector<std::shared_ptr<IAddon>> orphanedDependencies; for (const auto& addon : allAddons) @@ -333,27 +334,30 @@ bool CAddonMgr::IsOrphaned(const std::shared_ptr<IAddon>& addon, bool CAddonMgr::GetAddonsForUpdate(VECADDONS& addons) const { - return GetAddonsInternal(ADDON_UNKNOWN, addons, OnlyEnabled::YES, CheckIncompatible::YES); + return GetAddonsInternal(ADDON_UNKNOWN, addons, OnlyEnabled::CHOICE_YES, + CheckIncompatible::CHOICE_YES); } bool CAddonMgr::GetAddons(VECADDONS& addons) const { - return GetAddonsInternal(ADDON_UNKNOWN, addons, OnlyEnabled::YES, CheckIncompatible::NO); + return GetAddonsInternal(ADDON_UNKNOWN, addons, OnlyEnabled::CHOICE_YES, + CheckIncompatible::CHOICE_NO); } bool CAddonMgr::GetAddons(VECADDONS& addons, const TYPE& type) { - return GetAddonsInternal(type, addons, OnlyEnabled::YES, CheckIncompatible::NO); + return GetAddonsInternal(type, addons, OnlyEnabled::CHOICE_YES, CheckIncompatible::CHOICE_NO); } bool CAddonMgr::GetInstalledAddons(VECADDONS& addons) { - return GetAddonsInternal(ADDON_UNKNOWN, addons, OnlyEnabled::NO, CheckIncompatible::NO); + return GetAddonsInternal(ADDON_UNKNOWN, addons, OnlyEnabled::CHOICE_NO, + CheckIncompatible::CHOICE_NO); } bool CAddonMgr::GetInstalledAddons(VECADDONS& addons, const TYPE& type) { - return GetAddonsInternal(type, addons, OnlyEnabled::NO, CheckIncompatible::NO); + return GetAddonsInternal(type, addons, OnlyEnabled::CHOICE_NO, CheckIncompatible::CHOICE_NO); } bool CAddonMgr::GetDisabledAddons(VECADDONS& addons) @@ -420,7 +424,7 @@ bool CAddonMgr::FindInstallableById(const std::string& addonId, AddonPtr& result // check for an update if addon is installed already - if (GetAddon(addonId, addonToUpdate, ADDON_UNKNOWN, OnlyEnabled::NO)) + if (GetAddon(addonId, addonToUpdate, ADDON_UNKNOWN, OnlyEnabled::CHOICE_NO)) { if (addonRepos.DoAddonUpdateCheck(addonToUpdate, result)) return true; @@ -449,9 +453,10 @@ bool CAddonMgr::GetAddonsInternal(const TYPE& type, if (type != ADDON_UNKNOWN && !addonInfo.second->HasType(type)) continue; - if (onlyEnabled == OnlyEnabled::YES && - ((checkIncompatible == CheckIncompatible::NO && IsAddonDisabled(addonInfo.second->ID())) || - (checkIncompatible == CheckIncompatible::YES && + if (onlyEnabled == OnlyEnabled::CHOICE_YES && + ((checkIncompatible == CheckIncompatible::CHOICE_NO && + IsAddonDisabled(addonInfo.second->ID())) || + (checkIncompatible == CheckIncompatible::CHOICE_YES && IsAddonDisabledExcept(addonInfo.second->ID(), AddonDisabledReason::INCOMPATIBLE)))) continue; @@ -497,7 +502,7 @@ std::vector<AddonInfoPtr> CAddonMgr::MigrateAddons() CLog::Log(LOGINFO, "ADDON: waiting for add-ons to update..."); VECADDONS updates; GetAddonUpdateCandidates(updates); - InstallAddonUpdates(updates, true, AllowCheckForUpdates::NO); + InstallAddonUpdates(updates, true, AllowCheckForUpdates::CHOICE_NO); // get addons that became incompatible and disable them std::vector<AddonInfoPtr> incompatible; @@ -536,7 +541,7 @@ void CAddonMgr::CheckAndInstallAddonUpdates(bool wait) const std::lock_guard<std::mutex> lock(m_installAddonsMutex); VECADDONS updates; GetAddonUpdateCandidates(updates); - InstallAddonUpdates(updates, wait, AllowCheckForUpdates::YES); + InstallAddonUpdates(updates, wait, AllowCheckForUpdates::CHOICE_YES); } bool CAddonMgr::GetAddonUpdateCandidates(VECADDONS& updates) const @@ -617,7 +622,7 @@ bool CAddonMgr::GetAddon(const std::string& str, addon = CAddonBuilder::Generate(addonInfo, type); if (addon) { - if (onlyEnabled == OnlyEnabled::YES && IsAddonDisabled(addonInfo->ID())) + if (onlyEnabled == OnlyEnabled::CHOICE_YES && IsAddonDisabled(addonInfo->ID())) return false; // if the addon has a running instance, grab that @@ -634,7 +639,7 @@ bool CAddonMgr::GetAddon(const std::string& str, bool CAddonMgr::HasType(const std::string &id, const TYPE &type) { AddonPtr addon; - return GetAddon(id, addon, type, OnlyEnabled::NO); + return GetAddon(id, addon, type, OnlyEnabled::CHOICE_NO); } bool CAddonMgr::FindAddon(const std::string& addonId, @@ -713,8 +718,8 @@ bool CAddonMgr::UnloadAddon(const std::string& addonId) AddonPtr localAddon; // can't unload an binary addon that is in use - if (GetAddon(addonId, localAddon, ADDON_UNKNOWN, OnlyEnabled::NO) && localAddon->IsBinary() && - localAddon->IsInUse()) + if (GetAddon(addonId, localAddon, ADDON_UNKNOWN, OnlyEnabled::CHOICE_NO) && + localAddon->IsBinary() && localAddon->IsInUse()) { CLog::Log(LOGERROR, "CAddonMgr::{}: could not unload binary add-on {}, as is in use", __func__, addonId); @@ -738,7 +743,7 @@ bool CAddonMgr::LoadAddon(const std::string& addonId, CSingleLock lock(m_critSection); AddonPtr addon; - if (GetAddon(addonId, addon, ADDON_UNKNOWN, OnlyEnabled::NO)) + if (GetAddon(addonId, addon, ADDON_UNKNOWN, OnlyEnabled::CHOICE_NO)) { return true; } @@ -749,7 +754,7 @@ bool CAddonMgr::LoadAddon(const std::string& addonId, return false; } - if (!GetAddon(addonId, addon, ADDON_UNKNOWN, OnlyEnabled::NO)) + if (!GetAddon(addonId, addon, ADDON_UNKNOWN, OnlyEnabled::CHOICE_NO)) { CLog::Log(LOGERROR, "CAddonMgr: could not load add-on {}. No add-on with that ID is installed.", addonId); @@ -801,7 +806,8 @@ static void ResolveDependencies(const std::string& addonId, std::vector<std::str return; AddonPtr addon; - if (!CServiceBroker::GetAddonMgr().GetAddon(addonId, addon, ADDON_UNKNOWN, OnlyEnabled::NO)) + if (!CServiceBroker::GetAddonMgr().GetAddon(addonId, addon, ADDON_UNKNOWN, + OnlyEnabled::CHOICE_NO)) missing.push_back(addonId); else { @@ -827,7 +833,7 @@ bool CAddonMgr::DisableAddon(const std::string& id, AddonDisabledReason disabled //success CLog::Log(LOGDEBUG, "CAddonMgr: {} disabled", id); AddonPtr addon; - if (GetAddon(id, addon, ADDON_UNKNOWN, OnlyEnabled::NO) && addon != NULL) + if (GetAddon(id, addon, ADDON_UNKNOWN, OnlyEnabled::CHOICE_NO) && addon != NULL) { auto eventLog = CServiceBroker::GetEventLog(); if (eventLog) @@ -862,7 +868,7 @@ bool CAddonMgr::EnableSingle(const std::string& id) return true; //already enabled AddonPtr addon; - if (!GetAddon(id, addon, ADDON_UNKNOWN, OnlyEnabled::NO) || addon == nullptr) + if (!GetAddon(id, addon, ADDON_UNKNOWN, OnlyEnabled::CHOICE_NO) || addon == nullptr) return false; auto eventLog = CServiceBroker::GetEventLog(); @@ -937,7 +943,7 @@ bool CAddonMgr::CanAddonBeDisabled(const std::string& ID) AddonPtr localAddon; // can't disable an addon that isn't installed - if (!GetAddon(ID, localAddon, ADDON_UNKNOWN, OnlyEnabled::NO)) + if (!GetAddon(ID, localAddon, ADDON_UNKNOWN, OnlyEnabled::CHOICE_NO)) return false; // can't disable an addon that is in use @@ -955,14 +961,14 @@ bool CAddonMgr::CanAddonBeEnabled(const std::string& id) bool CAddonMgr::IsAddonInstalled(const std::string& ID) { AddonPtr tmp; - return GetAddon(ID, tmp, ADDON_UNKNOWN, OnlyEnabled::NO); + return GetAddon(ID, tmp, ADDON_UNKNOWN, OnlyEnabled::CHOICE_NO); } bool CAddonMgr::IsAddonInstalled(const std::string& ID, const std::string& origin) const { AddonPtr tmp; - if (GetAddon(ID, tmp, ADDON_UNKNOWN, OnlyEnabled::NO) && tmp) + if (GetAddon(ID, tmp, ADDON_UNKNOWN, OnlyEnabled::CHOICE_NO) && tmp) { if (tmp->Origin() == ORIGIN_SYSTEM) { @@ -982,7 +988,7 @@ bool CAddonMgr::IsAddonInstalled(const std::string& ID, { AddonPtr tmp; - if (GetAddon(ID, tmp, ADDON_UNKNOWN, OnlyEnabled::NO) && tmp) + if (GetAddon(ID, tmp, ADDON_UNKNOWN, OnlyEnabled::CHOICE_NO) && tmp) { if (tmp->Origin() == ORIGIN_SYSTEM) { @@ -1079,7 +1085,7 @@ bool CAddonMgr::IsCompatible(const IAddon& addon) const StringUtils::StartsWith(dependency.id, "kodi.")) { AddonPtr addon; - bool haveAddon = GetAddon(dependency.id, addon, ADDON_UNKNOWN, OnlyEnabled::YES); + bool haveAddon = GetAddon(dependency.id, addon, ADDON_UNKNOWN, OnlyEnabled::CHOICE_YES); if (!haveAddon || !addon->MeetsVersion(dependency.versionMin, dependency.version)) return false; } diff --git a/xbmc/addons/AddonManager.h b/xbmc/addons/AddonManager.h index 973981fd44..470c65d91e 100644 --- a/xbmc/addons/AddonManager.h +++ b/xbmc/addons/AddonManager.h @@ -28,28 +28,28 @@ namespace ADDON enum class AllowCheckForUpdates : bool; - enum class AddonCheckType + enum class AddonCheckType : bool { OUTDATED_ADDONS, - AVAILABLE_UPDATES + AVAILABLE_UPDATES, }; enum class OnlyEnabled : bool { - YES = true, - NO = false, + CHOICE_YES = true, + CHOICE_NO = false, }; enum class OnlyEnabledRootAddon : bool { - YES = true, - NO = false, + CHOICE_YES = true, + CHOICE_NO = false, }; enum class CheckIncompatible : bool { - YES = true, - NO = false, + CHOICE_YES = true, + CHOICE_NO = false, }; struct CAddonWithUpdate; diff --git a/xbmc/addons/AddonRepos.cpp b/xbmc/addons/AddonRepos.cpp index 79711b8d8a..b5757086fa 100644 --- a/xbmc/addons/AddonRepos.cpp +++ b/xbmc/addons/AddonRepos.cpp @@ -37,7 +37,7 @@ bool CAddonRepos::IsFromOfficialRepo(const std::shared_ptr<IAddon>& addon, CheckAddonPath checkAddonPath) { auto comparator = [&](const RepoInfo& officialRepo) { - if (checkAddonPath == CheckAddonPath::YES) + if (checkAddonPath == CheckAddonPath::CHOICE_YES) { return (addon->Origin() == officialRepo.m_repoId && StringUtils::StartsWithNoCase(addon->Path(), officialRepo.m_origin)); @@ -138,7 +138,7 @@ void CAddonRepos::SetupLatestVersionMaps() { const auto& addonToAdd = addonMapEntry.second; - if (IsFromOfficialRepo(addonToAdd, CheckAddonPath::YES)) + if (IsFromOfficialRepo(addonToAdd, CheckAddonPath::CHOICE_YES)) { AddAddonIfLatest(addonToAdd, m_latestOfficialVersions); } @@ -239,7 +239,7 @@ bool CAddonRepos::DoAddonUpdateCheck(const std::shared_ptr<IAddon>& addon, if (ORIGIN_SYSTEM != addon->Origin() && !hasOfficialUpdate) // not a system addon { // If we didn't find an official update - if (IsFromOfficialRepo(addon, CheckAddonPath::YES)) // is an official addon + if (IsFromOfficialRepo(addon, CheckAddonPath::CHOICE_YES)) // is an official addon { if (updateMode == AddonRepoUpdateMode::ANY_REPOSITORY) { @@ -453,7 +453,8 @@ bool CAddonRepos::FindDependency(const std::string& dependsId, // we got the dependency, so now get a repository-pointer to return std::shared_ptr<IAddon> tmp; - if (!m_addonMgr.GetAddon(dependencyToInstall->Origin(), tmp, ADDON_REPOSITORY, OnlyEnabled::YES)) + if (!m_addonMgr.GetAddon(dependencyToInstall->Origin(), tmp, ADDON_REPOSITORY, + OnlyEnabled::CHOICE_YES)) return false; repoForDep = std::static_pointer_cast<CRepository>(tmp); @@ -497,7 +498,7 @@ void CAddonRepos::BuildCompatibleVersionsList( { if (m_addonMgr.IsCompatible(*addon)) { - if (IsFromOfficialRepo(addon, CheckAddonPath::YES)) + if (IsFromOfficialRepo(addon, CheckAddonPath::CHOICE_YES)) { officialVersions.emplace_back(addon); } diff --git a/xbmc/addons/AddonRepos.h b/xbmc/addons/AddonRepos.h index 88a055f94b..27581af750 100644 --- a/xbmc/addons/AddonRepos.h +++ b/xbmc/addons/AddonRepos.h @@ -21,12 +21,12 @@ class CAddonDatabase; class CAddonMgr; class CRepository; class IAddon; -enum class AddonCheckType; +enum class AddonCheckType : bool; enum class CheckAddonPath { - YES, - NO, + CHOICE_YES = true, + CHOICE_NO = false, }; /** @@ -104,7 +104,7 @@ public: * is matching * \note if this function is called on locally installed add-ons, for instance when populating * 'My add-ons', the local installation path is returned as origin. - * thus parameter CheckAddonPath::NO needs to be passed in such cases + * thus parameter CheckAddonPath::CHOICE_NO needs to be passed in such cases * \param addon pointer to addon to be checked * \param checkAddonPath also check origin path * \return true if the repository id of a given addon is defined as official diff --git a/xbmc/addons/AddonStatusHandler.cpp b/xbmc/addons/AddonStatusHandler.cpp index a1a9554458..75f683e09a 100644 --- a/xbmc/addons/AddonStatusHandler.cpp +++ b/xbmc/addons/AddonStatusHandler.cpp @@ -44,7 +44,8 @@ CAddonStatusHandler::CAddonStatusHandler(const std::string &addonID, ADDON_STATU { //! @todo The status handled CAddonStatusHandler by is related to the class, not the instance //! having CAddonMgr construct an instance makes no sense - if (!CServiceBroker::GetAddonMgr().GetAddon(addonID, m_addon, ADDON_UNKNOWN, OnlyEnabled::YES)) + if (!CServiceBroker::GetAddonMgr().GetAddon(addonID, m_addon, ADDON_UNKNOWN, + OnlyEnabled::CHOICE_YES)) return; CLog::Log(LOGINFO, diff --git a/xbmc/addons/AddonSystemSettings.cpp b/xbmc/addons/AddonSystemSettings.cpp index 54c792fd90..e066830498 100644 --- a/xbmc/addons/AddonSystemSettings.cpp +++ b/xbmc/addons/AddonSystemSettings.cpp @@ -84,9 +84,10 @@ void CAddonSystemSettings::OnSettingChanged(const std::shared_ptr<const CSetting { using namespace KODI::MESSAGING::HELPERS; - if (setting->GetId() == CSettings::SETTING_ADDONS_ALLOW_UNKNOWN_SOURCES - && CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_ADDONS_ALLOW_UNKNOWN_SOURCES) - && ShowYesNoDialogText(19098, 36618) != DialogResponse::YES) + if (setting->GetId() == CSettings::SETTING_ADDONS_ALLOW_UNKNOWN_SOURCES && + CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool( + CSettings::SETTING_ADDONS_ALLOW_UNKNOWN_SOURCES) && + ShowYesNoDialogText(19098, 36618) != DialogResponse::CHOICE_YES) { CServiceBroker::GetSettingsComponent()->GetSettings()->SetBool(CSettings::SETTING_ADDONS_ALLOW_UNKNOWN_SOURCES, false); } @@ -98,7 +99,8 @@ bool CAddonSystemSettings::GetActive(const TYPE& type, AddonPtr& addon) if (it != m_activeSettings.end()) { auto settingValue = CServiceBroker::GetSettingsComponent()->GetSettings()->GetString(it->second); - return CServiceBroker::GetAddonMgr().GetAddon(settingValue, addon, type, OnlyEnabled::YES); + return CServiceBroker::GetAddonMgr().GetAddon(settingValue, addon, type, + OnlyEnabled::CHOICE_YES); } return false; } diff --git a/xbmc/addons/ContextMenus.cpp b/xbmc/addons/ContextMenus.cpp index 1bcfefa336..c8755b3259 100644 --- a/xbmc/addons/ContextMenus.cpp +++ b/xbmc/addons/ContextMenus.cpp @@ -25,7 +25,7 @@ bool CAddonSettings::IsVisible(const CFileItem& item) const AddonPtr addon; return item.HasAddonInfo() && CServiceBroker::GetAddonMgr().GetAddon(item.GetAddonInfo()->ID(), addon, ADDON_UNKNOWN, - OnlyEnabled::NO) && + OnlyEnabled::CHOICE_NO) && addon->HasSettings(); } @@ -33,7 +33,7 @@ bool CAddonSettings::Execute(const CFileItemPtr& item) const { AddonPtr addon; return CServiceBroker::GetAddonMgr().GetAddon(item->GetAddonInfo()->ID(), addon, ADDON_UNKNOWN, - OnlyEnabled::NO) && + OnlyEnabled::CHOICE_NO) && CGUIDialogAddonSettings::ShowForAddon(addon); } @@ -47,7 +47,7 @@ bool CCheckForUpdates::Execute(const CFileItemPtr& item) const AddonPtr addon; if (item->HasAddonInfo() && CServiceBroker::GetAddonMgr().GetAddon(item->GetAddonInfo()->ID(), addon, ADDON_REPOSITORY, - OnlyEnabled::YES)) + OnlyEnabled::CHOICE_YES)) { CServiceBroker::GetRepositoryUpdater().CheckForUpdates(std::static_pointer_cast<CRepository>(addon), true); return true; diff --git a/xbmc/addons/FontResource.cpp b/xbmc/addons/FontResource.cpp index 1ef8fd10f4..e39e8d3b20 100644 --- a/xbmc/addons/FontResource.cpp +++ b/xbmc/addons/FontResource.cpp @@ -28,7 +28,7 @@ void CFontResource::OnPostInstall(bool update, bool modal) { std::string skin = CServiceBroker::GetSettingsComponent()->GetSettings()->GetString(CSettings::SETTING_LOOKANDFEEL_SKIN); const auto& deps = - CServiceBroker::GetAddonMgr().GetDepsRecursive(skin, OnlyEnabledRootAddon::YES); + CServiceBroker::GetAddonMgr().GetDepsRecursive(skin, OnlyEnabledRootAddon::CHOICE_YES); for (const auto& it : deps) if (it.id == ID()) CApplicationMessenger::GetInstance().PostMsg(TMSG_EXECUTE_BUILT_IN, -1, -1, nullptr, "ReloadSkin"); diff --git a/xbmc/addons/LanguageResource.cpp b/xbmc/addons/LanguageResource.cpp index b9d1c41eed..87f18b99b5 100644 --- a/xbmc/addons/LanguageResource.cpp +++ b/xbmc/addons/LanguageResource.cpp @@ -97,9 +97,9 @@ void CLanguageResource::OnPostInstall(bool update, bool modal) if (!g_SkinInfo) return; - if (IsInUse() || - (!update && !modal && - (HELPERS::ShowYesNoDialogText(CVariant{Name()}, CVariant{24132}) == DialogResponse::YES))) + if (IsInUse() || (!update && !modal && + (HELPERS::ShowYesNoDialogText(CVariant{Name()}, CVariant{24132}) == + DialogResponse::CHOICE_YES))) { if (IsInUse()) g_langInfo.SetLanguage(ID()); @@ -137,7 +137,7 @@ bool CLanguageResource::FindLegacyLanguage(const std::string &locale, std::strin AddonPtr addon; if (!CServiceBroker::GetAddonMgr().GetAddon(addonId, addon, ADDON_RESOURCE_LANGUAGE, - OnlyEnabled::YES)) + OnlyEnabled::CHOICE_YES)) return false; legacyLanguage = addon->Name(); diff --git a/xbmc/addons/Scraper.cpp b/xbmc/addons/Scraper.cpp index 241d66ed73..e273057c5f 100644 --- a/xbmc/addons/Scraper.cpp +++ b/xbmc/addons/Scraper.cpp @@ -369,7 +369,7 @@ bool CScraper::Load() bool bOptional = itr->optional; if (CServiceBroker::GetAddonMgr().GetAddon((*itr).id, dep, ADDON::ADDON_UNKNOWN, - ADDON::OnlyEnabled::YES)) + ADDON::OnlyEnabled::CHOICE_YES)) { CXBMCTinyXML doc; if (dep->Type() == ADDON_SCRAPER_LIBRARY && doc.LoadFile(dep->LibPath())) diff --git a/xbmc/addons/Service.cpp b/xbmc/addons/Service.cpp index 285e76ba2f..e8d71fdce5 100644 --- a/xbmc/addons/Service.cpp +++ b/xbmc/addons/Service.cpp @@ -62,7 +62,7 @@ void CServiceAddonManager::Start() void CServiceAddonManager::Start(const std::string& addonId) { AddonPtr addon; - if (m_addonMgr.GetAddon(addonId, addon, ADDON_SERVICE, OnlyEnabled::YES)) + if (m_addonMgr.GetAddon(addonId, addon, ADDON_SERVICE, OnlyEnabled::CHOICE_YES)) { Start(addon); } diff --git a/xbmc/addons/Skin.cpp b/xbmc/addons/Skin.cpp index f6923fa7f1..0752eeaf64 100644 --- a/xbmc/addons/Skin.cpp +++ b/xbmc/addons/Skin.cpp @@ -381,7 +381,8 @@ void CSkinInfo::OnPostInstall(bool update, bool modal) return; if (IsInUse() || (!update && !modal && - HELPERS::ShowYesNoDialogText(CVariant{Name()}, CVariant{24099}) == DialogResponse::YES)) + HELPERS::ShowYesNoDialogText(CVariant{Name()}, CVariant{24099}) == + DialogResponse::CHOICE_YES)) { CGUIDialogKaiToast *toast = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogKaiToast>(WINDOW_DIALOG_KAI_TOAST); if (toast) diff --git a/xbmc/addons/addoninfo/AddonInfo.cpp b/xbmc/addons/addoninfo/AddonInfo.cpp index fa9762bf6b..a110547100 100644 --- a/xbmc/addons/addoninfo/AddonInfo.cpp +++ b/xbmc/addons/addoninfo/AddonInfo.cpp @@ -79,7 +79,7 @@ const std::string& CAddonInfo::OriginName() const { ADDON::AddonPtr origin; if (CServiceBroker::GetAddonMgr().GetAddon(m_origin, origin, ADDON::ADDON_UNKNOWN, - ADDON::OnlyEnabled::NO)) + ADDON::OnlyEnabled::CHOICE_NO)) m_originName = std::make_unique<std::string>(origin->Name()); else m_originName = std::make_unique<std::string>(); // remember we tried to fetch the name diff --git a/xbmc/addons/gui/GUIDialogAddonInfo.cpp b/xbmc/addons/gui/GUIDialogAddonInfo.cpp index 7b1004c692..fcefb9fc3d 100644 --- a/xbmc/addons/gui/GUIDialogAddonInfo.cpp +++ b/xbmc/addons/gui/GUIDialogAddonInfo.cpp @@ -118,7 +118,7 @@ bool CGUIDialogAddonInfo::OnMessage(CGUIMessage& message) } else if (iControl == CONTROL_BTN_DEPENDENCIES) { - ShowDependencyList(Reactivate::YES, EntryPoint::SHOW_DEPENDENCIES); + ShowDependencyList(Reactivate::CHOICE_YES, EntryPoint::SHOW_DEPENDENCIES); return true; } else if (iControl == CONTROL_BTN_AUTOUPDATE) @@ -166,7 +166,7 @@ void CGUIDialogAddonInfo::OnInitWindow() { CGUIDialog::OnInitWindow(); BuildDependencyList(); - UpdateControls(PerformButtonFocus::YES); + UpdateControls(PerformButtonFocus::CHOICE_YES); } void CGUIDialogAddonInfo::UpdateControls(PerformButtonFocus performButtonFocus) @@ -208,7 +208,7 @@ void CGUIDialogAddonInfo::UpdateControls(PerformButtonFocus performButtonFocus) } CONTROL_ENABLE_ON_CONDITION(CONTROL_BTN_INSTALL, canInstall); - if (canInstall && performButtonFocus == PerformButtonFocus::YES) + if (canInstall && performButtonFocus == PerformButtonFocus::CHOICE_YES) { SET_CONTROL_FOCUS(CONTROL_BTN_INSTALL, 0); } @@ -261,7 +261,8 @@ void CGUIDialogAddonInfo::UpdateControls(PerformButtonFocus performButtonFocus) SET_CONTROL_LABEL(CONTROL_BTN_SELECT, label); CONTROL_ENABLE_ON_CONDITION(CONTROL_BTN_SETTINGS, isInstalled && m_localAddon->HasSettings()); - if (isInstalled && m_localAddon->HasSettings() && performButtonFocus == PerformButtonFocus::YES) + if (isInstalled && m_localAddon->HasSettings() && + performButtonFocus == PerformButtonFocus::CHOICE_YES) { SET_CONTROL_FOCUS(CONTROL_BTN_SETTINGS, 0); } @@ -306,7 +307,7 @@ int CGUIDialogAddonInfo::AskForVersion(std::vector<std::pair<AddonVersion, std:: dialog->Add(item); } else if (CServiceBroker::GetAddonMgr().GetAddon(versionInfo.second, repo, ADDON_REPOSITORY, - OnlyEnabled::YES)) + OnlyEnabled::CHOICE_YES)) { item.SetLabel2(repo->Name()); item.SetArt("icon", repo->Icon()); @@ -328,7 +329,7 @@ void CGUIDialogAddonInfo::OnUpdate() Close(); if (!m_depsInstalledWithAvailable.empty() && - !ShowDependencyList(Reactivate::NO, EntryPoint::UPDATE)) + !ShowDependencyList(Reactivate::CHOICE_NO, EntryPoint::UPDATE)) return; CAddonInstaller::GetInstance().Install(addonId, version, origin); @@ -403,7 +404,7 @@ void CGUIDialogAddonInfo::OnSelectVersion() else { if (!m_depsInstalledWithAvailable.empty() && - !ShowDependencyList(Reactivate::NO, entryPoint)) + !ShowDependencyList(Reactivate::CHOICE_NO, entryPoint)) return; CAddonInstaller::GetInstance().Install(processAddonId, versions[i].first, versions[i].second); @@ -481,7 +482,7 @@ void CGUIDialogAddonInfo::OnInstall() Close(); if (!m_depsInstalledWithAvailable.empty() && - !ShowDependencyList(Reactivate::NO, EntryPoint::INSTALL)) + !ShowDependencyList(Reactivate::CHOICE_NO, EntryPoint::INSTALL)) return; CAddonInstaller::GetInstance().Install(addonId, version, origin); @@ -618,7 +619,7 @@ void CGUIDialogAddonInfo::OnEnableDisable() CServiceBroker::GetAddonMgr().EnableAddon(m_localAddon->ID()); } - UpdateControls(PerformButtonFocus::NO); + UpdateControls(PerformButtonFocus::CHOICE_NO); } void CGUIDialogAddonInfo::OnSettings() @@ -680,7 +681,7 @@ bool CGUIDialogAddonInfo::ShowDependencyList(Reactivate reactivate, EntryPoint e if (entryPoint == EntryPoint::SHOW_DEPENDENCIES || infoAddon->MainType() != ADDON_SCRIPT_MODULE || - !CAddonRepos::IsFromOfficialRepo(infoAddon, CheckAddonPath::NO)) + !CAddonRepos::IsFromOfficialRepo(infoAddon, CheckAddonPath::CHOICE_NO)) { item->SetLabel2(StringUtils::Format( g_localizeStrings.Get(messageId), it.m_depInfo.versionMin.asString(), @@ -708,11 +709,11 @@ bool CGUIDialogAddonInfo::ShowDependencyList(Reactivate reactivate, EntryPoint e while (true) { pDialog->Reset(); - pDialog->SetHeading(reactivate == Reactivate::YES ? 39024 : 39020); + pDialog->SetHeading(reactivate == Reactivate::CHOICE_YES ? 39024 : 39020); pDialog->SetUseDetails(true); for (auto& it : items) pDialog->Add(*it); - pDialog->EnableButton(reactivate == Reactivate::NO, 186); + pDialog->EnableButton(reactivate == Reactivate::CHOICE_NO, 186); pDialog->SetButtonFocus(true); pDialog->Open(); @@ -734,7 +735,7 @@ bool CGUIDialogAddonInfo::ShowDependencyList(Reactivate reactivate, EntryPoint e break; } SetItem(backup_item); - if (reactivate == Reactivate::YES) + if (reactivate == Reactivate::CHOICE_YES) Open(); return false; @@ -814,7 +815,7 @@ bool CGUIDialogAddonInfo::SetItem(const CFileItemPtr& item) m_item = std::make_shared<CFileItem>(*item); m_localAddon.reset(); if (CServiceBroker::GetAddonMgr().GetAddon(item->GetAddonInfo()->ID(), m_localAddon, - ADDON_UNKNOWN, OnlyEnabled::NO)) + ADDON_UNKNOWN, OnlyEnabled::CHOICE_NO)) { CLog::Log(LOGDEBUG, "{} - Addon with id {} not found locally.", __FUNCTION__, item->GetAddonInfo()->ID()); @@ -830,7 +831,7 @@ void CGUIDialogAddonInfo::BuildDependencyList() m_showDepDialogOnInstall = false; m_depsInstalledWithAvailable.clear(); m_deps = CServiceBroker::GetAddonMgr().GetDepsRecursive(m_item->GetAddonInfo()->ID(), - OnlyEnabledRootAddon::NO); + OnlyEnabledRootAddon::CHOICE_NO); for (const auto& dep : m_deps) { @@ -839,7 +840,7 @@ void CGUIDialogAddonInfo::BuildDependencyList() // Find add-on in local installation if (!CServiceBroker::GetAddonMgr().GetAddon(dep.id, addonInstalled, ADDON_UNKNOWN, - OnlyEnabled::YES)) + OnlyEnabled::CHOICE_YES)) { addonInstalled = nullptr; } @@ -859,7 +860,7 @@ void CGUIDialogAddonInfo::BuildDependencyList() // - the dependency is not a script/module OR // - the script/module is not available at an official repo if (!addonAvailable || addonAvailable->MainType() != ADDON_SCRIPT_MODULE || - !CAddonRepos::IsFromOfficialRepo(addonAvailable, CheckAddonPath::NO)) + !CAddonRepos::IsFromOfficialRepo(addonAvailable, CheckAddonPath::CHOICE_NO)) { m_showDepDialogOnInstall = true; } diff --git a/xbmc/addons/gui/GUIDialogAddonInfo.h b/xbmc/addons/gui/GUIDialogAddonInfo.h index 2495455f82..8738c0226c 100644 --- a/xbmc/addons/gui/GUIDialogAddonInfo.h +++ b/xbmc/addons/gui/GUIDialogAddonInfo.h @@ -16,19 +16,19 @@ #include <utility> #include <vector> -enum class Reactivate +enum class Reactivate : bool { - YES, - NO, + CHOICE_YES = true, + CHOICE_NO = false, }; -enum class PerformButtonFocus +enum class PerformButtonFocus : bool { - YES, - NO, + CHOICE_YES = true, + CHOICE_NO = false, }; -enum class EntryPoint +enum class EntryPoint : int { INSTALL, UPDATE, diff --git a/xbmc/addons/gui/GUIWindowAddonBrowser.cpp b/xbmc/addons/gui/GUIWindowAddonBrowser.cpp index 90058f990f..4e4bb6679f 100644 --- a/xbmc/addons/gui/GUIWindowAddonBrowser.cpp +++ b/xbmc/addons/gui/GUIWindowAddonBrowser.cpp @@ -162,7 +162,8 @@ class UpdateAddons : public IRunnable void Run() override { for (const auto& addon : CServiceBroker::GetAddonMgr().GetAvailableUpdates()) - CAddonInstaller::GetInstance().InstallOrUpdate(addon->ID(), BackgroundJob::YES, ModalJob::NO); + CAddonInstaller::GetInstance().InstallOrUpdate(addon->ID(), BackgroundJob::CHOICE_YES, + ModalJob::CHOICE_NO); } }; @@ -172,8 +173,8 @@ class UpdateAllowedAddons : public IRunnable { for (const auto& addon : CServiceBroker::GetAddonMgr().GetAvailableUpdates()) if (CServiceBroker::GetAddonMgr().IsAutoUpdateable(addon->ID())) - CAddonInstaller::GetInstance().InstallOrUpdate(addon->ID(), BackgroundJob::YES, - ModalJob::NO); + CAddonInstaller::GetInstance().InstallOrUpdate(addon->ID(), BackgroundJob::CHOICE_YES, + ModalJob::CHOICE_NO); } }; @@ -196,13 +197,13 @@ void CGUIWindowAddonBrowser::InstallFromZip() if (!CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool( CSettings::SETTING_ADDONS_ALLOW_UNKNOWN_SOURCES)) { - if (ShowYesNoDialogText(13106, 36617, 186, 10004) == DialogResponse::YES) + if (ShowYesNoDialogText(13106, 36617, 186, 10004) == DialogResponse::CHOICE_YES) CServiceBroker::GetGUI()->GetWindowManager().ActivateWindow( WINDOW_SETTINGS_SYSTEM, CSettings::SETTING_ADDONS_ALLOW_UNKNOWN_SOURCES); } else { - if (ShowYesNoDialogText(19098, 36637) == DialogResponse::YES) + if (ShowYesNoDialogText(19098, 36637) == DialogResponse::CHOICE_YES) { // pop up filebrowser to grab an installed folder VECSOURCES shares = *CMediaSourceSettings::GetInstance().GetSources("files"); @@ -329,7 +330,8 @@ bool CGUIWindowAddonBrowser::GetDirectory(const std::string& strDirectory, CFile //check if it's installed AddonPtr addon; if (!CServiceBroker::GetAddonMgr().GetAddon(items[i]->GetProperty("Addon.ID").asString(), - addon, ADDON_UNKNOWN, OnlyEnabled::YES)) + addon, ADDON_UNKNOWN, + OnlyEnabled::CHOICE_YES)) items.Remove(i); } } @@ -610,7 +612,7 @@ int CGUIWindowAddonBrowser::SelectAddonID(const std::vector<ADDON::TYPE>& types, { AddonPtr installedAddon; if (!CAddonInstaller::GetInstance().InstallModal(addon->ID(), installedAddon, - InstallModalPrompt::NO_PROMPT)) + InstallModalPrompt::CHOICE_NO)) continue; } diff --git a/xbmc/addons/interfaces/AddonBase.cpp b/xbmc/addons/interfaces/AddonBase.cpp index dd28c472a6..1f62868b16 100644 --- a/xbmc/addons/interfaces/AddonBase.cpp +++ b/xbmc/addons/interfaces/AddonBase.cpp @@ -313,7 +313,7 @@ bool Interface_Base::open_settings_dialog(const KODI_ADDON_BACKEND_HDL hdl) // show settings dialog AddonPtr addonInfo; if (!CServiceBroker::GetAddonMgr().GetAddon(addon->ID(), addonInfo, ADDON_UNKNOWN, - OnlyEnabled::YES)) + OnlyEnabled::CHOICE_YES)) { CLog::Log(LOGERROR, "Interface_Base::{} - Could not get addon information for '{}'", __func__, addon->ID()); diff --git a/xbmc/addons/interfaces/General.cpp b/xbmc/addons/interfaces/General.cpp index 50a38bd125..628d31c8e5 100644 --- a/xbmc/addons/interfaces/General.cpp +++ b/xbmc/addons/interfaces/General.cpp @@ -322,7 +322,7 @@ bool Interface_General::is_addon_avilable(void* kodiBase, } AddonPtr addonInfo; - if (!CServiceBroker::GetAddonMgr().GetAddon(id, addonInfo, ADDON_UNKNOWN, OnlyEnabled::NO)) + if (!CServiceBroker::GetAddonMgr().GetAddon(id, addonInfo, ADDON_UNKNOWN, OnlyEnabled::CHOICE_NO)) return false; *version = strdup(addonInfo->Version().asString().c_str()); diff --git a/xbmc/addons/interfaces/gui/dialogs/YesNo.cpp b/xbmc/addons/interfaces/gui/dialogs/YesNo.cpp index 2c635fb1f9..89dea580dd 100644 --- a/xbmc/addons/interfaces/gui/dialogs/YesNo.cpp +++ b/xbmc/addons/interfaces/gui/dialogs/YesNo.cpp @@ -63,8 +63,8 @@ bool Interface_GUIDialogYesNo::show_and_get_input_single_text(KODI_HANDLE kodiBa } DialogResponse result = HELPERS::ShowYesNoDialogText(heading, text, noLabel, yesLabel); - *canceled = (result == DialogResponse::CANCELLED); - return (result == DialogResponse::YES); + *canceled = (result == DialogResponse::CHOICE_CANCELLED); + return (result == DialogResponse::CHOICE_YES); } bool Interface_GUIDialogYesNo::show_and_get_input_line_text(KODI_HANDLE kodiBase, @@ -95,7 +95,7 @@ bool Interface_GUIDialogYesNo::show_and_get_input_line_text(KODI_HANDLE kodiBase } return HELPERS::ShowYesNoDialogLines(heading, line0, line1, line2, noLabel, yesLabel) == - DialogResponse::YES; + DialogResponse::CHOICE_YES; } bool Interface_GUIDialogYesNo::show_and_get_input_line_button_text(KODI_HANDLE kodiBase, @@ -129,8 +129,8 @@ bool Interface_GUIDialogYesNo::show_and_get_input_line_button_text(KODI_HANDLE k DialogResponse result = HELPERS::ShowYesNoDialogLines(heading, line0, line1, line2, noLabel, yesLabel); - *canceled = (result == DialogResponse::CANCELLED); - return (result == DialogResponse::YES); + *canceled = (result == DialogResponse::CHOICE_CANCELLED); + return (result == DialogResponse::CHOICE_YES); } } /* namespace ADDON */ diff --git a/xbmc/cdrip/EncoderFFmpeg.cpp b/xbmc/cdrip/EncoderFFmpeg.cpp index c0ab4bd786..a1a1964fb0 100644 --- a/xbmc/cdrip/EncoderFFmpeg.cpp +++ b/xbmc/cdrip/EncoderFFmpeg.cpp @@ -43,7 +43,7 @@ bool CEncoderFFmpeg::Init() const std::string addonId = CServiceBroker::GetSettingsComponent()->GetSettings()->GetString( CSettings::SETTING_AUDIOCDS_ENCODER); bool success = CServiceBroker::GetAddonMgr().GetAddon(addonId, addon, ADDON::ADDON_UNKNOWN, - ADDON::OnlyEnabled::YES); + ADDON::OnlyEnabled::CHOICE_YES); int bitrate; if (success && addon) { diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp index cef7374483..6cc19ffb4e 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp @@ -637,8 +637,6 @@ void CAESinkAUDIOTRACK::GetDelay(AEDelayStatus& status) gone = m_duration_written; double delay = m_duration_written - gone; - if (m_pause_ms > 0.0) - delay = m_audiotrackbuffer_sec; if (m_stampTimer.IsTimePast()) { @@ -725,9 +723,30 @@ void CAESinkAUDIOTRACK::GetDelay(AEDelayStatus& status) if (delay < 0.0) delay = 0.0; + // the RAW hack for simulating pause bursts should not come + // into the way of hw delay + if (m_pause_ms > 0.0) + { + double difference = (m_audiotrackbuffer_sec - delay) * 1000; + if (usesAdvancedLogging) + { + CLog::Log(LOGINFO, "Faking Pause-Bursts in Delay - returning smoothed {} ms Original {} ms", + m_audiotrackbuffer_sec * 1000, delay * 1000); + CLog::Log(LOGINFO, "Difference: {} ms m_pause_ms {}", difference, m_pause_ms); + } + // buffer not yet reached + if (difference > 0.0) + delay = m_audiotrackbuffer_sec; + else + { + CLog::Log(LOGINFO, "Resetting pause bursts as buffer level was reached! (2)"); + m_pause_ms = 0.0; + } + } + const double d = GetMovingAverageDelay(delay); - // Audiotrack is caching more than we though it would + // Audiotrack is caching more than we thought it would if (d > m_audiotrackbuffer_sec) m_audiotrackbuffer_sec = d; @@ -851,36 +870,28 @@ unsigned int CAESinkAUDIOTRACK::AddPackets(uint8_t **data, unsigned int frames, double time_to_add_ms = 1000.0 * (CurrentHostCounter() - startTime) / CurrentHostFrequency(); if (m_passthrough && !m_info.m_wantsIECPassthrough) { - // AT does not consume in a blocking way - it runs ahead and blocks // exactly once with the last package for some 100 ms - // help it sleeping a bit - but don't run dry -> at least 0.128 seconds of - // audio in buffer (e.g. 4 AC3 packages) + double extra_sleep = 0.0; if (time_to_add_ms < m_format.m_streamInfo.GetDuration()) + extra_sleep = (m_format.m_streamInfo.GetDuration() - time_to_add_ms) / 2.0; + + // if there is still place, just add it without blocking + if (m_delay < (m_audiotrackbuffer_sec - (m_format.m_streamInfo.GetDuration() / 1000.0))) + extra_sleep = 0; + + if (m_pause_ms > 0.0) { - // leave enough head room for eventualities - double extra_sleep = (m_format.m_streamInfo.GetDuration() - time_to_add_ms) / 2.0; - // warmup - if (m_pause_ms > 0) - { - m_pause_ms -= m_format.m_streamInfo.GetDuration(); - extra_sleep /= 4; // fillup after Addpause - } - else if (m_delay < 0.128) + extra_sleep = 0; + m_pause_ms -= m_format.m_streamInfo.GetDuration(); + if (m_pause_ms <= 0.0) { - // care for underrun - extra_sleep /= 2; + m_pause_ms = 0.0; + CLog::Log(LOGINFO, "Resetting pause bursts as buffer level was reached! (1)"); } - - usleep(extra_sleep * 1000); - } - else - { - if (m_pause_ms > 0) - m_pause_ms -= time_to_add_ms; - else - m_pause_ms = 0; } + + usleep(extra_sleep * 1000); } else { @@ -911,9 +922,6 @@ void CAESinkAUDIOTRACK::AddPause(unsigned int millis) // blocking, sleeping roughly and GetDelay smoothing // In short: Shit in, shit out usleep(millis * 1000); - if (m_pause_ms < 0) - m_pause_ms = 0.0; - m_pause_ms += millis; } diff --git a/xbmc/cores/RetroPlayer/RetroPlayer.cpp b/xbmc/cores/RetroPlayer/RetroPlayer.cpp index cc98d7660c..78cd78e785 100644 --- a/xbmc/cores/RetroPlayer/RetroPlayer.cpp +++ b/xbmc/cores/RetroPlayer/RetroPlayer.cpp @@ -110,7 +110,7 @@ bool CRetroPlayer::OpenFile(const CFileItem& file, const CPlayerOptions& options CLog::Log(LOGERROR, "RetroPlayer[PLAYER]: Can't play game, no game client was passed!"); } else if (!CServiceBroker::GetAddonMgr().GetAddon(gameClientId, addon, ADDON::ADDON_GAMEDLL, - ADDON::OnlyEnabled::YES)) + ADDON::OnlyEnabled::CHOICE_YES)) { CLog::Log(LOGERROR, "RetroPlayer[PLAYER]: Can't find add-on {} for game file!", gameClientId); } @@ -155,8 +155,8 @@ bool CRetroPlayer::OpenFile(const CFileItem& file, const CPlayerOptions& options if (save->GameClientID() != m_gameClient->ID()) { ADDON::AddonPtr addon; - if (CServiceBroker::GetAddonMgr().GetAddon(save->GameClientID(), addon, - ADDON::ADDON_UNKNOWN, ADDON::OnlyEnabled::YES)) + if (CServiceBroker::GetAddonMgr().GetAddon( + save->GameClientID(), addon, ADDON::ADDON_UNKNOWN, ADDON::OnlyEnabled::CHOICE_YES)) { // Warn the user that continuing with a different game client will // overwrite the save diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp index 795300cadb..2684df3f2f 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp @@ -326,7 +326,7 @@ bool CDVDVideoCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options m_hints = hints; m_options = options; - AVCodec* pCodec; + AVCodec* pCodec = nullptr; m_iOrientation = hints.orientation; @@ -336,7 +336,16 @@ bool CDVDVideoCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options m_processInfo.SetSwDeinterlacingMethods(); m_processInfo.SetVideoInterlaced(false); - pCodec = avcodec_find_decoder(hints.codec); + // libdav1d av1 sw decoding is implemented as a separate decoder + // in ffmpeg which is always found first when calling `avcodec_find_decoder`. + // To get hwaccels we look for decoders registered for `av1`. + // The decoder state check is needed to succesfully fallback to sw decoding if + // necessary. + if (hints.codec == AV_CODEC_ID_AV1 && m_decoderState != STATE_HW_FAILED) + pCodec = avcodec_find_decoder_by_name("av1"); + + if (!pCodec) + pCodec = avcodec_find_decoder(hints.codec); if(pCodec == NULL) { @@ -381,6 +390,7 @@ bool CDVDVideoCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options m_pCodecContext->coded_height = hints.height; m_pCodecContext->coded_width = hints.width; m_pCodecContext->bits_per_coded_sample = hints.bitsperpixel; + m_pCodecContext->bits_per_raw_sample = hints.bitdepth; if( hints.extradata && hints.extrasize > 0 ) { diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DXVA.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DXVA.cpp index a514fd0166..a9143b2397 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DXVA.cpp +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DXVA.cpp @@ -1035,7 +1035,7 @@ static bool IsL41LimitedATI() DXGI_ADAPTER_DESC AIdentifier = {}; DX::DeviceResources::Get()->GetAdapterDesc(&AIdentifier); - if (AIdentifier.VendorId == PCIV_ATI) + if (AIdentifier.VendorId == PCIV_AMD) { for (unsigned idx = 0; UVDDeviceID[idx] != 0; idx++) { @@ -1052,7 +1052,7 @@ static bool HasVP3WidthBug(AVCodecContext* avctx) DXGI_ADAPTER_DESC AIdentifier = {}; DX::DeviceResources::Get()->GetAdapterDesc(&AIdentifier); - if (AIdentifier.VendorId == PCIV_nVidia && + if (AIdentifier.VendorId == PCIV_NVIDIA && !CDVDCodecUtils::IsVP3CompatibleWidth(avctx->coded_width)) { // Find the card in a known list of problematic VP3 hardware @@ -1067,7 +1067,7 @@ static bool HasATIMP2Bug(AVCodecContext* avctx) { DXGI_ADAPTER_DESC AIdentifier = {}; DX::DeviceResources::Get()->GetAdapterDesc(&AIdentifier); - if (AIdentifier.VendorId != PCIV_ATI) + if (AIdentifier.VendorId != PCIV_AMD) return false; // AMD/ATI card doesn't like some SD MPEG2 content @@ -1245,7 +1245,7 @@ bool CDecoder::Open(AVCodecContext* avctx, AVCodecContext* mainctx, enum AVPixel "DXVA: used Intel ClearVideo decoder, but no support workaround for it in libavcodec."); #endif } - else if (ad.VendorId == PCIV_ATI && IsL41LimitedATI()) + else if (ad.VendorId == PCIV_AMD && IsL41LimitedATI()) { #ifdef FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG m_avD3D11Context->workaround |= FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG; @@ -1434,11 +1434,8 @@ bool CDecoder::OpenDecoder() m_avD3D11Context->video_context = nullptr; m_avD3D11Context->surface_count = m_refs; - DXGI_ADAPTER_DESC AIdentifier = {}; - DX::DeviceResources::Get()->GetAdapterDesc(&AIdentifier); - - // use true shared buffers on Intel - bool trueShared = m_dxvaContext->IsContextShared() && AIdentifier.VendorId == PCIV_Intel; + // use true shared buffers always on Intel or Nvidia/AMD with recent drivers + const bool trueShared = DX::DeviceResources::Get()->IsDXVA2SharedDecoderSurfaces(); if (!m_dxvaContext->CreateSurfaces(m_format, m_avD3D11Context->surface_count, m_surface_alignment, m_avD3D11Context->surface, &m_sharedHandle, trueShared)) diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.cpp index 37c7015b28..b860993072 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.cpp +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.cpp @@ -54,6 +54,7 @@ using namespace std::chrono_literals; #define NUM_RENDER_PICS 7 constexpr auto SETTING_VIDEOPLAYER_USEVAAPI = "videoplayer.usevaapi"; +constexpr auto SETTING_VIDEOPLAYER_USEVAAPIAV1 = "videoplayer.usevaapiav1"; constexpr auto SETTING_VIDEOPLAYER_USEVAAPIHEVC = "videoplayer.usevaapihevc"; constexpr auto SETTING_VIDEOPLAYER_USEVAAPIMPEG2 = "videoplayer.usevaapimpeg2"; constexpr auto SETTING_VIDEOPLAYER_USEVAAPIMPEG4 = "videoplayer.usevaapimpeg4"; @@ -532,14 +533,15 @@ bool CDecoder::Open(AVCodecContext* avctx, AVCodecContext* mainctx, const enum A // check if user wants to decode this format with VAAPI std::map<AVCodecID, std::string> settings_map = { - { AV_CODEC_ID_H263, SETTING_VIDEOPLAYER_USEVAAPIMPEG4 }, - { AV_CODEC_ID_MPEG4, SETTING_VIDEOPLAYER_USEVAAPIMPEG4 }, - { AV_CODEC_ID_WMV3, SETTING_VIDEOPLAYER_USEVAAPIVC1 }, - { AV_CODEC_ID_VC1, SETTING_VIDEOPLAYER_USEVAAPIVC1 }, - { AV_CODEC_ID_MPEG2VIDEO, SETTING_VIDEOPLAYER_USEVAAPIMPEG2 }, - { AV_CODEC_ID_VP8, SETTING_VIDEOPLAYER_USEVAAPIVP8 }, - { AV_CODEC_ID_VP9, SETTING_VIDEOPLAYER_USEVAAPIVP9 }, - { AV_CODEC_ID_HEVC, SETTING_VIDEOPLAYER_USEVAAPIHEVC }, + {AV_CODEC_ID_H263, SETTING_VIDEOPLAYER_USEVAAPIMPEG4}, + {AV_CODEC_ID_MPEG4, SETTING_VIDEOPLAYER_USEVAAPIMPEG4}, + {AV_CODEC_ID_WMV3, SETTING_VIDEOPLAYER_USEVAAPIVC1}, + {AV_CODEC_ID_VC1, SETTING_VIDEOPLAYER_USEVAAPIVC1}, + {AV_CODEC_ID_MPEG2VIDEO, SETTING_VIDEOPLAYER_USEVAAPIMPEG2}, + {AV_CODEC_ID_VP8, SETTING_VIDEOPLAYER_USEVAAPIVP8}, + {AV_CODEC_ID_VP9, SETTING_VIDEOPLAYER_USEVAAPIVP9}, + {AV_CODEC_ID_HEVC, SETTING_VIDEOPLAYER_USEVAAPIHEVC}, + {AV_CODEC_ID_AV1, SETTING_VIDEOPLAYER_USEVAAPIAV1}, }; auto entry = settings_map.find(avctx->codec_id); @@ -585,6 +587,7 @@ bool CDecoder::Open(AVCodecContext* avctx, AVCodecContext* mainctx, const enum A m_vaapiConfig.surfaceWidth = avctx->coded_width; m_vaapiConfig.surfaceHeight = avctx->coded_height; m_vaapiConfig.aspect = avctx->sample_aspect_ratio; + m_vaapiConfig.bitDepth = avctx->bits_per_raw_sample; m_DisplayState = VAAPI_OPEN; m_vaapiConfigured = false; m_presentPicture = nullptr; @@ -672,6 +675,20 @@ bool CDecoder::Open(AVCodecContext* avctx, AVCodecContext* mainctx, const enum A if (!m_vaapiConfig.context->SupportsProfile(profile)) return false; break; +#if VA_CHECK_VERSION(1, 8, 0) + case AV_CODEC_ID_AV1: + { + if (avctx->profile == FF_PROFILE_AV1_MAIN) + profile = VAProfileAV1Profile0; + else if (avctx->profile == FF_PROFILE_AV1_HIGH) + profile = VAProfileAV1Profile1; + else + profile = VAProfileNone; + if (!m_vaapiConfig.context->SupportsProfile(profile)) + return false; + break; + } +#endif default: return false; } @@ -696,6 +713,8 @@ bool CDecoder::Open(AVCodecContext* avctx, AVCodecContext* mainctx, const enum A m_vaapiConfig.maxReferences = 16; else if (avctx->codec_id == AV_CODEC_ID_VP9) m_vaapiConfig.maxReferences = 8; + else if (avctx->codec_id == AV_CODEC_ID_AV1) + m_vaapiConfig.maxReferences = 18; else m_vaapiConfig.maxReferences = 2; @@ -1134,7 +1153,12 @@ bool CDecoder::ConfigVAAPI() unsigned int format = VA_RT_FORMAT_YUV420; std::int32_t pixelFormat = VA_FOURCC_NV12; - if (m_vaapiConfig.profile == VAProfileHEVCMain10) + if ((m_vaapiConfig.profile == VAProfileHEVCMain10 +#if VA_CHECK_VERSION(1, 8, 0) + || m_vaapiConfig.profile == VAProfileAV1Profile0 +#endif + ) && + m_vaapiConfig.bitDepth == 10) { format = VA_RT_FORMAT_YUV420_10BPP; pixelFormat = VA_FOURCC_P010; @@ -1256,11 +1280,12 @@ void CDecoder::Register(IVaapiWinSystem *winSystem, bool deepColor) if (!settings) return; - constexpr std::array<const char*, 8> vaapiSettings = { + constexpr std::array<const char*, 9> vaapiSettings = { SETTING_VIDEOPLAYER_USEVAAPI, SETTING_VIDEOPLAYER_USEVAAPIMPEG4, SETTING_VIDEOPLAYER_USEVAAPIVC1, SETTING_VIDEOPLAYER_USEVAAPIMPEG2, SETTING_VIDEOPLAYER_USEVAAPIVP8, SETTING_VIDEOPLAYER_USEVAAPIVP9, - SETTING_VIDEOPLAYER_USEVAAPIHEVC, SETTING_VIDEOPLAYER_PREFERVAAPIRENDER}; + SETTING_VIDEOPLAYER_USEVAAPIHEVC, SETTING_VIDEOPLAYER_PREFERVAAPIRENDER, + SETTING_VIDEOPLAYER_USEVAAPIAV1}; for (const auto vaapiSetting : vaapiSettings) { diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.h index 8f966849d3..001f1bf00e 100644 --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.h +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.h @@ -115,6 +115,7 @@ struct CVaapiConfig VAConfigAttrib attrib; CProcessInfo *processInfo; bool driverIsMesa; + int bitDepth; }; /** diff --git a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemux.h b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemux.h index 031b2cfe35..a16d2fe192 100644 --- a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemux.h +++ b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemux.h @@ -138,6 +138,7 @@ public: int iOrientation = 0; // orientation of the video in degrees counter clockwise int iBitsPerPixel = 0; int iBitRate = 0; + int bitDepth = 0; AVColorSpace colorSpace = AVCOL_SPC_UNSPECIFIED; AVColorRange colorRange = AVCOL_RANGE_UNSPECIFIED; diff --git a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp index 20ad677057..ad3c1c2d21 100644 --- a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp +++ b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxClient.cpp @@ -668,6 +668,8 @@ std::string CDVDDemuxClient::GetStreamCodecName(int iStreamId) strName = "vp9"; else if (stream->codec == AV_CODEC_ID_HEVC) strName = "hevc"; + else if (stream->codec == AV_CODEC_ID_AV1) + strName = "av1"; } return strName; } diff --git a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp index 7790befe56..8700c87b86 100644 --- a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +++ b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp @@ -33,6 +33,11 @@ #include <sstream> #include <utility> +extern "C" +{ +#include "libavutil/pixdesc.h" +} + #ifdef HAVE_LIBBLURAY #include "DVDInputStreams/DVDInputStreamBluray.h" #endif @@ -1639,6 +1644,11 @@ CDemuxStream* CDVDDemuxFFmpeg::AddStream(int streamIdx) st->iOrientation = 0; st->iBitsPerPixel = pStream->codecpar->bits_per_coded_sample; st->iBitRate = static_cast<int>(pStream->codecpar->bit_rate); + st->bitDepth = 8; + const AVPixFmtDescriptor* desc = + av_pix_fmt_desc_get(static_cast<AVPixelFormat>(pStream->codecpar->format)); + if (desc != nullptr && desc->comp != nullptr) + st->bitDepth = desc->comp[0].depth; st->colorPrimaries = pStream->codecpar->color_primaries; st->colorSpace = pStream->codecpar->color_space; diff --git a/xbmc/cores/VideoPlayer/DVDStreamInfo.cpp b/xbmc/cores/VideoPlayer/DVDStreamInfo.cpp index a30becd31f..ddf54c241b 100644 --- a/xbmc/cores/VideoPlayer/DVDStreamInfo.cpp +++ b/xbmc/cores/VideoPlayer/DVDStreamInfo.cpp @@ -71,6 +71,7 @@ void CDVDStreamInfo::Clear() channellayout = 0; orientation = 0; + bitdepth = 0; } bool CDVDStreamInfo::Equal(const CDVDStreamInfo& right, int compare) @@ -91,22 +92,26 @@ bool CDVDStreamInfo::Equal(const CDVDStreamInfo& right, int compare) } // VIDEO - if( fpsscale != right.fpsscale - || fpsrate != right.fpsrate - || height != right.height - || width != right.width - || stills != right.stills - || level != right.level - || profile != right.profile - || ptsinvalid != right.ptsinvalid - || forced_aspect != right.forced_aspect - || bitsperpixel != right.bitsperpixel - || vfr != right.vfr - || colorSpace != right.colorSpace - || colorRange != right.colorRange - || colorPrimaries != right.colorPrimaries - || colorTransferCharacteristic != right.colorTransferCharacteristic - || stereo_mode != right.stereo_mode ) return false; + // clang-format off + if (fpsscale != right.fpsscale + || fpsrate != right.fpsrate + || height != right.height + || width != right.width + || stills != right.stills + || level != right.level + || profile != right.profile + || ptsinvalid != right.ptsinvalid + || forced_aspect != right.forced_aspect + || bitsperpixel != right.bitsperpixel + || bitdepth != right.bitdepth + || vfr != right.vfr + || colorSpace != right.colorSpace + || colorRange != right.colorRange + || colorPrimaries != right.colorPrimaries + || colorTransferCharacteristic != right.colorTransferCharacteristic + || stereo_mode != right.stereo_mode) + return false; + // clang-format on if (masteringMetadata && right.masteringMetadata) { @@ -217,6 +222,7 @@ void CDVDStreamInfo::Assign(const CDVDStreamInfo& right, bool withextradata) forced_aspect = right.forced_aspect; orientation = right.orientation; bitsperpixel = right.bitsperpixel; + bitdepth = right.bitdepth; vfr = right.vfr; codecOptions = right.codecOptions; colorSpace = right.colorSpace; @@ -286,6 +292,7 @@ void CDVDStreamInfo::Assign(const CDemuxStream& right, bool withextradata) forced_aspect = stream->bForcedAspect; orientation = stream->iOrientation; bitsperpixel = stream->iBitsPerPixel; + bitdepth = stream->bitDepth; colorSpace = stream->colorSpace; colorRange = stream->colorRange; colorPrimaries = stream->colorPrimaries; diff --git a/xbmc/cores/VideoPlayer/DVDStreamInfo.h b/xbmc/cores/VideoPlayer/DVDStreamInfo.h index 25049a3b83..840b66e980 100644 --- a/xbmc/cores/VideoPlayer/DVDStreamInfo.h +++ b/xbmc/cores/VideoPlayer/DVDStreamInfo.h @@ -66,6 +66,7 @@ public: bool forced_aspect; // aspect is forced from container int orientation; // orientation of the video in degrees counter clockwise int bitsperpixel; + int bitdepth; AVColorSpace colorSpace; AVColorRange colorRange; AVColorPrimaries colorPrimaries; diff --git a/xbmc/cores/VideoPlayer/VideoPlayerVideo.cpp b/xbmc/cores/VideoPlayer/VideoPlayerVideo.cpp index 14c562ca00..28cb58c9d5 100644 --- a/xbmc/cores/VideoPlayer/VideoPlayerVideo.cpp +++ b/xbmc/cores/VideoPlayer/VideoPlayerVideo.cpp @@ -105,6 +105,7 @@ bool CVideoPlayerVideo::OpenStream(CDVDStreamInfo hint) if (hint.extrasize == 0) { // codecs which require extradata + // clang-format off if (hint.codec == AV_CODEC_ID_NONE || hint.codec == AV_CODEC_ID_MPEG1VIDEO || hint.codec == AV_CODEC_ID_MPEG2VIDEO || @@ -112,7 +113,9 @@ bool CVideoPlayerVideo::OpenStream(CDVDStreamInfo hint) hint.codec == AV_CODEC_ID_HEVC || hint.codec == AV_CODEC_ID_MPEG4 || hint.codec == AV_CODEC_ID_WMV3 || - hint.codec == AV_CODEC_ID_VC1) + hint.codec == AV_CODEC_ID_VC1 || + hint.codec == AV_CODEC_ID_AV1) + // clang-format on return false; } diff --git a/xbmc/dbwrappers/Database.cpp b/xbmc/dbwrappers/Database.cpp index aa93955e81..d899e4f44c 100644 --- a/xbmc/dbwrappers/Database.cpp +++ b/xbmc/dbwrappers/Database.cpp @@ -390,7 +390,7 @@ bool CDatabase::ExecuteQuery(const std::string &strQuery) return bReturn; } -bool CDatabase::ResultQuery(const std::string &strQuery) +bool CDatabase::ResultQuery(const std::string& strQuery) const { bool bReturn = false; diff --git a/xbmc/dbwrappers/Database.h b/xbmc/dbwrappers/Database.h index a3bf01d9c1..441d6f83fd 100644 --- a/xbmc/dbwrappers/Database.h +++ b/xbmc/dbwrappers/Database.h @@ -178,7 +178,7 @@ public: * @param strQuery The query to execute. * @return True if the query was executed successfully, false otherwise. */ - bool ResultQuery(const std::string &strQuery); + bool ResultQuery(const std::string& strQuery) const; /*! * @brief Start a multiple execution queue. Any ExecuteQuery() function diff --git a/xbmc/filesystem/AddonsDirectory.cpp b/xbmc/filesystem/AddonsDirectory.cpp index e2274b7657..89a4fed92b 100644 --- a/xbmc/filesystem/AddonsDirectory.cpp +++ b/xbmc/filesystem/AddonsDirectory.cpp @@ -543,7 +543,7 @@ static bool Browse(const CURL& path, CFileItemList &items) AddonPtr repoAddon; const auto& addonMgr = CServiceBroker::GetAddonMgr(); - if (!addonMgr.GetAddon(repoId, repoAddon, ADDON_REPOSITORY, OnlyEnabled::YES)) + if (!addonMgr.GetAddon(repoId, repoAddon, ADDON_REPOSITORY, OnlyEnabled::CHOICE_YES)) return false; CAddonRepos addonRepos(addonMgr); @@ -770,7 +770,7 @@ bool CAddonsDirectory::IsRepoDirectory(const CURL& url) return url.GetHostName() == "repos" || url.GetHostName() == "all" || url.GetHostName() == "search" || CServiceBroker::GetAddonMgr().GetAddon(url.GetHostName(), tmp, ADDON_REPOSITORY, - OnlyEnabled::YES); + OnlyEnabled::CHOICE_YES); } void CAddonsDirectory::GenerateAddonListing(const CURL& path, @@ -819,7 +819,7 @@ void CAddonsDirectory::GenerateAddonListing(const CURL& path, validUpdateOrigin = mapEntry->second.m_update->Origin(); } - bool fromOfficialRepo = CAddonRepos::IsFromOfficialRepo(addon, CheckAddonPath::NO); + bool fromOfficialRepo = CAddonRepos::IsFromOfficialRepo(addon, CheckAddonPath::CHOICE_NO); pItem->SetProperty("Addon.IsInstalled", installed); pItem->SetProperty("Addon.IsEnabled", installed && !disabled); diff --git a/xbmc/filesystem/PluginDirectory.cpp b/xbmc/filesystem/PluginDirectory.cpp index c89932c75d..894839fc56 100644 --- a/xbmc/filesystem/PluginDirectory.cpp +++ b/xbmc/filesystem/PluginDirectory.cpp @@ -71,11 +71,11 @@ bool CPluginDirectory::StartScript(const std::string& strPath, bool resume) ADDON::AddonPtr addon; // try the plugin type first, and if not found, try an unknown type if (!CServiceBroker::GetAddonMgr().GetAddon(url.GetHostName(), addon, ADDON_PLUGIN, - OnlyEnabled::YES) && + OnlyEnabled::CHOICE_YES) && !CServiceBroker::GetAddonMgr().GetAddon(url.GetHostName(), addon, ADDON_UNKNOWN, - OnlyEnabled::YES) && + OnlyEnabled::CHOICE_YES) && !CAddonInstaller::GetInstance().InstallModal(url.GetHostName(), addon, - InstallModalPrompt::PROMPT)) + InstallModalPrompt::CHOICE_YES)) { CLog::Log(LOGERROR, "Unable to find plugin {}", url.GetHostName()); return false; @@ -427,9 +427,9 @@ bool CPluginDirectory::RunScriptWithParams(const std::string& strPath, bool resu AddonPtr addon; if (!CServiceBroker::GetAddonMgr().GetAddon(url.GetHostName(), addon, ADDON_PLUGIN, - OnlyEnabled::YES) && + OnlyEnabled::CHOICE_YES) && !CAddonInstaller::GetInstance().InstallModal(url.GetHostName(), addon, - InstallModalPrompt::PROMPT)) + InstallModalPrompt::CHOICE_YES)) { CLog::Log(LOGERROR, "Unable to find plugin {}", url.GetHostName()); return false; @@ -512,7 +512,7 @@ bool CPluginDirectory::IsMediaLibraryScanningAllowed(const std::string& content, return false; AddonPtr addon; if (!CServiceBroker::GetAddonMgr().GetAddon(url.GetHostName(), addon, ADDON_PLUGIN, - OnlyEnabled::YES)) + OnlyEnabled::CHOICE_YES)) { CLog::Log(LOGERROR, "Unable to find plugin {}", url.GetHostName()); return false; diff --git a/xbmc/filesystem/ResourceFile.cpp b/xbmc/filesystem/ResourceFile.cpp index 65ac717093..4b0b5fd439 100644 --- a/xbmc/filesystem/ResourceFile.cpp +++ b/xbmc/filesystem/ResourceFile.cpp @@ -46,7 +46,8 @@ bool CResourceFile::TranslatePath(const CURL &url, std::string &translatedPath) return false; AddonPtr addon; - if (!CServiceBroker::GetAddonMgr().GetAddon(addonId, addon, ADDON_UNKNOWN, OnlyEnabled::YES) || + if (!CServiceBroker::GetAddonMgr().GetAddon(addonId, addon, ADDON_UNKNOWN, + OnlyEnabled::CHOICE_YES) || addon == NULL) return false; diff --git a/xbmc/filesystem/StackDirectory.cpp b/xbmc/filesystem/StackDirectory.cpp index 99c081f221..a752a94648 100644 --- a/xbmc/filesystem/StackDirectory.cpp +++ b/xbmc/filesystem/StackDirectory.cpp @@ -147,7 +147,7 @@ namespace XFILE std::string CStackDirectory::GetFirstStackedFile(const std::string &strPath) { // the stacked files are always in volume order, so just get up to the first filename - // occurence of " , " + // occurrence of " , " std::string file, folder; size_t pos = strPath.find(" , "); if (pos != std::string::npos) @@ -191,7 +191,7 @@ namespace XFILE std::string folder, file; URIUtils::Split(items[stack[0]]->GetPath(), folder, file); stackedPath += folder; - // double escape any occurence of commas + // double escape any occurrence of commas StringUtils::Replace(file, ",", ",,"); stackedPath += file; for (unsigned int i = 1; i < stack.size(); ++i) @@ -199,7 +199,7 @@ namespace XFILE stackedPath += " , "; file = items[stack[i]]->GetPath(); - // double escape any occurence of commas + // double escape any occurrence of commas StringUtils::Replace(file, ",", ",,"); stackedPath += file; } @@ -214,7 +214,7 @@ namespace XFILE std::string folder, file; URIUtils::Split(paths[0], folder, file); stackedPath += folder; - // double escape any occurence of commas + // double escape any occurrence of commas StringUtils::Replace(file, ",", ",,"); stackedPath += file; for (unsigned int i = 1; i < paths.size(); ++i) @@ -222,7 +222,7 @@ namespace XFILE stackedPath += " , "; file = paths[i]; - // double escape any occurence of commas + // double escape any occurrence of commas StringUtils::Replace(file, ",", ",,"); stackedPath += file; } diff --git a/xbmc/games/addons/GameClient.cpp b/xbmc/games/addons/GameClient.cpp index 12b4c60572..ce404c082c 100644 --- a/xbmc/games/addons/GameClient.cpp +++ b/xbmc/games/addons/GameClient.cpp @@ -420,7 +420,7 @@ std::string CGameClient::GetMissingResource() { AddonPtr addon; const bool bInstalled = CServiceBroker::GetAddonMgr().GetAddon( - strDependencyId, addon, ADDON_UNKNOWN, OnlyEnabled::YES); + strDependencyId, addon, ADDON_UNKNOWN, OnlyEnabled::CHOICE_YES); if (!bInstalled) { strAddonId = strDependencyId; diff --git a/xbmc/games/addons/GameClientProperties.cpp b/xbmc/games/addons/GameClientProperties.cpp index 14ef38d5b2..9994b4a231 100644 --- a/xbmc/games/addons/GameClientProperties.cpp +++ b/xbmc/games/addons/GameClientProperties.cpp @@ -113,7 +113,7 @@ const char** CGameClientProperties::GetResourceDirectories(void) const std::string& strAddonId = it->id; AddonPtr addon; if (CServiceBroker::GetAddonMgr().GetAddon(strAddonId, addon, ADDON_RESOURCE_GAMES, - OnlyEnabled::YES)) + OnlyEnabled::CHOICE_YES)) { std::shared_ptr<CGameResource> resource = std::static_pointer_cast<CGameResource>(addon); @@ -204,7 +204,7 @@ bool CGameClientProperties::GetProxyAddons(ADDON::VECADDONS& addons) { AddonPtr addon; if (CServiceBroker::GetAddonMgr().GetAddon(dependency.id, addon, ADDON_UNKNOWN, - OnlyEnabled::NO)) + OnlyEnabled::CHOICE_NO)) { // If add-on is disabled, ask the user to enable it if (CServiceBroker::GetAddonMgr().IsAddonDisabled(dependency.id)) diff --git a/xbmc/games/controllers/ControllerManager.cpp b/xbmc/games/controllers/ControllerManager.cpp index b6d64f5a46..d612020be3 100644 --- a/xbmc/games/controllers/ControllerManager.cpp +++ b/xbmc/games/controllers/ControllerManager.cpp @@ -26,7 +26,7 @@ ControllerPtr CControllerManager::GetController(const std::string& controllerId) { AddonPtr addon; if (CServiceBroker::GetAddonMgr().GetAddon(controllerId, addon, ADDON_GAME_CONTROLLER, - OnlyEnabled::NO)) + OnlyEnabled::CHOICE_NO)) cachedController = LoadController(addon); } diff --git a/xbmc/games/controllers/windows/ControllerInstaller.cpp b/xbmc/games/controllers/windows/ControllerInstaller.cpp index 390aad8f55..26cf854749 100644 --- a/xbmc/games/controllers/windows/ControllerInstaller.cpp +++ b/xbmc/games/controllers/windows/ControllerInstaller.cpp @@ -108,7 +108,7 @@ void CControllerInstaller::Process() pProgressDialog->SetPercentage(percentage); if (!ADDON::CAddonInstaller::GetInstance().InstallOrUpdate( - addon->ID(), ADDON::BackgroundJob::NO, ADDON::ModalJob::NO)) + addon->ID(), ADDON::BackgroundJob::CHOICE_NO, ADDON::ModalJob::CHOICE_NO)) { CLog::Log(LOGERROR, "Controller installer: Failed to install {}", addon->ID()); // "Error" diff --git a/xbmc/games/controllers/windows/GUIControllerWindow.cpp b/xbmc/games/controllers/windows/GUIControllerWindow.cpp index a2096e271a..d2570d001e 100644 --- a/xbmc/games/controllers/windows/GUIControllerWindow.cpp +++ b/xbmc/games/controllers/windows/GUIControllerWindow.cpp @@ -223,7 +223,8 @@ void CGUIControllerWindow::OnInitWindow(void) { ADDON::AddonPtr addon; if (CServiceBroker::GetAddonMgr().GetAddon(gameSettingsHandle->GameClientID(), addon, - ADDON::ADDON_GAMEDLL, ADDON::OnlyEnabled::YES)) + ADDON::ADDON_GAMEDLL, + ADDON::OnlyEnabled::CHOICE_YES)) gameClient = std::static_pointer_cast<CGameClient>(addon); } } diff --git a/xbmc/games/controllers/windows/GUIPortWindow.cpp b/xbmc/games/controllers/windows/GUIPortWindow.cpp index 0ba93284cd..47e7aa347b 100644 --- a/xbmc/games/controllers/windows/GUIPortWindow.cpp +++ b/xbmc/games/controllers/windows/GUIPortWindow.cpp @@ -119,7 +119,8 @@ void CGUIPortWindow::OnInitWindow() { ADDON::AddonPtr addon; if (CServiceBroker::GetAddonMgr().GetAddon(gameSettingsHandle->GameClientID(), addon, - ADDON::ADDON_GAMEDLL, ADDON::OnlyEnabled::YES)) + ADDON::ADDON_GAMEDLL, + ADDON::OnlyEnabled::CHOICE_YES)) gameClient = std::static_pointer_cast<CGameClient>(addon); } } diff --git a/xbmc/games/dialogs/GUIDialogSelectGameClient.cpp b/xbmc/games/dialogs/GUIDialogSelectGameClient.cpp index 3b2afa458a..66a24ef773 100644 --- a/xbmc/games/dialogs/GUIDialogSelectGameClient.cpp +++ b/xbmc/games/dialogs/GUIDialogSelectGameClient.cpp @@ -133,7 +133,7 @@ bool CGUIDialogSelectGameClient::Install(const std::string& gameClient) { ADDON::AddonPtr installedAddon; bInstalled = ADDON::CAddonInstaller::GetInstance().InstallModal( - gameClient, installedAddon, ADDON::InstallModalPrompt::NO_PROMPT); + gameClient, installedAddon, ADDON::InstallModalPrompt::CHOICE_NO); if (!bInstalled) { CLog::Log(LOGERROR, "Select game client dialog: Failed to install {}", gameClient); diff --git a/xbmc/games/dialogs/osd/DialogGameAdvancedSettings.cpp b/xbmc/games/dialogs/osd/DialogGameAdvancedSettings.cpp index 5a035c622d..dd3fc7f307 100644 --- a/xbmc/games/dialogs/osd/DialogGameAdvancedSettings.cpp +++ b/xbmc/games/dialogs/osd/DialogGameAdvancedSettings.cpp @@ -35,7 +35,8 @@ bool CDialogGameAdvancedSettings::OnMessage(CGUIMessage& message) { ADDON::AddonPtr addon; if (CServiceBroker::GetAddonMgr().GetAddon(gameSettingsHandle->GameClientID(), addon, - ADDON::ADDON_GAMEDLL, ADDON::OnlyEnabled::YES)) + ADDON::ADDON_GAMEDLL, + ADDON::OnlyEnabled::CHOICE_YES)) { gameSettingsHandle.reset(); CGUIDialogAddonSettings::ShowForAddon(addon); diff --git a/xbmc/guilib/GUIAudioManager.cpp b/xbmc/guilib/GUIAudioManager.cpp index 68dc454841..e374c2fecf 100644 --- a/xbmc/guilib/GUIAudioManager.cpp +++ b/xbmc/guilib/GUIAudioManager.cpp @@ -199,7 +199,7 @@ std::string GetSoundSkinPath() ADDON::AddonPtr addon; if (!CServiceBroker::GetAddonMgr().GetAddon(value, addon, ADDON::ADDON_RESOURCE_UISOUNDS, - ADDON::OnlyEnabled::YES)) + ADDON::OnlyEnabled::CHOICE_YES)) { CLog::Log(LOGINFO, "Unknown sounds addon '{}'. Setting default sounds.", value); setting->Reset(); diff --git a/xbmc/guilib/GUIBaseContainer.cpp b/xbmc/guilib/GUIBaseContainer.cpp index a38c32c6e7..d39b102a45 100644 --- a/xbmc/guilib/GUIBaseContainer.cpp +++ b/xbmc/guilib/GUIBaseContainer.cpp @@ -48,22 +48,65 @@ CGUIBaseContainer::CGUIBaseContainer(int parentID, int controlID, float posX, fl m_cacheItems = preloadItems; m_scrollItemsPerFrame = 0.0f; m_type = VIEW_TYPE_NONE; - m_listProvider = NULL; m_autoScrollMoveTime = 0; m_autoScrollDelayTime = 0; m_autoScrollIsReversed = false; m_lastRenderTime = 0; } -CGUIBaseContainer::CGUIBaseContainer(const CGUIBaseContainer &) = default; +CGUIBaseContainer::CGUIBaseContainer(const CGUIBaseContainer& other) + : IGUIContainer(other), + m_renderOffset(other.m_renderOffset), + m_analogScrollCount(other.m_analogScrollCount), + m_lastHoldTime(other.m_lastHoldTime), + m_orientation(other.m_orientation), + m_itemsPerPage(other.m_itemsPerPage), + m_pageControl(other.m_pageControl), + m_layoutCondition(other.m_layoutCondition), + m_focusedLayoutCondition(other.m_focusedLayoutCondition), + m_scroller(other.m_scroller), + m_listProvider(other.m_listProvider ? other.m_listProvider->Clone() : nullptr), + m_wasReset(other.m_wasReset), + m_letterOffsets(other.m_letterOffsets), + m_autoScrollCondition(other.m_autoScrollCondition), + m_autoScrollMoveTime(other.m_autoScrollMoveTime), + m_autoScrollDelayTime(other.m_autoScrollDelayTime), + m_autoScrollIsReversed(other.m_autoScrollIsReversed), + m_lastRenderTime(other.m_lastRenderTime), + m_cursor(other.m_cursor), + m_offset(other.m_offset), + m_cacheItems(other.m_cacheItems), + m_scrollTimer(other.m_scrollTimer), + m_lastScrollStartTimer(other.m_lastScrollStartTimer), + m_pageChangeTimer(other.m_pageChangeTimer), + m_clickActions(other.m_clickActions), + m_focusActions(other.m_focusActions), + m_unfocusActions(other.m_unfocusActions), + m_matchTimer(other.m_matchTimer), + m_match(other.m_match), + m_scrollItemsPerFrame(other.m_scrollItemsPerFrame), + m_gestureActive(other.m_gestureActive), + m_waitForScrollEnd(other.m_waitForScrollEnd), + m_lastScrollValue(other.m_lastScrollValue) +{ + // Initialize CGUIControl + m_bInvalidated = true; + + for (const auto& item : other.m_items) + m_items.emplace_back(std::make_shared<CGUIListItem>(*item)); + + for (const auto& layout : other.m_layouts) + m_layouts.emplace_back(layout, this); + + for (const auto& focusedLayout : other.m_focusedLayouts) + m_focusedLayouts.emplace_back(focusedLayout, this); +} CGUIBaseContainer::~CGUIBaseContainer(void) { // release the container from items for (const auto& item : m_items) item->FreeMemory(); - - delete m_listProvider; } void CGUIBaseContainer::DoProcess(unsigned int currentTime, CDirtyRegionList &dirtyregions) @@ -165,7 +208,7 @@ void CGUIBaseContainer::ProcessItem(float posX, float posY, CGUIListItemPtr& ite { if (!item->GetFocusedLayout()) { - item->SetFocusedLayout(CGUIListItemLayoutPtr(new CGUIListItemLayout(*m_focusedLayout, this))); + item->SetFocusedLayout(std::make_unique<CGUIListItemLayout>(*m_focusedLayout, this)); } if (item->GetFocusedLayout()) { @@ -191,8 +234,7 @@ void CGUIBaseContainer::ProcessItem(float posX, float posY, CGUIListItemPtr& ite item->GetFocusedLayout()->SetFocusedItem(0); // focus is not set if (!item->GetLayout()) { - CGUIListItemLayoutPtr layout(new CGUIListItemLayout(*m_layout)); - layout->SetParentControl(this); + CGUIListItemLayoutPtr layout = std::make_unique<CGUIListItemLayout>(*m_layout, this); item->SetLayout(std::move(layout)); } if (item->GetFocusedLayout()) @@ -1213,16 +1255,14 @@ void CGUIBaseContainer::LoadLayout(TiXmlElement *layout) void CGUIBaseContainer::LoadListProvider(TiXmlElement *content, int defaultItem, bool defaultAlways) { - delete m_listProvider; m_listProvider = IListProvider::Create(content, GetParentID()); if (m_listProvider) m_listProvider->SetDefaultItem(defaultItem, defaultAlways); } -void CGUIBaseContainer::SetListProvider(IListProvider *provider) +void CGUIBaseContainer::SetListProvider(std::unique_ptr<IListProvider> provider) { - delete m_listProvider; - m_listProvider = provider; + m_listProvider = std::move(provider); UpdateListProvider(true); } diff --git a/xbmc/guilib/GUIBaseContainer.h b/xbmc/guilib/GUIBaseContainer.h index 4237421335..2ca35f0026 100644 --- a/xbmc/guilib/GUIBaseContainer.h +++ b/xbmc/guilib/GUIBaseContainer.h @@ -18,6 +18,7 @@ #include "utils/Stopwatch.h" #include <list> +#include <memory> #include <utility> #include <vector> @@ -34,7 +35,7 @@ class CGUIBaseContainer : public IGUIContainer { public: CGUIBaseContainer(int parentID, int controlID, float posX, float posY, float width, float height, ORIENTATION orientation, const CScroller& scroller, int preloadItems); - CGUIBaseContainer(const CGUIBaseContainer &); + explicit CGUIBaseContainer(const CGUIBaseContainer& other); ~CGUIBaseContainer(void) override; bool OnAction(const CAction &action) override; @@ -75,7 +76,7 @@ public: /*! \brief Set the list provider for this container (for python). \param provider the list provider to use for this container. */ - void SetListProvider(IListProvider *provider); + void SetListProvider(std::unique_ptr<IListProvider> provider); /*! \brief Set the offset of the first item in the container from the container's position Useful for lists/panels where the focused item may be larger than the non-focused items and thus @@ -147,8 +148,8 @@ protected: std::list<CGUIListItemLayout> m_layouts; std::list<CGUIListItemLayout> m_focusedLayouts; - CGUIListItemLayout *m_layout; - CGUIListItemLayout *m_focusedLayout; + CGUIListItemLayout* m_layout{nullptr}; + CGUIListItemLayout* m_focusedLayout{nullptr}; bool m_layoutCondition = false; bool m_focusedLayoutCondition = false; @@ -158,7 +159,7 @@ protected: CScroller m_scroller; - IListProvider *m_listProvider; + std::unique_ptr<IListProvider> m_listProvider; bool m_wasReset; // true if we've received a Reset message until we've rendered once. Allows // us to make sure we don't tell the infomanager that we've been moving when diff --git a/xbmc/guilib/GUIButtonControl.cpp b/xbmc/guilib/GUIButtonControl.cpp index ec16e34d67..0e7f757edc 100644 --- a/xbmc/guilib/GUIButtonControl.cpp +++ b/xbmc/guilib/GUIButtonControl.cpp @@ -176,7 +176,7 @@ void CGUIButtonControl::ProcessText(unsigned int currentTime) // auto-width - adjust hitrect if (m_minWidth && m_width != renderWidth) { - CRect rect(m_posX, m_posY, renderWidth, m_height); + CRect rect{m_posX, m_posY, m_posX + renderWidth, m_posY + m_height}; SetHitRect(rect, m_hitColor); } diff --git a/xbmc/guilib/GUIControlFactory.cpp b/xbmc/guilib/GUIControlFactory.cpp index 9ce6711330..7119b9de13 100644 --- a/xbmc/guilib/GUIControlFactory.cpp +++ b/xbmc/guilib/GUIControlFactory.cpp @@ -1129,7 +1129,8 @@ CGUIControl* CGUIControlFactory::Create(int parentID, const CRect &rect, TiXmlEl break; case CGUIControl::GUICONTROL_LABEL: { - const GUIINFO::CGUIInfoLabel &content = (infoLabels.size()) ? infoLabels[0] : GUIINFO::CGUIInfoLabel(""); + static const GUIINFO::CGUIInfoLabel empty; + const GUIINFO::CGUIInfoLabel& content = !infoLabels.empty() ? infoLabels[0] : empty; if (insideContainer) { // inside lists we use CGUIListLabel control = new CGUIListLabel(parentID, id, posX, posY, width, height, labelInfo, content, scrollValue); diff --git a/xbmc/guilib/GUIControlGroup.h b/xbmc/guilib/GUIControlGroup.h index 57e8ac97f0..5f4a761374 100644 --- a/xbmc/guilib/GUIControlGroup.h +++ b/xbmc/guilib/GUIControlGroup.h @@ -26,7 +26,7 @@ class CGUIControlGroup : public CGUIControlLookup public: CGUIControlGroup(); CGUIControlGroup(int parentID, int controlID, float posX, float posY, float width, float height); - CGUIControlGroup(const CGUIControlGroup &from); + explicit CGUIControlGroup(const CGUIControlGroup& from); ~CGUIControlGroup(void) override; CGUIControlGroup* Clone() const override { return new CGUIControlGroup(*this); } diff --git a/xbmc/guilib/GUIControlLookup.cpp b/xbmc/guilib/GUIControlLookup.cpp index 33548a1ce5..8c572bb331 100644 --- a/xbmc/guilib/GUIControlLookup.cpp +++ b/xbmc/guilib/GUIControlLookup.cpp @@ -8,6 +8,10 @@ #include "GUIControlLookup.h" +CGUIControlLookup::CGUIControlLookup(const CGUIControlLookup& from) : CGUIControl(from) +{ +} + CGUIControl *CGUIControlLookup::GetControl(int iControl, std::vector<CGUIControl*> *idCollector) { if (idCollector) diff --git a/xbmc/guilib/GUIControlLookup.h b/xbmc/guilib/GUIControlLookup.h index 0118305a54..01175e4b90 100644 --- a/xbmc/guilib/GUIControlLookup.h +++ b/xbmc/guilib/GUIControlLookup.h @@ -16,8 +16,7 @@ public: CGUIControlLookup() = default; CGUIControlLookup(int parentID, int controlID, float posX, float posY, float width, float height) : CGUIControl(parentID, controlID, posX, posY, width, height) {} - CGUIControlLookup(const CGUIControlLookup &from) - : CGUIControl(from) {} + explicit CGUIControlLookup(const CGUIControlLookup& from); ~CGUIControlLookup(void) override = default; CGUIControl *GetControl(int id, std::vector<CGUIControl*> *idCollector = nullptr) override; diff --git a/xbmc/guilib/GUIDialog.cpp b/xbmc/guilib/GUIDialog.cpp index 56ec5f008b..3205f27901 100644 --- a/xbmc/guilib/GUIDialog.cpp +++ b/xbmc/guilib/GUIDialog.cpp @@ -38,16 +38,7 @@ CGUIDialog::~CGUIDialog(void) = default; bool CGUIDialog::Load(TiXmlElement* pRootElement) { - bool retVal = CGUIWindow::Load(pRootElement); - - if (retVal && IsCustom()) - { - // custom dialog's modality type is modeless if visible condition is specified. - if (m_visibleCondition) - m_modalityType = DialogModalityType::MODELESS; - } - - return retVal; + return CGUIWindow::Load(pRootElement); } void CGUIDialog::OnWindowLoaded() diff --git a/xbmc/guilib/GUIListContainer.cpp b/xbmc/guilib/GUIListContainer.cpp index 158cd769ca..b078263aa6 100644 --- a/xbmc/guilib/GUIListContainer.cpp +++ b/xbmc/guilib/GUIListContainer.cpp @@ -20,6 +20,10 @@ CGUIListContainer::CGUIListContainer(int parentID, int controlID, float posX, fl m_type = VIEW_TYPE_LIST; } +CGUIListContainer::CGUIListContainer(const CGUIListContainer& other) : CGUIBaseContainer(other) +{ +} + CGUIListContainer::~CGUIListContainer(void) = default; bool CGUIListContainer::OnAction(const CAction &action) diff --git a/xbmc/guilib/GUIListContainer.h b/xbmc/guilib/GUIListContainer.h index 3032cf6e1f..d16aa65bea 100644 --- a/xbmc/guilib/GUIListContainer.h +++ b/xbmc/guilib/GUIListContainer.h @@ -26,12 +26,13 @@ class CGUIListContainer : public CGUIBaseContainer { public: CGUIListContainer(int parentID, int controlID, float posX, float posY, float width, float height, ORIENTATION orientation, const CScroller& scroller, int preloadItems); -//#ifdef GUILIB_PYTHON_COMPATIBILITY + explicit CGUIListContainer(const CGUIListContainer& other); + //#ifdef GUILIB_PYTHON_COMPATIBILITY CGUIListContainer(int parentID, int controlID, float posX, float posY, float width, float height, const CLabelInfo& labelInfo, const CLabelInfo& labelInfo2, const CTextureInfo& textureButton, const CTextureInfo& textureButtonFocus, float textureHeight, float itemWidth, float itemHeight, float spaceBetweenItems); -//#endif + //#endif ~CGUIListContainer(void) override; CGUIListContainer* Clone() const override { return new CGUIListContainer(*this); } diff --git a/xbmc/guilib/GUIListGroup.h b/xbmc/guilib/GUIListGroup.h index 5316df2b8b..548cdec23e 100644 --- a/xbmc/guilib/GUIListGroup.h +++ b/xbmc/guilib/GUIListGroup.h @@ -23,7 +23,7 @@ class CGUIListGroup final : public CGUIControlGroup { public: CGUIListGroup(int parentID, int controlID, float posX, float posY, float width, float height); - CGUIListGroup(const CGUIListGroup &right); + explicit CGUIListGroup(const CGUIListGroup& right); ~CGUIListGroup(void) override; CGUIListGroup* Clone() const override { return new CGUIListGroup(*this); } diff --git a/xbmc/guilib/GUIListItem.h b/xbmc/guilib/GUIListItem.h index df53e3f333..7c2d0dd6d2 100644 --- a/xbmc/guilib/GUIListItem.h +++ b/xbmc/guilib/GUIListItem.h @@ -48,7 +48,7 @@ public: /// @} CGUIListItem(void); - CGUIListItem(const CGUIListItem& item); + explicit CGUIListItem(const CGUIListItem& item); explicit CGUIListItem(const std::string& strLabel); virtual ~CGUIListItem(void); virtual CGUIListItem* Clone() const { return new CGUIListItem(*this); } diff --git a/xbmc/guilib/GUIListItemLayout.cpp b/xbmc/guilib/GUIListItemLayout.cpp index e6bd96e46b..a8b51f2ce4 100644 --- a/xbmc/guilib/GUIListItemLayout.cpp +++ b/xbmc/guilib/GUIListItemLayout.cpp @@ -28,6 +28,11 @@ CGUIListItemLayout::CGUIListItemLayout() } CGUIListItemLayout::CGUIListItemLayout(const CGUIListItemLayout& from) + : CGUIListItemLayout(from, nullptr) +{ +} + +CGUIListItemLayout::CGUIListItemLayout(const CGUIListItemLayout& from, CGUIControl* control) : m_group(from.m_group), m_width(from.m_width), m_height(from.m_height), @@ -37,20 +42,12 @@ CGUIListItemLayout::CGUIListItemLayout(const CGUIListItemLayout& from) m_isPlaying(from.m_isPlaying), m_infoUpdateMillis(from.m_infoUpdateMillis) { + m_group.SetParentControl(control); m_infoUpdateTimeout.Set(m_infoUpdateMillis); -} -CGUIListItemLayout::CGUIListItemLayout(const CGUIListItemLayout &from, CGUIControl *control) -: m_group(from.m_group), m_isPlaying(from.m_isPlaying) -{ - m_width = from.m_width; - m_height = from.m_height; - m_focused = from.m_focused; - m_condition = from.m_condition; - m_infoUpdateMillis = from.m_infoUpdateMillis; - m_infoUpdateTimeout.Set(m_infoUpdateMillis); - m_invalidated = true; - m_group.SetParentControl(control); + // m_group was just created, cloned controls with resources must be allocated + // before use + m_group.AllocResources(); } bool CGUIListItemLayout::IsAnimating(ANIMATION_TYPE animType) diff --git a/xbmc/guilib/GUIListItemLayout.h b/xbmc/guilib/GUIListItemLayout.h index a15e2c9531..6a84b6573a 100644 --- a/xbmc/guilib/GUIListItemLayout.h +++ b/xbmc/guilib/GUIListItemLayout.h @@ -21,8 +21,8 @@ class CGUIListItemLayout final { public: CGUIListItemLayout(); - CGUIListItemLayout(const CGUIListItemLayout& from); - CGUIListItemLayout(const CGUIListItemLayout &from, CGUIControl *control); + explicit CGUIListItemLayout(const CGUIListItemLayout& from); + explicit CGUIListItemLayout(const CGUIListItemLayout& from, CGUIControl* control); void LoadLayout(TiXmlElement *layout, int context, bool focused, float maxWidth, float maxHeight); void Process(CGUIListItem *item, int parentID, unsigned int currentTime, CDirtyRegionList &dirtyregions); void Render(CGUIListItem *item, int parentID); @@ -51,7 +51,6 @@ public: bool CheckCondition(); protected: void LoadControl(TiXmlElement *child, CGUIControlGroup *group); - void Update(CFileItem *item); CGUIListGroup m_group; diff --git a/xbmc/guilib/GUIStaticItem.cpp b/xbmc/guilib/GUIStaticItem.cpp index f251c0bb5c..f7105671eb 100644 --- a/xbmc/guilib/GUIStaticItem.cpp +++ b/xbmc/guilib/GUIStaticItem.cpp @@ -64,6 +64,15 @@ CGUIStaticItem::CGUIStaticItem(const CFileItem &item) m_visState = false; } +CGUIStaticItem::CGUIStaticItem(const CGUIStaticItem& other) + : CFileItem(other), + m_info(other.m_info), + m_visCondition(other.m_visCondition), + m_visState(other.m_visState), + m_clickActions(other.m_clickActions) +{ +} + void CGUIStaticItem::UpdateProperties(int contextWindow) { for (const auto& i : m_info) diff --git a/xbmc/guilib/GUIStaticItem.h b/xbmc/guilib/GUIStaticItem.h index 4d4ff8cb44..a68f7394e5 100644 --- a/xbmc/guilib/GUIStaticItem.h +++ b/xbmc/guilib/GUIStaticItem.h @@ -51,6 +51,7 @@ public: */ CGUIStaticItem(const TiXmlElement *element, int contextWindow); explicit CGUIStaticItem(const CFileItem &item); // for python + explicit CGUIStaticItem(const CGUIStaticItem& other); ~CGUIStaticItem() override = default; CGUIListItem* Clone() const override { return new CGUIStaticItem(*this); } diff --git a/xbmc/guilib/guiinfo/AddonsGUIInfo.cpp b/xbmc/guilib/guiinfo/AddonsGUIInfo.cpp index 999d746cd8..174b0c1e6a 100644 --- a/xbmc/guilib/guiinfo/AddonsGUIInfo.cpp +++ b/xbmc/guilib/guiinfo/AddonsGUIInfo.cpp @@ -155,7 +155,7 @@ bool CAddonsGUIInfo::GetLabel(std::string& value, const CFileItem *item, int con if (!info.GetData3().empty()) { bool success = CServiceBroker::GetAddonMgr().GetAddon( - info.GetData3(), addon, ADDON::ADDON_UNKNOWN, ADDON::OnlyEnabled::YES); + info.GetData3(), addon, ADDON::ADDON_UNKNOWN, ADDON::OnlyEnabled::CHOICE_YES); if (!success || !addon) break; @@ -205,7 +205,7 @@ bool CAddonsGUIInfo::GetBool(bool& value, const CGUIListItem *gitem, int context value = false; ADDON::AddonPtr addon; if (CServiceBroker::GetAddonMgr().GetAddon(info.GetData3(), addon, ADDON::ADDON_UNKNOWN, - ADDON::OnlyEnabled::YES)) + ADDON::OnlyEnabled::CHOICE_YES)) value = !CServiceBroker::GetAddonMgr().IsAddonDisabled(info.GetData3()); return true; } diff --git a/xbmc/guilib/guiinfo/VisualisationGUIInfo.cpp b/xbmc/guilib/guiinfo/VisualisationGUIInfo.cpp index 8400ad9860..2fe972255d 100644 --- a/xbmc/guilib/guiinfo/VisualisationGUIInfo.cpp +++ b/xbmc/guilib/guiinfo/VisualisationGUIInfo.cpp @@ -55,7 +55,7 @@ bool CVisualisationGUIInfo::GetLabel(std::string& value, const CFileItem *item, ADDON::AddonPtr addon; value = CServiceBroker::GetSettingsComponent()->GetSettings()->GetString(CSettings::SETTING_MUSICPLAYER_VISUALISATION); if (CServiceBroker::GetAddonMgr().GetAddon(value, addon, ADDON::ADDON_UNKNOWN, - ADDON::OnlyEnabled::YES) && + ADDON::OnlyEnabled::CHOICE_YES) && addon) { value = addon->Name(); diff --git a/xbmc/input/joysticks/dialogs/GUIDialogNewJoystick.cpp b/xbmc/input/joysticks/dialogs/GUIDialogNewJoystick.cpp index 8ac8adee11..b66ce89af4 100644 --- a/xbmc/input/joysticks/dialogs/GUIDialogNewJoystick.cpp +++ b/xbmc/input/joysticks/dialogs/GUIDialogNewJoystick.cpp @@ -47,7 +47,7 @@ void CGUIDialogNewJoystick::Process() // "New controller detected" // "A new controller has been detected. Configuration can be done at any time in "Settings -> // System Settings -> Input". Would you like to configure it now?" - if (ShowYesNoDialogText(CVariant{35011}, CVariant{35012}) == DialogResponse::YES) + if (ShowYesNoDialogText(CVariant{35011}, CVariant{35012}) == DialogResponse::CHOICE_YES) { CServiceBroker::GetGUI()->GetWindowManager().ActivateWindow(WINDOW_DIALOG_GAME_CONTROLLERS); } diff --git a/xbmc/interfaces/builtins/AddonBuiltins.cpp b/xbmc/interfaces/builtins/AddonBuiltins.cpp index 177a5aa4dd..aba6a748d1 100644 --- a/xbmc/interfaces/builtins/AddonBuiltins.cpp +++ b/xbmc/interfaces/builtins/AddonBuiltins.cpp @@ -53,7 +53,7 @@ static int InstallAddon(const std::vector<std::string>& params) const std::string& addonid = params[0]; AddonPtr addon; - CAddonInstaller::GetInstance().InstallModal(addonid, addon, InstallModalPrompt::PROMPT); + CAddonInstaller::GetInstance().InstallModal(addonid, addon, InstallModalPrompt::CHOICE_YES); return 0; } @@ -70,11 +70,12 @@ static int EnableAddon(const std::vector<std::string>& params) return -1; AddonPtr addon; - if (!CServiceBroker::GetAddonMgr().GetAddon(addonid, addon, ADDON_UNKNOWN, OnlyEnabled::NO)) + if (!CServiceBroker::GetAddonMgr().GetAddon(addonid, addon, ADDON_UNKNOWN, + OnlyEnabled::CHOICE_NO)) return -1; auto response = HELPERS::ShowYesNoDialogLines(CVariant{24076}, CVariant{24135}, CVariant{addon->Name()}, CVariant{24136}); - if (response == DialogResponse::YES) + if (response == DialogResponse::CHOICE_YES) CServiceBroker::GetAddonMgr().EnableAddon(addonid); return 0; @@ -117,7 +118,8 @@ static int RunAddon(const std::vector<std::string>& params) const std::string& addonid = params[0]; AddonPtr addon; - if (CServiceBroker::GetAddonMgr().GetAddon(addonid, addon, ADDON_PLUGIN, OnlyEnabled::YES)) + if (CServiceBroker::GetAddonMgr().GetAddon(addonid, addon, ADDON_PLUGIN, + OnlyEnabled::CHOICE_YES)) { PluginPtr plugin = std::dynamic_pointer_cast<CPluginSource>(addon); std::string urlParameters; @@ -160,13 +162,13 @@ static int RunAddon(const std::vector<std::string>& params) CBuiltins::GetInstance().Execute(cmd); } else if (CServiceBroker::GetAddonMgr().GetAddon(addonid, addon, ADDON_SCRIPT, - OnlyEnabled::YES) || + OnlyEnabled::CHOICE_YES) || CServiceBroker::GetAddonMgr().GetAddon(addonid, addon, ADDON_SCRIPT_WEATHER, - OnlyEnabled::YES) || + OnlyEnabled::CHOICE_YES) || CServiceBroker::GetAddonMgr().GetAddon(addonid, addon, ADDON_SCRIPT_LYRICS, - OnlyEnabled::YES) || + OnlyEnabled::CHOICE_YES) || CServiceBroker::GetAddonMgr().GetAddon(addonid, addon, ADDON_SCRIPT_LIBRARY, - OnlyEnabled::YES)) + OnlyEnabled::CHOICE_YES)) { // Pass the script name (addonid) and all the parameters // (params[1] ... params[x]) separated by a comma to RunScript @@ -174,7 +176,7 @@ static int RunAddon(const std::vector<std::string>& params) StringUtils::Format("RunScript({})", StringUtils::Join(params, ","))); } else if (CServiceBroker::GetAddonMgr().GetAddon(addonid, addon, ADDON_GAMEDLL, - OnlyEnabled::YES)) + OnlyEnabled::CHOICE_YES)) { CFileItem item; @@ -236,17 +238,18 @@ static int RunScript(const std::vector<std::string>& params) AddonPtr addon; std::string scriptpath; // Test to see if the param is an addon ID - if (CServiceBroker::GetAddonMgr().GetAddon(params[0], addon, ADDON_UNKNOWN, OnlyEnabled::YES)) + if (CServiceBroker::GetAddonMgr().GetAddon(params[0], addon, ADDON_UNKNOWN, + OnlyEnabled::CHOICE_YES)) { //Get the correct extension point to run if (CServiceBroker::GetAddonMgr().GetAddon(params[0], addon, ADDON_SCRIPT, - OnlyEnabled::YES) || + OnlyEnabled::CHOICE_YES) || CServiceBroker::GetAddonMgr().GetAddon(params[0], addon, ADDON_SCRIPT_WEATHER, - OnlyEnabled::YES) || + OnlyEnabled::CHOICE_YES) || CServiceBroker::GetAddonMgr().GetAddon(params[0], addon, ADDON_SCRIPT_LYRICS, - OnlyEnabled::YES) || + OnlyEnabled::CHOICE_YES) || CServiceBroker::GetAddonMgr().GetAddon(params[0], addon, ADDON_SCRIPT_LIBRARY, - OnlyEnabled::YES)) + OnlyEnabled::CHOICE_YES)) { scriptpath = addon->LibPath(); } @@ -254,7 +257,7 @@ static int RunScript(const std::vector<std::string>& params) { // Run a random extension point (old behaviour). if (CServiceBroker::GetAddonMgr().GetAddon(params[0], addon, ADDON_UNKNOWN, - OnlyEnabled::YES)) + OnlyEnabled::CHOICE_YES)) { scriptpath = addon->LibPath(); CLog::Log(LOGWARNING, @@ -330,7 +333,8 @@ static int SetDefaultAddon(const std::vector<std::string>& params) static int AddonSettings(const std::vector<std::string>& params) { AddonPtr addon; - if (CServiceBroker::GetAddonMgr().GetAddon(params[0], addon, ADDON_UNKNOWN, OnlyEnabled::YES)) + if (CServiceBroker::GetAddonMgr().GetAddon(params[0], addon, ADDON_UNKNOWN, + OnlyEnabled::CHOICE_YES)) CGUIDialogAddonSettings::ShowForAddon(addon); return 0; @@ -358,7 +362,8 @@ static int StopScript(const std::vector<std::string>& params) std::string scriptpath(params[0]); // Test to see if the param is an addon ID AddonPtr script; - if (CServiceBroker::GetAddonMgr().GetAddon(params[0], script, ADDON_UNKNOWN, OnlyEnabled::YES)) + if (CServiceBroker::GetAddonMgr().GetAddon(params[0], script, ADDON_UNKNOWN, + OnlyEnabled::CHOICE_YES)) scriptpath = script->LibPath(); CScriptInvocationManager::GetInstance().Stop(scriptpath); diff --git a/xbmc/interfaces/builtins/LibraryBuiltins.cpp b/xbmc/interfaces/builtins/LibraryBuiltins.cpp index 75c931440e..7d11ce83d9 100644 --- a/xbmc/interfaces/builtins/LibraryBuiltins.cpp +++ b/xbmc/interfaces/builtins/LibraryBuiltins.cpp @@ -135,8 +135,8 @@ static int ExportLibrary(const std::vector<std::string>& params) else { HELPERS::DialogResponse result = HELPERS::ShowYesNoDialogText(CVariant{iHeading}, CVariant{20426}, CVariant{20428}, CVariant{20429}); - cancelled = result == HELPERS::DialogResponse::CANCELLED; - singleFile = result != HELPERS::DialogResponse::YES; + cancelled = result == HELPERS::DialogResponse::CHOICE_CANCELLED; + singleFile = result != HELPERS::DialogResponse::CHOICE_YES; } if (cancelled) @@ -149,8 +149,8 @@ static int ExportLibrary(const std::vector<std::string>& params) else { HELPERS::DialogResponse result = HELPERS::ShowYesNoDialogText(CVariant{iHeading}, CVariant{20430}); - cancelled = result == HELPERS::DialogResponse::CANCELLED; - thumbs = result == HELPERS::DialogResponse::YES; + cancelled = result == HELPERS::DialogResponse::CHOICE_CANCELLED; + thumbs = result == HELPERS::DialogResponse::CHOICE_YES; } } @@ -164,7 +164,7 @@ static int ExportLibrary(const std::vector<std::string>& params) if (movieSetsInfoPath.empty()) { auto result = HELPERS::ShowYesNoDialogText(CVariant{iHeading}, CVariant{36301}); - cancelled = result != HELPERS::DialogResponse::YES; + cancelled = result != HELPERS::DialogResponse::CHOICE_YES; } } @@ -178,8 +178,8 @@ static int ExportLibrary(const std::vector<std::string>& params) else { HELPERS::DialogResponse result = HELPERS::ShowYesNoDialogText(CVariant{iHeading}, CVariant{20436}); - cancelled = result == HELPERS::DialogResponse::CANCELLED; - actorThumbs = result == HELPERS::DialogResponse::YES; + cancelled = result == HELPERS::DialogResponse::CHOICE_CANCELLED; + actorThumbs = result == HELPERS::DialogResponse::CHOICE_YES; } } @@ -193,8 +193,8 @@ static int ExportLibrary(const std::vector<std::string>& params) else { HELPERS::DialogResponse result = HELPERS::ShowYesNoDialogText(CVariant{iHeading}, CVariant{20431}); - cancelled = result == HELPERS::DialogResponse::CANCELLED; - overwrite = result == HELPERS::DialogResponse::YES; + cancelled = result == HELPERS::DialogResponse::CHOICE_CANCELLED; + overwrite = result == HELPERS::DialogResponse::CHOICE_YES; } } diff --git a/xbmc/interfaces/json-rpc/AddonsOperations.cpp b/xbmc/interfaces/json-rpc/AddonsOperations.cpp index e08ba34d63..0cb5cff6e3 100644 --- a/xbmc/interfaces/json-rpc/AddonsOperations.cpp +++ b/xbmc/interfaces/json-rpc/AddonsOperations.cpp @@ -131,7 +131,8 @@ JSONRPC_STATUS CAddonsOperations::GetAddonDetails(const std::string &method, ITr { std::string id = parameterObject["addonid"].asString(); AddonPtr addon; - if (!CServiceBroker::GetAddonMgr().GetAddon(id, addon, ADDON::ADDON_UNKNOWN, OnlyEnabled::NO) || + if (!CServiceBroker::GetAddonMgr().GetAddon(id, addon, ADDON::ADDON_UNKNOWN, + OnlyEnabled::CHOICE_NO) || addon.get() == NULL || addon->Type() <= ADDON_UNKNOWN || addon->Type() >= ADDON_MAX) return InvalidParams; @@ -145,7 +146,8 @@ JSONRPC_STATUS CAddonsOperations::SetAddonEnabled(const std::string &method, ITr { std::string id = parameterObject["addonid"].asString(); AddonPtr addon; - if (!CServiceBroker::GetAddonMgr().GetAddon(id, addon, ADDON::ADDON_UNKNOWN, OnlyEnabled::NO) || + if (!CServiceBroker::GetAddonMgr().GetAddon(id, addon, ADDON::ADDON_UNKNOWN, + OnlyEnabled::CHOICE_NO) || addon == nullptr || addon->Type() <= ADDON_UNKNOWN || addon->Type() >= ADDON_MAX) return InvalidParams; @@ -175,7 +177,7 @@ JSONRPC_STATUS CAddonsOperations::ExecuteAddon(const std::string &method, ITrans { std::string id = parameterObject["addonid"].asString(); AddonPtr addon; - if (!CServiceBroker::GetAddonMgr().GetAddon(id, addon, ADDON_UNKNOWN, OnlyEnabled::YES) || + if (!CServiceBroker::GetAddonMgr().GetAddon(id, addon, ADDON_UNKNOWN, OnlyEnabled::CHOICE_YES) || addon.get() == NULL || addon->Type() < ADDON_VIZ || addon->Type() >= ADDON_MAX) return InvalidParams; diff --git a/xbmc/interfaces/json-rpc/GUIOperations.cpp b/xbmc/interfaces/json-rpc/GUIOperations.cpp index 407489323d..e873c92e3a 100644 --- a/xbmc/interfaces/json-rpc/GUIOperations.cpp +++ b/xbmc/interfaces/json-rpc/GUIOperations.cpp @@ -136,7 +136,7 @@ JSONRPC_STATUS CGUIOperations::GetPropertyValue(const std::string &property, CVa { std::string skinId = CServiceBroker::GetSettingsComponent()->GetSettings()->GetString(CSettings::SETTING_LOOKANDFEEL_SKIN); AddonPtr addon; - if (!CServiceBroker::GetAddonMgr().GetAddon(skinId, addon, ADDON_SKIN, OnlyEnabled::YES)) + if (!CServiceBroker::GetAddonMgr().GetAddon(skinId, addon, ADDON_SKIN, OnlyEnabled::CHOICE_YES)) return InternalError; result["id"] = skinId; diff --git a/xbmc/interfaces/legacy/Addon.cpp b/xbmc/interfaces/legacy/Addon.cpp index 71b9712eb4..bf39d4cbee 100644 --- a/xbmc/interfaces/legacy/Addon.cpp +++ b/xbmc/interfaces/legacy/Addon.cpp @@ -64,7 +64,7 @@ namespace XBMCAddon "wasn't executed in a normal Kodi manner."); if (!CServiceBroker::GetAddonMgr().GetAddon(id.c_str(), pAddon, ADDON_UNKNOWN, - OnlyEnabled::YES)) + OnlyEnabled::CHOICE_YES)) throw AddonException("Unknown addon id '%s'.", id.c_str()); CServiceBroker::GetAddonMgr().AddToUpdateableAddons(pAddon); diff --git a/xbmc/interfaces/legacy/Control.cpp b/xbmc/interfaces/legacy/Control.cpp index 1e87083802..a6f336b384 100644 --- a/xbmc/interfaces/legacy/Control.cpp +++ b/xbmc/interfaces/legacy/Control.cpp @@ -1406,8 +1406,8 @@ namespace XBMCAddon } // set static list - IListProvider *provider = new CStaticListProvider(items); - static_cast<CGUIBaseContainer*>(pGUIControl)->SetListProvider(provider); + std::unique_ptr<IListProvider> provider = std::make_unique<CStaticListProvider>(items); + static_cast<CGUIBaseContainer*>(pGUIControl)->SetListProvider(std::move(provider)); } // ============================================================ diff --git a/xbmc/interfaces/legacy/Settings.h b/xbmc/interfaces/legacy/Settings.h index e4a583a269..8b8bb0eeb0 100644 --- a/xbmc/interfaces/legacy/Settings.h +++ b/xbmc/interfaces/legacy/Settings.h @@ -45,7 +45,7 @@ XBMCCOMMONS_STANDARD_EXCEPTION(SettingCallbacksNotSupportedException); /// **Example:** /// ~~~~~~~~~~~~~{.py} /// ... -/// settings = xbmc.Addon('id').getSettings() +/// settings = xbmcaddon.Addon('id').getSettings() /// ... /// ~~~~~~~~~~~~~ // diff --git a/xbmc/interfaces/python/PythonInvoker.cpp b/xbmc/interfaces/python/PythonInvoker.cpp index 93b26c0154..f04ce32c37 100644 --- a/xbmc/interfaces/python/PythonInvoker.cpp +++ b/xbmc/interfaces/python/PythonInvoker.cpp @@ -724,7 +724,7 @@ void CPythonInvoker::getAddonModuleDeps(const ADDON::AddonPtr& addon, std::set<s //Check if dependency is a module addon ADDON::AddonPtr dependency; if (CServiceBroker::GetAddonMgr().GetAddon(it.id, dependency, ADDON::ADDON_SCRIPT_MODULE, - ADDON::OnlyEnabled::YES)) + ADDON::OnlyEnabled::CHOICE_YES)) { std::string path = CSpecialProtocol::TranslatePath(dependency->LibPath()); if (paths.find(path) == paths.end()) diff --git a/xbmc/listproviders/DirectoryProvider.cpp b/xbmc/listproviders/DirectoryProvider.cpp index 2c7eef275a..0b20a9dcf9 100644 --- a/xbmc/listproviders/DirectoryProvider.cpp +++ b/xbmc/listproviders/DirectoryProvider.cpp @@ -180,11 +180,33 @@ CDirectoryProvider::CDirectoryProvider(const TiXmlElement *element, int parentID } } +CDirectoryProvider::CDirectoryProvider(const CDirectoryProvider& other) + : IListProvider(other.m_parentID), + m_updateState(INVALIDATED), + m_isAnnounced(false), + m_jobID(0), + m_url(other.m_url), + m_target(other.m_target), + m_sortMethod(other.m_sortMethod), + m_sortOrder(other.m_sortOrder), + m_limit(other.m_limit), + m_currentUrl(other.m_currentUrl), + m_currentTarget(other.m_currentTarget), + m_currentSort(other.m_currentSort), + m_currentLimit(other.m_currentLimit) +{ +} + CDirectoryProvider::~CDirectoryProvider() { Reset(); } +std::unique_ptr<IListProvider> CDirectoryProvider::Clone() +{ + return std::make_unique<CDirectoryProvider>(*this); +} + bool CDirectoryProvider::Update(bool forceRefresh) { // we never need to force refresh here diff --git a/xbmc/listproviders/DirectoryProvider.h b/xbmc/listproviders/DirectoryProvider.h index 42a03c7930..6906bd4986 100644 --- a/xbmc/listproviders/DirectoryProvider.h +++ b/xbmc/listproviders/DirectoryProvider.h @@ -51,8 +51,11 @@ public: } UpdateState; CDirectoryProvider(const TiXmlElement *element, int parentID); + explicit CDirectoryProvider(const CDirectoryProvider& other); ~CDirectoryProvider() override; + // Implementation of IListProvider + std::unique_ptr<IListProvider> Clone() override; bool Update(bool forceRefresh) override; void Announce(ANNOUNCEMENT::AnnouncementFlag flag, const std::string& sender, diff --git a/xbmc/listproviders/IListProvider.cpp b/xbmc/listproviders/IListProvider.cpp index 09148c0a60..3979319ba7 100644 --- a/xbmc/listproviders/IListProvider.cpp +++ b/xbmc/listproviders/IListProvider.cpp @@ -13,28 +13,28 @@ #include "StaticProvider.h" #include "utils/XBMCTinyXML.h" -IListProvider *IListProvider::Create(const TiXmlNode *node, int parentID) +std::unique_ptr<IListProvider> IListProvider::Create(const TiXmlNode* node, int parentID) { const TiXmlNode *root = node->FirstChild("content"); if (root) { const TiXmlNode *next = root->NextSibling("content"); if (next) - return new CMultiProvider(root, parentID); + return std::make_unique<CMultiProvider>(root, parentID); return CreateSingle(root, parentID); } - return NULL; + return std::unique_ptr<IListProvider>{}; } -IListProvider *IListProvider::CreateSingle(const TiXmlNode *content, int parentID) +std::unique_ptr<IListProvider> IListProvider::CreateSingle(const TiXmlNode* content, int parentID) { const TiXmlElement *item = content->FirstChildElement("item"); if (item) - return new CStaticListProvider(content->ToElement(), parentID); + return std::make_unique<CStaticListProvider>(content->ToElement(), parentID); if (!content->NoChildren()) - return new CDirectoryProvider(content->ToElement(), parentID); + return std::make_unique<CDirectoryProvider>(content->ToElement(), parentID); - return NULL; + return std::unique_ptr<IListProvider>{}; } diff --git a/xbmc/listproviders/IListProvider.h b/xbmc/listproviders/IListProvider.h index f92d99c534..501b399c1f 100644 --- a/xbmc/listproviders/IListProvider.h +++ b/xbmc/listproviders/IListProvider.h @@ -23,21 +23,26 @@ class IListProvider { public: explicit IListProvider(int parentID) : m_parentID(parentID) {} + explicit IListProvider(const IListProvider& other) = default; virtual ~IListProvider() = default; /*! \brief Factory to create list providers. \param parent a parent TiXmlNode for the container. \param parentID id of parent window for context. - \return the list provider, NULL if none. + \return the list provider, empty pointer if none. */ - static IListProvider *Create(const TiXmlNode *parent, int parentID); + static std::unique_ptr<IListProvider> Create(const TiXmlNode* parent, int parentID); /*! \brief Factory to create list providers. Cannot create a multi-provider. \param content the TiXmlNode for the content to create. \param parentID id of parent window for context. - \return the list provider, NULL if none. + \return the list provider, empty pointer if none. */ - static IListProvider *CreateSingle(const TiXmlNode *content, int parentID); + static std::unique_ptr<IListProvider> CreateSingle(const TiXmlNode* content, int parentID); + + /*! \brief Create an instance of the derived class. Allows for polymorphic copies. + */ + virtual std::unique_ptr<IListProvider> Clone() = 0; /*! \brief Update the list content \return true if the content has changed, false otherwise. diff --git a/xbmc/listproviders/MultiProvider.cpp b/xbmc/listproviders/MultiProvider.cpp index be5fde4457..6791cf4a79 100644 --- a/xbmc/listproviders/MultiProvider.cpp +++ b/xbmc/listproviders/MultiProvider.cpp @@ -18,10 +18,25 @@ CMultiProvider::CMultiProvider(const TiXmlNode *first, int parentID) { IListProviderPtr sub(IListProvider::CreateSingle(content, parentID)); if (sub) - m_providers.push_back(sub); + m_providers.push_back(std::move(sub)); } } +CMultiProvider::CMultiProvider(const CMultiProvider& other) : IListProvider(other.m_parentID) +{ + for (const auto& provider : other.m_providers) + { + std::unique_ptr<IListProvider> newProvider = provider->Clone(); + if (newProvider) + m_providers.emplace_back(std::move(newProvider)); + } +} + +std::unique_ptr<IListProvider> CMultiProvider::Clone() +{ + return std::make_unique<CMultiProvider>(*this); +} + bool CMultiProvider::Update(bool forceRefresh) { bool result = false; @@ -42,7 +57,7 @@ void CMultiProvider::Fetch(std::vector<CGUIListItemPtr> &items) for (auto& item : subItems) { auto key = GetItemKey(item); - m_itemMap[key] = provider; + m_itemMap[key] = provider.get(); items.push_back(item); } subItems.clear(); diff --git a/xbmc/listproviders/MultiProvider.h b/xbmc/listproviders/MultiProvider.h index 01664ecb9a..9eeddc012d 100644 --- a/xbmc/listproviders/MultiProvider.h +++ b/xbmc/listproviders/MultiProvider.h @@ -14,7 +14,7 @@ #include <map> #include <vector> -typedef std::shared_ptr<IListProvider> IListProviderPtr; +typedef std::unique_ptr<IListProvider> IListProviderPtr; /*! \ingroup listproviders @@ -24,7 +24,10 @@ class CMultiProvider : public IListProvider { public: CMultiProvider(const TiXmlNode *first, int parentID); + explicit CMultiProvider(const CMultiProvider& other); + // Implementation of IListProvider + std::unique_ptr<IListProvider> Clone() override; bool Update(bool forceRefresh) override; void Fetch(std::vector<CGUIListItemPtr> &items) override; bool IsUpdating() const override; @@ -37,6 +40,6 @@ protected: typedef size_t item_key_type; static item_key_type GetItemKey(CGUIListItemPtr const &item); std::vector<IListProviderPtr> m_providers; - std::map<item_key_type, IListProviderPtr> m_itemMap; + std::map<item_key_type, IListProvider*> m_itemMap; CCriticalSection m_section; // protects m_itemMap }; diff --git a/xbmc/listproviders/StaticProvider.cpp b/xbmc/listproviders/StaticProvider.cpp index 7f339b30c1..85c9d5b0e4 100644 --- a/xbmc/listproviders/StaticProvider.cpp +++ b/xbmc/listproviders/StaticProvider.cpp @@ -47,8 +47,33 @@ CStaticListProvider::CStaticListProvider(const std::vector<CGUIStaticItemPtr> &i { } +CStaticListProvider::CStaticListProvider(const CStaticListProvider& other) + : IListProvider(other.m_parentID), + m_defaultItem(other.m_defaultItem), + m_defaultAlways(other.m_defaultAlways), + m_updateTime(other.m_updateTime) +{ + for (const auto& item : other.m_items) + { + std::shared_ptr<CGUIListItem> control(item->Clone()); + if (!control) + continue; + + std::shared_ptr<CGUIStaticItem> newItem = std::dynamic_pointer_cast<CGUIStaticItem>(control); + if (!newItem) + continue; + + m_items.emplace_back(std::move(newItem)); + } +} + CStaticListProvider::~CStaticListProvider() = default; +std::unique_ptr<IListProvider> CStaticListProvider::Clone() +{ + return std::make_unique<CStaticListProvider>(*this); +} + bool CStaticListProvider::Update(bool forceRefresh) { bool changed = forceRefresh; diff --git a/xbmc/listproviders/StaticProvider.h b/xbmc/listproviders/StaticProvider.h index 4a62e26574..6aea6b1e58 100644 --- a/xbmc/listproviders/StaticProvider.h +++ b/xbmc/listproviders/StaticProvider.h @@ -18,8 +18,11 @@ class CStaticListProvider : public IListProvider public: CStaticListProvider(const TiXmlElement *element, int parentID); explicit CStaticListProvider(const std::vector<CGUIStaticItemPtr> &items); // for python + explicit CStaticListProvider(const CStaticListProvider& other); ~CStaticListProvider() override; + // Implementation of IListProvider + std::unique_ptr<IListProvider> Clone() override; bool Update(bool forceRefresh) override; void Fetch(std::vector<CGUIListItemPtr> &items) override; bool OnClick(const CGUIListItemPtr &item) override; diff --git a/xbmc/messaging/helpers/DialogHelper.cpp b/xbmc/messaging/helpers/DialogHelper.cpp index 2c042f5acb..0990108ba9 100644 --- a/xbmc/messaging/helpers/DialogHelper.cpp +++ b/xbmc/messaging/helpers/DialogHelper.cpp @@ -38,20 +38,20 @@ DialogResponse ShowYesNoCustomDialog(CVariant heading, CVariant text, CVariant n switch (CApplicationMessenger::GetInstance().SendMsg(TMSG_GUI_DIALOG_YESNO, -1, -1, static_cast<void*>(&options))) { case -1: - return DialogResponse::CANCELLED; + return DialogResponse::CHOICE_CANCELLED; case 0: - return DialogResponse::NO; + return DialogResponse::CHOICE_NO; case 1: - return DialogResponse::YES; + return DialogResponse::CHOICE_YES; case 2: - return DialogResponse::CUSTOM; + return DialogResponse::CHOICE_CUSTOM; default: //If we get here someone changed the return values without updating this code assert(false); } //This is unreachable code but we need to return something to suppress warnings about //no return - return DialogResponse::CANCELLED; + return DialogResponse::CHOICE_CANCELLED; } DialogResponse ShowYesNoDialogLines(CVariant heading, CVariant line0, CVariant line1, CVariant line2, @@ -70,20 +70,20 @@ DialogResponse ShowYesNoDialogLines(CVariant heading, CVariant line0, CVariant l switch (CApplicationMessenger::GetInstance().SendMsg(TMSG_GUI_DIALOG_YESNO, -1, -1, static_cast<void*>(&options))) { case -1: - return DialogResponse::CANCELLED; + return DialogResponse::CHOICE_CANCELLED; case 0: - return DialogResponse::NO; + return DialogResponse::CHOICE_NO; case 1: - return DialogResponse::YES; + return DialogResponse::CHOICE_YES; case 2: - return DialogResponse::CUSTOM; + return DialogResponse::CHOICE_CUSTOM; default: //If we get here someone changed the return values without updating this code assert(false); } //This is unreachable code but we need to return something to suppress warnings about //no return - return DialogResponse::CANCELLED; + return DialogResponse::CHOICE_CANCELLED; } } diff --git a/xbmc/messaging/helpers/DialogHelper.h b/xbmc/messaging/helpers/DialogHelper.h index cf3d982502..d36fad3325 100644 --- a/xbmc/messaging/helpers/DialogHelper.h +++ b/xbmc/messaging/helpers/DialogHelper.h @@ -20,12 +20,12 @@ namespace MESSAGING namespace HELPERS { -enum class DialogResponse +enum class DialogResponse : int { - CANCELLED, - YES, - NO, - CUSTOM + CHOICE_CANCELLED, + CHOICE_YES, + CHOICE_NO, + CHOICE_CUSTOM, }; /*! \struct DialogYesNoMessage DialogHelper.h "messaging/helpers/DialogHelper.h" diff --git a/xbmc/music/MusicDatabase.cpp b/xbmc/music/MusicDatabase.cpp index c93ae58865..f175a2627e 100644 --- a/xbmc/music/MusicDatabase.cpp +++ b/xbmc/music/MusicDatabase.cpp @@ -4810,7 +4810,7 @@ void CMusicDatabase::Clean() return; } - if (HELPERS::ShowYesNoDialogText(CVariant{313}, CVariant{333}) == DialogResponse::YES) + if (HELPERS::ShowYesNoDialogText(CVariant{313}, CVariant{333}) == DialogResponse::CHOICE_YES) { CMusicDatabase musicdatabase; if (musicdatabase.Open()) @@ -11594,7 +11594,7 @@ bool CMusicDatabase::GetScraper(int id, const CONTENT_TYPE& content, ADDON::Scra ADDON::AddonPtr addon; if (!scraperUUID.empty() && CServiceBroker::GetAddonMgr().GetAddon(scraperUUID, addon, ADDON::ADDON_UNKNOWN, - ADDON::OnlyEnabled::YES) && + ADDON::OnlyEnabled::CHOICE_YES) && addon) { scraper = std::dynamic_pointer_cast<ADDON::CScraper>(addon); diff --git a/xbmc/music/dialogs/GUIDialogInfoProviderSettings.cpp b/xbmc/music/dialogs/GUIDialogInfoProviderSettings.cpp index 39b6203063..92245254a9 100644 --- a/xbmc/music/dialogs/GUIDialogInfoProviderSettings.cpp +++ b/xbmc/music/dialogs/GUIDialogInfoProviderSettings.cpp @@ -180,7 +180,7 @@ void CGUIDialogInfoProviderSettings::OnSettingAction(const std::shared_ptr<const { AddonPtr scraperAddon; if (CServiceBroker::GetAddonMgr().GetAddon(selectedAddonId, scraperAddon, ADDON_UNKNOWN, - OnlyEnabled::YES)) + OnlyEnabled::CHOICE_YES)) { m_albumscraper = std::dynamic_pointer_cast<CScraper>(scraperAddon); SetupView(); @@ -205,7 +205,7 @@ void CGUIDialogInfoProviderSettings::OnSettingAction(const std::shared_ptr<const { AddonPtr scraperAddon; if (CServiceBroker::GetAddonMgr().GetAddon(selectedAddonId, scraperAddon, ADDON_UNKNOWN, - OnlyEnabled::YES)) + OnlyEnabled::CHOICE_YES)) { m_artistscraper = std::dynamic_pointer_cast<CScraper>(scraperAddon); SetupView(); diff --git a/xbmc/music/windows/GUIWindowMusicBase.cpp b/xbmc/music/windows/GUIWindowMusicBase.cpp index cb40f476ba..e11613ed8b 100644 --- a/xbmc/music/windows/GUIWindowMusicBase.cpp +++ b/xbmc/music/windows/GUIWindowMusicBase.cpp @@ -1233,15 +1233,15 @@ void CGUIWindowMusicBase::OnAssignContent(const std::string& oldName, const CMed // "Add to library" yes/no dialog with additional "settings" custom button // "Do you want to add the media from this source to your library?" - DialogResponse rep = DialogResponse::CUSTOM; - while (rep == DialogResponse::CUSTOM) + DialogResponse rep = DialogResponse::CHOICE_CUSTOM; + while (rep == DialogResponse::CHOICE_CUSTOM) { rep = HELPERS::ShowYesNoCustomDialog(CVariant{20444}, CVariant{20447}, CVariant{106}, CVariant{107}, CVariant{10004}); - if (rep == DialogResponse::CUSTOM) + if (rep == DialogResponse::CHOICE_CUSTOM) // Edit default info provider settings so can be applied during scan CGUIDialogInfoProviderSettings::Show(); } - if (rep == DialogResponse::YES) + if (rep == DialogResponse::CHOICE_YES) CMusicLibraryQueue::GetInstance().ScanLibrary(source.strPath, MUSIC_INFO::CMusicInfoScanner::SCAN_NORMAL, true); } diff --git a/xbmc/network/NetworkServices.cpp b/xbmc/network/NetworkServices.cpp index 86df207a55..03c9181b87 100644 --- a/xbmc/network/NetworkServices.cpp +++ b/xbmc/network/NetworkServices.cpp @@ -189,7 +189,7 @@ bool CNetworkServices::OnSettingChanging(const std::shared_ptr<const CSetting>& (!m_settings->GetBool(CSettings::SETTING_SERVICES_WEBSERVER) || (m_settings->GetBool(CSettings::SETTING_SERVICES_WEBSERVER) && !m_settings->GetString(CSettings::SETTING_SERVICES_WEBSERVERPASSWORD).empty())) && - HELPERS::ShowYesNoDialogText(19098, 36634) != DialogResponse::YES) + HELPERS::ShowYesNoDialogText(19098, 36634) != DialogResponse::CHOICE_YES) { // Leave it as-is return false; @@ -227,7 +227,7 @@ bool CNetworkServices::OnSettingChanging(const std::shared_ptr<const CSetting>& // Ask for confirmation when enabling the web server if (settingId == CSettings::SETTING_SERVICES_WEBSERVER && - HELPERS::ShowYesNoDialogText(19098, 36632) != DialogResponse::YES) + HELPERS::ShowYesNoDialogText(19098, 36632) != DialogResponse::CHOICE_YES) { // Revert change, do not start server return false; @@ -438,7 +438,7 @@ bool CNetworkServices::OnSettingChanging(const std::shared_ptr<const CSetting>& else if (settingId == CSettings::SETTING_SERVICES_ESALLINTERFACES) { if (m_settings->GetBool(CSettings::SETTING_SERVICES_ESALLINTERFACES) && - HELPERS::ShowYesNoDialogText(19098, 36633) != DialogResponse::YES) + HELPERS::ShowYesNoDialogText(19098, 36633) != DialogResponse::CHOICE_YES) { // Revert change, do not start server return false; @@ -506,7 +506,8 @@ void CNetworkServices::OnSettingChanged(const std::shared_ptr<const CSetting>& s { // okey we really don't need to restart, only deinit samba, but that could be damn hard if something is playing //! @todo - General way of handling setting changes that require restart - if (HELPERS::ShowYesNoDialogText(CVariant{14038}, CVariant{14039}) == DialogResponse::YES) + if (HELPERS::ShowYesNoDialogText(CVariant{14038}, CVariant{14039}) == + DialogResponse::CHOICE_YES) { m_settings->Save(); CApplicationMessenger::GetInstance().PostMsg(TMSG_RESTARTAPP); @@ -940,8 +941,8 @@ bool CNetworkServices::StopEventServer(bool bWait, bool promptuser) { if (server->GetNumberOfClients() > 0) { - if (HELPERS::ShowYesNoDialogText(CVariant{13140}, CVariant{13141}, CVariant{""}, CVariant{""}, 10000) != - DialogResponse::YES) + if (HELPERS::ShowYesNoDialogText(CVariant{13140}, CVariant{13141}, CVariant{""}, CVariant{""}, + 10000) != DialogResponse::CHOICE_YES) { CLog::Log(LOGINFO, "ES: Not stopping event server"); return false; diff --git a/xbmc/network/httprequesthandler/HTTPWebinterfaceHandler.cpp b/xbmc/network/httprequesthandler/HTTPWebinterfaceHandler.cpp index 8e5f4f692e..48d46035fe 100644 --- a/xbmc/network/httprequesthandler/HTTPWebinterfaceHandler.cpp +++ b/xbmc/network/httprequesthandler/HTTPWebinterfaceHandler.cpp @@ -91,7 +91,7 @@ bool CHTTPWebinterfaceHandler::ResolveAddon(const std::string &url, ADDON::Addon return false; if (!CServiceBroker::GetAddonMgr().GetAddon(components.at(1), addon, ADDON::ADDON_UNKNOWN, - ADDON::OnlyEnabled::YES) || + ADDON::OnlyEnabled::CHOICE_YES) || addon == NULL) return false; diff --git a/xbmc/network/upnp/UPnPPlayer.cpp b/xbmc/network/upnp/UPnPPlayer.cpp index 47e5b3408d..527754c141 100644 --- a/xbmc/network/upnp/UPnPPlayer.cpp +++ b/xbmc/network/upnp/UPnPPlayer.cpp @@ -603,7 +603,8 @@ bool CUPnPPlayer::OnAction(const CAction &action) if(IsPlaying()) { //stop on remote system - m_stopremote = HELPERS::ShowYesNoDialogText(CVariant{37022}, CVariant{37023}) == DialogResponse::YES; + m_stopremote = HELPERS::ShowYesNoDialogText(CVariant{37022}, CVariant{37023}) == + DialogResponse::CHOICE_YES; return false; /* let normal code handle the action */ } diff --git a/xbmc/peripherals/Peripherals.cpp b/xbmc/peripherals/Peripherals.cpp index 5efe10283b..759cda91cf 100644 --- a/xbmc/peripherals/Peripherals.cpp +++ b/xbmc/peripherals/Peripherals.cpp @@ -975,7 +975,7 @@ void CPeripherals::OnSettingAction(const std::shared_ptr<const CSetting>& settin { ADDON::AddonPtr addon; if (CServiceBroker::GetAddonMgr().GetAddon(strAddonId, addon, ADDON::ADDON_UNKNOWN, - ADDON::OnlyEnabled::YES)) + ADDON::OnlyEnabled::CHOICE_YES)) CGUIDialogAddonSettings::ShowForAddon(addon); } } diff --git a/xbmc/peripherals/bus/virtual/PeripheralBusAddon.cpp b/xbmc/peripherals/bus/virtual/PeripheralBusAddon.cpp index 6307207151..f6e6220973 100644 --- a/xbmc/peripherals/bus/virtual/PeripheralBusAddon.cpp +++ b/xbmc/peripherals/bus/virtual/PeripheralBusAddon.cpp @@ -482,7 +482,8 @@ void CPeripheralBusAddon::PromptEnableAddons(const std::vector<ADDON::AddonInfoP { // "Unable to configure controllers" // "Controller configuration depends on a disabled add-on. Would you like to enable it?" - bAccepted = (ShowYesNoDialogLines(CVariant{35017}, CVariant{35018}) == DialogResponse::YES); + bAccepted = + (ShowYesNoDialogLines(CVariant{35017}, CVariant{35018}) == DialogResponse::CHOICE_YES); } if (bAccepted) diff --git a/xbmc/platform/android/CPUInfoAndroid.cpp b/xbmc/platform/android/CPUInfoAndroid.cpp index 3c854e8ae2..cd7ee1ad2c 100644 --- a/xbmc/platform/android/CPUInfoAndroid.cpp +++ b/xbmc/platform/android/CPUInfoAndroid.cpp @@ -8,10 +8,14 @@ #include "CPUInfoAndroid.h" +#include "URL.h" +#include "utils/StringUtils.h" #include "utils/Temperature.h" #include "platform/android/activity/AndroidFeatures.h" +#include <array> + std::shared_ptr<CCPUInfo> CCPUInfo::GetCPUInfo() { return std::make_shared<CCPUInfoAndroid>(); @@ -19,6 +23,28 @@ std::shared_ptr<CCPUInfo> CCPUInfo::GetCPUInfo() CCPUInfoAndroid::CCPUInfoAndroid() { + m_posixFile = std::make_unique<CPosixFile>(); + + if (m_posixFile && m_posixFile->Open(CURL("/proc/cpuinfo"))) + { + std::array<char, 2048> buffer = {}; + + if (0 < m_posixFile->Read(buffer.data(), buffer.size())) + { + for (const auto& line : StringUtils::Split(buffer.data(), '\n')) + { + if (line.find("vendor_id") != std::string::npos) + m_cpuVendor = line.substr(line.find(':') + 2); + else if (line.find("model name") != std::string::npos) + m_cpuModel = line.substr(line.find(':') + 2); + else if (line.find("BogoMIPS") != std::string::npos) + m_cpuBogoMips = line.substr(line.find(':') + 2); + } + } + + m_posixFile->Close(); + } + m_cpuCount = CAndroidFeatures::GetCPUCount(); for (int i = 0; i < m_cpuCount; i++) @@ -31,3 +57,23 @@ CCPUInfoAndroid::CCPUInfoAndroid() if (CAndroidFeatures::HasNeon()) m_cpuFeatures |= CPU_FEATURE_NEON; } + +float CCPUInfoAndroid::GetCPUFrequency() +{ + float freq = 0.f; + + if (!m_posixFile) + return freq; + + if (m_posixFile->Open(CURL("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq"))) + { + std::array<char, 32> buffer = {}; + + if (0 < m_posixFile->Read(buffer.data(), buffer.size())) + freq = std::atof(buffer.data()) / 1000; + + m_posixFile->Close(); + } + + return freq; +} diff --git a/xbmc/platform/android/CPUInfoAndroid.h b/xbmc/platform/android/CPUInfoAndroid.h index c8fdbd1655..edb26e5198 100644 --- a/xbmc/platform/android/CPUInfoAndroid.h +++ b/xbmc/platform/android/CPUInfoAndroid.h @@ -11,6 +11,11 @@ #include "utils/Temperature.h" #include "platform/posix/CPUInfoPosix.h" +#include "platform/posix/filesystem/PosixFile.h" + +#include <memory> + +using namespace XFILE; class CCPUInfoAndroid : public CCPUInfoPosix { @@ -20,5 +25,8 @@ public: bool SupportsCPUUsage() const override { return false; } int GetUsedPercentage() override { return 0; } - float GetCPUFrequency() override { return 0; } + float GetCPUFrequency() override; + +private: + std::unique_ptr<CPosixFile> m_posixFile; }; diff --git a/xbmc/platform/darwin/tvos/XBMCController.mm b/xbmc/platform/darwin/tvos/XBMCController.mm index 9e9dde4fd2..87d3da2a84 100644 --- a/xbmc/platform/darwin/tvos/XBMCController.mm +++ b/xbmc/platform/darwin/tvos/XBMCController.mm @@ -22,7 +22,6 @@ #include "network/NetworkServices.h" #include "platform/xbmc.h" #include "powermanagement/PowerManager.h" -#include "pvr/PVRManager.h" #include "settings/AdvancedSettings.h" #include "settings/SettingsComponent.h" #include "utils/log.h" diff --git a/xbmc/platform/win32/WIN32Util.cpp b/xbmc/platform/win32/WIN32Util.cpp index 02cb880a18..d2cf1363c7 100644 --- a/xbmc/platform/win32/WIN32Util.cpp +++ b/xbmc/platform/win32/WIN32Util.cpp @@ -15,6 +15,7 @@ #include "WindowHelper.h" #include "guilib/LocalizeStrings.h" #include "my_ntddscsi.h" +#include "rendering/dx/DirectXHelper.h" #include "storage/MediaManager.h" #include "storage/cdioSupport.h" #include "utils/CharsetConverter.h" @@ -1504,3 +1505,78 @@ void CWIN32Util::PlatformSyslog() CLog::Log(LOGINFO, "Display HDR capable is detected and Windows HDR switch is {}", (hdrStatus == HDR_STATUS::HDR_ON) ? "ON" : "OFF"); } + +VideoDriverInfo CWIN32Util::GetVideoDriverInfo(const UINT vendorId, const std::wstring& driverDesc) +{ + VideoDriverInfo info = {}; + +#ifdef TARGET_WINDOWS_DESKTOP + HKEY hKey = nullptr; + const wchar_t* SUBKEY = L"SYSTEM\\CurrentControlSet\\Control\\Video"; + + if (ERROR_SUCCESS != RegOpenKeyExW(HKEY_LOCAL_MACHINE, SUBKEY, 0, KEY_ENUMERATE_SUB_KEYS, &hKey)) + return {}; + + LSTATUS sta = ERROR_SUCCESS; + wchar_t keyName[128] = {}; + DWORD index = 0; + DWORD len; + + using KODI::PLATFORM::WINDOWS::FromW; + + do + { + len = sizeof(keyName) / sizeof(wchar_t); + sta = RegEnumKeyExW(hKey, index, keyName, &len, nullptr, nullptr, nullptr, nullptr); + index++; + + if (sta != ERROR_SUCCESS) + continue; + + std::wstring subkey(SUBKEY); + subkey.append(L"\\"); + subkey.append(keyName); + subkey.append(L"\\"); + subkey.append(L"0000"); + DWORD lg; + + wchar_t desc[128] = {}; + lg = sizeof(desc) / sizeof(wchar_t); + if (ERROR_SUCCESS != RegGetValueW(HKEY_LOCAL_MACHINE, subkey.c_str(), L"DriverDesc", + RRF_RT_REG_SZ, nullptr, desc, &lg)) + continue; + + std::wstring s_desc(desc); + if (s_desc != driverDesc) + continue; + + // driver of interest found, we read version + wchar_t version[64] = {}; + lg = sizeof(version) / sizeof(wchar_t); + if (ERROR_SUCCESS != RegGetValueW(HKEY_LOCAL_MACHINE, subkey.c_str(), L"DriverVersion", + RRF_RT_REG_SZ, nullptr, version, &lg)) + continue; + + info.valid = true; + info.version = FromW(std::wstring(version)); + + // convert driver store version to Nvidia version + if (vendorId == PCIV_NVIDIA) + { + std::string ver(info.version); + StringUtils::Replace(ver, ".", ""); + info.majorVersion = std::stoi(ver.substr(ver.length() - 5, 3)); + info.minorVersion = std::stoi(ver.substr(ver.length() - 2, 2)); + } + else // for Intel/AMD fill major version only + { + info.majorVersion = std::stoi(info.version.substr(0, 2)); + } + + } while (sta == ERROR_SUCCESS && !info.valid); + + RegCloseKey(hKey); +#endif + + return info; +} diff --git a/xbmc/platform/win32/WIN32Util.h b/xbmc/platform/win32/WIN32Util.h index e87f9ee343..247bed0a35 100644 --- a/xbmc/platform/win32/WIN32Util.h +++ b/xbmc/platform/win32/WIN32Util.h @@ -20,6 +20,14 @@ #define BONJOUR_BROWSER_EVENT ( WM_USER + 0x110 ) #define TRAY_ICON_NOTIFY ( WM_USER + 0x120 ) +struct VideoDriverInfo +{ + int majorVersion; + int minorVersion; + bool valid; + std::string version; +}; + class CURL; // forward declaration class CWIN32Util @@ -74,4 +82,6 @@ public: static HDR_STATUS GetWindowsHDRStatus(); static void PlatformSyslog(); + + static VideoDriverInfo GetVideoDriverInfo(const UINT vendorId, const std::wstring& driverDesc); }; diff --git a/xbmc/pvr/PVRDatabase.cpp b/xbmc/pvr/PVRDatabase.cpp index 7cd1703dc3..cfc93cba55 100644 --- a/xbmc/pvr/PVRDatabase.cpp +++ b/xbmc/pvr/PVRDatabase.cpp @@ -91,6 +91,25 @@ namespace ")"; // clang-format on + + std::string GetClientIdsSQL(const std::vector<std::shared_ptr<CPVRClient>>& clients) + { + if (clients.empty()) + return {}; + + std::string clientIds = "("; + for (auto it = clients.cbegin(); it != clients.cend(); ++it) + { + if (it != clients.cbegin()) + clientIds += " OR "; + + clientIds += "iClientId = "; + clientIds += std::to_string((*it)->GetID()); + } + clientIds += ")"; + return clientIds; + } + } // unnamed namespace bool CPVRDatabase::Open() @@ -406,12 +425,18 @@ bool CPVRDatabase::Delete(const CPVRProvider& provider) return DeleteValues("providers", filter); } -bool CPVRDatabase::Get(CPVRProviders& results) +bool CPVRDatabase::Get(CPVRProviders& results, + const std::vector<std::shared_ptr<CPVRClient>>& clients) const { bool bReturn = false; - CSingleLock lock(m_critSection); - const std::string strQuery = PrepareSQL("SELECT * from providers"); + std::string strQuery = "SELECT * from providers "; + const std::string clientIds = GetClientIdsSQL(clients); + if (!clientIds.empty()) + strQuery += "WHERE " + clientIds; + + CSingleLock lock(m_critSection); + strQuery = PrepareSQL(strQuery); if (ResultQuery(strQuery)) { try @@ -451,12 +476,18 @@ bool CPVRDatabase::Get(CPVRProviders& results) /********** Channel methods **********/ int CPVRDatabase::Get(bool bRadio, - std::map<std::pair<int, int>, std::shared_ptr<CPVRChannel>>& results) + const std::vector<std::shared_ptr<CPVRClient>>& clients, + std::map<std::pair<int, int>, std::shared_ptr<CPVRChannel>>& results) const { int iReturn = 0; - const std::string strQuery = PrepareSQL("SELECT * from channels WHERE bIsRadio = %u", bRadio); + + std::string strQuery = "SELECT * from channels WHERE bIsRadio = %u "; + const std::string clientIds = GetClientIdsSQL(clients); + if (!clientIds.empty()) + strQuery += "AND " + clientIds; CSingleLock lock(m_critSection); + strQuery = PrepareSQL(strQuery, bRadio); if (ResultQuery(strQuery)) { try @@ -590,7 +621,7 @@ bool CPVRDatabase::Delete(const CPVRChannelGroup& group) return RemoveChannelsFromGroup(group) && DeleteValues("channelgroups", filter); } -int CPVRDatabase::Get(CPVRChannelGroups& results) +int CPVRDatabase::Get(CPVRChannelGroups& results) const { int iLoaded = 0; CSingleLock lock(m_critSection); @@ -635,7 +666,7 @@ int CPVRDatabase::Get(CPVRChannelGroups& results) } std::vector<std::shared_ptr<CPVRChannelGroupMember>> CPVRDatabase::Get( - const CPVRChannelGroup& group) + const CPVRChannelGroup& group, const std::vector<std::shared_ptr<CPVRClient>>& clients) const { std::vector<std::shared_ptr<CPVRChannelGroupMember>> results; @@ -646,22 +677,24 @@ std::vector<std::shared_ptr<CPVRChannelGroupMember>> CPVRDatabase::Get( return results; } - const std::string strQuery = - PrepareSQL("SELECT map_channelgroups_channels.idChannel, " - "map_channelgroups_channels.iChannelNumber, " - "map_channelgroups_channels.iSubChannelNumber, " - "map_channelgroups_channels.iOrder, " - "map_channelgroups_channels.iClientChannelNumber, " - "map_channelgroups_channels.iClientSubChannelNumber, " - "channels.iClientId, channels.iUniqueId, channels.bIsRadio " - "FROM map_channelgroups_channels " - "LEFT JOIN channels ON channels.idChannel = map_channelgroups_channels.idChannel " - "WHERE map_channelgroups_channels.idGroup = %i ORDER BY " - "map_channelgroups_channels.iChannelNumber", - group.GroupID()); + std::string strQuery = + "SELECT map_channelgroups_channels.idChannel, " + "map_channelgroups_channels.iChannelNumber, " + "map_channelgroups_channels.iSubChannelNumber, " + "map_channelgroups_channels.iOrder, " + "map_channelgroups_channels.iClientChannelNumber, " + "map_channelgroups_channels.iClientSubChannelNumber, " + "channels.iClientId, channels.iUniqueId, channels.bIsRadio " + "FROM map_channelgroups_channels " + "LEFT JOIN channels ON channels.idChannel = map_channelgroups_channels.idChannel " + "WHERE map_channelgroups_channels.idGroup = %i "; + const std::string clientIds = GetClientIdsSQL(clients); + if (!clientIds.empty()) + strQuery += "AND " + clientIds; + strQuery += " ORDER BY map_channelgroups_channels.iChannelNumber"; CSingleLock lock(m_critSection); - + strQuery = PrepareSQL(strQuery, group.GroupID()); if (ResultQuery(strQuery)) { try @@ -963,12 +996,18 @@ bool CPVRDatabase::UpdateLastOpened(const CPVRChannelGroup& group) /********** Timer methods **********/ -std::vector<std::shared_ptr<CPVRTimerInfoTag>> CPVRDatabase::GetTimers(CPVRTimers& timers) +std::vector<std::shared_ptr<CPVRTimerInfoTag>> CPVRDatabase::GetTimers( + CPVRTimers& timers, const std::vector<std::shared_ptr<CPVRClient>>& clients) const { std::vector<std::shared_ptr<CPVRTimerInfoTag>> result; + std::string strQuery = "SELECT * FROM timers "; + const std::string clientIds = GetClientIdsSQL(clients); + if (!clientIds.empty()) + strQuery += "WHERE " + clientIds; + CSingleLock lock(m_critSection); - const std::string strQuery = PrepareSQL("SELECT * FROM timers"); + strQuery = PrepareSQL(strQuery); if (ResultQuery(strQuery)) { try diff --git a/xbmc/pvr/PVRDatabase.h b/xbmc/pvr/PVRDatabase.h index 853de802be..9359148734 100644 --- a/xbmc/pvr/PVRDatabase.h +++ b/xbmc/pvr/PVRDatabase.h @@ -114,10 +114,13 @@ namespace PVR /*! * @brief Get channels from the database. * @param bRadio Whether to fetch radio or TV channels. + * @param clients The PVR clients the channels should be loaded for. Leave empty for all clients. * @param results The container for the channels. * @return The number of channels loaded. */ - int Get(bool bRadio, std::map<std::pair<int, int>, std::shared_ptr<CPVRChannel>>& results); + int Get(bool bRadio, + const std::vector<std::shared_ptr<CPVRClient>>& clients, + std::map<std::pair<int, int>, std::shared_ptr<CPVRChannel>>& results) const; /*! * @brief Add or update a channel entry in the database @@ -175,9 +178,10 @@ namespace PVR /*! * @brief Get the list of providers from the database * @param results The providers to store the results in. + * @param clients The PVR clients the providers should be loaded for. Leave empty for all clients. * @return The amount of providers that were added. */ - bool Get(CPVRProviders& results); + bool Get(CPVRProviders& results, const std::vector<std::shared_ptr<CPVRClient>>& clients) const; //@} @@ -202,14 +206,17 @@ namespace PVR * @param results The container to store the results in. * @return The number of groups loaded. */ - int Get(CPVRChannelGroups& results); + int Get(CPVRChannelGroups& results) const; /*! * @brief Get the members of a channel group. * @param group The group to get the members for. + * @param clients The PVR clients the group members should be loaded for. Leave empty for all clients. * @return The group members. */ - std::vector<std::shared_ptr<CPVRChannelGroupMember>> Get(const CPVRChannelGroup& group); + std::vector<std::shared_ptr<CPVRChannelGroupMember>> Get( + const CPVRChannelGroup& group, + const std::vector<std::shared_ptr<CPVRClient>>& clients) const; /*! * @brief Add or update a channel group entry in the database. @@ -230,9 +237,11 @@ namespace PVR /*! * @brief Get the timers. * @param timers The container for the timers. + * @param clients The PVR clients the timers should be loaded for. Leave empty for all clients. * @return The timers. */ - std::vector<std::shared_ptr<CPVRTimerInfoTag>> GetTimers(CPVRTimers& timers); + std::vector<std::shared_ptr<CPVRTimerInfoTag>> GetTimers( + CPVRTimers& timers, const std::vector<std::shared_ptr<CPVRClient>>& clients) const; /*! * @brief Add or update a timer entry in the database @@ -300,6 +309,6 @@ namespace PVR bool RemoveChannelsFromGroup(const CPVRChannelGroup& group); - CCriticalSection m_critSection; + mutable CCriticalSection m_critSection; }; } diff --git a/xbmc/pvr/PVRManager.cpp b/xbmc/pvr/PVRManager.cpp index 24f083695a..f8ff4ed2d0 100644 --- a/xbmc/pvr/PVRManager.cpp +++ b/xbmc/pvr/PVRManager.cpp @@ -390,7 +390,7 @@ void CPVRManager::Start() return; CLog::Log(LOGINFO, "PVR Manager: Starting"); - SetState(ManagerStateStarting); + SetState(ManagerState::STATE_STARTING); /* create the pvrmanager thread, which will ensure that all data will be loaded */ Create(); @@ -413,25 +413,9 @@ void CPVRManager::Stop(bool bRestart /* = false */) } CLog::Log(LOGINFO, "PVR Manager: Stopping"); - SetState(ManagerStateStopping); - - m_addons->Stop(); - m_pendingUpdates->Stop(); - m_timers->Stop(); - m_epgContainer.Stop(); - m_guiInfo->Stop(); + SetState(ManagerState::STATE_SSTOPPING); StopThread(); - - SetState(ManagerStateInterrupted); - - UnloadComponents(); - m_database->Close(); - - ResetProperties(); - - CLog::Log(LOGINFO, "PVR Manager: Stopped"); - SetState(ManagerStateStopped); } void CPVRManager::Unload() @@ -469,22 +453,22 @@ void CPVRManager::SetState(CPVRManager::ManagerState state) PVREvent event; switch (state) { - case ManagerStateError: + case ManagerState::STATE_ERROR: event = PVREvent::ManagerError; break; - case ManagerStateStopped: + case ManagerState::STATE_STOPPED: event = PVREvent::ManagerStopped; break; - case ManagerStateStarting: + case ManagerState::STATE_STARTING: event = PVREvent::ManagerStarting; break; - case ManagerStateStopping: + case ManagerState::STATE_SSTOPPING: event = PVREvent::ManagerStopped; break; - case ManagerStateInterrupted: + case ManagerState::STATE_INTERRUPTED: event = PVREvent::ManagerInterrupted; break; - case ManagerStateStarted: + case ManagerState::STATE_STARTED: event = PVREvent::ManagerStarted; break; default: @@ -504,27 +488,24 @@ void CPVRManager::Process() m_addons->Continue(); m_database->Open(); - /* load the pvr data from the db and clients if it's not already loaded */ - XbmcThreads::EndTime<> progressTimeout(30s); // 30 secs - CPVRGUIProgressHandler* progressHandler = new CPVRGUIProgressHandler(g_localizeStrings.Get(19235)); // PVR manager is starting up - while (!LoadComponents(progressHandler) && IsInitialising()) + if (!IsInitialising()) { - CLog::Log(LOGWARNING, "PVR Manager failed to load data, retrying"); - CThread::Sleep(1000ms); - - if (progressHandler && progressTimeout.IsTimePast()) - { - progressHandler->DestroyProgress(); - progressHandler = nullptr; // no delete, instance is deleting itself - } + CLog::Log(LOGINFO, "PVR Manager: Start aborted"); + return; } - if (progressHandler) + UnloadComponents(); + + if (!IsInitialising()) { - progressHandler->DestroyProgress(); - progressHandler = nullptr; // no delete, instance is deleting itself + CLog::Log(LOGINFO, "PVR Manager: Start aborted"); + return; } + // Wait for at least one client to come up and load/update data + std::vector<std::shared_ptr<CPVRClient>> knownClients; + UpdateComponents(knownClients, ManagerState::STATE_STARTING); + if (!IsInitialising()) { CLog::Log(LOGINFO, "PVR Manager: Start aborted"); @@ -542,22 +523,30 @@ void CPVRManager::Process() m_timers->Start(); m_pendingUpdates->Start(); - SetState(ManagerStateStarted); + SetState(ManagerState::STATE_STARTED); CLog::Log(LOGINFO, "PVR Manager: Started"); - /* main loop */ - CLog::LogFC(LOGDEBUG, LOGPVR, "PVR Manager entering main loop"); - bool bRestart(false); XbmcThreads::EndTime<> cachedImagesCleanupTimeout(30s); // first timeout after 30 secs while (IsStarted() && m_addons->HasCreatedClients() && !bRestart) { + // In case any new client connected, load from db and fetch data update from new client(s) + UpdateComponents(knownClients, ManagerState::STATE_STARTED); + if (cachedImagesCleanupTimeout.IsTimePast()) { - // start a job to erase stale texture db entries and image files - TriggerCleanupCachedImages(); - cachedImagesCleanupTimeout.Set(12h); // following timeouts after 12 hours + // We don't know for sure what to delete if there are not (yet) connected clients + if (m_addons->HasIgnoredClients()) + { + cachedImagesCleanupTimeout.Set(10s); // try again in 10 secs + } + else + { + // start a job to erase stale texture db entries and image files + TriggerCleanupCachedImages(); + cachedImagesCleanupTimeout.Set(12h); // following timeouts after 12 hours + } } /* first startup */ @@ -593,7 +582,21 @@ void CPVRManager::Process() m_pendingUpdates->WaitForJobs(1000); } - CLog::LogFC(LOGDEBUG, LOGPVR, "PVR Manager leaving main loop"); + m_addons->Stop(); + m_pendingUpdates->Stop(); + m_timers->Stop(); + m_epgContainer.Stop(); + m_guiInfo->Stop(); + + SetState(ManagerState::STATE_INTERRUPTED); + + UnloadComponents(); + m_database->Close(); + + ResetProperties(); + + CLog::Log(LOGINFO, "PVR Manager: Stopped"); + SetState(ManagerState::STATE_STOPPED); } bool CPVRManager::SetWakeupCommand() @@ -659,47 +662,127 @@ void CPVRManager::OnWake() TriggerTimersUpdate(); } -bool CPVRManager::LoadComponents(CPVRGUIProgressHandler* progressHandler) +void CPVRManager::UpdateComponents(std::vector<std::shared_ptr<CPVRClient>>& knownClients, + ManagerState stateToCheck) +{ + XbmcThreads::EndTime<> progressTimeout(30s); + CPVRGUIProgressHandler* progressHandler = + new CPVRGUIProgressHandler(g_localizeStrings.Get(19235)); // PVR manager is starting up + + // Wait for at least one client to come up and load/update data + while (!UpdateComponents(knownClients, stateToCheck, progressHandler) && + m_addons->HasCreatedClients() && (stateToCheck == GetState())) + { + CThread::Sleep(1000ms); + + if (progressHandler && progressTimeout.IsTimePast()) + { + progressHandler->DestroyProgress(); + progressHandler = nullptr; // no delete, instance is deleting itself + } + } + + if (progressHandler) + { + progressHandler->DestroyProgress(); + progressHandler = nullptr; // no delete, instance is deleting itself + } +} + +bool CPVRManager::UpdateComponents(std::vector<std::shared_ptr<CPVRClient>>& knownClients, + ManagerState stateToCheck, + CPVRGUIProgressHandler* progressHandler) { - /* load at least one client */ - while (IsInitialising() && m_addons && !m_addons->HasCreatedClients()) - CThread::Sleep(50ms); + // find clients which disappeared since last check and remove them from known clients + for (auto it = knownClients.begin(); it != knownClients.end();) + { + if ((*it)->IgnoreClient()) + { + it = knownClients.erase(it); + CLog::LogFC(LOGDEBUG, LOGPVR, + "PVR client '{}' disconnected. Erasing from list of known clients.", (*it)->ID()); + } + else + ++it; + } - if (!IsInitialising() || !m_addons->HasCreatedClients()) + // find clients which appeared since last check and update them + CPVRClientMap clientMap; + m_addons->GetCreatedClients(clientMap); + if (clientMap.empty()) + { + CLog::LogFC(LOGDEBUG, LOGPVR, "All created PVR clients gone!"); return false; + } + + std::vector<std::shared_ptr<CPVRClient>> newClients; + for (const auto& entry : clientMap) + { + // skip not (yet) connected clients + if (entry.second->IgnoreClient()) + { + CLog::LogFC(LOGDEBUG, LOGPVR, "Skipping not (yet) connected PVR client '{}'", + entry.second->ID()); + continue; + } - CLog::LogFC(LOGDEBUG, LOGPVR, "PVR Manager found active clients. Continuing startup"); + if (knownClients.empty() || std::find_if(knownClients.cbegin(), knownClients.cend(), + [&entry](const std::shared_ptr<CPVRClient>& client) { + return entry.first == client->GetID(); + }) == knownClients.cend()) + { + knownClients.emplace_back(entry.second); + newClients.emplace_back(entry.second); - /* load all channels and groups */ + CLog::LogFC(LOGDEBUG, LOGPVR, "Adding new PVR client '{}' to list of known clients", + entry.second->ID()); + } + } + + if (newClients.empty()) + return !knownClients.empty(); + + // Load all channels and groups if (progressHandler) - progressHandler->UpdateProgress(g_localizeStrings.Get(19236), 0); // Loading channels from clients + progressHandler->UpdateProgress(g_localizeStrings.Get(19236), 0); // Loading channels and groups - if (!m_providers->Load() || !IsInitialising()) + if (!m_providers->Update(newClients) || (stateToCheck != GetState())) + { + CLog::LogF(LOGERROR, "Failed to load PVR providers."); + knownClients.clear(); // start over return false; + } - if (!m_channelGroups->Load() || !IsInitialising()) + if (!m_channelGroups->Update(newClients) || (stateToCheck != GetState())) + { + CLog::LogF(LOGERROR, "Failed to load PVR channels / groups."); + knownClients.clear(); // start over return false; + } PublishEvent(PVREvent::ChannelGroupsLoaded); - /* get timers from the backends */ + // Load all timers if (progressHandler) - progressHandler->UpdateProgress(g_localizeStrings.Get(19237), 50); // Loading timers from clients + progressHandler->UpdateProgress(g_localizeStrings.Get(19237), 50); // Loading timers - m_timers->Load(); + if (!m_timers->Update(newClients) || (stateToCheck != GetState())) + { + CLog::LogF(LOGERROR, "Failed to load PVR timers."); + knownClients.clear(); // start over + return false; + } - /* get recordings from the backend */ + // Load all recordings if (progressHandler) - progressHandler->UpdateProgress(g_localizeStrings.Get(19238), 75); // Loading recordings from clients + progressHandler->UpdateProgress(g_localizeStrings.Get(19238), 75); // Loading recordings - m_recordings->Load(); - - if (!IsInitialising()) + if (!m_recordings->Update(newClients) || (stateToCheck != GetState())) + { + CLog::LogF(LOGERROR, "Failed to load PVR recordings."); + knownClients.clear(); // start over return false; - - /* start the other pvr related update threads */ - if (progressHandler) - progressHandler->UpdateProgress(g_localizeStrings.Get(19239), 85); // Starting background threads + } return true; } @@ -812,13 +895,6 @@ void CPVRManager::TriggerEpgsCreate() }); } -void CPVRManager::TriggerRecordingsUpdate() -{ - m_pendingUpdates->Append("pvr-update-recordings", [this]() { - return Recordings()->Update(); - }); -} - void CPVRManager::TriggerRecordingsSizeInProgressUpdate() { m_pendingUpdates->Append("pvr-update-recordings-size", [this]() { @@ -826,32 +902,80 @@ void CPVRManager::TriggerRecordingsSizeInProgressUpdate() }); } -void CPVRManager::TriggerTimersUpdate() +void CPVRManager::TriggerRecordingsUpdate(int clientId) { - m_pendingUpdates->Append("pvr-update-timers", [this]() { - return Timers()->Update(); + m_pendingUpdates->Append("pvr-update-recordings-" + std::to_string(clientId), [this, clientId]() { + const std::shared_ptr<CPVRClient> client = GetClient(clientId); + if (client) + Recordings()->UpdateFromClients({client}); }); } -void CPVRManager::TriggerChannelsUpdate() +void CPVRManager::TriggerRecordingsUpdate() { - m_pendingUpdates->Append("pvr-update-channels", [this]() { - return ChannelGroups()->Update(true); + m_pendingUpdates->Append("pvr-update-recordings", + [this]() { Recordings()->UpdateFromClients({}); }); +} + +void CPVRManager::TriggerTimersUpdate(int clientId) +{ + m_pendingUpdates->Append("pvr-update-timers-" + std::to_string(clientId), [this, clientId]() { + const std::shared_ptr<CPVRClient> client = GetClient(clientId); + if (client) + Timers()->UpdateFromClients({client}); }); } +void CPVRManager::TriggerTimersUpdate() +{ + m_pendingUpdates->Append("pvr-update-timers", [this]() { Timers()->UpdateFromClients({}); }); +} + +void CPVRManager::TriggerProvidersUpdate(int clientId) +{ + m_pendingUpdates->Append("pvr-update-channel-providers-" + std::to_string(clientId), + [this, clientId]() { + const std::shared_ptr<CPVRClient> client = GetClient(clientId); + if (client) + Providers()->UpdateFromClients({client}); + }); +} + void CPVRManager::TriggerProvidersUpdate() { - m_pendingUpdates->Append("pvr-update-channel-providers", [this]() { - return Providers()->Update(); + m_pendingUpdates->Append("pvr-update-channel-providers", + [this]() { Providers()->UpdateFromClients({}); }); +} + +void CPVRManager::TriggerChannelsUpdate(int clientId) +{ + m_pendingUpdates->Append("pvr-update-channels-" + std::to_string(clientId), [this, clientId]() { + const std::shared_ptr<CPVRClient> client = GetClient(clientId); + if (client) + ChannelGroups()->UpdateFromClients({client}, true); }); } +void CPVRManager::TriggerChannelsUpdate() +{ + m_pendingUpdates->Append("pvr-update-channels", + [this]() { ChannelGroups()->UpdateFromClients({}, true); }); +} + +void CPVRManager::TriggerChannelGroupsUpdate(int clientId) +{ + m_pendingUpdates->Append("pvr-update-channelgroups-" + std::to_string(clientId), + [this, clientId]() { + const std::shared_ptr<CPVRClient> client = GetClient(clientId); + if (client) + ChannelGroups()->UpdateFromClients({client}, false); + }); +} + void CPVRManager::TriggerChannelGroupsUpdate() { - m_pendingUpdates->Append("pvr-update-channelgroups", [this]() { - return ChannelGroups()->Update(false); - }); + m_pendingUpdates->Append("pvr-update-channelgroups", + [this]() { ChannelGroups()->UpdateFromClients({}, false); }); } void CPVRManager::TriggerSearchMissingChannelIcons() @@ -895,10 +1019,6 @@ void CPVRManager::ConnectionStateChange(CPVRClient* client, { CJobManager::GetInstance().Submit([this, client, connectString, state, message] { Clients()->ConnectionStateChange(client, connectString, state, message); - - if (state == PVR_CONNECTION_STATE_CONNECTED) - Start(); // start over - return true; }); } diff --git a/xbmc/pvr/PVRManager.h b/xbmc/pvr/PVRManager.h index a28ce57c6b..86e5326dab 100644 --- a/xbmc/pvr/PVRManager.h +++ b/xbmc/pvr/PVRManager.h @@ -211,39 +211,10 @@ namespace PVR std::shared_ptr<CPVRDatabase> GetTVDatabase() const; /*! - * @return True while the PVRManager is initialising. - */ - inline bool IsInitialising() const - { - return GetState() == ManagerStateStarting; - } - - /*! * @brief Check whether the PVRManager has fully started. * @return True if started, false otherwise. */ - inline bool IsStarted() const - { - return GetState() == ManagerStateStarted; - } - - /*! - * @brief Check whether the PVRManager is stopping - * @return True while the PVRManager is stopping. - */ - inline bool IsStopping() const - { - return GetState() == ManagerStateStopping; - } - - /*! - * @brief Check whether the PVRManager has been stopped. - * @return True if stopped, false otherwise. - */ - inline bool IsStopped() const - { - return GetState() == ManagerStateStopped; - } + bool IsStarted() const { return GetState() == ManagerState::STATE_STARTED; } /*! * @brief Check whether EPG tags for channels have been created. @@ -276,7 +247,9 @@ namespace PVR /*! * @brief Let the background thread update the recordings list. + * @param clientId The id of the PVR client to update. */ + void TriggerRecordingsUpdate(int clientId); void TriggerRecordingsUpdate(); /*! @@ -286,22 +259,30 @@ namespace PVR /*! * @brief Let the background thread update the timer list. + * @param clientId The id of the PVR client to update. */ + void TriggerTimersUpdate(int clientId); void TriggerTimersUpdate(); /*! * @brief Let the background thread update the channel list. + * @param clientId The id of the PVR client to update. */ + void TriggerChannelsUpdate(int clientId); void TriggerChannelsUpdate(); /*! * @brief Let the background thread update the provider list. + * @param clientId The id of the PVR client to update. */ + void TriggerProvidersUpdate(int clientId); void TriggerProvidersUpdate(); /*! * @brief Let the background thread update the channel groups list. + * @param clientId The id of the PVR client to update. */ + void TriggerChannelGroupsUpdate(int clientId); void TriggerChannelGroupsUpdate(); /*! @@ -381,12 +362,57 @@ namespace PVR */ bool SetWakeupCommand(); + enum class ManagerState + { + STATE_ERROR = 0, + STATE_STOPPED, + STATE_STARTING, + STATE_SSTOPPING, + STATE_INTERRUPTED, + STATE_STARTED + }; + + /*! + * @return True while the PVRManager is initialising. + */ + bool IsInitialising() const { return GetState() == ManagerState::STATE_STARTING; } + + /*! + * @brief Check whether the PVRManager has been stopped. + * @return True if stopped, false otherwise. + */ + bool IsStopped() const { return GetState() == ManagerState::STATE_STOPPED; } + + /*! + * @brief Get the current state of the PVR manager. + * @return the state. + */ + ManagerState GetState() const; + /*! - * @brief Load at least one client and load all other PVR data (channelgroups, timers, recordings) after loading the client. - * @param progressHandler The progress handler to use for showing the different load stages. - * @return If at least one client and all pvr data was loaded, false otherwise. + * @brief Set the current state of the PVR manager. + * @param state the new state. */ - bool LoadComponents(CPVRGUIProgressHandler* progressHandler); + void SetState(ManagerState state); + + /*! + * @brief Wait until at least one client is up. Update all data from database and the given PVR clients. + * @param knownClients [inout] List of last known active clients. + * @param stateToCheck Required state of the PVR manager while this method gets called. + */ + void UpdateComponents(std::vector<std::shared_ptr<CPVRClient>>& knownClients, + ManagerState stateToCheck); + + /*! + * @brief Update all data from database and the given PVR clients. + * @param knownClients [inout] List of last known active clients. + * @param stateToCheck Required state of the PVR manager while this method gets called. + * @param progressHandler The progress handler to use for showing the different stages. + * @return True if at least one client is known and successfully loaded, false otherwise. + */ + bool UpdateComponents(std::vector<std::shared_ptr<CPVRClient>>& knownClients, + ManagerState stateToCheck, + CPVRGUIProgressHandler* progressHandler); /*! * @brief Unload all PVR data (recordings, timers, channelgroups). @@ -408,28 +434,6 @@ namespace PVR */ void TriggerPlayChannelOnStartup(); - enum ManagerState - { - ManagerStateError = 0, - ManagerStateStopped, - ManagerStateStarting, - ManagerStateStopping, - ManagerStateInterrupted, - ManagerStateStarted - }; - - /*! - * @brief Get the current state of the PVR manager. - * @return the state. - */ - ManagerState GetState() const; - - /*! - * @brief Set the current state of the PVR manager. - * @param state the new state. - */ - void SetState(ManagerState state); - bool IsCurrentlyParentalLocked(const std::shared_ptr<CPVRChannel>& channel, bool bGenerallyLocked) const; CEventSource<PVREvent> m_events; @@ -453,7 +457,7 @@ namespace PVR bool m_bEpgsCreated = false; /*!< true if epg data for channels has been created */ mutable CCriticalSection m_managerStateMutex; - ManagerState m_managerState = ManagerStateStopped; + ManagerState m_managerState = ManagerState::STATE_STOPPED; std::unique_ptr<CStopWatch> m_parentalTimer; CCriticalSection m_startStopMutex; // mutex for protecting pvr manager's start/restart/stop sequence */ diff --git a/xbmc/pvr/addons/PVRClient.cpp b/xbmc/pvr/addons/PVRClient.cpp index fb374ec5e1..5e95f27fdb 100644 --- a/xbmc/pvr/addons/PVRClient.cpp +++ b/xbmc/pvr/addons/PVRClient.cpp @@ -171,11 +171,15 @@ ADDON_STATUS CPVRClient::Create(int iClientId) ResetProperties(iClientId); /* initialise the add-on */ - bool bReadyToUse(false); - CLog::LogFC(LOGDEBUG, LOGPVR, "Creating PVR add-on instance '{}'", Name()); + CLog::LogFC(LOGDEBUG, LOGPVR, "Creating PVR add-on instance '{}'", ID()); + + bool bReadyToUse = false; if ((status = CreateInstance()) == ADDON_STATUS_OK) bReadyToUse = GetAddonProperties(); + CLog::LogFC(LOGDEBUG, LOGPVR, "Created PVR add-on instance '{}'. readytouse={} ", ID(), + bReadyToUse); + m_bReadyToUse = bReadyToUse; return status; } @@ -187,14 +191,14 @@ void CPVRClient::Destroy() m_bReadyToUse = false; - CLog::LogFC(LOGDEBUG, LOGPVR, "Destroying PVR add-on instance '{}'", GetFriendlyName()); + CLog::LogFC(LOGDEBUG, LOGPVR, "Destroying PVR add-on instance '{}'", ID()); m_bBlockAddonCalls = true; m_allAddonCallsFinished.Wait(); DestroyInstance(); - CLog::LogFC(LOGDEBUG, LOGPVR, "PVR add-on instance '{}' destroyed", GetFriendlyName()); + CLog::LogFC(LOGDEBUG, LOGPVR, "Destroyed PVR add-on instance '{}'", ID()); if (m_menuhooks) m_menuhooks->Clear(); @@ -561,10 +565,7 @@ bool CPVRClient::GetAddonProperties() { if (types_array[i].iId == PVR_TIMER_TYPE_NONE) { - CLog::LogF(LOGERROR, - "Invalid timer type supplied by add-on '{}'. Please contact the developer " - "of this add-on: {}", - GetFriendlyName(), Author()); + CLog::LogF(LOGERROR, "Invalid timer type supplied by add-on '{}'.", ID()); continue; } timerTypes.emplace_back( @@ -1418,10 +1419,24 @@ PVR_ERROR CPVRClient::DoAddonCall(const char* strFunctionName, return PVR_ERROR_NOT_IMPLEMENTED; if (m_bBlockAddonCalls) + { + CLog::Log(LOGWARNING, "{}: Blocking call to add-on '{}'.", strFunctionName, ID()); + return PVR_ERROR_SERVER_ERROR; + } + + if (bCheckReadyToUse && IgnoreClient()) + { + CLog::Log(LOGWARNING, "{}: Blocking call to add-on '{}'. Add-on not (yet) connected.", + strFunctionName, ID()); return PVR_ERROR_SERVER_ERROR; + } - if (bCheckReadyToUse && (!ReadyToUse() || IgnoreClient())) + if (bCheckReadyToUse && !ReadyToUse()) + { + CLog::Log(LOGWARNING, "{}: Blocking call to add-on '{}'. Add-on not ready to use.", + strFunctionName, ID()); return PVR_ERROR_SERVER_ERROR; + } // Call. m_allAddonCallsFinished.Reset(); @@ -1435,7 +1450,7 @@ PVR_ERROR CPVRClient::DoAddonCall(const char* strFunctionName, // Log error, if any. if (error != PVR_ERROR_NO_ERROR && error != PVR_ERROR_NOT_IMPLEMENTED) - CLog::Log(LOGERROR, "{}: Add-on '{}' returned an error: {}", strFunctionName, GetFriendlyName(), + CLog::Log(LOGERROR, "{}: Add-on '{}' returned an error: {}", strFunctionName, ID(), ToString(error)); return error; @@ -1457,7 +1472,7 @@ PVR_ERROR CPVRClient::OpenLiveStream(const std::shared_ptr<CPVRChannel>& channel if (!CanPlayChannel(channel)) { - CLog::LogFC(LOGDEBUG, LOGPVR, "Add-on '{}' can not play channel '{}'", GetFriendlyName(), + CLog::LogFC(LOGDEBUG, LOGPVR, "Add-on '{}' can not play channel '{}'", ID(), channel->ChannelName()); return PVR_ERROR_SERVER_ERROR; } @@ -1716,7 +1731,7 @@ void CPVRClient::HandleAddonCallback(const char* strFunctionName, if (!bForceCall && client->m_bBlockAddonCalls && client->m_iAddonCalls == 0) { CLog::Log(LOGWARNING, LOGPVR, "{}: Ignoring callback from PVR client '{}'", strFunctionName, - client->GetFriendlyName()); + client->ID()); return; } @@ -1922,7 +1937,7 @@ void CPVRClient::cb_recording_notification(void* kodiInstance, EventPtr(new CNotificationEvent(client->Name(), strLine1, client->Icon(), strLine2))); CLog::LogFC(LOGDEBUG, LOGPVR, "Recording {} on client '{}'. name='{}' filename='{}'", - bOnOff ? "started" : "finished", client->Name(), strName, strFileName); + bOnOff ? "started" : "finished", client->ID(), strName, strFileName); }); } @@ -1930,21 +1945,23 @@ void CPVRClient::cb_trigger_channel_update(void* kodiInstance) { HandleAddonCallback(__func__, kodiInstance, [&](CPVRClient* client) { // update channels in the next iteration of the pvrmanager's main loop - CServiceBroker::GetPVRManager().TriggerChannelsUpdate(); + CServiceBroker::GetPVRManager().TriggerChannelsUpdate(client->GetID()); }); } void CPVRClient::cb_trigger_provider_update(void* kodiInstance) { - /* update the providers table in the next iteration of the pvrmanager's main loop */ - CServiceBroker::GetPVRManager().TriggerProvidersUpdate(); + HandleAddonCallback(__func__, kodiInstance, [&](CPVRClient* client) { + /* update the providers table in the next iteration of the pvrmanager's main loop */ + CServiceBroker::GetPVRManager().TriggerProvidersUpdate(client->GetID()); + }); } void CPVRClient::cb_trigger_timer_update(void* kodiInstance) { HandleAddonCallback(__func__, kodiInstance, [&](CPVRClient* client) { // update timers in the next iteration of the pvrmanager's main loop - CServiceBroker::GetPVRManager().TriggerTimersUpdate(); + CServiceBroker::GetPVRManager().TriggerTimersUpdate(client->GetID()); }); } @@ -1952,7 +1969,7 @@ void CPVRClient::cb_trigger_recording_update(void* kodiInstance) { HandleAddonCallback(__func__, kodiInstance, [&](CPVRClient* client) { // update recordings in the next iteration of the pvrmanager's main loop - CServiceBroker::GetPVRManager().TriggerRecordingsUpdate(); + CServiceBroker::GetPVRManager().TriggerRecordingsUpdate(client->GetID()); }); } @@ -1960,7 +1977,7 @@ void CPVRClient::cb_trigger_channel_groups_update(void* kodiInstance) { HandleAddonCallback(__func__, kodiInstance, [&](CPVRClient* client) { // update all channel groups in the next iteration of the pvrmanager's main loop - CServiceBroker::GetPVRManager().TriggerChannelGroupsUpdate(); + CServiceBroker::GetPVRManager().TriggerChannelGroupsUpdate(client->GetID()); }); } @@ -2009,7 +2026,7 @@ void CPVRClient::cb_connection_state_change(void* kodiInstance, CLog::LogFC(LOGDEBUG, LOGPVR, "State for connection '{}' on client '{}' changed from '{}' to '{}'", - strConnectionString, client->Name(), prevState, newState); + strConnectionString, client->ID(), prevState, newState); client->SetConnectionState(newState); diff --git a/xbmc/pvr/addons/PVRClients.cpp b/xbmc/pvr/addons/PVRClients.cpp index d6b30ca5f6..23ce9bbed7 100644 --- a/xbmc/pvr/addons/PVRClients.cpp +++ b/xbmc/pvr/addons/PVRClients.cpp @@ -157,8 +157,7 @@ void CPVRClients::UpdateAddons(const std::string& changedAddonId /*= ""*/) if (status != ADDON_STATUS_OK) { - CLog::LogF(LOGERROR, "Failed to create add-on {}, status = {}", addon.first->Name(), - status); + CLog::LogF(LOGERROR, "Failed to create add-on {}, status = {}", addon.first->ID(), status); if (status == ADDON_STATUS_PERMANENT_FAILURE) { CServiceBroker::GetAddonMgr().DisableAddon(addon.first->ID(), @@ -305,7 +304,7 @@ bool CPVRClients::HasCreatedClients() const CSingleLock lock(m_critSection); for (const auto& client : m_clientMap) { - if (client.second->ReadyToUse() && !client.second->IgnoreClient()) + if (client.second->ReadyToUse()) return true; } @@ -350,7 +349,7 @@ int CPVRClients::GetCreatedClients(CPVRClientMap& clients) const CSingleLock lock(m_critSection); for (const auto& client : m_clientMap) { - if (client.second->ReadyToUse() && !client.second->IgnoreClient()) + if (client.second->ReadyToUse()) { clients.insert(std::make_pair(client.second->GetID(), client.second)); ++iReturn; @@ -391,7 +390,20 @@ std::vector<CVariant> CPVRClients::GetClientProviderInfos() const return clientProviderInfos; } -PVR_ERROR CPVRClients::GetCreatedClients(CPVRClientMap& clientsReady, std::vector<int>& clientsNotReady) const +int CPVRClients::GetFirstCreatedClientID() +{ + CSingleLock lock(m_critSection); + for (const auto& client : m_clientMap) + { + if (client.second->ReadyToUse()) + return client.second->GetID(); + } + + return -1; +} + +PVR_ERROR CPVRClients::GetCallableClients(CPVRClientMap& clientsReady, + std::vector<int>& clientsNotReady) const { clientsNotReady.clear(); @@ -417,18 +429,6 @@ PVR_ERROR CPVRClients::GetCreatedClients(CPVRClientMap& clientsReady, std::vecto return clientsNotReady.empty() ? PVR_ERROR_NO_ERROR : PVR_ERROR_SERVER_ERROR; } -int CPVRClients::GetFirstCreatedClientID() -{ - CSingleLock lock(m_critSection); - for (const auto& client : m_clientMap) - { - if (client.second->ReadyToUse()) - return client.second->GetID(); - } - - return -1; -} - int CPVRClients::EnabledClientAmount() const { int iReturn = 0; @@ -448,6 +448,13 @@ int CPVRClients::EnabledClientAmount() const return iReturn; } +bool CPVRClients::IsEnabledClient(int clientId) const +{ + std::shared_ptr<CPVRClient> client; + GetClient(clientId, client); + return client && !CServiceBroker::GetAddonMgr().IsAddonDisabled(client->ID()); +} + std::vector<CVariant> CPVRClients::GetEnabledClientInfos() const { std::vector<CVariant> clientInfos; @@ -487,6 +494,18 @@ std::vector<CVariant> CPVRClients::GetEnabledClientInfos() const return clientInfos; } +bool CPVRClients::HasIgnoredClients() const +{ + CSingleLock lock(m_critSection); + for (const auto& client : m_clientMap) + { + if (client.second->IgnoreClient()) + return true; + } + + return false; +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////// // client API calls //////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -528,11 +547,15 @@ std::vector<SBackend> CPVRClients::GetBackendProperties() const return backendProperties; } -bool CPVRClients::GetTimers(CPVRTimersContainer* timers, std::vector<int>& failedClients) +bool CPVRClients::GetTimers(const std::vector<std::shared_ptr<CPVRClient>>& clients, + CPVRTimersContainer* timers, + std::vector<int>& failedClients) { - return ForCreatedClients(__FUNCTION__, [timers](const std::shared_ptr<CPVRClient>& client) { - return client->GetTimers(timers); - }, failedClients) == PVR_ERROR_NO_ERROR; + return ForClients(__FUNCTION__, clients, + [timers](const std::shared_ptr<CPVRClient>& client) { + return client->GetTimers(timers); + }, + failedClients) == PVR_ERROR_NO_ERROR; } PVR_ERROR CPVRClients::GetTimerTypes(std::vector<std::shared_ptr<CPVRTimerType>>& results) const @@ -546,16 +569,16 @@ PVR_ERROR CPVRClients::GetTimerTypes(std::vector<std::shared_ptr<CPVRTimerType>> }); } -PVR_ERROR CPVRClients::GetRecordings(CPVRRecordings* recordings, +PVR_ERROR CPVRClients::GetRecordings(const std::vector<std::shared_ptr<CPVRClient>>& clients, + CPVRRecordings* recordings, bool deleted, std::vector<int>& failedClients) { - return ForCreatedClients( - __FUNCTION__, - [recordings, deleted](const std::shared_ptr<CPVRClient>& client) { - return client->GetRecordings(recordings, deleted); - }, - failedClients); + return ForClients(__FUNCTION__, clients, + [recordings, deleted](const std::shared_ptr<CPVRClient>& client) { + return client->GetRecordings(recordings, deleted); + }, + failedClients); } PVR_ERROR CPVRClients::DeleteAllRecordingsFromTrash() @@ -579,44 +602,51 @@ PVR_ERROR CPVRClients::SetEPGMaxFutureDays(int iFutureDays) }); } -PVR_ERROR CPVRClients::GetChannels(bool bRadio, +PVR_ERROR CPVRClients::GetChannels(const std::vector<std::shared_ptr<CPVRClient>>& clients, + bool bRadio, std::vector<std::shared_ptr<CPVRChannel>>& channels, std::vector<int>& failedClients) { - return ForCreatedClients( - __FUNCTION__, - [bRadio, &channels](const std::shared_ptr<CPVRClient>& client) { - return client->GetChannels(bRadio, channels); - }, - failedClients); + return ForClients(__FUNCTION__, clients, + [bRadio, &channels](const std::shared_ptr<CPVRClient>& client) { + return client->GetChannels(bRadio, channels); + }, + failedClients); } -PVR_ERROR CPVRClients::GetProviders(CPVRProvidersContainer* providers, +PVR_ERROR CPVRClients::GetProviders(const std::vector<std::shared_ptr<CPVRClient>>& clients, + CPVRProvidersContainer* providers, std::vector<int>& failedClients) { - return ForCreatedClients(__FUNCTION__, [providers](const std::shared_ptr<CPVRClient>& client) { - return client->GetProviders(*providers); - }, failedClients); + return ForClients(__FUNCTION__, clients, + [providers](const std::shared_ptr<CPVRClient>& client) { + return client->GetProviders(*providers); + }, + failedClients); } -PVR_ERROR CPVRClients::GetChannelGroups(CPVRChannelGroups* groups, std::vector<int>& failedClients) +PVR_ERROR CPVRClients::GetChannelGroups(const std::vector<std::shared_ptr<CPVRClient>>& clients, + CPVRChannelGroups* groups, + std::vector<int>& failedClients) { - return ForCreatedClients(__FUNCTION__, [groups](const std::shared_ptr<CPVRClient>& client) { - return client->GetChannelGroups(groups); - }, failedClients); + return ForClients(__FUNCTION__, clients, + [groups](const std::shared_ptr<CPVRClient>& client) { + return client->GetChannelGroups(groups); + }, + failedClients); } PVR_ERROR CPVRClients::GetChannelGroupMembers( + const std::vector<std::shared_ptr<CPVRClient>>& clients, CPVRChannelGroup* group, std::vector<std::shared_ptr<CPVRChannelGroupMember>>& groupMembers, std::vector<int>& failedClients) { - return ForCreatedClients( - __FUNCTION__, - [group, &groupMembers](const std::shared_ptr<CPVRClient>& client) { - return client->GetChannelGroupMembers(group, groupMembers); - }, - failedClients); + return ForClients(__FUNCTION__, clients, + [group, &groupMembers](const std::shared_ptr<CPVRClient>& client) { + return client->GetChannelGroupMembers(group, groupMembers); + }, + failedClients); } std::vector<std::shared_ptr<CPVRClient>> CPVRClients::GetClientsSupportingChannelScan() const @@ -786,6 +816,24 @@ void CPVRClients::ConnectionStateChange(CPVRClient* client, CJobManager::GetInstance().AddJob(new CPVREventLogJob(bNotify, bError, client->Name(), strMsg, client->Icon()), nullptr); } +namespace +{ + +void LogClientWarning(const char* strFunctionName, const std::shared_ptr<CPVRClient>& client) +{ + if (client->IgnoreClient()) + CLog::Log(LOGWARNING, "{}: Not calling add-on '{}'. Add-on not (yet) connected.", + strFunctionName, client->ID()); + else if (!client->ReadyToUse()) + CLog::Log(LOGWARNING, "{}: Not calling add-on '{}'. Add-on not ready to use.", strFunctionName, + client->ID()); + else + CLog::Log(LOGERROR, "{}: Not calling add-on '{}' for unexpected reason.", strFunctionName, + client->ID()); +} + +} // unnamed namespace + PVR_ERROR CPVRClients::ForCreatedClients(const char* strFunctionName, const PVRClientFunction& function) const { @@ -800,7 +848,19 @@ PVR_ERROR CPVRClients::ForCreatedClients(const char* strFunctionName, PVR_ERROR lastError = PVR_ERROR_NO_ERROR; CPVRClientMap clients; - GetCreatedClients(clients, failedClients); + GetCallableClients(clients, failedClients); + + if (!failedClients.empty()) + { + for (int id : failedClients) + { + std::shared_ptr<CPVRClient> client; + GetClient(id, client); + + if (client) + LogClientWarning(strFunctionName, client); + } + } for (const auto& clientEntry : clients) { @@ -808,11 +868,61 @@ PVR_ERROR CPVRClients::ForCreatedClients(const char* strFunctionName, if (currentError != PVR_ERROR_NO_ERROR && currentError != PVR_ERROR_NOT_IMPLEMENTED) { - CLog::Log(LOGERROR, "{}: PVR client '{}' returned an error: {}", strFunctionName, - clientEntry.second->GetFriendlyName(), CPVRClient::ToString(currentError)); lastError = currentError; failedClients.emplace_back(clientEntry.first); } } return lastError; } + +PVR_ERROR CPVRClients::ForClients(const char* strFunctionName, + const std::vector<std::shared_ptr<CPVRClient>>& clients, + const PVRClientFunction& function, + std::vector<int>& failedClients) const +{ + if (clients.empty()) + return ForCreatedClients(strFunctionName, function, failedClients); + + PVR_ERROR lastError = PVR_ERROR_NO_ERROR; + + failedClients.clear(); + + { + CSingleLock lock(m_critSection); + for (const auto& entry : m_clientMap) + { + if (entry.second->ReadyToUse() && !entry.second->IgnoreClient() && + std::find_if(clients.cbegin(), clients.cend(), + [&entry](const std::shared_ptr<CPVRClient>& client) { + return entry.first == client->GetID(); + }) != clients.cend()) + { + // Allow ready to use clients that shall be called + continue; + } + + failedClients.emplace_back(entry.first); + } + } + + for (const auto& client : clients) + { + if (std::find_if(failedClients.cbegin(), failedClients.cend(), [&client](int failedClientId) { + return client->GetID() == failedClientId; + }) == failedClients.cend()) + { + PVR_ERROR currentError = function(client); + + if (currentError != PVR_ERROR_NO_ERROR && currentError != PVR_ERROR_NOT_IMPLEMENTED) + { + lastError = currentError; + failedClients.emplace_back(client->GetID()); + } + } + else + { + LogClientWarning(strFunctionName, client); + } + } + return lastError; +} diff --git a/xbmc/pvr/addons/PVRClients.h b/xbmc/pvr/addons/PVRClients.h index f1edc34331..8bb173069b 100644 --- a/xbmc/pvr/addons/PVRClients.h +++ b/xbmc/pvr/addons/PVRClients.h @@ -158,12 +158,25 @@ namespace PVR int GetFirstCreatedClientID(); /*! + * @brief Check whether there are any created, but not (yet) connected clients. + * @return True if at least one client is ignored. + */ + bool HasIgnoredClients() const; + + /*! * @brief Get the number of enabled clients. * @return The amount of enabled clients. */ int EnabledClientAmount() const; /*! + * @brief Check whether a given client ID points to an enabled client. + * @param clientId The client ID. + * @return True if the the client ID represents an enabled client, false otherwise. + */ + bool IsEnabledClient(int clientId) const; + + /*! * @brief Get a list of the enabled client infos. * @return A list of enabled client infos. */ @@ -186,12 +199,15 @@ namespace PVR //@{ /*! - * @brief Get all timers from all created clients + * @brief Get all timers from the given clients + * @param clients The clients to fetch data from. Leave empty to fetch data from all created clients. * @param timers Store the timers in this container. * @param failedClients in case of errors will contain the ids of the clients for which the timers could not be obtained. * @return true on success for all clients, false in case of error for at least one client. */ - bool GetTimers(CPVRTimersContainer* timers, std::vector<int>& failedClients); + bool GetTimers(const std::vector<std::shared_ptr<CPVRClient>>& clients, + CPVRTimersContainer* timers, + std::vector<int>& failedClients); /*! * @brief Get all supported timer types. @@ -206,13 +222,15 @@ namespace PVR //@{ /*! - * @brief Get all recordings from clients + * @brief Get all recordings from the given clients + * @param clients The clients to fetch data from. Leave empty to fetch data from all created clients. * @param recordings Store the recordings in this container. * @param deleted If true, return deleted recordings, return not deleted recordings otherwise. * @param failedClients in case of errors will contain the ids of the clients for which the recordings could not be obtained. * @return PVR_ERROR_NO_ERROR if the operation succeeded, the respective PVR_ERROR value otherwise. */ - PVR_ERROR GetRecordings(CPVRRecordings* recordings, + PVR_ERROR GetRecordings(const std::vector<std::shared_ptr<CPVRClient>>& clients, + CPVRRecordings* recordings, bool deleted, std::vector<int>& failedClients); @@ -263,40 +281,50 @@ namespace PVR //@{ /*! - * @brief Get all channels from backends. + * @brief Get all channels from the given clients. + * @param clients The clients to fetch data from. Leave empty to fetch data from all created clients. * @param bRadio Whether to fetch radio or TV channels. * @param channels The container to store the channels. * @param failedClients in case of errors will contain the ids of the clients for which the channels could not be obtained. * @return PVR_ERROR_NO_ERROR if the channels were fetched successfully, last error otherwise. */ - PVR_ERROR GetChannels(bool bRadio, + PVR_ERROR GetChannels(const std::vector<std::shared_ptr<CPVRClient>>& clients, + bool bRadio, std::vector<std::shared_ptr<CPVRChannel>>& channels, std::vector<int>& failedClients); /*! * @brief Get all providers from backends. + * @param clients The clients to fetch data from. Leave empty to fetch data from all created clients. * @param group The container to store the providers in. * @param failedClients in case of errors will contain the ids of the clients for which the providers could not be obtained. * @return PVR_ERROR_NO_ERROR if the providers were fetched successfully, last error otherwise. */ - PVR_ERROR GetProviders(CPVRProvidersContainer* providers, std::vector<int>& failedClients); + PVR_ERROR GetProviders(const std::vector<std::shared_ptr<CPVRClient>>& clients, + CPVRProvidersContainer* providers, + std::vector<int>& failedClients); /*! - * @brief Get all channel groups from backends. + * @brief Get all channel groups from the given clients. + * @param clients The clients to fetch data from. Leave empty to fetch data from all created clients. * @param groups Store the channel groups in this container. * @param failedClients in case of errors will contain the ids of the clients for which the channel groups could not be obtained. * @return PVR_ERROR_NO_ERROR if the channel groups were fetched successfully, last error otherwise. */ - PVR_ERROR GetChannelGroups(CPVRChannelGroups* groups, std::vector<int>& failedClients); + PVR_ERROR GetChannelGroups(const std::vector<std::shared_ptr<CPVRClient>>& clients, + CPVRChannelGroups* groups, + std::vector<int>& failedClients); /*! - * @brief Get all group members of a channel group. + * @brief Get all group members of a channel group from the given clients. + * @param clients The clients to fetch data from. Leave empty to fetch data from all created clients. * @param group The group to get the member for. * @param groupMembers The container for the group members. * @param failedClients in case of errors will contain the ids of the clients for which the channel group members could not be obtained. * @return PVR_ERROR_NO_ERROR if the channel group members were fetched successfully, last error otherwise. */ PVR_ERROR GetChannelGroupMembers( + const std::vector<std::shared_ptr<CPVRClient>>& clients, CPVRChannelGroup* group, std::vector<std::shared_ptr<CPVRChannelGroupMember>>& groupMembers, std::vector<int>& failedClients); @@ -405,11 +433,25 @@ namespace PVR * @param clientsNotReady Store the the ids of the not (yet) ready clients in this list. * @return PVR_ERROR_NO_ERROR in case all clients are ready, PVR_ERROR_SERVER_ERROR otherwise. */ - PVR_ERROR GetCreatedClients(CPVRClientMap& clientsReady, std::vector<int>& clientsNotReady) const; + PVR_ERROR GetCallableClients(CPVRClientMap& clientsReady, + std::vector<int>& clientsNotReady) const; typedef std::function<PVR_ERROR(const std::shared_ptr<CPVRClient>&)> PVRClientFunction; /*! + * @brief Wraps calls to the given clients in order to do common pre and post function invocation actions. + * @param strFunctionName The function name, for logging purposes. + * @param clients The clients to wrap. + * @param function The function to wrap. It has to have return type PVR_ERROR and must take a const reference to a std::shared_ptr<CPVRClient> as parameter. + * @param failedClients Contains a list of the ids of clients for that the call failed, if any. + * @return PVR_ERROR_NO_ERROR on success, any other PVR_ERROR_* value otherwise. + */ + PVR_ERROR ForClients(const char* strFunctionName, + const std::vector<std::shared_ptr<CPVRClient>>& clients, + const PVRClientFunction& function, + std::vector<int>& failedClients) const; + + /*! * @brief Wraps calls to all created clients in order to do common pre and post function invocation actions. * @param strFunctionName The function name, for logging purposes. * @param function The function to wrap. It has to have return type PVR_ERROR and must take a const reference to a std::shared_ptr<CPVRClient> as parameter. diff --git a/xbmc/pvr/channels/PVRChannelGroup.cpp b/xbmc/pvr/channels/PVRChannelGroup.cpp index ca15abd5de..460c6ba12b 100644 --- a/xbmc/pvr/channels/PVRChannelGroup.cpp +++ b/xbmc/pvr/channels/PVRChannelGroup.cpp @@ -93,18 +93,19 @@ std::shared_ptr<CPVRChannelGroupSettings> CPVRChannelGroup::GetSettings() const return m_settings; } -bool CPVRChannelGroup::Load( - const std::map<std::pair<int, int>, std::shared_ptr<CPVRChannel>>& channels) +bool CPVRChannelGroup::LoadFromDatabase( + const std::map<std::pair<int, int>, std::shared_ptr<CPVRChannel>>& channels, + const std::vector<std::shared_ptr<CPVRClient>>& clients) { - /* make sure this container is empty before loading */ - Unload(); - - int iChannelCount = m_iGroupId > 0 ? LoadFromDb() : 0; + const int iChannelCount = m_iGroupId > 0 ? LoadFromDatabase(clients) : 0; CLog::LogFC(LOGDEBUG, LOGPVR, "Fetched {} {} group members from the database for group '{}'", iChannelCount, IsRadio() ? "radio" : "TV", GroupName()); for (const auto& groupMember : m_members) { + if (groupMember.second->Channel()) + continue; + auto channel = channels.find(groupMember.first); if (channel == channels.end()) { @@ -127,14 +128,14 @@ void CPVRChannelGroup::Unload() m_failedClients.clear(); } -bool CPVRChannelGroup::Update() +bool CPVRChannelGroup::UpdateFromClients(const std::vector<std::shared_ptr<CPVRClient>>& clients) { if (GroupType() == PVR_GROUP_TYPE_USER_DEFINED || !GetSettings()->SyncChannelGroups()) return true; // get the channel group members from the backends. std::vector<std::shared_ptr<CPVRChannelGroupMember>> groupMembers; - CServiceBroker::GetPVRManager().Clients()->GetChannelGroupMembers(this, groupMembers, + CServiceBroker::GetPVRManager().Clients()->GetChannelGroupMembers(clients, this, groupMembers, m_failedClients); return UpdateGroupEntries(groupMembers); } @@ -470,26 +471,32 @@ void CPVRChannelGroup::GetChannelNumbers(std::vector<std::string>& channelNumber } } -int CPVRChannelGroup::LoadFromDb() +int CPVRChannelGroup::LoadFromDatabase(const std::vector<std::shared_ptr<CPVRClient>>& clients) { const std::shared_ptr<CPVRDatabase> database(CServiceBroker::GetPVRManager().GetTVDatabase()); if (!database) return -1; - const int iChannelCount = Size(); - const std::vector<std::shared_ptr<CPVRChannelGroupMember>> results = database->Get(*this); + const std::vector<std::shared_ptr<CPVRChannelGroupMember>> results = + database->Get(*this, clients); std::vector<std::shared_ptr<CPVRChannelGroupMember>> membersToDelete; if (!results.empty()) { + const std::shared_ptr<CPVRClients> clients = CServiceBroker::GetPVRManager().Clients(); + CSingleLock lock(m_critSection); for (const auto& member : results) { // Consistency check. if (member->ClientID() > 0 && member->ChannelUID() > 0 && member->IsRadio() == IsRadio()) { - m_sortedMembers.emplace_back(member); - m_members.emplace(std::make_pair(member->ClientID(), member->ChannelUID()), member); + // Ignore data from unknown/disabled clients + if (clients->IsEnabledClient(member->ClientID())) + { + m_sortedMembers.emplace_back(member); + m_members.emplace(std::make_pair(member->ClientID(), member->ChannelUID()), member); + } } else { @@ -506,7 +513,7 @@ int CPVRChannelGroup::LoadFromDb() DeleteGroupMembersFromDb(membersToDelete); - return results.size() - membersToDelete.size() - iChannelCount; + return results.size() - membersToDelete.size(); } void CPVRChannelGroup::DeleteGroupMembersFromDb( @@ -661,15 +668,13 @@ std::vector<std::shared_ptr<CPVRChannelGroupMember>> CPVRChannelGroup::RemoveDel CLog::Log(LOGINFO, "Removed stale {} channel '{}' from group '{}'", IsRadio() ? "radio" : "TV", channel->ChannelName(), GroupName()); membersToRemove.emplace_back(*it); - } - m_members.erase(channel->StorageId()); - it = m_sortedMembers.erase(it); - } - else - { - ++it; + m_members.erase(channel->StorageId()); + it = m_sortedMembers.erase(it); + continue; + } } + ++it; } DeleteGroupMembersFromDb(membersToRemove); diff --git a/xbmc/pvr/channels/PVRChannelGroup.h b/xbmc/pvr/channels/PVRChannelGroup.h index ca3026aa44..07c4be20cc 100644 --- a/xbmc/pvr/channels/PVRChannelGroup.h +++ b/xbmc/pvr/channels/PVRChannelGroup.h @@ -32,6 +32,7 @@ namespace PVR class CPVRChannel; class CPVRChannelGroupMember; + class CPVRClient; class CPVREpgInfoTag; enum EpgDateType @@ -82,11 +83,14 @@ namespace PVR CEventStream<PVREvent>& Events() { return m_events; } /*! - * @brief Load the channels from the database, update and sync data from clients. + * @brief Load the channels from the database. * @param channels All available channels. + * @param clients The PVR clients data should be loaded for. Leave empty for all clients. * @return True when loaded successfully, false otherwise. */ - virtual bool Load(const std::map<std::pair<int, int>, std::shared_ptr<CPVRChannel>>& channels); + virtual bool LoadFromDatabase( + const std::map<std::pair<int, int>, std::shared_ptr<CPVRChannel>>& channels, + const std::vector<std::shared_ptr<CPVRClient>>& clients); /*! * @brief Clear all data. @@ -99,10 +103,11 @@ namespace PVR size_t Size() const; /*! - * @brief Refresh the channel list from the clients, sync with local data. + * @brief Update data with channel group members from the given clients, sync with local data. + * @param clients The clients to fetch data from. Leave empty to fetch data from all created clients. * @return True on success, false otherwise. */ - virtual bool Update(); + virtual bool UpdateFromClients(const std::vector<std::shared_ptr<CPVRClient>>& clients); /*! * @brief Get the path of this group. @@ -514,9 +519,10 @@ namespace PVR private: /*! * @brief Load the channel group members stored in the database. + * @param clients The PVR clients to load data for. Leave empty for all clients. * @return The amount of channel group members that were added. */ - int LoadFromDb(); + int LoadFromDatabase(const std::vector<std::shared_ptr<CPVRClient>>& clients); /*! * @brief Delete channel group members from database. diff --git a/xbmc/pvr/channels/PVRChannelGroupInternal.cpp b/xbmc/pvr/channels/PVRChannelGroupInternal.cpp index e7b4bc6715..0ec5ffb3a4 100644 --- a/xbmc/pvr/channels/PVRChannelGroupInternal.cpp +++ b/xbmc/pvr/channels/PVRChannelGroupInternal.cpp @@ -44,10 +44,11 @@ CPVRChannelGroupInternal::~CPVRChannelGroupInternal() Unload(); } -bool CPVRChannelGroupInternal::Load( - const std::map<std::pair<int, int>, std::shared_ptr<CPVRChannel>>& channels) +bool CPVRChannelGroupInternal::LoadFromDatabase( + const std::map<std::pair<int, int>, std::shared_ptr<CPVRChannel>>& channels, + const std::vector<std::shared_ptr<CPVRClient>>& clients) { - if (CPVRChannelGroup::Load(channels)) + if (CPVRChannelGroup::LoadFromDatabase(channels, clients)) { for (const auto& groupMember : m_members) { @@ -102,11 +103,13 @@ void CPVRChannelGroupInternal::UpdateChannelPaths() } } -bool CPVRChannelGroupInternal::Update() +bool CPVRChannelGroupInternal::UpdateFromClients( + const std::vector<std::shared_ptr<CPVRClient>>& clients) { - // get the channels from the backends + // get the channels from the given clients std::vector<std::shared_ptr<CPVRChannel>> channels; - CServiceBroker::GetPVRManager().Clients()->GetChannels(IsRadio(), channels, m_failedClients); + CServiceBroker::GetPVRManager().Clients()->GetChannels(clients, IsRadio(), channels, + m_failedClients); // create group members for the channels std::vector<std::shared_ptr<CPVRChannelGroupMember>> groupMembers; diff --git a/xbmc/pvr/channels/PVRChannelGroupInternal.h b/xbmc/pvr/channels/PVRChannelGroupInternal.h index 5511a6087e..5f8a06d9a7 100644 --- a/xbmc/pvr/channels/PVRChannelGroupInternal.h +++ b/xbmc/pvr/channels/PVRChannelGroupInternal.h @@ -82,17 +82,21 @@ namespace PVR const std::vector<std::shared_ptr<CPVRChannelGroupMember>>& groupMembers) override; /*! - * @brief Refresh the channel list from the clients, sync with local data. + * @brief Update data with 'all channels' group members from the given clients, sync with local data. + * @param clients The clients to fetch data from. Leave empty to fetch data from all created clients. * @return True on success, false otherwise. */ - bool Update() override; + bool UpdateFromClients(const std::vector<std::shared_ptr<CPVRClient>>& clients) override; /*! - * @brief Load the channels from the database, update and sync data from clients. + * @brief Load the channels from the database. * @param channels All available channels. + * @param clients The PVR clients data should be loaded for. Leave empty for all clients. * @return True when loaded successfully, false otherwise. */ - bool Load(const std::map<std::pair<int, int>, std::shared_ptr<CPVRChannel>>& channels) override; + bool LoadFromDatabase( + const std::map<std::pair<int, int>, std::shared_ptr<CPVRChannel>>& channels, + const std::vector<std::shared_ptr<CPVRClient>>& clients) override; /*! * @brief Clear all data. diff --git a/xbmc/pvr/channels/PVRChannelGroups.cpp b/xbmc/pvr/channels/PVRChannelGroups.cpp index dc0529e354..b8c97cf754 100644 --- a/xbmc/pvr/channels/PVRChannelGroups.cpp +++ b/xbmc/pvr/channels/PVRChannelGroups.cpp @@ -39,12 +39,15 @@ CPVRChannelGroups::CPVRChannelGroups(bool bRadio) : CPVRChannelGroups::~CPVRChannelGroups() { - Clear(); + Unload(); } -void CPVRChannelGroups::Clear() +void CPVRChannelGroups::Unload() { CSingleLock lock(m_critSection); + for (const auto& group : m_groups) + group->Unload(); + m_groups.clear(); m_failedClientsForChannelGroups.clear(); } @@ -195,7 +198,8 @@ bool CPVRChannelGroups::HasValidDataForAllClients() const return m_failedClientsForChannelGroups.empty(); } -bool CPVRChannelGroups::Update(bool bChannelsOnly /* = false */) +bool CPVRChannelGroups::UpdateFromClients(const std::vector<std::shared_ptr<CPVRClient>>& clients, + bool bChannelsOnly /* = false */) { bool bSyncWithBackends = CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool( CSettings::SETTING_PVRMANAGER_SYNCCHANNELGROUPS); @@ -207,7 +211,7 @@ bool CPVRChannelGroups::Update(bool bChannelsOnly /* = false */) if (bUpdateAllGroups) { // get channel groups from the clients - CServiceBroker::GetPVRManager().Clients()->GetChannelGroups(this, + CServiceBroker::GetPVRManager().Clients()->GetChannelGroups(clients, this, m_failedClientsForChannelGroups); CLog::LogFC(LOGDEBUG, LOGPVR, "{} new user defined {} channel groups fetched from clients", (m_groups.size() - iSize), m_bRadio ? "radio" : "TV"); @@ -231,7 +235,7 @@ bool CPVRChannelGroups::Update(bool bChannelsOnly /* = false */) if (bUpdateAllGroups || group->IsInternalGroup()) { const int iMemberCount = group->Size(); - if (!group->Update()) + if (!group->UpdateFromClients(clients)) { CLog::LogFC(LOGERROR, LOGPVR, "Failed to update channel group '{}'", group->GroupName()); bReturn = false; @@ -298,18 +302,29 @@ std::shared_ptr<CPVRChannelGroup> CPVRChannelGroups::CreateChannelGroup( return std::make_shared<CPVRChannelGroup>(path, GetGroupAll()); } -bool CPVRChannelGroups::LoadFromDb() +bool CPVRChannelGroups::LoadFromDatabase(const std::vector<std::shared_ptr<CPVRClient>>& clients) { const std::shared_ptr<CPVRDatabase> database(CServiceBroker::GetPVRManager().GetTVDatabase()); if (!database) return false; + CSingleLock lock(m_critSection); + + // Ensure we have an internal group. It is important that the internal group is created before + // loading contents from database and that it gets inserted in front of m_groups. Look at + // GetGroupAll() implementation to see why. + if (m_groups.empty()) + { + const auto internalGroup = std::make_shared<CPVRChannelGroupInternal>(m_bRadio); + m_groups.emplace_back(internalGroup); + } + CLog::LogFC(LOGDEBUG, LOGPVR, "Loading all {} channel groups and members", m_bRadio ? "radio" : "TV"); // load all channels from the database std::map<std::pair<int, int>, std::shared_ptr<CPVRChannel>> channels; - database->Get(m_bRadio, channels); + database->Get(m_bRadio, clients, channels); CLog::LogFC(LOGDEBUG, LOGPVR, "Fetched {} {} channels from the database", channels.size(), m_bRadio ? "radio" : "TV"); @@ -321,41 +336,24 @@ bool CPVRChannelGroups::LoadFromDb() // load all group members from the database for (const auto& group : m_groups) { - if (!group->Load(channels)) + if (!group->LoadFromDatabase(channels, clients)) { - CLog::LogFC(LOGERROR, LOGPVR, "Failed to load {} channel group '{}'", + CLog::LogFC(LOGERROR, LOGPVR, + "Failed to load members of {} channel group '{}' from the database", m_bRadio ? "radio" : "TV", group->GroupName()); } } - return true; -} -bool CPVRChannelGroups::Load() -{ + // Hide empty groups + for (auto it = m_groups.begin(); it != m_groups.end();) { - CSingleLock lock(m_critSection); - - // Remove previous contents - Clear(); - - // Ensure we have an internal group. It is important that the internal group is created before - // loading contents from database and that it gets inserted in front of m_groups. Look at - // GetGroupAll() implementation to see why. - const auto internalGroup = std::make_shared<CPVRChannelGroupInternal>(m_bRadio); - m_groups.emplace_back(internalGroup); - - // Load groups, group members and channels from database - LoadFromDb(); + if ((*it)->Size() == 0 && !(*it)->IsInternalGroup()) + it = m_groups.erase(it); + else + ++it; } - // Load data from clients and sync with local data - Update(); - - CLog::LogFC(LOGDEBUG, LOGPVR, "{} {} channel groups loaded", m_groups.size(), - m_bRadio ? "radio" : "TV"); - - // need at least 1 group - return m_groups.size() > 0; + return true; } bool CPVRChannelGroups::PersistAll() diff --git a/xbmc/pvr/channels/PVRChannelGroups.h b/xbmc/pvr/channels/PVRChannelGroups.h index f3367668c7..0e64ece1ca 100644 --- a/xbmc/pvr/channels/PVRChannelGroups.h +++ b/xbmc/pvr/channels/PVRChannelGroups.h @@ -19,6 +19,7 @@ namespace PVR { class CPVRChannel; + class CPVRClient; /** A container class for channel groups */ @@ -33,15 +34,16 @@ namespace PVR virtual ~CPVRChannelGroups(); /*! - * @brief Remove all channels from this group. + * @brief Remove all groups from this container. */ - void Clear(); + void Unload(); /*! - * @brief Load this container's contents from the database or PVR clients. - * @return True if it was loaded successfully, false if not. + * @brief Load all channel groups and all channels from PVR database. + * @param clients The PVR clients data should be loaded for. Leave empty for all clients. + * @return True on success, false otherwise. */ - bool Load(); + bool LoadFromDatabase(const std::vector<std::shared_ptr<CPVRClient>>& clients); /*! * @brief Create a channel group matching the given type. @@ -199,11 +201,13 @@ namespace PVR bool IsRadio() const { return m_bRadio; } /*! - * @brief Update the contents of the groups in this container. + * @brief Update data with groups and channels from the given clients, sync with local data. + * @param clients The clients to fetch data from. Leave empty to fetch data from all created clients. * @param bChannelsOnly Set to true to only update channels, not the groups themselves. - * @return True if the update was successful, false otherwise. + * @return True on success, false otherwise. */ - bool Update(bool bChannelsOnly = false); + bool UpdateFromClients(const std::vector<std::shared_ptr<CPVRClient>>& clients, + bool bChannelsOnly = false); /*! * @brief Update the channel numbers across the channel groups from the all channels group @@ -218,7 +222,6 @@ namespace PVR int CleanupCachedImages(); private: - bool LoadFromDb(); void SortGroups(); /*! diff --git a/xbmc/pvr/channels/PVRChannelGroupsContainer.cpp b/xbmc/pvr/channels/PVRChannelGroupsContainer.cpp index 19cdf51cd9..a8b65ddbe1 100644 --- a/xbmc/pvr/channels/PVRChannelGroupsContainer.cpp +++ b/xbmc/pvr/channels/PVRChannelGroupsContainer.cpp @@ -27,11 +27,24 @@ CPVRChannelGroupsContainer::CPVRChannelGroupsContainer() : CPVRChannelGroupsContainer::~CPVRChannelGroupsContainer() { + Unload(); delete m_groupsRadio; delete m_groupsTV; } -bool CPVRChannelGroupsContainer::Update(bool bChannelsOnly /* = false */) +bool CPVRChannelGroupsContainer::Update(const std::vector<std::shared_ptr<CPVRClient>>& clients) +{ + return LoadFromDatabase(clients) && UpdateFromClients(clients); +} + +bool CPVRChannelGroupsContainer::LoadFromDatabase( + const std::vector<std::shared_ptr<CPVRClient>>& clients) +{ + return m_groupsTV->LoadFromDatabase(clients) && m_groupsRadio->LoadFromDatabase(clients); +} + +bool CPVRChannelGroupsContainer::UpdateFromClients( + const std::vector<std::shared_ptr<CPVRClient>>& clients, bool bChannelsOnly /* = false */) { CSingleLock lock(m_critSection); if (m_bIsUpdating) @@ -40,7 +53,8 @@ bool CPVRChannelGroupsContainer::Update(bool bChannelsOnly /* = false */) lock.Leave(); CLog::LogFC(LOGDEBUG, LOGPVR, "Updating {}", bChannelsOnly ? "channels" : "channel groups"); - bool bReturn = m_groupsTV->Update(bChannelsOnly) && m_groupsRadio->Update(bChannelsOnly); + bool bReturn = m_groupsTV->UpdateFromClients(clients, bChannelsOnly) && + m_groupsRadio->UpdateFromClients(clients, bChannelsOnly); lock.Enter(); m_bIsUpdating = false; @@ -49,23 +63,10 @@ bool CPVRChannelGroupsContainer::Update(bool bChannelsOnly /* = false */) return bReturn; } -bool CPVRChannelGroupsContainer::Load() -{ - Unload(); - m_bLoaded = m_groupsTV->Load() && m_groupsRadio->Load(); - return m_bLoaded; -} - -bool CPVRChannelGroupsContainer::Loaded() const -{ - return m_bLoaded; -} - void CPVRChannelGroupsContainer::Unload() { - m_groupsRadio->Clear(); - m_groupsTV->Clear(); - m_bLoaded = false; + m_groupsRadio->Unload(); + m_groupsTV->Unload(); } CPVRChannelGroups* CPVRChannelGroupsContainer::Get(bool bRadio) const diff --git a/xbmc/pvr/channels/PVRChannelGroupsContainer.h b/xbmc/pvr/channels/PVRChannelGroupsContainer.h index 3eefc7276d..d7b7f57835 100644 --- a/xbmc/pvr/channels/PVRChannelGroupsContainer.h +++ b/xbmc/pvr/channels/PVRChannelGroupsContainer.h @@ -11,6 +11,7 @@ #include "threads/CriticalSection.h" #include <memory> +#include <vector> namespace PVR { @@ -18,6 +19,7 @@ namespace PVR class CPVRChannelGroup; class CPVRChannelGroupMember; class CPVRChannelGroups; + class CPVRClient; class CPVREpgInfoTag; class CPVRChannelGroupsContainer @@ -34,16 +36,20 @@ namespace PVR virtual ~CPVRChannelGroupsContainer(); /*! - * @brief Load all channel groups and all channels in those channel groups. - * @return True if all groups were loaded, false otherwise. + * @brief Update all channel groups and all channels from PVR database and from given clients. + * @param clients The PVR clients data should be loaded for. Leave empty for all clients. + * @return True on success, false otherwise. */ - bool Load(); + bool Update(const std::vector<std::shared_ptr<CPVRClient>>& clients); /*! - * @brief Checks whether groups were already loaded. - * @return True if groups were successfully loaded, false otherwise. + * @brief Update data with groups and channels from the given clients, sync with local data. + * @param clients The clients to fetch data from. Leave empty to fetch data from all created clients. + * @param bChannelsOnly Set to true to only update channels, not the groups themselves. + * @return True on success, false otherwise. */ - bool Loaded() const; + bool UpdateFromClients(const std::vector<std::shared_ptr<CPVRClient>>& clients, + bool bChannelsOnly = false); /*! * @brief Unload and destruct all channel groups and all channels in them. @@ -51,13 +57,6 @@ namespace PVR void Unload(); /*! - * @brief Update the contents of all the groups in this container. - * @param bChannelsOnly Set to true to only update channels, not the groups themselves. - * @return True if the update was successful, false otherwise. - */ - bool Update(bool bChannelsOnly = false); - - /*! * @brief Get the TV channel groups. * @return The TV channel groups. */ @@ -161,10 +160,16 @@ namespace PVR CPVRChannelGroupsContainer& operator=(const CPVRChannelGroupsContainer&) = delete; CPVRChannelGroupsContainer(const CPVRChannelGroupsContainer&) = delete; + /*! + * @brief Load all channel groups and all channels from PVR database. + * @param clients The PVR clients data should be loaded for. Leave empty for all clients. + * @return True on success, false otherwise. + */ + bool LoadFromDatabase(const std::vector<std::shared_ptr<CPVRClient>>& clients); + CPVRChannelGroups* m_groupsRadio; /*!< all radio channel groups */ CPVRChannelGroups* m_groupsTV; /*!< all TV channel groups */ CCriticalSection m_critSection; bool m_bIsUpdating = false; - bool m_bLoaded = false; }; } diff --git a/xbmc/pvr/dialogs/GUIDialogPVRChannelManager.cpp b/xbmc/pvr/dialogs/GUIDialogPVRChannelManager.cpp index 7c8f9b364c..d92d049a7f 100644 --- a/xbmc/pvr/dialogs/GUIDialogPVRChannelManager.cpp +++ b/xbmc/pvr/dialogs/GUIDialogPVRChannelManager.cpp @@ -706,7 +706,7 @@ bool CGUIDialogPVRChannelManager::OnContextButton(int itemNumber, CONTEXT_BUTTON CServiceBroker::GetPVRManager().ChannelGroups()->Get(m_bIsRadio); if (groups) { - groups->Update(); + groups->UpdateFromClients({}); Update(); } } @@ -754,10 +754,10 @@ void CGUIDialogPVRChannelManager::Update() std::shared_ptr<CPVRChannelGroup> channels = CServiceBroker::GetPVRManager().ChannelGroups()->GetGroupAll(m_bIsRadio); // No channels available, nothing to do. - if(!channels) + if (!channels) return; - channels->Update(); + channels->UpdateFromClients({}); const std::vector<std::shared_ptr<CPVRChannelGroupMember>> groupMembers = channels->GetMembers(); std::shared_ptr<CFileItem> channelFile; diff --git a/xbmc/pvr/dialogs/GUIDialogPVRRecordingSettings.cpp b/xbmc/pvr/dialogs/GUIDialogPVRRecordingSettings.cpp index 01904e66aa..7f3d7c3fd5 100644 --- a/xbmc/pvr/dialogs/GUIDialogPVRRecordingSettings.cpp +++ b/xbmc/pvr/dialogs/GUIDialogPVRRecordingSettings.cpp @@ -136,7 +136,7 @@ bool CGUIDialogPVRRecordingSettings::OnSettingChanging( CVariant{19068}, // "Recording settings" StringUtils::Format(g_localizeStrings.Get(19147), iNewLifetime)) // "Setting the lifetime..." - != HELPERS::DialogResponse::YES) + != HELPERS::DialogResponse::CHOICE_YES) return false; } } diff --git a/xbmc/pvr/epg/EpgContainer.cpp b/xbmc/pvr/epg/EpgContainer.cpp index ef6bc2af19..9bb73d7315 100644 --- a/xbmc/pvr/epg/EpgContainer.cpp +++ b/xbmc/pvr/epg/EpgContainer.cpp @@ -236,7 +236,7 @@ void CPVREpgContainer::Notify(const PVREvent& event) m_events.Publish(event); } -void CPVREpgContainer::LoadFromDB() +void CPVREpgContainer::LoadFromDatabase() { CSingleLock lock(m_critSection); @@ -564,7 +564,7 @@ std::shared_ptr<CPVREpg> CPVREpgContainer::CreateChannelEpg(int iEpgId, const st std::shared_ptr<CPVREpg> epg; WaitForUpdateFinish(); - LoadFromDB(); + LoadFromDatabase(); if (iEpgId > 0) epg = GetById(iEpgId); @@ -736,7 +736,8 @@ bool CPVREpgContainer::UpdateEPG(bool bOnlyPending /* = false */) CPVRGUIProgressHandler* progressHandler = nullptr; if (bShowProgress && !bOnlyPending) - progressHandler = new CPVRGUIProgressHandler(g_localizeStrings.Get(19004)); // Importing guide from clients + progressHandler = + new CPVRGUIProgressHandler(g_localizeStrings.Get(19004)); // Loading programme guide /* load or update all EPG tables */ unsigned int iCounter = 0; diff --git a/xbmc/pvr/epg/EpgContainer.h b/xbmc/pvr/epg/EpgContainer.h index 90df6d3eb3..f4a3fed2d2 100644 --- a/xbmc/pvr/epg/EpgContainer.h +++ b/xbmc/pvr/epg/EpgContainer.h @@ -312,7 +312,7 @@ namespace PVR /*! * @brief Load all tables from the database */ - void LoadFromDB(); + void LoadFromDatabase(); /*! * @brief Insert data from database diff --git a/xbmc/pvr/filesystem/PVRGUIDirectory.cpp b/xbmc/pvr/filesystem/PVRGUIDirectory.cpp index 148c05afeb..5dabfde0db 100644 --- a/xbmc/pvr/filesystem/PVRGUIDirectory.cpp +++ b/xbmc/pvr/filesystem/PVRGUIDirectory.cpp @@ -200,8 +200,7 @@ bool CPVRGUIDirectory::GetDirectory(CFileItemList& results) const } else if (StringUtils::StartsWith(fileName, "channels")) { - if (CServiceBroker::GetPVRManager().ChannelGroups() && - CServiceBroker::GetPVRManager().ChannelGroups()->Loaded()) + if (CServiceBroker::GetPVRManager().IsStarted()) { return GetChannelsDirectory(results); } diff --git a/xbmc/pvr/guilib/GUIEPGGridContainer.cpp b/xbmc/pvr/guilib/GUIEPGGridContainer.cpp index 78deab458d..6015883787 100644 --- a/xbmc/pvr/guilib/GUIEPGGridContainer.cpp +++ b/xbmc/pvr/guilib/GUIEPGGridContainer.cpp @@ -370,7 +370,7 @@ void CGUIEPGGridContainer::ProcessItem(float posX, float posY, const CFileItemPt { if (!item->GetFocusedLayout()) { - item->SetFocusedLayout(CGUIListItemLayoutPtr(new CGUIListItemLayout(*focusedlayout))); + item->SetFocusedLayout(std::make_unique<CGUIListItemLayout>(*focusedlayout, this)); } if (resize != -1.0f) @@ -402,7 +402,7 @@ void CGUIEPGGridContainer::ProcessItem(float posX, float posY, const CFileItemPt { if (!item->GetLayout()) { - item->SetLayout(CGUIListItemLayoutPtr(new CGUIListItemLayout(*normallayout))); + item->SetLayout(std::make_unique<CGUIListItemLayout>(*normallayout, this)); } if (resize != -1.0f) diff --git a/xbmc/pvr/guilib/PVRGUIActionListener.cpp b/xbmc/pvr/guilib/PVRGUIActionListener.cpp index d6112c2515..374801b0cc 100644 --- a/xbmc/pvr/guilib/PVRGUIActionListener.cpp +++ b/xbmc/pvr/guilib/PVRGUIActionListener.cpp @@ -333,7 +333,7 @@ void CPVRGUIActionListener::OnSettingAction(const std::shared_ptr<const CSetting if (dialog) { dialog->Open(); - CServiceBroker::GetPVRManager().ChannelGroups()->Update(); + CServiceBroker::GetPVRManager().ChannelGroups()->UpdateFromClients({}); } } } diff --git a/xbmc/pvr/guilib/PVRGUIActions.cpp b/xbmc/pvr/guilib/PVRGUIActions.cpp index 321afd8ed5..3c6a9f6e04 100644 --- a/xbmc/pvr/guilib/PVRGUIActions.cpp +++ b/xbmc/pvr/guilib/PVRGUIActions.cpp @@ -950,9 +950,11 @@ namespace PVR case TimerOperationResult::RECORDING: { // recording running. ask the user if it should be deleted anyway - if (HELPERS::ShowYesNoDialogText(CVariant{122}, // "Confirm delete" - CVariant{19122}) // "This timer is still recording. Are you sure you want to delete this timer?" - != HELPERS::DialogResponse::YES) + if (HELPERS::ShowYesNoDialogText( + CVariant{122}, // "Confirm delete" + CVariant{ + 19122}) // "This timer is still recording. Are you sure you want to delete this timer?" + != HELPERS::DialogResponse::CHOICE_YES) return false; return DeleteTimer(timer, true, bDeleteRule); @@ -2168,12 +2170,12 @@ namespace PVR } // Inform user about PVR being busy. Ask if user wants to powerdown anyway. - bReturn = HELPERS::ShowYesNoDialogText(CVariant{19685}, // "Confirm shutdown" - CVariant{text}, - CVariant{222}, // "Shutdown anyway", - CVariant{19696}, // "Cancel" - 10000) // timeout value before closing - == HELPERS::DialogResponse::YES; + bReturn = + HELPERS::ShowYesNoDialogText(CVariant{19685}, // "Confirm shutdown" + CVariant{text}, CVariant{222}, // "Shutdown anyway", + CVariant{19696}, // "Cancel" + 10000) // timeout value before closing + == HELPERS::DialogResponse::CHOICE_YES; } else bReturn = false; // do not powerdown (busy, but no user interaction requested). diff --git a/xbmc/pvr/guilib/PVRGUIProgressHandler.cpp b/xbmc/pvr/guilib/PVRGUIProgressHandler.cpp index c03fac7a0d..2b2f8cc4ba 100644 --- a/xbmc/pvr/guilib/PVRGUIProgressHandler.cpp +++ b/xbmc/pvr/guilib/PVRGUIProgressHandler.cpp @@ -22,77 +22,82 @@ using namespace std::chrono_literals; namespace PVR { - CPVRGUIProgressHandler::CPVRGUIProgressHandler(const std::string& strTitle) - : CThread("PVRGUIProgressHandler"), - m_strTitle(strTitle), - m_fProgress(0.0f), - m_bChanged(false) + +CPVRGUIProgressHandler::CPVRGUIProgressHandler(const std::string& strTitle) + : CThread("PVRGUIProgressHandler"), m_strTitle(strTitle) +{ +} + +void CPVRGUIProgressHandler::UpdateProgress(const std::string& strText, float fProgress) +{ + CSingleLock lock(m_critSection); + m_bChanged = true; + m_strText = strText; + m_fProgress = fProgress; + + if (!m_bCreated) { + m_bCreated = true; Create(true /* bAutoDelete */); } +} - void CPVRGUIProgressHandler::UpdateProgress(const std::string& strText, float fProgress) - { - CSingleLock lock(m_critSection); - m_bChanged = true; - m_strText = strText; - m_fProgress = fProgress; - } +void CPVRGUIProgressHandler::UpdateProgress(const std::string& strText, int iCurrent, int iMax) +{ + float fPercentage = (iCurrent * 100.0f) / iMax; + if (!std::isnan(fPercentage)) + fPercentage = std::min(100.0f, fPercentage); - void CPVRGUIProgressHandler::UpdateProgress(const std::string& strText, int iCurrent, int iMax) - { - float fPercentage = (iCurrent * 100.0f) / iMax; - if (!std::isnan(fPercentage)) - fPercentage = std::min(100.0f, fPercentage); + UpdateProgress(strText, fPercentage); +} - UpdateProgress(strText, fPercentage); - } +void CPVRGUIProgressHandler::DestroyProgress() +{ + CSingleLock lock(m_critSection); + m_bStop = true; + m_bChanged = false; +} - void CPVRGUIProgressHandler::DestroyProgress() - { - CSingleLock lock(m_critSection); - m_bStop = true; - m_bChanged = false; - } +void CPVRGUIProgressHandler::Process() +{ + CGUIDialogExtendedProgressBar* progressBar = + CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogExtendedProgressBar>( + WINDOW_DIALOG_EXT_PROGRESS); + if (m_bStop || !progressBar) + return; - void CPVRGUIProgressHandler::Process() - { - CGUIDialogExtendedProgressBar* progressBar = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogExtendedProgressBar>(WINDOW_DIALOG_EXT_PROGRESS); - if (m_bStop || !progressBar) - return; + CGUIDialogProgressBarHandle* progressHandle = progressBar->GetHandle(m_strTitle); + if (!progressHandle) + return; - CGUIDialogProgressBarHandle* progressHandle = progressBar->GetHandle(m_strTitle); - if (!progressHandle) - return; + while (!m_bStop) + { + float fProgress = 0.0; + std::string strText; + bool bUpdate = false; - while (!m_bStop) { - float fProgress = 0.0; - std::string strText; - bool bUpdate = false; - + CSingleLock lock(m_critSection); + if (m_bChanged) { - CSingleLock lock(m_critSection); - if (m_bChanged) - { - m_bChanged = false; - fProgress = m_fProgress; - strText = m_strText; - bUpdate = true; - } - } - - if (bUpdate) - { - progressHandle->SetPercentage(fProgress); - progressHandle->SetText(strText); + m_bChanged = false; + fProgress = m_fProgress; + strText = m_strText; + bUpdate = true; } + } - // Intentionally ignore some changes that come in too fast. Humans cannot read as fast as Mr. Data ;-) - CThread::Sleep(100ms); + if (bUpdate) + { + progressHandle->SetPercentage(fProgress); + progressHandle->SetText(strText); } - progressHandle->MarkFinished(); + // Intentionally ignore some changes that come in too fast. Humans cannot read as fast as Mr. Data ;-) + CThread::Sleep(100ms); } + progressHandle->MarkFinished(); +} + } // namespace PVR diff --git a/xbmc/pvr/guilib/PVRGUIProgressHandler.h b/xbmc/pvr/guilib/PVRGUIProgressHandler.h index 7660edb77f..b82534328b 100644 --- a/xbmc/pvr/guilib/PVRGUIProgressHandler.h +++ b/xbmc/pvr/guilib/PVRGUIProgressHandler.h @@ -55,8 +55,9 @@ namespace PVR CCriticalSection m_critSection; const std::string m_strTitle; std::string m_strText; - float m_fProgress; - bool m_bChanged; + float m_fProgress{0.0f}; + bool m_bChanged{false}; + bool m_bCreated{false}; }; } // namespace PVR diff --git a/xbmc/pvr/providers/PVRProviders.cpp b/xbmc/pvr/providers/PVRProviders.cpp index a65ce7fc2c..53f9ec2f88 100644 --- a/xbmc/pvr/providers/PVRProviders.cpp +++ b/xbmc/pvr/providers/PVRProviders.cpp @@ -90,18 +90,9 @@ std::size_t CPVRProvidersContainer::GetNumProviders() const return m_providers.size(); } -bool CPVRProviders::Load() +bool CPVRProviders::Update(const std::vector<std::shared_ptr<CPVRClient>>& clients) { - // unload previous providers - Unload(); - - // load providers from database - bool bReturn = LoadFromDatabase(); - - // update from clients - Update(); - - return bReturn; + return LoadFromDatabase(clients) && UpdateFromClients(clients); } void CPVRProviders::Unload() @@ -111,7 +102,7 @@ void CPVRProviders::Unload() m_providers.clear(); } -bool CPVRProviders::LoadFromDatabase() +bool CPVRProviders::LoadFromDatabase(const std::vector<std::shared_ptr<CPVRClient>>& clients) { const std::shared_ptr<CPVRDatabase> database = CServiceBroker::GetPVRManager().GetTVDatabase(); if (database) @@ -119,7 +110,7 @@ bool CPVRProviders::LoadFromDatabase() bool bChanged = false; CPVRProviders providers; - database->Get(providers); + database->Get(providers, clients); for (auto& provider : providers.GetProvidersList()) { @@ -129,7 +120,7 @@ bool CPVRProviders::LoadFromDatabase() return true; } -bool CPVRProviders::Update() +bool CPVRProviders::UpdateFromClients(const std::vector<std::shared_ptr<CPVRClient>>& clients) { { CSingleLock lock(m_critSection); @@ -163,7 +154,7 @@ bool CPVRProviders::Update() CLog::LogFC(LOGDEBUG, LOGPVR, "Updating providers"); CPVRProvidersContainer newProviderList; std::vector<int> failedClients; - CServiceBroker::GetPVRManager().Clients()->GetProviders(&newProviderList, failedClients); + CServiceBroker::GetPVRManager().Clients()->GetProviders(clients, &newProviderList, failedClients); return UpdateClientEntries(newProviderList, failedClients, disabledClients); } @@ -220,14 +211,12 @@ bool CPVRProviders::UpdateClientEntries(const CPVRProvidersContainer& newProvide const std::vector<int>& failedClients, const std::vector<int>& disabledClients) { - bool bChanged = false; - CSingleLock lock(m_critSection); // go through the provider list and check for updated or new providers for (const auto& newProvider : newProviders.GetProvidersList()) { - bChanged |= (CheckAndPersistEntry(newProvider, ProviderUpdateMode::BY_CLIENT) != nullptr); + CheckAndPersistEntry(newProvider, ProviderUpdateMode::BY_CLIENT); } // check for deleted providers @@ -271,8 +260,6 @@ bool CPVRProviders::UpdateClientEntries(const CPVRProvidersContainer& newProvide (*it)->DeleteFromDatabase(); it = m_providers.erase(it); - - bChanged = true; } else { @@ -282,7 +269,7 @@ bool CPVRProviders::UpdateClientEntries(const CPVRProvidersContainer& newProvide m_bIsUpdating = false; - return bChanged; + return true; } std::shared_ptr<CPVRProvider> CPVRProviders::CheckAndAddEntry( diff --git a/xbmc/pvr/providers/PVRProviders.h b/xbmc/pvr/providers/PVRProviders.h index acb4b11737..8196d3b6d2 100644 --- a/xbmc/pvr/providers/PVRProviders.h +++ b/xbmc/pvr/providers/PVRProviders.h @@ -15,6 +15,7 @@ namespace PVR { +class CPVRClient; class CPVRProvider; enum class ProviderUpdateMode; @@ -64,10 +65,11 @@ public: ~CPVRProviders() = default; /** - * @brief (re)load the providers from the clients. - * @return True if loaded successfully, false otherwise. + * @brief Update all providers from PVR database and from given clients. + * @param clients The PVR clients data should be loaded for. Leave empty for all clients. + * @return True on success, false otherwise. */ - bool Load(); + bool Update(const std::vector<std::shared_ptr<CPVRClient>>& clients); /** * @brief unload all providers. @@ -75,15 +77,18 @@ public: void Unload(); /** - * @brief refresh the providers list from the clients. + * @brief Update data with providers from the given clients, sync with local data. + * @param clients The clients to fetch data from. Leave empty to fetch data from all created clients. + * @return True on success, false otherwise. */ - bool Update(); + bool UpdateFromClients(const std::vector<std::shared_ptr<CPVRClient>>& clients); /** - * @brief load the local providers from database. - * @return True if loaded successfully, false otherwise. + * @brief Load all local providers from PVR database. + * @param clients The PVR clients data should be loaded for. Leave empty for all clients. + * @return True on success, false otherwise. */ - bool LoadFromDatabase(); + bool LoadFromDatabase(const std::vector<std::shared_ptr<CPVRClient>>& clients); /*! * @brief Check if the entry exists in the container, if it does update it otherwise add it diff --git a/xbmc/pvr/recordings/PVRRecordings.cpp b/xbmc/pvr/recordings/PVRRecordings.cpp index f4c3b4c98c..ad0b74c397 100644 --- a/xbmc/pvr/recordings/PVRRecordings.cpp +++ b/xbmc/pvr/recordings/PVRRecordings.cpp @@ -34,16 +34,21 @@ CPVRRecordings::~CPVRRecordings() m_database->Close(); } -void CPVRRecordings::UpdateFromClients() +bool CPVRRecordings::UpdateFromClients(const std::vector<std::shared_ptr<CPVRClient>>& clients) { CSingleLock lock(m_critSection); + if (m_bIsUpdating) + return false; + + m_bIsUpdating = true; + for (const auto& recording : m_recordings) recording.second->SetDirty(true); std::vector<int> failedClients; - CServiceBroker::GetPVRManager().Clients()->GetRecordings(this, false, failedClients); - CServiceBroker::GetPVRManager().Clients()->GetRecordings(this, true, failedClients); + CServiceBroker::GetPVRManager().Clients()->GetRecordings(clients, this, false, failedClients); + CServiceBroker::GetPVRManager().Clients()->GetRecordings(clients, this, true, failedClients); // remove recordings that were deleted at the backend for (auto it = m_recordings.begin(); it != m_recordings.end();) @@ -54,13 +59,15 @@ void CPVRRecordings::UpdateFromClients() else ++it; } + + m_bIsUpdating = false; + CServiceBroker::GetPVRManager().PublishEvent(PVREvent::RecordingsInvalidated); + return true; } -int CPVRRecordings::Load() +bool CPVRRecordings::Update(const std::vector<std::shared_ptr<CPVRClient>>& clients) { - Unload(); - Update(); - return m_recordings.size(); + return UpdateFromClients(clients); } void CPVRRecordings::Unload() @@ -73,24 +80,6 @@ void CPVRRecordings::Unload() m_recordings.clear(); } -void CPVRRecordings::Update() -{ - CSingleLock lock(m_critSection); - if (m_bIsUpdating) - return; - m_bIsUpdating = true; - lock.Leave(); - - CLog::LogFC(LOGDEBUG, LOGPVR, "Updating recordings"); - UpdateFromClients(); - - lock.Enter(); - m_bIsUpdating = false; - lock.Leave(); - - CServiceBroker::GetPVRManager().PublishEvent(PVREvent::RecordingsInvalidated); -} - void CPVRRecordings::UpdateInProgressSize() { CSingleLock lock(m_critSection); diff --git a/xbmc/pvr/recordings/PVRRecordings.h b/xbmc/pvr/recordings/PVRRecordings.h index a592687a92..6ddea0fe69 100644 --- a/xbmc/pvr/recordings/PVRRecordings.h +++ b/xbmc/pvr/recordings/PVRRecordings.h @@ -32,10 +32,11 @@ namespace PVR virtual ~CPVRRecordings(); /*! - * @brief (re)load the recordings from the clients. - * @return the number of recordings loaded. + * @brief Update all recordings from the given PVR clients. + * @param clients The PVR clients data should be loaded for. Leave empty for all clients. + * @return True on success, false otherwise. */ - int Load(); + bool Update(const std::vector<std::shared_ptr<CPVRClient>>& clients); /*! * @brief unload all recordings. @@ -43,6 +44,13 @@ namespace PVR void Unload(); /*! + * @brief Update data with recordings from the given clients, sync with local data. + * @param clients The clients to fetch data from. Leave empty to fetch data from all created clients. + * @return True on success, false otherwise. + */ + bool UpdateFromClients(const std::vector<std::shared_ptr<CPVRClient>>& clients); + + /*! * @brief client has delivered a new/updated recording. * @param tag The recording * @param client The client the recording belongs to. @@ -50,11 +58,6 @@ namespace PVR void UpdateFromClient(const std::shared_ptr<CPVRRecording>& tag, const CPVRClient& client); /*! - * @brief refresh the recordings list from the clients. - */ - void Update(); - - /*! * @brief refresh the size of any in progress recordings from the clients. */ void UpdateInProgressSize(); @@ -113,8 +116,6 @@ namespace PVR unsigned int m_iTVRecordings = 0; unsigned int m_iRadioRecordings = 0; - void UpdateFromClients(); - /*! * @brief Get/Open the video database. * @return A reference to the video database. diff --git a/xbmc/pvr/timers/PVRTimers.cpp b/xbmc/pvr/timers/PVRTimers.cpp index 3b906454d4..b1c5ed7af9 100644 --- a/xbmc/pvr/timers/PVRTimers.cpp +++ b/xbmc/pvr/timers/PVRTimers.cpp @@ -99,18 +99,30 @@ CPVRTimers::CPVRTimers() { } -bool CPVRTimers::Load() +bool CPVRTimers::Update(const std::vector<std::shared_ptr<CPVRClient>>& clients) { - // unload previous timers - Unload(); + return LoadFromDatabase(clients) && UpdateFromClients(clients); +} +bool CPVRTimers::LoadFromDatabase(const std::vector<std::shared_ptr<CPVRClient>>& clients) +{ // load local timers from database - bool bReturn = LoadFromDatabase(); + const std::shared_ptr<CPVRDatabase> database = CServiceBroker::GetPVRManager().GetTVDatabase(); + if (database) + { + bool bChanged = false; - // update from clients - Update(); + const std::vector<std::shared_ptr<CPVRTimerInfoTag>> timers = + database->GetTimers(*this, clients); + for (const auto& timer : timers) + { + bChanged |= !!UpdateEntry(timer); + } - return bReturn; + if (bChanged) + NotifyTimersEvent(); + } + return true; } void CPVRTimers::Unload() @@ -134,7 +146,7 @@ void CPVRTimers::Stop() CServiceBroker::GetPVRManager().Events().Unsubscribe(this); } -bool CPVRTimers::Update() +bool CPVRTimers::UpdateFromClients(const std::vector<std::shared_ptr<CPVRClient>>& clients) { { CSingleLock lock(m_critSection); @@ -146,29 +158,10 @@ bool CPVRTimers::Update() CLog::LogFC(LOGDEBUG, LOGPVR, "Updating timers"); CPVRTimersContainer newTimerList; std::vector<int> failedClients; - CServiceBroker::GetPVRManager().Clients()->GetTimers(&newTimerList, failedClients); + CServiceBroker::GetPVRManager().Clients()->GetTimers(clients, &newTimerList, failedClients); return UpdateEntries(newTimerList, failedClients); } -bool CPVRTimers::LoadFromDatabase() -{ - const std::shared_ptr<CPVRDatabase> database = CServiceBroker::GetPVRManager().GetTVDatabase(); - if (database) - { - bool bChanged = false; - - const std::vector<std::shared_ptr<CPVRTimerInfoTag>> timers = database->GetTimers(*this); - for (const auto& timer : timers) - { - bChanged |= !!UpdateEntry(timer); - } - - if (bChanged) - NotifyTimersEvent(); - } - return true; -} - void CPVRTimers::Process() { while (!m_bStop) @@ -404,7 +397,7 @@ bool CPVRTimers::UpdateEntries(const CPVRTimersContainer& timers, const std::vec } } - return bChanged; + return true; } namespace diff --git a/xbmc/pvr/timers/PVRTimers.h b/xbmc/pvr/timers/PVRTimers.h index 9a937070f0..c052379d29 100644 --- a/xbmc/pvr/timers/PVRTimers.h +++ b/xbmc/pvr/timers/PVRTimers.h @@ -23,6 +23,7 @@ namespace PVR enum class PVREvent; class CPVRChannel; + class CPVRClient; class CPVREpgInfoTag; class CPVRTimerInfoTag; class CPVRTimersPath; @@ -68,37 +69,34 @@ namespace PVR CPVRTimers(); ~CPVRTimers() override = default; - /** + /*! * @brief start the timer update thread. */ void Start(); - /** + /*! * @brief stop the timer update thread. */ void Stop(); - /** - * @brief (re)load the timers from the clients. - * @return True if loaded successfully, false otherwise. + /*! + * @brief Update all timers from PVR database and from given clients. + * @param clients The PVR clients data should be loaded for. Leave empty for all clients. + * @return True on success, false otherwise. */ - bool Load(); + bool Update(const std::vector<std::shared_ptr<CPVRClient>>& clients); - /** + /*! * @brief unload all timers. */ void Unload(); - /** - * @brief refresh the timer list from the clients. - */ - bool Update(); - - /** - * @brief load the local timers from database. - * @return True if loaded successfully, false otherwise. + /*! + * @brief Update data with recordings from the given clients, sync with local data. + * @param clients The clients to fetch data from. Leave empty to fetch data from all created clients. + * @return True on success, false otherwise. */ - bool LoadFromDatabase(); + bool UpdateFromClients(const std::vector<std::shared_ptr<CPVRClient>>& clients); /*! * @param bIgnoreReminders include or ignore reminders @@ -269,6 +267,13 @@ namespace PVR private: void Process() override; + /*! + * @brief Load all timers from PVR database. + * @param clients The PVR clients data should be loaded for. Leave empty for all clients. + * @return True on success, false otherwise. + */ + bool LoadFromDatabase(const std::vector<std::shared_ptr<CPVRClient>>& clients); + void RemoveEntry(const std::shared_ptr<CPVRTimerInfoTag>& tag); bool UpdateEntries(const CPVRTimersContainer& timers, const std::vector<int>& failedClients); bool UpdateEntries(int iMaxNotificationDelay); diff --git a/xbmc/pvr/windows/GUIWindowPVRGuide.cpp b/xbmc/pvr/windows/GUIWindowPVRGuide.cpp index 728ee88df2..bbac6396cf 100644 --- a/xbmc/pvr/windows/GUIWindowPVRGuide.cpp +++ b/xbmc/pvr/windows/GUIWindowPVRGuide.cpp @@ -486,9 +486,9 @@ bool CGUIWindowPVRGuideBase::OnMessage(CGUIMessage& message) HELPERS::ShowYesNoDialogText(CVariant{19096}, // "Smart select" CVariant{iTextID}, CVariant{iNoButtonID}, CVariant{19165}); // Yes => "Switch" - if (ret == HELPERS::DialogResponse::NO) + if (ret == HELPERS::DialogResponse::CHOICE_NO) CServiceBroker::GetPVRManager().GUIActions()->AddTimer(pItem, false); - else if (ret == HELPERS::DialogResponse::YES) + else if (ret == HELPERS::DialogResponse::CHOICE_YES) CServiceBroker::GetPVRManager().GUIActions()->SwitchToChannel(pItem, true); } } diff --git a/xbmc/rendering/dx/DeviceResources.cpp b/xbmc/rendering/dx/DeviceResources.cpp index b58a1e6df3..4993b9344b 100644 --- a/xbmc/rendering/dx/DeviceResources.cpp +++ b/xbmc/rendering/dx/DeviceResources.cpp @@ -432,6 +432,8 @@ void DX::DeviceResources::CreateDeviceResources() KODI::PLATFORM::WINDOWS::FromW(aDesc.Description), GetFeatureLevelDescription(m_d3dFeatureLevel)); + CheckDXVA2SharedDecoderSurfaces(); + m_bDeviceCreated = true; } @@ -1096,6 +1098,45 @@ void DX::DeviceResources::CheckNV12SharedTexturesSupport() m_NV12SharedTexturesSupport ? " " : " NOT "); } +void DX::DeviceResources::CheckDXVA2SharedDecoderSurfaces() +{ + if (CSysInfo::GetWindowsDeviceFamily() != CSysInfo::Desktop) + return; + + VideoDriverInfo driver = GetVideoDriverVersion(); + + if (!m_NV12SharedTexturesSupport) + return; + + DXGI_ADAPTER_DESC ad = {}; + GetAdapterDesc(&ad); + + m_DXVA2SharedDecoderSurfaces = + ad.VendorId == PCIV_Intel || + (ad.VendorId == PCIV_NVIDIA && driver.valid && driver.majorVersion >= 465) || + (ad.VendorId == PCIV_AMD && driver.valid && driver.majorVersion >= 30); + + CLog::LogF(LOGINFO, "DXVA2 shared decoder surfaces is{}supported", + m_DXVA2SharedDecoderSurfaces ? " " : " NOT "); +} + +VideoDriverInfo DX::DeviceResources::GetVideoDriverVersion() +{ + DXGI_ADAPTER_DESC ad = {}; + GetAdapterDesc(&ad); + + VideoDriverInfo driver = CWIN32Util::GetVideoDriverInfo(ad.VendorId, ad.Description); + + if (ad.VendorId == PCIV_NVIDIA) + CLog::LogF(LOGINFO, "video driver version is {} {}.{} ({})", GetGFXProviderName(ad.VendorId), + driver.majorVersion, driver.minorVersion, driver.version); + else + CLog::LogF(LOGINFO, "video driver version is {} {}", GetGFXProviderName(ad.VendorId), + driver.version); + + return driver; +} + #if defined(TARGET_WINDOWS_DESKTOP) // This method is called when the window (WND) is created (or re-created). void DX::DeviceResources::SetWindow(HWND window) diff --git a/xbmc/rendering/dx/DeviceResources.h b/xbmc/rendering/dx/DeviceResources.h index 33c93b1462..d45890264f 100644 --- a/xbmc/rendering/dx/DeviceResources.h +++ b/xbmc/rendering/dx/DeviceResources.h @@ -22,6 +22,7 @@ struct RESOLUTION_INFO; struct DEBUG_INFO_RENDER; +struct VideoDriverInfo; namespace DX { @@ -112,6 +113,7 @@ namespace DX void SetWindowPos(winrt::Windows::Foundation::Rect rect); #endif // TARGET_WINDOWS_STORE bool IsNV12SharedTexturesSupported() const { return m_NV12SharedTexturesSupport; } + bool IsDXVA2SharedDecoderSurfaces() const { return m_DXVA2SharedDecoderSurfaces; } // Gets debug info from swapchain DEBUG_INFO_RENDER GetDebugInfo() const; @@ -136,6 +138,8 @@ namespace DX void HandleOutputChange(const std::function<bool(DXGI_OUTPUT_DESC)>& cmpFunc); bool CreateFactory(); void CheckNV12SharedTexturesSupport(); + VideoDriverInfo GetVideoDriverVersion(); + void CheckDXVA2SharedDecoderSurfaces(); HWND m_window{ nullptr }; #if defined(TARGET_WINDOWS_STORE) @@ -178,5 +182,6 @@ namespace DX bool m_IsHDROutput; bool m_IsTransferPQ; bool m_NV12SharedTexturesSupport{false}; + bool m_DXVA2SharedDecoderSurfaces{false}; }; } diff --git a/xbmc/rendering/dx/DirectXHelper.h b/xbmc/rendering/dx/DirectXHelper.h index 1133b6b024..bb51ca6fd7 100644 --- a/xbmc/rendering/dx/DirectXHelper.h +++ b/xbmc/rendering/dx/DirectXHelper.h @@ -16,6 +16,13 @@ #include <d3d11_4.h> #include <ppltasks.h> // For create_task +enum PCI_Vendors +{ + PCIV_AMD = 0x1002, + PCIV_NVIDIA = 0x10DE, + PCIV_Intel = 0x8086, +}; + namespace DX { #define RATIONAL_TO_FLOAT(rational) ((rational.Denominator != 0) ? \ @@ -94,6 +101,25 @@ namespace DX return StringUtils::Format("D3D_FEATURE_LEVEL_{}_{}", fl_major, fl_minor); } + inline std::string GetGFXProviderName(UINT vendorId) + { + std::string name; + switch (vendorId) + { + case PCIV_AMD: + name = "AMD"; + break; + case PCIV_Intel: + name = "Intel"; + break; + case PCIV_NVIDIA: + name = "NVIDIA"; + break; + } + + return name; + } + template <typename T> struct SizeGen { SizeGen<T>() { Width = Height = 0; } diff --git a/xbmc/rendering/dx/RenderSystemDX.h b/xbmc/rendering/dx/RenderSystemDX.h index 0889fe096c..9a18e22045 100644 --- a/xbmc/rendering/dx/RenderSystemDX.h +++ b/xbmc/rendering/dx/RenderSystemDX.h @@ -17,13 +17,6 @@ #include <wrl/client.h> -enum PCI_Vendors -{ - PCIV_ATI = 0x1002, - PCIV_nVidia = 0x10DE, - PCIV_Intel = 0x8086 -}; - class ID3DResource; class CGUIShaderDX; enum AVPixelFormat; diff --git a/xbmc/settings/DisplaySettings.cpp b/xbmc/settings/DisplaySettings.cpp index 407a3e126a..c6e816c550 100644 --- a/xbmc/settings/DisplaySettings.cpp +++ b/xbmc/settings/DisplaySettings.cpp @@ -290,8 +290,8 @@ bool CDisplaySettings::OnSettingChanging(const std::shared_ptr<const CSetting>& { if (!m_resolutionChangeAborted) { - if (HELPERS::ShowYesNoDialogText(CVariant{13110}, CVariant{13111}, CVariant{""}, CVariant{""}, 15000) != - DialogResponse::YES) + if (HELPERS::ShowYesNoDialogText(CVariant{13110}, CVariant{13111}, CVariant{""}, + CVariant{""}, 15000) != DialogResponse::CHOICE_YES) { m_resolutionChangeAborted = true; return false; @@ -311,8 +311,8 @@ bool CDisplaySettings::OnSettingChanging(const std::shared_ptr<const CSetting>& if (!m_resolutionChangeAborted) { - if (HELPERS::ShowYesNoDialogText(CVariant{13110}, CVariant{13111}, CVariant{""}, CVariant{""}, 10000) != - DialogResponse::YES) + if (HELPERS::ShowYesNoDialogText(CVariant{13110}, CVariant{13111}, CVariant{""}, CVariant{""}, + 10000) != DialogResponse::CHOICE_YES) { m_resolutionChangeAborted = true; return false; diff --git a/xbmc/settings/MediaSettings.cpp b/xbmc/settings/MediaSettings.cpp index f4af55a0ce..bc090ffb18 100644 --- a/xbmc/settings/MediaSettings.cpp +++ b/xbmc/settings/MediaSettings.cpp @@ -301,7 +301,7 @@ void CMediaSettings::OnSettingAction(const std::shared_ptr<const CSetting>& sett const std::string &settingId = setting->GetId(); if (settingId == CSettings::SETTING_MUSICLIBRARY_CLEANUP) { - if (HELPERS::ShowYesNoDialogText(CVariant{313}, CVariant{333}) == DialogResponse::YES) + if (HELPERS::ShowYesNoDialogText(CVariant{313}, CVariant{333}) == DialogResponse::CHOICE_YES) { if (!CMusicLibraryQueue::GetInstance().IsRunning()) CMusicLibraryQueue::GetInstance().CleanLibrary(true); @@ -332,7 +332,7 @@ void CMediaSettings::OnSettingAction(const std::shared_ptr<const CSetting>& sett } else if (settingId == CSettings::SETTING_VIDEOLIBRARY_CLEANUP) { - if (HELPERS::ShowYesNoDialogText(CVariant{313}, CVariant{333}) == DialogResponse::YES) + if (HELPERS::ShowYesNoDialogText(CVariant{313}, CVariant{333}) == DialogResponse::CHOICE_YES) { if (!CVideoLibraryQueue::GetInstance().IsRunning()) CVideoLibraryQueue::GetInstance().CleanLibraryModal(); diff --git a/xbmc/settings/SettingConditions.cpp b/xbmc/settings/SettingConditions.cpp index 048f269c17..8f5ec6a824 100644 --- a/xbmc/settings/SettingConditions.cpp +++ b/xbmc/settings/SettingConditions.cpp @@ -41,8 +41,9 @@ bool AddonHasSettings(const std::string& condition, return false; ADDON::AddonPtr addon; - if (!CServiceBroker::GetAddonMgr().GetAddon( - settingAddon->GetValue(), addon, settingAddon->GetAddonType(), ADDON::OnlyEnabled::YES) || + if (!CServiceBroker::GetAddonMgr().GetAddon(settingAddon->GetValue(), addon, + settingAddon->GetAddonType(), + ADDON::OnlyEnabled::CHOICE_YES) || addon == NULL) return false; diff --git a/xbmc/settings/dialogs/GUIDialogContentSettings.cpp b/xbmc/settings/dialogs/GUIDialogContentSettings.cpp index fb4e6e689e..8d0061d2ef 100644 --- a/xbmc/settings/dialogs/GUIDialogContentSettings.cpp +++ b/xbmc/settings/dialogs/GUIDialogContentSettings.cpp @@ -248,8 +248,8 @@ void CGUIDialogContentSettings::OnSettingAction(const std::shared_ptr<const CSet && selectedAddonId != currentScraperId) { AddonPtr scraperAddon; - if (CServiceBroker::GetAddonMgr().GetAddon(selectedAddonId, scraperAddon, - ADDON::ADDON_UNKNOWN, ADDON::OnlyEnabled::YES)) + if (CServiceBroker::GetAddonMgr().GetAddon( + selectedAddonId, scraperAddon, ADDON::ADDON_UNKNOWN, ADDON::OnlyEnabled::CHOICE_YES)) { m_scraper = std::dynamic_pointer_cast<CScraper>(scraperAddon); SetupView(); diff --git a/xbmc/settings/dialogs/GUIDialogLibExportSettings.cpp b/xbmc/settings/dialogs/GUIDialogLibExportSettings.cpp index 9c3a2c585a..7e88553af9 100644 --- a/xbmc/settings/dialogs/GUIDialogLibExportSettings.cpp +++ b/xbmc/settings/dialogs/GUIDialogLibExportSettings.cpp @@ -211,7 +211,7 @@ void CGUIDialogLibExportSettings::OnOK() { //"Unable to export to library folders as the system artist information folder setting is empty" //Settings (YES) button takes user to enter the artist info folder setting - if (HELPERS::ShowYesNoDialogText(20223, 38317, 186, 10004) == DialogResponse::YES) + if (HELPERS::ShowYesNoDialogText(20223, 38317, 186, 10004) == DialogResponse::CHOICE_YES) { m_confirmed = false; Close(); diff --git a/xbmc/settings/windows/GUIControlSettings.cpp b/xbmc/settings/windows/GUIControlSettings.cpp index a4f77c13d1..12aced38e7 100644 --- a/xbmc/settings/windows/GUIControlSettings.cpp +++ b/xbmc/settings/windows/GUIControlSettings.cpp @@ -1089,7 +1089,7 @@ void CGUIControlButtonSetting::Update(bool fromControl, bool updateDisplayOnly) { ADDON::AddonPtr addon; if (CServiceBroker::GetAddonMgr().GetAddon(addonID, addon, ADDON::ADDON_UNKNOWN, - ADDON::OnlyEnabled::YES)) + ADDON::OnlyEnabled::CHOICE_YES)) addonNames.push_back(addon->Name()); } diff --git a/xbmc/utils/RssManager.cpp b/xbmc/utils/RssManager.cpp index 765d8f9058..099347f436 100644 --- a/xbmc/utils/RssManager.cpp +++ b/xbmc/utils/RssManager.cpp @@ -66,10 +66,10 @@ void CRssManager::OnSettingAction(const std::shared_ptr<const CSetting>& setting { ADDON::AddonPtr addon; if (!CServiceBroker::GetAddonMgr().GetAddon("script.rss.editor", addon, ADDON::ADDON_UNKNOWN, - ADDON::OnlyEnabled::YES)) + ADDON::OnlyEnabled::CHOICE_YES)) { - if (!ADDON::CAddonInstaller::GetInstance().InstallModal("script.rss.editor", addon, - ADDON::InstallModalPrompt::PROMPT)) + if (!ADDON::CAddonInstaller::GetInstance().InstallModal( + "script.rss.editor", addon, ADDON::InstallModalPrompt::CHOICE_YES)) return; } CBuiltins::GetInstance().Execute("RunScript(script.rss.editor)"); diff --git a/xbmc/utils/StreamDetails.cpp b/xbmc/utils/StreamDetails.cpp index bea28b20c1..4944134df0 100644 --- a/xbmc/utils/StreamDetails.cpp +++ b/xbmc/utils/StreamDetails.cpp @@ -615,7 +615,11 @@ std::string CStreamDetails::VideoAspectToAspectDescription(float fAspect) // aspect ratios, particularly when cropping prior to video encoding is taken into account // the best we can do is take the "common" aspect ratios, and return the closest one available. // The cutoffs are the geometric mean of the two aspect ratios either side. - if (fAspect < 1.3499f) // sqrt(1.33*1.37) + if (fAspect < 1.0909f) // sqrt(1.00*1.19) + return "1.00"; + else if (fAspect < 1.2581f) // sqrt(1.19*1.33) + return "1.19"; + else if (fAspect < 1.3499f) // sqrt(1.33*1.37) return "1.33"; else if (fAspect < 1.5080f) // sqrt(1.37*1.66) return "1.37"; @@ -623,8 +627,10 @@ std::string CStreamDetails::VideoAspectToAspectDescription(float fAspect) return "1.66"; else if (fAspect < 1.8147f) // sqrt(1.78*1.85) return "1.78"; - else if (fAspect < 2.0174f) // sqrt(1.85*2.20) + else if (fAspect < 1.9235f) // sqrt(1.85*2.00) return "1.85"; + else if (fAspect < 2.0976f) // sqrt(2.00*2.20) + return "2.00"; else if (fAspect < 2.2738f) // sqrt(2.20*2.35) return "2.20"; else if (fAspect < 2.3749f) // sqrt(2.35*2.40) diff --git a/xbmc/video/VideoDatabase.cpp b/xbmc/video/VideoDatabase.cpp index b82cb92b7a..2ee513e978 100644 --- a/xbmc/video/VideoDatabase.cpp +++ b/xbmc/video/VideoDatabase.cpp @@ -8082,7 +8082,7 @@ ScraperPtr CVideoDatabase::GetScraperForPath(const std::string& strPath, SScanSe AddonPtr addon; if (!scraperID.empty() && CServiceBroker::GetAddonMgr().GetAddon(scraperID, addon, ADDON::ADDON_UNKNOWN, - ADDON::OnlyEnabled::YES)) + ADDON::OnlyEnabled::CHOICE_YES)) { scraper = std::dynamic_pointer_cast<CScraper>(addon); if (!scraper) @@ -8130,7 +8130,7 @@ ScraperPtr CVideoDatabase::GetScraperForPath(const std::string& strPath, SScanSe AddonPtr addon; if (content != CONTENT_NONE && CServiceBroker::GetAddonMgr().GetAddon( m_pDS->fv("path.strScraper").get_asString(), addon, - ADDON::ADDON_UNKNOWN, ADDON::OnlyEnabled::YES)) + ADDON::ADDON_UNKNOWN, ADDON::OnlyEnabled::CHOICE_YES)) { scraper = std::dynamic_pointer_cast<CScraper>(addon); scraper->SetPathSettings(content, m_pDS->fv("path.strSettings").get_asString()); @@ -10434,7 +10434,7 @@ void CVideoDatabase::ImportFromXML(const std::string &path) std::string id; XMLUtils::GetString(path,"scraperpath",id); if (CServiceBroker::GetAddonMgr().GetAddon(id, addon, ADDON::ADDON_UNKNOWN, - ADDON::OnlyEnabled::YES)) + ADDON::OnlyEnabled::CHOICE_YES)) { SScanSettings settings; ScraperPtr scraper = std::dynamic_pointer_cast<CScraper>(addon); diff --git a/xbmc/video/VideoInfoScanner.cpp b/xbmc/video/VideoInfoScanner.cpp index 39bfcb52d7..8cd3c937fb 100644 --- a/xbmc/video/VideoInfoScanner.cpp +++ b/xbmc/video/VideoInfoScanner.cpp @@ -2166,7 +2166,8 @@ namespace VIDEO HELPERS::ShowOKDialogText(CVariant{20448}, CVariant{20449}); return false; } - return HELPERS::ShowYesNoDialogText(CVariant{20448}, CVariant{20450}) == DialogResponse::YES; + return HELPERS::ShowYesNoDialogText(CVariant{20448}, CVariant{20450}) == + DialogResponse::CHOICE_YES; } bool CVideoInfoScanner::ProgressCancelled(CGUIDialogProgress* progress, int heading, const std::string &line1) diff --git a/xbmc/video/dialogs/GUIDialogSubtitles.cpp b/xbmc/video/dialogs/GUIDialogSubtitles.cpp index 4f0f3f29f5..99ec404cdc 100644 --- a/xbmc/video/dialogs/GUIDialogSubtitles.cpp +++ b/xbmc/video/dialogs/GUIDialogSubtitles.cpp @@ -425,7 +425,7 @@ void CGUIDialogSubtitles::OnSubtitleServiceContextMenu(int itemIdx) { AddonPtr addon; if (CServiceBroker::GetAddonMgr().GetAddon(service->GetProperty("Addon.ID").asString(), addon, - ADDON_SUBTITLE_MODULE, OnlyEnabled::YES)) + ADDON_SUBTITLE_MODULE, OnlyEnabled::CHOICE_YES)) { CGUIDialogAddonSettings::ShowForAddon(addon); } diff --git a/xbmc/view/GUIViewState.cpp b/xbmc/view/GUIViewState.cpp index f54d5ff45f..ff99c1baa4 100644 --- a/xbmc/view/GUIViewState.cpp +++ b/xbmc/view/GUIViewState.cpp @@ -598,7 +598,7 @@ CGUIViewStateFromItems::CGUIViewStateFromItems(const CFileItemList &items) : CGU CURL url(items.GetPath()); AddonPtr addon; if (CServiceBroker::GetAddonMgr().GetAddon(url.GetHostName(), addon, ADDON_PLUGIN, - OnlyEnabled::YES)) + OnlyEnabled::CHOICE_YES)) { PluginPtr plugin = std::static_pointer_cast<CPluginSource>(addon); if (plugin->Provides(CPluginSource::AUDIO)) diff --git a/xbmc/weather/WeatherJob.cpp b/xbmc/weather/WeatherJob.cpp index 6cb214bf19..7638dbbad3 100644 --- a/xbmc/weather/WeatherJob.cpp +++ b/xbmc/weather/WeatherJob.cpp @@ -53,7 +53,7 @@ bool CWeatherJob::DoWork() if (!CServiceBroker::GetAddonMgr().GetAddon( CServiceBroker::GetSettingsComponent()->GetSettings()->GetString( CSettings::SETTING_WEATHER_ADDON), - addon, ADDON_SCRIPT_WEATHER, OnlyEnabled::YES)) + addon, ADDON_SCRIPT_WEATHER, OnlyEnabled::CHOICE_YES)) return false; // initialize our sys.argv variables diff --git a/xbmc/weather/WeatherManager.cpp b/xbmc/weather/WeatherManager.cpp index 0c31cbdf9a..42c2c65ea2 100644 --- a/xbmc/weather/WeatherManager.cpp +++ b/xbmc/weather/WeatherManager.cpp @@ -177,7 +177,7 @@ void CWeatherManager::OnSettingAction(const std::shared_ptr<const CSetting>& set if (CServiceBroker::GetAddonMgr().GetAddon( CServiceBroker::GetSettingsComponent()->GetSettings()->GetString( CSettings::SETTING_WEATHER_ADDON), - addon, ADDON_SCRIPT_WEATHER, OnlyEnabled::YES) && + addon, ADDON_SCRIPT_WEATHER, OnlyEnabled::CHOICE_YES) && addon != NULL) { //! @todo maybe have ShowAndGetInput return a bool if settings changed, then only reset weather if true. CGUIDialogAddonSettings::ShowForAddon(addon); diff --git a/xbmc/windows/GUIMediaWindow.cpp b/xbmc/windows/GUIMediaWindow.cpp index a36b4d5253..908abe5bb3 100644 --- a/xbmc/windows/GUIMediaWindow.cpp +++ b/xbmc/windows/GUIMediaWindow.cpp @@ -1052,7 +1052,7 @@ bool CGUIMediaWindow::OnClick(int iItem, const std::string &player) CURL url(pItem->GetPath()); AddonPtr addon; if (CServiceBroker::GetAddonMgr().GetAddon(url.GetHostName(), addon, ADDON_SCRIPT, - OnlyEnabled::YES)) + OnlyEnabled::CHOICE_YES)) { if (!CScriptInvocationManager::GetInstance().Stop(addon->LibPath())) { @@ -1156,7 +1156,7 @@ bool CGUIMediaWindow::OnClick(int iItem, const std::string &player) CURL url(m_vecItems->GetPath()); AddonPtr addon; if (CServiceBroker::GetAddonMgr().GetAddon(url.GetHostName(), addon, ADDON_UNKNOWN, - OnlyEnabled::YES)) + OnlyEnabled::CHOICE_YES)) { PluginPtr plugin = std::dynamic_pointer_cast<CPluginSource>(addon); if (plugin && plugin->Provides(CPluginSource::AUDIO)) diff --git a/xbmc/windows/GUIWindowScreensaverDim.cpp b/xbmc/windows/GUIWindowScreensaverDim.cpp index 7746b23f39..87a12331e2 100644 --- a/xbmc/windows/GUIWindowScreensaverDim.cpp +++ b/xbmc/windows/GUIWindowScreensaverDim.cpp @@ -38,7 +38,7 @@ void CGUIWindowScreensaverDim::UpdateVisibility() m_visible = true; ADDON::AddonPtr info; bool success = CServiceBroker::GetAddonMgr().GetAddon(usedId, info, ADDON::ADDON_SCREENSAVER, - ADDON::OnlyEnabled::YES); + ADDON::OnlyEnabled::CHOICE_YES); if (success && info && !info->GetSetting("level").empty()) m_newDimLevel = 100.0f - (float)atof(info->GetSetting("level").c_str()); else |