New Upstream Release - kodi-pvr-waipu

Ready changes

Summary

Merged new upstream version: 20.9.0+ds1 (was: 20.6.0+ds1).

Resulting package

Built on 2023-07-25T12:10 (took 5m30s)

The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:

apt install -t fresh-releases kodi-pvr-waipu-dbgsymapt install -t fresh-releases kodi-pvr-waipu

Lintian Result

Diff

diff --git a/.clang-format b/.clang-format
index d7c740c..e29c658 100644
--- a/.clang-format
+++ b/.clang-format
@@ -22,12 +22,13 @@ BinPackParameters: false
 BreakBeforeBinaryOperators: None
 BreakBeforeBraces: Allman
 BreakBeforeTernaryOperators: true
-BreakConstructorInitializersBeforeComma: true
+BreakConstructorInitializersBeforeComma: false
+BreakConstructorInitializers: BeforeColon
 BreakAfterJavaFieldAnnotations: false
 BreakStringLiterals: true
 ColumnLimit:     100
 CommentPragmas:  '^ IWYU pragma:'
-ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerAllOnOneLineOrOnePerLine: true
 ConstructorInitializerIndentWidth: 2
 ContinuationIndentWidth: 4
 Cpp11BracedListStyle: true
@@ -37,7 +38,9 @@ ExperimentalAutoDetectBinPacking: false
 ForEachMacros:   [ foreach, Q_FOREACH, BOOST_FOREACH ]
 IncludeBlocks: Regroup
 IncludeCategories:
-  - Regex:           '(["/]PlatformDefs|"(system|system_gl))\.h"'
+  - Regex:           '<EGL/.*\.h>'
+    Priority:        6
+  - Regex:           '(["/]PlatformDefs|"(system|system_gl|system_egl))\.h"'
     Priority:        5
   - Regex:           '"platform/[^/]+/'
     Priority:        2
@@ -50,7 +53,7 @@ IncludeCategories:
   - Regex:           '.*'
     Priority:        1
 IncludeIsMainRegex: '$'
-IndentCaseLabels: false
+IndentCaseLabels: true
 IndentWidth:     2
 IndentWrappedFunctionNames: false
 JavaScriptQuotes: Leave
@@ -58,7 +61,7 @@ JavaScriptWrapImports: true
 KeepEmptyLinesAtTheStartOfBlocks: true
 MacroBlockBegin: ''
 MacroBlockEnd:   ''
-MaxEmptyLinesToKeep: 2
+MaxEmptyLinesToKeep: 1
 NamespaceIndentation: None
 ObjCBlockIndentWidth: 2
 ObjCSpaceAfterProperty: false
@@ -85,4 +88,5 @@ SpacesInParentheses: false
 SpacesInSquareBrackets: false
 Standard:        Cpp11
 TabWidth:        8
-UseTab:          Never
\ No newline at end of file
+UseTab:          Never
+...
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000..fc6b2f1
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,19 @@
+---
+name: Bug report
+about: Report a Bug / Melde einen Fehler
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Describe the bug / Beschreibe den Fehler**
+A clear and concise description of what the bug is. 
+Feel free to write in english or in german.
+
+
+**Environment / Umgebung:**
+ - Kodi version: [e.g. 18 or 19]
+ - OS: [e.g. LibreELEC, OSMC, Android TV]
+ - pvr.waipu version [e.g. 1.3.2]
+ - inputstream.adaptive version [e.g. 0.5.2]
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 0000000..826ffd7
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,61 @@
+name: Build and run tests
+on: [push, pull_request]
+env:
+  app_id: pvr.waipu
+
+jobs:
+  build:
+    runs-on: ${{ matrix.os }}
+    strategy:
+      fail-fast: false
+      matrix:
+        include:
+        - name: "Debian package test"
+          os: ubuntu-22.04
+          CC: gcc
+          CXX: g++
+          DEBIAN_BUILD: true
+        #- os: ubuntu-22.04
+          #CC: gcc
+          #CXX: g++
+        #- os: ubuntu-22.04
+          #CC: clang
+          #CXX: clang++
+        #- os: macos-10.15
+    steps:
+    - name: Install needed ubuntu depends
+      env:
+        DEBIAN_BUILD: ${{ matrix.DEBIAN_BUILD }}
+      run: |
+        if [[ $DEBIAN_BUILD == true ]]; then sudo add-apt-repository -y ppa:team-xbmc/xbmc-nightly; fi
+        if [[ $DEBIAN_BUILD == true ]]; then sudo apt-get update; fi
+        if [[ $DEBIAN_BUILD == true ]]; then sudo apt-get install fakeroot; fi
+    - name: Checkout Kodi repo
+      uses: actions/checkout@v2
+      with:
+        repository: xbmc/xbmc
+        ref: master
+        path: xbmc
+    - name: Checkout pvr.waipu repo
+      uses: actions/checkout@v2
+      with:
+        path: ${{ env.app_id }}
+    - name: Configure
+      env:
+        CC: ${{ matrix.CC }}
+        CXX: ${{ matrix.CXX }}
+        DEBIAN_BUILD: ${{ matrix.DEBIAN_BUILD }}
+      run: |
+        if [[ $DEBIAN_BUILD != true ]]; then cd ${app_id} && mkdir -p build && cd build; fi
+        if [[ $DEBIAN_BUILD != true ]]; then cmake -DADDONS_TO_BUILD=${app_id} -DADDON_SRC_PREFIX=${{ github.workspace }} -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/xbmc/addons -DPACKAGE_ZIP=1 ${{ github.workspace }}/xbmc/cmake/addons; fi
+        if [[ $DEBIAN_BUILD == true ]]; then wget https://raw.githubusercontent.com/xbmc/xbmc/master/xbmc/addons/kodi-dev-kit/tools/debian-addon-package-test.sh && chmod +x ./debian-addon-package-test.sh; fi
+        if [[ $DEBIAN_BUILD == true ]]; then sudo apt-get build-dep ${{ github.workspace }}/${app_id}; fi
+    - name: Build
+      env:
+        CC: ${{ matrix.CC }}
+        CXX: ${{ matrix.CXX }}
+        DEBIAN_BUILD: ${{ matrix.DEBIAN_BUILD }}
+      run: |
+        if [[ $DEBIAN_BUILD != true ]]; then cd ${app_id}/build; fi
+        if [[ $DEBIAN_BUILD != true ]]; then make; fi
+        if [[ $DEBIAN_BUILD == true ]]; then ./debian-addon-package-test.sh ${{ github.workspace }}/${app_id}; fi
diff --git a/.github/workflows/changelog-and-release.yml b/.github/workflows/changelog-and-release.yml
new file mode 100644
index 0000000..c952b58
--- /dev/null
+++ b/.github/workflows/changelog-and-release.yml
@@ -0,0 +1,149 @@
+name: Changelog and Release
+# Update the changelog and news(optionally), bump the version, and create a release
+#
+# The release is created on the given branch, release and tag name format will be <version>-<branch> and
+# the body of the release will be created from the changelog.txt or news element in the addon.xml.in
+#
+# options:
+# - version_type: 'minor' / 'micro' # whether to do a minor or micro version bump
+# - changelog_text: string to add to the changelog and news
+# - update_news: 'true' / 'false' # whether to update the news in the addon.xml.in
+# - add_date: 'true' / 'false' # Add date to version number in changelog and news. ie. v1.0.1 (2021-7-17)
+
+on:
+  workflow_dispatch:
+    inputs:
+      version_type:
+        description: 'Create a ''minor'' or ''micro'' release?'
+        required: true
+        default: 'minor'
+      changelog_text:
+        description: 'Input the changes you''d like to add to the changelogs. Your text should be encapsulated in "''s with line feeds represented by literal \n''s. ie. "This is the first change\nThis is the second change"'
+        required: true
+        default: ''
+      update_news:
+        description: 'Update news in addon.xml.in? [true|false]'
+        required: true
+        default: 'true'
+      add_date:
+        description: 'Add date to version number in changelog and news. ie. "v1.0.1 (2021-7-17)" [true|false]'
+        required: true
+        default: 'false'
+
+jobs:
+  default:
+    runs-on: ubuntu-latest
+    name: Changelog and Release
+
+    steps:
+
+      # Checkout the current repository into a directory (repositories name)
+      - name: Checkout Repository
+        uses: actions/checkout@v2
+        with:
+          fetch-depth: 0
+          path: ${{ github.event.repository.name }}
+
+      # Checkout the required scripts from kodi-pvr/pvr-scripts into the 'scripts' directory
+      - name: Checkout Scripts
+        uses: actions/checkout@v2
+        with:
+          fetch-depth: 0
+          repository: kodi-pvr/pvr-scripts
+          path: scripts
+
+      # Install all dependencies required by the following steps
+      # - libxml2-utils, xmlstarlet: reading news and version from addon.xml.in
+      - name: Install dependencies
+        run: |
+          sudo apt-get install libxml2-utils xmlstarlet
+
+      # Setup python version 3.9
+      - name: Set up Python
+        uses: actions/setup-python@v2
+        with:
+          python-version: '3.9'
+
+      # Run the python script to increment the version, changelog and news
+      - name: Increment version and update changelogs
+        run: |
+          arguments=
+          if [[ ${{ github.event.inputs.update_news }} == true ]] ;
+          then
+            arguments=$(echo $arguments && echo --update-news)
+          fi
+          if [[ ${{ github.event.inputs.add_date }} == true ]] ;
+          then
+            arguments=$(echo $arguments && echo --add-date)
+          fi
+          python3 ../scripts/changelog_and_release.py ${{ github.event.inputs.version_type }} ${{ github.event.inputs.changelog_text }} $arguments
+        working-directory: ${{ github.event.repository.name }}
+
+      # Create the variables required by the following steps
+      # - steps.required-variables.outputs.changes: latest entry in the changelog.txt (if exists), or addon.xml.in news element
+      # - steps.required-variables.outputs.version: version element from addon.xml.in
+      # - steps.required-variables.outputs.branch: branch of the triggering ref
+      # - steps.required-variables.outputs.today: today's date in format '%Y-%m-%d'
+      - name: Get required variables
+        id: required-variables
+        run: |
+          changes=$(cat "$(find . -name changelog.txt)" | awk -v RS= 'NR==1')
+          if [ -z "$changes" ] ;
+          then
+            changes=$(xmlstarlet fo -R "$(find . -name addon.xml.in)" | xmlstarlet sel -t -v 'string(/addon/extension/news)' | awk -v RS= 'NR==1')
+          fi
+          changes="${changes//'%'/'%25'}"
+          changes="${changes//$'\n'/'%0A'}"
+          changes="${changes//$'\r'/'%0D'}"
+          changes="${changes//$'\\n'/'%0A'}"
+          changes="${changes//$'\\r'/'%0D'}"
+          echo ::set-output name=changes::$changes
+          version=$(xmlstarlet fo -R "$(find . -name addon.xml.in)" | xmlstarlet sel -t -v 'string(/addon/@version)')
+          echo ::set-output name=version::$version
+          branch=$(echo ${GITHUB_REF#refs/heads/})
+          echo ::set-output name=branch::$branch
+          echo ::set-output name=today::$(date +'%Y-%m-%d')
+        working-directory: ${{ github.event.repository.name }}
+
+      # Create a commit of the incremented version and changelog, news changes
+      # Commit message (add_date=false): changelog and version v{steps.required-variables.outputs.version}
+      # Commit message (add_date=true): changelog and version v{steps.required-variables.outputs.version} ({steps.required-variables.outputs.today})
+      - name: Commit changes
+        run: |
+          git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
+          git config --local user.name "github-actions[bot]"
+          commit_message="changelog and version v${{ steps.required-variables.outputs.version }}"
+          if [[ ${{ github.event.inputs.add_date }} == true ]] ;
+          then
+            commit_message="$commit_message (${{ steps.required-variables.outputs.today }})"
+          fi
+          git commit -m "$commit_message" -a
+        working-directory: ${{ github.event.repository.name }}
+
+      # Push the commit(s) created above to the triggering branch
+      - name: Push changes
+        uses: ad-m/github-push-action@master
+        with:
+          branch: ${{ github.ref }}
+          directory: ${{ github.event.repository.name }}
+
+      # Sleep for 60 seconds to allow for any delays in the push
+      - name: Sleep for 60 seconds
+        run: sleep 60s
+        shell: bash
+
+      # Create a release at {steps.required-variables.outputs.branch}
+      # - tag and release name format: {steps.required-variables.outputs.version}-{steps.required-variables.outputs.branch} ie. 20.0.0-Nexus
+      # - release body: {steps.required-variables.outputs.changes}
+      - name: Create Release
+        id: create-release
+        uses: actions/create-release@v1
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+        with:
+          tag_name: ${{ steps.required-variables.outputs.version }}-${{ steps.required-variables.outputs.branch }}
+          release_name: ${{ steps.required-variables.outputs.version }}-${{ steps.required-variables.outputs.branch }}
+          body: ${{ steps.required-variables.outputs.changes }}
+          draft: false
+          prerelease: false
+          commitish: ${{ steps.required-variables.outputs.branch }}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..df673ee
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,67 @@
+name: Make Release
+# Create a release on the given branch
+# Release and tag name format will be <version>-<branch>
+# The body of the release will be created from the changelog.txt or news element in the addon.xml.in
+
+on: workflow_dispatch
+
+jobs:
+  default:
+    runs-on: ubuntu-latest
+    name: Make Release
+
+    steps:
+
+      # Checkout the current repository into a directory (repositories name)
+      - name: Checkout Repository
+        uses: actions/checkout@v2
+        with:
+          fetch-depth: 0
+          path: ${{ github.event.repository.name }}
+
+      # Install all dependencies required by the following steps
+      # - libxml2-utils, xmlstarlet: reading news and version from addon.xml.in
+      - name: Install dependencies
+        run: |
+          sudo apt-get update
+          sudo apt-get install libxml2-utils xmlstarlet
+
+      # Create the variables required by the following steps
+      # - steps.required-variables.outputs.changes: latest entry in the changelog.txt (if exists), or addon.xml.in news element
+      # - steps.required-variables.outputs.version: version element from addon.xml.in
+      # - steps.required-variables.outputs.branch: branch of the triggering ref
+      - name: Get required variables
+        id: required-variables
+        run: |
+          changes=$(cat "$(find . -name changelog.txt)" | awk -v RS= 'NR==1')
+          if [ -z "$changes" ] ;
+          then
+            changes=$(xmlstarlet fo -R "$(find . -name addon.xml.in)" | xmlstarlet sel -t -v 'string(/addon/extension/news)' | awk -v RS= 'NR==1')
+          fi
+          changes="${changes//'%'/'%25'}"
+          changes="${changes//$'\n'/'%0A'}"
+          changes="${changes//$'\r'/'%0D'}"
+          changes="${changes//$'\\n'/'%0A'}"
+          changes="${changes//$'\\r'/'%0D'}"
+          echo ::set-output name=changes::$changes
+          version=$(xmlstarlet fo -R "$(find . -name addon.xml.in)" | xmlstarlet sel -t -v 'string(/addon/@version)')
+          echo ::set-output name=version::$version
+          branch=$(echo ${GITHUB_REF#refs/heads/})
+          echo ::set-output name=branch::$branch
+        working-directory: ${{ github.event.repository.name }}
+
+      # Create a release at {steps.required-variables.outputs.branch}
+      # - tag and release name format: {steps.required-variables.outputs.version}-{steps.required-variables.outputs.branch} ie. 20.0.0-Nexus
+      # - release body: {steps.required-variables.outputs.changes}
+      - name: Create Release
+        id: create-release
+        uses: actions/create-release@v1
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+        with:
+          tag_name: ${{ steps.required-variables.outputs.version }}-${{ steps.required-variables.outputs.branch }}
+          release_name: ${{ steps.required-variables.outputs.version }}-${{ steps.required-variables.outputs.branch }}
+          body: ${{ steps.required-variables.outputs.changes }}
+          draft: false
+          prerelease: false
+          commitish: ${{ steps.required-variables.outputs.branch }}
diff --git a/.github/workflows/sync-addon-metadata-translations.yml b/.github/workflows/sync-addon-metadata-translations.yml
new file mode 100644
index 0000000..e18b419
--- /dev/null
+++ b/.github/workflows/sync-addon-metadata-translations.yml
@@ -0,0 +1,57 @@
+name: Sync addon metadata translations
+
+on:
+  push:
+    branches: [ Nexus ]
+    paths:
+      - '**addon.xml.in'
+      - '**resource.language.**strings.po'
+
+jobs:
+  default:
+    if: github.repository == 'flubshi/pvr.waipu'
+    runs-on: ubuntu-latest
+
+    strategy:
+
+      fail-fast: false
+      matrix:
+        python-version: [ 3.9 ]
+
+    steps:
+
+      - name: Checkout repository
+        uses: actions/checkout@v2
+        with:
+          path: project
+
+      - name: Checkout sync_addon_metadata_translations repository
+        uses: actions/checkout@v2
+        with:
+          repository: xbmc/sync_addon_metadata_translations
+          path: sync_addon_metadata_translations
+
+      - name: Set up Python ${{ matrix.python-version }}
+        uses: actions/setup-python@v2
+        with:
+          python-version: ${{ matrix.python-version }}
+
+      - name: Install dependencies
+        run: |
+          python -m pip install --upgrade pip
+          python -m pip install sync_addon_metadata_translations/
+
+      - name: Run sync-addon-metadata-translations
+        run: |
+          sync-addon-metadata-translations
+        working-directory: ./project
+
+      - name: Create PR for sync-addon-metadata-translations changes
+        uses: peter-evans/create-pull-request@v3.10.0
+        with:
+          commit-message: Sync of addon metadata translations
+          title: Sync of addon metadata translations
+          body: Sync of addon metadata translations triggered by ${{ github.sha }}
+          branch: amt-sync
+          delete-branch: true
+          path: ./project
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b8b8fd2
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,50 @@
+# build artifacts
+build/
+pvr.*/addon.xml
+
+# Debian build files
+debian/changelog
+debian/files
+debian/*.log
+debian/*.substvars
+debian/.debhelper/
+debian/tmp/
+debian/kodi-pvr-*/
+obj-x86_64-linux-gnu/
+
+# commonly used editors
+# vim
+*.swp
+
+# Eclipse
+*.project
+*.cproject
+.classpath
+*.sublime-*
+.settings/
+
+# KDevelop 4
+*.kdev4
+
+# gedit
+*~
+
+# CLion
+/.idea
+
+# clion
+.idea/
+
+# to prevent add after a "git format-patch VALUE" and "git add ." call
+/*.patch
+
+# Visual Studio Code
+.vscode
+
+# to prevent add if project code opened by Visual Studio over CMake file
+.vs/
+
+# General MacOS
+.DS_Store
+.AppleDouble
+.LSOverride
diff --git a/debian/changelog b/debian/changelog
index e5f4a6b..5ce7945 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+kodi-pvr-waipu (20.9.0+ds1-1) UNRELEASED; urgency=low
+
+  * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Tue, 25 Jul 2023 12:05:13 -0000
+
 kodi-pvr-waipu (20.6.0+ds1-1) unstable; urgency=medium
 
   * New upstream version 20.6.0+ds1
diff --git a/pvr.waipu/addon.xml.in b/pvr.waipu/addon.xml.in
index 11e733b..0d78cc3 100644
--- a/pvr.waipu/addon.xml.in
+++ b/pvr.waipu/addon.xml.in
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <addon
   id="pvr.waipu"
-  version="20.6.0"
+  version="20.9.0"
   name="waipu.tv PVR Client"
   provider-name="flubshi">
   <requires>@ADDON_DEPENDS@
@@ -25,23 +25,30 @@
       <screenshot>resources/screenshots/screenshot-02.jpg</screenshot>
     </assets>
     <news>
-- 20.5.1 Remove Sport1 from HLS allowlist
-- 20.5.0 Update translations; Implement EPG tag preview images
-- 20.4.2 Update translations from weblate; Update eit Categories
+- Add settings option to filter channels on import
+- Update translation files from weblate
     </news>
     <summary lang="da_DK">waipu.tv PVR-klient</summary>
     <summary lang="de_DE">waipu.tv PVR Client</summary>
     <summary lang="en_GB">waipu.tv PVR Client</summary>
     <summary lang="es_ES">Cliente PVR waipu.tv</summary>
     <summary lang="es_MX">Cliente PVR de waipu.tv</summary>
-    <summary lang="it_IT">waipu.tv client PVR</summary>
+    <summary lang="fi_FI">waipu.tv PVR-pääte</summary>
+    <summary lang="fr_FR">Client PVR waipu.tv</summary>
+    <summary lang="hr_HR">waipu.tv PVR klijent</summary>
+    <summary lang="it_IT">Client PVR di waipu.tv</summary>
     <summary lang="ko_KR">waipu.tv PVR 클라이언트</summary>
+    <summary lang="ru_RU">Клиент записи эфира waipu.tv</summary>
     <description lang="da_DK">waipu.tv PVR-klient. Bemærk: Dette er ikke et officielt waipu-plugin og er ikke relateret til Exaring AG eller waipu.tv. Det er udviklet af frivillige.</description>
     <description lang="de_DE">waipu.tv PVR Client. Hinweis: Dies ist kein offizielles Waipu-Plugin und steht nicht in Verbindung zur Exaring AG oder zu waipu.tv. Es wurde von Freiwilligen entwickelt.</description>
     <description lang="en_GB">waipu.tv PVR Client. Note: This is not an official waipu plugin and not related to Exaring AG or waipu.tv. It was developed by volunteers.</description>
-    <description lang="es_ES">Cliente PVR waipu.tv. Nota: Este no es un plugin oficial de waipu y no está relacionado con Exaring AG o waipu.tv. Esta desarrollado por voluntarios.</description>
+    <description lang="es_ES">Cliente PVR de waipu.tv. Nota: Este no es un complemento oficial de waipu y no está relacionado con Exaring AG o waipu.tv. Fue desarrollado por voluntarios.</description>
     <description lang="es_MX">Cliente PVR de waipu.tv. Nota: Este no es un complemento oficial de waipu y no está relacionado a Exaring AG o waipu.tv. Ha sido desarrollado por voluntarios.</description>
-    <description lang="it_IT">waipu.tv client PVR. Nota: questo non è un plug-in waipu ufficiale e non è correlato a Exaring AG o waipu.tv. È stato sviluppato da volontari.</description>
+    <description lang="fi_FI">waipu.tv PVR-pääte. Huomioi: Tämä ei ole virallinen waipu-lisäosa, eivätkä Exaring AG tai waipu.tv ole osallistuneet sen kehitykseen. Lisäosa on vapaaehtoisten kehittämä.</description>
+    <description lang="fr_FR">Client PVR waipu.tv. Remarque : Il ne s&apos;agit pas d&apos;un plugin waipu officiel et n&apos;est pas lié à Exaring AG ou waipu.tv. Il a été développé par des bénévoles.</description>
+    <description lang="hr_HR">waipu.tv PVR klijent. Napomena: Ovo nije služebeni waipu dodatak i nije povezan s Exaring AG ili waipu.tv. Razvijen je od strane dobrovoljaca.</description>
+    <description lang="it_IT">Client PVR di waipu.tv. Nota: questo non è un add-on ufficiale waipu e non è correlato a Exaring AG o waipu.tv. È stato sviluppato da volontari.</description>
     <description lang="ko_KR">waipu.tv PVR 클라이언트. 참고: 이것은 공식 waipu 플러그인이 아니며 Exaring AG 또는 waipu.tv와 관련이 없습니다. 자원 봉사자에 의해 개발되었습니다.</description>
+    <description lang="ru_RU">Клиент записи эфира waipu.tv. Примечание: Не является официальным дополнением Waipu и не связан с Exaring AG или waipu.tv. Разработка добровольцев.</description>
   </extension>
 </addon>
diff --git a/pvr.waipu/resources/language/resource.language.af_za/strings.po b/pvr.waipu/resources/language/resource.language.af_za/strings.po
index 3e57878..03cbab2 100644
--- a/pvr.waipu/resources/language/resource.language.af_za/strings.po
+++ b/pvr.waipu/resources/language/resource.language.af_za/strings.po
@@ -158,3 +158,27 @@ msgstr "Teken in"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.am_et/strings.po b/pvr.waipu/resources/language/resource.language.am_et/strings.po
index ceb5905..15e6ec9 100644
--- a/pvr.waipu/resources/language/resource.language.am_et/strings.po
+++ b/pvr.waipu/resources/language/resource.language.am_et/strings.po
@@ -158,3 +158,27 @@ msgstr "መግቢያ"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.ar_sa/strings.po b/pvr.waipu/resources/language/resource.language.ar_sa/strings.po
index 30b33fd..cac9aa7 100644
--- a/pvr.waipu/resources/language/resource.language.ar_sa/strings.po
+++ b/pvr.waipu/resources/language/resource.language.ar_sa/strings.po
@@ -158,3 +158,27 @@ msgstr "تسجيل الدخول"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.ast_es/strings.po b/pvr.waipu/resources/language/resource.language.ast_es/strings.po
new file mode 100644
index 0000000..a61b732
--- /dev/null
+++ b/pvr.waipu/resources/language/resource.language.ast_es/strings.po
@@ -0,0 +1,179 @@
+# Kodi Media Center language file
+# Addon Name: PVR waipu.tv Client
+# Addon id: pvr.waipu
+# Addon Provider: flubshi
+msgid ""
+msgstr ""
+"Language: ast_es\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "waipu.tv PVR Client"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "waipu.tv PVR Client. Note: This is not an official waipu plugin and not related to Exaring AG or waipu.tv. It was developed by volunteers."
+msgstr ""
+
+msgctxt "#30001"
+msgid "General"
+msgstr ""
+
+msgctxt "#30002"
+msgid "Mail"
+msgstr ""
+
+msgctxt "#30003"
+msgid "Password"
+msgstr ""
+
+msgctxt "#30004"
+msgid "Protocol"
+msgstr ""
+
+msgctxt "#30005"
+msgid "Streaming"
+msgstr ""
+
+msgctxt "#30006"
+msgid "InputStream Helper information"
+msgstr ""
+
+msgctxt "#30007"
+msgid "(Re)install Widevine CDM library..."
+msgstr ""
+
+msgctxt "#30008"
+msgid "Provider"
+msgstr ""
+
+msgctxt "#30009"
+msgid "Waipu.tv (Credentials)"
+msgstr ""
+
+msgctxt "#30010"
+msgid "O2 TV"
+msgstr ""
+
+msgctxt "#30011"
+msgid "Streaming Protocol"
+msgstr ""
+
+msgctxt "#30012"
+msgid "Video Resolution"
+msgstr ""
+
+msgctxt "#30013"
+msgid "Audio Codecs"
+msgstr ""
+
+msgctxt "#30014"
+msgid "SD-PALp25: h264; 720x540; 25fps"
+msgstr ""
+
+msgctxt "#30015"
+msgid "SD-PALp50: h264; 720x540; 50fps"
+msgstr ""
+
+msgctxt "#30016"
+msgid "HD-720p25: h264; 1280x720; 25fps"
+msgstr ""
+
+msgctxt "#30017"
+msgid "HD-720p50: h264; 1280x720; 50fps"
+msgstr ""
+
+msgctxt "#30018"
+msgid "HD-1080p25: h264; 1920x1080; 25fps"
+msgstr ""
+
+msgctxt "#30019"
+msgid "HD-1080p50: h264; 1920x1080; 50fps"
+msgstr ""
+
+msgctxt "#30020"
+msgid "HEVC-1080p50: hevc; 1920x1080; 50fps"
+msgstr ""
+
+msgctxt "#30021"
+msgid "HEVC-2160p50: hevc; 3840x2160; 50fps"
+msgstr ""
+
+msgctxt "#30025"
+msgid "AAC-LC: 128kBit, 48kHz"
+msgstr ""
+
+msgctxt "#30030"
+msgid "Error: Login not possible. Check credentials!"
+msgstr ""
+
+msgctxt "#30031"
+msgid "No network connection"
+msgstr ""
+
+msgctxt "#30032"
+msgid "Invalid login credentials"
+msgstr ""
+
+msgctxt "#30033"
+msgid "Required username and password not available"
+msgstr ""
+
+msgctxt "#30034"
+msgid "Refresh Token"
+msgstr ""
+
+msgctxt "#30035"
+msgid "Misc"
+msgstr ""
+
+msgctxt "#30036"
+msgid "Device ID"
+msgstr ""
+
+msgctxt "#30037"
+msgid "Reset Login"
+msgstr ""
+
+msgctxt "#30038"
+msgid "Waipu.tv (Device Login)"
+msgstr ""
+
+msgctxt "#30039"
+msgid "Go to:"
+msgstr ""
+
+msgctxt "#30040"
+msgid "Login"
+msgstr ""
+
+msgctxt "#30041"
+msgid "Use Code:"
+msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.az_az/strings.po b/pvr.waipu/resources/language/resource.language.az_az/strings.po
index e6056db..fbf6d26 100644
--- a/pvr.waipu/resources/language/resource.language.az_az/strings.po
+++ b/pvr.waipu/resources/language/resource.language.az_az/strings.po
@@ -158,3 +158,27 @@ msgstr ""
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.be_by/strings.po b/pvr.waipu/resources/language/resource.language.be_by/strings.po
index e94f0d3..4b8397e 100644
--- a/pvr.waipu/resources/language/resource.language.be_by/strings.po
+++ b/pvr.waipu/resources/language/resource.language.be_by/strings.po
@@ -158,3 +158,27 @@ msgstr "Login"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.bg_bg/strings.po b/pvr.waipu/resources/language/resource.language.bg_bg/strings.po
index 29c2edd..f5fac4d 100644
--- a/pvr.waipu/resources/language/resource.language.bg_bg/strings.po
+++ b/pvr.waipu/resources/language/resource.language.bg_bg/strings.po
@@ -158,3 +158,27 @@ msgstr "Влизане"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.bs_ba/strings.po b/pvr.waipu/resources/language/resource.language.bs_ba/strings.po
index 33bbc31..c836e14 100644
--- a/pvr.waipu/resources/language/resource.language.bs_ba/strings.po
+++ b/pvr.waipu/resources/language/resource.language.bs_ba/strings.po
@@ -158,3 +158,27 @@ msgstr ""
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.ca_es/strings.po b/pvr.waipu/resources/language/resource.language.ca_es/strings.po
index fc1b603..160bb6b 100644
--- a/pvr.waipu/resources/language/resource.language.ca_es/strings.po
+++ b/pvr.waipu/resources/language/resource.language.ca_es/strings.po
@@ -158,3 +158,27 @@ msgstr "Autenticació"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.cs_cz/strings.po b/pvr.waipu/resources/language/resource.language.cs_cz/strings.po
index f01b7f6..46601b3 100644
--- a/pvr.waipu/resources/language/resource.language.cs_cz/strings.po
+++ b/pvr.waipu/resources/language/resource.language.cs_cz/strings.po
@@ -158,3 +158,27 @@ msgstr "Přihlášení"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.cy_gb/strings.po b/pvr.waipu/resources/language/resource.language.cy_gb/strings.po
index 8a48db7..43d220d 100644
--- a/pvr.waipu/resources/language/resource.language.cy_gb/strings.po
+++ b/pvr.waipu/resources/language/resource.language.cy_gb/strings.po
@@ -158,3 +158,27 @@ msgstr "Mewngofnodi"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.da_dk/strings.po b/pvr.waipu/resources/language/resource.language.da_dk/strings.po
index 133f570..fef0371 100644
--- a/pvr.waipu/resources/language/resource.language.da_dk/strings.po
+++ b/pvr.waipu/resources/language/resource.language.da_dk/strings.po
@@ -5,7 +5,7 @@
 msgid ""
 msgstr ""
 "Report-Msgid-Bugs-To: translations@kodi.tv\n"
-"PO-Revision-Date: 2021-10-31 00:30+0000\n"
+"PO-Revision-Date: 2023-05-09 23:16+0000\n"
 "Last-Translator: Christian Gade <gade@kodi.tv>\n"
 "Language-Team: Danish <https://kodi.weblate.cloud/projects/kodi-add-ons-pvr-clients/pvr-waipu/da_dk/>\n"
 "Language: da_dk\n"
@@ -13,7 +13,7 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.8\n"
+"X-Generator: Weblate 4.15.2\n"
 
 msgctxt "Addon Summary"
 msgid "waipu.tv PVR Client"
@@ -159,6 +159,30 @@ msgctxt "#30041"
 msgid "Use Code:"
 msgstr "Brug kode:"
 
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr "Forhåndsvisning af billeder for EPG"
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
+
 #~ msgctxt "#30009"
 #~ msgid "Waipu.tv"
 #~ msgstr "Waipu.tv"
diff --git a/pvr.waipu/resources/language/resource.language.de_de/strings.po b/pvr.waipu/resources/language/resource.language.de_de/strings.po
index c610d4c..170bcde 100644
--- a/pvr.waipu/resources/language/resource.language.de_de/strings.po
+++ b/pvr.waipu/resources/language/resource.language.de_de/strings.po
@@ -5,7 +5,7 @@
 msgid ""
 msgstr ""
 "Report-Msgid-Bugs-To: translations@kodi.tv\n"
-"PO-Revision-Date: 2022-03-19 06:52+0000\n"
+"PO-Revision-Date: 2023-02-01 15:54+0000\n"
 "Last-Translator: Kai Sommerfeld <kai.sommerfeld@gmx.com>\n"
 "Language-Team: German <https://kodi.weblate.cloud/projects/kodi-add-ons-pvr-clients/pvr-waipu/de_de/>\n"
 "Language: de_de\n"
@@ -13,7 +13,7 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.11.2\n"
+"X-Generator: Weblate 4.15.2\n"
 
 msgctxt "Addon Summary"
 msgid "waipu.tv PVR Client"
@@ -45,11 +45,11 @@ msgstr "Streaming"
 
 msgctxt "#30006"
 msgid "InputStream Helper information"
-msgstr "InputStream Helper-Informationen"
+msgstr "InputStream-Helper-Informationen"
 
 msgctxt "#30007"
 msgid "(Re)install Widevine CDM library..."
-msgstr "Widevine CDM Bibliothek (erneut) installieren..."
+msgstr "Widevine CDM-Bibliothek (erneut) installieren ..."
 
 msgctxt "#30008"
 msgid "Provider"
@@ -65,11 +65,11 @@ msgstr "O2 TV"
 
 msgctxt "#30011"
 msgid "Streaming Protocol"
-msgstr "Streaming Protokoll"
+msgstr "Streamingprotokoll"
 
 msgctxt "#30012"
 msgid "Video Resolution"
-msgstr "Video Auflösung"
+msgstr "Videoauflösung"
 
 msgctxt "#30013"
 msgid "Audio Codecs"
@@ -113,7 +113,7 @@ msgstr "AAC-LC: 128kBit, 48kHz"
 
 msgctxt "#30030"
 msgid "Error: Login not possible. Check credentials!"
-msgstr "Fehler: Login nicht möglich. Ungültiger Account!"
+msgstr "Fehler: Anmeldung nicht möglich. Zugangsdaten überprüfen!"
 
 msgctxt "#30031"
 msgid "No network connection"
@@ -141,7 +141,7 @@ msgstr "Device ID"
 
 msgctxt "#30037"
 msgid "Reset Login"
-msgstr "Login zurücksetzen"
+msgstr "Anmeldedaten zurücksetzen"
 
 msgctxt "#30038"
 msgid "Waipu.tv (Device Login)"
@@ -158,3 +158,27 @@ msgstr "Anmeldung"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr "Code:"
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.el_gr/strings.po b/pvr.waipu/resources/language/resource.language.el_gr/strings.po
index 64ed3be..9309e5f 100644
--- a/pvr.waipu/resources/language/resource.language.el_gr/strings.po
+++ b/pvr.waipu/resources/language/resource.language.el_gr/strings.po
@@ -158,3 +158,27 @@ msgstr "Σύνδεση"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.en_au/strings.po b/pvr.waipu/resources/language/resource.language.en_au/strings.po
index de6afd8..139fd85 100644
--- a/pvr.waipu/resources/language/resource.language.en_au/strings.po
+++ b/pvr.waipu/resources/language/resource.language.en_au/strings.po
@@ -158,3 +158,27 @@ msgstr "Login"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.en_gb/strings.po b/pvr.waipu/resources/language/resource.language.en_gb/strings.po
index 6fc6229..3993c6a 100644
--- a/pvr.waipu/resources/language/resource.language.en_gb/strings.po
+++ b/pvr.waipu/resources/language/resource.language.en_gb/strings.po
@@ -153,3 +153,27 @@ msgstr ""
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.en_nz/strings.po b/pvr.waipu/resources/language/resource.language.en_nz/strings.po
index c454833..7e596e0 100644
--- a/pvr.waipu/resources/language/resource.language.en_nz/strings.po
+++ b/pvr.waipu/resources/language/resource.language.en_nz/strings.po
@@ -158,3 +158,27 @@ msgstr "Login"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.en_us/strings.po b/pvr.waipu/resources/language/resource.language.en_us/strings.po
index 94d1fa1..d9e5df6 100644
--- a/pvr.waipu/resources/language/resource.language.en_us/strings.po
+++ b/pvr.waipu/resources/language/resource.language.en_us/strings.po
@@ -158,3 +158,27 @@ msgstr "Login"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.eo/strings.po b/pvr.waipu/resources/language/resource.language.eo/strings.po
index 77d514d..69ed5f3 100644
--- a/pvr.waipu/resources/language/resource.language.eo/strings.po
+++ b/pvr.waipu/resources/language/resource.language.eo/strings.po
@@ -158,3 +158,27 @@ msgstr ""
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.es_ar/strings.po b/pvr.waipu/resources/language/resource.language.es_ar/strings.po
index 4869247..7af2e07 100644
--- a/pvr.waipu/resources/language/resource.language.es_ar/strings.po
+++ b/pvr.waipu/resources/language/resource.language.es_ar/strings.po
@@ -158,3 +158,27 @@ msgstr "Ingresar"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.es_es/strings.po b/pvr.waipu/resources/language/resource.language.es_es/strings.po
index f4d876f..8e9d004 100644
--- a/pvr.waipu/resources/language/resource.language.es_es/strings.po
+++ b/pvr.waipu/resources/language/resource.language.es_es/strings.po
@@ -5,15 +5,15 @@
 msgid ""
 msgstr ""
 "Report-Msgid-Bugs-To: translations@kodi.tv\n"
-"PO-Revision-Date: 2022-03-06 18:03+0000\n"
-"Last-Translator: Alfonso Cachero <alfonso.cachero@gmail.com>\n"
+"PO-Revision-Date: 2023-05-09 23:16+0000\n"
+"Last-Translator: José Antonio Alvarado <jalvarado0.eses@gmail.com>\n"
 "Language-Team: Spanish (Spain) <https://kodi.weblate.cloud/projects/kodi-add-ons-pvr-clients/pvr-waipu/es_es/>\n"
 "Language: es_es\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.11.2\n"
+"X-Generator: Weblate 4.15.2\n"
 
 msgctxt "Addon Summary"
 msgid "waipu.tv PVR Client"
@@ -21,7 +21,7 @@ msgstr "Cliente PVR waipu.tv"
 
 msgctxt "Addon Description"
 msgid "waipu.tv PVR Client. Note: This is not an official waipu plugin and not related to Exaring AG or waipu.tv. It was developed by volunteers."
-msgstr "Cliente PVR waipu.tv. Nota: Este no es un plugin oficial de waipu y no está relacionado con Exaring AG o waipu.tv. Esta desarrollado por voluntarios."
+msgstr "Cliente PVR de waipu.tv. Nota: Este no es un complemento oficial de waipu y no está relacionado con Exaring AG o waipu.tv. Fue desarrollado por voluntarios."
 
 msgctxt "#30001"
 msgid "General"
@@ -41,7 +41,7 @@ msgstr "Protocolo"
 
 msgctxt "#30005"
 msgid "Streaming"
-msgstr "Retransmisiones"
+msgstr "Streaming"
 
 msgctxt "#30006"
 msgid "InputStream Helper information"
@@ -65,7 +65,7 @@ msgstr "O2 TV"
 
 msgctxt "#30011"
 msgid "Streaming Protocol"
-msgstr "Protocolo de retransmisión"
+msgstr "Protocolo de transmisión"
 
 msgctxt "#30012"
 msgid "Video Resolution"
@@ -113,7 +113,7 @@ msgstr "AAC-LC: 128kBit, 48kHz"
 
 msgctxt "#30030"
 msgid "Error: Login not possible. Check credentials!"
-msgstr "Error: No es posible iniciar sesión. Compruebe las credenciales."
+msgstr "Error: No es posible iniciar sesión. ¡Comprueba tus credenciales!"
 
 msgctxt "#30031"
 msgid "No network connection"
@@ -137,7 +137,7 @@ msgstr "Otros"
 
 msgctxt "#30036"
 msgid "Device ID"
-msgstr "ID Dispositivo"
+msgstr "Identificador de dispositivo"
 
 msgctxt "#30037"
 msgid "Reset Login"
@@ -159,6 +159,30 @@ msgctxt "#30041"
 msgid "Use Code:"
 msgstr "Usar Código:"
 
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr "Imágenes de vista previa de EPG"
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
+
 #~ msgctxt "#30009"
 #~ msgid "Waipu.tv"
 #~ msgstr "Waipu.tv"
diff --git a/pvr.waipu/resources/language/resource.language.es_mx/strings.po b/pvr.waipu/resources/language/resource.language.es_mx/strings.po
index 6961cdf..42276d0 100644
--- a/pvr.waipu/resources/language/resource.language.es_mx/strings.po
+++ b/pvr.waipu/resources/language/resource.language.es_mx/strings.po
@@ -158,3 +158,27 @@ msgstr "iniciar sesión"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.et_ee/strings.po b/pvr.waipu/resources/language/resource.language.et_ee/strings.po
index 2e0575b..ca68193 100644
--- a/pvr.waipu/resources/language/resource.language.et_ee/strings.po
+++ b/pvr.waipu/resources/language/resource.language.et_ee/strings.po
@@ -158,3 +158,27 @@ msgstr "Logi sisse"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.eu_es/strings.po b/pvr.waipu/resources/language/resource.language.eu_es/strings.po
index eee1abe..0c1654b 100644
--- a/pvr.waipu/resources/language/resource.language.eu_es/strings.po
+++ b/pvr.waipu/resources/language/resource.language.eu_es/strings.po
@@ -158,3 +158,27 @@ msgstr "Hasi saioa"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.fa_af/strings.po b/pvr.waipu/resources/language/resource.language.fa_af/strings.po
index f01c12c..aeabce0 100644
--- a/pvr.waipu/resources/language/resource.language.fa_af/strings.po
+++ b/pvr.waipu/resources/language/resource.language.fa_af/strings.po
@@ -158,3 +158,27 @@ msgstr ""
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.fa_ir/strings.po b/pvr.waipu/resources/language/resource.language.fa_ir/strings.po
index c05ff99..0c68cb0 100644
--- a/pvr.waipu/resources/language/resource.language.fa_ir/strings.po
+++ b/pvr.waipu/resources/language/resource.language.fa_ir/strings.po
@@ -158,3 +158,27 @@ msgstr "ورود"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.fi_fi/strings.po b/pvr.waipu/resources/language/resource.language.fi_fi/strings.po
index 2b00504..81d8bdb 100644
--- a/pvr.waipu/resources/language/resource.language.fi_fi/strings.po
+++ b/pvr.waipu/resources/language/resource.language.fi_fi/strings.po
@@ -5,7 +5,7 @@
 msgid ""
 msgstr ""
 "Report-Msgid-Bugs-To: translations@kodi.tv\n"
-"PO-Revision-Date: 2022-03-19 06:52+0000\n"
+"PO-Revision-Date: 2023-03-27 07:16+0000\n"
 "Last-Translator: Oskari Lavinto <olavinto@protonmail.com>\n"
 "Language-Team: Finnish <https://kodi.weblate.cloud/projects/kodi-add-ons-pvr-clients/pvr-waipu/fi_fi/>\n"
 "Language: fi_fi\n"
@@ -13,15 +13,15 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.11.2\n"
+"X-Generator: Weblate 4.15.2\n"
 
 msgctxt "Addon Summary"
 msgid "waipu.tv PVR Client"
-msgstr ""
+msgstr "waipu.tv PVR-pääte"
 
 msgctxt "Addon Description"
 msgid "waipu.tv PVR Client. Note: This is not an official waipu plugin and not related to Exaring AG or waipu.tv. It was developed by volunteers."
-msgstr ""
+msgstr "waipu.tv PVR-pääte. Huomioi: Tämä ei ole virallinen waipu-lisäosa, eivätkä Exaring AG tai waipu.tv ole osallistuneet sen kehitykseen. Lisäosa on vapaaehtoisten kehittämä."
 
 msgctxt "#30001"
 msgid "General"
@@ -45,7 +45,7 @@ msgstr "Suoratoisto"
 
 msgctxt "#30006"
 msgid "InputStream Helper information"
-msgstr ""
+msgstr "InputStream Helper -tiedot"
 
 msgctxt "#30007"
 msgid "(Re)install Widevine CDM library..."
@@ -137,7 +137,7 @@ msgstr "Muut"
 
 msgctxt "#30036"
 msgid "Device ID"
-msgstr "Laitetunnus"
+msgstr "Laitetunniste"
 
 msgctxt "#30037"
 msgid "Reset Login"
@@ -158,3 +158,27 @@ msgstr "Kirjautuminen"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.fo_fo/strings.po b/pvr.waipu/resources/language/resource.language.fo_fo/strings.po
index 9e92811..be105cf 100644
--- a/pvr.waipu/resources/language/resource.language.fo_fo/strings.po
+++ b/pvr.waipu/resources/language/resource.language.fo_fo/strings.po
@@ -158,3 +158,27 @@ msgstr ""
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.fr_ca/strings.po b/pvr.waipu/resources/language/resource.language.fr_ca/strings.po
index 7d2d2f5..477fa0e 100644
--- a/pvr.waipu/resources/language/resource.language.fr_ca/strings.po
+++ b/pvr.waipu/resources/language/resource.language.fr_ca/strings.po
@@ -158,3 +158,27 @@ msgstr "Connexion"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.fr_fr/strings.po b/pvr.waipu/resources/language/resource.language.fr_fr/strings.po
index 5727cbd..de9baa5 100644
--- a/pvr.waipu/resources/language/resource.language.fr_fr/strings.po
+++ b/pvr.waipu/resources/language/resource.language.fr_fr/strings.po
@@ -5,23 +5,23 @@
 msgid ""
 msgstr ""
 "Report-Msgid-Bugs-To: translations@kodi.tv\n"
-"PO-Revision-Date: 2022-03-27 01:17+0000\n"
-"Last-Translator: Christian Gade <gade@kodi.tv>\n"
+"PO-Revision-Date: 2023-01-04 17:15+0000\n"
+"Last-Translator: skypichat <skypichat@hotmail.fr>\n"
 "Language-Team: French (France) <https://kodi.weblate.cloud/projects/kodi-add-ons-pvr-clients/pvr-waipu/fr_fr/>\n"
 "Language: fr_fr\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=n > 1;\n"
-"X-Generator: Weblate 4.11.2\n"
+"X-Generator: Weblate 4.15\n"
 
 msgctxt "Addon Summary"
 msgid "waipu.tv PVR Client"
-msgstr ""
+msgstr "Client PVR waipu.tv"
 
 msgctxt "Addon Description"
 msgid "waipu.tv PVR Client. Note: This is not an official waipu plugin and not related to Exaring AG or waipu.tv. It was developed by volunteers."
-msgstr ""
+msgstr "Client PVR waipu.tv. Remarque : Il ne s'agit pas d'un plugin waipu officiel et n'est pas lié à Exaring AG ou waipu.tv. Il a été développé par des bénévoles."
 
 msgctxt "#30001"
 msgid "General"
@@ -29,7 +29,7 @@ msgstr "Général"
 
 msgctxt "#30002"
 msgid "Mail"
-msgstr ""
+msgstr "Courrier"
 
 msgctxt "#30003"
 msgid "Password"
@@ -37,99 +37,99 @@ msgstr "Mot de passe"
 
 msgctxt "#30004"
 msgid "Protocol"
-msgstr ""
+msgstr "Protocole"
 
 msgctxt "#30005"
 msgid "Streaming"
-msgstr "Diffusion par flux"
+msgstr "Diffusion"
 
 msgctxt "#30006"
 msgid "InputStream Helper information"
-msgstr ""
+msgstr "Informations sur InputStream Helper"
 
 msgctxt "#30007"
 msgid "(Re)install Widevine CDM library..."
-msgstr ""
+msgstr "(Ré)installer la bibliothèque Widevine CDM..."
 
 msgctxt "#30008"
 msgid "Provider"
-msgstr ""
+msgstr "Fournisseur"
 
 msgctxt "#30009"
 msgid "Waipu.tv (Credentials)"
-msgstr ""
+msgstr "Waipu.tv (Identifiants)"
 
 msgctxt "#30010"
 msgid "O2 TV"
-msgstr ""
+msgstr "O2 TV"
 
 msgctxt "#30011"
 msgid "Streaming Protocol"
-msgstr ""
+msgstr "Protocole de diffusion"
 
 msgctxt "#30012"
 msgid "Video Resolution"
-msgstr ""
+msgstr "Résolution vidéo"
 
 msgctxt "#30013"
 msgid "Audio Codecs"
-msgstr ""
+msgstr "Codecs audio"
 
 msgctxt "#30014"
 msgid "SD-PALp25: h264; 720x540; 25fps"
-msgstr ""
+msgstr "SD-PALp25 : h264 ; 720x540 ; 25fps"
 
 msgctxt "#30015"
 msgid "SD-PALp50: h264; 720x540; 50fps"
-msgstr ""
+msgstr "SD-PALp50 : h264 ; 720x540 ; 50fps"
 
 msgctxt "#30016"
 msgid "HD-720p25: h264; 1280x720; 25fps"
-msgstr ""
+msgstr "HD-720p25 : h264 ; 1280x720 ; 25fps"
 
 msgctxt "#30017"
 msgid "HD-720p50: h264; 1280x720; 50fps"
-msgstr ""
+msgstr "HD-720p50 : h264 ; 1280x720 ; 50fps"
 
 msgctxt "#30018"
 msgid "HD-1080p25: h264; 1920x1080; 25fps"
-msgstr ""
+msgstr "HD-1080p25 : h264 ; 1920x1080 ; 25fps"
 
 msgctxt "#30019"
 msgid "HD-1080p50: h264; 1920x1080; 50fps"
-msgstr ""
+msgstr "HD-1080p50 : h264 ; 1920x1080 ; 50fps"
 
 msgctxt "#30020"
 msgid "HEVC-1080p50: hevc; 1920x1080; 50fps"
-msgstr ""
+msgstr "HEVC-1080p50 : hevc ; 1920x1080 ; 50fps"
 
 msgctxt "#30021"
 msgid "HEVC-2160p50: hevc; 3840x2160; 50fps"
-msgstr ""
+msgstr "HEVC-2160p50 : hevc ; 3840x2160 ; 50fps"
 
 msgctxt "#30025"
 msgid "AAC-LC: 128kBit, 48kHz"
-msgstr ""
+msgstr "AAC-LC : 128kBit, 48kHz"
 
 msgctxt "#30030"
 msgid "Error: Login not possible. Check credentials!"
-msgstr ""
+msgstr "Erreur : Connexion impossible. Vérifier les informations d'identification !"
 
 msgctxt "#30031"
 msgid "No network connection"
-msgstr ""
+msgstr "Pas de connexion réseau"
 
 msgctxt "#30032"
 msgid "Invalid login credentials"
-msgstr ""
+msgstr "Authentification invalide"
 
 msgctxt "#30033"
 msgid "Required username and password not available"
-msgstr ""
+msgstr "Nom d'utilisateur et mot de passe requis non disponibles"
 
 msgctxt "#30034"
 msgid "Refresh Token"
-msgstr ""
+msgstr "Actualiser Token"
 
 msgctxt "#30035"
 msgid "Misc"
@@ -137,19 +137,19 @@ msgstr "Divers"
 
 msgctxt "#30036"
 msgid "Device ID"
-msgstr "ID de dispositif"
+msgstr "ID du dispositif"
 
 msgctxt "#30037"
 msgid "Reset Login"
-msgstr ""
+msgstr "Réinitialiser la connexion"
 
 msgctxt "#30038"
 msgid "Waipu.tv (Device Login)"
-msgstr ""
+msgstr "Waipu.tv (Connexion à l'appareil)"
 
 msgctxt "#30039"
 msgid "Go to:"
-msgstr ""
+msgstr "Aller à :"
 
 msgctxt "#30040"
 msgid "Login"
@@ -157,4 +157,28 @@ msgstr "Identification"
 
 msgctxt "#30041"
 msgid "Use Code:"
+msgstr "Utiliser le code :"
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
 msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.gl_es/strings.po b/pvr.waipu/resources/language/resource.language.gl_es/strings.po
index 9d09ce8..d55c9da 100644
--- a/pvr.waipu/resources/language/resource.language.gl_es/strings.po
+++ b/pvr.waipu/resources/language/resource.language.gl_es/strings.po
@@ -158,3 +158,27 @@ msgstr "Usuario"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.he_il/strings.po b/pvr.waipu/resources/language/resource.language.he_il/strings.po
index 95016f1..e37458e 100644
--- a/pvr.waipu/resources/language/resource.language.he_il/strings.po
+++ b/pvr.waipu/resources/language/resource.language.he_il/strings.po
@@ -158,3 +158,27 @@ msgstr "שם משתמש"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.hi_in/strings.po b/pvr.waipu/resources/language/resource.language.hi_in/strings.po
index 73a3201..bb17e20 100644
--- a/pvr.waipu/resources/language/resource.language.hi_in/strings.po
+++ b/pvr.waipu/resources/language/resource.language.hi_in/strings.po
@@ -158,3 +158,27 @@ msgstr ""
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.hr_hr/strings.po b/pvr.waipu/resources/language/resource.language.hr_hr/strings.po
index a6ba9f6..8b75d40 100644
--- a/pvr.waipu/resources/language/resource.language.hr_hr/strings.po
+++ b/pvr.waipu/resources/language/resource.language.hr_hr/strings.po
@@ -5,23 +5,23 @@
 msgid ""
 msgstr ""
 "Report-Msgid-Bugs-To: translations@kodi.tv\n"
-"PO-Revision-Date: 2022-03-27 01:17+0000\n"
-"Last-Translator: Christian Gade <gade@kodi.tv>\n"
+"PO-Revision-Date: 2023-01-04 17:15+0000\n"
+"Last-Translator: gogogogi <trebelnik2@gmail.com>\n"
 "Language-Team: Croatian <https://kodi.weblate.cloud/projects/kodi-add-ons-pvr-clients/pvr-waipu/hr_hr/>\n"
 "Language: hr_hr\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.11.2\n"
+"X-Generator: Weblate 4.15\n"
 
 msgctxt "Addon Summary"
 msgid "waipu.tv PVR Client"
-msgstr ""
+msgstr "waipu.tv PVR klijent"
 
 msgctxt "Addon Description"
 msgid "waipu.tv PVR Client. Note: This is not an official waipu plugin and not related to Exaring AG or waipu.tv. It was developed by volunteers."
-msgstr ""
+msgstr "waipu.tv PVR klijent. Napomena: Ovo nije služebeni waipu dodatak i nije povezan s Exaring AG ili waipu.tv. Razvijen je od strane dobrovoljaca."
 
 msgctxt "#30001"
 msgid "General"
@@ -29,7 +29,7 @@ msgstr "Općenito"
 
 msgctxt "#30002"
 msgid "Mail"
-msgstr ""
+msgstr "E-pošta"
 
 msgctxt "#30003"
 msgid "Password"
@@ -45,11 +45,11 @@ msgstr "Strujanje"
 
 msgctxt "#30006"
 msgid "InputStream Helper information"
-msgstr ""
+msgstr "InputStream Helper informacije"
 
 msgctxt "#30007"
 msgid "(Re)install Widevine CDM library..."
-msgstr ""
+msgstr "Ponovno instaliraj Widevine CDM biblioteku..."
 
 msgctxt "#30008"
 msgid "Provider"
@@ -57,15 +57,15 @@ msgstr "Pružatelj usluge"
 
 msgctxt "#30009"
 msgid "Waipu.tv (Credentials)"
-msgstr ""
+msgstr "Waipu.tv (Vjerodajnice)"
 
 msgctxt "#30010"
 msgid "O2 TV"
-msgstr ""
+msgstr "O2 TV"
 
 msgctxt "#30011"
 msgid "Streaming Protocol"
-msgstr ""
+msgstr "Protokol strujanja"
 
 msgctxt "#30012"
 msgid "Video Resolution"
@@ -73,63 +73,63 @@ msgstr "Video razlučivost"
 
 msgctxt "#30013"
 msgid "Audio Codecs"
-msgstr ""
+msgstr "Zvučni kôdek"
 
 msgctxt "#30014"
 msgid "SD-PALp25: h264; 720x540; 25fps"
-msgstr ""
+msgstr "SD-PALp25: h264; 720x540; 25sl/sek"
 
 msgctxt "#30015"
 msgid "SD-PALp50: h264; 720x540; 50fps"
-msgstr ""
+msgstr "SD-PALp50: h264; 720x540; 50sl/sek"
 
 msgctxt "#30016"
 msgid "HD-720p25: h264; 1280x720; 25fps"
-msgstr ""
+msgstr "HD-720p25: h264; 1280x720; sl/sek"
 
 msgctxt "#30017"
 msgid "HD-720p50: h264; 1280x720; 50fps"
-msgstr ""
+msgstr "HD-720p50: h264; 1280x720; 50sl/sek"
 
 msgctxt "#30018"
 msgid "HD-1080p25: h264; 1920x1080; 25fps"
-msgstr ""
+msgstr "HD-1080p25: h264; 1920x1080; 25sl/sek"
 
 msgctxt "#30019"
 msgid "HD-1080p50: h264; 1920x1080; 50fps"
-msgstr ""
+msgstr "HD-1080p50: h264; 1920x1080; 50sl/sek"
 
 msgctxt "#30020"
 msgid "HEVC-1080p50: hevc; 1920x1080; 50fps"
-msgstr ""
+msgstr "HEVC-1080p50: hevc; 1920x1080; 50sl/sek"
 
 msgctxt "#30021"
 msgid "HEVC-2160p50: hevc; 3840x2160; 50fps"
-msgstr ""
+msgstr "HEVC-2160p50: hevc; 3840x2160; 50sl/sek"
 
 msgctxt "#30025"
 msgid "AAC-LC: 128kBit, 48kHz"
-msgstr ""
+msgstr "AAC-LC: 128kBit, 48kHz"
 
 msgctxt "#30030"
 msgid "Error: Login not possible. Check credentials!"
-msgstr ""
+msgstr "Greška: Prijava nije moguća. Provjerite vjerodajnice!"
 
 msgctxt "#30031"
 msgid "No network connection"
-msgstr "Nema mrežne veze"
+msgstr "Nema mrežnog povezivanja"
 
 msgctxt "#30032"
 msgid "Invalid login credentials"
-msgstr ""
+msgstr "Nevaljane vjerodajnice prijave"
 
 msgctxt "#30033"
 msgid "Required username and password not available"
-msgstr ""
+msgstr "Potrebno korisničko ime i lozinka nisu dostupni"
 
 msgctxt "#30034"
 msgid "Refresh Token"
-msgstr ""
+msgstr "Osvježi token"
 
 msgctxt "#30035"
 msgid "Misc"
@@ -141,15 +141,15 @@ msgstr "ID uređaja"
 
 msgctxt "#30037"
 msgid "Reset Login"
-msgstr ""
+msgstr "Poništi prijavu"
 
 msgctxt "#30038"
 msgid "Waipu.tv (Device Login)"
-msgstr ""
+msgstr "Waipu.tv (prijava na uređaj)"
 
 msgctxt "#30039"
 msgid "Go to:"
-msgstr ""
+msgstr "Idi na:"
 
 msgctxt "#30040"
 msgid "Login"
@@ -157,4 +157,28 @@ msgstr "Prijava"
 
 msgctxt "#30041"
 msgid "Use Code:"
+msgstr "Koristi kôd:"
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
 msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.hu_hu/strings.po b/pvr.waipu/resources/language/resource.language.hu_hu/strings.po
index b191b08..ea9105b 100644
--- a/pvr.waipu/resources/language/resource.language.hu_hu/strings.po
+++ b/pvr.waipu/resources/language/resource.language.hu_hu/strings.po
@@ -158,3 +158,27 @@ msgstr "Bejelentkezés"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.hy_am/strings.po b/pvr.waipu/resources/language/resource.language.hy_am/strings.po
index 31295d7..caf3006 100644
--- a/pvr.waipu/resources/language/resource.language.hy_am/strings.po
+++ b/pvr.waipu/resources/language/resource.language.hy_am/strings.po
@@ -158,3 +158,27 @@ msgstr "Մուտք"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.id_id/strings.po b/pvr.waipu/resources/language/resource.language.id_id/strings.po
index 810f2b0..d77dfcd 100644
--- a/pvr.waipu/resources/language/resource.language.id_id/strings.po
+++ b/pvr.waipu/resources/language/resource.language.id_id/strings.po
@@ -158,3 +158,27 @@ msgstr "Masuk"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.is_is/strings.po b/pvr.waipu/resources/language/resource.language.is_is/strings.po
index ea023cb..6b03940 100644
--- a/pvr.waipu/resources/language/resource.language.is_is/strings.po
+++ b/pvr.waipu/resources/language/resource.language.is_is/strings.po
@@ -158,3 +158,27 @@ msgstr "Innskrá"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.it_it/strings.po b/pvr.waipu/resources/language/resource.language.it_it/strings.po
index ccb1fd3..4acd424 100644
--- a/pvr.waipu/resources/language/resource.language.it_it/strings.po
+++ b/pvr.waipu/resources/language/resource.language.it_it/strings.po
@@ -5,7 +5,7 @@
 msgid ""
 msgstr ""
 "Report-Msgid-Bugs-To: translations@kodi.tv\n"
-"PO-Revision-Date: 2022-08-18 05:14+0000\n"
+"PO-Revision-Date: 2023-05-09 23:16+0000\n"
 "Last-Translator: Massimo Pissarello <mapi68@gmail.com>\n"
 "Language-Team: Italian <https://kodi.weblate.cloud/projects/kodi-add-ons-pvr-clients/pvr-waipu/it_it/>\n"
 "Language: it_it\n"
@@ -13,15 +13,15 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.13\n"
+"X-Generator: Weblate 4.15.2\n"
 
 msgctxt "Addon Summary"
 msgid "waipu.tv PVR Client"
-msgstr "waipu.tv client PVR"
+msgstr "Client PVR di waipu.tv"
 
 msgctxt "Addon Description"
 msgid "waipu.tv PVR Client. Note: This is not an official waipu plugin and not related to Exaring AG or waipu.tv. It was developed by volunteers."
-msgstr "waipu.tv client PVR. Nota: questo non è un plug-in waipu ufficiale e non è correlato a Exaring AG o waipu.tv. È stato sviluppato da volontari."
+msgstr "Client PVR di waipu.tv. Nota: questo non è un add-on ufficiale waipu e non è correlato a Exaring AG o waipu.tv. È stato sviluppato da volontari."
 
 msgctxt "#30001"
 msgid "General"
@@ -121,11 +121,11 @@ msgstr "Nessuna connessione di rete"
 
 msgctxt "#30032"
 msgid "Invalid login credentials"
-msgstr "Credenziali di autenticazione non valide"
+msgstr "Credenziali di accesso non valide"
 
 msgctxt "#30033"
 msgid "Required username and password not available"
-msgstr "Nome utente e password richiesti non disponibili"
+msgstr "Nome utente e password obbligatori non disponibili"
 
 msgctxt "#30034"
 msgid "Refresh Token"
@@ -145,7 +145,7 @@ msgstr "Reimposta accesso"
 
 msgctxt "#30038"
 msgid "Waipu.tv (Device Login)"
-msgstr "Waipu.tv (Accesso al dispositivo)"
+msgstr "Waipu.tv (accesso al dispositivo)"
 
 msgctxt "#30039"
 msgid "Go to:"
@@ -153,8 +153,32 @@ msgstr "Vai a:"
 
 msgctxt "#30040"
 msgid "Login"
-msgstr "Login"
+msgstr "Accedi"
 
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr "Usa il codice:"
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr "Anteprima immagini EPG"
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.ja_jp/strings.po b/pvr.waipu/resources/language/resource.language.ja_jp/strings.po
index 3600b02..882fec4 100644
--- a/pvr.waipu/resources/language/resource.language.ja_jp/strings.po
+++ b/pvr.waipu/resources/language/resource.language.ja_jp/strings.po
@@ -158,3 +158,27 @@ msgstr "ログイン"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.ko_kr/strings.po b/pvr.waipu/resources/language/resource.language.ko_kr/strings.po
index dacef3d..d28e05e 100644
--- a/pvr.waipu/resources/language/resource.language.ko_kr/strings.po
+++ b/pvr.waipu/resources/language/resource.language.ko_kr/strings.po
@@ -5,7 +5,7 @@
 msgid ""
 msgstr ""
 "Report-Msgid-Bugs-To: translations@kodi.tv\n"
-"PO-Revision-Date: 2022-03-27 01:17+0000\n"
+"PO-Revision-Date: 2023-05-09 23:16+0000\n"
 "Last-Translator: Minho Park <parkmino@gmail.com>\n"
 "Language-Team: Korean <https://kodi.weblate.cloud/projects/kodi-add-ons-pvr-clients/pvr-waipu/ko_kr/>\n"
 "Language: ko_kr\n"
@@ -13,7 +13,7 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Weblate 4.11.2\n"
+"X-Generator: Weblate 4.15.2\n"
 
 msgctxt "Addon Summary"
 msgid "waipu.tv PVR Client"
@@ -158,3 +158,27 @@ msgstr "로그인"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr "코드 사용:"
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr "EPG 미리보기 이미지"
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.lt_lt/strings.po b/pvr.waipu/resources/language/resource.language.lt_lt/strings.po
index 85b1a62..9d0aa06 100644
--- a/pvr.waipu/resources/language/resource.language.lt_lt/strings.po
+++ b/pvr.waipu/resources/language/resource.language.lt_lt/strings.po
@@ -158,3 +158,27 @@ msgstr "Prisijungimo vardas"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.lv_lv/strings.po b/pvr.waipu/resources/language/resource.language.lv_lv/strings.po
index 7ae7838..9f07df9 100644
--- a/pvr.waipu/resources/language/resource.language.lv_lv/strings.po
+++ b/pvr.waipu/resources/language/resource.language.lv_lv/strings.po
@@ -158,3 +158,27 @@ msgstr "Pieteikšanās"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.mi/strings.po b/pvr.waipu/resources/language/resource.language.mi/strings.po
index 179805d..c279fc7 100644
--- a/pvr.waipu/resources/language/resource.language.mi/strings.po
+++ b/pvr.waipu/resources/language/resource.language.mi/strings.po
@@ -158,3 +158,27 @@ msgstr ""
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.mk_mk/strings.po b/pvr.waipu/resources/language/resource.language.mk_mk/strings.po
index 45913fc..ff1e37e 100644
--- a/pvr.waipu/resources/language/resource.language.mk_mk/strings.po
+++ b/pvr.waipu/resources/language/resource.language.mk_mk/strings.po
@@ -158,3 +158,27 @@ msgstr "Најави се"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.ml_in/strings.po b/pvr.waipu/resources/language/resource.language.ml_in/strings.po
index 4390e05..41e816e 100644
--- a/pvr.waipu/resources/language/resource.language.ml_in/strings.po
+++ b/pvr.waipu/resources/language/resource.language.ml_in/strings.po
@@ -158,3 +158,27 @@ msgstr ""
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.mn_mn/strings.po b/pvr.waipu/resources/language/resource.language.mn_mn/strings.po
index bc0e88a..a35b5f0 100644
--- a/pvr.waipu/resources/language/resource.language.mn_mn/strings.po
+++ b/pvr.waipu/resources/language/resource.language.mn_mn/strings.po
@@ -158,3 +158,27 @@ msgstr ""
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.ms_my/strings.po b/pvr.waipu/resources/language/resource.language.ms_my/strings.po
index cac7a37..e130ef1 100644
--- a/pvr.waipu/resources/language/resource.language.ms_my/strings.po
+++ b/pvr.waipu/resources/language/resource.language.ms_my/strings.po
@@ -158,3 +158,27 @@ msgstr "Daftar Masuk"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.mt_mt/strings.po b/pvr.waipu/resources/language/resource.language.mt_mt/strings.po
index a370022..7f47cb5 100644
--- a/pvr.waipu/resources/language/resource.language.mt_mt/strings.po
+++ b/pvr.waipu/resources/language/resource.language.mt_mt/strings.po
@@ -158,3 +158,27 @@ msgstr ""
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.my_mm/strings.po b/pvr.waipu/resources/language/resource.language.my_mm/strings.po
index 0a501e5..b01216f 100644
--- a/pvr.waipu/resources/language/resource.language.my_mm/strings.po
+++ b/pvr.waipu/resources/language/resource.language.my_mm/strings.po
@@ -158,3 +158,27 @@ msgstr "ဝင်ရန်"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.nb_no/strings.po b/pvr.waipu/resources/language/resource.language.nb_no/strings.po
index ed76437..35462d5 100644
--- a/pvr.waipu/resources/language/resource.language.nb_no/strings.po
+++ b/pvr.waipu/resources/language/resource.language.nb_no/strings.po
@@ -158,3 +158,27 @@ msgstr "Innlogging"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.nl_nl/strings.po b/pvr.waipu/resources/language/resource.language.nl_nl/strings.po
index 8d33ae3..74dda70 100644
--- a/pvr.waipu/resources/language/resource.language.nl_nl/strings.po
+++ b/pvr.waipu/resources/language/resource.language.nl_nl/strings.po
@@ -158,3 +158,27 @@ msgstr "Gebruikersnaam"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.pl_pl/strings.po b/pvr.waipu/resources/language/resource.language.pl_pl/strings.po
index 4f17d77..60ef713 100644
--- a/pvr.waipu/resources/language/resource.language.pl_pl/strings.po
+++ b/pvr.waipu/resources/language/resource.language.pl_pl/strings.po
@@ -158,3 +158,27 @@ msgstr "Użytkownik"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.pt_br/strings.po b/pvr.waipu/resources/language/resource.language.pt_br/strings.po
index e2509d2..3487a20 100644
--- a/pvr.waipu/resources/language/resource.language.pt_br/strings.po
+++ b/pvr.waipu/resources/language/resource.language.pt_br/strings.po
@@ -158,3 +158,27 @@ msgstr "Login"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.pt_pt/strings.po b/pvr.waipu/resources/language/resource.language.pt_pt/strings.po
index cd6cdd6..c38db9b 100644
--- a/pvr.waipu/resources/language/resource.language.pt_pt/strings.po
+++ b/pvr.waipu/resources/language/resource.language.pt_pt/strings.po
@@ -158,3 +158,27 @@ msgstr "Iniciar sessão"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.ro_ro/strings.po b/pvr.waipu/resources/language/resource.language.ro_ro/strings.po
index 579b392..314a843 100644
--- a/pvr.waipu/resources/language/resource.language.ro_ro/strings.po
+++ b/pvr.waipu/resources/language/resource.language.ro_ro/strings.po
@@ -158,3 +158,27 @@ msgstr "Autentificare"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.ru_ru/strings.po b/pvr.waipu/resources/language/resource.language.ru_ru/strings.po
index 9a3e4f6..06b1b36 100644
--- a/pvr.waipu/resources/language/resource.language.ru_ru/strings.po
+++ b/pvr.waipu/resources/language/resource.language.ru_ru/strings.po
@@ -5,23 +5,23 @@
 msgid ""
 msgstr ""
 "Report-Msgid-Bugs-To: translations@kodi.tv\n"
-"PO-Revision-Date: 2022-04-09 10:15+0000\n"
-"Last-Translator: Christian Gade <gade@kodi.tv>\n"
+"PO-Revision-Date: 2022-09-13 09:14+0000\n"
+"Last-Translator: Andrei Stepanov <adem4ik@gmail.com>\n"
 "Language-Team: Russian <https://kodi.weblate.cloud/projects/kodi-add-ons-pvr-clients/pvr-waipu/ru_ru/>\n"
 "Language: ru_ru\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.11.2\n"
+"X-Generator: Weblate 4.14\n"
 
 msgctxt "Addon Summary"
 msgid "waipu.tv PVR Client"
-msgstr ""
+msgstr "Клиент записи эфира waipu.tv"
 
 msgctxt "Addon Description"
 msgid "waipu.tv PVR Client. Note: This is not an official waipu plugin and not related to Exaring AG or waipu.tv. It was developed by volunteers."
-msgstr ""
+msgstr "Клиент записи эфира waipu.tv. Примечание: Не является официальным дополнением Waipu и не связан с Exaring AG или waipu.tv. Разработка добровольцев."
 
 msgctxt "#30001"
 msgid "General"
@@ -29,7 +29,7 @@ msgstr "Общие"
 
 msgctxt "#30002"
 msgid "Mail"
-msgstr ""
+msgstr "Почта"
 
 msgctxt "#30003"
 msgid "Password"
@@ -37,7 +37,7 @@ msgstr "Пароль"
 
 msgctxt "#30004"
 msgid "Protocol"
-msgstr ""
+msgstr "Протокол"
 
 msgctxt "#30005"
 msgid "Streaming"
@@ -45,91 +45,91 @@ msgstr "Видео-поток"
 
 msgctxt "#30006"
 msgid "InputStream Helper information"
-msgstr ""
+msgstr "Справочная информация входящего потока"
 
 msgctxt "#30007"
 msgid "(Re)install Widevine CDM library..."
-msgstr ""
+msgstr "(Пере)установить библиотеку Widevine CDM…"
 
 msgctxt "#30008"
 msgid "Provider"
-msgstr ""
+msgstr "Поставщик"
 
 msgctxt "#30009"
 msgid "Waipu.tv (Credentials)"
-msgstr ""
+msgstr "Waipu.tv (учётные данные)"
 
 msgctxt "#30010"
 msgid "O2 TV"
-msgstr ""
+msgstr "O2 TV"
 
 msgctxt "#30011"
 msgid "Streaming Protocol"
-msgstr ""
+msgstr "Протокол вещания"
 
 msgctxt "#30012"
 msgid "Video Resolution"
-msgstr ""
+msgstr "Разрешение видео"
 
 msgctxt "#30013"
 msgid "Audio Codecs"
-msgstr ""
+msgstr "Кодеки аудио"
 
 msgctxt "#30014"
 msgid "SD-PALp25: h264; 720x540; 25fps"
-msgstr ""
+msgstr "SD-PALp25: h264; 720x540; 25fps"
 
 msgctxt "#30015"
 msgid "SD-PALp50: h264; 720x540; 50fps"
-msgstr ""
+msgstr "SD-PALp50: h264; 720x540; 50fps"
 
 msgctxt "#30016"
 msgid "HD-720p25: h264; 1280x720; 25fps"
-msgstr ""
+msgstr "HD-720p25: h264; 1280x720; 25fps"
 
 msgctxt "#30017"
 msgid "HD-720p50: h264; 1280x720; 50fps"
-msgstr ""
+msgstr "HD-720p50: h264; 1280x720; 50fps"
 
 msgctxt "#30018"
 msgid "HD-1080p25: h264; 1920x1080; 25fps"
-msgstr ""
+msgstr "HD-1080p25: h264; 1920x1080; 25fps"
 
 msgctxt "#30019"
 msgid "HD-1080p50: h264; 1920x1080; 50fps"
-msgstr ""
+msgstr "HD-1080p50: h264; 1920x1080; 50fps"
 
 msgctxt "#30020"
 msgid "HEVC-1080p50: hevc; 1920x1080; 50fps"
-msgstr ""
+msgstr "HEVC-1080p50: hevc; 1920x1080; 50fps"
 
 msgctxt "#30021"
 msgid "HEVC-2160p50: hevc; 3840x2160; 50fps"
-msgstr ""
+msgstr "HEVC-2160p50: hevc; 3840x2160; 50fps"
 
 msgctxt "#30025"
 msgid "AAC-LC: 128kBit, 48kHz"
-msgstr ""
+msgstr "AAC-LC: 128 кбит/с, 48 кГц"
 
 msgctxt "#30030"
 msgid "Error: Login not possible. Check credentials!"
-msgstr ""
+msgstr "Ошибка: Вход невозможен. Проверьте учётные данные!"
 
 msgctxt "#30031"
 msgid "No network connection"
-msgstr ""
+msgstr "Отсутствует сетевое подключение"
 
 msgctxt "#30032"
 msgid "Invalid login credentials"
-msgstr ""
+msgstr "Неверные учётные данные для входа"
 
 msgctxt "#30033"
 msgid "Required username and password not available"
-msgstr ""
+msgstr "Требуемые имя пользователя и пароль недоступны"
 
 msgctxt "#30034"
 msgid "Refresh Token"
-msgstr ""
+msgstr "Обновить токен"
 
 msgctxt "#30035"
 msgid "Misc"
@@ -141,15 +141,15 @@ msgstr "ID устройства"
 
 msgctxt "#30037"
 msgid "Reset Login"
-msgstr ""
+msgstr "Сбросить логин"
 
 msgctxt "#30038"
 msgid "Waipu.tv (Device Login)"
-msgstr ""
+msgstr "Waipu.tv (логин устройства)"
 
 msgctxt "#30039"
 msgid "Go to:"
-msgstr ""
+msgstr "Перейти:"
 
 msgctxt "#30040"
 msgid "Login"
@@ -157,4 +157,28 @@ msgstr "Логин"
 
 msgctxt "#30041"
 msgid "Use Code:"
+msgstr "Использовать код:"
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
 msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.si_lk/strings.po b/pvr.waipu/resources/language/resource.language.si_lk/strings.po
index 272d612..2687bef 100644
--- a/pvr.waipu/resources/language/resource.language.si_lk/strings.po
+++ b/pvr.waipu/resources/language/resource.language.si_lk/strings.po
@@ -158,3 +158,27 @@ msgstr ""
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.sk_sk/strings.po b/pvr.waipu/resources/language/resource.language.sk_sk/strings.po
index a0b0e84..5ddc3cf 100644
--- a/pvr.waipu/resources/language/resource.language.sk_sk/strings.po
+++ b/pvr.waipu/resources/language/resource.language.sk_sk/strings.po
@@ -158,3 +158,27 @@ msgstr "Prihlasovavie meno"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.sl_si/strings.po b/pvr.waipu/resources/language/resource.language.sl_si/strings.po
index fa48d17..56675f8 100644
--- a/pvr.waipu/resources/language/resource.language.sl_si/strings.po
+++ b/pvr.waipu/resources/language/resource.language.sl_si/strings.po
@@ -158,3 +158,27 @@ msgstr "Prijava"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.sq_al/strings.po b/pvr.waipu/resources/language/resource.language.sq_al/strings.po
index eeef57e..c0e242e 100644
--- a/pvr.waipu/resources/language/resource.language.sq_al/strings.po
+++ b/pvr.waipu/resources/language/resource.language.sq_al/strings.po
@@ -158,3 +158,27 @@ msgstr ""
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.sr_rs/strings.po b/pvr.waipu/resources/language/resource.language.sr_rs/strings.po
index f67af1d..5fdcb6c 100644
--- a/pvr.waipu/resources/language/resource.language.sr_rs/strings.po
+++ b/pvr.waipu/resources/language/resource.language.sr_rs/strings.po
@@ -158,3 +158,27 @@ msgstr "Пријава"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.sr_rs@latin/strings.po b/pvr.waipu/resources/language/resource.language.sr_rs@latin/strings.po
index 3ddafd4..724cf19 100644
--- a/pvr.waipu/resources/language/resource.language.sr_rs@latin/strings.po
+++ b/pvr.waipu/resources/language/resource.language.sr_rs@latin/strings.po
@@ -158,3 +158,27 @@ msgstr "Prijava"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.sv_se/strings.po b/pvr.waipu/resources/language/resource.language.sv_se/strings.po
index c9ca28a..3790e1c 100644
--- a/pvr.waipu/resources/language/resource.language.sv_se/strings.po
+++ b/pvr.waipu/resources/language/resource.language.sv_se/strings.po
@@ -158,3 +158,27 @@ msgstr "Logga in"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.szl/strings.po b/pvr.waipu/resources/language/resource.language.szl/strings.po
index 9e0d04e..2410e0d 100644
--- a/pvr.waipu/resources/language/resource.language.szl/strings.po
+++ b/pvr.waipu/resources/language/resource.language.szl/strings.po
@@ -158,3 +158,27 @@ msgstr "Logowanie"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.ta_in/strings.po b/pvr.waipu/resources/language/resource.language.ta_in/strings.po
index 65caa38..0658ad4 100644
--- a/pvr.waipu/resources/language/resource.language.ta_in/strings.po
+++ b/pvr.waipu/resources/language/resource.language.ta_in/strings.po
@@ -158,3 +158,27 @@ msgstr "புகுபதிகை"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.te_in/strings.po b/pvr.waipu/resources/language/resource.language.te_in/strings.po
index 995ccc3..e0f2008 100644
--- a/pvr.waipu/resources/language/resource.language.te_in/strings.po
+++ b/pvr.waipu/resources/language/resource.language.te_in/strings.po
@@ -158,3 +158,27 @@ msgstr ""
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.tg_tj/strings.po b/pvr.waipu/resources/language/resource.language.tg_tj/strings.po
index 499d60f..e282bd3 100644
--- a/pvr.waipu/resources/language/resource.language.tg_tj/strings.po
+++ b/pvr.waipu/resources/language/resource.language.tg_tj/strings.po
@@ -158,3 +158,27 @@ msgstr "Вуруд"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.th_th/strings.po b/pvr.waipu/resources/language/resource.language.th_th/strings.po
index 3812dfe..879662b 100644
--- a/pvr.waipu/resources/language/resource.language.th_th/strings.po
+++ b/pvr.waipu/resources/language/resource.language.th_th/strings.po
@@ -158,3 +158,27 @@ msgstr "ลงชื่อเข้าใช้"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.tr_tr/strings.po b/pvr.waipu/resources/language/resource.language.tr_tr/strings.po
index 4b57fa3..61fbf7c 100644
--- a/pvr.waipu/resources/language/resource.language.tr_tr/strings.po
+++ b/pvr.waipu/resources/language/resource.language.tr_tr/strings.po
@@ -158,3 +158,27 @@ msgstr "Giriş"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.uk_ua/strings.po b/pvr.waipu/resources/language/resource.language.uk_ua/strings.po
index bdbc93c..03dd46a 100644
--- a/pvr.waipu/resources/language/resource.language.uk_ua/strings.po
+++ b/pvr.waipu/resources/language/resource.language.uk_ua/strings.po
@@ -158,3 +158,27 @@ msgstr "Логін"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.uz_uz/strings.po b/pvr.waipu/resources/language/resource.language.uz_uz/strings.po
index 57173a5..5195ae1 100644
--- a/pvr.waipu/resources/language/resource.language.uz_uz/strings.po
+++ b/pvr.waipu/resources/language/resource.language.uz_uz/strings.po
@@ -158,3 +158,27 @@ msgstr "Kirish"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.vi_vn/strings.po b/pvr.waipu/resources/language/resource.language.vi_vn/strings.po
index 01777dd..e38b20f 100644
--- a/pvr.waipu/resources/language/resource.language.vi_vn/strings.po
+++ b/pvr.waipu/resources/language/resource.language.vi_vn/strings.po
@@ -158,3 +158,27 @@ msgstr "Đăng nhập"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.zh_cn/strings.po b/pvr.waipu/resources/language/resource.language.zh_cn/strings.po
index 5ecc91d..9646405 100644
--- a/pvr.waipu/resources/language/resource.language.zh_cn/strings.po
+++ b/pvr.waipu/resources/language/resource.language.zh_cn/strings.po
@@ -158,3 +158,27 @@ msgstr "登录"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/language/resource.language.zh_tw/strings.po b/pvr.waipu/resources/language/resource.language.zh_tw/strings.po
index faf0d04..69d95b0 100644
--- a/pvr.waipu/resources/language/resource.language.zh_tw/strings.po
+++ b/pvr.waipu/resources/language/resource.language.zh_tw/strings.po
@@ -158,3 +158,27 @@ msgstr "登入"
 msgctxt "#30041"
 msgid "Use Code:"
 msgstr ""
+
+msgctxt "#30042"
+msgid "EPG preview images"
+msgstr ""
+
+msgctxt "#30043"
+msgid "Import Channels"
+msgstr ""
+
+msgctxt "#30044"
+msgid "All visible"
+msgstr ""
+
+msgctxt "#30045"
+msgid "All"
+msgstr ""
+
+msgctxt "#30046"
+msgid "Favourites"
+msgstr ""
+
+msgctxt "#30047"
+msgid "Live TV"
+msgstr ""
diff --git a/pvr.waipu/resources/settings.xml b/pvr.waipu/resources/settings.xml
index e71e314..ff40141 100644
--- a/pvr.waipu/resources/settings.xml
+++ b/pvr.waipu/resources/settings.xml
@@ -149,27 +149,47 @@
 		</category>
 		<category id="misc" label="30035" help="">
 			<group id="6">
-				<setting id="refresh_token" type="string" label="30034" help="">
-					<level>3</level>
-					<default />
-					<constraints>
-						<allowempty>true</allowempty>
-					</constraints>
-					<control type="edit" format="string">
-						<heading>30034</heading>
-					</control>
-					<enable>false</enable>
-				</setting>
-				<setting id="device_id_uuid4" type="string" label="30036" help="">
-					<level>3</level>
-					<default />
-					<constraints>
-						<allowempty>true</allowempty>
-					</constraints>
-					<control type="edit" format="string">
-						<heading>30036</heading>
-					</control>
-				</setting>
+             <setting id="channel_import_filter" type="integer" label="30043"
+               help="">
+               <level>0</level>
+               <default>0</default>
+               <constraints>
+                  <options>
+                     <option label="30044">0</option>
+                     <option label="30045">1</option>
+                     <option label="30046">2</option>
+                     <option label="30047">3</option>
+                  </options>
+               </constraints>
+               <control type="spinner" format="string" />
+            </setting>
+				<setting id="epg_show_preview_images" type="boolean" label="30042" help="">
+               <level>3</level>
+               <default>false</default>
+               <control type="toggle"/>
+            </setting>
+            <setting id="refresh_token" type="string" label="30034" help="">
+               <level>3</level>
+               <default />
+               <constraints>
+                  <allowempty>true</allowempty>
+               </constraints>
+               <control type="edit" format="string">
+                  <heading>30034</heading>
+               </control>
+               <enable>false</enable>
+               <visible>false</visible>
+            </setting>
+            <setting id="device_id_uuid4" type="string" label="30036" help="">
+               <level>3</level>
+               <default />
+               <constraints>
+                  <allowempty>true</allowempty>
+               </constraints>
+               <control type="edit" format="string">
+                  <heading>30036</heading>
+               </control>
+            </setting>
 			</group>
 		</category>
 	</section>
diff --git a/src/Curl.cpp b/src/Curl.cpp
index 7722ab4..7a80554 100644
--- a/src/Curl.cpp
+++ b/src/Curl.cpp
@@ -4,7 +4,6 @@
 #include "Curl.h"
 
 #include "Utils.h"
-
 #include "kodi/tools/StringUtils.h"
 
 Curl::Curl() = default;
@@ -23,7 +22,8 @@ std::string Curl::GetCookie(const std::string& name)
 
 void Curl::SetCookie(const std::string& host, const std::string& name, const std::string& value)
 {
-  for(auto& cookie : m_cookies){
+  for (auto& cookie : m_cookies)
+  {
     if (cookie.host == host && cookie.name == name)
     {
       cookie.value = value;
@@ -148,11 +148,10 @@ kodi::vfs::CFile* Curl::PrepareRequest(const std::string& action,
   return file;
 }
 
-
 std::string Curl::Request(const std::string& action,
-                     const std::string& url,
-                     const std::string& postData,
-                     int& statusCode)
+                          const std::string& url,
+                          const std::string& postData,
+                          int& statusCode)
 {
   int remaining_redirects = m_redirectLimit;
   m_location = url;
@@ -177,8 +176,10 @@ std::string Curl::Request(const std::string& action,
     statusCode = 200;
 
     // get the real statusCode
-    const std::string tmpRespLine = file->GetPropertyValue(ADDON_FILE_PROPERTY_RESPONSE_PROTOCOL, "");
-    const std::vector<std::string> resp_protocol_parts = kodi::tools::StringUtils::Split(tmpRespLine, " ", 3);
+    const std::string tmpRespLine =
+        file->GetPropertyValue(ADDON_FILE_PROPERTY_RESPONSE_PROTOCOL, "");
+    const std::vector<std::string> resp_protocol_parts =
+        kodi::tools::StringUtils::Split(tmpRespLine, " ", 3);
 
     if (resp_protocol_parts.size() >= 2)
     {
@@ -217,7 +218,6 @@ std::string Curl::Request(const std::string& action,
   return body;
 }
 
-
 std::string Curl::Base64Encode(const std::string& str, bool urlEncode)
 {
   std::string ret;
@@ -227,8 +227,8 @@ std::string Curl::Base64Encode(const std::string& str, bool urlEncode)
 
   const char* to_base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
-int len = str.size();
-int curr = 0;
+  int len = str.size();
+  int curr = 0;
   while (len)
   {
     i = len > 2 ? 3 : len;
diff --git a/src/HLSAllowlist.cpp b/src/HLSAllowlist.cpp
index 93a823e..034214f 100644
--- a/src/HLSAllowlist.cpp
+++ b/src/HLSAllowlist.cpp
@@ -20,34 +20,32 @@
  */
 
 #include "HLSAllowlist.h"
+
 #include "kodi/tools/StringUtils.h"
 
 #include <kodi/Filesystem.h>
 
-
 HLSAllowlist::HLSAllowlist() : m_hls_allowed()
 {
   LoadHLSAllowlist();
 }
 
-
 bool HLSAllowlist::contains(std::string channelid) const
 {
   return std::find(m_hls_allowed.begin(), m_hls_allowed.end(), channelid) != m_hls_allowed.end();
 }
 
-
 void HLSAllowlist::LoadHLSAllowlist()
 {
-  const char *filePath = "special://home/addons/pvr.waipu/resources/hls_allowlist.txt";
-  if (!kodi::vfs::FileExists(filePath, false)) {
+  const char* filePath = "special://home/addons/pvr.waipu/resources/hls_allowlist.txt";
+  if (!kodi::vfs::FileExists(filePath, false))
+  {
     filePath = "special://xbmc/addons/pvr.waipu/resources/hls_allowlist.txt";
   }
 
   if (kodi::vfs::FileExists(filePath, false))
   {
-    kodi::Log(ADDON_LOG_DEBUG, "%s: Loading hls allowlist from file '%s'",
-        __FUNCTION__, filePath);
+    kodi::Log(ADDON_LOG_DEBUG, "%s: Loading hls allowlist from file '%s'", __FUNCTION__, filePath);
     kodi::vfs::CFile file;
     if (!file.OpenFile(filePath, 0))
     {
@@ -60,8 +58,8 @@ void HLSAllowlist::LoadHLSAllowlist()
     {
       line = kodi::tools::StringUtils::TrimRight(line);
       m_hls_allowed.push_back(line);
-      kodi::Log(ADDON_LOG_DEBUG, "%s: Add channel to hls allowlist '%s'",
-                __FUNCTION__, line.c_str());
+      kodi::Log(ADDON_LOG_DEBUG, "%s: Add channel to hls allowlist '%s'", __FUNCTION__,
+                line.c_str());
     }
   }
   else
diff --git a/src/HLSAllowlist.h b/src/HLSAllowlist.h
index 0a1e657..1f6844d 100644
--- a/src/HLSAllowlist.h
+++ b/src/HLSAllowlist.h
@@ -22,9 +22,8 @@
 
 #include "Utils.h"
 
-#include <string>
 #include <list>
-
+#include <string>
 
 class HLSAllowlist
 {
diff --git a/src/JWT.cpp b/src/JWT.cpp
index 19e53ad..fb73efc 100644
--- a/src/JWT.cpp
+++ b/src/JWT.cpp
@@ -20,6 +20,7 @@
  */
 
 #include "JWT.h"
+
 #include "Base64.h"
 #include "Utils.h"
 #include "kodi/General.h"
@@ -28,10 +29,12 @@
 #include <chrono>
 #include <vector>
 
-
 JWT::JWT(std::string token)
 {
-  if (token.empty()){ return; };
+  if (token.empty())
+  {
+    return;
+  };
   strToken = token;
   std::vector<std::string> jwt_arr = kodi::tools::StringUtils::Split(strToken, ".", 3);
   if (jwt_arr.size() == 3)
@@ -51,7 +54,7 @@ JWT::JWT(std::string token)
   }
 
   // parse iat
-  if(!this->parsedToken.HasMember("iat") || !this->parsedToken["iat"].IsInt())
+  if (!this->parsedToken.HasMember("iat") || !this->parsedToken["iat"].IsInt())
   {
     kodi::Log(ADDON_LOG_ERROR, "[jwt parse doc] ERROR: field 'iat' missing");
     this->initialized = false;
@@ -60,7 +63,7 @@ JWT::JWT(std::string token)
   this->iat = this->parsedToken["iat"].GetInt();
 
   // parse exp
-  if(!this->parsedToken.HasMember("exp") || !this->parsedToken["exp"].IsInt())
+  if (!this->parsedToken.HasMember("exp") || !this->parsedToken["exp"].IsInt())
   {
     kodi::Log(ADDON_LOG_ERROR, "[jwt parse doc] ERROR: field 'exp' missing");
     this->initialized = false;
@@ -74,10 +77,9 @@ JWT::JWT(std::string token)
 bool JWT::isExpired(int offset) const
 {
   kodi::Log(ADDON_LOG_DEBUG, "[jwt isExpired] exp: %i", exp);
-  int currTime = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count();
+  int currTime = std::chrono::duration_cast<std::chrono::seconds>(
+                     std::chrono::system_clock::now().time_since_epoch())
+                     .count();
   kodi::Log(ADDON_LOG_DEBUG, "[jwt isExpired] curr: %i", currTime);
   return (exp - offset) < currTime;
 }
-
-
-
diff --git a/src/JWT.h b/src/JWT.h
index 4dc5eb8..e811bdf 100644
--- a/src/JWT.h
+++ b/src/JWT.h
@@ -20,12 +20,10 @@
  *
  */
 
-
 #include "rapidjson/document.h"
 
 #include <string>
 
-
 class JWT
 {
 public:
@@ -34,9 +32,9 @@ public:
 
   bool isExpired(int offset = 0) const;
 
-  std::string getToken(){ return strToken; };
-  int getExp(){ return exp; };
-  bool isInitialized(){ return initialized; };
+  std::string getToken() { return strToken; };
+  int getExp() { return exp; };
+  bool isInitialized() { return initialized; };
   rapidjson::Document parsedToken; // bad, I know..
 
 private:
diff --git a/src/Utils.cpp b/src/Utils.cpp
index c4f931b..08fffc9 100644
--- a/src/Utils.cpp
+++ b/src/Utils.cpp
@@ -91,7 +91,6 @@ time_t Utils::StringToTime(std::string timeString)
   return ret;
 }
 
-
 std::string Utils::TimeToString(const time_t time)
 {
   char time_str[21] = "";
@@ -107,7 +106,7 @@ int Utils::GetIDDirty(std::string str)
   if (str.rfind("_", 0) == 0)
   {
     // str starts with _
-    return StringToInt(kodi::tools::StringUtils::TrimLeft(str,"\t\n\v\f\r _"), 1);
+    return StringToInt(kodi::tools::StringUtils::TrimLeft(str, "\t\n\v\f\r _"), 1);
   }
   return rand() % 99999 + 1;
 }
@@ -135,11 +134,12 @@ int Utils::StringToInt(std::string str, int defaultValue)
   }
 }
 
-std::string Utils::Replace(std::string str, const std::string& from, const std::string& to) {
+std::string Utils::Replace(std::string str, const std::string& from, const std::string& to)
+{
   // replaces the first occurrence
   // taken from: https://stackoverflow.com/questions/3418231/replace-part-of-a-string-with-another-string
   size_t start_pos = str.find(from);
-  if(start_pos != std::string::npos)
+  if (start_pos != std::string::npos)
     str.replace(start_pos, from.length(), to);
   return str;
 }
@@ -178,3 +178,25 @@ std::string Utils::CreateUUID()
   return uuid;
 }
 
+bool Utils::FileDownload(std::string source, std::string target)
+{
+  kodi::vfs::CFile inputFile;
+  if (inputFile.OpenFile(source, ADDON_READ_NO_CACHE))
+  {
+    kodi::vfs::CFile outputFile;
+    if (outputFile.OpenFileForWrite(target, true))
+    {
+      char buffer[1024];
+      int bytesRead = 0;
+      while ((bytesRead = inputFile.Read(buffer, sizeof(buffer) - 1)) > 0)
+      {
+        outputFile.Write(buffer, bytesRead);
+      }
+      inputFile.Close();
+      outputFile.Close();
+      return true;
+    }
+  }
+  return false;
+}
+
diff --git a/src/Utils.h b/src/Utils.h
index ea1adf3..7af9017 100644
--- a/src/Utils.h
+++ b/src/Utils.h
@@ -23,4 +23,5 @@ public:
   static int StringToInt(std::string str, int defaultValue);
   static std::string Replace(std::string str, const std::string& from, const std::string& to);
   static std::string CreateUUID();
+  static bool FileDownload(std::string url, std::string targetFile);
 };
diff --git a/src/WaipuData.cpp b/src/WaipuData.cpp
index 71b038a..0a441a6 100644
--- a/src/WaipuData.cpp
+++ b/src/WaipuData.cpp
@@ -20,12 +20,11 @@
  */
 
 #include "WaipuData.h"
+
 #include "Base64.h"
 #include "Utils.h"
-#include "kodi/tools/StringUtils.h"
 #include "kodi/General.h"
-#include <kodi/gui/dialogs/Progress.h>
-
+#include "kodi/tools/StringUtils.h"
 #include "rapidjson/document.h"
 
 #include <algorithm>
@@ -34,25 +33,35 @@
 #include <regex>
 #include <thread>
 
+#include <kodi/gui/dialogs/Progress.h>
+
 std::mutex WaipuData::mutex;
 
 // BEGIN CURL helpers from zattoo addon:
-std::string WaipuData::HttpGet(const std::string& url, const std::map<std::string,std::string>& headers)
+std::string WaipuData::HttpGet(const std::string& url,
+                               const std::map<std::string, std::string>& headers)
 {
   return HttpRequest("GET", url, "", headers);
 }
 
-std::string WaipuData::HttpDelete(const std::string& url, const std::string& postData, const std::map<std::string,std::string>& headers)
+std::string WaipuData::HttpDelete(const std::string& url,
+                                  const std::string& postData,
+                                  const std::map<std::string, std::string>& headers)
 {
   return HttpRequest("DELETE", url, postData, headers);
 }
 
-std::string WaipuData::HttpPost(const std::string& url, const std::string& postData, const std::map<std::string,std::string>& headers)
+std::string WaipuData::HttpPost(const std::string& url,
+                                const std::string& postData,
+                                const std::map<std::string, std::string>& headers)
 {
   return HttpRequest("POST", url, postData, headers);
 }
 
-std::string WaipuData::HttpRequest(const std::string& action, const std::string& url, const std::string& postData, const std::map<std::string,std::string>& headers)
+std::string WaipuData::HttpRequest(const std::string& action,
+                                   const std::string& url,
+                                   const std::string& postData,
+                                   const std::map<std::string, std::string>& headers)
 {
   Curl curl;
   int statusCode;
@@ -64,15 +73,17 @@ std::string WaipuData::HttpRequest(const std::string& action, const std::string&
 
   curl.AddHeader("Authorization", "Bearer " + m_accessToken.getToken());
 
-
   curl.AddHeader("User-Agent", WAIPU_USER_AGENT);
   kodi::Log(ADDON_LOG_DEBUG, "HTTP User-Agent: %s.", WAIPU_USER_AGENT.c_str());
 
   return HttpRequestToCurl(curl, action, url, postData, statusCode);
 }
 
-std::string WaipuData::HttpRequestToCurl(
-    Curl& curl, const std::string& action, const std::string& url, const std::string& postData, int& statusCode)
+std::string WaipuData::HttpRequestToCurl(Curl& curl,
+                                         const std::string& action,
+                                         const std::string& url,
+                                         const std::string& postData,
+                                         int& statusCode)
 {
   kodi::Log(ADDON_LOG_DEBUG, "Http-Request: %s %s.", action.c_str(), url.c_str());
   std::string content;
@@ -98,58 +109,108 @@ std::string WaipuData::HttpRequestToCurl(
 // END CURL helpers from zattoo addon
 
 // returns true if m_apiToken contains valid session
-bool WaipuData::ApiLogin()
+bool WaipuData::IsConnected()
 {
-  if(m_login_failed_counter > WAIPU_LOGIN_FAILED_LOCK_LIMIT){
-     // more than x consecutive failed login attempts
-     // check time limit
-     time_t currTime;
-     time(&currTime);
-     if(m_login_failed_locktime + 3*60 < currTime)
-     {
-       kodi::Log(ADDON_LOG_ERROR, "[API LOGIN] Reset login lock due to timer");
-       m_login_failed_counter = 0;
-     }else{
-       // block login attempt
-       kodi::Log(ADDON_LOG_ERROR, "[API LOGIN] Locked due to invalid attempts");
-       m_login_status = WAIPU_LOGIN_STATUS::INVALID_CREDENTIALS;
-       return false;
-     }
-  }
-
-  bool login_result;
-  if (m_provider == WAIPU_PROVIDER_WAIPU)
+  return m_login_status == WAIPU_LOGIN_STATUS::OK;
+}
+
+WAIPU_LOGIN_STATUS WaipuData::Login()
+{
+  kodi::Log(ADDON_LOG_DEBUG, "[token] current time %i", std::time(0));
+  kodi::Log(ADDON_LOG_DEBUG, "[token] expire  time %i", m_accessToken.getExp());
+  if (m_accessToken.isInitialized() && !m_accessToken.isExpired(20 * 60))
   {
-    login_result = WaipuLogin();
+    // API token exists and is valid, more than x in future
+    kodi::Log(ADDON_LOG_DEBUG, "[login check] old token still valid");
+    return WAIPU_LOGIN_STATUS::OK;
   }
-  else if (m_provider == WAIPU_PROVIDER_O2)
+
+  if (m_refreshToken.isInitialized() && !m_refreshToken.isExpired())
   {
-    login_result = DeviceLogin("o2");
-  }else
+    // Since the refresh token is valid for a long time, we do not check expiration for now
+    // refresh API token
+    std::string req = "refresh_token=" + Utils::UrlEncode(m_refreshToken.getToken()) +
+                      "&grant_type=refresh_token" + "&waipu_device_id=" + m_device_id;
+    kodi::Log(ADDON_LOG_DEBUG, "[login check] Login-Request (refresh): %s;", req.c_str());
+    return OAuthRequest(req);
+  }
+
+  if (m_provider == WAIPU_PROVIDER_WAIPU)
   {
-    // waipu oauth device workflow
-    login_result = DeviceLogin("waipu");
+    kodi::Log(ADDON_LOG_DEBUG, "[login check] WAIPU.TV LOGIN...");
+
+    // get API by login user/pw
+    std::string req = "username=" + Utils::UrlEncode(m_username) +
+                      "&password=" + Utils::UrlEncode(m_password) + "&grant_type=password" +
+                      "&waipu_device_id=" + m_device_id;
+    kodi::Log(ADDON_LOG_DEBUG, "[login check] Login-Request (user/pw)");
+    return OAuthRequest(req);
   }
-  if(login_result){
-    // login okay, reset counter
-    m_login_failed_counter = 0;
-  }else if (m_login_status != WAIPU_LOGIN_STATUS::NO_NETWORK) {
-      if(m_login_failed_counter == WAIPU_LOGIN_FAILED_LOCK_LIMIT)
-	{
-	  time_t currTime;
-	  time(&currTime);
-	  m_login_failed_locktime = currTime;
-	}
-      // login failed, increase counter
-      m_login_failed_counter = m_login_failed_counter + 1;
+  else if (m_provider == WAIPU_PROVIDER_O2)
+  {
+    return DeviceLogin("o2");
   }
 
-  return login_result;
+  // waipu oauth device workflow
+  return DeviceLogin("waipu");
+}
+
+void WaipuData::LoginThread()
+{
+  while (true)
+  {
+    if (!m_loginThreadRunning)
+      return;
+
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+    if (m_nextLoginAttempt > std::time(0) ||
+        m_login_status == WAIPU_LOGIN_STATUS::INVALID_CREDENTIALS)
+      continue;
+
+    if (m_login_failed_counter >= WAIPU_LOGIN_FAILED_LOCK_LIMIT)
+    {
+      kodi::Log(ADDON_LOG_ERROR, "[API LOGIN] Reset login lock due to timer");
+      m_login_failed_counter = 0;
+    }
+
+    auto previousStatus = m_login_status;
+    m_login_status = Login();
+
+    m_nextLoginAttempt = std::time(0) + 1;
+    if (m_login_status == WAIPU_LOGIN_STATUS::OK)
+    {
+      // login okay, reset counter
+      m_login_failed_counter = 0;
+
+      kodi::addon::CInstancePVRClient::ConnectionStateChange("Connected",
+                                                             PVR_CONNECTION_STATE_CONNECTED, "");
+      m_nextLoginAttempt = std::time(0) + 60;
+
+      if (previousStatus != m_login_status)
+      {
+        kodi::addon::CInstancePVRClient::TriggerChannelUpdate();
+        kodi::addon::CInstancePVRClient::TriggerRecordingUpdate();
+        kodi::addon::CInstancePVRClient::TriggerTimerUpdate();
+      }
+
+      continue;
+    }
+
+    kodi::addon::CInstancePVRClient::ConnectionStateChange("Connecting",
+                                                           PVR_CONNECTION_STATE_CONNECTING, "");
+
+    if (m_login_status == WAIPU_LOGIN_STATUS::NO_NETWORK)
+      continue;
+
+    if (++m_login_failed_counter >= WAIPU_LOGIN_FAILED_LOCK_LIMIT)
+      m_nextLoginAttempt = std::time(0) + 180;
+  }
 }
 
 bool WaipuData::ParseAccessToken()
 {
-  if(!m_accessToken.isInitialized() || m_accessToken.isExpired())
+  if (!m_accessToken.isInitialized() || m_accessToken.isExpired())
   {
     m_login_status = WAIPU_LOGIN_STATUS::UNKNOWN;
     kodi::Log(ADDON_LOG_ERROR, "[jwt_doc] ERROR: error while parsing json (error/expired)");
@@ -160,31 +221,35 @@ bool WaipuData::ParseAccessToken()
   kodi::Log(ADDON_LOG_DEBUG, "[jwt] userHandle: %s", m_userhandle.c_str());
   // generate the license
   std::string license_plain = "{\"merchant\" : \"exaring\", \"sessionId\" : \"default\", "
-                         "\"userId\" : \"" +
-                         m_userhandle + "\"}";
+                              "\"userId\" : \"" +
+                              m_userhandle + "\"}";
   kodi::Log(ADDON_LOG_DEBUG, "[jwt] license_plain: %s", license_plain.c_str());
   m_license = base64_encode(license_plain.c_str(), license_plain.length());
   kodi::Log(ADDON_LOG_DEBUG, "[jwt] license: %s", m_license.c_str());
   // get user channels
   m_user_channels_sd.clear();
   m_user_channels_hd.clear();
-  for (const auto& user_channel : m_accessToken.parsedToken["userAssets"]["channels"]["SD"].GetArray())
+  for (const auto& user_channel :
+       m_accessToken.parsedToken["userAssets"]["channels"]["SD"].GetArray())
   {
     std::string user_channel_s = user_channel.GetString();
     kodi::Log(ADDON_LOG_DEBUG, "[jwt] SD channel: %s", user_channel_s.c_str());
     m_user_channels_sd.emplace_back(user_channel_s);
   }
-  for (const auto& user_channel : m_accessToken.parsedToken["userAssets"]["channels"]["HD"].GetArray())
+  for (const auto& user_channel :
+       m_accessToken.parsedToken["userAssets"]["channels"]["HD"].GetArray())
   {
     std::string user_channel_s = user_channel.GetString();
     m_user_channels_hd.emplace_back(user_channel_s);
     kodi::Log(ADDON_LOG_DEBUG, "[jwt] HD channel: %s", user_channel_s.c_str());
   }
-  if(m_accessToken.parsedToken["userAssets"].HasMember("instantRestart")){
+  if (m_accessToken.parsedToken["userAssets"].HasMember("instantRestart"))
+  {
     m_account_replay_allowed = m_accessToken.parsedToken["userAssets"]["instantRestart"].GetBool();
     kodi::Log(ADDON_LOG_DEBUG, "[jwt] Account InstantStart: %i", m_account_replay_allowed);
   }
-  if(m_accessToken.parsedToken["userAssets"].HasMember("hoursRecording")){
+  if (m_accessToken.parsedToken["userAssets"].HasMember("hoursRecording"))
+  {
     m_account_hours_recording = m_accessToken.parsedToken["userAssets"]["hoursRecording"].GetInt();
     kodi::Log(ADDON_LOG_DEBUG, "[jwt] Account HoursReording: %i", m_account_hours_recording);
   }
@@ -193,11 +258,11 @@ bool WaipuData::ParseAccessToken()
   return true;
 }
 
-const std::map<std::string,std::string> WaipuData::GetOAuthDeviceCode(const std::string& tenant)
+const std::map<std::string, std::string> WaipuData::GetOAuthDeviceCode(const std::string& tenant)
 {
   kodi::Log(ADDON_LOG_DEBUG, "[device] GetOAuthDeviceCode, tenant '%s'", tenant.c_str());
   std::string jsonString;
-  std::map<std::string,std::string> result;
+  std::map<std::string, std::string> result;
   // curl request
   Curl curl;
   int statusCode = 0;
@@ -205,9 +270,12 @@ const std::map<std::string,std::string> WaipuData::GetOAuthDeviceCode(const std:
   curl.AddHeader("Content-Type", "application/json");
   curl.AddHeader("User-Agent", WAIPU_USER_AGENT);
   jsonString = HttpRequestToCurl(curl, "POST", "https://auth.waipu.tv/oauth/device_authorization",
-                               "{\"client_id\":\""+tenant+"\", \"waipu_device_id\":\""+m_device_id+"\"}", statusCode);
+                                 "{\"client_id\":\"" + tenant + "\", \"waipu_device_id\":\"" +
+                                     m_device_id + "\"}",
+                                 statusCode);
 
-  kodi::Log(ADDON_LOG_DEBUG, "[login check] GetOAuthDeviceCode-response: (HTTP %i) %s;", statusCode, jsonString.c_str());
+  kodi::Log(ADDON_LOG_DEBUG, "[login check] GetOAuthDeviceCode-response: (HTTP %i) %s;", statusCode,
+            jsonString.c_str());
 
   if (jsonString.empty() && statusCode == -1)
   {
@@ -216,7 +284,6 @@ const std::map<std::string,std::string> WaipuData::GetOAuthDeviceCode(const std:
     return result;
   }
 
-
   if (!jsonString.empty())
   {
     rapidjson::Document doc;
@@ -226,33 +293,38 @@ const std::map<std::string,std::string> WaipuData::GetOAuthDeviceCode(const std:
       kodi::Log(ADDON_LOG_ERROR, "[GetOAuthDeviceCode] ERROR: error while parsing json");
       return result;
     }
-    for(const std::string key : {"verification_uri", "user_code", "device_code", "verification_uri_complete"})
+    for (const std::string key :
+         {"verification_uri", "user_code", "device_code", "verification_uri_complete"})
     {
       if (doc.HasMember(key.c_str()))
       {
-	const std::string value = doc[key.c_str()].GetString();
-	kodi::Log(ADDON_LOG_DEBUG, "[GetOAuthDeviceCode] found %s: %s", key.c_str(), value.c_str());
-	result[key] = value;
+        const std::string value = doc[key.c_str()].GetString();
+        kodi::Log(ADDON_LOG_DEBUG, "[GetOAuthDeviceCode] found %s: %s", key.c_str(), value.c_str());
+        result[key] = value;
       }
     }
   }
-    return result;
+  return result;
 }
 
-const std::map<std::string,std::string> WaipuData::CheckOAuthState(const std::string& device_code)
+const std::map<std::string, std::string> WaipuData::CheckOAuthState(const std::string& device_code)
 {
   kodi::Log(ADDON_LOG_DEBUG, "[device] CheckOAuthState");
   std::string jsonString;
-  std::map<std::string,std::string> result;
+  std::map<std::string, std::string> result;
   // curl request
   Curl curl;
   int statusCode = 0;
   curl.AddHeader("Authorization", "Basic YW5kcm9pZENsaWVudDpzdXBlclNlY3JldA==");
   curl.AddHeader("User-Agent", WAIPU_USER_AGENT);
-  jsonString = HttpRequestToCurl(curl, "POST", "https://auth.waipu.tv/oauth/token",
-                               "device_code="+device_code+"&grant_type=urn:ietf:params:oauth:grant-type:device_code&waipu_device_id="+m_device_id, statusCode);
+  jsonString = HttpRequestToCurl(
+      curl, "POST", "https://auth.waipu.tv/oauth/token",
+      "device_code=" + device_code +
+          "&grant_type=urn:ietf:params:oauth:grant-type:device_code&waipu_device_id=" + m_device_id,
+      statusCode);
 
-  kodi::Log(ADDON_LOG_DEBUG, "[login check] CheckOAuthState-response: (HTTP %i) %s;", statusCode, jsonString.c_str());
+  kodi::Log(ADDON_LOG_DEBUG, "[login check] CheckOAuthState-response: (HTTP %i) %s;", statusCode,
+            jsonString.c_str());
 
   if (jsonString.empty() && statusCode == -1)
   {
@@ -261,7 +333,6 @@ const std::map<std::string,std::string> WaipuData::CheckOAuthState(const std::st
     return result;
   }
 
-
   if (!jsonString.empty())
   {
     rapidjson::Document doc;
@@ -271,20 +342,20 @@ const std::map<std::string,std::string> WaipuData::CheckOAuthState(const std::st
       kodi::Log(ADDON_LOG_ERROR, "[CheckOAuthState] ERROR: error while parsing json");
       return result;
     }
-    for(const std::string key : {"access_token", "refresh_token", "token_type"})
+    for (const std::string key : {"access_token", "refresh_token", "token_type"})
     {
       if (doc.HasMember(key.c_str()))
       {
-	const std::string value = doc[key.c_str()].GetString();
-	kodi::Log(ADDON_LOG_DEBUG, "[CheckOAuthState] found %s: %s", key.c_str(), value.c_str());
-	result[key] = value;
+        const std::string value = doc[key.c_str()].GetString();
+        kodi::Log(ADDON_LOG_DEBUG, "[CheckOAuthState] found %s: %s", key.c_str(), value.c_str());
+        result[key] = value;
       }
     }
   }
-    return result;
+  return result;
 }
 
-bool WaipuData::OAuthRequest(const std::string& postData)
+WAIPU_LOGIN_STATUS WaipuData::OAuthRequest(const std::string& postData)
 {
   kodi::Log(ADDON_LOG_DEBUG, "[OAuthRequest] Body: %s;", postData.c_str());
   std::string jsonString;
@@ -292,19 +363,19 @@ bool WaipuData::OAuthRequest(const std::string& postData)
   Curl curl;
   int statusCode = 0;
   curl.AddHeader("Authorization", "Basic YW5kcm9pZENsaWVudDpzdXBlclNlY3JldA==");
-//  curl.AddHeader("Content-Type", "application/x-www-form-urlencoded");
+  //  curl.AddHeader("Content-Type", "application/x-www-form-urlencoded");
   curl.AddHeader("User-Agent", WAIPU_USER_AGENT);
-  jsonString = HttpRequestToCurl(curl, "POST", "https://auth.waipu.tv/oauth/token", postData, statusCode);
+  jsonString =
+      HttpRequestToCurl(curl, "POST", "https://auth.waipu.tv/oauth/token", postData, statusCode);
 
   kodi::Log(ADDON_LOG_DEBUG, "[OAuthRequest] Login-response: (HTTP %i) %s;", statusCode,
             jsonString.c_str());
 
-  if (jsonString.empty() && statusCode == -1)
+  if (statusCode == -1)
   {
     // no network connection?
-    m_login_status = WAIPU_LOGIN_STATUS::NO_NETWORK;
     kodi::Log(ADDON_LOG_ERROR, "[OAuthRequest] no network connection");
-    return false;
+    return WAIPU_LOGIN_STATUS::NO_NETWORK;
   }
   else if (statusCode == 401)
   {
@@ -312,175 +383,111 @@ bool WaipuData::OAuthRequest(const std::string& postData)
     {
       // we used invalid refresh token, delete it
       m_refreshToken = JWT();
-      m_login_status = WAIPU_LOGIN_STATUS::UNKNOWN;
-      return false;
+      return WAIPU_LOGIN_STATUS::UNKNOWN;
     }
     // invalid credentials
-    m_login_status = WAIPU_LOGIN_STATUS::INVALID_CREDENTIALS;
-    return false;
+    return WAIPU_LOGIN_STATUS::INVALID_CREDENTIALS;
   }
 
-  if (!jsonString.empty())
+  if (jsonString.empty())
+    return WAIPU_LOGIN_STATUS::UNKNOWN;
+
+  rapidjson::Document doc;
+  doc.Parse(jsonString.c_str());
+  if (doc.HasParseError())
   {
-    rapidjson::Document doc;
-    doc.Parse(jsonString.c_str());
-    if (doc.GetParseError())
-    {
-      kodi::Log(ADDON_LOG_ERROR, "[OAuthRequest] ERROR: error while parsing json");
-      m_login_status = WAIPU_LOGIN_STATUS::UNKNOWN;
-      return false;
-    }
+    kodi::Log(ADDON_LOG_ERROR, "[OAuthRequest] ERROR: error while parsing json");
+    return WAIPU_LOGIN_STATUS::UNKNOWN;
+  }
 
-    if (doc.HasMember("error") && doc["error"] == "invalid_request")
+  if (doc.HasMember("error"))
+  {
+    if (doc["error"] == "invalid_request")
     {
       kodi::Log(ADDON_LOG_ERROR, "[OAuthRequest] ERROR: invalid credentials?");
-      m_login_status = WAIPU_LOGIN_STATUS::INVALID_CREDENTIALS;
-      return false;
-    }
-    else if (doc.HasMember("error"))
-    {
-      // unhandled error -> handle if known
-      std::string err = doc["error"].GetString();
-      kodi::Log(ADDON_LOG_ERROR, "[OAuthRequest] ERROR: (%s)", err.c_str());
-      m_login_status = WAIPU_LOGIN_STATUS::UNKNOWN;
-      return false;
+      return WAIPU_LOGIN_STATUS::INVALID_CREDENTIALS;
     }
 
-    m_accessToken = JWT(doc["access_token"].GetString());
-    kodi::Log(ADDON_LOG_DEBUG, "[OAuthRequest] accessToken: %s;", m_accessToken.getToken().c_str());
-    std::string refresh_token = doc["refresh_token"].GetString();
-    if (!refresh_token.empty())
-    {
-      m_refreshToken = JWT(refresh_token);
-      kodi::addon::SetSettingString("refresh_token", refresh_token);
-      kodi::Log(ADDON_LOG_DEBUG, "[OAuthRequest] refreshToken: %s;", refresh_token.c_str());
-    }
+    // unhandled error -> handle if known
+    std::string err = doc["error"].GetString();
+    kodi::Log(ADDON_LOG_ERROR, "[OAuthRequest] ERROR: (%s)", err.c_str());
+    return WAIPU_LOGIN_STATUS::UNKNOWN;
+  }
 
-    return ParseAccessToken();
+  m_accessToken = JWT(doc["access_token"].GetString());
+  kodi::Log(ADDON_LOG_DEBUG, "[OAuthRequest] accessToken: %s;", m_accessToken.getToken().c_str());
+  std::string refresh_token = doc["refresh_token"].GetString();
+  if (!refresh_token.empty())
+  {
+    m_refreshToken = JWT(refresh_token);
+    kodi::addon::SetSettingString("refresh_token", refresh_token);
+    kodi::Log(ADDON_LOG_DEBUG, "[OAuthRequest] refreshToken: %s;", refresh_token.c_str());
   }
-  // no valid session?
-  m_login_status = WAIPU_LOGIN_STATUS::UNKNOWN;
-  return false;
-}
 
+  return ParseAccessToken() ? WAIPU_LOGIN_STATUS::OK : WAIPU_LOGIN_STATUS::UNKNOWN;
+}
 
-bool WaipuData::DeviceLogin(const std::string& tenant)
+WAIPU_LOGIN_STATUS WaipuData::DeviceLogin(const std::string& tenant)
 {
-  kodi::Log(ADDON_LOG_DEBUG, "[DeviceLogin] waipu.tv DeviceLogin, tenant '%s' ...", tenant.c_str());
-
-  time_t currTime;
-  time(&currTime);
-  kodi::Log(ADDON_LOG_DEBUG, "[token] current time %i", currTime);
-  kodi::Log(ADDON_LOG_DEBUG, "[token] expire  time %i", m_accessToken.getExp());
-  std::lock_guard<std::mutex> lock(mutex);
-  if (m_accessToken.isInitialized() && !m_accessToken.isExpired(20 * 60))
-  {
-    // API token exists and is valid, more than x in future
-    kodi::Log(ADDON_LOG_DEBUG, "[login check] old token still valid");
-    return true;
-  }
+  WAIPU_LOGIN_STATUS ret = WAIPU_LOGIN_STATUS::INVALID_CREDENTIALS;
 
-  if (m_refreshToken.isInitialized() && !m_refreshToken.isExpired())
-  {
-    // Since the refresh token is valid for a long time, we do not check expiration for now
-    // refresh API token
-    std::string req = "refresh_token=" + Utils::UrlEncode(m_refreshToken.getToken())
-               + "&grant_type=refresh_token"
-               + "&waipu_device_id=" + m_device_id;
-    kodi::Log(ADDON_LOG_DEBUG, "[login check] Login-Request (refresh): %s;", req.c_str());
-    return OAuthRequest(req);
-  }
+  kodi::Log(ADDON_LOG_DEBUG, "[DeviceLogin] waipu.tv DeviceLogin, tenant '%s' ...", tenant.c_str());
 
-  const std::map<std::string,std::string> deviceCodeMap = GetOAuthDeviceCode(tenant);
-  if (!deviceCodeMap.count("verification_uri") || !deviceCodeMap.count("user_code") || !deviceCodeMap.count("device_code"))
+  const std::map<std::string, std::string> deviceCodeMap = GetOAuthDeviceCode(tenant);
+  if (!deviceCodeMap.count("verification_uri") || !deviceCodeMap.count("user_code") ||
+      !deviceCodeMap.count("device_code"))
   {
-	kodi::Log(ADDON_LOG_DEBUG, "OAuth missing response");
-	return false;
+    kodi::Log(ADDON_LOG_DEBUG, "OAuth missing response");
+    return ret;
   }
-  std::string code_req = "device_code="+deviceCodeMap.find("device_code")->second+"&grant_type=urn:ietf:params:oauth:grant-type:device_code&waipu_device_id="+m_device_id;
+  std::string code_req =
+      "device_code=" + deviceCodeMap.find("device_code")->second +
+      "&grant_type=urn:ietf:params:oauth:grant-type:device_code&waipu_device_id=" + m_device_id;
   kodi::Log(ADDON_LOG_DEBUG, "Create Login Progress");
-  kodi::gui::dialogs::CProgress *progress = new kodi::gui::dialogs::CProgress;
-  progress->SetHeading("pvr.waipu - "+tenant+" Login");
-  progress->SetLine(1, "1) "+kodi::addon::GetLocalizedString(30039)+" "+deviceCodeMap.find("verification_uri")->second);
-  progress->SetLine(2, "2) "+kodi::addon::GetLocalizedString(30040));
-  progress->SetLine(3, "3) "+kodi::addon::GetLocalizedString(30041)+" "+deviceCodeMap.find("user_code")->second);
+  kodi::gui::dialogs::CProgress* progress = new kodi::gui::dialogs::CProgress;
+  progress->SetHeading("pvr.waipu - " + tenant + " Login");
+  progress->SetLine(1, "1) " + kodi::addon::GetLocalizedString(30039) + " " +
+                           deviceCodeMap.find("verification_uri")->second);
+  progress->SetLine(2, "2) " + kodi::addon::GetLocalizedString(30040));
+  progress->SetLine(3, "3) " + kodi::addon::GetLocalizedString(30041) + " " +
+                           deviceCodeMap.find("user_code")->second);
   progress->SetCanCancel(true);
   progress->ShowProgressBar(true);
   progress->Open();
   for (unsigned int i = 0; i < 100; i += 1)
   {
     progress->SetPercentage(i);
-    if(OAuthRequest(code_req))
+    if (OAuthRequest(code_req) == WAIPU_LOGIN_STATUS::OK)
     {
-      delete progress;
+      ret = WAIPU_LOGIN_STATUS::OK;
       kodi::Log(ADDON_LOG_DEBUG, "OAuth success!");
-      return true;
+      break;
     }
 
     kodi::Log(ADDON_LOG_DEBUG, "OAuth pending");
 
     if (progress->IsCanceled())
     {
-	progress->Abort();
-	delete progress;
-	m_login_status = WAIPU_LOGIN_STATUS::INVALID_CREDENTIALS;
-        kodi::Log(ADDON_LOG_DEBUG, "OAuth login canceled");
-        return false;
+      progress->Abort();
+      ret = WAIPU_LOGIN_STATUS::INVALID_CREDENTIALS;
+      kodi::Log(ADDON_LOG_DEBUG, "OAuth login canceled");
+      break;
     }
     std::this_thread::sleep_for(std::chrono::seconds(3));
   }
-  m_login_status = WAIPU_LOGIN_STATUS::INVALID_CREDENTIALS;
+
   progress->Abort();
   delete progress;
-  return false;
-}
-
-
-bool WaipuData::WaipuLogin()
-{
-  kodi::Log(ADDON_LOG_DEBUG, "[login check] WAIPU.TV LOGIN...");
 
-  time_t currTime;
-  time(&currTime);
-  kodi::Log(ADDON_LOG_DEBUG, "[token] current time %i", currTime);
-  kodi::Log(ADDON_LOG_DEBUG, "[token] expire  time %i", m_accessToken.getExp());
-  std::lock_guard<std::mutex> lock(mutex);
-  if (m_accessToken.isInitialized() && !m_accessToken.isExpired(20 * 60))
-  {
-    // API token exists and is valid, more than x in future
-    kodi::Log(ADDON_LOG_DEBUG, "[login check] old token still valid");
-    return true;
-  }
-
-  if (m_refreshToken.isInitialized() && !m_refreshToken.isExpired())
-  {
-    // Since the refresh token is valid for a long time, we do not check expiration for now
-    // refresh API token
-    std::string req = "refresh_token=" + Utils::UrlEncode(m_refreshToken.getToken())
-               + "&grant_type=refresh_token"
-               + "&waipu_device_id=" + m_device_id;
-    kodi::Log(ADDON_LOG_DEBUG, "[login check] Login-Request (refresh): %s;", req.c_str());
-    return OAuthRequest(req);
-  }
-  else
-  {
-    // get API by login user/pw
-      std::string req = "username=" + Utils::UrlEncode(m_username)
-               + "&password=" + Utils::UrlEncode(m_password)
-               + "&grant_type=password"
-               + "&waipu_device_id=" + m_device_id;
-    kodi::Log(ADDON_LOG_DEBUG, "[login check] Login-Request (user/pw)");
-    return OAuthRequest(req);
-  }
+  return ret;
 }
 
-
 bool WaipuData::RefreshDeviceCapabiltiesToken()
 {
   kodi::Log(ADDON_LOG_DEBUG, "%s - Creating the waipu.tv PVR add-on", __FUNCTION__);
 
   kodi::Log(ADDON_LOG_DEBUG, "[device token] expire time %i", m_deviceCapabilitiesToken.getExp());
-  if (m_deviceCapabilitiesToken.isInitialized() && !m_deviceCapabilitiesToken.isExpired(5*60))
+  if (m_deviceCapabilitiesToken.isInitialized() && !m_deviceCapabilitiesToken.isExpired(5 * 60))
   {
     // device token exists and is valid, more than x in future
     kodi::Log(ADDON_LOG_DEBUG, "[device token] old token still valid, no need to refresh");
@@ -496,20 +503,31 @@ bool WaipuData::RefreshDeviceCapabiltiesToken()
 
   bool cap_audio_aac = kodi::addon::GetSettingBoolean("streaming_capabilities_audio_aac", false);
 
-  std::string capabilitesData = "{\"type\": \"receiver\", \"model\": \"Kodi 19\", \"manufacturer\": \"Team Kodi\", \"platform\": \"Kodi 19-pvr.waipu\", \"appVersion\": \""+appVersion+"\", \"capabilities\": {\"audio\": {\"aac\": "+(cap_audio_aac ? "true" : "false")+"},\"video\": { ";
+  std::string capabilitesData =
+      "{\"type\": \"receiver\", \"model\": \"Kodi 19\", \"manufacturer\": \"Team Kodi\", "
+      "\"platform\": \"Kodi 19-pvr.waipu\", \"appVersion\": \"" +
+      appVersion +
+      "\", \"capabilities\": {\"audio\": {\"aac\": " + (cap_audio_aac ? "true" : "false") +
+      "},\"video\": { ";
 
-  std::vector<std::string> video_cap_options = { "sdpalp25", "sdpalp50", "hd720p25", "hd720p50", "hd1080p25", "hd1080p50", "hevc1080p50", "hevc2160p50" };
+  std::vector<std::string> video_cap_options = {"sdpalp25",    "sdpalp50",   "hd720p25",
+                                                "hd720p50",    "hd1080p25",  "hd1080p50",
+                                                "hevc1080p50", "hevc2160p50"};
   bool first = true;
   for (const std::string& cap_option : video_cap_options)
   {
     bool cap_value =
         kodi::addon::GetSettingBoolean("streaming_capabilities_video_" + cap_option, false);
-    capabilitesData += std::string(first ? "" : ",")+ "\""+cap_option+"\": " + (cap_value ? "true" : "false");
+    capabilitesData +=
+        std::string(first ? "" : ",") + "\"" + cap_option + "\": " + (cap_value ? "true" : "false");
     first = false;
   }
   capabilitesData += "}}}";
 
-  std::string jsonDeviceToken = HttpPost("https://device-capabilities.waipu.tv/api/device-capabilities", capabilitesData, {{"Content-Type", "application/vnd.dc.device-info-v1+json"},{"X-USERCONTEXT-USERHANDLE",m_userhandle.c_str()}});
+  std::string jsonDeviceToken =
+      HttpPost("https://device-capabilities.waipu.tv/api/device-capabilities", capabilitesData,
+               {{"Content-Type", "application/vnd.dc.device-info-v1+json"},
+                {"X-USERCONTEXT-USERHANDLE", m_userhandle.c_str()}});
 
   kodi::Log(ADDON_LOG_DEBUG, "[X-Device-Token] response: %s", jsonDeviceToken.c_str());
 
@@ -519,14 +537,15 @@ bool WaipuData::RefreshDeviceCapabiltiesToken()
   deviceTokenDoc.Parse(jsonDeviceToken.c_str());
   if (deviceTokenDoc.GetParseError())
   {
-      kodi::Log(ADDON_LOG_DEBUG, "[X-Device-Token] parse error :(");
-      return false;
+    kodi::Log(ADDON_LOG_DEBUG, "[X-Device-Token] parse error :(");
+    return false;
   }
 
-  if(deviceTokenDoc.HasMember("token"))
+  if (deviceTokenDoc.HasMember("token"))
   {
     m_deviceCapabilitiesToken = JWT(deviceTokenDoc["token"].GetString());
-    kodi::Log(ADDON_LOG_DEBUG, "[X-Device-Token] discovered token: %s", m_deviceCapabilitiesToken.getToken().c_str());
+    kodi::Log(ADDON_LOG_DEBUG, "[X-Device-Token] discovered token: %s",
+              m_deviceCapabilitiesToken.getToken().c_str());
     return true;
   }
 
@@ -534,29 +553,6 @@ bool WaipuData::RefreshDeviceCapabiltiesToken()
   return false;
 }
 
-
-ADDON_STATUS WaipuData::Create()
-{
-  kodi::Log(ADDON_LOG_DEBUG, "%s - Creating the waipu.tv PVR add-on", __FUNCTION__);
-
-  // set User-Agent
-  std::string ua = kodi::network::GetUserAgent();
-  // use our replace, since kodi utils replaces all occurrences
-  WAIPU_USER_AGENT = Utils::Replace(ua, " ", std::string(" pvr.waipu/").append(STR(IPTV_VERSION)).append(" "));
-
-  ReadSettings();
-
-  if (m_provider == WAIPU_PROVIDER_WAIPU && (m_username.empty() || m_password.empty()))
-  {
-      kodi::QueueNotification(QUEUE_ERROR, "", kodi::addon::GetLocalizedString(30033));
-      return ADDON_STATUS_NEED_SETTINGS;
-  }
-  kodi::addon::CInstancePVRClient::TriggerChannelUpdate();
-  kodi::addon::CInstancePVRClient::TriggerRecordingUpdate();
-  kodi::addon::CInstancePVRClient::TriggerTimerUpdate();
-  return ADDON_STATUS_OK;
-}
-
 void WaipuData::ReadSettings()
 {
   kodi::Log(ADDON_LOG_DEBUG, "waipu.tv function call: [%s]", __FUNCTION__);
@@ -565,6 +561,8 @@ void WaipuData::ReadSettings()
   m_password = kodi::addon::GetSettingString("password");
   m_protocol = kodi::addon::GetSettingString("protocol", "auto");
   m_provider = kodi::addon::GetSettingEnum<WAIPU_PROVIDER>("provider_select", WAIPU_PROVIDER_WAIPU);
+  m_channel_filter = kodi::addon::GetSettingEnum<WAIPU_CHANNEL_IMPORT_FILTER>("channel_import_filter", CHANNEL_FILTER_ALL_VISIBLE);
+  m_epg_show_preview_images = kodi::addon::GetSettingBoolean("epg_show_preview_images");
   m_refreshToken = JWT(kodi::addon::GetSettingString("refresh_token", ""));
 
   m_device_id = kodi::addon::GetSettingString("device_id_uuid4");
@@ -607,13 +605,15 @@ ADDON_STATUS WaipuData::SetSetting(const std::string& settingName,
 
   else if (settingName == "protocol")
   {
-    std::string protocol = settingValue.GetString();
-    if (protocol != m_protocol)
+     m_protocol = settingValue.GetString();
+     return ADDON_STATUS_OK;
+  }
+
+  else if (settingName == "epg_show_preview_images")
     {
-      m_protocol = protocol;
+      m_epg_show_preview_images = settingValue.GetBoolean();
       return ADDON_STATUS_OK;
     }
-  }
 
   else if (settingName == "provider_select")
   {
@@ -625,17 +625,31 @@ ADDON_STATUS WaipuData::SetSetting(const std::string& settingName,
       kodi::addon::SetSettingString("refresh_token", "");
       return ADDON_STATUS_NEED_RESTART;
     }
-  }else if (settingName.rfind("streaming_capabilities_", 0) == 0)
+  }
+  else if (settingName == "channel_import_filter")
   {
-    // settings name begins with "streaming_capabilities_"
-    // reset capabilities to force refresh
-    m_deviceCapabilitiesToken = JWT();
-  }else if( settingName == "refresh_reset" && settingValue.GetBoolean())
+    WAIPU_CHANNEL_IMPORT_FILTER tmpFilter = settingValue.GetEnum<WAIPU_CHANNEL_IMPORT_FILTER>();
+    if (tmpFilter != m_channel_filter)
     {
-      kodi::addon::SetSettingBoolean("refresh_reset", false);
-      kodi::addon::SetSettingString("refresh_token", "");
+      m_channel_filter = tmpFilter;
+      // we need to restart plugin for now, to LoadChannelData()
+      //kodi::addon::CInstancePVRClient::TriggerChannelUpdate();
+      //return ADDON_STATUS_OK;
       return ADDON_STATUS_NEED_RESTART;
     }
+  }
+  else if (settingName.rfind("streaming_capabilities_", 0) == 0)
+  {
+    // settings name begins with "streaming_capabilities_"
+    // reset capabilities to force refresh
+    m_deviceCapabilitiesToken = JWT();
+  }
+  else if (settingName == "refresh_reset" && settingValue.GetBoolean())
+  {
+    kodi::addon::SetSettingBoolean("refresh_reset", false);
+    kodi::addon::SetSettingString("refresh_token", "");
+    return ADDON_STATUS_NEED_RESTART;
+  }
 
   return ADDON_STATUS_OK;
 }
@@ -666,14 +680,13 @@ PVR_ERROR WaipuData::GetBackendVersion(std::string& version)
 
 std::string WaipuData::GetLicense()
 {
-  // ensure that userHandle is valid
-  ApiLogin();
   return m_license;
 }
 
 void WaipuData::SetStreamProperties(std::vector<kodi::addon::PVRStreamProperty>& properties,
                                     const std::string& url,
-                                    bool realtime, bool playTimeshiftBuffer,
+                                    bool realtime,
+                                    bool playTimeshiftBuffer,
                                     const std::string& protocol)
 {
   kodi::Log(ADDON_LOG_DEBUG, "[PLAY STREAM] url: %s", url.c_str());
@@ -691,7 +704,7 @@ void WaipuData::SetStreamProperties(std::vector<kodi::addon::PVRStreamProperty>&
 
     if (playTimeshiftBuffer)
     {
-       properties.emplace_back("inputstream.adaptive.play_timeshift_buffer","true");
+      properties.emplace_back("inputstream.adaptive.play_timeshift_buffer", "true");
     }
 
     // get widevine license
@@ -714,19 +727,20 @@ void WaipuData::SetStreamProperties(std::vector<kodi::addon::PVRStreamProperty>&
   }
   else
   {
-    kodi::Log(ADDON_LOG_ERROR, "[SetStreamProperties] called with invalid protocol '%s'", protocol.c_str());
+    kodi::Log(ADDON_LOG_ERROR, "[SetStreamProperties] called with invalid protocol '%s'",
+              protocol.c_str());
   }
 }
 
 bool WaipuData::LoadChannelData()
 {
-  if (m_channels.size() > 0) return true;
+  if (m_channels.size() > 0)
+    return true;
 
-  if (!ApiLogin())
-  {
-    // no valid session
+  // no valid session
+  if (!IsConnected())
     return false;
-  }
+
   std::lock_guard<std::mutex> lock(mutex);
   kodi::Log(ADDON_LOG_DEBUG, "[load data] Get channels");
 
@@ -755,7 +769,6 @@ bool WaipuData::LoadChannelData()
   kodi::Log(ADDON_LOG_DEBUG, "[channels] iterate channels");
   kodi::Log(ADDON_LOG_DEBUG, "[channels] size: %i;", channelsDoc["result"].Size());
 
-
   WaipuChannelGroup cgroup_fav;
   cgroup_fav.name = "Favoriten";
 
@@ -796,10 +809,18 @@ bool WaipuData::LoadChannelData()
         skipChannel |= (prop.GetString() == std::string("UserSetHidden"));
         tvfuse |= (prop.GetString() == std::string("tvfuse"));
       }
-      if (skipChannel)
+      // skip if we do not enforce to show all
+      if (m_channel_filter != CHANNEL_FILTER_ALL && skipChannel)
         continue;
     }
 
+    // Apply LiveTV filter (=!tvfuse)
+    if (m_channel_filter == CHANNEL_FILTER_LIVE && tvfuse) continue;
+
+    // Apply Favourites filter
+    bool isFav = channel["faved"].GetBool();
+    if (m_channel_filter == CHANNEL_FILTER_FAVOURITES && !isFav) continue;
+
     ++i;
     WaipuChannel waipu_channel;
     waipu_channel.iChannelNumber = i; // position
@@ -844,22 +865,31 @@ bool WaipuData::LoadChannelData()
       }
       kodi::Log(ADDON_LOG_DEBUG, "[channel] link: %s -> %s;", rel.c_str(), href.c_str());
     }
+
+    std::string channel_url = "";
     if (icon_hd.size() > 0 && isHD)
     {
-      waipu_channel.strIconPath = icon_hd + "?width=256&height=256";
+      channel_url = icon_hd + "?width=256&height=256";
     }
     else if (icon_sd.size() > 0)
     {
-      waipu_channel.strIconPath = icon_sd + "?width=256&height=256";
+      channel_url = icon_sd + "?width=256&height=256";
     }
     else if (icon.size() > 0)
     {
-      waipu_channel.strIconPath = icon + "?width=256&height=256";
+      channel_url = icon + "?width=256&height=256";
     }
-    kodi::Log(ADDON_LOG_DEBUG, "[channel] selected channel logo: %s",
-              waipu_channel.strIconPath.c_str());
 
-    bool isFav = channel["faved"].GetBool();
+    std::string iconPath = "special://home/addons/pvr.waipu/resources/channel_icons/" + waipu_channel.waipuID + ".png";
+    if (!kodi::vfs::FileExists(iconPath, true))
+    {
+      kodi::Log(ADDON_LOG_DEBUG, "[channel] download channel logo: %s -> %s", channel_url.c_str(), iconPath.c_str());
+      Utils::FileDownload(channel_url, iconPath);
+    }
+    waipu_channel.strIconPath = iconPath;
+
+    kodi::Log(ADDON_LOG_DEBUG, "[channel] selected channel logo: %s", waipu_channel.strIconPath.c_str());
+
     if (isFav)
     {
       // user added channel to favorites
@@ -888,6 +918,9 @@ bool WaipuData::LoadChannelData()
 
 PVR_ERROR WaipuData::GetChannelsAmount(int& amount)
 {
+  if (!IsConnected())
+    return PVR_ERROR_SERVER_ERROR;
+
   kodi::Log(ADDON_LOG_DEBUG, "waipu.tv function call: [%s]", __FUNCTION__);
   LoadChannelData();
 
@@ -897,6 +930,9 @@ PVR_ERROR WaipuData::GetChannelsAmount(int& amount)
 
 PVR_ERROR WaipuData::GetChannels(bool radio, kodi::addon::PVRChannelsResultSet& results)
 {
+  if (!IsConnected())
+    return PVR_ERROR_SERVER_ERROR;
+
   kodi::Log(ADDON_LOG_DEBUG, "waipu.tv function call: [%s]", __FUNCTION__);
   LoadChannelData();
 
@@ -954,56 +990,66 @@ PVR_ERROR WaipuData::GetChannelStreamProperties(
   return ret;
 }
 
-std::string WaipuData::GetChannelStreamURL(int uniqueId, const std::string& protocol, const std::string& startTime)
+std::string WaipuData::GetChannelStreamURL(int uniqueId,
+                                           const std::string& protocol,
+                                           const std::string& startTime)
 {
+  if (!IsConnected())
+  {
+    kodi::Log(ADDON_LOG_DEBUG, "[GetStreamURL] No stream login");
+    return "";
+  }
+
   for (const auto& channel : m_channels)
   {
     if (channel.iUniqueId == uniqueId)
     {
-      kodi::Log(ADDON_LOG_DEBUG, "[GetStreamURL] Get live URL for channel %s", channel.strChannelName.c_str());
-
-      if (!ApiLogin())
-      {
-        // invalid
-        kodi::Log(ADDON_LOG_DEBUG, "[GetStreamURL] No stream login");
-        return {};
-      }
+      kodi::Log(ADDON_LOG_DEBUG, "[GetStreamURL] Get live URL for channel %s",
+                channel.strChannelName.c_str());
 
       // ensure device token is fresh
       RefreshDeviceCapabiltiesToken();
 
-      std::string postData = "{\"stream\": { \"station\": \""+channel.waipuID+"\", \"protocol\": \""+protocol+"\", \"requestMuxInstrumentation\": false";
+      std::string postData = "{\"stream\": { \"station\": \"" + channel.waipuID +
+                             "\", \"protocol\": \"" + protocol +
+                             "\", \"requestMuxInstrumentation\": false";
       if (!startTime.empty())
       {
-	  postData += ", \"startTime\": "+startTime;
+        postData += ", \"startTime\": " + startTime;
       }
       postData += "}}";
       kodi::Log(ADDON_LOG_DEBUG, "[GetStreamURL] Post data: %s", postData.c_str());
 
-      std::string jsonStreamURL = HttpPost("https://stream-url-provider.waipu.tv/api/stream-url", postData, {{"Content-Type", "application/vnd.streamurlprovider.stream-url-request-v1+json"}, {"X-Device-Token", m_deviceCapabilitiesToken.getToken().c_str()}});
+      std::string jsonStreamURL = HttpPost(
+          "https://stream-url-provider.waipu.tv/api/stream-url", postData,
+          {{"Content-Type", "application/vnd.streamurlprovider.stream-url-request-v1+json"},
+           {"X-Device-Token", m_deviceCapabilitiesToken.getToken().c_str()}});
 
       rapidjson::Document streamURLDoc;
       streamURLDoc.Parse(jsonStreamURL.c_str());
       if (streamURLDoc.GetParseError())
       {
-          kodi::Log(ADDON_LOG_ERROR, "[GetStreamURL] ERROR: error while parsing json");
-          return {};
+        kodi::Log(ADDON_LOG_ERROR, "[GetStreamURL] ERROR: error while parsing json");
+        return "";
       }
 
-      if(!streamURLDoc.HasMember("streamUrl"))
+      if (!streamURLDoc.HasMember("streamUrl"))
       {
-          kodi::Log(ADDON_LOG_ERROR, "[GetStreamURL] ERROR: missing param streamUrl");
-          return {};
+        kodi::Log(ADDON_LOG_ERROR, "[GetStreamURL] ERROR: missing param streamUrl");
+        return "";
       }
 
       return streamURLDoc["streamUrl"].GetString();
     }
   }
-  return {};
+  return "";
 }
 
 PVR_ERROR WaipuData::GetChannelGroupsAmount(int& amount)
 {
+  if (!IsConnected())
+    return PVR_ERROR_SERVER_ERROR;
+
   LoadChannelData();
   amount = static_cast<int>(m_channelGroups.size());
   return PVR_ERROR_NO_ERROR;
@@ -1011,6 +1057,9 @@ PVR_ERROR WaipuData::GetChannelGroupsAmount(int& amount)
 
 PVR_ERROR WaipuData::GetChannelGroups(bool radio, kodi::addon::PVRChannelGroupsResultSet& results)
 {
+  if (!IsConnected())
+    return PVR_ERROR_SERVER_ERROR;
+
   LoadChannelData();
   std::vector<WaipuChannelGroup>::iterator it;
   for (it = m_channelGroups.begin(); it != m_channelGroups.end(); ++it)
@@ -1056,10 +1105,9 @@ PVR_ERROR WaipuData::GetEPGForChannel(int channelUid,
                                       time_t end,
                                       kodi::addon::PVREPGTagsResultSet& results)
 {
-  if (!ApiLogin())
-  {
+  if (!IsConnected())
     return PVR_ERROR_SERVER_ERROR;
-  }
+
   LoadChannelData();
 
   for (const auto& channel : m_channels)
@@ -1070,9 +1118,9 @@ PVR_ERROR WaipuData::GetEPGForChannel(int channelUid,
     std::string startTime = Utils::TimeToString(start);
     std::string endTime = Utils::TimeToString(end);
 
-    std::string jsonEpg =
-        HttpGet("https://epg.waipu.tv/api/channels/" + channel.waipuID +
-                "/programs?startTime=" + std::string(startTime) + "&stopTime=" + std::string(endTime));
+    std::string jsonEpg = HttpGet("https://epg.waipu.tv/api/channels/" + channel.waipuID +
+                                  "/programs?startTime=" + std::string(startTime) +
+                                  "&stopTime=" + std::string(endTime));
     kodi::Log(ADDON_LOG_DEBUG, "[epg-all] %s", jsonEpg.c_str());
     if (jsonEpg.empty())
     {
@@ -1118,12 +1166,18 @@ PVR_ERROR WaipuData::GetEPGForChannel(int channelUid,
       // is recordable
       bool isRecordable = !epgData["recordingForbidden"].GetBool();
       kodi::Log(ADDON_LOG_DEBUG, "[epg] recordable: %i;", isRecordable);
-      if (isRecordable){flags |= EPG_TAG_FLAG_IS_RECORDABLE_WAIPU; }
+      if (isRecordable)
+      {
+        flags |= EPG_TAG_FLAG_IS_RECORDABLE_WAIPU;
+      }
 
       // instantRestartAllowed
       bool instantRestartAllowed = !epgData["instantRestartForbidden"].GetBool();
       kodi::Log(ADDON_LOG_DEBUG, "[epg] instantRestartAllowed: %i;", instantRestartAllowed);
-      if (isRecordable){flags |= EPG_TAG_FLAG_INSTANT_RESTART_ALLOWED_WAIPU; }
+      if (isRecordable)
+      {
+        flags |= EPG_TAG_FLAG_INSTANT_RESTART_ALLOWED_WAIPU;
+      }
 
       // set title
       tag.SetTitle(epgData["title"].GetString());
@@ -1147,13 +1201,16 @@ PVR_ERROR WaipuData::GetEPGForChannel(int channelUid,
       }
 
       // epg preview image
-      if(epgData.HasMember("previewImages") && epgData["previewImages"].IsArray() && epgData["previewImages"].Size() > 0){
-          std::string tmp_img = epgData["previewImages"][0].GetString();
-          tmp_img += "?width=480&height=270";
-          tag.SetIconPath(tmp_img);
-          kodi::Log(ADDON_LOG_DEBUG, "[epg] previewImage: %s;", tmp_img.c_str());
+      if (m_epg_show_preview_images && epgData.HasMember("previewImages") &&
+	  epgData["previewImages"].IsArray() && epgData["previewImages"].Size() > 0)
+      {
+        std::string tmp_img = epgData["previewImages"][0].GetString();
+        tmp_img += "?width=480&height=270";
+        tag.SetIconPath(tmp_img);
+        kodi::Log(ADDON_LOG_DEBUG, "[epg] previewImage: %s;", tmp_img.c_str());
       }
 
+
       // iSeriesNumber
       if (epgData.HasMember("season") && !epgData["season"].IsNull())
       {
@@ -1191,7 +1248,7 @@ PVR_ERROR WaipuData::GetEPGForChannel(int channelUid,
       // genre
       if (epgData.HasMember("genreDisplayName") && !epgData["genreDisplayName"].IsNull())
       {
-	const std::string genreStr = epgData["genreDisplayName"].GetString();
+        const std::string genreStr = epgData["genreDisplayName"].GetString();
         int genre = m_categories.Category(genreStr);
         if (genre)
         {
@@ -1247,16 +1304,18 @@ PVR_ERROR WaipuData::IsEPGTagPlayable(const kodi::addon::PVREPGTag& tag, bool& i
     if (channel.iUniqueId != tag.GetUniqueChannelId())
       continue;
     isPlayable = channel.tvfuse;
-    if (isPlayable) {
+    if (isPlayable)
+    {
       return PVR_ERROR_NO_ERROR;
     }
   }
 
   // check if program is running and replay allowed
   auto current_time = time(NULL);
-  if (m_account_replay_allowed && current_time > tag.GetStartTime() && current_time < tag.GetEndTime())
+  if (m_account_replay_allowed && current_time > tag.GetStartTime() &&
+      current_time < tag.GetEndTime())
   {
-      isPlayable = (tag.GetFlags() & EPG_TAG_FLAG_INSTANT_RESTART_ALLOWED_WAIPU);
+    isPlayable = (tag.GetFlags() & EPG_TAG_FLAG_INSTANT_RESTART_ALLOWED_WAIPU);
   }
 
   return PVR_ERROR_NO_ERROR;
@@ -1269,7 +1328,8 @@ PVR_ERROR WaipuData::GetEPGTagStreamProperties(
   LoadChannelData();
 
   std::string protocol = m_protocol;
-  if (protocol == "auto") protocol = "dash";  //fallback to dash
+  if (protocol == "auto")
+    protocol = "dash"; //fallback to dash
 
   std::string strUrl = GetEPGTagURL(tag, protocol);
   if (strUrl.empty())
@@ -1284,9 +1344,6 @@ PVR_ERROR WaipuData::GetEPGTagStreamProperties(
 
 std::string WaipuData::GetEPGTagURL(const kodi::addon::PVREPGTag& tag, const std::string& protocol)
 {
-  ApiLogin();
-  LoadChannelData();
-
   for (const auto& channel : m_channels)
   {
     if (channel.iUniqueId == tag.GetUniqueChannelId())
@@ -1295,23 +1352,27 @@ std::string WaipuData::GetEPGTagURL(const kodi::addon::PVREPGTag& tag, const std
       std::string endTime = Utils::TimeToString(tag.GetEndTime());
 
       std::string jsonEpg =
-	  HttpGet("https://epg.waipu.tv/api/channels/" + channel.waipuID +
-	          "/programs?includeRunningAtStartTime=false&startTime=" + std::string(startTime) + "&stopTime=" + std::string(endTime));
+          HttpGet("https://epg.waipu.tv/api/channels/" + channel.waipuID +
+                  "/programs?includeRunningAtStartTime=false&startTime=" + std::string(startTime) +
+                  "&stopTime=" + std::string(endTime));
       kodi::Log(ADDON_LOG_DEBUG, "[epg-single-tag] %s", jsonEpg.c_str());
       if (jsonEpg.empty())
       {
         kodi::Log(ADDON_LOG_ERROR, "[epg-single-tag] empty server response");
-        return {};
+        return "";
       }
       jsonEpg = "{\"result\": " + jsonEpg + "}";
 
       rapidjson::Document epgDoc;
       epgDoc.Parse(jsonEpg.c_str());
 
-      if (epgDoc.GetParseError() || epgDoc["result"].Empty() || !epgDoc["result"][0].HasMember("streamUrlProvider") || epgDoc["result"][0]["streamUrlProvider"].IsNull())
+      if (epgDoc.GetParseError() || epgDoc["result"].Empty() ||
+          !epgDoc["result"][0].HasMember("streamUrlProvider") ||
+          epgDoc["result"][0]["streamUrlProvider"].IsNull())
       {
         // fallback to replay playback
-        kodi::Log(ADDON_LOG_DEBUG, "[play epg tag] streamUrlProvider not found -> fallback to replay!");
+        kodi::Log(ADDON_LOG_DEBUG,
+                  "[play epg tag] streamUrlProvider not found -> fallback to replay!");
         std::string startTime = std::to_string(tag.GetStartTime());
         return GetChannelStreamURL(tag.GetUniqueChannelId(), protocol, startTime);
       }
@@ -1330,13 +1391,13 @@ std::string WaipuData::GetEPGTagURL(const kodi::addon::PVREPGTag& tag, const std
         if (tagDoc.GetParseError())
         {
           kodi::Log(ADDON_LOG_ERROR, "[getEPGTagURL] ERROR: error while parsing json");
-          return {};
+          return "";
         }
         kodi::Log(ADDON_LOG_DEBUG, "[tag] streams");
         // check if streams there
         if (tagDoc.HasMember("player") && tagDoc["player"].HasMember("mpd"))
         {
-            std::string mpdUrl = tagDoc["player"]["mpd"].GetString();
+          std::string mpdUrl = tagDoc["player"]["mpd"].GetString();
           kodi::Log(ADDON_LOG_DEBUG, "mpd url -> %s", mpdUrl.c_str());
           return mpdUrl;
         }
@@ -1344,172 +1405,136 @@ std::string WaipuData::GetEPGTagURL(const kodi::addon::PVREPGTag& tag, const std
     }
   }
   kodi::Log(ADDON_LOG_DEBUG, "[play epg tag] channel or tag not found!");
-  return {};
+  return "";
 }
 
 PVR_ERROR WaipuData::GetRecordingsAmount(bool deleted, int& amount)
 {
+  if (!IsConnected())
+    return PVR_ERROR_SERVER_ERROR;
+
   amount = m_recordings_count;
   return PVR_ERROR_NO_ERROR;
 }
 
 PVR_ERROR WaipuData::GetRecordings(bool deleted, kodi::addon::PVRRecordingsResultSet& results)
 {
-  if (!ApiLogin())
-  {
+  if (!IsConnected())
     return PVR_ERROR_SERVER_ERROR;
-  }
-  m_active_recordings_update = true;
-
-  std::string jsonRecordings = HttpGet("https://recording.waipu.tv/api/recordings",{{"Accept", "application/vnd.waipu.recordings-v2+json"}});
-  kodi::Log(ADDON_LOG_DEBUG, "[recordings] %s", jsonRecordings.c_str());
 
-  jsonRecordings = "{\"result\": " + jsonRecordings + "}";
+  m_active_recordings_update = true;
 
-  rapidjson::Document recordingsDoc;
-  recordingsDoc.Parse(jsonRecordings.c_str());
-  if (recordingsDoc.GetParseError())
   {
-    kodi::Log(ADDON_LOG_ERROR, "[GetRecordings] ERROR: error while parsing json");
-    return PVR_ERROR_SERVER_ERROR;
-  }
-  kodi::Log(ADDON_LOG_DEBUG, "[recordings] iterate entries");
+    std::string json = HttpGet("https://recording.waipu.tv/api/recordings",
+                               {{"Accept", "application/vnd.waipu.recordings-v2+json"}});
+    kodi::Log(ADDON_LOG_DEBUG, "[recordings] %s", json.c_str());
 
-  kodi::Log(ADDON_LOG_DEBUG, "[recordings] size: %i;", recordingsDoc["result"].Size());
+    rapidjson::Document doc;
+    doc.Parse(json.c_str());
+    if (doc.HasParseError())
+    {
+      kodi::Log(ADDON_LOG_ERROR, "[GetRecordings] ERROR: error while parsing json");
+      return PVR_ERROR_SERVER_ERROR;
+    }
+    kodi::Log(ADDON_LOG_DEBUG, "[recordings] iterate entries");
+    kodi::Log(ADDON_LOG_DEBUG, "[recordings] size: %i;", doc.Size());
 
-  int recordings_count = 0;
+    int recordings_count = 0;
 
-  for (const auto& recording : recordingsDoc["result"].GetArray())
-  {
-    // skip not FINISHED entries
-    std::string status = recording["status"].GetString();
-    if (status != "FINISHED")
-      continue;
+    for (const auto& recording : doc.GetArray())
+    {
+      // skip not FINISHED entries
+      std::string status = recording["status"].GetString();
+      if (status != "FINISHED")
+        continue;
 
-    // new tag
-    kodi::addon::PVRRecording tag;
+      kodi::addon::PVRRecording tag;
 
-    tag.SetIsDeleted(false);
+      tag.SetIsDeleted(false);
+      tag.SetRecordingId(recording["id"].GetString());
+      tag.SetPlayCount(recording.HasMember("watched") && recording["watched"].GetBool());
 
-    // set recording id
-    std::string rec_id = recording["id"].GetString();
-    tag.SetRecordingId(rec_id);
+      const rapidjson::Value& epgData = recording["epgData"];
 
-    // playcount
-    if (recording.HasMember("watched") && recording["watched"].GetBool())
-    {
-      tag.SetPlayCount(1);
-    }
-    else
-    {
-      tag.SetPlayCount(0);
-    }
+      const std::string rec_title = epgData["title"].GetString();
+      tag.SetTitle(rec_title);
+      tag.SetDirectory(rec_title);
 
-    const rapidjson::Value& epgData = recording["epgData"];
-
-    // set recording title
-    const std::string rec_title = epgData["title"].GetString();
-    tag.SetTitle(rec_title);
-    // set folder; test
-    tag.SetDirectory(rec_title);
-
-    // set image
-    if (epgData.HasMember("previewImages") && epgData["previewImages"].IsArray() &&
-        epgData["previewImages"].Size() > 0)
-    {
-      std::string rec_img = epgData["previewImages"][0].GetString();
-      rec_img = rec_img + "?width=256&height=256";
-      tag.SetIconPath(rec_img);
-      tag.SetThumbnailPath(rec_img);
-    }
+      if (epgData.HasMember("previewImages") && epgData["previewImages"].IsArray() &&
+          epgData["previewImages"].Size() > 0)
+      {
+        std::string rec_img =
+            std::string(epgData["previewImages"][0].GetString()) + "?width=256&height=256";
+        tag.SetIconPath(rec_img);
+        tag.SetThumbnailPath(rec_img);
+      }
 
-    // duration
-    if (epgData.HasMember("duration") && !epgData["duration"].IsNull())
-    {
-      const std::string rec_dur = epgData["duration"].GetString();
-      tag.SetDuration(Utils::StringToInt(rec_dur, 0) * 60);
-    }
+      if (epgData.HasMember("duration") && !epgData["duration"].IsNull())
+        tag.SetDuration(Utils::StringToInt(epgData["duration"].GetString(), 0) * 60);
 
-    // iSeriesNumber
-    if (epgData.HasMember("season") && !epgData["season"].IsNull())
-    {
-      tag.SetSeriesNumber(
-          Utils::StringToInt(epgData["season"].GetString(), PVR_RECORDING_INVALID_SERIES_EPISODE));
-    }
-    else
-    {
-      tag.SetSeriesNumber(PVR_RECORDING_INVALID_SERIES_EPISODE);
-    }
+      if (epgData.HasMember("season") && !epgData["season"].IsNull())
+        tag.SetSeriesNumber(Utils::StringToInt(epgData["season"].GetString(),
+                                               PVR_RECORDING_INVALID_SERIES_EPISODE));
 
-    // episodeNumber
-    if (epgData.HasMember("episode") && !epgData["episode"].IsNull())
-    {
-      tag.SetEpisodeNumber(
-          Utils::StringToInt(epgData["episode"].GetString(), PVR_RECORDING_INVALID_SERIES_EPISODE));
-    }
-    else
-    {
-      tag.SetEpisodeNumber(PVR_RECORDING_INVALID_SERIES_EPISODE);
-    }
+      if (epgData.HasMember("episode") && !epgData["episode"].IsNull())
+        tag.SetEpisodeNumber(Utils::StringToInt(epgData["episode"].GetString(),
+                                                PVR_RECORDING_INVALID_SERIES_EPISODE));
 
-    // episodeName
-    if (epgData.HasMember("episodeTitle") && !epgData["episodeTitle"].IsNull())
-    {
-      std::string rec_episodename = epgData["episodeTitle"].GetString();
-      tag.SetEpisodeName(rec_episodename);
-    }
+      if (epgData.HasMember("episodeTitle") && !epgData["episodeTitle"].IsNull())
+        tag.SetEpisodeName(epgData["episodeTitle"].GetString());
 
-    // year
-    if (epgData.HasMember("year") && !epgData["year"].IsNull())
-    {
-      const std::string rec_year = epgData["year"].GetString();
-      tag.SetYear(Utils::StringToInt(rec_year, 1970));
-    }
+      if (epgData.HasMember("year") && !epgData["year"].IsNull())
+        tag.SetYear(Utils::StringToInt(epgData["year"].GetString(), 1970));
 
-    // get recording time
-    if (recording.HasMember("startTime") && !recording["startTime"].IsNull())
-    {
-      const std::string recordingTime = recording["startTime"].GetString();
-      tag.SetRecordingTime(Utils::StringToTime(recordingTime));
-    }
+      if (recording.HasMember("startTime") && !recording["startTime"].IsNull())
+        tag.SetRecordingTime(Utils::StringToTime(recording["startTime"].GetString()));
 
-    // get plot
-    if (epgData.HasMember("description") && !epgData["description"].IsNull())
-    {
-      const std::string rec_plot = epgData["description"].GetString();
-      tag.SetPlot(rec_plot);
-    }
+      if (epgData.HasMember("description") && !epgData["description"].IsNull())
+        tag.SetPlot(epgData["description"].GetString());
 
-    // genre
-    if (epgData.HasMember("genreDisplayName") && !epgData["genreDisplayName"].IsNull())
-    {
-      std::string genreStr = epgData["genreDisplayName"].GetString();
-      int genre = m_categories.Category(genreStr);
-      if (genre)
+      if (epgData.HasMember("genreDisplayName") && !epgData["genreDisplayName"].IsNull())
       {
-        tag.SetGenreSubType(genre & 0x0F);
-        tag.SetGenreType(genre & 0xF0);
+        std::string genreStr = epgData["genreDisplayName"].GetString();
+        int genre = m_categories.Category(genreStr);
+        if (genre)
+        {
+          tag.SetGenreSubType(genre & 0x0F);
+          tag.SetGenreType(genre & 0xF0);
+        }
+        else
+        {
+          tag.SetGenreType(EPG_GENRE_USE_STRING);
+          tag.SetGenreSubType(0); /* not supported */
+          tag.SetGenreDescription(genreStr);
+        }
       }
-      else
+
+      // epg mapping
+      if (epgData.HasMember("id") && !epgData["id"].IsNull())
       {
-        tag.SetGenreType(EPG_GENRE_USE_STRING);
-        tag.SetGenreSubType(0); /* not supported */
-        tag.SetGenreDescription(genreStr);
+        std::string epg_id = epgData["id"].GetString();
+        int dirtyID = Utils::GetIDDirty(epg_id);
+        tag.SetEPGEventId(dirtyID);
       }
+
+      recordings_count++;
+      results.Add(tag);
     }
+    m_recordings_count = recordings_count;
+  }
 
-    // epg mapping
-    if (epgData.HasMember("id") && !epgData["id"].IsNull())
+  {
+    std::string json = HttpGet("https://recording.waipu.tv/api/recordings/summary",
+                               {{"Accept", "application/vnd.waipu.recording-summary-v2+json"}});
+    kodi::Log(ADDON_LOG_DEBUG, "[recordings summary] %s", json.c_str());
+    rapidjson::Document doc;
+    doc.Parse(json.c_str());
+    if (!doc.HasParseError() && doc.HasMember("finishedRecordingsSeconds"))
     {
-      std::string epg_id = epgData["id"].GetString();
-      int dirtyID = Utils::GetIDDirty(epg_id);
-      tag.SetEPGEventId(dirtyID);
+      m_finishedRecordingsSeconds = doc["finishedRecordingsSeconds"].GetInt();
     }
-
-    ++recordings_count;
-    results.Add(tag);
   }
-  m_recordings_count = recordings_count;
+
   m_active_recordings_update = false;
 
   return PVR_ERROR_NO_ERROR;
@@ -1518,8 +1543,6 @@ PVR_ERROR WaipuData::GetRecordings(bool deleted, kodi::addon::PVRRecordingsResul
 std::string WaipuData::GetRecordingURL(const kodi::addon::PVRRecording& recording,
                                        const std::string& protocol)
 {
-  ApiLogin();
-
   std::string recording_id = recording.GetRecordingId();
   kodi::Log(ADDON_LOG_DEBUG, "play recording -> %s", recording_id.c_str());
 
@@ -1531,14 +1554,14 @@ std::string WaipuData::GetRecordingURL(const kodi::addon::PVRRecording& recordin
   if (recordingDoc.GetParseError())
   {
     kodi::Log(ADDON_LOG_ERROR, "[getRecordingURL] ERROR: error while parsing json");
-    return {};
+    return "";
   }
   kodi::Log(ADDON_LOG_DEBUG, "[recording] streams");
   // check if streams there
   if (!recordingDoc.HasMember("streamingDetails") ||
       !recordingDoc["streamingDetails"].HasMember("streams"))
   {
-    return {};
+    return "";
   }
 
   kodi::Log(ADDON_LOG_DEBUG, "[recordings] size: %i;",
@@ -1557,22 +1580,23 @@ std::string WaipuData::GetRecordingURL(const kodi::addon::PVRRecording& recordin
       return href;
     }
   }
-  return {};
+  return "";
 }
 
 PVR_ERROR WaipuData::DeleteRecording(const kodi::addon::PVRRecording& recording)
 {
-  if (ApiLogin())
-  {
-    std::string recording_id = recording.GetRecordingId();
-    std::string request_data = "{\"ids\":[\"" + recording_id + "\"]}";
-    kodi::Log(ADDON_LOG_DEBUG, "[delete recording] req: %s;", request_data.c_str());
-    std::string deleted = HttpDelete("https://recording.waipu.tv/api/recordings", request_data.c_str(), {{"Content-Type","application/vnd.waipu.pvr-recording-ids-v2+json"}});
-    kodi::Log(ADDON_LOG_DEBUG, "[delete recording] response: %s;", deleted.c_str());
-    kodi::addon::CInstancePVRClient::TriggerRecordingUpdate();
-    return PVR_ERROR_NO_ERROR;
-  }
-  return PVR_ERROR_FAILED;
+  if (!IsConnected())
+    return PVR_ERROR_FAILED;
+
+  std::string recording_id = recording.GetRecordingId();
+  std::string request_data = "{\"ids\":[\"" + recording_id + "\"]}";
+  kodi::Log(ADDON_LOG_DEBUG, "[delete recording] req: %s;", request_data.c_str());
+  std::string deleted =
+      HttpDelete("https://recording.waipu.tv/api/recordings", request_data.c_str(),
+                 {{"Content-Type", "application/vnd.waipu.pvr-recording-ids-v2+json"}});
+  kodi::Log(ADDON_LOG_DEBUG, "[delete recording] response: %s;", deleted.c_str());
+  kodi::addon::CInstancePVRClient::TriggerRecordingUpdate();
+  return PVR_ERROR_NO_ERROR;
 }
 
 PVR_ERROR WaipuData::GetRecordingStreamProperties(
@@ -1583,7 +1607,8 @@ PVR_ERROR WaipuData::GetRecordingStreamProperties(
   LoadChannelData();
 
   std::string protocol = m_protocol;
-  if (protocol == "auto") protocol = "dash"; //fallback to dash
+  if (protocol == "auto")
+    protocol = "dash"; //fallback to dash
 
   std::string strUrl = GetRecordingURL(recording, protocol);
   if (strUrl.empty())
@@ -1607,26 +1632,30 @@ void WaipuData::AddTimerType(std::vector<kodi::addon::PVRTimerType>& types, int
 PVR_ERROR WaipuData::GetTimerTypes(std::vector<kodi::addon::PVRTimerType>& types)
 {
   AddTimerType(types, 1, PVR_TIMER_TYPE_REQUIRES_EPG_TAG_ON_CREATE);
-  AddTimerType(types, 2, PVR_TIMER_TYPE_REQUIRES_EPG_SERIES_ON_CREATE | PVR_TIMER_TYPE_IS_REPEATING );
+  AddTimerType(types, 2,
+               PVR_TIMER_TYPE_REQUIRES_EPG_SERIES_ON_CREATE | PVR_TIMER_TYPE_IS_REPEATING);
 
   return PVR_ERROR_NO_ERROR;
 }
 
 PVR_ERROR WaipuData::GetTimersAmount(int& amount)
 {
+  if (!IsConnected())
+    return PVR_ERROR_SERVER_ERROR;
+
   amount = m_timers_count;
   return PVR_ERROR_NO_ERROR;
 }
 
 PVR_ERROR WaipuData::GetTimers(kodi::addon::PVRTimersResultSet& results)
 {
-  if (!ApiLogin())
-  {
+  if (!IsConnected())
     return PVR_ERROR_SERVER_ERROR;
-  }
+
   LoadChannelData();
 
-  std::string jsonRecordings = HttpGet("https://recording.waipu.tv/api/recordings", {{"Accept", "application/vnd.waipu.recordings-v2+json"}});
+  std::string jsonRecordings = HttpGet("https://recording.waipu.tv/api/recordings",
+                                       {{"Accept", "application/vnd.waipu.recordings-v2+json"}});
   kodi::Log(ADDON_LOG_DEBUG, "[Timers] %s", jsonRecordings.c_str());
 
   jsonRecordings = "{\"result\": " + jsonRecordings + "}";
@@ -1695,22 +1724,22 @@ PVR_ERROR WaipuData::GetTimers(kodi::addon::PVRTimersResultSet& results)
     if (timer.HasMember("recordingGroup"))
     {
 
-	int group = timer["recordingGroup"].GetInt();
-	tag.SetRecordingGroup(group);
-	if (std::find(timerGroups.begin(), timerGroups.end(), group) == timerGroups.end())
-	{
-	  // add group
-	  kodi::addon::PVRTimer tagGroup;
-	  tagGroup.SetTimerType(2);
-	  tagGroup.SetTitle(rec_title);
-	  tagGroup.SetClientIndex(group);
-	  tagGroup.SetClientChannelUid(tag_channel);
-	  tag.SetRecordingGroup(group);
-	  kodi::Log(ADDON_LOG_DEBUG, "[add timer group] group: %i;", group);
-
-	  results.Add(tagGroup);
-	  timerGroups.emplace_back(group);
-	}
+      int group = timer["recordingGroup"].GetInt();
+      tag.SetRecordingGroup(group);
+      if (std::find(timerGroups.begin(), timerGroups.end(), group) == timerGroups.end())
+      {
+        // add group
+        kodi::addon::PVRTimer tagGroup;
+        tagGroup.SetTimerType(2);
+        tagGroup.SetTitle(rec_title);
+        tagGroup.SetClientIndex(group);
+        tagGroup.SetClientChannelUid(tag_channel);
+        tag.SetRecordingGroup(group);
+        kodi::Log(ADDON_LOG_DEBUG, "[add timer group] group: %i;", group);
+
+        results.Add(tagGroup);
+        timerGroups.emplace_back(group);
+      }
     }
 
     tag.SetTimerType(1);
@@ -1764,88 +1793,134 @@ PVR_ERROR WaipuData::GetTimers(kodi::addon::PVRTimersResultSet& results)
 
 PVR_ERROR WaipuData::DeleteTimer(const kodi::addon::PVRTimer& timer, bool forceDelete)
 {
-  if (ApiLogin())
+  if (!IsConnected())
+    return PVR_ERROR_FAILED;
+
+  if (timer.GetTimerType() == 1)
+  {
+    // single tag
+    int timer_id = timer.GetClientIndex();
+    std::string request_data = "{\"ids\":[\"" + std::to_string(timer_id) + "\"]}";
+    kodi::Log(ADDON_LOG_DEBUG, "[delete single timer] req: %s;", request_data.c_str());
+    std::string deleted =
+        HttpDelete("https://recording.waipu.tv/api/recordings", request_data.c_str(),
+                   {{"Content-Type", "application/vnd.waipu.pvr-recording-ids-v2+json"}});
+    kodi::Log(ADDON_LOG_DEBUG, "[delete single timer] response: %s;", deleted.c_str());
+    kodi::QueueNotification(QUEUE_INFO, "Recording", "Recording Deleted");
+    kodi::addon::CInstancePVRClient::TriggerRecordingUpdate();
+    kodi::addon::CInstancePVRClient::TriggerTimerUpdate();
+    return PVR_ERROR_NO_ERROR;
+  }
+  else
   {
-      LoadChannelData();
+    // delete record series
+    int groupID = timer.GetClientIndex();
+    std::string request_data = "{\"serialRecordings\":[{\"id\":" + std::to_string(groupID) +
+                               ",\"deleteFutureRecordings\":true,\"deleteFinishedRecordings\":"
+                               "false,\"deleteRunningRecordingss\":false}]}";
+    kodi::Log(ADDON_LOG_DEBUG, "[delete multi timer] req (group: %i): %s;", groupID,
+              request_data.c_str());
+    std::string deleted =
+        HttpPost("https://recording-scheduler.waipu.tv/api/delete-requests", request_data.c_str(),
+                 {{"Content-Type",
+                   "application/vnd.waipu.recording-scheduler-delete-serial-recordings-v1+json"}});
+    kodi::Log(ADDON_LOG_DEBUG, "[delete multi timer] response: %s;", deleted.c_str());
+    kodi::QueueNotification(QUEUE_INFO, "Recording", "Rule Deleted");
+    kodi::addon::CInstancePVRClient::TriggerRecordingUpdate();
+    kodi::addon::CInstancePVRClient::TriggerTimerUpdate();
+    return PVR_ERROR_NO_ERROR;
+  }
+}
+
+PVR_ERROR WaipuData::AddTimer(const kodi::addon::PVRTimer& timer)
+{
+  // we currently only support epg based
+  if (timer.GetEPGUid() <= EPG_TAG_INVALID_UID)
+    return PVR_ERROR_REJECTED;
+
+  if (!IsConnected())
+    return PVR_ERROR_FAILED;
+
+  for (const auto& channel : m_channels)
+  {
+    if (channel.iUniqueId != timer.GetClientChannelUid())
+      continue;
+
     if (timer.GetTimerType() == 1)
     {
-      // single tag
-      int timer_id = timer.GetClientIndex();
-      std::string request_data = "{\"ids\":[\"" + std::to_string(timer_id) + "\"]}";
-      kodi::Log(ADDON_LOG_DEBUG, "[delete single timer] req: %s;", request_data.c_str());
-      std::string deleted = HttpDelete("https://recording.waipu.tv/api/recordings", request_data.c_str(),{{"Content-Type", "application/vnd.waipu.pvr-recording-ids-v2+json"}});
-      kodi::Log(ADDON_LOG_DEBUG, "[delete single timer] response: %s;", deleted.c_str());
-      kodi::QueueNotification(QUEUE_INFO, "Recording", "Recording Deleted");
-      kodi::addon::CInstancePVRClient::TriggerRecordingUpdate();
+      // record single element
+      kodi::Log(ADDON_LOG_DEBUG, "[add timer] Record single tag;");
+      // {"programId":"_1051966761","channelId":"PRO7","startTime":"2019-02-03T18:05:00.000Z","stopTime":"2019-02-03T19:15:00.000Z"}
+      std::string postData = "{\"programId\":\"_" + std::to_string(timer.GetEPGUid()) +
+                             "\",\"channelId\":\"" + channel.waipuID + "\"" + "}";
+      std::string recordResp =
+          HttpPost("https://recording.waipu.tv/api/recordings", postData,
+                   {{"Content-Type", "application/vnd.waipu.start-recording-v2+json"}});
+      kodi::Log(ADDON_LOG_DEBUG, "[add timer] single response: %s;", recordResp.c_str());
+      kodi::QueueNotification(QUEUE_INFO, "Recording", "Recording Created");
       kodi::addon::CInstancePVRClient::TriggerTimerUpdate();
-      return PVR_ERROR_NO_ERROR;
-    }else{
-      // delete record series
-      int groupID = timer.GetClientIndex();
-      std::string request_data = "{\"serialRecordings\":[{\"id\":" + std::to_string(groupID) + ",\"deleteFutureRecordings\":true,\"deleteFinishedRecordings\":false,\"deleteRunningRecordingss\":false}]}";
-      kodi::Log(ADDON_LOG_DEBUG, "[delete multi timer] req (group: %i): %s;", groupID, request_data.c_str());
-      std::string deleted = HttpPost("https://recording-scheduler.waipu.tv/api/delete-requests", request_data.c_str(),{{"Content-Type", "application/vnd.waipu.recording-scheduler-delete-serial-recordings-v1+json"}});
-      kodi::Log(ADDON_LOG_DEBUG, "[delete multi timer] response: %s;", deleted.c_str());
-      kodi::QueueNotification(QUEUE_INFO, "Recording", "Rule Deleted");
+    }
+    else
+    {
+      // record series
+      kodi::Log(ADDON_LOG_DEBUG, "[add timer] Record single tag;");
+      // {"title":"Das A-Team","channel":"RTLNITRO"}
+      std::string postData =
+          "{\"title\": \"" + timer.GetTitle() + "\",\"channel\":\"" + channel.waipuID + "\"" + "}";
+      std::string recordResp =
+          HttpPost("https://recording-scheduler.waipu.tv/api/serials", postData,
+                   {{"Content-Type", "application/vnd.waipu.recording-scheduler-serials-v1+json"}});
+      kodi::Log(ADDON_LOG_DEBUG, "[add timer] repeating response: %s;", recordResp.c_str());
+      kodi::QueueNotification(QUEUE_INFO, "Recording", "Rule Created");
       kodi::addon::CInstancePVRClient::TriggerRecordingUpdate();
       kodi::addon::CInstancePVRClient::TriggerTimerUpdate();
-      return PVR_ERROR_NO_ERROR;
     }
   }
-  return PVR_ERROR_FAILED;
+  return PVR_ERROR_NO_ERROR;
 }
 
-PVR_ERROR WaipuData::AddTimer(const kodi::addon::PVRTimer& timer)
+WaipuData::~WaipuData()
 {
-  if (timer.GetEPGUid() <= EPG_TAG_INVALID_UID)
+  m_loginThreadRunning = false;
+  if (m_loginThread.joinable())
+    m_loginThread.join();
+}
+
+ADDON_STATUS WaipuData::Create()
+{
+  kodi::Log(ADDON_LOG_DEBUG, "%s - Creating the waipu.tv PVR add-on", __FUNCTION__);
+
+  // set User-Agent
+  std::string ua = kodi::network::GetUserAgent();
+  // use our replace, since kodi utils replaces all occurrences
+  WAIPU_USER_AGENT =
+      Utils::Replace(ua, " ", std::string(" pvr.waipu/").append(STR(IPTV_VERSION)).append(" "));
+
+  ReadSettings();
+
+  if (m_provider == WAIPU_PROVIDER_WAIPU && (m_username.empty() || m_password.empty()))
   {
-    // we currently only support epg based
-    return PVR_ERROR_REJECTED;
+    kodi::QueueNotification(QUEUE_ERROR, "", kodi::addon::GetLocalizedString(30033));
+    return ADDON_STATUS_NEED_SETTINGS;
   }
 
-  if (ApiLogin())
-  {
-      LoadChannelData();
-    for (const auto& channel : m_channels)
-    {
-      if (channel.iUniqueId != timer.GetClientChannelUid())
-        continue;
+  m_loginThreadRunning = true;
+  m_loginThread = std::thread([&] { LoginThread(); });
 
-      if (timer.GetTimerType() == 1)
-      {
-        // record single element
-        kodi::Log(ADDON_LOG_DEBUG, "[add timer] Record single tag;");
-        // {"programId":"_1051966761","channelId":"PRO7","startTime":"2019-02-03T18:05:00.000Z","stopTime":"2019-02-03T19:15:00.000Z"}
-        std::string postData = "{\"programId\":\"_" + std::to_string(timer.GetEPGUid()) +
-                          "\",\"channelId\":\"" + channel.waipuID + "\"" + "}";
-        std::string recordResp = HttpPost("https://recording.waipu.tv/api/recordings", postData, {{"Content-Type", "application/vnd.waipu.start-recording-v2+json"}});
-        kodi::Log(ADDON_LOG_DEBUG, "[add timer] single response: %s;", recordResp.c_str());
-        kodi::QueueNotification(QUEUE_INFO, "Recording", "Recording Created");
-        kodi::addon::CInstancePVRClient::TriggerTimerUpdate();
-        return PVR_ERROR_NO_ERROR;
-      }else{
-        // record series
-        kodi::Log(ADDON_LOG_DEBUG, "[add timer] Record single tag;");
-        // {"title":"Das A-Team","channel":"RTLNITRO"}
-        std::string postData = "{\"title\": \"" + timer.GetTitle() +
-                          "\",\"channel\":\"" + channel.waipuID + "\"" + "}";
-        std::string recordResp = HttpPost("https://recording-scheduler.waipu.tv/api/serials", postData, {{"Content-Type", "application/vnd.waipu.recording-scheduler-serials-v1+json"}});
-        kodi::Log(ADDON_LOG_DEBUG, "[add timer] repeating response: %s;", recordResp.c_str());
-        kodi::QueueNotification(QUEUE_INFO, "Recording", "Rule Created");
-        kodi::addon::CInstancePVRClient::TriggerRecordingUpdate();
-        kodi::addon::CInstancePVRClient::TriggerTimerUpdate();
-        return PVR_ERROR_NO_ERROR;
-      }
-    }
-  }
-  return PVR_ERROR_FAILED;
+  kodi::addon::CInstancePVRClient::ConnectionStateChange("Initializing",
+                                                         PVR_CONNECTION_STATE_CONNECTING, "");
+
+  return ADDON_STATUS_OK;
 }
 
 PVR_ERROR WaipuData::GetDriveSpace(uint64_t& total, uint64_t& used)
 {
-  ApiLogin();
+  if (!IsConnected())
+    return PVR_ERROR_SERVER_ERROR;
+
   total = m_account_hours_recording * 1024 * 1024;
-  used =  0;
+  used = m_finishedRecordingsSeconds > 0 ? m_finishedRecordingsSeconds * 1024 * 1024 / 3600 : 0;
+
   return PVR_ERROR_NO_ERROR;
 }
 
diff --git a/src/WaipuData.h b/src/WaipuData.h
index 70d1445..4d66786 100644
--- a/src/WaipuData.h
+++ b/src/WaipuData.h
@@ -20,15 +20,17 @@
  *
  */
 
-#include "categories.h"
 #include "Curl.h"
 #include "HLSAllowlist.h"
-#include "kodi/addon-instance/PVR.h"
-#include "kodi/Network.h"
 #include "JWT.h"
+#include "categories.h"
+#include "kodi/Network.h"
+#include "kodi/addon-instance/PVR.h"
 
-#include <mutex>
+#include <atomic>
 #include <map>
+#include <mutex>
+#include <thread>
 #include <vector>
 
 // User Agent for HTTP Requests
@@ -42,6 +44,14 @@ enum WAIPU_PROVIDER
   WAIPU_PROVIDER_WAIPU_DEVICE = 2
 };
 
+enum WAIPU_CHANNEL_IMPORT_FILTER
+{
+  CHANNEL_FILTER_ALL_VISIBLE = 0,
+  CHANNEL_FILTER_ALL = 1,
+  CHANNEL_FILTER_FAVOURITES = 2,
+  CHANNEL_FILTER_LIVE = 3
+};
+
 enum class WAIPU_LOGIN_STATUS
 {
   OK,
@@ -60,6 +70,8 @@ public:
   WaipuData() = default;
   WaipuData(const WaipuData&) = delete;
   WaipuData(WaipuData&&) = delete;
+  ~WaipuData();
+
   WaipuData& operator=(const WaipuData&) = delete;
   WaipuData& operator=(WaipuData&&) = delete;
 
@@ -107,6 +119,13 @@ public:
   PVR_ERROR GetDriveSpace(uint64_t& total, uint64_t& used) override;
 
 private:
+  bool m_isConnected = false;
+  bool m_epg_show_preview_images = false;
+  std::atomic<bool> m_loginThreadRunning = {false};
+  std::thread m_loginThread;
+  void LoginThread();
+  int m_nextLoginAttempt = 0;
+  WAIPU_CHANNEL_IMPORT_FILTER m_channel_filter = WAIPU_CHANNEL_IMPORT_FILTER::CHANNEL_FILTER_ALL_VISIBLE;
 
   struct WaipuChannel
   {
@@ -147,6 +166,7 @@ private:
   bool m_active_recordings_update = false;
   bool m_account_replay_allowed = false;
   int m_account_hours_recording = 0;
+  uint64_t m_finishedRecordingsSeconds = 0;
   std::vector<std::string> m_user_channels_sd;
   std::vector<std::string> m_user_channels_hd;
   WAIPU_LOGIN_STATUS m_login_status = WAIPU_LOGIN_STATUS::UNKNOWN;
@@ -158,27 +178,42 @@ private:
 
   void AddTimerType(std::vector<kodi::addon::PVRTimerType>& types, int idx, int attributes);
 
-  std::string GetChannelStreamURL(int uniqueId, const std::string& protocol, const std::string& startTime);
+  std::string GetChannelStreamURL(int uniqueId,
+                                  const std::string& protocol,
+                                  const std::string& startTime);
   std::string GetRecordingURL(const kodi::addon::PVRRecording& recording,
                               const std::string& protocol);
   std::string GetEPGTagURL(const kodi::addon::PVREPGTag& tag, const std::string& protocol);
   std::string GetLicense();
-  const std::map<std::string,std::string> GetOAuthDeviceCode(const std::string& tenant);
-  const std::map<std::string,std::string> CheckOAuthState(const std::string& device_code);
+  const std::map<std::string, std::string> GetOAuthDeviceCode(const std::string& tenant);
+  const std::map<std::string, std::string> CheckOAuthState(const std::string& device_code);
   void SetStreamProperties(std::vector<kodi::addon::PVRStreamProperty>& properties,
                            const std::string& url,
-                           bool realtime, bool playTimeshiftBuffer, const std::string& protocol);
-
-  std::string HttpGet(const std::string& url, const std::map<std::string,std::string>& headers = {});
-  std::string HttpDelete(const std::string& url, const std::string& postData, const std::map<std::string,std::string>& headers = {});
-  std::string HttpPost(const std::string& url, const std::string& postData, const std::map<std::string,std::string>& headers = {});
-  std::string HttpRequest(const std::string& action, const std::string& url, const std::string& postData, const std::map<std::string,std::string>& headers = {});
-  std::string HttpRequestToCurl(
-      Curl& curl, const std::string& action, const std::string& url, const std::string& postData, int& statusCode);
-  bool ApiLogin();
-  bool WaipuLogin();
-  bool DeviceLogin(const std::string& tenant);
-  bool OAuthRequest(const std::string& postData);
+                           bool realtime,
+                           bool playTimeshiftBuffer,
+                           const std::string& protocol);
+
+  std::string HttpGet(const std::string& url,
+                      const std::map<std::string, std::string>& headers = {});
+  std::string HttpDelete(const std::string& url,
+                         const std::string& postData,
+                         const std::map<std::string, std::string>& headers = {});
+  std::string HttpPost(const std::string& url,
+                       const std::string& postData,
+                       const std::map<std::string, std::string>& headers = {});
+  std::string HttpRequest(const std::string& action,
+                          const std::string& url,
+                          const std::string& postData,
+                          const std::map<std::string, std::string>& headers = {});
+  std::string HttpRequestToCurl(Curl& curl,
+                                const std::string& action,
+                                const std::string& url,
+                                const std::string& postData,
+                                int& statusCode);
+  bool IsConnected();
+  WAIPU_LOGIN_STATUS Login();
+  WAIPU_LOGIN_STATUS DeviceLogin(const std::string& tenant);
+  WAIPU_LOGIN_STATUS OAuthRequest(const std::string& postData);
   bool LoadChannelData();
   bool RefreshDeviceCapabiltiesToken();
 };
diff --git a/src/categories.cpp b/src/categories.cpp
index d0ed4bc..09b4352 100644
--- a/src/categories.cpp
+++ b/src/categories.cpp
@@ -22,12 +22,14 @@
 // Code taken from pvr.zattoo
 
 #include "categories.h"
+
 #include <cstring>
 #include <iostream>
-#include <kodi/Filesystem.h>
 #include <regex>
 
-#define CATEGORIES_MAXLINESIZE    255
+#include <kodi/Filesystem.h>
+
+#define CATEGORIES_MAXLINESIZE 255
 
 #if defined(_WIN32) || defined(_WIN64)
 /* We are on Windows */
@@ -35,10 +37,9 @@
 #define strdup _strdup
 #endif
 
-Categories::Categories() :
-    m_categoriesById()
+Categories::Categories() : m_categoriesById()
 {
-  char *saveptr;
+  char* saveptr;
   LoadEITCategories();
   // Copy over
   CategoryByIdMap::const_iterator it;
@@ -47,8 +48,8 @@ Categories::Categories() :
     m_categoriesByName[it->second] = it->first;
     if (it->second.find("/") != std::string::npos)
     {
-      char *categories = strdup(it->second.c_str());
-      char *p = strtok_r(categories, "/", &saveptr);
+      char* categories = strdup(it->second.c_str());
+      char* p = strtok_r(categories, "/", &saveptr);
       while (p != nullptr)
       {
         std::string category = p;
@@ -70,28 +71,29 @@ std::string Categories::Category(int category) const
 
 int Categories::Category(const std::string& category)
 {
-  if (category.empty()) {
+  if (category.empty())
+  {
     return 0;
   }
   auto it = m_categoriesByName.find(category);
   if (it != m_categoriesByName.end())
     return it->second;
   kodi::Log(ADDON_LOG_INFO, "Missing category: %s", category.c_str());
-  m_categoriesByName[category]=0;
+  m_categoriesByName[category] = 0;
   return 0;
 }
 
 void Categories::LoadEITCategories()
 {
-  const char *filePath = "special://home/addons/pvr.waipu/resources/eit_categories.txt";
-  if (!kodi::vfs::FileExists(filePath, false)) {
+  const char* filePath = "special://home/addons/pvr.waipu/resources/eit_categories.txt";
+  if (!kodi::vfs::FileExists(filePath, false))
+  {
     filePath = "special://xbmc/addons/pvr.waipu/resources/eit_categories.txt";
   }
 
   if (kodi::vfs::FileExists(filePath, false))
   {
-    kodi::Log(ADDON_LOG_DEBUG, "%s: Loading EIT categories from file '%s'",
-        __FUNCTION__, filePath);
+    kodi::Log(ADDON_LOG_DEBUG, "%s: Loading EIT categories from file '%s'", __FUNCTION__, filePath);
     kodi::vfs::CFile file;
     if (!file.OpenFile(filePath, 0))
     {
@@ -110,8 +112,8 @@ void Categories::LoadEITCategories()
         std::string name = matches[2].str();
 
         m_categoriesById.insert(std::pair<int, std::string>(catId, name));
-        kodi::Log(ADDON_LOG_DEBUG, "%s: Add name [%s] for category %.2X",
-            __FUNCTION__, name.c_str(), catId);
+        kodi::Log(ADDON_LOG_DEBUG, "%s: Add name [%s] for category %.2X", __FUNCTION__,
+                  name.c_str(), catId);
       }
     }
   }
diff --git a/src/categories.h b/src/categories.h
index b68bd1d..f1b854a 100644
--- a/src/categories.h
+++ b/src/categories.h
@@ -22,8 +22,8 @@
  */
 // Code taken from pvr.zattoo
 
-#include <string>
 #include <map>
+#include <string>
 
 typedef std::multimap<int, std::string> CategoryByIdMap;
 typedef std::map<std::string, int> CategoryByNameMap;

Debdiff

[The following lists of changes regard files as different if they have different names, permissions or owners.]

Files in second set of .debs but not in first

-rw-r--r--  root/root   /usr/lib/debug/.build-id/50/17808f61b8b19fd43c30bd51981477e7d0135a.debug
-rw-r--r--  root/root   /usr/lib/x86_64-linux-gnu/kodi/addons/pvr.waipu/pvr.waipu.so.20.9.0
-rw-r--r--  root/root   /usr/share/kodi/addons/pvr.waipu/resources/language/resource.language.ast_es/strings.po
lrwxrwxrwx  root/root   /usr/lib/x86_64-linux-gnu/kodi/addons/pvr.waipu/pvr.waipu.so.20.2 -> pvr.waipu.so.20.9.0

Files in first set of .debs but not in second

-rw-r--r--  root/root   /usr/lib/debug/.build-id/4b/db3e85a47a8d9adf953447ee535aeda0e34507.debug
-rw-r--r--  root/root   /usr/lib/x86_64-linux-gnu/kodi/addons/pvr.waipu/pvr.waipu.so.20.6.0
lrwxrwxrwx  root/root   /usr/lib/x86_64-linux-gnu/kodi/addons/pvr.waipu/pvr.waipu.so.20.2 -> pvr.waipu.so.20.6.0

No differences were encountered between the control files of package kodi-pvr-waipu

Control files of package kodi-pvr-waipu-dbgsym: lines which differ (wdiff format)

  • Build-Ids: 4bdb3e85a47a8d9adf953447ee535aeda0e34507 5017808f61b8b19fd43c30bd51981477e7d0135a

More details

Full run details