pax_global_header00006660000000000000000000000064136027465010014516gustar00rootroot0000000000000052 comment=fac4f704b83bff5f266b405a4693eef602f63e6e pvr.nextpvr-3.3.18-Leia/000077500000000000000000000000001360274650100147765ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/.gitignore000066400000000000000000000007161360274650100167720ustar00rootroot00000000000000# build artifacts build/ debian/changelog debian/files debian/kodi-pvr-nextpvr-dbg.debhelper.log debian/kodi-pvr-nextpvr-dbg.substvars debian/kodi-pvr-nextpvr-dbg/ debian/kodi-pvr-nextpvr.debhelper.log debian/kodi-pvr-nextpvr.postinst.debhelper debian/kodi-pvr-nextpvr.postrm.debhelper debian/kodi-pvr-nextpvr.substvars debian/kodi-pvr-nextpvr/ debian/tmp/ obj-x86_64-linux-gnu/ pvr.nextpvr/addon.xml # clion .idea/ # Eclipse/CDT .cproject .project .settings/ pvr.nextpvr-3.3.18-Leia/.travis.yml000066400000000000000000000022241360274650100171070ustar00rootroot00000000000000language: cpp # # Define the build matrix # # Travis defaults to building on Ubuntu Trusty when building on # Linux. We need Xenial in order to get up to date versions of # cmake and g++. # env: global: - app_id=pvr.nextpvr matrix: include: - os: linux dist: xenial sudo: required compiler: gcc - os: linux dist: xenial sudo: required compiler: clang - os: osx osx_image: xcode9 - os: osx osx_image: xcode9.4 # # The addon source is automatically checked out in $TRAVIS_BUILD_DIR, # we'll put the Kodi source on the same level # before_script: - cd $TRAVIS_BUILD_DIR/.. - git clone --branch Leia --depth=1 https://github.com/xbmc/xbmc.git - cd ${app_id} && mkdir build && cd build - mkdir -p definition/${app_id} - echo ${app_id} $TRAVIS_BUILD_DIR $TRAVIS_COMMIT > definition/${app_id}/${app_id}.txt - cmake -DADDONS_TO_BUILD=${app_id} -DADDON_SRC_PREFIX=$TRAVIS_BUILD_DIR/.. -DADDONS_DEFINITION_DIR=$TRAVIS_BUILD_DIR/build/definition -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=$TRAVIS_BUILD_DIR/../xbmc/addons -DPACKAGE_ZIP=1 $TRAVIS_BUILD_DIR/../xbmc/cmake/addons script: make pvr.nextpvr-3.3.18-Leia/CMakeLists.txt000066400000000000000000000040211360274650100175330ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.5) project(pvr.nextpvr) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}) find_package(Kodi REQUIRED) find_package(kodiplatform REQUIRED) find_package(p8-platform REQUIRED) find_package(TinyXML REQUIRED) include_directories(${kodiplatform_INCLUDE_DIRS} ${p8-platform_INCLUDE_DIRS} ${TINYXML_INCLUDE_DIR} ${KODI_INCLUDE_DIR}/..) # Hack way with "/..", need bigger Kodi cmake rework to match right include ways set(NEXTPVR_SOURCES src/client.cpp src/md5.cpp src/pvrclient-nextpvr.cpp src/Socket.cpp src/uri.cpp src/BackendRequest.cpp src/buffers/Buffer.cpp src/buffers/DummyBuffer.cpp src/buffers/ClientTimeshift.cpp src/buffers/TimeshiftBuffer.cpp src/buffers/RecordingBuffer.cpp src/buffers/CircularBuffer.cpp src/buffers/RollingFile.cpp src/buffers/Seeker.cpp) set(NEXTPVR_HEADERS src/client.h src/FileUtils.h src/md5.h src/os-dependent.h src/pvrclient-nextpvr.h src/Socket.h src/uri.h src/BackendRequest.h src/buffers/Buffer.h src/buffers/DummyBuffer.h src/buffers/ClientTimeshift.h src/buffers/TimeshiftBuffer.h src/buffers/RecordingBuffer.h src/buffers/CircularBuffer.h src/buffers/RollingFile.h src/buffers/Seeker.h) SET(DEPLIBS ${p8-platform_LIBRARIES} ${kodiplatform_LIBRARIES} ${TINYXML_LIBRARIES}) if(WIN32) list(APPEND DEPLIBS ws2_32) add_definitions(/D_WINSOCK_DEPRECATED_NO_WARNINGS) endif() build_addon(pvr.nextpvr NEXTPVR DEPLIBS) include(CPack) pvr.nextpvr-3.3.18-Leia/FindTinyXML.cmake000066400000000000000000000015311360274650100201050ustar00rootroot00000000000000# - Find TinyXML # Find the native TinyXML includes and library # # TINYXML_FOUND - True if TinyXML found. # TINYXML_INCLUDE_DIRS - where to find tinyxml.h, etc. # TINYXML_LIBRARIES - List of libraries when using TinyXML. # find_package(PkgConfig) if(PKG_CONFIG_FOUND) pkg_check_modules(PC_TINYXML tinyxml QUIET) endif() find_path(TINYXML_INCLUDE_DIRS NAMES tinyxml.h PATHS ${PC_TINYXML_INCLUDEDIR} PATH_SUFFIXES tinyxml) find_library(TINYXML_LIBRARIES NAMES tinyxml PATHS ${PC_TINYXML_LIBDIR} PATH_SUFFIXES tinyxml) include("FindPackageHandleStandardArgs") find_package_handle_standard_args(TinyXML REQUIRED_VARS TINYXML_INCLUDE_DIRS TINYXML_LIBRARIES) mark_as_advanced(TINYXML_INCLUDE_DIRS TINYXML_LIBRARIES) pvr.nextpvr-3.3.18-Leia/Jenkinsfile000066400000000000000000000000351360274650100171600ustar00rootroot00000000000000buildPlugin(version: "Leia") pvr.nextpvr-3.3.18-Leia/README.md000066400000000000000000000020551360274650100162570ustar00rootroot00000000000000[![Build Status](https://travis-ci.org/kodi-pvr/pvr.nextpvr.svg?branch=Leia)](https://travis-ci.org/kodi-pvr/pvr.nextpvr/branches) [![Build Status](https://ci.appveyor.com/api/projects/status/github/kodi-pvr/pvr.nextpvr?branch=Leia&svg=true)](https://ci.appveyor.com/project/kodi-pvr/pvr-nextpvr?branch=Leia) [![Coverity Scan Build Status](https://scan.coverity.com/projects/5120/badge.svg)](https://scan.coverity.com/projects/5120) # NextPVR PVR NextPVR PVR client addon for [Kodi] (https://kodi.tv) ## Build instructions ### Linux 1. `git clone --branch Leia https://github.com/xbmc/xbmc.git` 2. `git clone https://github.com/kodi-pvr/pvr.nextpvr.git` 3. `cd pvr.nextpvr && mkdir build && cd build` 4. `cmake -DADDONS_TO_BUILD=pvr.nextpvr -DADDON_SRC_PREFIX=../.. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=../../xbmc/addons -DPACKAGE_ZIP=1 ../../xbmc/cmake/addons` 5. `make` ##### Useful links * [Kodi's PVR user support] (https://forum.kodi.tv/forumdisplay.php?fid=167) * [Kodi's PVR development support] (https://forum.kodi.tv/forumdisplay.php?fid=136) pvr.nextpvr-3.3.18-Leia/appveyor.yml000066400000000000000000000022431360274650100173670ustar00rootroot00000000000000version: BuildNr.{build} image: Visual Studio 2015 shallow_clone: true clone_folder: c:\projects\pvr.nextpvr environment: app_id: pvr.nextpvr matrix: - GENERATOR: "Visual Studio 14" CONFIG: Release - GENERATOR: "Visual Studio 14 Win64" CONFIG: Release - GENERATOR: "Visual Studio 14 Win64" CONFIG: Release WINSTORE: -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION="10.0.16299.0" - GENERATOR: "Visual Studio 14 ARM" CONFIG: Release WINSTORE: -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION="10.0.16299.0" build_script: - cd .. - git clone --branch Leia --depth=1 https://github.com/xbmc/xbmc.git - cd %app_id% - mkdir build - cd build - mkdir -p definition\%app_id% - echo %app_id% %APPVEYOR_BUILD_FOLDER% %APPVEYOR_REPO_COMMIT% > definition\%app_id%\%app_id%.txt - cmake -T host=x64 -G "%GENERATOR%" %WINSTORE% -DADDONS_TO_BUILD=%app_id% -DCMAKE_BUILD_TYPE=%CONFIG% -DADDONS_DEFINITION_DIR=%APPVEYOR_BUILD_FOLDER%/build/definition -DADDON_SRC_PREFIX=../.. -DCMAKE_INSTALL_PREFIX=../../xbmc/addons -DPACKAGE_ZIP=1 ../../xbmc/cmake/addons - cmake --build . --config %CONFIG% --target %app_id% pvr.nextpvr-3.3.18-Leia/debian/000077500000000000000000000000001360274650100162205ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/debian/changelog.in000066400000000000000000000002651360274650100205020ustar00rootroot00000000000000kodi-pvr-nextpvr (#PACKAGEVERSION#-#TAGREV#~#DIST#) #DIST#; urgency=low [ kodi ] * autogenerated dummy changelog -- Nobody Sat, 01 Jun 2013 00:59:22 +0200 pvr.nextpvr-3.3.18-Leia/debian/compat000066400000000000000000000000021360274650100174160ustar00rootroot000000000000009 pvr.nextpvr-3.3.18-Leia/debian/control000066400000000000000000000011501360274650100176200ustar00rootroot00000000000000Source: kodi-pvr-nextpvr Priority: extra Maintainer: Nobody Build-Depends: debhelper (>= 9.0.0), cmake, libtinyxml-dev, libkodiplatform-dev (>= 16.0.0), kodi-addon-dev Standards-Version: 3.9.4 Section: libs Homepage: http://www.nextpvr.com Package: kodi-pvr-nextpvr Section: libs Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: NextPVR for Kodi NextPVR for Kodi Package: kodi-pvr-nextpvr-dbg Section: debug Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: debug symbols for NextPVR for Kodi debug symbols for NextPVR for Kodi pvr.nextpvr-3.3.18-Leia/debian/copyright000066400000000000000000000034671360274650100201650ustar00rootroot00000000000000Format: http://dep.debian.net/deps/dep5 Upstream-Name: pvr.nextpvr Files: * Copyright: 2012-2013 Graeme Blackley www.nextpvr.com 2005-2013 Team XBMC License: GPL-2+ This package is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. . This package is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. . You should have received a copy of the GNU General Public License along with this program. If not, see . On Debian systems, the complete text of the GNU General Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". Files: debian/* Copyright: 2013 Arne Morten Kvarving 2013 wsnipex License: GPL-2+ This package is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. . This package is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. . You should have received a copy of the GNU General Public License along with this program. If not, see . On Debian systems, the complete text of the GNU General Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". pvr.nextpvr-3.3.18-Leia/debian/kodi-pvr-nextpvr.install000066400000000000000000000000261360274650100230450ustar00rootroot00000000000000usr/lib/* usr/share/* pvr.nextpvr-3.3.18-Leia/debian/rules000077500000000000000000000013051360274650100172770ustar00rootroot00000000000000#!/usr/bin/make -f # -*- makefile -*- # Sample debian/rules that uses debhelper. # This file was originally written by Joey Hess and Craig Small. # As a special exception, when this file is copied by dh-make into a # dh-make output file, you may use that output file without restriction. # This special exception was added by Craig Small in version 0.37 of dh-make. # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 %: dh $@ override_dh_auto_configure: dh_auto_configure -- -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=1 -DUSE_LTO=1 override_dh_strip: dh_strip -pkodi-pvr-nextpvr --dbg-package=kodi-pvr-nextpvr-dbg override_dh_installdocs: dh_installdocs --link-doc=kodi-pvr-nextpvr pvr.nextpvr-3.3.18-Leia/debian/source/000077500000000000000000000000001360274650100175205ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/debian/source/format000066400000000000000000000000151360274650100207270ustar00rootroot000000000000003.0 (native) pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/000077500000000000000000000000001360274650100173125ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/addon.xml.in000066400000000000000000000467131360274650100215410ustar00rootroot00000000000000 @ADDON_DEPENDS@ Kodi voorprogram vir die NextPVR Kodi frontend for the NextPVR Клиент за „NextPVR“ Frontal de Kodi per a NextPVR Rozhraní Kodi pro NextPVR Blaen Kodi ar gyfer NextPVR Kodi frontend til NextPVR Kodi Oberfläche für NextPVR Frontend του Kodi για το NextPVR Kodi frontend for the NextPVR Kodi frontend for the NextPVR Kodi frontend for the NextPVR Kodi frontend for the NextPVR Front-end de Kodi para NextPVR Front-end de Kodi para NextPVR Kodi frontend para el NextPVR Kodi liides NextPVR'ile Kodin NextPVR-asiakasohjelma Frontale Kodi pour NextPVR Interface logicielle pour l'enregistreur vidéo NextPVR Interface de Kodi para NextPVR לקוח טלוויזיה חיה עבור NextPVR Kodi sučelje za NextPVR Kodi előtét a NextPVR-hez Frontend Kodi untuk NextPVR Kodi framendi fyrir NextPVR Frontend Kodi per NextPVR NextPVR 用 Kodi フロントエンド NextPVR을 위한 Kodi 프론트엔드 Kodi sąsaja dėl/su NextPVR Kodi galasistēma NextPVR Kodi интерфејс за NextPVR Bahagian hadapan Kodi untuk NextPVR Kodi ၏ frontend အတွက် NextPVR Kodis grenseflate for NextPVR Kodi frontend voor de NextPVR Klient telewizji dla NextPVR Kodi Frontend para o NextPVR Interface Kodi para NextPVR Interfața Kodi pentru NextPVR Интерфейс Kodi для NextPVR Kodi rozhranie pre NextPVR Kodijev vmesnik za NextPVR Kodi интерфејс за NextPVR Kodi interfejs za NextPVR Kodi-frontend för NextPVR Klijynt telewizyjny dlŏ NextPVR ส่วนหน้า Kodi สำหรับ NextPVR NextPVR için Kodi ön ucu Накладка Kodi для NextPVR Giao tiếp Kodi cho NextPVR Kodi 的 NextPVR 前端 NextPVR的Kodi前端 NextPVR voorprogram. Ondersteun stroom van Lewendige TV & Opnames, luister na Radio kanale en EPG. NextPVR frontend. Supports streaming of Live TV & Recordings, listening to Radio channels and EPG. Клиент за „NextPVR“. Поддържа телевизия на живо и записване, слушане на радио канали и електронен програмен справочник. Frontal de NextPVR. És compatible amb les transmissions en línia de TV en directe i enregistraments, escolta d'emissores de ràdio i guia electrònica de programació (EPG). Rozhraní NextPVR. Podporuje streamování živého vysílání a nahrávek, poslech kanálů rádia a televizní program. Blaen NextPVR. Mae'n cynnal ffrydio Teledu Byw a Recordiadau, gwrando ar sianeli Radio ac Amserlenni Rhaglenni Electronig. NextPVR frontend; understøtter streaming af TV og Optagelser, Radiokanaler og EPG. NextPVR Oberfläche. Unterstützt Live TV & Aufnahmen, Radiokanäle und EPG. Frontend για το NextPVR. Υποστηρίζει ροές Live TV & Εγγραφές, ακρόαση Ραδιοφώνου και EPG. NextPVR frontend. Supports streaming of Live TV & Recordings, listening to Radio channels and EPG. NextPVR frontend. Supports streaming of Live TV & Recordings, listening to Radio channels and EPG. NextPVR frontend. Supports streaming of Live TV & Recordings, listening to Radio channels and EPG. NextPVR frontend. Supports streaming of Live TV & Recordings, listening to Radio channels and EPG. Front-end de NextPVR. Soporta transmisiones de TV en Vivo y Grabaciones, escuchar canales de Radio y Guía Electrónica de Programas (GEP). Front-end de NextPVR. Soporta transmisiones de TV en Vivo y Grabaciones, escuchar canales de Radio y Guía Electrónica de Programas (EPG). NextPVR frontend. Soporta transmisión de TV en directo y Grabaciones, escuchando canales de Radio y EPG. NextPVR'i liides. Toetab telekanalite striimimist ja salvestamist, raadio kuulamist ja elektroonilist saatekava. NextPVR-asiakasohjelma. Tukee suorien tv-lähetysten ja tallennusten katsomista, radiokanavia, ohjelmaopasta ja ohjelmien ajastamista. Frontale de numériscope pour NextPVR, prenant en charge la diffusion en continu des télés en direct et les enregistrements, l’écoute de chaînes radio, et le GÉP. Interface logicielle pour l'enregistreur vidéo (PVR) NextPVR. Gère la diffusion de la TV en direct et des enregistrements en direct, l'écoute de chaînes de radios et le guide électronique des programmes TV. Interface de NextPVR. Compatíbel coa transmisión de TV en directo, gravacións, escoita de canles de radio e Guía. לקוח טלוויזיה חיה של NextPVR. תומך בהזרמת שידורים חיים והקלטות, האזנה לרדיו, הצגת לוח שידורים ותזמון הקלטות. NextPVR sučelje. Podržava stremanje i snimanje TV programa, slušanje radio programa i elektronski programski vodič (EPG). NextPVR előtét. Élő adások, felvételek és rádiócsatornák támogatása EPG-vel. Frontend NextPVR. Mendukung pengaliran Siaran TV langsung dan perekaman, mendengarkan radio dan EPG. Framendi fyrir NextPVR. Styður streymi á beinum útsendingum og upptökum, hlustun á útvarpsrásir og rafræna sjónvarpsvísa. (EGP). Frontend NextPVR. Supporta lo streaming di Live TV, le Registrazioni, l'ascolto dei Canali Radio e l'EPG. NextPVR フロントエンドです。Live TV や録画番組のストリーミング、ラジオチャンネルの視聴、EPG をサポートしています。 NextPVR 프론트엔드. 라이브 TV 스트리밍과 녹화, 라디오 청취, EPG를 지원합니다. NextPVR sąsaja remia transliacijos Live TV & Įrašus, klausytis radijo kanalus per EPG NextPVR galasistēma. Atbalsta tiešraides TV un ierakstu straumēšanu, radio kanālu klausīšanos un EPG. NextPVR интерфејс. Подржува стриминг на Live TV и снимања, слушање радио канали и ЕПГ Bahagian hadapan NextPVR; menyokong penstirman TV Langsung & Rakaman, mendengar saluran Radio dan EPG. NextPVR frontend. Live TV နှင့် Recordings ၊ ရေဒီယိုလှိုင်းများကို နားဆင်ခြင်း ၊ EPG စသည်တို့ကို ထောက်ပံ့ပေးသည်။ NextPVR-grenseflate. Støtter visning av direkte-TV og opptak, lytting til radiokanaler og EPG. NextPVR frontend. Ondersteunt streaming van Live-TV & opnames, luisteren naar radiokanalen en EPG. Klient telewizji dla NextPVR obsługuje transmisję kanałów radiowych i telewizyjnych, nagrywanie oraz funkcje przewodnika telewizyjnego. NextPVR Frontend. Suporta streaming de TV ao Vivo e Gravações, ouvir canais de rádio e EPG. Interface NextPVR. Suporta transmissão de TV em direto, gravações, estações de rádio e EPG. Interfața NextPVR. Suporta streaming Live TV și inregistrari, radio și ghid electronic de programe (EPG) Интерфейс для NextPVR. Поддерживает просмотр и запись ТВ, прослушивание радио и EPG. NextPVR rozhranie. Podporuje streamovanie živého televízneho vysielania a nahrávok, počúvanie rozhlasových kanálov a EPG. Vmesnik za NextPVR; podpira pretakanje televizije v živo & posnetkov, poslušanje radia in EPG. NextPVR интерфејс. Подржава стримовање ТВ Уживо & Снимака, слушање Радио канала и EPG. NextPVR interfejs. Podržava strimovanje TV Uživo & Snimaka, slušanje Radio kanala i EPG. NextPVR-frontend. Stödjer strömning av Live-TV & inspelningar, lyssna på radiokanaler och EPG. Klijynt telewizyjny dlŏ NextPVR podpiyrŏ szpricowanie kanałōw radyjowych i telewizyjnych, nagrowanie aji funkcyje EPG. ส่วนหน้า NextPVR รองรับการส่งกระแสของทีวี สด & การบันทึก, ฟังช่องรายการวิทยุ และ EPG NextPVR ön ucu. Canlı TV akışı ve kayıt yapabilme, radyo kanallarını dinleme ve EPG destekler. Накладка для NextPVR. Підтримує потокове Live TV & запис, прослуховування радіо каналів і телегід. Giao tiếp NextPVR. Hỗ trợ truyền phát và thu chương trình Live TV, nghe Radio và hiển thị lịch trình chiếu (EPG). NextPVR 前端。支持直播电视和录像流媒体、收听电台和电子节目单。 NextPVR前端。支援的串流媒體包括有:直播電視和錄影,收聽廣播頻道和電子節目表。 Hierdie is werk in vordering. Gebruik op jou eie risiko. This is a work in progress. Use at your own risk. Разработката на програмата не е завършена. Ползвайте на своя отговорност. Això és un treball en curs. Utilitzeu-lo sota la vostra responsabilitat. Práce na tomto rozhraní stále probíhají. Používejte na vlastní nebezpečí. Gwaith ar y gweill ydy hwn. Defnyddiwch er eich risg eich hun. Dette er igangværende arbejde. Brug på eget ansvar. Dieses Addon befindet sich noch in der Entwicklung. Benutzung auf eigene Gefahr! Έργο υπό ανάπτυξη. Χρησιμοποιήστε το υπ' ευθύνη σας. This is a work in progress. Use at your own risk. This is a work in progress. Use at your own risk. This is a work in progress. Use at your own risk. This is a work in progress. Use at your own risk. Este es un trabajo en desarrollo. Usarlo bajo propio riesgo. Este es un trabajo en desarrollo. Úsalo bajo tu responsabilidad. Este es un trabajo en curso. Úsalo bajo tu propio riesgo. See on pooleliolev töö. Kasutada omal vastutusel. Tämä on epävakaa ohjelma! Sen tekijät eivät ole millään muotoa vastuussa epäonnistuneista tallennuksista, virheellisistä ajastuksista, haaskatusta ajasta, verenpaineen noususta tai mistään muusta epäsuotuisasta vaikutuksesta. Cela est un travail en cours. À utiliser à vos propres risques. Logiciel en cours d'élaboration. À utiliser à vos risques et périls. Aínda está en desenvolvemento. Usar baixo o seu propio risco. זוהי הרחבה נסיונית. השימוש באחריות המשתמש בלבד. NextPVR PVR klijent je je još uvijek pod razvojem. Koristite ga na vlastitu odgovornost. Fejlesztés alatt! A saját felelősségére használja! Ini adalah proyek yang masih berjalan. Resiko ditanggung sendiri. Þetta er í vinnslu. Notist á eigin ábyrgð. Questo è un lavoro in corso d'opera. Utilizzalo a tuo rischio e pericolo. これは現在開発中のプログラムです。利用は自己責任でお願いします。 아직 개발 진행중입니다. 부족한 부분이 있을 수 있습니다. Tai yra nestabili programinė įranga! Autorius jokiu būdu neatsakingas už nepavykusius įrašus, neteisingus laikmačius, iššvaistytas valandas, ar nutikus kitiems nepageidaujamiems poveikiams ...[COLOR=red](Kodi.lt siūlo/rekomenduoja testuojant šį priedą persijungti į Anglų [orinali] kalbą)[/COLOR] Šis darbs ir procesā. Izmantojiet paši uz savu risku. Ова е сеуште незавршена програма. Користи на сопствен ризик. Ia masih dalam pembangunan. Guna atas risiko sendiri. အသုံးပြုရန် လုပ်ဆောင်နေခြင်းဖြစ်သည်။ ကိုယ့်တာဝန်ကိုယ်ယူပြီး အသုံးပြုပါ။ Dette er fortsatt under utvikling. Bruk på eget ansvar. Hier wordt aan gewerkt, Gebruik op eigen risico. Oprogramowanie nadal jest w fazie rozwoju i jest niestabilne! Autorzy w żaden sposób nie są odpowiedzialni za nieudane nagrania, błędy w harmonogramie nagrań, zmarnowany czas ani jakiekolwiek inne niepożądane efekty. Este é um trabalho em progresso. Use a seu próprio risco Este é um trabalho em curso. Use-o por sua conta e risco. Aceasta este un proiect în lucru. Utilizați pe propriul risc. Разработка программы не окончена. Используйте на свой страх и риск. Práca na tomto rozhraní stále prebieha. Používajte ho preto na vlastné riziko. Dodatek je še v izdelavi. Uporaba na lastno odgovornost. На овоме се тренутно ради. Користити на свој ризик. Na ovome se trenutno radi. Koristiti na svoj rizik. Detta är ett pågående arbete. Använd på egen risk. Software durch je w fazie rozrostu i je niysztabilne! Autory w żŏdyn knif niy sōm ôdpedzialni za niypodarzōne nagrania, felery w harmōnogramie nagrań, stracōny czŏs ani jaki ino inksze niynazdane efekty. นี่คืองานที่ยังดำเนินการอยู่ ใช้ด้วยการเสี่ยงของคุณเอง Bu devam eden bir çalışmadır. Kendiniz risk kullanın. Роботи все ще тривають. Використовуйте на власний розсуд. Đây là bản thử nghiệm. Bạn phải tự chịu trách nhiệm với nó 此插件仍在开发中,请自行把握试用风险。 這個程式尚在開發中。使用上您須自行考慮到可能有的風險。 @PLATFORM@ pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/changelog.txt000066400000000000000000000174651360274650100220170ustar00rootroot00000000000000v3.3.18 - fix uninitialized variable in Extended Timeshift v3.3.17 - implement v5 timeshifting - improve playback of in progress recordings - added the sid to recordings - reintroduce XMLUtils makes the parsing code easier to read. - fixed bug passing empty group titles to Kodi (kodi bug) v3.3.16 - Update build system version and cleanup - Fix package check for TinyXML - Added AppVeyor for Windows related build tests v3.3.15 - CreateThread() change - Move LiveStreams.xml to only load once - Changes for NextPVR v5 v3.3.14 - Fixed issue with art not showing up on recordings from deleted channels - New settings option to enabled Kodi style recordings - defaults to NextPVR style (no title, with S/E ) - Reduce channel tuning time in Extended Timeshift - Removed trigger on deletes causing Kodi crash - Adjust for server time difference loading instant recordings (could show as scheduled) - Clean up MAC address logic, no WOL for localhost - Allow Kodi plugin:// URL in LiveStreams.xml v3.3.13 - Add Extended Timeshift Rolling File based live tv and radio buffer (pause and seekable) - Use file-system for recording and rolling file playback if available - Removed GetBackendTime() not part of API, changed RenameRecordings not supported - Fixed radio playback with timeshift, All Channel recurring recordings, problems passing expired EPG ID's - Fixed URL encoding of recording directory virtual name. - Separate and show Failed recordings, added Conflict Timers - Disable backend updates during media playback. Kodi still will update if configured - Separate Radio recordings for current stations, don't know type for deleted stations - Use S##E## and subtitles for improved Kodi skin display - Update recordings when timers are added or deleted - Improved system wake and added WOL (still needs state machine), get server time difference as global - Fixed problem with in-progress files. v3.3.12 - Bugfixes, seek re-init, and jump to last block already buffered. v3.3.11 - Fixes for live tv timeshift and seeking. v3.3.10 - In-progress recording changes v3.3.9 - more bugfixing in timeshift seeking, GetStreamTimes() changes. v3.3.8 - bugfixes for live tv tsb seeking, fix uninitialzed struct timeval in socket.cpp v3.3.3 - language string updates. v3.3.2 - use iUniqueId instead of iChannelNumber for live streaming. v3.3.1 - Implement GetStreamReadChunkSize() v3.3.0 - Updated to PVR addon API v5.10.0 v3.2.7 - Implement GetStreamTimes() so live tv timeshift will work. v3.2.6 - Updated to PVR addon API 5.9.0 v3.2.5 - Change buffer management, using pvr.vbox model/code as a starting point. v3.2.3 - Remove StdString usage v3.2.1 - Remove unneeded code added in last revision v3.2.0 - Updated to PVR addon API 5.7.0 v3.1.0 - Updated to PVR addon API v5.3.0 v3.0.4 - Remove of never used addon interface function v3.0.3 - Update Debian package control - PVR addon callback way changes v3.0.2 - Removed old no more needed version functions v3.0.1 - set dependency versions automatic during build - removed never used kodi to addon functions - build system fixes - language updates v3.0.0 - Initial Kodi v18 version v2.4.7 - fixed issue where the recording/timers lists were no longer automatically updating v2.4.6 - prevent crash if invalid or missing XML is received v2.4.5 - fix Travis CI build on XCode 6.1 - fix compilation with GCC 5 - always include "NextPVR" in the backend name - fix GetLiveStreamURL() for channels with subchannel number v2.4.4 - updated language files from Transifex v2.4.3 - updated language files from Transifex v2.4.2 - updated language files from Transifex v2.4.1 - updated language files from Transifex v2.4.0 - Cmake: rename find_package kodi to Kodi v2.3.1 - Fix includes v2.3.0 - Updated to PVR addon API v5.2.0 v2.1.0 - Updated to PVR addon API v5.1.0 v2.1.1 -Fixed issue where user couldn't select to only record new episodes -Fixed issue with updating one-off recordings -Fixed issue where pre/post padding was not being loaded with recording list v2.1.0 - Updated to PVR addon API v5.0.0 v2.0.3 - Updated to PVR API v4.2.0 v2.0.2 - fixed issue with Transifex overwritting strings - added extra string 'Repeating (keyword)" string to correct duplicate recording type entry v2.0.1 - updated language files from Transifex v2.0.0 - Initial Kodi Krypton version. v1.12.7 - updated language files from Transifex v1.12.6 - updated language files from Transifex v1.12.5 - updated language files from Transifex v1.12.4 - Updated to GUI API v5.10.0 v1.12.3 - Fixed bug that could occur with recording groups - Upped minimum NextPVR version to 3.6.0 v1.12.2 - fixed a potential illegal memory access, picked up by Coverity. v1.12.1 - added support for keyword timers - added support for dynamic downloading of artwork in TV guide - fixed issue with updating existing timers v1.12.0 - added support Jarvis timers v1.11.6 - Updated to PVR API v4.1.0 v1.11.5 - Updated to PVR API v4.0.0 v1.11.4 - Updated to PVR API v3.0.0 (1.9.7 compatibility mode) v1.11.3 - Updated to PVR API v2.1.0 - Automatically fill in platform and library name v1.11.2 - Debian packaging: fix library install path - Miscellaneous backend fixes v1.11.1 - Updated to PVR API v2.0.0 v1.11.0 - Updated to PVR API v1.9.7 v1.10.6 - updated language files from Transifex v1.10.5 - fixed issue where RPi user were unable to watch live tv due to subtle socket differences on that platform - fixed issue where recording list would get out of date and not reflect reality of backend v1.10.4 - Updated to use new libplatform-dev v1.10.3 - Updated to PVR API v1.9.6 v1.10.2 - Updated to PVR API v1.9.5 v1.10.1 - Updated to PVR API v1.9.4 - Updated to GUI API v5.8.0 v1.9.21 - updated language files from Transifex v1.9.20 - updated language files from Transifex - minor changes to conform with C++11 v1.9.19 - added getBackendHostname function - added support for ATSC subchannel numbers, fixing 'no tuner available' message users were getting with this type of channel - fixes a problem with playback of radio stations - added recording artwork - added fanart v1.9.18 - Fixed mime-type for MPEG-TS v1.9.17 - updated language files from Transifex v1.9.16 - change library name to Kodi v1.9.15 - fixed deadlock when activating the addon on some darwin (osx, ios) runtimes v1.9.14 - updated language files from Transifex v1.9.13 - updated language files from Transifex v1.9.11 - updated to API v1.9.2 v1.9.9 - updated language files from Transifex v1.9.8 - fixed bug that could cause connection to close prematurely v1.9.7 - updated language files from Transifex v1.9.6 - updated language files from Transifex v1.9.6 - added dialog to set recurring recordings, including recurrence type, padding, number of recordings to keep, and recording directory - added support for EDL - added support for retrieving and storing last playback position - now requires NextPVR 3.1.1 or higher - fixed a bug that could cause an EPG event with no description to have a copy of last show's description, or cause a crash if the user was unlucky. - more flexible approach to genre v1.9.5 - add timeshift buffer functions v1.8.4 - sync with PVR API v1.8.0 v1.7.4 - Bump after PVR API version bump v1.6.4 - small change to improve the performance of radio channels v1.6.3 - updated language files from Transifex v1.6.2 - updated language files from Transifex v1.6.0 - New version number by Team XBMC v1.0.1.0 - added: new experimental timeshift support. This requires updated backend components, otherwise falls back to previous non-timeshift live tv. - added: new 'advanced' settings page where timeshift can be enabled/disabled. - added: radio support, mainly to workaround an XBMC channel group bug. - changed: now using XBMC curl abstraction for HTTP requests - added: detection of live tv having to exit if tuner was required for a recording. Shows user a notification message when this was required. v1.0.0.0 - Created pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/icon.png000066400000000000000000001172001360274650100207510ustar00rootroot00000000000000PNG  IHDR\rfbKGD pHYsodtIME 4fC IDATxڼyWu'4ڒ,yyc0I"$ 4dtU]Y"TgRJ{T*TUؖY% k7oΰ9{Zϖ޻;9{mº0?D+`N 01`0?c5Z@! 4o̰]}\kkP;Wn <Olfoͪ %>;j=z]I>A}GsJ3{s@1pƿd]lZ`@~},wl;뇅^ch}M_yߛo%s0|eݗp~t%?Qb!~XQ=я_3$L\(93-;_F=>I\>I_䆶7d$dmb5].#Iʵ_"drKD֚"ʒQ8~vPjFue*w->0D$k''ȋV׊3޵z-@ HGdV(ûS޶bhS* /6+)HZ%nx~qkBU31icEnog/ǚ.}O5fAjFƐ>-oL8v`_?qh'p9瀔fx^1V!\W,R:L(DΥ7nb'?DNnWJ=}RS_+"1ܾIlM[=K:E P_X;?ʴQP199ύL)q Q"WS9D2UijR$O";""K/?FŴ,,8'M{9SVbl=FU9E{`%Dj%U*kky!O)y^fD( Wܽ#V,;Z2M<'LѤ\˧!na+Qpd)Nx`nNjzZȬ~ $ =‘`si}}Rb5}r2'7"n=)bY>,'ŢEdG@ 6%@j=I)\Xˣ>X}1Of)"SPC6«YM/pس>nDP.E$`$qқ~&I!?Ad]<+sGJvyXdǮP{(>>CB\8oOxvhDiJ n^oq/H-(;?\p9p:eQLcI^Fb<(5[(AY.2e^ O4WTpqC帍`!e{cS2m\e5PbXNlXMoaG=ZUȢ3Fb3{9rB|u$s&aF0˳ 8hNΒd]ĵYl.>'}^*TP$ye^MB"~@d&v> _9iWY-mD>s˚qz\'bH<9s0HJI$hhvg$Eص%Ya83MD }3$֔/su!5H o9`|ٟYlİ8R9JV@Kb'>~gH [?4]w eUYcc¶cjղdhre&L jF5&;XOwX}y({s5v=b(tꘒ YP%3=JcImLXG@VzBV 9lb +8p"LT].-.B7o8# ΢6Qx9i(hI#d?]C"U$^QtK~(LY3\lgaffAGQ1yʚ(eƚl<2JzY%ˮ%hC6Wb$V)sLYM>',Q [v4Jj]_I9g` ;Fm,YVXkYH=ǠРT%^1qE $V%KJDҌQ J@-K"RkF9 $^D? baYbt(#UX2+lu.֞HS[%Qч#~T\ AOmܣ|c%-XO>V4m}/,!) OfJ@0+M/KZ&j$+W>ٜn+( @fxnEG+Ij%d+U 9* bЅ ԶBuJ!xOg"qc0ޟUٻ$SYPD iG25yHqm:BR&ɁYQJp}յ'Y\ M\:LېCSJd D3=#BnqHcy*)ҵG^{$afJd+×Fr,|ݜlYNYg -Ȉ{J&nbx8NDL:\΂UgJEr(̱Y;*CyO"ir#9MpW֌8|J"܊AΕvZTQgqղ$=4;ϯ 9)\]-2r/ZQrd !Z bBG;b# 6@%)j ?6{Mu*#\n brKP>.+Zє :eY.<ˡF{U*R6+6L,E챵[Y}F*Z 5C9$w7Iu)rZC#Ar|܎ f«Ƅ%beDv:JGH*3(Yb,Hhtj793L,P7ǤxKa3 Inx Fm^S=9B/ ll>(j6s䝥䌅o[AE.HBJZsT 5y*f!ܛeNVL0G/I%b&GH %>a2$stF s!T)+@eP.A1+<٧"y9'(C75$nF ̑هJs K+ajr(sS☱I8JumR&[J]umGMDYe=5ƜyAԸDcgL^̵ū _`m JG Z<J>%Yw^*7Hkf3$OU"v a.(E>3%X$i<^LFEcPypn]yǜm]ķ mo3ԠG nit];m7אsJ5ْ QG@X[&kƤH"v: N7F2 .W(R/%Mxy&mIHI yX7s~#9Eߓ6kRl̂$"VO4-3c:)$"D2B1R26KEf>BVrKoRDNeB*&ا( [!&g]rj,6X+T{{y:DyødtxMfBHbgF+%C;8T*9Hd)3h*K]1d7EXRH%ώ FDHUP;CC?{'GRak,zZ9F%%?_x!9vX؛DαZoE=r:itqȻjMˎs$E&@M6,hsrP,2Dq&:юnsrHfB8< q$6MBjHx>er/1Q?KfۙJ*0 EYZT(C\EMuE Q!ee9jؖ*H|, SdC@,tÿ\vRJGaQCJINRξaKNb^S$BrGl0nU۴g2{N G07F{!?# aa,Oi ,ovw wGt@8O11 qn*و]쬝{L'C 9n sY5("'.)h^qȼ(EDD%doVos 菤 [HB-)#N|@ac7ɱkY9Sex+K :h!Ap(K1._}H>0Ʌ.TS˺k"@ pqJhi]J ŪZ- fW"}})DAu<[Ւ8+@HG=jD$r*AHİ>x82c##_d^þDB[p9[ޓdv׉$lFV9DPTy߆Ŵ/I<,Gv=(:VHmŠ:1®se+a( zn%$0h`I#?CrʋItw"[(SWPe`ţHOOSN*Gű?Pi-Ţ M!\2 "yb4:/\1fK:xE>ZFf! 0Ӡ4dEuqf[L`8VQ>*EhԎeZoZ;So9ssx2hHA$^m~նl?&"CМȿ+KH ;| Da50ǏL)p02Sa4eŎ(YDyUElRKw1#ֹURМA{KqX(/F[s" 9A=GaoCVit|lY[nAQ"[H^#IH'=ɛ1翵)@Kc|]rμL}J))2 q1blJpF$]rRz9Od`A+h4bgKc_ Itl vtXb:s}f"AʉjAZN*֤EN~eCIh jxm(8fcƔH(pI"km?a=p2eSk" hB.U,A8/߲g%ȩOKCqrJ`J9Bɜq75_M T O ! F9^QG}&!ǜi=@sZ"R?Iо/xrd|aQG׽&< A-Ȳ1hΛ~z+M[t:-yi<6*nKߛ3rP?°Ŕ/8N<;K-L8g.5uHeu:/ 4v@B7 ݁6ca)3w^$| !B)]9%ڢ2v+-jvhε=F"deM8Zqa'H9:u&B,#} -{6ȸ6@؜aړ٬; k/⭩KHQزB±pg1plM"h{LM7V rE"{ 䱸1yF)A"ZKq42im#md"nQlvASܓ J6!N$\IsLI->2a$/,GDeL::E68PI9wCqqudC,x>h!ł#Dj` T<1X6] r`%oiykuVJ[w6.9n2 IDAT9($J]kحfTT0E3cMR"ސHr-(QgLzZ- f(z!i F#PE`Br :?T)$,QE4 -mJ%Š"$9(YlːhآXHhmpH ? ٴKA]_@29|dhnNNz{FNN&.zij _H(7VL0Rs%୼E!1glXFA$h{$9l[Y OI~y"SNU"o4NQBV5hq)ԋ!da*0J*0'PXJRIJNbhΑiDhwؙ_3t)r5 G{5[LtJ*je+ *!OHy3f+);VިV7f8WSb(Q&[ȆQ P M/%^96j3ή&BFL*ʥ$G#Xm*md}BB*@.w&/f$H]@3e OJx6V]i` T`D`{;5!}[R 2'xHJ sW +('x,OC2TZ Z 1b/9 v27AstQX v<5 sqi@`JPғAkx#O|CQX*,ߤGN+e8v`Br#?(*("p"R|h7h Ö%gzϘW]"dҒ\*a} -rM^t±B-8R%$g{Q87코,v5$L3̮& ]٧\roW0!06.˰,}u *%,;+FHPP!uܠ ~Rx.twx` $S>{T 2BR 61I E(<8. y JF~ITQPfK[dq*ퟙ {)3I^pz !HRAϵUmFrw{<\+8 \KSsIK]Xk!Z')st`ň.yJX7 g36wmWznC2f5ʼn)kF1(ET9 5gy*^$kDSdAr\P&N"/Pi0w*[>X_+SW4/37d b+"q;Cԝyp#pҔfE+!cZ3SIEF h,6T OOESrq%_ WbSkHlGBd6BElJT&7[fR6"EPbI7H):zxnl_>.!SYuٙ> MI5;i2}B |iq6etTuDD34Q=M?kgcQ#imyē LRP#t>Ns`[ - w8ω#Me6cAhD!G_ m0KPDQթPv8 *IFJHDz@ѬW9F G!'7)π̜#07)$E_>b:w>`vL֍GD c 6ZJ ;Na Z}ڙK蟔*)xʒ`5;B<]sx ce4,P%JzAAnD,H"WY--24YcФ/):q :si iqbP 4ɞI,o}hvK%n94cKvDfl" er&q7G=Ɯx|"ʉ(fWzBuja3X[m$ k,("&r-yJi!iD*oghTRsS .gJ⡱唖"jє Y2GuFG xJVgjb )k‘(L30GBs ಅJNNeK_p^7X7}>Y}n}_5ģ#bjb3s8r0vnۉ9,ϣ 0pVaatvZ_]v!zB~ =C8Ĵ+5Gt~w:O|GNNkpWr0& cGGm_3G$`W<09RQ7̿b2F-Ac` NGs>p͸Aʞ}Os__; tGBP=GC_.8PXK)>φɅGe عe+}1me =c5a,[ 7F\pbr,+[r ޳?Ec >O/WA\ԀK9b\El(tw؍mg p89dA1Np- +Y9^ݬ¿g/y͗S㍗?!EOy-zvrp_yu'/`+wu}€P(6p=μ"<_C_ t劫.xN=s[2WUe)@%ŀW,7:#c0[=Mr" 87$ ,=2B2nQ,R`Ơvμ!#ji t,22uhMcㆅQľ3oNouS`ݚUxbH>{w|=̊0G&3P{ 0;^y| s3sMY ON>0W(nJ %g+:8kѣG@ C,ū >P7X"(2i VgQBD"$ /ER邪2;\H`5?n{'>8FGex `P 3/'i}0.J(fr"G"`ϑ >`իqb0?3W7؍}GyeՇ?\#"WrWUZU&''i&ŷīG'A\@;S8=7ɵ`Sj;|^>zFS%/&nƀv{Y'o1qf9m 4Bw,ooy~~ C!=v }\]6kVcҥt:ƬO>w &4Z%Bڋp`h3按6@wl)F/Gwl9[eע3 m4 h˯|''p-o? ?W`jP. ,'N`fg6) <o\ept"`yQXn.h#/_^˻baa!%333[_=EK3L%~N~nJ: cG{q=9ٹX]vޙ݉NYOC/zJl|U>gS__~;eŤO}pX՝ }Gx=8xb'/]%2uy]\~ طo6?O<܇݇&0>SsXr)V,bkq7\z*1cP>b=h5.pWW݁0+jt: ܼ X|Lt29,Rr42+~.؈78s_0V\fWvΝ8zSSXu]I O03 3;SX.|׮]~KF:֦'gƁX`P1|J/߰n5>֛0;;izcvdX'&gn—vKCQcxW 7`X="ľjʙ9Oȑ#x-X G42bџxX V(/.]Vz_SC 89<0wۑd_>sݩhpo<݄u~߃O?K, 3[^{'{05;7\>ķߊK6[܈3VS X냌־``Iw<< _엾f65::K=s:t#nf#vU>;O{?$ndH,އ+.: ׫úo><ܼ ><'t+4 d9(23M| Gƞa#/kKwߊ}'ϼg=?;V^g௾|wb͚5w܈RƎ1xȑ#ؾk?ZrF}Om~ c7(e|l.p/܍;o6>~ʪdϺ_[t;v,ycǎ駟opWo)AϽw|pQ;^c p6ac N=ԐNѴC:~O~+س,LOࡇ/r̀驾OL>[6āP %6LV¬KB㌆/`à/0?`a0@?{/0cjngŽU}SSSތ-gyᵃxuac.&؛DmJ#7u+֭^^z _{lU1b94ý@ zb>5U˗w^NH,Pl oŸ[N"~y"{n|=eIhqR-;v?}}' "[9kW4^@{ ٟi}:jY_2/~ E? Ңמy?zI/zk>:T_n=|/2) kh)jc\PKUe~p^?$q G`rz+/ Q^O_}pgzr .4 IDATcOh1 m6|M?ٝ~G5:>ۏS+q g:#{)/4[s+ 4~aY)+wXmNT5֛Aۯ=-/p8kjltpuOqycKpgѣS/gfm4ilwE?###8Xri:B%hT›oCqN87Bu70б |',y[-Nv\ǀx"YsroX90ÇO,11}Z{SV Pa6to³-vpc[3W]DeLMZҥnۆ. v#Gb~f d4YhrʃJs~_GxP30ZZ!`T#*lV5͕<=νG}\3_}oyx߈Ʈ7t0:|ˍ ]{ޣ%cYg\Lm 5lvf ` a0艉!<1h1 4ȼ16EQ豓h|F<;GONc|j։<*!xڕXdngQ_EQ[Ÿ7ddE3ƎكnI) X_fџ6WUaF4p:ed*u Ӕq#:|Vt~,r.9,,8NNϺ}d?rZ[ }wu_?~> Yso:p|JVkHYpOyƽ! xbb E}[;>LV#"zahnpETF֍iX=pSÇ* b BDȆ:hl*i:.^֓xMW|FP)♸ U` b>^Srnc'ʕ+Nt;X*8 ӽJ\;~?za_쌇TjKSo xvL.hXƵSy11@r#lNXs IGtK02"WfObEiic]+7? E@:dEގ_Lm@ sVfd3.y3Xɥc} N?GۉsB> =\{ZD'155~ b%μ"yQ6U3֮cŲ1#xޚ xs1[b^LMhNr‰hpJ:+98 OoeXցiGIW\._ a2(AFNdN ζ3rQE>pD+g0) 0D)"NXZb̷(2؅-;_Ú5kwbrslkNY}ǭdz/ɩyy,ǫYbu*eN0򣺺BXz%~o7ݷ]|ust*dUlPGb]CBV%ŬO \c:,Çv[8poMYT TJ++מf`P ](7w:=e :KFџ[p7q OeDd&6E0$! n Vc5gCX19\-]]kHX¥į.{D<G-Ћq`סxʋߊ˯`U$ws'ؼOz_ƚ5϶( r)(vlֶ0k/^*{{=_8pb:h лߤU7 '۲n!tƵn9;}#܉-zJ jVuYg{u0 wgb31sjh ՛$u`{6^\T|9ꪥKѷG_3~8{|'v*|5|빽88cxpˢ|߼ػ`zd[!^cr \p\s83@#c}qS;EE,ݙz%xˡٵ!B|V'D]lՃ _>;E Hz BQAɯ2ұ_itp+^~u ,SlOF d  ߩE_؁܂S1l볦q$>8,]mx^|."rxlF ~߄n=m{VvPK} ?k~~qlzm}*;#[_y.މ;n_~w(Lb85}z$ә8-Ďÿ6ߚXBr^xwSd1moyFQ4 /\ؚgZL, sb{EG~ 6C6yhh ,]XuAO[n{?N[a鰨Lm(N_]s1ۇǷ^F.V,],r{d#s;Iowr0~79a3JJFF<m!ZlkJQ]!6ިWx~spbaHH@ \ޟ H-?„Lr[qtX`` 00(ޯP' z/ע2B)q(u4ش̌7p%\;,=ތN;v ٙa6;*V=RM?(x~A羁}KǯMHޟ!SILA"r. lYa'bw 95-Ӻz=%0C'`(tZ\O! $^I7$d!  7-ipn}jʪ c'e7+. F k/4^|m?vg?a-D9Nk݃voށ/)csol83a8zdw5қ'~D5Mnqnي\qouW.; Mo f#EDVK0J>PdaP`yq5rwQTsbL7'|u(W1Hhw#DZ|rUq5`Ϟ=[܎W,jTo4A  Ѝq}oI'P D.5gn(?ɸ|}ao{ 06NQ;L?z'^!L-V?X7>,_ f s!n_\K-r2{)['R`jBR@v RiG6eFٝlmڬW066| 6>f\sn5N<_JoEϪ 4Yx*Uo'4w6m]|ros1 $H7(34:nIagoZңI 3ڐfP[!`ũbK.ŹހR0`Pp3i~ [ tِUtug;ȎpAL8~5.k,onznۺL$i-okc[ypm0W^&򘍮7ٌ^g[.>;3f2|;g|g03ߓ0YHg [~ (9V0l͸qWbca/:OZh{l {IdtG׏d0:6k>ߗLj^ Ȍ,]β螺#K|OCi|86ȳ05S[`ƖkIe{Ϙ,j `aƞ)GW av~7?#{v-Q..u>$/?a)M7 :2<6Q|w_|͘3.Ŗ-[^))bRzaϒ|fa_|q|?UV#ܷyuEz ?{L>#D¿qMvgѥcx߯:x8`~ VB]Ny??wʎɃzIyI,L 9O0c˰b0W$d1,[βè5+67RP;޾7Ƀl}@*jW'嘚Qk=AD-^pojl8} ^s?1>>G}MxщGπ B Pg9;| zl ~qMW~Lya`.'bLX95IGHΨUo};z Scs{0cLS T/ 1f{s(E1,cıNc7=}KP U`0|cz15_~~uz\&{5/0&'Yih HNPEM L)r6k bʕ;o3|г;qbjN(ߑ{K*XU&Ӝؑ#|[ l~gFd9}H'X noHd͔ N*mzyTiتmepIЧaJD(1k;f^z'^yٲ B)&;42:\C LXY!۱* Ji,hfY&Ӷ JCnEc*S&E8@ wׁ#qe7~=xz^,[2M;_]|!j9*=H)!nJ0 WyGNL`x M;Y>?A1&t@憇moCI=7X禠g'k!f3e$@z* 4߷ܟyRi'zy9ry0== B=9#2ڷ$o@S2>ByI yk |m8rb\?,~vtcY2$r{8y,b?}t:+p, h쥐AX}8t|z3}d8~Hfh^{333`fa۶mO`7pNk| ܐC]0M#忇_E˦|AC4ٱ '~p<yQL}8.?o5tm.BsaQP+mhG =J24+Fң#KX6 t 0 ,ש'PSVO1eԻz Jmv;3wQtJo#މF1R_%1]tQan?kQEӔ ,܀Mc?rF]`~~3} A#S{F' Pbɠ LbMuuąTil%]zp 2cǒ :|5˗}L-+=`kULC&|K,[2B7Bṡn?.r.bpa\n 1S4nXO1*y 4N| UZL9;)4^ zāe)xG-xL2+Ρ- ҝUp@1,5Upss 8EQFXR8}\udU&$]#r.ep1a~:ubQ 3Vχ%cp&2[m-!,03_kYHgf3$fW X0xd-Wۜb CT֛7JLV%`_D4Ng! @-:fdTW)/79s)pAKO5NXlZD6,'K:ߓ])H-iEjCp>>=K+*6spSp5Mm@HV$8YzעL7N/2Ns\xCuR7&0rh E; 5(=g YStxФh]اLr[ qΩq&4Xb)f;6:%::+඼` Vb›Pƞ,x]ףlLꘈP+[fK/C-z7r94g+sX*[`l@ζ;\ IDATw=Ln0 #pYs+ԷPVIZk),|M%Qt;Y }{䓠hai[AiKMw|b117C;иQ99~V0!ӷ :g-Dfi9kNkQmn3R?^R#qUH2f݌.qcHPHL#Xm7D=+ek"iYJ.X~-2A~qGǎmSws_̛&,b]Qj(bH,\W_<ϳ.056艝"*m:M$Sy,g'-Sw5JFr,5 Dyd].yHǡG|sjslPB kI4c9, 4,́6& 8p8>pʗxO߉pݽO8o5+ Bᵯ){ n?p=$@{_| {Yػwvmx> /^ԛ.ʼnwh^y-ʫ1™gϼx}?/|z_ oK08x,^psqھSG{ gq֙ |;q<%ied};ŧaijˡ+0dCKjq~#T^qQ=㜸 ~uʗgOܝ1k`ozݫww|}p=W1 ?Kpoq3oq~xG ow|Wc׉{pO>0>qq܎uЫ^9_++߼v^OكrvWs8}?y/_|6|_xC_i>{ N޻??SO݋|xW%_5+qxw_8r(>Oo| ;woOO7܂\*<}7c<G7BԤϹ_*.s쀋(*ZYS17+^! D6h~) @k!v􉱱t:qXb"w%biˀig/1WΤ6 H@U `,<| Oƻk/y}.zux` 5~+} .cکx߸VO(/+\+ql3% sx;p翄8y3㶻}]r!vo7o'>} pֳu @?7{5?y7n>|ӭxE/LGD0>vǗ_7⁇>?O'9c45,QݚabyjkaNA%lSz˲I)Gj-D`m_ZQe^6_QK 3LaX83ܑ t6@Dp3xjcOև8ȓ>|;O^][b߾S>?:b='d8 \V]o,i2ocLp xgy眍 /]w8Sqa< :cO<|Sسg7Nmؽ8x~E:x䙣xG0NqaqjqGqȔ%>'cc^W)st߾8gC]3$8X5sC(H"ީ9U+ۈ2XA{nO8}*Okj^(-ASlK|0H.n|h p詧~iuIak;ocm!7ܧ| 'ٛ3_~سsǝ{oތ]86͐:|F$lGrI5Ldop\"@drUPSE#`8 FSCOMm x~'|R"ξAq%d!Z|R6B%57Άs5g㯽vgzsea&~o ߈s=ߏ4 Lo ?dZN<1>40wލ~ٟ}3q /%kq-Ow;oW\}c,a>'08g`'-o}Ӟ ?{u}7~#B .E 3>|qNZiP<" !.1Z؛1K]F,4ӆAў!Z\?H_4䋝9 YNRgQkE(:~LvIhD~JJ8;nx1z3Nċ$d-ɽYq gK26RVN$0/4ևF#Lf@^0ll#R6 p:~m4/s2U@Z0&pmͩlp8d<p `2 G*5 SqҰ ֦7b5sa@ 2Y0-?8:x"N7+k0h9.Q렌D2<<fHȲ"Ajhc5ItIr 5iG$4B`su\&XژtV4R+WdZ0b5G(6UZ xZ>@ꉦA(JEkEӽf1m.X1ԆD8Sw ^SaC>z*+"HpF<V_7F)[oV^hTzPJ(YᘷED1VfW,Y2ʳ{>dف>)a I.%hbF%*fĊEYO@հ`7f('y2dHB:ԋ˓g=zqD{7< l;PtdpF t y$ʷ&X6Mn# hd9VA ğuzC23p IT<'ۋ5'uhqA{]4oB+Sp՗7OҵѺLyU/t Iy³52Rl-cdHucҰsY52rS$Db0>CdcFa(ђЊ_N I*MVIKIƗl@HG{)@ͥ)aRak#s5mcsW P2u]MZZwX>3l~!NҐW$$[ ){) JS9< hdfjcl|kOB$s䠧dmH4ߊZ:f|~Gٻ5u_Y ԫ3~; bJQʀ&cpxRj-ɻ 2Pj]UaG1Nqii =?R2 hZ@!{YZJtf *h<\^UHij gc9+EY9Ju4B1J3"N,GhKD'RVCބP"tz :2{ߟ(n!6كkU\hYNBl0CדK# )32=0L0|]BYbnHBX|EH[U$Q2/R*9}srQ8H${Ch5:Ӿ(k%1rB%D/.[y:d *KE zIQ]_o;4<8Y%JT%ėFx8AS >fN0%e vA8@[g^r`HBfh{fyhR[㲒vY<>Jپ<6zCqe x{|Ɋ_*j猾$W$YnaeծoH7/֢p]s/Pov_.VF/\4} ^ բw6»!Og |x>$1BJK-afR.3黯DN: ڧ Wc AcrToC":ӺhL=LO9Ku\󮾶N;tяW)w+-\Q 'IMB- M2&}!4fIe#l_[03s.M4xl^R|VZ 膵/:}r#i^kmVs%+E TnҴ|i|CCYbhCiI9gՐӵiՁ Fzдc"*E6W&:4%hFlY@˩ZkalH~XVZ~8נkUY3`W7k EA3?BlW<Ӕ%tZCXAV3"86Y|V@=lf;x"pDBUT$/iVVAuROd٦;I2/G q;P[8Wo!ѥP\E XnlP #QUixq6 Za^>r垊 }FO y0a4īl dDq8*ێ&Js&-dR}|(*̢dq)tEH=gIDATd#`fK3 %/æt;2]{< ئސt!R g)Ԯ!(;04u~ fbuƭmZY:27m$Yb98mb"\4#Y=_'3p\ll"3[DO\ҫ=~3[J>AE-v` j,6;9($u٪*JBu4`G Mei`XSRߩHr-Ԟc 3מvM$zZ.ÕJcUNwz_FșMa׋UXe\`EM:*lѤ++w[օ 5fҠjm\,w^0ק9lE(bJypԂB_=n w󂨭OyH՞5mC sM [l, (+qaf&X)#YY,;| Y/(-f3T:y:KaBZt?ɇ7FI-HGĸJ?sRjܻYTYKKλEq.3,i8 \)K"xpRkcY+4(cae[9{#*u~xM&:DSI0yaRV`U_$zjPlx'֥>4T2ڳ66BVɑ!4 X샍=cLն%}o5}paϐJVHaBK.uo{w*KV;Sne0rE Q U1UN&kY{W`LJ_j{!W)?3{v S|aW K) `jU0` TJN1sȄ jq]!se ,fdHW3I)6i)74@@6-B.ڤ#C;ўm<ò=LDaʼnq: Uky"=]؈H_8hIYzDpGA- O׌cɯ)Ra*(3Zň/shIQrb$)Ec¯A eϔ--\(HT<<:4Ǜi^10M,;ok3s}hgCM롹 3{BS-b*FT4zؘRfzǥml%X_ԭXi\=j((ƯhYiHˠ;AM%ˈe )eAkwK:<-k.ұv)ݠ U&TlH#}b om T9Č5Uiby]FR&u @H62oi@Jh3_ UgHdh(32;ӕ*}+/mwNݐ*%W"[ =ۢڏhEhg`4˴AKZL/ܢJ6UYحX0Ö6XSWjO+@l2ml&:LjgBu!1%*k6vRF=E{_Ly1mpXVLOvTl[[*ݵgLiܐd$oZjt&R[W|fDI5CExKPz.[]"Ibz5_{? Umb 0 :8Y#Oi$kZj9}"j jwtUZJ3UHꢴ!: }t֦8f6҅j^K>Ɯ= p}+~!+v(Ǽi!_ep|GPT}H?gad<{E YisRWZ7(@mfJK|s[zoE;9Msnœt[z8Q#9U-Z^fKL-ٔG D=bm$A1R)AKN M›_vd,i!PV(0PڼE}D;)n\ts-]vKk٤i0鯯 kXmdрs:3qWܴ7izJFha- gd5U^<`Zg߉!%\_iG7T5J W 6L S#ĚhnϭE bi Jk#'v z^RhC%+PW1DU}v $Y+KPJ9AʫJ3!~F%= FJIir'O$" ,R0Y;* IA(M7Yr RS +]}iFسY 4^L(ڍ#zOG~-pO=0̒U|oe#*g[^nr(d޺.-Gn<OaPIϫyI_hynzR^b%Zd#b3]aWJ1aC*lxV^R/׋9Q%DG2Kј؁SKH3 6gWUلozcT)/V+)%XiMw6hXEC!\|q^`?d &M*%"i"H8sneo ! K )YHdͺu\b# ߜ4bпjzy!,&,:B -5@0BFn "dAA #OԮ5 S)Ȋ^UR|;j"6FNg#V{/qgXH~<9yM*t F}+S4p=r!Ql5Lei*l[H!!Vc@U$0y<ڭ&INkQbcJ C\QobM19 j(,o71y%Ӗmce&b̼BF>nJ܉1YJ?׌ RHpBCΙ%'VaW08PV3*jmĞ:!⺐Q\6?$s"m>5 ̱B[GΓ=8̦kwBuZi!G5Hח6[`.h=W#H_<ز D?%+G;϶+`i-#3틘NqGj*uǥh*Ҝ-:$sB3 h٬XW-Zd1Xp)xʼ,{ƶK*UI3MiZzak~[ ]`g v .Lū\`cnCp2 *II%-:jb_Pi]ޓe:R}l8s]_lweiQ=3VƑWeVö6CM -E ,ҨwqО .NjU-N PZx.O@(jC"5󂼳avԷIB)J.+gP7h~[ V#[AG= >.C`']ZqeY\FFa<ӈXS#LT(Q*}D3JB zIo5Q2oXQˋ1iLk,[X{+WW{^E[Dm55uKcTKHEL!jSAO$ACU~+l( xwr+@ yEE}Yzr$_LU,QQ6RLjKΕZbyg9JنlPWb;2`5⍔&n(B9#&jܥQsl%E/1IN:tP35c/U*I-ZsV%K;Ki0'ީR.K5jY䈒 ɉH1dw('Rڅ Ij,4NCՃ[!&'3UxkrjN}킫M]EB~je:ga~Ufv1 w֟`2i&e[ O_.pru (ޮfWꕬK?H}l5|DmS);A {C3Ȯ@КϚLIh3p`l%&w(&{)]idw!M /ōƈeV+mQE)\śnH8GJCt.څxlکy@EŒ!164,i4-z4BUJ:IXN5Z}3 U:Jc"Uh^Ա>?PNl:L_1&_zx*-bѯ X.Y`s ڙICklH rޏ+3&{wT@ 9xPyYtzT{^܈&ͼ:> *D;j 6bm _DMh{ZT @`el:O:d+ӓ1aeΈ`.}#Ko~aj5t"oTR]Z Th"4ly?YB|H $$Aq,z!+1rҥ ȁ̆hϊMCķl $yD>J&) !Q Hb Tx8\CSjWN~PmIWX];}t*Lp'B7gH]}D'm+cIZ/k£RlAجWrkiJ1biXW4,؇z$hwՒ[dL3[RW+/ي* ,*Eϼ_%l:g1)|쨈ڷWMPVV] H7,KhIW54%5{apk_Um{ȇ酚!{ԢRݨiK)qHT ~ƳkUNm~(T)@t`f!" 2]3l;6*B҉aa!HġQ6QS$k,sς&s4Tc_|JYk6ϗ, s/I+@/{by^F\4bTF\surp3xٶA⩳RrjFUw+=C Zǡʵr+/\~%@%R"pQ,lS 8!0C>f3rBF !"Qq*!y\ub߭}ۊb4Yn$B*Q!/܀jpe">3^Ɍ\]|fE-&NKL/ lh/BL-dQ3 hMjۚL9F" ɲ_TCDs ;- "D(,)EG0D*fչI\-nkcʊ'gC=*URX89KTCkFfhcyH)ͣ5Fbꢮo:IENDB`pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/000077500000000000000000000000001360274650100213245ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/000077500000000000000000000000001360274650100231075ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.af_za/000077500000000000000000000000001360274650100275775ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.af_za/strings.po000066400000000000000000000051161360274650100316330ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Afrikaans (South Africa) (http://www.transifex.com/projects/p/kodi-main/language/af_ZA/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: af_ZA\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "NextPVR Gasheernaam" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "NextPVR Poort (gewoonlik 8866 of 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "NextPVR PinKode" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Stel Tydskuif met Lewendige TV in staat" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Laai TV Gids Kunswerk af" msgctxt "#30040" msgid "Connection" msgstr "Konneksie" msgctxt "#30041" msgid "Advanced" msgstr "Gevorderde" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "NextPVR bediener is te oud." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Opgradeer na '%s' of hoër!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Konneksie het gefaal. Verkeerde PIN?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Instemmer nie meer beskikbaar" msgctxt "#30140" msgid "One time (manual)" msgstr "Een keer (handrolies)" msgctxt "#30141" msgid "One time (guide)" msgstr "Een keer (gids)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Herhalend (handrolies)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Herhalend (gids)" msgctxt "#30144" msgid "Child Recording" msgstr "Kind Opname" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Herhalend (sleutelwoord)" msgctxt "#30150" msgid "All Recordings" msgstr "Alle opnames" msgctxt "#30151" msgid "1 Recording" msgstr "1 Opname" msgctxt "#30152" msgid "2 Recordings" msgstr "2 Opnames" msgctxt "#30153" msgid "3 Recordings" msgstr "3 Opnames" msgctxt "#30154" msgid "4 Recordings" msgstr "4 Opnames" msgctxt "#30155" msgid "5 Recordings" msgstr "5 Opnames" msgctxt "#30156" msgid "6 Recordings" msgstr "6 Opnames" msgctxt "#30157" msgid "7 Recordings" msgstr "7 Opnames" msgctxt "#30158" msgid "10 Recordings" msgstr "10 Opnames" msgctxt "#30160" msgid "New Only" msgstr "Slegs Nuut" msgctxt "#30161" msgid "All" msgstr "Almal" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.am_et/000077500000000000000000000000001360274650100276045ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.am_et/strings.po000066400000000000000000000024221360274650100316350ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Amharic (Ethiopia) (http://www.transifex.com/projects/p/kodi-main/language/am_ET/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: am_ET\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" msgctxt "#30040" msgid "Connection" msgstr "ግንኙነት " msgctxt "#30041" msgid "Advanced" msgstr "የረቀቀ" msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "ማሻሻያ ወደ '%s' ወይንም ከፍተኛ!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "ግንኙነቱ አልተሳካም የተሳሳተ PIN?" msgctxt "#30140" msgid "One time (manual)" msgstr "አንድ ጊዜ (በ እጅ)" msgctxt "#30141" msgid "One time (guide)" msgstr "አንድ ጊዜ (መምሪያ)" msgctxt "#30150" msgid "All Recordings" msgstr "ሁሉንም መቅረጫ " msgctxt "#30161" msgid "All" msgstr "ሁሉንም" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.ar_sa/000077500000000000000000000000001360274650100276045ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.ar_sa/strings.po000066400000000000000000000015011360274650100316320ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Arabic (Saudi Arabia) (http://www.transifex.com/projects/p/kodi-main/language/ar_SA/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ar_SA\n" "Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" msgctxt "#30041" msgid "Advanced" msgstr "منقدم" msgctxt "#30161" msgid "All" msgstr "الكل" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.az_az/000077500000000000000000000000001360274650100276235ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.az_az/strings.po000066400000000000000000000012721360274650100316560ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Azerbaijani (Azerbaijan) (http://www.transifex.com/projects/p/kodi-main/language/az_AZ/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: az_AZ\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30040" msgid "Connection" msgstr "Qoşulma" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.be_by/000077500000000000000000000000001360274650100275775ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.be_by/strings.po000066400000000000000000000030661360274650100316350ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Belarusian (Belarus) (http://www.transifex.com/projects/p/kodi-main/language/be_BY/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: be_BY\n" "Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "NextPVR Hostname" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "NextPVR Port (usually 8866 or 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "NextPVR PinCode" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Enable TimeShift with Live TV" msgctxt "#30040" msgid "Connection" msgstr "Злучэньне" msgctxt "#30041" msgid "Advanced" msgstr "Advanced" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "NextPVR server is too old." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Upgrade to '%s' or higher!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Connection failed. Incorrect PIN?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Tuner no longer available" msgctxt "#30161" msgid "All" msgstr "Усе" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.bg_bg/000077500000000000000000000000001360274650100275575ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.bg_bg/strings.po000066400000000000000000000057711360274650100316220ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Bulgarian (Bulgaria) (http://www.transifex.com/projects/p/kodi-main/language/bg_BG/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: bg_BG\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "Име на хоста на NextPVR" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "Порт за NextPVR (обикн. 8866 или 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "ПИН-код за NextPVR" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Изместване във времето за ТВ на живо" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Сваляне на изображения за справочника" msgctxt "#30040" msgid "Connection" msgstr "Връзка" msgctxt "#30041" msgid "Advanced" msgstr "Допълнителни" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "Сървърът NextPVR е твърде стар." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Обновете до версия „%s“ или по-нова!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Неуспешно свързване. Неправилен ПИН-код?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Тунерът вече не е наличен" msgctxt "#30140" msgid "One time (manual)" msgstr "Еднократно (ръчно)" msgctxt "#30141" msgid "One time (guide)" msgstr "Еднократно (справочник)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Повтаряемо (ръчно)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Повтаряемо (справочник)" msgctxt "#30144" msgid "Child Recording" msgstr "Дъщерен запис" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Повтаряемо (ключова дума)" msgctxt "#30150" msgid "All Recordings" msgstr "Всички записи" msgctxt "#30151" msgid "1 Recording" msgstr "1 запис" msgctxt "#30152" msgid "2 Recordings" msgstr "2 записа" msgctxt "#30153" msgid "3 Recordings" msgstr "3 записа" msgctxt "#30154" msgid "4 Recordings" msgstr "4 записа" msgctxt "#30155" msgid "5 Recordings" msgstr "5 записа" msgctxt "#30156" msgid "6 Recordings" msgstr "6 записа" msgctxt "#30157" msgid "7 Recordings" msgstr "7 записа" msgctxt "#30158" msgid "10 Recordings" msgstr "10 записа" msgctxt "#30160" msgid "New Only" msgstr "Само новите" msgctxt "#30161" msgid "All" msgstr "Всички" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.bs_ba/000077500000000000000000000000001360274650100275655ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.bs_ba/strings.po000066400000000000000000000014071360274650100316200ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Bosnian (Bosnia and Herzegovina) (http://www.transifex.com/projects/p/kodi-main/language/bs_BA/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: bs_BA\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" msgctxt "#30161" msgid "All" msgstr "Sve" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.ca_es/000077500000000000000000000000001360274650100275715ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.ca_es/strings.po000066400000000000000000000050441360274650100316250ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Catalan (Spain) (http://www.transifex.com/projects/p/kodi-main/language/ca_ES/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ca_ES\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "Nom d'amfitrió de NextPVR" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "Port del NextPVR (normalment 8866 o 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "Codi PIN del NextPVR" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Habilita els salts en el temps amb la TV en directe" msgctxt "#30040" msgid "Connection" msgstr "Connexió" msgctxt "#30041" msgid "Advanced" msgstr "Avançat" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "El servidor NextPVR és massa antic." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Actualitzeu a '%s' o superior!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Ha fallat la connexió. PIN incorrecte?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "El sintonitzador ja no està disponible" msgctxt "#30140" msgid "One time (manual)" msgstr "Un cop (manual)" msgctxt "#30141" msgid "One time (guide)" msgstr "Un cop (guia)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Repetició (manual)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Repetició (guia)" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Repetició (paraula clau)" msgctxt "#30150" msgid "All Recordings" msgstr "Tots els enregistraments" msgctxt "#30151" msgid "1 Recording" msgstr "1 enregistrament" msgctxt "#30152" msgid "2 Recordings" msgstr "2 enregistraments" msgctxt "#30153" msgid "3 Recordings" msgstr "3 enregistraments" msgctxt "#30154" msgid "4 Recordings" msgstr "4 enregistraments" msgctxt "#30155" msgid "5 Recordings" msgstr "5 enregistraments" msgctxt "#30156" msgid "6 Recordings" msgstr "6 enregistraments" msgctxt "#30157" msgid "7 Recordings" msgstr "7 enregistraments" msgctxt "#30158" msgid "10 Recordings" msgstr "10 enregistraments" msgctxt "#30160" msgid "New Only" msgstr "Només nous" msgctxt "#30161" msgid "All" msgstr "Tot" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.cs_cz/000077500000000000000000000000001360274650100276205ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.cs_cz/strings.po000066400000000000000000000053161360274650100316560ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Czech (Czech Republic) (http://www.transifex.com/projects/p/kodi-main/language/cs_CZ/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: cs_CZ\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "Název hostitele NextPVR" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "Port NextPVR (obvykle 8866 nebo 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "Kód PIN NextPVR" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Povolit časový posun u živého visílání" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Stáhnout artwork pro televizní program" msgctxt "#30040" msgid "Connection" msgstr "Spojení" msgctxt "#30041" msgid "Advanced" msgstr "Rozšířené" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "Server NextPVR je příliš starý." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Přejděte na verzi „%s“ nebo novější!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Spojení se nepodařilo. Nesprávný PIN?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Tuner už není dostupný" msgctxt "#30140" msgid "One time (manual)" msgstr "Jednorázově (ručně)" msgctxt "#30141" msgid "One time (guide)" msgstr "Jednorázově (program)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Opakovaný (ručně)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Opakovaný (program)" msgctxt "#30144" msgid "Child Recording" msgstr "Dětské nahrávky" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Opakovaný (klíčové slovo)" msgctxt "#30150" msgid "All Recordings" msgstr "Všechny nahrávky" msgctxt "#30151" msgid "1 Recording" msgstr "1 nahrávka" msgctxt "#30152" msgid "2 Recordings" msgstr "2 nahrávky" msgctxt "#30153" msgid "3 Recordings" msgstr "3 nahrávky" msgctxt "#30154" msgid "4 Recordings" msgstr "4 nahrávky" msgctxt "#30155" msgid "5 Recordings" msgstr "5 nahrávek" msgctxt "#30156" msgid "6 Recordings" msgstr "6 nahrávek" msgctxt "#30157" msgid "7 Recordings" msgstr "7 nahrávek" msgctxt "#30158" msgid "10 Recordings" msgstr "10 nahrávek" msgctxt "#30160" msgid "New Only" msgstr "Pouze nové" msgctxt "#30161" msgid "All" msgstr "Vše" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.cy_gb/000077500000000000000000000000001360274650100276025ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.cy_gb/strings.po000066400000000000000000000052541360274650100316410ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Welsh (United Kingdom) (http://www.transifex.com/projects/p/kodi-main/language/cy_GB/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: cy_GB\n" "Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3;\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "Enw Gwesteiwr NextPVR" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "Porth NextPVR (8866 neu 7799 fel rheol)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "Cod PIN NextPVR" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Galluogi SymudAmser gyda Theledu Byw?" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Lawrlwytho Gwaith Celf y Canllaw Teledu" msgctxt "#30040" msgid "Connection" msgstr "Cysylltiad" msgctxt "#30041" msgid "Advanced" msgstr "Uwch" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "Mae'r gweinydd NextPVR yn rhy hen." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Diweddarwch i '%s' neu'n uwch!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Methodd y cysylltiad. PIN anghywir?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Tiwniwr ddim ar gael" msgctxt "#30140" msgid "One time (manual)" msgstr "Unwaith (â llaw)" msgctxt "#30141" msgid "One time (guide)" msgstr "Unwaith (gydag arweiniad)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Ailadrodd (â llaw)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Ailadrodd (gydag arweiniad)" msgctxt "#30144" msgid "Child Recording" msgstr "Recordio Plentyn" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Ailadrodd (allweddair)" msgctxt "#30150" msgid "All Recordings" msgstr "Pob Recordiad" msgctxt "#30151" msgid "1 Recording" msgstr "1 Recordiad" msgctxt "#30152" msgid "2 Recordings" msgstr "2 Recordiad" msgctxt "#30153" msgid "3 Recordings" msgstr "3 Recordiad" msgctxt "#30154" msgid "4 Recordings" msgstr "4 Recordiad" msgctxt "#30155" msgid "5 Recordings" msgstr "5 Recordiad" msgctxt "#30156" msgid "6 Recordings" msgstr "6 Recordiad" msgctxt "#30157" msgid "7 Recordings" msgstr "7 Recordiad" msgctxt "#30158" msgid "10 Recordings" msgstr "10 Recordiad" msgctxt "#30160" msgid "New Only" msgstr "Newydd yn Unig" msgctxt "#30161" msgid "All" msgstr "Pob un" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.da_dk/000077500000000000000000000000001360274650100275615ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.da_dk/strings.po000066400000000000000000000043321360274650100316140ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Danish (Denmark) (http://www.transifex.com/projects/p/kodi-main/language/da_DK/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: da_DK\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "NextPVR værtsnavn" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "NextPVR port (almindeligvis 8866 eller 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "NextPVR PinKode" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Aktiver Tidsforskydelse af Direkte TV" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Hent TV guide grafik" msgctxt "#30040" msgid "Connection" msgstr "Forbindelse" msgctxt "#30041" msgid "Advanced" msgstr "Avanceret" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "NextPVR server er for gammel." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Opgrader til '%s' eller højere!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Forbindelse mislykkedes. Forkert Pinkode?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Tuneren er ikke længere tilgængelig" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Gentagende (vejledning)" msgctxt "#30150" msgid "All Recordings" msgstr "Alle Optagelser" msgctxt "#30151" msgid "1 Recording" msgstr "1 optagelse" msgctxt "#30152" msgid "2 Recordings" msgstr "2 optagelser" msgctxt "#30153" msgid "3 Recordings" msgstr "3 optagelser" msgctxt "#30154" msgid "4 Recordings" msgstr "4 optagelser" msgctxt "#30155" msgid "5 Recordings" msgstr "5 optagelser" msgctxt "#30156" msgid "6 Recordings" msgstr "6 optagelser" msgctxt "#30157" msgid "7 Recordings" msgstr "7 optagelser" msgctxt "#30158" msgid "10 Recordings" msgstr "10 optagelser" msgctxt "#30161" msgid "All" msgstr "Alle" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.de_de/000077500000000000000000000000001360274650100275575ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.de_de/strings.po000066400000000000000000000051561360274650100316170ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: German (Germany) (http://www.transifex.com/projects/p/kodi-main/language/de_DE/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: de_DE\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "NextPVR Hostname" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "NextPVR Port (normalerweise 8866 oder 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "NextPVR PinCode" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Timeshift für Live TV aktivieren" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "TV-Guide Artwork herunterladen" msgctxt "#30040" msgid "Connection" msgstr "Verbindung" msgctxt "#30041" msgid "Advanced" msgstr "Erweitert" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "NextPVR-Server ist zu alt." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Upgrade auf '%s' oder höher!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Verbindung fehlgeschlagen. Ist die PIN richtig?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Tuner nicht länger verfügbar" msgctxt "#30140" msgid "One time (manual)" msgstr "Einmalig (Manuell)" msgctxt "#30141" msgid "One time (guide)" msgstr "Einmalig (Guide)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Mehrmalig (Manuell)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Mehrmalig (Guide)" msgctxt "#30144" msgid "Child Recording" msgstr "Untergeordnete Aufnahme" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Mehrmalig (Schlüsselwort)" msgctxt "#30150" msgid "All Recordings" msgstr "Alle Aufnahmen" msgctxt "#30151" msgid "1 Recording" msgstr "1 Aufnahme" msgctxt "#30152" msgid "2 Recordings" msgstr "2 Aufnahmen" msgctxt "#30153" msgid "3 Recordings" msgstr "3 Aufnahmen" msgctxt "#30154" msgid "4 Recordings" msgstr "4 Aufnahmen" msgctxt "#30155" msgid "5 Recordings" msgstr "5 Aufnahmen" msgctxt "#30156" msgid "6 Recordings" msgstr "6 Aufnahmen" msgctxt "#30157" msgid "7 Recordings" msgstr "7 Aufnahmen" msgctxt "#30158" msgid "10 Recordings" msgstr "10 Aufnahmen" msgctxt "#30160" msgid "New Only" msgstr "Nur Neue" msgctxt "#30161" msgid "All" msgstr "Alle" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.el_gr/000077500000000000000000000000001360274650100276075ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.el_gr/strings.po000066400000000000000000000051741360274650100316470ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Greek (Greece) (http://www.transifex.com/projects/p/kodi-main/language/el_GR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: el_GR\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "Όνομα Υπολογιστή του NextPVR" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "Θύρα NextPVR (συνήθως 8866 ή 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "Κωδικός PIN του NextPVR" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Ενεργοποίηση TimeShift με Live TV" msgctxt "#30040" msgid "Connection" msgstr "Σύνδεση" msgctxt "#30041" msgid "Advanced" msgstr "Για προχωρημένους" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "Ο διακομιστής του NextPVR είναι πολύ παλιός." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Αναβαθμίστε στην έκδοση '%s' ή ανώτερη!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Αποτυχία σύνδεσης. Λανθασμένο PIN;" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Ο δέκτης (tuner) δεν είναι πλέον διαθέσιμος" msgctxt "#30140" msgid "One time (manual)" msgstr "Μία φορά (χειροποίητα)" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "επαναλαμβάνοντας (λέξη κλειδί)" msgctxt "#30150" msgid "All Recordings" msgstr "Όλες οι Εγγραφές" msgctxt "#30151" msgid "1 Recording" msgstr "1 Εγγραφή" msgctxt "#30152" msgid "2 Recordings" msgstr "2 Εγγραφές" msgctxt "#30153" msgid "3 Recordings" msgstr "3 Εγγραφές" msgctxt "#30154" msgid "4 Recordings" msgstr "4 Εγγραφές" msgctxt "#30155" msgid "5 Recordings" msgstr "5 Εγγραφές" msgctxt "#30156" msgid "6 Recordings" msgstr "6 Εγγραφές" msgctxt "#30157" msgid "7 Recordings" msgstr "7 Εγγραφές" msgctxt "#30158" msgid "10 Recordings" msgstr "10 Εγγραφές" msgctxt "#30160" msgid "New Only" msgstr "Μόνον νεα (καινούργια)" msgctxt "#30161" msgid "All" msgstr "Όλα" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.en_au/000077500000000000000000000000001360274650100276065ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.en_au/strings.po000066400000000000000000000030411360274650100316350ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: English (Australia) (http://www.transifex.com/projects/p/kodi-main/language/en_AU/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: en_AU\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "NextPVR Hostname" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "NextPVR Port (usually 8866 or 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "NextPVR PinCode" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Enable TimeShift with Live TV" msgctxt "#30040" msgid "Connection" msgstr "Connection" msgctxt "#30041" msgid "Advanced" msgstr "Advanced" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "NextPVR server is too old." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Upgrade to '%s' or higher!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Connection failed. Incorrect PIN?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Tuner no longer available" msgctxt "#30150" msgid "All Recordings" msgstr "All Recordings" msgctxt "#30161" msgid "All" msgstr "All" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.en_gb/000077500000000000000000000000001360274650100275715ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.en_gb/strings.po000066400000000000000000000054041360274650100316250ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: English (United Kingdom) (http://www.transifex.com/projects/p/kodi-main/language/en_GB/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: en_GB\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "" #empty strings from id 30005 to 30039 msgctxt "#30040" msgid "Connection" msgstr "" msgctxt "#30041" msgid "Advanced" msgstr "" #empty strings from id 30042 to 30049 msgctxt "#30050" msgid "NextPVR server is too old." msgstr "" msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "" msgctxt "#30053" msgid "Tuner no longer available" msgstr "" #empty strings from id 30054 to 30139 msgctxt "#30140" msgid "One time (manual)" msgstr "" msgctxt "#30141" msgid "One time (guide)" msgstr "" msgctxt "#30142" msgid "Repeating (manual)" msgstr "" msgctxt "#30143" msgid "Repeating (guide)" msgstr "" msgctxt "#30144" msgid "Child Recording" msgstr "" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "" #empty strings from id 30146 to 30149 msgctxt "#30150" msgid "All Recordings" msgstr "" msgctxt "#30151" msgid "1 Recording" msgstr "" msgctxt "#30152" msgid "2 Recordings" msgstr "" msgctxt "#30153" msgid "3 Recordings" msgstr "" msgctxt "#30154" msgid "4 Recordings" msgstr "" msgctxt "#30155" msgid "5 Recordings" msgstr "" msgctxt "#30156" msgid "6 Recordings" msgstr "" msgctxt "#30157" msgid "7 Recordings" msgstr "" msgctxt "#30158" msgid "10 Recordings" msgstr "" #empty string with id 30159 msgctxt "#30160" msgid "New Only" msgstr "" msgctxt "#30161" msgid "All" msgstr "" msgctxt "#30162" msgid "Pre-buffer time in seconds" msgstr "" msgctxt "#30163" msgid "Enable Wake On LAN" msgstr "" msgctxt "#30164" msgid "Wait for server after wake in seconds" msgstr "" msgctxt "#30165" msgid "NextPVR server MAC address" msgstr "" msgctxt "#30166" msgid "Failed Recordings" msgstr "" msgctxt "#30167" msgid "Live TV Chunk Size" msgstr "" msgctxt "#30168" msgid "Recording Chunk Size" msgstr "" msgctxt "#30169" msgid "Kodi Style Recordings" msgstr ""pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.en_nz/000077500000000000000000000000001360274650100276305ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.en_nz/strings.po000066400000000000000000000051011360274650100316560ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: English (New Zealand) (http://www.transifex.com/projects/p/kodi-main/language/en_NZ/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: en_NZ\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "NextPVR Hostname" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "NextPVR Port (usually 8866 or 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "NextPVR PinCode" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Enable TimeShift with Live TV" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Download TV Guide Artwork" msgctxt "#30040" msgid "Connection" msgstr "Connection" msgctxt "#30041" msgid "Advanced" msgstr "Advanced" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "NextPVR server is too old." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Upgrade to '%s' or higher!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Connection failed. Incorrect PIN?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Tuner no longer available" msgctxt "#30140" msgid "One time (manual)" msgstr "One time (manual)" msgctxt "#30141" msgid "One time (guide)" msgstr "One time (guide)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Repeating (manual)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Repeating (guide)" msgctxt "#30144" msgid "Child Recording" msgstr "Child Recording" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Repeating (keyword)" msgctxt "#30150" msgid "All Recordings" msgstr "All Recordings" msgctxt "#30151" msgid "1 Recording" msgstr "1 Recording" msgctxt "#30152" msgid "2 Recordings" msgstr "2 Recordings" msgctxt "#30153" msgid "3 Recordings" msgstr "3 Recordings" msgctxt "#30154" msgid "4 Recordings" msgstr "4 Recordings" msgctxt "#30155" msgid "5 Recordings" msgstr "5 Recordings" msgctxt "#30156" msgid "6 Recordings" msgstr "6 Recordings" msgctxt "#30157" msgid "7 Recordings" msgstr "7 Recordings" msgctxt "#30158" msgid "10 Recordings" msgstr "10 Recordings" msgctxt "#30160" msgid "New Only" msgstr "New Only" msgctxt "#30161" msgid "All" msgstr "All" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.en_us/000077500000000000000000000000001360274650100276305ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.en_us/strings.po000066400000000000000000000051031360274650100316600ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: English (United States) (http://www.transifex.com/projects/p/kodi-main/language/en_US/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: en_US\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "NextPVR Hostname" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "NextPVR Port (usually 8866 or 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "NextPVR PinCode" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Enable TimeShift with Live TV" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Download TV Guide Artwork" msgctxt "#30040" msgid "Connection" msgstr "Connection" msgctxt "#30041" msgid "Advanced" msgstr "Advanced" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "NextPVR server is too old." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Upgrade to '%s' or higher!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Connection failed. Incorrect PIN?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Tuner no longer available" msgctxt "#30140" msgid "One time (manual)" msgstr "One time (manual)" msgctxt "#30141" msgid "One time (guide)" msgstr "One time (guide)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Repeating (manual)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Repeating (guide)" msgctxt "#30144" msgid "Child Recording" msgstr "Child Recording" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Repeating (keyword)" msgctxt "#30150" msgid "All Recordings" msgstr "All Recordings" msgctxt "#30151" msgid "1 Recording" msgstr "1 Recording" msgctxt "#30152" msgid "2 Recordings" msgstr "2 Recordings" msgctxt "#30153" msgid "3 Recordings" msgstr "3 Recordings" msgctxt "#30154" msgid "4 Recordings" msgstr "4 Recordings" msgctxt "#30155" msgid "5 Recordings" msgstr "5 Recordings" msgctxt "#30156" msgid "6 Recordings" msgstr "6 Recordings" msgctxt "#30157" msgid "7 Recordings" msgstr "7 Recordings" msgctxt "#30158" msgid "10 Recordings" msgstr "10 Recordings" msgctxt "#30160" msgid "New Only" msgstr "New Only" msgctxt "#30161" msgid "All" msgstr "All" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.eo/000077500000000000000000000000001360274650100271225ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.eo/strings.po000066400000000000000000000012421360274650100311520ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Esperanto (http://www.transifex.com/projects/p/kodi-main/language/eo/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: eo\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30161" msgid "All" msgstr "ĉiom" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.es_ar/000077500000000000000000000000001360274650100276105ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.es_ar/strings.po000066400000000000000000000031351360274650100316430ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Spanish (Argentina) (http://www.transifex.com/projects/p/kodi-main/language/es_AR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: es_AR\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "Nombre del servidor NextPVR" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "Puerto NextPVR (usualmente 8866 o 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "Código Pin de NextPVR" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Activar TimeShift con TV en vivo" msgctxt "#30040" msgid "Connection" msgstr "Conexión" msgctxt "#30041" msgid "Advanced" msgstr "Avanzado" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "El servidor NextPVR es muy antiguo." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "¡Actualice a '%s' o posterior!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Conexión fallida. ¿PIN incorrecto?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Sintonizador ya no está disponible" msgctxt "#30150" msgid "All Recordings" msgstr "Todas las grabaciones" msgctxt "#30161" msgid "All" msgstr "Todos" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.es_es/000077500000000000000000000000001360274650100276155ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.es_es/strings.po000066400000000000000000000052331360274650100316510ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Spanish (Spain) (http://www.transifex.com/projects/p/kodi-main/language/es_ES/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: es_ES\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "Nombre del servidor NextPVR" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "Puerto NextPVR (normalmente 8866 o 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "Código Pin de NextPVR" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Activar TimeShift con TV en vivo" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Descargar artwork para la guía" msgctxt "#30040" msgid "Connection" msgstr "Conexión" msgctxt "#30041" msgid "Advanced" msgstr "Avanzado" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "El servidor NextPVR es muy antiguo." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "¡Actualice a '%s' o posterior!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Conexión fallida. ¿PIN incorrecto?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Sintonizador ya no está disponible" msgctxt "#30140" msgid "One time (manual)" msgstr "Una vez (manual)" msgctxt "#30141" msgid "One time (guide)" msgstr "Una vez (Guía)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Repetición (Manual)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Repetición (Guía)" msgctxt "#30144" msgid "Child Recording" msgstr "Grabación para niños" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Repetición (palabra clave)" msgctxt "#30150" msgid "All Recordings" msgstr "Todas las grabaciones" msgctxt "#30151" msgid "1 Recording" msgstr "1 Grabación" msgctxt "#30152" msgid "2 Recordings" msgstr "2 Grabaciones" msgctxt "#30153" msgid "3 Recordings" msgstr "3 Grabaciones" msgctxt "#30154" msgid "4 Recordings" msgstr "4 Grabaciones" msgctxt "#30155" msgid "5 Recordings" msgstr "5 Grabaciones" msgctxt "#30156" msgid "6 Recordings" msgstr "6 Grabaciones" msgctxt "#30157" msgid "7 Recordings" msgstr "7 Grabaciones" msgctxt "#30158" msgid "10 Recordings" msgstr "10 Grabaciones" msgctxt "#30160" msgid "New Only" msgstr "Sólo Nuevos" msgctxt "#30161" msgid "All" msgstr "Todos" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.es_mx/000077500000000000000000000000001360274650100276325ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.es_mx/strings.po000066400000000000000000000052321360274650100316650ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Spanish (Mexico) (http://www.transifex.com/projects/p/kodi-main/language/es_MX/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: es_MX\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "Nombre de host de NextPVR" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "Puerto de NextPVR (usualmente 8866 o 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "PinCode de NextPVR" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Activar TimeShift con TV en directo" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Descargar Artwork de Guía de TV" msgctxt "#30040" msgid "Connection" msgstr "Conexión" msgctxt "#30041" msgid "Advanced" msgstr "Avanzado" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "El servidor de NextPVR es muy antiguo" msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "¡Actualice a '%s' o superior!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Conexión fallida. ¿PIN incorrecto?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "El sintonizador ya no está disponible" msgctxt "#30140" msgid "One time (manual)" msgstr "Una vez (manual)" msgctxt "#30141" msgid "One time (guide)" msgstr "Una vez (guía)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Repetición (manual)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Repitiendo (guía)" msgctxt "#30144" msgid "Child Recording" msgstr "Grabación infantil" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Repetición (palabra clave)" msgctxt "#30150" msgid "All Recordings" msgstr "Todas las grabaciones" msgctxt "#30151" msgid "1 Recording" msgstr "1 Grabación" msgctxt "#30152" msgid "2 Recordings" msgstr "2 Grabaciones" msgctxt "#30153" msgid "3 Recordings" msgstr "3 Grabaciones" msgctxt "#30154" msgid "4 Recordings" msgstr "4 Grabaciones" msgctxt "#30155" msgid "5 Recordings" msgstr "5 Grabaciones" msgctxt "#30156" msgid "6 Recordings" msgstr "6 Grabaciones" msgctxt "#30157" msgid "7 Recordings" msgstr "7 Grabaciones" msgctxt "#30158" msgid "10 Recordings" msgstr "10 Grabaciones" msgctxt "#30160" msgid "New Only" msgstr "Solo nuevo" msgctxt "#30161" msgid "All" msgstr "Todos" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.et_ee/000077500000000000000000000000001360274650100276005ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.et_ee/strings.po000066400000000000000000000027621360274650100316400ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Estonian (Estonia) (http://www.transifex.com/projects/p/kodi-main/language/et_EE/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: et_EE\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "NextPVR hosti nimi" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "NextPVR port (tavaliselt 8866 või 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "NextPVR PinCode" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Luba TV ajanihutus" msgctxt "#30040" msgid "Connection" msgstr "Ühendus" msgctxt "#30041" msgid "Advanced" msgstr "Põhjalikumad seaded" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "NextPVR server on liiga vana." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Uuenda versioonile '%s' või uuemale!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Ühendus nurjus. Vale PIN?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Tüüner ei ole enam saadaval" msgctxt "#30161" msgid "All" msgstr "Kõik" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.eu_es/000077500000000000000000000000001360274650100276175ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.eu_es/strings.po000066400000000000000000000013441360274650100316520ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Basque (Spain) (http://www.transifex.com/projects/p/kodi-main/language/eu_ES/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: eu_ES\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30041" msgid "Advanced" msgstr "Aurreratua" msgctxt "#30161" msgid "All" msgstr "Denak" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.fa_af/000077500000000000000000000000001360274650100275535ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.fa_af/strings.po000066400000000000000000000014421360274650100316050ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Persian (Afghanistan) (http://www.transifex.com/projects/p/kodi-main/language/fa_AF/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: fa_AF\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30040" msgid "Connection" msgstr "اتصال" msgctxt "#30041" msgid "Advanced" msgstr "پیشرفته" msgctxt "#30161" msgid "All" msgstr "همه" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.fa_ir/000077500000000000000000000000001360274650100275775ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.fa_ir/strings.po000066400000000000000000000013421360274650100316300ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Persian (Iran) (http://www.transifex.com/projects/p/kodi-main/language/fa_IR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: fa_IR\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30041" msgid "Advanced" msgstr "پیشرفته" msgctxt "#30161" msgid "All" msgstr "همه" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.fi_fi/000077500000000000000000000000001360274650100275735ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.fi_fi/strings.po000066400000000000000000000051721360274650100316310ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Finnish (Finland) (http://www.transifex.com/projects/p/kodi-main/language/fi_FI/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: fi_FI\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "NextPVR-isäntänimi" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "NextPVR-portti (yleensä 8866 tai 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "NextPVR-PIN-koodi" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Käytä ajansiirtoa" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Lataa ohjelmaoppaan kuvat" msgctxt "#30040" msgid "Connection" msgstr "Yhteys" msgctxt "#30041" msgid "Advanced" msgstr "Lisäasetukset" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "NextPVR-palvelimen versio on liian vanha." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Päivitä vähintään versioon '%s'!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Yhteys epäonnistui. Väärä PIN-koodi?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Viritin ei ole enää saatavilla" msgctxt "#30140" msgid "One time (manual)" msgstr "Kerran (manuaalinen)" msgctxt "#30141" msgid "One time (guide)" msgstr "Kerran (opas)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Toistuva (manuaalinen)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Toistuva (opas)" msgctxt "#30144" msgid "Child Recording" msgstr "Lapsitallennus" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Toistuva (avainsana)" msgctxt "#30150" msgid "All Recordings" msgstr "Kaikki tallennukset" msgctxt "#30151" msgid "1 Recording" msgstr "1 tallennus" msgctxt "#30152" msgid "2 Recordings" msgstr "2 tallennusta" msgctxt "#30153" msgid "3 Recordings" msgstr "3 tallennusta" msgctxt "#30154" msgid "4 Recordings" msgstr "4 tallennusta" msgctxt "#30155" msgid "5 Recordings" msgstr "5 tallennusta" msgctxt "#30156" msgid "6 Recordings" msgstr "6 tallennusta" msgctxt "#30157" msgid "7 Recordings" msgstr "7 tallennusta" msgctxt "#30158" msgid "10 Recordings" msgstr "10 tallennusta" msgctxt "#30160" msgid "New Only" msgstr "Vain uudet" msgctxt "#30161" msgid "All" msgstr "Kaikki" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.fo_fo/000077500000000000000000000000001360274650100276075ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.fo_fo/strings.po000066400000000000000000000012641360274650100316430ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Faroese (Faroe Islands) (http://www.transifex.com/projects/p/kodi-main/language/fo_FO/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: fo_FO\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30161" msgid "All" msgstr "Alt" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.fr_ca/000077500000000000000000000000001360274650100275715ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.fr_ca/strings.po000066400000000000000000000053731360274650100316320ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: French (Canada) (http://www.transifex.com/projects/p/kodi-main/language/fr_CA/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: fr_CA\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "Nom d’hôte de NextPVR" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "Port de NextPVR (habituellement 8866 ou 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "NIP de NextPVR" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Activer le décalage temporel avec la télé en direct" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Télécharger les illustrations du guide télé" msgctxt "#30040" msgid "Connection" msgstr "Connexion" msgctxt "#30041" msgid "Advanced" msgstr "Avancé" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "Le serveur NextPVR est trop ancien." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Mettre à niveau vers « %s » ou ultérieure !" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Échec de connexion. NIP erroné ?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Le syntonisateur n’est plus disponible" msgctxt "#30140" msgid "One time (manual)" msgstr "Une fois (manuelle)" msgctxt "#30141" msgid "One time (guide)" msgstr "Une fois (guide)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Répétition (manuelle)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Répétition (guide)" msgctxt "#30144" msgid "Child Recording" msgstr "Enregistrement enfant" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Répétition (mot-clef)" msgctxt "#30150" msgid "All Recordings" msgstr "Tous les enregistrements" msgctxt "#30151" msgid "1 Recording" msgstr "1 enregistrement" msgctxt "#30152" msgid "2 Recordings" msgstr "2 enregistrements" msgctxt "#30153" msgid "3 Recordings" msgstr "3 enregistrements" msgctxt "#30154" msgid "4 Recordings" msgstr "4 enregistrements" msgctxt "#30155" msgid "5 Recordings" msgstr "5 enregistrements" msgctxt "#30156" msgid "6 Recordings" msgstr "6 enregistrements" msgctxt "#30157" msgid "7 Recordings" msgstr "7 enregistrements" msgctxt "#30158" msgid "10 Recordings" msgstr "10 enregistrements" msgctxt "#30160" msgid "New Only" msgstr "Nouveaux seulement" msgctxt "#30161" msgid "All" msgstr "Tout" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.fr_fr/000077500000000000000000000000001360274650100276155ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.fr_fr/strings.po000066400000000000000000000053171360274650100316540ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: French (France) (http://www.transifex.com/projects/p/kodi-main/language/fr_FR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: fr_FR\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "Nom d'hôte NextPVR" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "Port NextPVR (généralement 8866 ou 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "Code PIN NextPVR" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Activer le différé avec la TV en direct" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Télécharger les illustrations du guide TV" msgctxt "#30040" msgid "Connection" msgstr "Connexion" msgctxt "#30041" msgid "Advanced" msgstr "Avancé" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "Le serveur NextPVR est périmé." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Mettre à niveau vers « %s » ou supérieur !" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Connexion échouée. Code Pin incorrect ?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Le tuner n'est plus disponible." msgctxt "#30140" msgid "One time (manual)" msgstr "Unique (manuelle)" msgctxt "#30141" msgid "One time (guide)" msgstr "Unique (guide)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Répétée (manuelle)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Répétée (guide)" msgctxt "#30144" msgid "Child Recording" msgstr "Enregistrement enfant" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Répétée (mot clé)" msgctxt "#30150" msgid "All Recordings" msgstr "Tous les enregistrements" msgctxt "#30151" msgid "1 Recording" msgstr "1 enregistrement" msgctxt "#30152" msgid "2 Recordings" msgstr "2 enregistrements" msgctxt "#30153" msgid "3 Recordings" msgstr "3 enregistrements" msgctxt "#30154" msgid "4 Recordings" msgstr "4 enregistrements" msgctxt "#30155" msgid "5 Recordings" msgstr "5 enregistrements" msgctxt "#30156" msgid "6 Recordings" msgstr "6 enregistrements" msgctxt "#30157" msgid "7 Recordings" msgstr "7 enregistrements" msgctxt "#30158" msgid "10 Recordings" msgstr "8 enregistrements" msgctxt "#30160" msgid "New Only" msgstr "Nouveaux seulement" msgctxt "#30161" msgid "All" msgstr "Tout" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.gl_es/000077500000000000000000000000001360274650100276105ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.gl_es/strings.po000066400000000000000000000051161360274650100316440ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Galician (Spain) (http://www.transifex.com/projects/p/kodi-main/language/gl_ES/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: gl_ES\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "Nome do host NextPVR" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "Porto de NextPVR (en xeral 8866 ou 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "Código PIN de NextPRV" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Activar TimeShift na TV en directo" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Descargar arte para a Guía de TV" msgctxt "#30040" msgid "Connection" msgstr "Conexión" msgctxt "#30041" msgid "Advanced" msgstr "Avanzado" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "O servidor NextPRV é demasiado vello." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Actualizar a '%s' ou superior!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "A conexión fallou. O PIN é incorrecto?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "O sintonizador non está dispoñíbel" msgctxt "#30140" msgid "One time (manual)" msgstr "Unha vez (manual)" msgctxt "#30141" msgid "One time (guide)" msgstr "Unha vez (guía)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Repetición (manual)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Repetición (guía)" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Repetición (palabra chave)" msgctxt "#30150" msgid "All Recordings" msgstr "Todas as gravacións" msgctxt "#30151" msgid "1 Recording" msgstr "1 gravación" msgctxt "#30152" msgid "2 Recordings" msgstr "2 gravación" msgctxt "#30153" msgid "3 Recordings" msgstr "3 gravación" msgctxt "#30154" msgid "4 Recordings" msgstr "4 gravación" msgctxt "#30155" msgid "5 Recordings" msgstr "5 gravación" msgctxt "#30156" msgid "6 Recordings" msgstr "6 gravación" msgctxt "#30157" msgid "7 Recordings" msgstr "7 gravación" msgctxt "#30158" msgid "10 Recordings" msgstr "10 gravación" msgctxt "#30160" msgid "New Only" msgstr "Só novos" msgctxt "#30161" msgid "All" msgstr "Todos" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.he_il/000077500000000000000000000000001360274650100275775ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.he_il/strings.po000066400000000000000000000054141360274650100316340ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Hebrew (Israel) (http://www.transifex.com/projects/p/kodi-main/language/he_IL/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: he_IL\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "שם מארח או כתובת IP" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "פורט (בד\"כ 8866 או 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "סיסמה" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "אפשר טיימשיפט לשידור חי" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "הורד גרפיקת מדריך טלוויזיה" msgctxt "#30040" msgid "Connection" msgstr "חיבור" msgctxt "#30041" msgid "Advanced" msgstr "מתקדם" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "גרסת שרת NextPVR ישנה מדי." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "יש לעדכן לגרסה '%s' ומעלה!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "התחברות נכשלה. אולי הסיסמה שגויה?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "מקלט אינו זמין יותר" msgctxt "#30140" msgid "One time (manual)" msgstr "פעם אחת (ידני)" msgctxt "#30141" msgid "One time (guide)" msgstr "חד פעמי (לוח שידורים)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "חוזר (ידני)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "חוזר (לוח שידורים)" msgctxt "#30144" msgid "Child Recording" msgstr "הקלטה לילדים" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "חוזר (מילת מפתח)" msgctxt "#30150" msgid "All Recordings" msgstr "כל ההקלטות" msgctxt "#30151" msgid "1 Recording" msgstr "1 הקלטה" msgctxt "#30152" msgid "2 Recordings" msgstr "2 הקלטות" msgctxt "#30153" msgid "3 Recordings" msgstr "3 הקלטות" msgctxt "#30154" msgid "4 Recordings" msgstr "4 הקלטות" msgctxt "#30155" msgid "5 Recordings" msgstr "5 הקלטות" msgctxt "#30156" msgid "6 Recordings" msgstr "6 הקלטות" msgctxt "#30157" msgid "7 Recordings" msgstr "7 הקלטות" msgctxt "#30158" msgid "10 Recordings" msgstr "10 הקלטות" msgctxt "#30160" msgid "New Only" msgstr "חדש בלבד" msgctxt "#30161" msgid "All" msgstr "הכל" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.hi_in/000077500000000000000000000000001360274650100276055ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.hi_in/strings.po000066400000000000000000000013511360274650100316360ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Hindi (India) (http://www.transifex.com/projects/p/kodi-main/language/hi_IN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: hi_IN\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30041" msgid "Advanced" msgstr "उन्नत" msgctxt "#30161" msgid "All" msgstr "सब" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.hr_hr/000077500000000000000000000000001360274650100276215ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.hr_hr/strings.po000066400000000000000000000052771360274650100316650ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Croatian (Croatia) (http://www.transifex.com/projects/p/kodi-main/language/hr_HR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: hr_HR\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" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "NextPVR naziv računala" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "NextPVR ulaz (uobičajen 8866 ili 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "NextPVR PIN kôd" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Omogućiti vremensko premotavanje za TV programe" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Preuzmi poster TV vodiča" msgctxt "#30040" msgid "Connection" msgstr "Povezivanje" msgctxt "#30041" msgid "Advanced" msgstr "Napredno" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "NextPVR poslužitelj je zastario." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Nadogradi na '%s' ili više!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Neuspješno povezivanje. Pogrešan PIN?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Prijemnik više nije dostupan" msgctxt "#30140" msgid "One time (manual)" msgstr "Jednom (ručno)" msgctxt "#30141" msgid "One time (guide)" msgstr "Jednom (EPG vodič)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Ponavljajuće (ručno)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Ponavljajuće (EPG vodič)" msgctxt "#30144" msgid "Child Recording" msgstr "Podsnimke" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Ponavljajuće zakazano snimanje (ključnom riječi)" msgctxt "#30150" msgid "All Recordings" msgstr "Sve snimke" msgctxt "#30151" msgid "1 Recording" msgstr "1 snimka" msgctxt "#30152" msgid "2 Recordings" msgstr "2 snimke" msgctxt "#30153" msgid "3 Recordings" msgstr "3 snimke" msgctxt "#30154" msgid "4 Recordings" msgstr "4 snimke" msgctxt "#30155" msgid "5 Recordings" msgstr "5 snimka" msgctxt "#30156" msgid "6 Recordings" msgstr "6 snimka" msgctxt "#30157" msgid "7 Recordings" msgstr "7 snimka" msgctxt "#30158" msgid "10 Recordings" msgstr "10 snimka" msgctxt "#30160" msgid "New Only" msgstr "Samo nove" msgctxt "#30161" msgid "All" msgstr "Sve" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.hu_hu/000077500000000000000000000000001360274650100276275ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.hu_hu/strings.po000066400000000000000000000052571360274650100316710ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Hungarian (Hungary) (http://www.transifex.com/projects/p/kodi-main/language/hu_HU/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: hu_HU\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "NextPVR Kiszolgálónév " msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "NextPVR port (általában 8866 vagy 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "NextPVR PIN kód" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Időeltolás engedélyezése az Élő TV-vel" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "TV műsorújság illusztráció letöltése" msgctxt "#30040" msgid "Connection" msgstr "Kapcsolat" msgctxt "#30041" msgid "Advanced" msgstr "Haladó" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "A NextPVR szerver túl régi." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Frissíts '%s'-re vagy újabbra!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "A kapcsolódás sikertelen. Helyes PIN kódot adott meg?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "A vevőkártya már nem elérhető" msgctxt "#30140" msgid "One time (manual)" msgstr "Egyszeri (kézi)" msgctxt "#30141" msgid "One time (guide)" msgstr "Egyszeri (műsorújság)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Ismétlődő (kézi)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Ismétlődő (műsorújság)" msgctxt "#30144" msgid "Child Recording" msgstr "Gyermek felvétel" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Ismétlődő (kulcsszó)" msgctxt "#30150" msgid "All Recordings" msgstr "Minden felvétel" msgctxt "#30151" msgid "1 Recording" msgstr "1 felvétel" msgctxt "#30152" msgid "2 Recordings" msgstr "2 felvétel" msgctxt "#30153" msgid "3 Recordings" msgstr "3 felvétel" msgctxt "#30154" msgid "4 Recordings" msgstr "4 felvétel" msgctxt "#30155" msgid "5 Recordings" msgstr "5 felvétel" msgctxt "#30156" msgid "6 Recordings" msgstr "6 felvétel" msgctxt "#30157" msgid "7 Recordings" msgstr "7 felvétel" msgctxt "#30158" msgid "10 Recordings" msgstr "10 felvétel" msgctxt "#30160" msgid "New Only" msgstr "Csak új" msgctxt "#30161" msgid "All" msgstr "Mind" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.hy_am/000077500000000000000000000000001360274650100276145ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.hy_am/strings.po000066400000000000000000000012701360274650100316450ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Armenian (Armenia) (http://www.transifex.com/projects/p/kodi-main/language/hy_AM/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: hy_AM\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30161" msgid "All" msgstr "Բոլորը" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.id_id/000077500000000000000000000000001360274650100275675ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.id_id/strings.po000066400000000000000000000030621360274650100316210ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Indonesian (Indonesia) (http://www.transifex.com/projects/p/kodi-main/language/id_ID/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: id_ID\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "Hostname NextPVR" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "Port NextPVR (Biasanya 8866 atau 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "Kode Pin NextPVR" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Aktifkan TimeShift dengan Siaran TV" msgctxt "#30040" msgid "Connection" msgstr "Koneksi" msgctxt "#30041" msgid "Advanced" msgstr "Tingkat Lanjut" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "Server NextPVR terlalu tua." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Upgrade ke versi '%s' atau lebih tinggi!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Koneksi gagal. PIN salah?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Tuner tidak lagi tersedia" msgctxt "#30150" msgid "All Recordings" msgstr "Semua rekaman" msgctxt "#30161" msgid "All" msgstr "Semua" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.is_is/000077500000000000000000000000001360274650100276255ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.is_is/strings.po000066400000000000000000000052131360274650100316570ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Icelandic (Iceland) (http://www.transifex.com/projects/p/kodi-main/language/is_IS/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: is_IS\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "Hýsingarnafn NextPVR" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "Gátt fyrir NextPVR (vanalega 8866 eða 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "PIN-kóði NextPVR" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Virkja tímahliðrun með beinum útsendingum" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Sækja myndefni dagskrár" msgctxt "#30040" msgid "Connection" msgstr "Tenging" msgctxt "#30041" msgid "Advanced" msgstr "Ítarlegt" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "NextPVR-miðlari er of gamall." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Uppfærðu í '%s' eða nýrri!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Tenging mistókst. Rangt PIN?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Móttakari ekki lengur tiltækur" msgctxt "#30140" msgid "One time (manual)" msgstr "Eitt skipti (handvirkt)" msgctxt "#30141" msgid "One time (guide)" msgstr "Eitt skipti (dagskrárvísir)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Endurtekið (handvirkt)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Endurtekið (dagskrá)" msgctxt "#30144" msgid "Child Recording" msgstr "Afleidd upptaka" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Endurtekið (stikkorð)" msgctxt "#30150" msgid "All Recordings" msgstr "Allar upptökur" msgctxt "#30151" msgid "1 Recording" msgstr "1 upptaka" msgctxt "#30152" msgid "2 Recordings" msgstr "2 upptökur" msgctxt "#30153" msgid "3 Recordings" msgstr "3 upptökur" msgctxt "#30154" msgid "4 Recordings" msgstr "4 upptökur" msgctxt "#30155" msgid "5 Recordings" msgstr "5 upptökur" msgctxt "#30156" msgid "6 Recordings" msgstr "6 upptökur" msgctxt "#30157" msgid "7 Recordings" msgstr "7 upptökur" msgctxt "#30158" msgid "10 Recordings" msgstr "10 upptökur" msgctxt "#30160" msgid "New Only" msgstr "Einungis nýtt" msgctxt "#30161" msgid "All" msgstr "Allt" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.it_it/000077500000000000000000000000001360274650100276275ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.it_it/strings.po000066400000000000000000000052341360274650100316640ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Italian (Italy) (http://www.transifex.com/projects/p/kodi-main/language/it_IT/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it_IT\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "Nome Host NextPVR" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "Porta NextPVR (di solito 8866 o 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "Codice PIN NextPVR" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Abilita TimeShift su Live TV" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Scarica Artwork Guida TV" msgctxt "#30040" msgid "Connection" msgstr "Connessione" msgctxt "#30041" msgid "Advanced" msgstr "Avanzato" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "Il server NextPVR è troppo vecchio." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Aggiornare alla '%s' o superiore!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Connessione fallita. PIN non corretto?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Il tuner non è più disponibile" msgctxt "#30140" msgid "One time (manual)" msgstr "Una volta (manuale)" msgctxt "#30141" msgid "One time (guide)" msgstr "Una volta (guida)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Ripetizione (manuale)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Ripetizione (guida)" msgctxt "#30144" msgid "Child Recording" msgstr "Registrazione per bambini" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Ripetizione (parola chiave)" msgctxt "#30150" msgid "All Recordings" msgstr "Tutte le registrazioni" msgctxt "#30151" msgid "1 Recording" msgstr "1 registrazione" msgctxt "#30152" msgid "2 Recordings" msgstr "2 registrazioni" msgctxt "#30153" msgid "3 Recordings" msgstr "3 registrazioni" msgctxt "#30154" msgid "4 Recordings" msgstr "4 registrazioni" msgctxt "#30155" msgid "5 Recordings" msgstr "5 registrazioni" msgctxt "#30156" msgid "6 Recordings" msgstr "6 registrazioni" msgctxt "#30157" msgid "7 Recordings" msgstr "7 registrazioni" msgctxt "#30158" msgid "10 Recordings" msgstr "10 registrazioni" msgctxt "#30160" msgid "New Only" msgstr "Solo nuovi" msgctxt "#30161" msgid "All" msgstr "Tutte" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.ja_jp/000077500000000000000000000000001360274650100276025ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.ja_jp/strings.po000066400000000000000000000032261360274650100316360ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Japanese (Japan) (http://www.transifex.com/projects/p/kodi-main/language/ja_JP/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ja_JP\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "NextPVR ホスト名" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "NextPVR ポート番号 (通常 8866 か 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "NextPVR Pinコード" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "タイムシフト視聴を有効に" msgctxt "#30040" msgid "Connection" msgstr "接続" msgctxt "#30041" msgid "Advanced" msgstr "高度な設定" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "NextPVR サーバが古すぎます。" msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "'%s' 以上のバージョンにアップグレードしてください!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "接続に失敗。PIN が間違っていませんか?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "チューナーがみつかりません" msgctxt "#30150" msgid "All Recordings" msgstr "全録画" msgctxt "#30161" msgid "All" msgstr "すべて" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.ko_kr/000077500000000000000000000000001360274650100276245ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.ko_kr/strings.po000066400000000000000000000051641360274650100316630ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Korean (Korea) (http://www.transifex.com/projects/p/kodi-main/language/ko_KR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ko_KR\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "NextPVR 호스트 네임" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "NextPVR 포트 (보통 8866 또는 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "NextPVR PIN 코드" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "라이브 TV에서 타임시프트 사용" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "TV 가이드 아트 다운로드" msgctxt "#30040" msgid "Connection" msgstr "연결" msgctxt "#30041" msgid "Advanced" msgstr "고급" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "NextPVR 서버가 오래된 버전입니다." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "'%s' 이상으로 업그레이드 하세요!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "연결 실패. 틀린 암호?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "튜너 사용할 수 없음" msgctxt "#30140" msgid "One time (manual)" msgstr "한 번 (수동)" msgctxt "#30141" msgid "One time (guide)" msgstr "한 번 (가이드)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "반복 (수동)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "반복 (가이드)" msgctxt "#30144" msgid "Child Recording" msgstr "파생된 녹화" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "반복 (키워드)" msgctxt "#30150" msgid "All Recordings" msgstr "모든 녹화영상" msgctxt "#30151" msgid "1 Recording" msgstr "녹화 1편" msgctxt "#30152" msgid "2 Recordings" msgstr "녹화 2편" msgctxt "#30153" msgid "3 Recordings" msgstr "녹화 3편" msgctxt "#30154" msgid "4 Recordings" msgstr "녹화 4편" msgctxt "#30155" msgid "5 Recordings" msgstr "녹화 5편" msgctxt "#30156" msgid "6 Recordings" msgstr "녹화 6편" msgctxt "#30157" msgid "7 Recordings" msgstr "녹화 7편" msgctxt "#30158" msgid "10 Recordings" msgstr "녹화 10편" msgctxt "#30160" msgid "New Only" msgstr "최신만" msgctxt "#30161" msgid "All" msgstr "전체" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.lt_lt/000077500000000000000000000000001360274650100276355ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.lt_lt/strings.po000066400000000000000000000053411360274650100316710ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Lithuanian (Lithuania) (http://www.transifex.com/projects/p/kodi-main/language/lt_LT/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: lt_LT\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "NextPVR mazgo vardas" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "NextPVR portas (paprastai 8866 arba 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "NextPVR pin kodas" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Įjungti TimeShift su Live TV" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Atsisiųsti TV gido iliustracijas" msgctxt "#30040" msgid "Connection" msgstr "Prijungimas" msgctxt "#30041" msgid "Advanced" msgstr "Išplėstinė(-is)" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "NextPVR serveris per senas" msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Atnaujinti į '%s' arba naujesnį!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Ryšys nutrūko. Klaidingas PIN kodas?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Imtuvas nebepasiekiamas" msgctxt "#30140" msgid "One time (manual)" msgstr "Vieną kartą (vadovas)" msgctxt "#30141" msgid "One time (guide)" msgstr "Vieną kartą (instrukcija)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Pasikartojantis (vadovas)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Pasikartojantis (instrukcija)" msgctxt "#30144" msgid "Child Recording" msgstr "Vaikų įrašymai" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Pasikartojantis (raktinis žodis)" msgctxt "#30150" msgid "All Recordings" msgstr "Visi įrašai" msgctxt "#30151" msgid "1 Recording" msgstr "1 įrašymas" msgctxt "#30152" msgid "2 Recordings" msgstr "2 įrašymai" msgctxt "#30153" msgid "3 Recordings" msgstr "3 įrašymai" msgctxt "#30154" msgid "4 Recordings" msgstr "4 įrašymai" msgctxt "#30155" msgid "5 Recordings" msgstr "5 įrašymai" msgctxt "#30156" msgid "6 Recordings" msgstr "6 įrašymai" msgctxt "#30157" msgid "7 Recordings" msgstr "7 įrašymai" msgctxt "#30158" msgid "10 Recordings" msgstr "10 įrašymų" msgctxt "#30160" msgid "New Only" msgstr "Tik nauji" msgctxt "#30161" msgid "All" msgstr "Visi" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.lv_lv/000077500000000000000000000000001360274650100276415ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.lv_lv/strings.po000066400000000000000000000031541360274650100316750ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Latvian (Latvia) (http://www.transifex.com/projects/p/kodi-main/language/lv_LV/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: lv_LV\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "NextPVR saimniekvārds" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "NextPVR ports (parasti 8866 vai 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "NextPVR pinkods" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Ieslēgt laika nobīdi tiešraides TV" msgctxt "#30040" msgid "Connection" msgstr "Pieslēgums" msgctxt "#30041" msgid "Advanced" msgstr "Papildus" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "NextPVR serveris ir pārāk vecs." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Janiniet uz '%s' vai augstāku!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Pieslēgums neizdevās. Vai nepareizs PIN?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Uztvērējs vairs nav pieejams" msgctxt "#30150" msgid "All Recordings" msgstr "Visi ieraksti" msgctxt "#30161" msgid "All" msgstr "Visi" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.mi/000077500000000000000000000000001360274650100271245ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.mi/strings.po000066400000000000000000000013271360274650100311600ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Maori (http://www.transifex.com/projects/p/kodi-main/language/mi/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: mi\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" msgctxt "#30041" msgid "Advanced" msgstr "Arā Atu Anō" msgctxt "#30161" msgid "All" msgstr "Katoa" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.mk_mk/000077500000000000000000000000001360274650100276155ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.mk_mk/strings.po000066400000000000000000000033471360274650100316550ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Macedonian (Macedonia) (http://www.transifex.com/projects/p/kodi-main/language/mk_MK/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: mk_MK\n" "Plural-Forms: nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "NextPVR име на хост" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "NextPVR порт (вообичаено 8866 или 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "NextPVR Пин код" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Овозможи TimeShift со Live TV" msgctxt "#30040" msgid "Connection" msgstr "Конекција" msgctxt "#30041" msgid "Advanced" msgstr "Напредно" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "NextPVR серверот е престар" msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Надгради на '%s' или поново!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Неуспешна конекција. Погрешен PIN" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Тјунерот повеќе не е достапен" msgctxt "#30150" msgid "All Recordings" msgstr "Сите снимки" msgctxt "#30161" msgid "All" msgstr "Се" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.mn_mn/000077500000000000000000000000001360274650100276235ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.mn_mn/strings.po000066400000000000000000000012661360274650100316610ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Mongolian (Mongolia) (http://www.transifex.com/projects/p/kodi-main/language/mn_MN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: mn_MN\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30161" msgid "All" msgstr "Бүгд" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.ms_my/000077500000000000000000000000001360274650100276435ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.ms_my/strings.po000066400000000000000000000051141360274650100316750ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Malay (Malaysia) (http://www.transifex.com/projects/p/kodi-main/language/ms_MY/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ms_MY\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "Nama hos NextPVR" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "Port NextPVR (biasanya 8866 atau 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "Kod Pin NextPVR" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Benarkan Anjak Masa dengan TV Langsung" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Muat Turun Kerja Seni Panduan TV" msgctxt "#30040" msgid "Connection" msgstr "Sambungan" msgctxt "#30041" msgid "Advanced" msgstr "Lanjutan" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "Pelayan NextPVR terlalu tua." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Tatar ke '%s' atau lebih baharu!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Sambungan gagal. PIN salah?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Penala tiada lagi tersedia" msgctxt "#30140" msgid "One time (manual)" msgstr "Satu kali (manual)" msgctxt "#30141" msgid "One time (guide)" msgstr "Satu kali (panduan)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Pengulangan (manual)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Pengulangan (panduan)" msgctxt "#30144" msgid "Child Recording" msgstr "Rakaman Kanak-Kanak" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Pengulangan (kata kunci)" msgctxt "#30150" msgid "All Recordings" msgstr "Semua Rakaman" msgctxt "#30151" msgid "1 Recording" msgstr "1 Rakaman" msgctxt "#30152" msgid "2 Recordings" msgstr "2 Rakaman" msgctxt "#30153" msgid "3 Recordings" msgstr "3 Rakaman" msgctxt "#30154" msgid "4 Recordings" msgstr "4 Rakaman" msgctxt "#30155" msgid "5 Recordings" msgstr "5 Rakaman" msgctxt "#30156" msgid "6 Recordings" msgstr "6 Rakaman" msgctxt "#30157" msgid "7 Recordings" msgstr "7 Rakaman" msgctxt "#30158" msgid "10 Recordings" msgstr "10 Rakaman" msgctxt "#30160" msgid "New Only" msgstr "Baharu Sahaja" msgctxt "#30161" msgid "All" msgstr "Semua" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.mt_mt/000077500000000000000000000000001360274650100276375ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.mt_mt/strings.po000066400000000000000000000014551360274650100316750ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Maltese (Malta) (http://www.transifex.com/projects/p/kodi-main/language/mt_MT/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: mt_MT\n" "Plural-Forms: nplurals=4; plural=(n==1 ? 0 : n==0 || ( n%100>1 && n%100<11) ? 1 : (n%100>10 && n%100<20 ) ? 2 : 3);\n" msgctxt "#30041" msgid "Advanced" msgstr "Avvanzat" msgctxt "#30161" msgid "All" msgstr "Kollox" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.my_mm/000077500000000000000000000000001360274650100276355ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.my_mm/strings.po000066400000000000000000000036151360274650100316730ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Burmese (Myanmar) (http://www.transifex.com/projects/p/kodi-main/language/my_MM/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: my_MM\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "NextPVR Hostname" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "NextPVR Port (ပုံမှန်အားဖြင့် 8866 သို့မဟုတ် 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "NextPVR PinCode" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Live TV နှင့် အတူ TimeShift ကို အသုံးပြုပါ" msgctxt "#30040" msgid "Connection" msgstr "ကွန်နက်ရှင်" msgctxt "#30041" msgid "Advanced" msgstr "အဆင့်မြင့်သော" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "NextPVR server သည် ဟောင်းနေပြီ။" msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "%s ထိ သို့မဟုတ် ဒီထက်ပိုပြီး ဒီထက်ပိုပြီး မြှင့်ပါ" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "ချိတ်ဆက်မှု မအောင်မြင်ပါ။ PIN မှားနေလား ?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Tuner မရရှိနိုင်တော့ပါ" msgctxt "#30161" msgid "All" msgstr "အားလုံး" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.nb_no/000077500000000000000000000000001360274650100276125ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.nb_no/strings.po000066400000000000000000000051011360274650100316400ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Norwegian Bokmål (Norway) (http://www.transifex.com/projects/p/kodi-main/language/nb_NO/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: nb_NO\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "NextPVR vertsnavn" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "NextPVR-port (som regel 8866 eller 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "NextPVR PIN-kode" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Aktiver TimeShift med direkte TV" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Last ned TV-guide-kunst" msgctxt "#30040" msgid "Connection" msgstr "Tilkobling" msgctxt "#30041" msgid "Advanced" msgstr "Avansert" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "NextPVR-vert er for gammel." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Oppgrader til '%s' eller høyere!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Tilkobling feilet. Feil PIN?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Tuner er ikke lengre tilgjengelig" msgctxt "#30140" msgid "One time (manual)" msgstr "Én gang (manuell)" msgctxt "#30141" msgid "One time (guide)" msgstr "Én gang (guide)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Gjentagende (manuell)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Gjentagende (guide)" msgctxt "#30144" msgid "Child Recording" msgstr "Barneopptak" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Gjentagende (nøkkelord)" msgctxt "#30150" msgid "All Recordings" msgstr "Alle opptak" msgctxt "#30151" msgid "1 Recording" msgstr "Ett opptak" msgctxt "#30152" msgid "2 Recordings" msgstr "To opptak" msgctxt "#30153" msgid "3 Recordings" msgstr "3 opptak" msgctxt "#30154" msgid "4 Recordings" msgstr "4 opptak" msgctxt "#30155" msgid "5 Recordings" msgstr "5 opptak" msgctxt "#30156" msgid "6 Recordings" msgstr "6 opptak" msgctxt "#30157" msgid "7 Recordings" msgstr "7 opptak" msgctxt "#30158" msgid "10 Recordings" msgstr "10 opptak" msgctxt "#30160" msgid "New Only" msgstr "Kun nye" msgctxt "#30161" msgid "All" msgstr "Alle" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.nl_nl/000077500000000000000000000000001360274650100276215ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.nl_nl/strings.po000066400000000000000000000051141360274650100316530ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Dutch (Netherlands) (http://www.transifex.com/projects/p/kodi-main/language/nl_NL/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: nl_NL\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "NextPVR-hostnaam" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "NextPVR-poort (meestal 8866 of 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "NextPVR-pincode" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Gebruik TimeShift met Live-TV" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Download TV-gidsillustraties" msgctxt "#30040" msgid "Connection" msgstr "Verbinding" msgctxt "#30041" msgid "Advanced" msgstr "Geavanceerd" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "NextPVR-server is te oud." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Voer upgrade uit naar '%s' of hoger!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Verbinding is mislukt. Verkeerde pincode?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Tuner niet langer beschikbaar" msgctxt "#30140" msgid "One time (manual)" msgstr "Eén keer (handmatig)" msgctxt "#30141" msgid "One time (guide)" msgstr "Eén tijd (gids)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Herhaling (handmatig)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Herhaling (gids)" msgctxt "#30144" msgid "Child Recording" msgstr "Kinderopname" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Herhalend (trefwoord)" msgctxt "#30150" msgid "All Recordings" msgstr "Alle opnames" msgctxt "#30151" msgid "1 Recording" msgstr "1 opname" msgctxt "#30152" msgid "2 Recordings" msgstr "2 opnames" msgctxt "#30153" msgid "3 Recordings" msgstr "3 opnames" msgctxt "#30154" msgid "4 Recordings" msgstr "4 opnames" msgctxt "#30155" msgid "5 Recordings" msgstr "5 opnames" msgctxt "#30156" msgid "6 Recordings" msgstr "6 opnames" msgctxt "#30157" msgid "7 Recordings" msgstr "7 opnames" msgctxt "#30158" msgid "10 Recordings" msgstr "10 opnames" msgctxt "#30160" msgid "New Only" msgstr "Alleen nieuw" msgctxt "#30161" msgid "All" msgstr "Alles" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.pl_pl/000077500000000000000000000000001360274650100276255ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.pl_pl/strings.po000066400000000000000000000053171360274650100316640ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Polish (Poland) (http://www.transifex.com/projects/p/kodi-main/language/pl_PL/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: pl_PL\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "Nazwa lub adres serwera" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "Port (zazwyczaj 8866 lub 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "Kod PIN" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Aktywuj funkcję przesunięcia czasowego" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Pobieraj grafiki dla pozycji przewodnika" msgctxt "#30040" msgid "Connection" msgstr "Połączenie" msgctxt "#30041" msgid "Advanced" msgstr "Zaawansowane" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "Serwer NextPVR jest w zbyt starej wersji. " msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Zainstaluj wersję '%s' lub nowszą!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Nieudane połączenie. Nieprawidłowy PIN?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Tuner jest niedostępny" msgctxt "#30140" msgid "One time (manual)" msgstr "Jednorazowo (manualnie)" msgctxt "#30141" msgid "One time (guide)" msgstr "Jednorazowo (przewodnik)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Cyklicznie (manualnie)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Cyklicznie (przewodnik)" msgctxt "#30144" msgid "Child Recording" msgstr "Nagrywanie potomków" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Cyklicznie (słowo kluczowe)" msgctxt "#30150" msgid "All Recordings" msgstr "Wszystkie nagrania" msgctxt "#30151" msgid "1 Recording" msgstr "1 Nagranie" msgctxt "#30152" msgid "2 Recordings" msgstr "2 Nagrania" msgctxt "#30153" msgid "3 Recordings" msgstr "3 Nagrania" msgctxt "#30154" msgid "4 Recordings" msgstr "4 Nagrania" msgctxt "#30155" msgid "5 Recordings" msgstr "5 Nagrań" msgctxt "#30156" msgid "6 Recordings" msgstr "6 Nagrań" msgctxt "#30157" msgid "7 Recordings" msgstr "7 Nagrań" msgctxt "#30158" msgid "10 Recordings" msgstr "10 Nagrań" msgctxt "#30160" msgid "New Only" msgstr "Tylko nowe" msgctxt "#30161" msgid "All" msgstr "Wszystkie" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.pt_br/000077500000000000000000000000001360274650100276255ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.pt_br/strings.po000066400000000000000000000052211360274650100316560ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/kodi-main/language/pt_BR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: pt_BR\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "Hostname do NextPVR" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "Porta do NextPVR (normalmente 8866 ou 7799" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "Pincode do NextPVR" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Ativar TimeShift com Tv ao Vivo" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Transferir artes Guia de TV" msgctxt "#30040" msgid "Connection" msgstr "Conexão" msgctxt "#30041" msgid "Advanced" msgstr "Avançado" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "O servidor NextPVR é muito antigo." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Atualizar para '%s' ou superior!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "A conexão falhou. PIN incorreto?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Sintonizador não está disponível" msgctxt "#30140" msgid "One time (manual)" msgstr "Uma vez (manual)" msgctxt "#30141" msgid "One time (guide)" msgstr "Uma vez (guia)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Recorrente (manual)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Recorrente (guia)" msgctxt "#30144" msgid "Child Recording" msgstr "Gravações Aninhadas" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Recorrente (palavra chave)" msgctxt "#30150" msgid "All Recordings" msgstr "Todas as gravações" msgctxt "#30151" msgid "1 Recording" msgstr "1 Gravação" msgctxt "#30152" msgid "2 Recordings" msgstr "2 Gravações" msgctxt "#30153" msgid "3 Recordings" msgstr "3 Gravações" msgctxt "#30154" msgid "4 Recordings" msgstr "4 Gravações" msgctxt "#30155" msgid "5 Recordings" msgstr "5 Gravações" msgctxt "#30156" msgid "6 Recordings" msgstr "6 Gravações" msgctxt "#30157" msgid "7 Recordings" msgstr "7 Gravações" msgctxt "#30158" msgid "10 Recordings" msgstr "10 Gravações" msgctxt "#30160" msgid "New Only" msgstr "Somente Novo" msgctxt "#30161" msgid "All" msgstr "Todos os Add-ons" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.pt_pt/000077500000000000000000000000001360274650100276455ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.pt_pt/strings.po000066400000000000000000000052411360274650100317000ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Portuguese (Portugal) (http://www.transifex.com/projects/p/kodi-main/language/pt_PT/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: pt_PT\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "Nome do servidor NextPVR" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "Porta do NextPVR (normalmente 8866 ou 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "Código Pin do NextPVR" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Ativar TimeShift com TV em direto" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Descarregar imagens do guia" msgctxt "#30040" msgid "Connection" msgstr "Ligação" msgctxt "#30041" msgid "Advanced" msgstr "Avançado" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "O servidor NextPVR é muito antigo." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Atualize para a versão '%s' ou superior!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Erro de ligação. PIN incorreto? " msgctxt "#30053" msgid "Tuner no longer available" msgstr "Sintonizador não disponível" msgctxt "#30140" msgid "One time (manual)" msgstr "Uma vez (manual)" msgctxt "#30141" msgid "One time (guide)" msgstr "Uma vez (guia)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Repetição (manual)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Repetição (guia)" msgctxt "#30144" msgid "Child Recording" msgstr "Gravação para crianças" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Repetição (palavra-chave)" msgctxt "#30150" msgid "All Recordings" msgstr "Todas as gravações" msgctxt "#30151" msgid "1 Recording" msgstr "1 gravação" msgctxt "#30152" msgid "2 Recordings" msgstr "2 gravações" msgctxt "#30153" msgid "3 Recordings" msgstr "3 gravações" msgctxt "#30154" msgid "4 Recordings" msgstr "4 gravações" msgctxt "#30155" msgid "5 Recordings" msgstr "5 gravações" msgctxt "#30156" msgid "6 Recordings" msgstr "6 gravações" msgctxt "#30157" msgid "7 Recordings" msgstr "7 gravações" msgctxt "#30158" msgid "10 Recordings" msgstr "10 gravações" msgctxt "#30160" msgid "New Only" msgstr "Apenas novas" msgctxt "#30161" msgid "All" msgstr "Todas" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.ro_ro/000077500000000000000000000000001360274650100276375ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.ro_ro/strings.po000066400000000000000000000053371360274650100317000ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Romanian (Romania) (http://www.transifex.com/projects/p/kodi-main/language/ro_RO/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ro_RO\n" "Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "NextPVR Hostname" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "Portul NextPVR (de obicei 8866 sau 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "NextPVR cod PIN" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Activează decalajul temporal cu televiziunea în direct" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Descarcă lucrare de artă ghid tv" msgctxt "#30040" msgid "Connection" msgstr "Conexiune" msgctxt "#30041" msgid "Advanced" msgstr "Avansat" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "Servitorul NextPVR este prea vechi." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Upgrade la '%s' sau mai mare!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Conexiune nereușită. Cod PIN incorect?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Tuner-ul nu mai este disponibil" msgctxt "#30140" msgid "One time (manual)" msgstr "O dată (manual)" msgctxt "#30141" msgid "One time (guide)" msgstr "O dată (ghid)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Repetant (manual)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Repetant (ghid)" msgctxt "#30144" msgid "Child Recording" msgstr "Înregistrare pentru copii" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Repetat (cuvânt cheie)" msgctxt "#30150" msgid "All Recordings" msgstr "Toate înregistrările" msgctxt "#30151" msgid "1 Recording" msgstr "1 Înregistrare" msgctxt "#30152" msgid "2 Recordings" msgstr "2 Înregistrări" msgctxt "#30153" msgid "3 Recordings" msgstr "3 Înregistrări" msgctxt "#30154" msgid "4 Recordings" msgstr "4 Înregistrări" msgctxt "#30155" msgid "5 Recordings" msgstr "5 Înregistrări" msgctxt "#30156" msgid "6 Recordings" msgstr "6 Înregistrări" msgctxt "#30157" msgid "7 Recordings" msgstr "7 Înregistrări" msgctxt "#30158" msgid "10 Recordings" msgstr "10 Înregistrări" msgctxt "#30160" msgid "New Only" msgstr "Doar cele noi" msgctxt "#30161" msgid "All" msgstr "Toate" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.ru_ru/000077500000000000000000000000001360274650100276535ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.ru_ru/strings.po000066400000000000000000000061161360274650100317100ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Russian (Russia) (http://www.transifex.com/projects/p/kodi-main/language/ru_RU/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ru_RU\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" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "Имя хоста NextPVR" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "Порт NextPVR (обычно 8866 или 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "ПИН-код NextPVR" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Включить таймшифт LIveTV" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Загрузить фон для телепрограммы" msgctxt "#30040" msgid "Connection" msgstr "Соединение" msgctxt "#30041" msgid "Advanced" msgstr "Дополнительные" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "Слишком старая версия сервера NextPVR" msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Обновите до '%s' или выше!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Не удалось подключиться. Возможно, неправильный ПИН-код." msgctxt "#30053" msgid "Tuner no longer available" msgstr "Тюнер более недоступен" msgctxt "#30140" msgid "One time (manual)" msgstr "Одноразовый (вручную)" msgctxt "#30141" msgid "One time (guide)" msgstr "Одноразовый (программа)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Повторяющийся (ручной)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Повторяющийся (программа)" msgctxt "#30144" msgid "Child Recording" msgstr "Дочерняя запись" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Повторяющийся (ключевое слово)" msgctxt "#30150" msgid "All Recordings" msgstr "Все Записи" msgctxt "#30151" msgid "1 Recording" msgstr "1 запись" msgctxt "#30152" msgid "2 Recordings" msgstr "2 записи" msgctxt "#30153" msgid "3 Recordings" msgstr "3 записи" msgctxt "#30154" msgid "4 Recordings" msgstr "4 записи" msgctxt "#30155" msgid "5 Recordings" msgstr "5 записей" msgctxt "#30156" msgid "6 Recordings" msgstr "6 записей" msgctxt "#30157" msgid "7 Recordings" msgstr "7 записей" msgctxt "#30158" msgid "10 Recordings" msgstr "10 записей" msgctxt "#30160" msgid "New Only" msgstr "Только новые" msgctxt "#30161" msgid "All" msgstr "Все треки" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.si_lk/000077500000000000000000000000001360274650100276205ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.si_lk/strings.po000066400000000000000000000013661360274650100316570ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Sinhala (Sri Lanka) (http://www.transifex.com/projects/p/kodi-main/language/si_LK/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: si_LK\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30041" msgid "Advanced" msgstr "උසස්" msgctxt "#30161" msgid "All" msgstr "සියළු " pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.sk_sk/000077500000000000000000000000001360274650100276315ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.sk_sk/strings.po000066400000000000000000000053321360274650100316650ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Slovak (Slovakia) (http://www.transifex.com/projects/p/kodi-main/language/sk_SK/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: sk_SK\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "Názov NextPVR hostiteľa" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "NextPVR port (zvyčajne 8866 alebo 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "NextPVR PIN-kód" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Povoliť časový posun v režime Živé TV vysielanie" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Prevziať predlohu TV programu" msgctxt "#30040" msgid "Connection" msgstr "Pripojenie" msgctxt "#30041" msgid "Advanced" msgstr "Pokročilé" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "NextPVR server je príliš neaktuálny." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Aktualizovať na verziu '%s' alebo vyššiu!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Počas pripájania nastala chyba. Nesprávny PIN-kód?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Tuner už nie je k dispozícii" msgctxt "#30140" msgid "One time (manual)" msgstr "Iba raz (ručne)" msgctxt "#30141" msgid "One time (guide)" msgstr "Iba raz (TV program)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Opakovanie (ručne)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Opakovanie (TV program)" msgctxt "#30144" msgid "Child Recording" msgstr "Nahrávky pre deti" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Opakovanie (kľúčové slovo)" msgctxt "#30150" msgid "All Recordings" msgstr "Všetky nahrávky" msgctxt "#30151" msgid "1 Recording" msgstr "1 nahrávka" msgctxt "#30152" msgid "2 Recordings" msgstr "2 nahrávky" msgctxt "#30153" msgid "3 Recordings" msgstr "3 nahrávky" msgctxt "#30154" msgid "4 Recordings" msgstr "4 nahrávky" msgctxt "#30155" msgid "5 Recordings" msgstr "5 nahrávok" msgctxt "#30156" msgid "6 Recordings" msgstr "6 nahrávok" msgctxt "#30157" msgid "7 Recordings" msgstr "7 nahrávok" msgctxt "#30158" msgid "10 Recordings" msgstr "10 nahrávok" msgctxt "#30160" msgid "New Only" msgstr "Iba nové" msgctxt "#30161" msgid "All" msgstr "Všetky" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.sl_si/000077500000000000000000000000001360274650100276305ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.sl_si/strings.po000066400000000000000000000031761360274650100316700ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Slovenian (Slovenia) (http://www.transifex.com/projects/p/kodi-main/language/sl_SI/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: sl_SI\n" "Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "Ime gostitelja NextPVR" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "Vrata NextPVR (običajno 8866 ali 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "PIN za NextPVR" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Vključi časovni zamik televizije v živo" msgctxt "#30040" msgid "Connection" msgstr "Povezava" msgctxt "#30041" msgid "Advanced" msgstr "Napredno" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "Strežnik NextPVR je prestar." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Posodobite na različico '%s' ali novejšo!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Povezava ni uspela. Napačen PIN?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Sprejemnik ni več na voljo" msgctxt "#30150" msgid "All Recordings" msgstr "Vsi posnetki" msgctxt "#30161" msgid "All" msgstr "Vse" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.sq_al/000077500000000000000000000000001360274650100276165ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.sq_al/strings.po000066400000000000000000000013521360274650100316500ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Albanian (Albania) (http://www.transifex.com/projects/p/kodi-main/language/sq_AL/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: sq_AL\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30041" msgid "Advanced" msgstr "Të shtuar" msgctxt "#30161" msgid "All" msgstr "Gjithë" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.sr_rs/000077500000000000000000000000001360274650100276475ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.sr_rs/strings.po000066400000000000000000000056771360274650100317170ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Serbian (Serbia) (http://www.transifex.com/projects/p/kodi-main/language/sr_RS/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: sr_RS\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" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "NextPVR Hostname" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "NextPVR Порт (обично 8866 или 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "NextPVR ПинКод" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Омогући померај времена код ТВ Уживо" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Преузми Илустрације ТВ Водича" msgctxt "#30040" msgid "Connection" msgstr "Веза" msgctxt "#30041" msgid "Advanced" msgstr "Напредно" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "NextPVR сервер је превише стар." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Ажурирајте на '%s' или више!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Неуспело повезивање. Нетачан PIN?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Пријемник више није доступан" msgctxt "#30140" msgid "One time (manual)" msgstr "Једном (ручно)" msgctxt "#30141" msgid "One time (guide)" msgstr "Једном (водич)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Понављајуће (ручно)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Понављајуће (водич)" msgctxt "#30144" msgid "Child Recording" msgstr "Снимак Деце" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Понављај (кључна реч)" msgctxt "#30150" msgid "All Recordings" msgstr "Сва Снимања" msgctxt "#30151" msgid "1 Recording" msgstr "1 Снимак" msgctxt "#30152" msgid "2 Recordings" msgstr "2 Снимка" msgctxt "#30153" msgid "3 Recordings" msgstr "3 Снимка" msgctxt "#30154" msgid "4 Recordings" msgstr "4 Снимака" msgctxt "#30155" msgid "5 Recordings" msgstr "5 Снимака" msgctxt "#30156" msgid "6 Recordings" msgstr "6 Снимака" msgctxt "#30157" msgid "7 Recordings" msgstr "7 Снимака" msgctxt "#30158" msgid "10 Recordings" msgstr "10 Снимака" msgctxt "#30160" msgid "New Only" msgstr "Само Нови" msgctxt "#30161" msgid "All" msgstr "Све" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.sr_rs@latin/000077500000000000000000000000001360274650100307775ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.sr_rs@latin/strings.po000066400000000000000000000052371360274650100330370ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Serbian (Latin) (Serbia) (http://www.transifex.com/projects/p/kodi-main/language/sr_RS@latin/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: sr_RS@latin\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" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "NextPVR Hostname" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "NextPVR Port (obično 8866 ili 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "NextPVR PinKod" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Omogući pomeraj vremena kod TV Uživo" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Preuzmi Ilustracije TV Vodiča" msgctxt "#30040" msgid "Connection" msgstr "Veza" msgctxt "#30041" msgid "Advanced" msgstr "Napredno" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "NextPVR server je previše star." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Ažurirajte na '%s' ili više!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Neuspelo povezivanje. Netačan PIN?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Prijemnik više nije dostupan" msgctxt "#30140" msgid "One time (manual)" msgstr "Jednom (ručno)" msgctxt "#30141" msgid "One time (guide)" msgstr "Jednom (vodič)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Ponavljajuće (ručno)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Ponavljajuće (vodič)" msgctxt "#30144" msgid "Child Recording" msgstr "Snimak Dece" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Ponavljaj (ključna reč)" msgctxt "#30150" msgid "All Recordings" msgstr "Sva snimanja" msgctxt "#30151" msgid "1 Recording" msgstr "1 Snimak" msgctxt "#30152" msgid "2 Recordings" msgstr "2 Snimka" msgctxt "#30153" msgid "3 Recordings" msgstr "3 Snimka" msgctxt "#30154" msgid "4 Recordings" msgstr "4 Snimaka" msgctxt "#30155" msgid "5 Recordings" msgstr "5 Snimaka" msgctxt "#30156" msgid "6 Recordings" msgstr "6 Snimaka" msgctxt "#30157" msgid "7 Recordings" msgstr "7 Snimaka" msgctxt "#30158" msgid "10 Recordings" msgstr "10 Snimaka" msgctxt "#30160" msgid "New Only" msgstr "Samo Novi" msgctxt "#30161" msgid "All" msgstr "Sve" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.sv_se/000077500000000000000000000000001360274650100276365ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.sv_se/strings.po000066400000000000000000000051671360274650100317000ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Swedish (Sweden) (http://www.transifex.com/projects/p/kodi-main/language/sv_SE/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: sv_SE\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "NextPVR-värdnamn" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "NextPVR-port (vanligtvis 8866 eller 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "NextPVR pinkod" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Aktivera TimeShift med Live-TV" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Hämta tv-guide utsmyckning" msgctxt "#30040" msgid "Connection" msgstr "Anslutning" msgctxt "#30041" msgid "Advanced" msgstr "Avancerad" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "NextPVR-servern är för gammal" msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Uppgradera till '%s' eller nyare!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Anslutning misslyckades. Ogiltig PIN?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Mottagaren är inte tillgänglig" msgctxt "#30140" msgid "One time (manual)" msgstr "En gång (manuell)" msgctxt "#30141" msgid "One time (guide)" msgstr "En gång (guide)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Upprepande (manuell)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Upprepande (guide)" msgctxt "#30144" msgid "Child Recording" msgstr "Spela in barn" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Upprepande (nyckelord)" msgctxt "#30150" msgid "All Recordings" msgstr "Alla inspelningar" msgctxt "#30151" msgid "1 Recording" msgstr "1 Inspelning" msgctxt "#30152" msgid "2 Recordings" msgstr "2 Inspelningar" msgctxt "#30153" msgid "3 Recordings" msgstr "3 Inspelningar" msgctxt "#30154" msgid "4 Recordings" msgstr "4 Inspelningar" msgctxt "#30155" msgid "5 Recordings" msgstr "5 Inspelningar" msgctxt "#30156" msgid "6 Recordings" msgstr "6 Inspelningar" msgctxt "#30157" msgid "7 Recordings" msgstr "7 Inspelningar" msgctxt "#30158" msgid "10 Recordings" msgstr "10 Inspelningar" msgctxt "#30160" msgid "New Only" msgstr "Endast Nya" msgctxt "#30161" msgid "All" msgstr "Alla" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.szl/000077500000000000000000000000001360274650100273275ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.szl/strings.po000066400000000000000000000052371360274650100313670ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Silesian (http://www.transifex.com/projects/p/kodi-main/language/szl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: szl\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "Miano lebo adresa serwera" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "Port (zaôbycz 8866 lebo 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "Kod PIN" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Aktywuj funkcyjõ timeshift" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "Sebiyrej grafiki do EPG" msgctxt "#30040" msgid "Connection" msgstr "Skuplowanie" msgctxt "#30041" msgid "Advanced" msgstr "Zaawansowane" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "Serwer NextPVR je w za staryj wersyje. " msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Zainstaluj wersyjõ '%s' lebo nowszõ!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Niypodarzōne skuplowanie. Niynŏleżny PIN?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Tuner je niydostympny" msgctxt "#30140" msgid "One time (manual)" msgstr "Jednorazowo (manualnie)" msgctxt "#30141" msgid "One time (guide)" msgstr "Jednorazowo (ôkludzŏcz)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Cyklicznie (manualnie)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Cyklicznie (ôkludzŏcz)" msgctxt "#30144" msgid "Child Recording" msgstr "Nagrowanie potōmne" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Cyklicznie (słowo iste)" msgctxt "#30150" msgid "All Recordings" msgstr "Wszyjske nagrania" msgctxt "#30151" msgid "1 Recording" msgstr "1 Nagranie" msgctxt "#30152" msgid "2 Recordings" msgstr "2 Nagrania" msgctxt "#30153" msgid "3 Recordings" msgstr "3 Nagrania" msgctxt "#30154" msgid "4 Recordings" msgstr "4 Nagrania" msgctxt "#30155" msgid "5 Recordings" msgstr "5 Nagrań" msgctxt "#30156" msgid "6 Recordings" msgstr "6 Nagrań" msgctxt "#30157" msgid "7 Recordings" msgstr "7 Nagrań" msgctxt "#30158" msgid "10 Recordings" msgstr "10 Nagrań" msgctxt "#30160" msgid "New Only" msgstr "Ino nowe" msgctxt "#30161" msgid "All" msgstr "Wszyjsko" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.ta_in/000077500000000000000000000000001360274650100276115ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.ta_in/strings.po000066400000000000000000000014071360274650100316440ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Tamil (India) (http://www.transifex.com/projects/p/kodi-main/language/ta_IN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ta_IN\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30041" msgid "Advanced" msgstr "மேம்பட்ட" msgctxt "#30161" msgid "All" msgstr "அனைத்தும்" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.tg_tj/000077500000000000000000000000001360274650100276265ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.tg_tj/strings.po000066400000000000000000000013571360274650100316650ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Tajik (Tajikistan) (http://www.transifex.com/projects/p/kodi-main/language/tg_TJ/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: tg_TJ\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30041" msgid "Advanced" msgstr "Иловагӣ" msgctxt "#30161" msgid "All" msgstr "Ҳама" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.th_th/000077500000000000000000000000001360274650100276255ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.th_th/strings.po000066400000000000000000000036321360274650100316620ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Thai (Thailand) (http://www.transifex.com/projects/p/kodi-main/language/th_TH/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: th_TH\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "ชื่อโฮสต์ NextPVR" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "พอร์ต NextPVR (โดยปกติ 8866 หรือ 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "รหัสพิน NextPVR" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "เปิดใช้งานเลื่อนเวลากับทีวี สด" msgctxt "#30040" msgid "Connection" msgstr "การเชื่อมต่อ" msgctxt "#30041" msgid "Advanced" msgstr "ขั้นสูง" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "แม่ข่าย NextPVR เก่าเกินไป" msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "ปรับรุ่นเป็น '%s' หรือสูงกว่า!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "การเชื่อมต่อล้มเหลว PIN ไม่ถูกต้อง?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "ตัวรับไม่สามารถใช้ได้" msgctxt "#30150" msgid "All Recordings" msgstr "ทุกการบันทึก" msgctxt "#30161" msgid "All" msgstr "ทั้งหมด" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.tr_tr/000077500000000000000000000000001360274650100276515ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.tr_tr/strings.po000066400000000000000000000051311360274650100317020ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Turkish (Turkey) (http://www.transifex.com/projects/p/kodi-main/language/tr_TR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: tr_TR\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "NextPVR Ana makine adı" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "NextPVR Portu (genellikle 8866 veya 7799'dur)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "NextPVR Pin Kodu" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Live TV için zaman kaydırma aktif" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "TV Rehberi çizimlerini indir" msgctxt "#30040" msgid "Connection" msgstr "Bağlantı" msgctxt "#30041" msgid "Advanced" msgstr "Gelişmiş" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "NextPVR sunucusu çok eski." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "'%s' ya da daha yükseğine güncelleştir!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Bağlantı başarısız. PIN doğru mu?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Radyo mevcut değil." msgctxt "#30140" msgid "One time (manual)" msgstr "Tek seferlik (elle)" msgctxt "#30141" msgid "One time (guide)" msgstr "Tek seferiik (rehber)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "Tekrarlı (elle)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "Tekrarlı (rehber)" msgctxt "#30144" msgid "Child Recording" msgstr "Alt kayıt" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "Tekrarlı (anahtar sözcük)" msgctxt "#30150" msgid "All Recordings" msgstr "Bütün kayıtlar" msgctxt "#30151" msgid "1 Recording" msgstr "1 kayıt" msgctxt "#30152" msgid "2 Recordings" msgstr "2 kayıt" msgctxt "#30153" msgid "3 Recordings" msgstr "3 kayıt" msgctxt "#30154" msgid "4 Recordings" msgstr "4 kayıt" msgctxt "#30155" msgid "5 Recordings" msgstr "5 kayıt" msgctxt "#30156" msgid "6 Recordings" msgstr "6 kayıt" msgctxt "#30157" msgid "7 Recordings" msgstr "7 kayıt" msgctxt "#30158" msgid "10 Recordings" msgstr "10 kayıt" msgctxt "#30160" msgid "New Only" msgstr "Sadece yeni" msgctxt "#30161" msgid "All" msgstr "Hepsi" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.uk_ua/000077500000000000000000000000001360274650100276235ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.uk_ua/strings.po000066400000000000000000000034051360274650100316560ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Ukrainian (Ukraine) (http://www.transifex.com/projects/p/kodi-main/language/uk_UA/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: uk_UA\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" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "Сервер NextPVR" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "Порт NextPVR (зазвичай 8866 або 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "Пін-код NextPVR" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Включити зсув часу з Live TV" msgctxt "#30040" msgid "Connection" msgstr "Зв’язок" msgctxt "#30041" msgid "Advanced" msgstr "Більше" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "Сервер NextPVR застарів." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Оновити до '%s' або вище!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Зв’язок не вдався. Неправильний пін?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Тюнер більше не доступний" msgctxt "#30150" msgid "All Recordings" msgstr "Усі записи" msgctxt "#30161" msgid "All" msgstr "Усі треки" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.uz_uz/000077500000000000000000000000001360274650100276735ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.uz_uz/strings.po000066400000000000000000000012561360274650100317300ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Uzbek (Uzbekistan) (http://www.transifex.com/projects/p/kodi-main/language/uz_UZ/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: uz_UZ\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30161" msgid "All" msgstr "Hammasini" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.vi_vn/000077500000000000000000000000001360274650100276405ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.vi_vn/strings.po000066400000000000000000000031431360274650100316720ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Vietnamese (Viet Nam) (http://www.transifex.com/projects/p/kodi-main/language/vi_VN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: vi_VN\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "Tên miền NextPVR" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "Cổng NextPVR (thông thường là 8866 hoặc 7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "Mã Pin NextPVR" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "Sử dụng chế độ TimeShift với Live TV" msgctxt "#30040" msgid "Connection" msgstr "Kết nối" msgctxt "#30041" msgid "Advanced" msgstr "Nâng cao" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "Máy chủ NextPVR đã không còn sử dụng." msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "Nâng cấp lên phiên bản '%s' hoặc mới hơn!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "Không thể kết nối được. Kiểm tra lại mã Pin?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "Dò kênh không được hỗ trợ" msgctxt "#30161" msgid "All" msgstr "Tất cả" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.zh_cn/000077500000000000000000000000001360274650100276205ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.zh_cn/strings.po000066400000000000000000000050601360274650100316520ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Chinese (China) (http://www.transifex.com/projects/p/kodi-main/language/zh_CN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: zh_CN\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "NextPVR 主机名" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "NextPVR 端口(通常为8866或7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "NextPVR PIN 码" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "启用直播电视时光平移" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "下载电视指南艺术图片" msgctxt "#30040" msgid "Connection" msgstr "连接" msgctxt "#30041" msgid "Advanced" msgstr "高级" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "NextPVR 服务器版本太旧。" msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "升级到“%s”或更高版本!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "连接失败,错误 PIN 码?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "电视接收设备不可用" msgctxt "#30140" msgid "One time (manual)" msgstr "一次(手动)" msgctxt "#30141" msgid "One time (guide)" msgstr "一次(指南)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "重复(手动)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "重复(指南)" msgctxt "#30144" msgid "Child Recording" msgstr "儿童录像" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "重复(关键字)" msgctxt "#30150" msgid "All Recordings" msgstr "所有录像" msgctxt "#30151" msgid "1 Recording" msgstr "1 录像" msgctxt "#30152" msgid "2 Recordings" msgstr "2 录像" msgctxt "#30153" msgid "3 Recordings" msgstr "3 录像" msgctxt "#30154" msgid "4 Recordings" msgstr "4 录像" msgctxt "#30155" msgid "5 Recordings" msgstr "5 录像" msgctxt "#30156" msgid "6 Recordings" msgstr "6 录像" msgctxt "#30157" msgid "7 Recordings" msgstr "7 录像" msgctxt "#30158" msgid "10 Recordings" msgstr "10 录像" msgctxt "#30160" msgid "New Only" msgstr "仅新的" msgctxt "#30161" msgid "All" msgstr "全部" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.zh_tw/000077500000000000000000000000001360274650100276525ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/language/resource.language.zh_tw/strings.po000066400000000000000000000051461360274650100317110ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: NextPVR PVR Client # Addon id: pvr.nextpvr # Addon Provider: Graeme Blackley msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Chinese (Taiwan) (http://www.transifex.com/projects/p/kodi-main/language/zh_TW/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: zh_TW\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30000" msgid "NextPVR Hostname" msgstr "NextPVR主機名稱" msgctxt "#30001" msgid "NextPVR Port (usually 8866 or 7799)" msgstr "NextPVR端口(通常是8866或7799)" msgctxt "#30002" msgid "NextPVR PinCode" msgstr "NextPVR PIN碼代號" msgctxt "#30003" msgid "Enable TimeShift with Live TV" msgstr "直播電視啟用時光平移(TimeShift)" msgctxt "#30004" msgid "Download TV Guide Artwork" msgstr "下載電視節目指南的美術圖" msgctxt "#30040" msgid "Connection" msgstr "連接" msgctxt "#30041" msgid "Advanced" msgstr "進階" msgctxt "#30050" msgid "NextPVR server is too old." msgstr "NextPVR伺服器太舊了" msgctxt "#30051" msgid "Upgrade to '%s' or higher!" msgstr "升級到'%s'或更高版本!" msgctxt "#30052" msgid "Connection failed. Incorrect PIN?" msgstr "連接失敗。不正確的PIN碼?" msgctxt "#30053" msgid "Tuner no longer available" msgstr "選台器已無法使用" msgctxt "#30140" msgid "One time (manual)" msgstr "單次 (首動)" msgctxt "#30141" msgid "One time (guide)" msgstr "單次 (節目指南)" msgctxt "#30142" msgid "Repeating (manual)" msgstr "重複 (手動)" msgctxt "#30143" msgid "Repeating (guide)" msgstr "重複 (節目指南)" msgctxt "#30144" msgid "Child Recording" msgstr "錄影子集" msgctxt "#30145" msgid "Repeating (keyword)" msgstr "重複 (關鍵字)" msgctxt "#30150" msgid "All Recordings" msgstr "所有錄影檔" msgctxt "#30151" msgid "1 Recording" msgstr "1個錄影檔" msgctxt "#30152" msgid "2 Recordings" msgstr "2個錄影檔" msgctxt "#30153" msgid "3 Recordings" msgstr "3個錄影檔" msgctxt "#30154" msgid "4 Recordings" msgstr "4個錄影檔" msgctxt "#30155" msgid "5 Recordings" msgstr "5個錄影檔" msgctxt "#30156" msgid "6 Recordings" msgstr "6個錄影檔" msgctxt "#30157" msgid "7 Recordings" msgstr "7個錄影檔" msgctxt "#30158" msgid "10 Recordings" msgstr "10個錄影檔" msgctxt "#30160" msgid "New Only" msgstr "僅新番" msgctxt "#30161" msgid "All" msgstr "全部" pvr.nextpvr-3.3.18-Leia/pvr.nextpvr/resources/settings.xml000066400000000000000000000026341360274650100237130ustar00rootroot00000000000000 pvr.nextpvr-3.3.18-Leia/src/000077500000000000000000000000001360274650100155655ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/src/BackendRequest.cpp000066400000000000000000000072211360274650100211730ustar00rootroot00000000000000/* * Copyright (C) 2005-2011 Team XBMC * http://www.xbmc.org * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "BackendRequest.h" using namespace ADDON; namespace NextPVR { Request *m_backEnd; int Request::DoRequest(const char *resource, std::string &response) { P8PLATFORM::CLockObject lock(m_mutexRequest); m_start = time(nullptr); // build request string, adding SID if requred char strURL[1024]; if (strstr(resource, "method=session") == NULL) snprintf(strURL,sizeof(strURL),"http://%s:%d%s&sid=%s", g_szHostname.c_str(), g_iPort, resource, m_sid); else snprintf(strURL,sizeof(strURL),"http://%s:%d%s", g_szHostname.c_str(), g_iPort, resource); // ask XBMC to read the URL for us int resultCode = HTTP_NOTFOUND; void* fileHandle = XBMC->OpenFile(strURL, READ_NO_CACHE); if (fileHandle) { char buffer[1024]; while (XBMC->ReadFileString(fileHandle, buffer, 1024)) { response.append(buffer); } XBMC->CloseFile(fileHandle); resultCode = HTTP_OK; if ((response.empty() || strstr(response.c_str(), "") == NULL) && strstr(resource, "method=channel.stream.info") == NULL ) { XBMC->Log(LOG_ERROR, "DoRequest failed, response=%s", response.c_str()); resultCode = HTTP_BADREQUEST; } } XBMC->Log(LOG_DEBUG, "DoRequest return %s %d %d %d", resource, resultCode,response.length(),time(nullptr) -m_start); return resultCode; } int Request::FileCopy(const char *resource,std::string fileName) { P8PLATFORM::CLockObject lock(m_mutexRequest); int written = 0; m_start = time(nullptr); char strURL[1024]; char separator = (strchr(resource,'?') == nullptr) ? '?' : '&'; snprintf(strURL,sizeof(strURL),"http://%s:%d%s%csid=%s", g_szHostname.c_str(), g_iPort, resource, separator, m_sid); // ask XBMC to read the URL for us int resultCode = HTTP_NOTFOUND; void* inputFile = XBMC->OpenFile(strURL, READ_NO_CACHE); int datalen; if (inputFile) { void* outputFile = XBMC->OpenFileForWrite(fileName.c_str(), true); if (outputFile) { char buffer[1024]; while ((datalen=XBMC->ReadFile(inputFile, buffer, sizeof(buffer)))) { XBMC->WriteFile(outputFile, buffer, datalen); written += datalen; } XBMC->CloseFile(inputFile); XBMC->CloseFile(outputFile); resultCode = HTTP_OK; } } if (written == 0) { resultCode = HTTP_BADREQUEST; } XBMC->Log(LOG_DEBUG, "FileCopy (%s - %s) %d %d %d", resource, fileName.c_str(), resultCode,written,time(nullptr) -m_start); return resultCode; } bool Request::PingBackend() { char strURL[1024]; snprintf(strURL,sizeof(strURL),"http://%s:%d%s|connection-timeout=2", g_szHostname.c_str(), g_iPort, "/service?method=recording.lastupdated"); void* fileHandle = XBMC->OpenFile(strURL, READ_NO_CACHE); if (fileHandle) { XBMC->CloseFile(fileHandle); return true; } return false; } }pvr.nextpvr-3.3.18-Leia/src/BackendRequest.h000066400000000000000000000027011360274650100206360ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2011 Team XBMC * http://www.xbmc.org * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include #include #include #include "client.h" #include "p8-platform/threads/mutex.h" #define HTTP_OK 200 #define HTTP_NOTFOUND 404 #define HTTP_BADREQUEST 400 using namespace ADDON; namespace NextPVR { class Request { public: int DoRequest(const char *resource, std::string &response); int FileCopy(const char *resource, std::string fileName); void setSID(char *newsid) {strcpy(m_sid,newsid);}; bool PingBackend(); const char *getSID() {return m_sid;}; Request(void){}; virtual ~Request() {}; private: P8PLATFORM::CMutex m_mutexRequest; time_t m_start; char m_sid[64]; }; extern Request *m_backEnd; }pvr.nextpvr-3.3.18-Leia/src/FileUtils.h000066400000000000000000000001761360274650100176420ustar00rootroot00000000000000#include namespace OS { class CFile { public: static bool Exists(const std::string& strFileName); }; }; pvr.nextpvr-3.3.18-Leia/src/README000066400000000000000000000011451360274650100164460ustar00rootroot00000000000000XBMC NextPVR Add-on ---------------------------------------------- Written by: Graeme Blackley HomePage: http://www.nextpvr.com Contact: http://www.nextpvr.com/contact/ ---------------------------------------------- Supported platforms: - Windows - Linux - OSX (should work, not tested by me) Dependencies: - NextPVR 3.6.6 or higher. This addon is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or any later version. See the file LICENSE.GPL for more information. pvr.nextpvr-3.3.18-Leia/src/Socket.cpp000066400000000000000000000415741360274650100175340ustar00rootroot00000000000000/* * Copyright (C) 2005-2011 Team XBMC * http://www.xbmc.org * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "kodi/libXBMC_addon.h" #include #include "p8-platform/os.h" #include "p8-platform/util/timeutils.h" #include "client.h" #include "Socket.h" using namespace std; using namespace ADDON; using namespace NextPVR; namespace NextPVR { /* Master defines for client control */ #define RECEIVE_TIMEOUT 6 //sec Socket::Socket(const enum SocketFamily family, const enum SocketDomain domain, const enum SocketType type, const enum SocketProtocol protocol) { _sd = INVALID_SOCKET; _family = family; _domain = domain; _type = type; _protocol = protocol; memset (&_sockaddr, 0, sizeof( _sockaddr ) ); } Socket::Socket() { // Default constructor, default settings _sd = INVALID_SOCKET; _family = af_inet; _domain = pf_inet; _type = sock_stream; _protocol = tcp; memset (&_sockaddr, 0, sizeof( _sockaddr ) ); } Socket::~Socket() { close(); } bool Socket::setHostname ( const std::string& host ) { if (isalpha(host.c_str()[0])) { // host address is a name struct hostent *he = NULL; if ((he = gethostbyname( host.c_str() )) == 0) { errormessage( getLastError(), "Socket::setHostname"); return false; } _sockaddr.sin_addr = *((in_addr *) he->h_addr); } else { _sockaddr.sin_addr.s_addr = inet_addr(host.c_str()); } return true; } bool Socket::read_ready() { fd_set fdset; FD_ZERO(&fdset); FD_SET(_sd, &fdset); struct timeval tv = { 1, 0 }; // tv.tv_sec = 1; int retVal = select(_sd+1, &fdset, NULL, NULL, &tv); if (retVal > 0) return true; return false; } bool Socket::close() { if (is_valid()) { if (_sd != SOCKET_ERROR) #ifdef TARGET_WINDOWS closesocket(_sd); #else ::close(_sd); #endif _sd = INVALID_SOCKET; osCleanup(); return true; } return false; } bool Socket::create() { if( is_valid() ) { close(); } if(!osInit()) { return false; } _sd = socket(_family, _type, _protocol ); //0 indicates that the default protocol for the type selected is to be used. //For example, IPPROTO_TCP is chosen for the protocol if the type was set to //SOCK_STREAM and the address family is AF_INET. if (_sd == INVALID_SOCKET) { errormessage( getLastError(), "Socket::create" ); return false; } return true; } bool Socket::bind ( const unsigned short port ) { if (!is_valid()) { return false; } _sockaddr.sin_family = _family; _sockaddr.sin_addr.s_addr = INADDR_ANY; //listen to all _sockaddr.sin_port = htons( port ); int bind_return = ::bind(_sd, (sockaddr*)(&_sockaddr), sizeof(_sockaddr)); if ( bind_return == -1 ) { errormessage( getLastError(), "Socket::bind" ); return false; } return true; } bool Socket::listen() const { if (!is_valid()) { return false; } int listen_return = ::listen (_sd, SOMAXCONN); //This is defined as 5 in winsock.h, and 0x7FFFFFFF in winsock2.h. //linux 128//MAXCONNECTIONS =1 if (listen_return == -1) { errormessage( getLastError(), "Socket::listen" ); return false; } return true; } bool Socket::accept ( Socket& new_socket ) const { if (!is_valid()) { return false; } socklen_t addr_length = sizeof( _sockaddr ); new_socket._sd = ::accept(_sd, const_cast( (const sockaddr*) &_sockaddr), &addr_length ); if (new_socket._sd <= 0) { errormessage( getLastError(), "Socket::accept" ); return false; } return true; } int Socket::send ( const std::string& data ) { if (!is_valid()) { return 0; } int status = 0; do { status = Socket::send( (const char*) data.c_str(), (const unsigned int) data.size()); #if defined(TARGET_WINDOWS) } while (status == SOCKET_ERROR && errno == WSAEWOULDBLOCK); #else } while (status == SOCKET_ERROR && errno == EAGAIN); #endif return status; } int Socket::send ( const char* data, const unsigned int len ) { fd_set set_w, set_e; struct timeval tv; int result; if (!is_valid()) { return 0; } // fill with new data tv.tv_sec = 0; tv.tv_usec = 0; FD_ZERO(&set_w); FD_ZERO(&set_e); FD_SET(_sd, &set_w); FD_SET(_sd, &set_e); result = select(FD_SETSIZE, &set_w, NULL, &set_e, &tv); if (result < 0) { XBMC->Log(LOG_ERROR, "Socket::send - select failed"); _sd = INVALID_SOCKET; return 0; } int status = 0; do { status = ::send(_sd, data, len, 0 ); #if defined(TARGET_WINDOWS) } while (status == SOCKET_ERROR && errno == WSAEWOULDBLOCK); #else } while (status == SOCKET_ERROR && errno == EAGAIN); #endif if (status == SOCKET_ERROR) { errormessage( getLastError(), "Socket::send"); XBMC->Log(LOG_ERROR, "Socket::send - failed to send data"); _sd = INVALID_SOCKET; } return status; } int Socket::sendto ( const char* data, unsigned int size, bool sendcompletebuffer) { int sentbytes = 0; int i; do { i = ::sendto(_sd, data, size, 0, (const struct sockaddr*) &_sockaddr, sizeof( _sockaddr ) ); if (i <= 0) { errormessage( getLastError(), "Socket::sendto"); osCleanup(); return i; } sentbytes += i; } while ( (sentbytes < (int) size) && (sendcompletebuffer == true)); return i; } int Socket::receive ( std::string& data, unsigned int minpacketsize ) const { char * buf = NULL; int status = 0; if (!is_valid()) { return 0; } buf = new char [ minpacketsize + 1 ]; memset ( buf, 0, minpacketsize + 1 ); status = receive( buf, minpacketsize, minpacketsize ); data = buf; delete[] buf; return status; } //Receive until error or \n bool Socket::ReadResponse (int &code, vector &lines) { fd_set set_r, set_e; timeval timeout; int result; int retries = 6; char buffer[2048]; char cont = 0; string line; size_t pos1 = 0, pos2 = 0, pos3 = 0; code = 0; while (true) { while ((pos1 = line.find("\r\n", pos3)) != std::string::npos) { pos2 = line.find(cont); lines.push_back(line.substr(pos2+1, pos1-pos2-1)); line.erase(0, pos1 + 2); pos3 = 0; return true; } // we only need to recheck 1 byte if (line.size() > 0) { pos3 = line.size() - 1; } else { pos3 = 0; } if (cont == ' ') { break; } timeout.tv_sec = RECEIVE_TIMEOUT; timeout.tv_usec = 0; // fill with new data FD_ZERO(&set_r); FD_ZERO(&set_e); FD_SET(_sd, &set_r); FD_SET(_sd, &set_e); result = select(FD_SETSIZE, &set_r, NULL, &set_e, &timeout); if (result < 0) { XBMC->Log(LOG_DEBUG, "CVTPTransceiver::ReadResponse - select failed"); lines.push_back("ERROR: Select failed"); code = 1; //error _sd = INVALID_SOCKET; return false; } if (result == 0) { if (retries != 0) { XBMC->Log(LOG_DEBUG, "CVTPTransceiver::ReadResponse - timeout waiting for response, retrying... (%i)", retries); retries--; continue; } else { XBMC->Log(LOG_DEBUG, "CVTPTransceiver::ReadResponse - timeout waiting for response. Failed after 10 retries."); lines.push_back("ERROR: Failed after 10 retries"); code = 1; //error _sd = INVALID_SOCKET; return false; } } result = recv(_sd, buffer, sizeof(buffer) - 1, 0); if (result < 0) { XBMC->Log(LOG_DEBUG, "CVTPTransceiver::ReadResponse - recv failed"); lines.push_back("ERROR: Recv failed"); code = 1; //error _sd = INVALID_SOCKET; return false; } buffer[result] = 0; line.append(buffer); } return true; } int Socket::receive ( std::string& data) const { char buf[MAXRECV + 1]; int status = 0; if ( !is_valid() ) { return 0; } memset ( buf, 0, MAXRECV + 1 ); status = receive( buf, MAXRECV, 0 ); data = buf; return status; } int Socket::receive ( char* data, const unsigned int buffersize, const unsigned int minpacketsize ) const { unsigned int receivedsize = 0; int status = 0; if ( !is_valid() ) { return 0; } while ( (receivedsize <= minpacketsize) && (receivedsize < buffersize) ) { status = ::recv(_sd, data+receivedsize, (buffersize - receivedsize), 0 ); if ( status == SOCKET_ERROR ) { int lasterror = getLastError(); #if defined(TARGET_WINDOWS) if ( lasterror != WSAEWOULDBLOCK) #else if ( lasterror != EAGAIN ) #endif { errormessage( lasterror, "Socket::receive" ); } else { XBMC->Log(LOG_ERROR, "Socket::read EAGAIN"); usleep(50000); continue; } return status; } receivedsize += status; if (receivedsize >= minpacketsize) break; } return receivedsize; } int Socket::recvfrom ( char* data, const int buffersize, struct sockaddr* from, socklen_t* fromlen) const { int status = ::recvfrom(_sd, data, buffersize, 0, from, fromlen); return status; } bool Socket::connect ( const std::string& host, const unsigned short port ) { if ( !is_valid() ) { return false; } _sockaddr.sin_family = _family; _sockaddr.sin_port = htons ( port ); if ( !setHostname( host ) ) { XBMC->Log(LOG_ERROR, "Socket::setHostname(%s) failed.\n", host.c_str()); return false; } int status = ::connect ( _sd, reinterpret_cast(&_sockaddr), sizeof ( _sockaddr ) ); if ( status == SOCKET_ERROR ) { XBMC->Log(LOG_ERROR, "Socket::connect %s:%u\n", host.c_str(), port); errormessage( getLastError(), "Socket::connect" ); return false; } return true; } bool Socket::reconnect() { if ( _sd != INVALID_SOCKET ) { return true; } if( !create() ) return false; int status = ::connect ( _sd, reinterpret_cast(&_sockaddr), sizeof ( _sockaddr ) ); if ( status == SOCKET_ERROR ) { errormessage( getLastError(), "Socket::connect" ); return false; } return true; } bool Socket::is_valid() const { return (_sd != INVALID_SOCKET); } #if defined(TARGET_WINDOWS) bool Socket::set_non_blocking ( const bool b ) { u_long iMode; if ( b ) iMode = 1; // enable non_blocking else iMode = 0; // disable non_blocking if (ioctlsocket(_sd, FIONBIO, &iMode) == -1) { XBMC->Log(LOG_ERROR, "Socket::set_non_blocking - Can't set socket condition to: %i", iMode); return false; } return true; } void Socket::errormessage( int errnum, const char* functionname) const { const char* errmsg = NULL; switch (errnum) { case WSANOTINITIALISED: errmsg = "A successful WSAStartup call must occur before using this function."; break; case WSAENETDOWN: errmsg = "The network subsystem or the associated service provider has failed"; break; case WSA_NOT_ENOUGH_MEMORY: errmsg = "Insufficient memory available"; break; case WSA_INVALID_PARAMETER: errmsg = "One or more parameters are invalid"; break; case WSA_OPERATION_ABORTED: errmsg = "Overlapped operation aborted"; break; case WSAEINTR: errmsg = "Interrupted function call"; break; case WSAEBADF: errmsg = "File handle is not valid"; break; case WSAEACCES: errmsg = "Permission denied"; break; case WSAEFAULT: errmsg = "Bad address"; break; case WSAEINVAL: errmsg = "Invalid argument"; break; case WSAENOTSOCK: errmsg = "Socket operation on nonsocket"; break; case WSAEDESTADDRREQ: errmsg = "Destination address required"; break; case WSAEMSGSIZE: errmsg = "Message too long"; break; case WSAEPROTOTYPE: errmsg = "Protocol wrong type for socket"; break; case WSAENOPROTOOPT: errmsg = "Bad protocol option"; break; case WSAEPFNOSUPPORT: errmsg = "Protocol family not supported"; break; case WSAEAFNOSUPPORT: errmsg = "Address family not supported by protocol family"; break; case WSAEADDRINUSE: errmsg = "Address already in use"; break; case WSAECONNRESET: errmsg = "Connection reset by peer"; break; case WSAHOST_NOT_FOUND: errmsg = "Authoritative answer host not found"; break; case WSATRY_AGAIN: errmsg = "Nonauthoritative host not found, or server failure"; break; case WSAEISCONN: errmsg = "Socket is already connected"; break; case WSAETIMEDOUT: errmsg = "Connection timed out"; break; case WSAECONNREFUSED: errmsg = "Connection refused"; break; case WSANO_DATA: errmsg = "Valid name, no data record of requested type"; break; default: errmsg = "WSA Error"; } XBMC->Log(LOG_ERROR, "%s: (Winsock error=%i) %s\n", functionname, errnum, errmsg); } int Socket::getLastError() const { return WSAGetLastError(); } int Socket::win_usage_count = 0; //Declared static in Socket class bool Socket::osInit() { win_usage_count++; // initialize winsock: if (WSAStartup(MAKEWORD(2,2),&_wsaData) != 0) { return false; } WORD wVersionRequested = MAKEWORD(2,2); // check version if (_wsaData.wVersion != wVersionRequested) { return false; } return true; } void Socket::osCleanup() { win_usage_count--; if(win_usage_count == 0) { WSACleanup(); } } #elif defined TARGET_LINUX || defined TARGET_DARWIN || defined TARGET_FREEBSD bool Socket::set_non_blocking ( const bool b ) { int opts; opts = fcntl(_sd, F_GETFL); if ( opts < 0 ) { return false; } if ( b ) opts = ( opts | O_NONBLOCK ); else opts = ( opts & ~O_NONBLOCK ); if(fcntl (_sd , F_SETFL, opts) == -1) { XBMC->Log(LOG_ERROR, "Socket::set_non_blocking - Can't set socket flags to: %i", opts); return false; } return true; } void Socket::errormessage( int errnum, const char* functionname) const { const char* errmsg = NULL; switch ( errnum ) { case EAGAIN: //same as EWOULDBLOCK errmsg = "EAGAIN: The socket is marked non-blocking and the requested operation would block"; break; case EBADF: errmsg = "EBADF: An invalid descriptor was specified"; break; case ECONNRESET: errmsg = "ECONNRESET: Connection reset by peer"; break; case EDESTADDRREQ: errmsg = "EDESTADDRREQ: The socket is not in connection mode and no peer address is set"; break; case EFAULT: errmsg = "EFAULT: An invalid userspace address was specified for a parameter"; break; case EINTR: errmsg = "EINTR: A signal occurred before data was transmitted"; break; case EINVAL: errmsg = "EINVAL: Invalid argument passed"; break; case ENOTSOCK: errmsg = "ENOTSOCK: The argument is not a valid socket"; break; case EMSGSIZE: errmsg = "EMSGSIZE: The socket requires that message be sent atomically, and the size of the message to be sent made this impossible"; break; case ENOBUFS: errmsg = "ENOBUFS: The output queue for a network interface was full"; break; case ENOMEM: errmsg = "ENOMEM: No memory available"; break; case EPIPE: errmsg = "EPIPE: The local end has been shut down on a connection oriented socket"; break; case EPROTONOSUPPORT: errmsg = "EPROTONOSUPPORT: The protocol type or the specified protocol is not supported within this domain"; break; case EAFNOSUPPORT: errmsg = "EAFNOSUPPORT: The implementation does not support the specified address family"; break; case ENFILE: errmsg = "ENFILE: Not enough kernel memory to allocate a new socket structure"; break; case EMFILE: errmsg = "EMFILE: Process file table overflow"; break; case EACCES: errmsg = "EACCES: Permission to create a socket of the specified type and/or protocol is denied"; break; case ECONNREFUSED: errmsg = "ECONNREFUSED: A remote host refused to allow the network connection (typically because it is not running the requested service)"; break; case ENOTCONN: errmsg = "ENOTCONN: The socket is associated with a connection-oriented protocol and has not been connected"; break; default: break; } XBMC->Log(LOG_ERROR, "%s: (errno=%i) %s\n", functionname, errnum, errmsg); } int Socket::getLastError() const { return errno; } bool Socket::osInit() { // Not needed for Linux return true; } void Socket::osCleanup() { // Not needed for Linux } #endif //TARGET_WINDOWS || TARGET_LINUX || TARGET_DARWIN || TARGET_FREEBSD } //namespace NextPVR pvr.nextpvr-3.3.18-Leia/src/Socket.h000066400000000000000000000217111360274650100171700ustar00rootroot00000000000000/* * Copyright (C) 2005-2011 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #pragma once //Include platform specific datatypes, header files, defines and constants: #if defined TARGET_WINDOWS #define WIN32_LEAN_AND_MEAN // Enable LEAN_AND_MEAN support #pragma warning(disable:4005) // Disable "warning C4005: '_WINSOCKAPI_' : macro redefinition" #include #pragma warning(default:4005) #include #ifndef NI_MAXHOST #define NI_MAXHOST 1025 #endif #ifndef socklen_t typedef int socklen_t; #endif #ifndef ipaddr_t typedef unsigned long ipaddr_t; #endif #ifndef port_t typedef unsigned short port_t; #endif #elif defined TARGET_LINUX || defined TARGET_DARWIN || defined TARGET_FREEBSD #ifdef SOCKADDR_IN #undef SOCKADDR_IN #endif #include /* for socket,connect */ #include /* for socket,connect */ #include /* for Unix socket */ #include /* for inet_pton */ #include /* for gethostbyname */ #include /* for htons */ #include /* for read, write, close */ #include #include typedef int SOCKET; typedef sockaddr SOCKADDR; typedef sockaddr_in SOCKADDR_IN; #ifndef INVALID_SOCKET #define INVALID_SOCKET (-1) #endif #define SOCKET_ERROR (-1) #else #error Platform specific socket support is not yet available on this platform! #endif #include namespace NextPVR { #define MAXCONNECTIONS 1 ///< Maximum number of pending connections before "Connection refused" #define MAXRECV 1500 ///< Maximum packet size enum SocketFamily { #ifdef CONFIG_SOCKET_IPV6 af_inet6 = AF_INET6, af_unspec = AF_UNSPEC, ///< Either INET or INET6 #endif af_inet = AF_INET }; enum SocketDomain { #if defined TARGET_LINUX || defined TARGET_DARWIN || defined TARGET_FREEBSD pf_unix = PF_UNIX, pf_local = PF_LOCAL, #endif #ifdef CONFIG_SOCKET_IPV6 pf_inet6 = PF_INET6, pf_unspec = PF_UNSPEC, //< Either INET or INET6 #endif pf_inet = PF_INET }; enum SocketType { sock_stream = SOCK_STREAM, sock_dgram = SOCK_DGRAM }; enum SocketProtocol { tcp = IPPROTO_TCP, udp = IPPROTO_UDP #ifdef CONFIG_SOCKET_IPV6 , ipv6 = IPPROTO_IPV6 #endif }; class Socket { public: /*! * An unconnected socket may be created directly on the local * machine. The socket type (SOCK_STREAM, SOCK_DGRAM) and * protocol may also be specified. * If the socket cannot be created, an exception is thrown. * * \param family Socket family (IPv4 or IPv6) * \param domain The domain parameter specifies a communications domain within which communication will take place; * this selects the protocol family which should be used. * \param type base type and protocol family of the socket. * \param protocol specific protocol to apply. */ Socket(const enum SocketFamily family, const enum SocketDomain domain, const enum SocketType type, const enum SocketProtocol protocol = tcp); Socket(void); virtual ~Socket(); //Socket settings /*! * Socket setFamily * \param family Can be af_inet or af_inet6. Default: af_inet */ void setFamily(const enum SocketFamily family) { _family = family; }; /*! * Socket setDomain * \param domain Can be pf_unix, pf_local, pf_inet or pf_inet6. Default: pf_inet */ void setDomain(const enum SocketDomain domain) { _domain = domain; }; /*! * Socket setType * \param type Can be sock_stream or sock_dgram. Default: sock_stream. */ void setType(const enum SocketType type) { _type = type; }; /*! * Socket setProtocol * \param protocol Can be tcp or udp. Default: tcp. */ void setProtocol(const enum SocketProtocol protocol) { _protocol = protocol; }; /*! * Socket setPort * \param port port number for socket communication */ void setPort (const unsigned short port) { _sockaddr.sin_port = htons ( port ); }; bool setHostname ( const std::string& host ); // Server initialization /*! * Socket create * Create a new socket * \return True if succesful */ bool create(); /*! * Socket close * Close the socket * \return True if succesful */ bool close(); /*! * Socket bind */ bool bind ( const unsigned short port ); bool listen() const; bool accept ( Socket& socket ) const; // Client initialization bool connect ( const std::string& host, const unsigned short port ); bool reconnect(); // Data Transmission /*! * Socket send function * * \param data Reference to a std::string with the data to transmit * \return Number of bytes send or -1 in case of an error */ int send ( const std::string& data ); /*! * Socket send function * * \param data Pointer to a character array of size 'size' with the data to transmit * \param size Length of the data to transmit * \return Number of bytes send or -1 in case of an error */ int send ( const char* data, const unsigned int size ); /*! * Socket sendto function * * \param data Reference to a std::string with the data to transmit * \param size Length of the data to transmit * \param sendcompletebuffer If 'true': do not return until the complete buffer is transmitted * \return Number of bytes send or -1 in case of an error */ int sendto ( const char* data, unsigned int size, bool sendcompletebuffer = false); // Data Receive /*! * Socket receive function * * \param data Reference to a std::string for storage of the received data. * \param minpacketsize The minimum number of bytes that should be received before returning from this function * \return Number of bytes received or SOCKET_ERROR */ int receive ( std::string& data, unsigned int minpacketsize ) const; /*! * Socket receive function * * \param data Reference to a std::string for storage of the received data. * \return Number of bytes received or SOCKET_ERROR */ int receive ( std::string& data ) const; /*! * Socket receive function * * \param data Pointer to a character array of size buffersize. Used to store the received data. * \param buffersize Size of the 'data' buffer * \param minpacketsize Specifies the minimum number of bytes that need to be received before returning * \return Number of bytes received or SOCKET_ERROR */ int receive ( char* data, const unsigned int buffersize, const unsigned int minpacketsize ) const; /*! * Socket recvfrom function * * \param data Pointer to a character array of size buffersize. Used to store the received data. * \param buffersize Size of the 'data' buffer * \param from Optional: pointer to a sockaddr struct that will get the address from which the data is received * \param fromlen Optional, only required if 'from' is given: length of from struct * \return Number of bytes received or SOCKET_ERROR */ int recvfrom ( char* data, const int buffersize, struct sockaddr* from = NULL, socklen_t* fromlen = NULL) const; bool set_non_blocking ( const bool ); bool ReadResponse (int &code, std::vector &lines); bool is_valid() const; bool read_ready(); private: SOCKET _sd; ///< Socket Descriptor SOCKADDR_IN _sockaddr; ///< Socket Address enum SocketFamily _family; ///< Socket Address Family enum SocketProtocol _protocol; ///< Socket Protocol enum SocketType _type; ///< Socket Type enum SocketDomain _domain; ///< Socket domain #ifdef TARGET_WINDOWS WSADATA _wsaData; ///< Windows Socket data static int win_usage_count; ///< Internal Windows usage counter used to prevent a global WSACleanup when more than one Socket object is used #endif void errormessage( int errornum, const char* functionname = NULL) const; int getLastError(void) const; bool osInit(); void osCleanup(); }; } //namespace MPTV pvr.nextpvr-3.3.18-Leia/src/buffers/000077500000000000000000000000001360274650100172215ustar00rootroot00000000000000pvr.nextpvr-3.3.18-Leia/src/buffers/Buffer.cpp000066400000000000000000000055621360274650100211460ustar00rootroot00000000000000/* * Copyright (C) 2015 Sam Stenvall * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "Buffer.h" #include using namespace timeshift; using namespace ADDON; const int Buffer::DEFAULT_READ_TIMEOUT = 10; bool Buffer::Open(const std::string inputUrl) { return Buffer::Open(inputUrl,READ_NO_CACHE); } bool Buffer::Open(const std::string inputUrl, int optFlag) { m_active = true; if (!inputUrl.empty()) { // Append the read timeout parameter XBMC->Log(LOG_DEBUG, "Buffer::Open() called! [ %s ]", inputUrl.c_str()); std::stringstream ss; if (inputUrl.rfind("http", 0) == 0) { ss << inputUrl << "|connection-timeout=" << m_readTimeout; } else { ss << inputUrl; } m_inputHandle = XBMC->OpenFile(ss.str().c_str(), optFlag ); } // Remember the start time and open the input m_startTime = time(nullptr); return m_inputHandle != nullptr; } Buffer::~Buffer() { Buffer::Close(); } void Buffer::Close() { m_active = false; CloseHandle(m_inputHandle); } void Buffer::CloseHandle(void *&handle) { if (handle) { XBMC->CloseFile(handle); XBMC->Log(LOG_DEBUG, "%s:%d:", __FUNCTION__, __LINE__); handle = nullptr; } } void Buffer::LeaseWorker(void) { while (m_isLeaseRunning == true) { time_t now = time(nullptr); bool complete = false; if ( m_nextLease <= now && m_complete == false) { std::this_thread::yield(); std::unique_lock lock(m_mutex); int retval = Lease(); if ( retval == HTTP_OK) { m_nextLease = now + 7; } else if (retval == HTTP_BADREQUEST) { complete = true; XBMC->QueueNotification(QUEUE_INFO, "Tuner required for recording"); } else { XBMC->Log(LOG_ERROR, "channel.transcode.lease failed %lld", m_nextLease ); m_nextLease = now + 1; } } if (m_nextStreamInfo <= now || m_nextRoll <= now || complete == true) { GetStreamInfo(); if (complete) m_complete = true; } SLEEP(1000); } } int Buffer::Lease() { std::string response; return NextPVR::m_backEnd->DoRequest("/service?method=channel.transcode.lease", response); } pvr.nextpvr-3.3.18-Leia/src/buffers/Buffer.h000066400000000000000000000117221360274650100206060ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2015 Sam Stenvall * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #if defined(TARGET_WINDOWS) #include #include #endif #include #include #include #include "../client.h" #include #include #include "../BackendRequest.h" #if defined(TARGET_WINDOWS) #define SLEEP(ms) Sleep(ms) #else #define SLEEP(ms) usleep(ms*1000) #endif using namespace ADDON; namespace timeshift { /** * The basic type all buffers operate on */ #ifdef _WIN32 #include #else typedef unsigned char byte; #endif /** * Base class for all timeshift buffers */ class Buffer { public: Buffer() : m_active(false), m_inputHandle(nullptr), m_startTime(0), m_readTimeout(DEFAULT_READ_TIMEOUT) {XBMC->Log(LOG_NOTICE, "Buffer created!"); }; virtual ~Buffer(); /** * Opens the input handle * @return whether the input was successfully opened */ virtual bool Open(const std::string inputUrl); /** * Opens the input handle with options Kodi addons use 0 * @return whether the input was successfully opened */ virtual bool Open(const std::string inputUrl, int optFlag); /** * Closes the buffer */ virtual void Close(); /** * Reads "length" bytes into the specified buffer * @return the number of bytes read */ virtual int Read(byte *buffer, size_t length) = 0; /** * Seeks to the specified position * @return the new position */ virtual int64_t Seek(int64_t position, int whence) = 0; /** * Whether the buffer supports pausing */ virtual bool CanPauseStream() const { return false; } virtual void PauseStream(bool bPause) {} /** * Whether the buffer supports seeking */ virtual bool CanSeekStream() const { return false; } /** * @return the current read position */ virtual int64_t Position() const = 0; /** * @return the current length of the buffer */ virtual int64_t Length() const = 0; virtual bool IsTimeshifting() const { return false; } virtual bool IsRealTimeStream() const { if (m_active) return true; return false; } /** * @return stream times */ virtual PVR_ERROR GetStreamTimes(PVR_STREAM_TIMES *stimes) { stimes->startTime = m_startTime; stimes->ptsStart = 0; stimes->ptsBegin = 0; stimes->ptsEnd = 0; return PVR_ERROR_NO_ERROR; } /** * The time the buffer was created */ int m_chunkSize = 16; virtual PVR_ERROR GetStreamReadChunkSize(int* chunksize) { // Return 16K for recordings, and non-timeshift if (g_NowPlaying == Radio) *chunksize = 4096; else *chunksize = m_chunkSize * 1024; return PVR_ERROR_NO_ERROR; } /** * @return basically the current time */ virtual time_t GetEndTime() { return time(nullptr); } /** * Sets the read timeout (defaults to 10 seconds) * @param timeout the read timeout in seconds */ void SetReadTimeout(int timeout) { m_readTimeout = timeout; } void Channel(int channel_id) { m_channel_id = channel_id; } protected: time_t m_nextRoll; time_t m_nextLease; time_t m_nextStreamInfo; bool m_isLeaseRunning; std::thread m_leaseThread; int Lease(); void LeaseWorker(); virtual bool GetStreamInfo() {return true;} bool m_complete; mutable std::mutex m_mutex; const static int DEFAULT_READ_TIMEOUT; /** * Safely closes an open file handle. * @param the handle to close. The pointer will be nulled. */ void CloseHandle(void *&handle); /** * The input handle (where data is read from) */ void *m_inputHandle; /** * The time (in seconds) to wait when opening a read handle and when * waiting for the buffer to have enough data */ int m_readTimeout; /** * Whether the buffer is active, i.e. m_inputHandle should be read from */ volatile std::atomic m_active; /** * The time the buffer was created */ time_t m_startTime; int m_channel_id; }; } pvr.nextpvr-3.3.18-Leia/src/buffers/CircularBuffer.cpp000066400000000000000000000051401360274650100226230ustar00rootroot00000000000000/* * Copyright (C) 2017 Mike Burgett * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ // // Dead simple circular buffer // #include "CircularBuffer.h" using namespace timeshift; using namespace ADDON; bool CircularBuffer::WriteBytes(const byte *buffer, int length) { if (length > m_iSize - m_iBytes) { XBMC->Log(LOG_DEBUG, "WriteBytes: returning false %d [%d] [%d] [%d]", length, m_iSize, m_iBytes, m_iSize - m_iBytes); return false; } if (length + m_iWritePos > m_iSize) { unsigned int chunk = m_iSize - m_iWritePos; memcpy(m_cBuffer + m_iWritePos, buffer, chunk); memcpy(m_cBuffer, buffer + chunk, length - chunk); m_iWritePos = length - chunk; } else { memcpy(m_cBuffer + m_iWritePos, buffer, length); m_iWritePos += length; } if (m_iWritePos == m_iSize) m_iWritePos = 0; m_iBytes += length; XBMC->Log(LOG_DEBUG, "WriteBytes: wrote %d bytes, returning true. [%d] [%d] [%d]", length, m_iSize, m_iBytes, m_iSize - m_iBytes); return true; } int CircularBuffer::ReadBytes(byte *buffer, int length) { if (length + m_iReadPos > m_iSize) { unsigned int chunk = m_iSize - m_iReadPos; memcpy(buffer, m_cBuffer + m_iReadPos, chunk); memcpy(buffer + chunk, m_cBuffer, length - chunk); m_iReadPos = length - chunk; } else { memcpy(buffer, m_cBuffer + m_iReadPos, length); m_iReadPos += length; } if (m_iReadPos == m_iSize) m_iReadPos = 0; m_iBytes -= length; XBMC->Log(LOG_DEBUG, "ReadBytes: returning %d\n", length); return length; } int CircularBuffer::AdjustBytes(int delta) { XBMC->Log(LOG_DEBUG, "AdjustBytes(%d): before: %d [%d]\n", delta, m_iReadPos, m_iBytes); m_iReadPos += delta; if (m_iReadPos < 0) m_iReadPos += m_iSize; if (m_iReadPos > m_iSize) m_iReadPos -= m_iSize; m_iBytes -= delta; XBMC->Log(LOG_DEBUG, "AdjustBytes(%d): after: %d [%d]\n", delta, m_iReadPos, m_iBytes); return m_iBytes; } pvr.nextpvr-3.3.18-Leia/src/buffers/CircularBuffer.h000066400000000000000000000030201360274650100222630ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2017 Mike Burgett * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ // // Dead simple circular buffer // #include "../client.h" namespace timeshift { class CircularBuffer { public: CircularBuffer(int size) : m_iBytes(0), m_iReadPos(0), m_iWritePos(0), m_iSize(size) { m_cBuffer = new byte[m_iSize]; } ~CircularBuffer() { delete[] m_cBuffer; } void Reset() { m_iBytes = m_iReadPos = m_iWritePos = 0; } bool WriteBytes(const byte *, int); int ReadBytes(byte *, int); int BytesFree() { return m_iSize - m_iBytes; } int BytesAvailable() { return m_iBytes; } int AdjustBytes(int); int Size() { return m_iSize; } private: byte *m_cBuffer; int32_t m_iReadPos; int32_t m_iWritePos; int32_t m_iSize; int32_t m_iBytes; }; } pvr.nextpvr-3.3.18-Leia/src/buffers/ClientTimeshift.cpp000066400000000000000000000133711360274650100230250ustar00rootroot00000000000000/* * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "ClientTimeshift.h" #include "../BackendRequest.h" #include "tinyxml.h" #include "kodi/util/XMLUtils.h" //#define FMODE 1 using namespace timeshift; bool ClientTimeShift::Open(const std::string inputUrl) { m_isPaused = false; m_stream_length = 0; m_stream_duration = 0; m_nextLease = 0; m_nextRoll = 0; m_nextStreamInfo = 0; m_isLive = true; m_rollingStartSeconds = 0; m_bytesPerSecond = 0; m_complete = false; if (g_NowPlaying == TV) { m_chunkSize = m_liveChunkSize; } else m_chunkSize = 4; XBMC->Log(LOG_DEBUG, "%s:%d: %d", __FUNCTION__, __LINE__, m_chunkSize); if (m_channel_id != 0) { std::string timeshift = "/services/service?method=channel.stream.start&channel_id=" + std::to_string(m_channel_id); std::string response; if (NextPVR::m_backEnd->DoRequest(timeshift.c_str(), response) != HTTP_OK) { return false; } } else { XBMC->Log(LOG_ERROR, "Missing channel for ClientTImeShift"); return false; } time_t timeout = time(nullptr) + 20; do { SLEEP(1000); if ( ClientTimeShift::GetStreamInfo()) { if ( m_stream_duration > m_prebuffer ) { break; } } Lease(); } while (!m_complete && (timeout > time(nullptr))); if (m_complete || m_stream_duration == 0) { XBMC->Log(LOG_ERROR,"Could not buffer stream"); StreamStop(); return false; } if (Buffer::Open(inputUrl, 0 ) == false) { XBMC->Log(LOG_ERROR,"Could not open streaming file"); StreamStop(); return false; } m_sourceURL = inputUrl + "&seek="; m_rollingStartSeconds = m_streamStart = time(nullptr); m_isLeaseRunning = true; m_leaseThread = std::thread([this]() { LeaseWorker(); }); return true; } void ClientTimeShift::Close() { Buffer::Close(); m_isLeaseRunning = false; if (m_leaseThread.joinable()) m_leaseThread.join(); StreamStop(); XBMC->Log(LOG_DEBUG, "%s:%d:", __FUNCTION__, __LINE__); m_lastClose = time(nullptr); } void ClientTimeShift::StreamStop() { std::string response; if (NextPVR::m_backEnd->DoRequest("/services/service?method=channel.stream.stop", response) != HTTP_OK) { XBMC->Log(LOG_ERROR, "%s:%d:", __FUNCTION__, __LINE__); } } int64_t ClientTimeShift::Seek(int64_t position, int whence) { if (m_complete) return -1; if (m_active) Buffer::Close(); ClientTimeShift::GetStreamInfo(); if (m_stream_duration > g_timeShiftBufferSeconds) { int64_t startSlipBuffer = m_stream_length - (g_timeShiftBufferSeconds * m_stream_length/m_stream_duration); XBMC->Log(LOG_DEBUG, "%s:%d: %lld %lld %lld", __FUNCTION__, __LINE__, startSlipBuffer, position, m_stream_length.load()); if (position < startSlipBuffer) position = startSlipBuffer; } XBMC->Log(LOG_DEBUG, "%s:%d: %lld %d %lld %d", __FUNCTION__, __LINE__, position, whence, m_stream_duration.load(), m_isPaused); if ( m_isPaused == true) { // skip while paused m_streamPosition = position; } else { std::string seekingInput = m_sourceURL + std::to_string(position ) + "-"; if ( Buffer::Open(seekingInput.c_str(), 0) == false) { XBMC->Log(LOG_ERROR, "Could not open file on seek"); return -1; } } return position; } bool ClientTimeShift::GetStreamInfo() { enum infoReturns { OK, XML_PARSE, HTTP_ERROR }; int64_t stream_duration; infoReturns infoReturn = HTTP_ERROR; std::string response; if (m_complete) { XBMC->Log(LOG_ERROR, "NextPVR not updating completed rolling file"); return ( m_stream_length != 0 ); } if (NextPVR::m_backEnd->DoRequest("/services/service?method=channel.stream.info", response) == HTTP_OK) { TiXmlDocument doc; if (doc.Parse(response.c_str()) != NULL) { TiXmlElement* filesNode = doc.FirstChildElement("map"); if (filesNode != NULL) { stream_duration = strtoll(filesNode->FirstChildElement("stream_duration")->GetText(),nullptr,0); if (stream_duration != 0) { m_stream_length = strtoll(filesNode->FirstChildElement("stream_length")->GetText(),nullptr,0); m_stream_duration = stream_duration/1000; if (m_stream_duration > g_timeShiftBufferSeconds) { m_rollingStartSeconds = m_streamStart + m_stream_duration - g_timeShiftBufferSeconds; } XMLUtils::GetBoolean(filesNode,"complete",m_complete); if (m_complete == false) { if (m_nextRoll < time(nullptr)) { m_nextRoll = time(nullptr) + g_timeShiftBufferSeconds/3 + g_ServerTimeOffset; } } else { XBMC->QueueNotification(QUEUE_INFO, "Tuner required. Navigation disabled"); } } XBMC->Log(LOG_DEBUG,"CT channel.stream.info %lld %lld %d %lld",m_stream_length.load(), stream_duration,m_complete, m_rollingStartSeconds.load()); infoReturn = OK; } } else { infoReturn = XML_PARSE; } } m_nextStreamInfo = time(nullptr) + 10; return infoReturn == OK; } pvr.nextpvr-3.3.18-Leia/src/buffers/ClientTimeshift.h000066400000000000000000000050671360274650100224750ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2015 Sam Stenvall * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "RollingFile.h" #include #include std::string UriEncode(const std::string sSrc); using namespace ADDON; namespace timeshift { class ClientTimeShift : public RollingFile { private: bool m_isPaused = false; int64_t m_streamPosition; /** * The current live stream url with &seek= */ std::string m_sourceURL; public: ClientTimeShift() : RollingFile() { if (!XBMC->GetSetting("prebuffer", &m_prebuffer)) { m_prebuffer = 0; } if (!XBMC->GetSetting("chunklivetv", &m_liveChunkSize)) { m_liveChunkSize = 64; } m_lastClose = 0; m_channel_id = 0; XBMC->Log(LOG_NOTICE, "ClientTimeShift Buffer created!"); } virtual void PauseStream(bool bPause) override { if ((m_isPaused = bPause)) { // pause m_streamPosition = XBMC->GetFilePosition(m_inputHandle); if (!m_complete) Buffer::Close(); } else { Seek(m_streamPosition,0); } } virtual ~ClientTimeShift() {} virtual bool Open(const std::string inputUrl) override; virtual void Close() override; virtual bool GetStreamInfo(); virtual int64_t Position() const override { return XBMC->GetFilePosition(m_inputHandle); } virtual int Read(byte *buffer, size_t length) override { int64_t dataLen = XBMC->ReadFile(m_inputHandle, buffer, length); if (m_complete && dataLen == 0) { XBMC->Log(LOG_DEBUG, "%s:%d: %lld %lld %lld %lld", __FUNCTION__, __LINE__, dataLen, length, XBMC->GetFileLength(m_inputHandle) ,XBMC->GetFilePosition(m_inputHandle)); } return dataLen; } int64_t Seek(int64_t position, int whence) override; void StreamStop(void); }; } pvr.nextpvr-3.3.18-Leia/src/buffers/DummyBuffer.cpp000066400000000000000000000017051360274650100221550ustar00rootroot00000000000000/* * Copyright (C) 2015 Sam Stenvall * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "DummyBuffer.h" using namespace timeshift; PVR_ERROR DummyBuffer::GetStreamTimes(PVR_STREAM_TIMES *stimes) { return Buffer::GetStreamTimes(stimes); } pvr.nextpvr-3.3.18-Leia/src/buffers/DummyBuffer.h000066400000000000000000000032701360274650100216210ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2015 Sam Stenvall * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "Buffer.h" using namespace ADDON; namespace timeshift { /** * Dummy buffer that just passes all calls through to the input file * handle without actually buffering anything */ class DummyBuffer : public Buffer { public: DummyBuffer() : Buffer() { XBMC->Log(LOG_NOTICE, "DummyBuffer created!"); } virtual ~DummyBuffer() {} virtual int Read(byte *buffer, size_t length) override { return XBMC->ReadFile(m_inputHandle, buffer, length); } virtual int64_t Seek(int64_t position, int whence) override { return -1; // we can't seek without a real buffer } virtual int64_t Position() const override { return XBMC->GetFilePosition(m_inputHandle); } virtual int64_t Length() const override { return XBMC->GetFileLength(m_inputHandle); } PVR_ERROR GetStreamTimes(PVR_STREAM_TIMES *) override; }; } pvr.nextpvr-3.3.18-Leia/src/buffers/RecordingBuffer.cpp000066400000000000000000000075131360274650100230010ustar00rootroot00000000000000/* * Copyright (C) 2015 Sam Stenvall * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "RecordingBuffer.h" using namespace timeshift; PVR_ERROR RecordingBuffer::GetStreamTimes(PVR_STREAM_TIMES *stimes) { stimes->startTime = 0; stimes->ptsStart = 0; stimes->ptsBegin = 0; stimes->ptsEnd = ((int64_t ) Duration() ) * DVD_TIME_BASE; return PVR_ERROR_NO_ERROR; } int RecordingBuffer::Duration(void) { if (m_recordingTime) { std::unique_lock lock(m_mutex); time_t endTime = time(nullptr); int diff = (int) (endTime - m_recordingTime -10); if (diff > 0) { int64_t bps = XBMC->GetFileLength(m_inputHandle) / diff; if ((XBMC->GetFileLength(m_inputHandle) - XBMC->GetFilePosition(m_inputHandle)) * bps < 10) { m_isLive = false; } else { m_isLive = true; } return diff; } else { m_isLive = false; return 0; } } else { return m_Duration; } } bool RecordingBuffer::Open(const std::string inputUrl,const PVR_RECORDING &recording) { m_Duration = recording.iDuration; if (!XBMC->GetSetting("chunkrecording", &m_chunkSize)) { m_chunkSize = 32; } XBMC->Log(LOG_DEBUG, "RecordingBuffer::Open In Progress %d %lld", recording.iDuration, recording.recordingTime); if (recording.iDuration + recording.recordingTime > time(nullptr)) { m_recordingTime = recording.recordingTime + g_ServerTimeOffset; XBMC->Log(LOG_DEBUG, "RecordingBuffer::Open In Progress %d %lld", recording.iDuration, recording.recordingTime); m_isLive = true; } else { m_recordingTime = 0; m_isLive = false; } m_recordingURL = inputUrl; if (recording.strDirectory[0] != 0) { char strDirectory [PVR_ADDON_URL_STRING_LENGTH]; strcpy(strDirectory,recording.strDirectory); int i = 0; int j = 0; for(; i <= strlen(recording.strDirectory); i++, j++) { if (recording.strDirectory[i] == '\\') { if (i==0 && recording.strDirectory[1] == '\\') { strcpy(strDirectory,"smb://"); i = 1; j = 5; } else { strDirectory[j] = '/'; } } else { strDirectory[j] = recording.strDirectory[i]; } } if ( XBMC->FileExists(strDirectory,false)) { //m_recordingURL = strDirectory; } } return Buffer::Open(m_recordingURL,0); } int RecordingBuffer::Read(byte *buffer, size_t length) { if (m_recordingTime) std::unique_lock lock(m_mutex); int dataRead = (int) XBMC->ReadFile(m_inputHandle, buffer, length); if (dataRead == 0 && m_isLive) { XBMC->Log(LOG_DEBUG, "%s:%d: %lld %lld", __FUNCTION__, __LINE__, XBMC->GetFileLength(m_inputHandle) ,XBMC->GetFilePosition(m_inputHandle)); int64_t position = XBMC->GetFilePosition(m_inputHandle); Buffer::Close(); Buffer::Open(m_recordingURL,0); Seek(position,0); dataRead = (int) XBMC->ReadFile(m_inputHandle, buffer, length); XBMC->Log(LOG_DEBUG, "%s:%d: %lld %lld", __FUNCTION__, __LINE__, XBMC->GetFileLength(m_inputHandle) ,XBMC->GetFilePosition(m_inputHandle)); } return dataRead; } pvr.nextpvr-3.3.18-Leia/src/buffers/RecordingBuffer.h000066400000000000000000000051171360274650100224440ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2015 Sam Stenvall * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "Buffer.h" using namespace ADDON; namespace timeshift { /** * Dummy buffer that just passes all calls through to the input file * handle without actually buffering anything */ class RecordingBuffer : public Buffer { private: int m_Duration; bool m_buffering = false; std::string m_recordingURL; public: RecordingBuffer() : Buffer() { m_Duration = 0; XBMC->Log(LOG_NOTICE, "RecordingBuffer created!"); } virtual ~RecordingBuffer() {} virtual int Read(byte *buffer, size_t length) override; virtual int64_t Seek(int64_t position, int whence) override { XBMC->Log(LOG_DEBUG, "Seek: %s:%d %lld %lld %lld", __FUNCTION__, __LINE__,position, XBMC->GetFilePosition(m_inputHandle), XBMC->GetFileLength(m_inputHandle) ); return XBMC->SeekFile(m_inputHandle, position, whence); } virtual bool CanPauseStream() const override { return true; } virtual bool CanSeekStream() const override { return true; } virtual bool IsRealTimeStream() const override { return false; } PVR_ERROR GetStreamTimes(PVR_STREAM_TIMES *) override; virtual int64_t Length() const override { return XBMC->GetFileLength(m_inputHandle); } virtual int64_t Position() const override { return XBMC->GetFilePosition(m_inputHandle); } virtual int Duration(void); int GetDuration(void) { return m_Duration; XBMC->Log(LOG_ERROR, "XXXXX Duration set to %d XXXXX", m_Duration); } void SetDuration(int duration) { m_Duration = duration; XBMC->Log(LOG_ERROR, "XXXXX Duration set to %d XXXXX", m_Duration); } bool Open(const std::string inputUrl,const PVR_RECORDING &recording); std::atomic m_isLive; // recording start time time_t m_recordingTime; }; } pvr.nextpvr-3.3.18-Leia/src/buffers/RollingFile.cpp000066400000000000000000000320051360274650100221330ustar00rootroot00000000000000/* * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "RollingFile.h" #include "../BackendRequest.h" #include #include #include "tinyxml.h" #include "util/XMLUtils.h" //#define TESTURL "d:/downloads/abc.ts" using namespace timeshift; /* Rolling File mode functions */ bool RollingFile::Open(const std::string inputUrl) { m_isPaused = false; m_nextLease = 0; m_nextStreamInfo = 0; m_nextRoll = 0; m_complete = false; m_stream_duration = 0; m_bytesPerSecond = 0; m_activeFilename.clear(); m_isLive = true; slipFiles.clear(); std::stringstream ss; if (g_NowPlaying == TV) { m_chunkSize = m_liveChunkSize; } else m_chunkSize = 4; XBMC->Log(LOG_DEBUG, "%s:%d: %d", __FUNCTION__, __LINE__, m_chunkSize); ss << inputUrl ;//<< "|connection-timeout=" << 15; if (ss.str().find("&epgmode=true") != std::string::npos) { m_isEpgBased = true; } else { m_isEpgBased = false; } m_slipHandle = XBMC->OpenFile(ss.str().c_str(), READ_NO_CACHE ); if (m_slipHandle == nullptr) { XBMC->Log(LOG_ERROR,"Could not open slipHandle file"); return false; } int waitTime = 0; if (g_NowPlaying == TV) { waitTime = m_prebuffer; } do { // epgmode=true requires a 10 second pause changing channels SLEEP(1000); waitTime--; if ( RollingFile::GetStreamInfo()) { m_lastClose = 0; } } while ((m_lastClose + 10) > time(nullptr)); if ( !RollingFile::GetStreamInfo()) { XBMC->Log(LOG_ERROR,"Could not read rolling file"); return false; } m_rollingStartSeconds = m_streamStart = time(nullptr); XBMC->Log(LOG_DEBUG, "RollingFile::Open in Rolling File Mode: %d", m_isEpgBased); m_activeFilename = slipFiles.back().filename; m_activeLength = -1; m_isLeaseRunning = true; m_leaseThread = std::thread([this]() { LeaseWorker(); }); while (m_stream_length < waitTime) { SLEEP(500); RollingFile::GetStreamInfo(); }; return RollingFile::RollingFileOpen(); } bool RollingFile::RollingFileOpen() { struct PVR_RECORDING recording; recording.recordingTime = time(nullptr); recording.iDuration = 5 * 60 * 60; memset(recording.strDirectory,0,sizeof(recording.strDirectory)); #if !defined(TESTURL) strcpy(recording.strDirectory, m_activeFilename.c_str()); #endif char strURL[1024]; #if defined(TESTURL) strcpy(strURL,TESTURL); #else snprintf(strURL,sizeof(strURL),"http://%s:%d/stream?f=%s&mode=http&sid=%s", g_szHostname.c_str(), g_iPort, UriEncode(m_activeFilename).c_str(), NextPVR::m_backEnd->getSID()); if (g_NowPlaying == Radio && m_activeLength == -1) { // reduce buffer for radio when playing in-progess slip file strcat(strURL,"&bufsize=32768&wait=true"); } #endif return RecordingBuffer::Open(strURL,recording); } bool RollingFile::GetStreamInfo() { enum infoReturns { OK, XML_PARSE, HTTP_ERROR }; int64_t stream_length; int64_t duration; infoReturns infoReturn; infoReturn = HTTP_ERROR; std::string response; if (m_nextRoll == LLONG_MAX) { XBMC->Log(LOG_ERROR, "NextPVR not updating completed rolling file"); return ( m_stream_length != 0 ); } if (NextPVR::m_backEnd->DoRequest("/services/service?method=channel.stream.info", response) == HTTP_OK) { TiXmlDocument doc; if (doc.Parse(response.c_str()) != NULL) { TiXmlElement* filesNode = doc.FirstChildElement("Files"); if (filesNode != NULL) { stream_length = strtoll(filesNode->FirstChildElement("Length")->GetText(),nullptr,0); duration = strtoll(filesNode->FirstChildElement("Duration")->GetText(),nullptr,0); XMLUtils::GetBoolean(filesNode,"Complete",m_complete); XBMC->Log(LOG_DEBUG,"channel.stream.info %lld %lld %d %d",stream_length, duration,m_complete, m_bytesPerSecond.load()); if (m_complete == true) { if ( slipFiles.empty() ) { return false; } m_stream_length = stream_length-500000; slipFiles.back().length = stream_length - slipFiles.back().offset; m_nextStreamInfo = m_nextRoll = LLONG_MAX; return true; } infoReturn = OK; if (duration!=0) { m_bytesPerSecond = stream_length/duration * 1000; } m_stream_length = stream_length; m_stream_duration = duration/1000; TiXmlElement* pFileNode; for( pFileNode = filesNode->FirstChildElement("File"); pFileNode; pFileNode=pFileNode->NextSiblingElement("File")) { int64_t offset = strtoll(pFileNode->Attribute("offset"),nullptr,0); if (!slipFiles.empty()) { if ( slipFiles.back().offset == offset) { // already have this file on top time_t now = time(nullptr); if (now >= m_nextRoll) { m_nextRoll = now + 1; } if (slipFiles.size() == 4) { slipFiles.front().offset = slipFiles.front().offset + stream_length - offset; if (!m_isEpgBased) { duration = slipFiles.front().seconds - duration; m_rollingStartSeconds = now - g_timeShiftBufferSeconds; } } break; } slipFiles.back().length = offset - slipFiles.back().offset; if (m_activeLength == -1) { m_activeLength = slipFiles.back().length; } } else { m_activeLength = -1; } struct slipFile newFile; newFile.filename = pFileNode->GetText(); newFile.offset = offset; newFile.length = -1; newFile.seconds = time(nullptr); slipFiles.push_back(newFile); if (m_isEpgBased) { std::regex base_regex(".+_20.+_(\\d{4})(\\d{4})\\.ts"); std::smatch base_match; if (std::regex_match(newFile.filename , base_match, base_regex)) { // The first sub_match is the whole string; the next // sub_match is the first parenthesized expression. if (base_match.size() == 3) { std::ssub_match base_sub_match = base_match[1]; int startTime = std::stoi(base_sub_match.str()); base_sub_match = base_match[2]; int endTime = std::stoi(base_sub_match.str()); XBMC->Log(LOG_DEBUG,"channel.stream.info %d %d",startTime,endTime); if (startTime < endTime) { m_nextRoll = (time(nullptr) / 60) * 60 + (endTime - startTime) * 60 - 3 + g_ServerTimeOffset; } else { m_nextRoll = (time(nullptr) / 60) * 60 + (2400 - startTime + endTime) * 60 - 3 + g_ServerTimeOffset; } } } if (m_nextRoll == 0) { m_isEpgBased = false; XBMC->Log(LOG_DEBUG,"Reset to Time-based %s",newFile.filename.c_str()); } } if (!m_isEpgBased) { m_nextRoll = time(nullptr) + g_timeShiftBufferSeconds/3 - 3 + g_ServerTimeOffset; } if (slipFiles.size() == 5) { time_t slipDuration = slipFiles.front().seconds; slipFiles.pop_front(); if (m_isEpgBased) { slipDuration = slipFiles.front().seconds - slipDuration; m_rollingStartSeconds += slipDuration; } else { m_rollingStartSeconds = time(nullptr) - g_timeShiftBufferSeconds; } } for (auto File : slipFiles ) { XBMC->Log(LOG_DEBUG," %s %lld %lld",File.filename.c_str(),File.offset, File.length); } break; } } } } if (infoReturn != OK) { XBMC->Log(LOG_ERROR, "NextPVR not updating rolling file %d", infoReturn ); m_nextStreamInfo = time(nullptr) + 1; return false; } m_nextStreamInfo = time(nullptr) + 10; return true; } PVR_ERROR RollingFile::GetStreamTimes(PVR_STREAM_TIMES *stimes) { if (m_isLive == false) return RecordingBuffer::GetStreamTimes(stimes); stimes->startTime = m_streamStart; stimes->ptsStart = 0; stimes->ptsBegin = (m_rollingStartSeconds - m_streamStart) * DVD_TIME_BASE; stimes->ptsEnd = (time(nullptr) - m_streamStart) * DVD_TIME_BASE; return PVR_ERROR_NO_ERROR; } void RollingFile::Close() { if (m_slipHandle != nullptr) { RecordingBuffer::Close(); SLEEP(500); XBMC->CloseFile(m_slipHandle); XBMC->Log(LOG_DEBUG, "%s:%d:", __FUNCTION__, __LINE__); m_slipHandle = nullptr; } m_isLeaseRunning = false; if (m_leaseThread.joinable()) m_leaseThread.join(); m_lastClose = time(nullptr); } int RollingFile::Read(byte *buffer, size_t length) { std::unique_lock lock(m_mutex); bool foundFile = false; int dataRead = (int) XBMC->ReadFile(m_inputHandle,buffer, length); if (dataRead == 0) { RollingFile::GetStreamInfo(); if (XBMC->GetFilePosition(m_inputHandle) == m_activeLength) { RecordingBuffer::Close(); for (std::list::reverse_iterator File=slipFiles.rbegin(); File!=slipFiles.rend(); ++File) { if (File->filename == m_activeFilename) { foundFile = true; if (File==slipFiles.rbegin()) { // still waiting for new filename XBMC->Log(LOG_ERROR, "%s:%d: waiting %s %s", __FUNCTION__, __LINE__,File->filename.c_str(),m_activeFilename.c_str()); } else { --File; m_activeFilename = File->filename; m_activeLength = File->length; } break; } } if (foundFile == false) { // file removed from slip file m_activeFilename = slipFiles.front().filename; m_activeLength = slipFiles.front().length; } RollingFile::RollingFileOpen(); dataRead = (int) XBMC->ReadFile(m_inputHandle, buffer, length); } else { while( XBMC->GetFilePosition(m_inputHandle) == XBMC->GetFileLength(m_inputHandle)) { RollingFile::GetStreamInfo(); if (m_nextRoll == LLONG_MAX) { XBMC->Log(LOG_DEBUG, "should exit %s:%d: %lld %lld %lld", __FUNCTION__, __LINE__,Length(), XBMC->GetFileLength(m_inputHandle) ,XBMC->GetFilePosition(m_inputHandle)); return 0; } XBMC->Log(LOG_DEBUG, "should exit %s:%d: %lld %lld %lld", __FUNCTION__, __LINE__,Length(), XBMC->GetFileLength(m_inputHandle) ,XBMC->GetFilePosition(m_inputHandle)); SLEEP(200); } } XBMC->Log(LOG_DEBUG, "%s:%d: %d %d %lld %lld", __FUNCTION__, __LINE__,length, dataRead, XBMC->GetFileLength(m_inputHandle) ,XBMC->GetFilePosition(m_inputHandle)); } else if (dataRead < length) { //XBMC->Log(LOG_DEBUG, "short read %s:%d: %lld %d", __FUNCTION__, __LINE__,length, dataRead); } return dataRead; } int64_t RollingFile::Seek(int64_t position, int whence) { slipFile prevFile; int64_t adjust; RollingFile::GetStreamInfo(); prevFile = slipFiles.front(); if (slipFiles.back().offset <= position) { // seek on head if ( m_activeFilename != slipFiles.back().filename) { RecordingBuffer::Close(); m_activeFilename = slipFiles.back().filename; m_activeLength = slipFiles.back().length; RollingFile::RollingFileOpen(); } adjust = slipFiles.back().offset; } else { for (auto File : slipFiles ) { if (position < File.offset) { XBMC->Log(LOG_INFO,"Found slip file %s %lld",prevFile.filename.c_str(),prevFile.offset); adjust = prevFile.offset; if ( m_activeFilename != prevFile.filename) { RecordingBuffer::Close(); m_activeFilename = prevFile.filename; m_activeLength = prevFile.length; RollingFile::RollingFileOpen(); } break; } else { adjust = File.offset; } prevFile = File; } } if (position-adjust < 0) { adjust = position; } int64_t seekval = RecordingBuffer::Seek(position - adjust,whence); XBMC->Log(LOG_DEBUG, "%s:%d: %lld %d %lld", __FUNCTION__, __LINE__, position, adjust, seekval); return seekval; } pvr.nextpvr-3.3.18-Leia/src/buffers/RollingFile.h000066400000000000000000000054201360274650100216010ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2015 Sam Stenvall * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "RecordingBuffer.h" #include #include #include std::string UriEncode(const std::string sSrc); using namespace ADDON; namespace timeshift { /** * Dummy buffer that just passes all calls through to the input file * handle without actually buffering anything */ class RollingFile : public RecordingBuffer { private: std::string m_activeFilename; int64_t m_activeLength; protected: void *m_slipHandle = nullptr; time_t m_streamStart; std::atomic m_rollingStartSeconds; std::atomic m_stream_length; std::atomic m_stream_duration; std::atomic m_bytesPerSecond; bool m_isEpgBased; int m_prebuffer; int m_liveChunkSize; time_t m_lastClose; bool m_isPaused; struct slipFile{ std::string filename; int64_t offset; int64_t length; int seconds; }; std::list slipFiles; public: RollingFile() : RecordingBuffer() { if (!XBMC->GetSetting("prebuffer", &m_prebuffer)) { m_prebuffer = 8; } if (!XBMC->GetSetting("chunklivetv", &m_liveChunkSize)) { m_liveChunkSize = 64; } m_lastClose = 0; XBMC->Log(LOG_NOTICE, "EPG Based Buffer created!"); } virtual ~RollingFile() {} virtual bool Open(const std::string inputUrl) override; virtual void Close() override; virtual void PauseStream(bool bPause) override { if ((m_isPaused = bPause)) m_nextLease = 20; } virtual int64_t Length() const override { return m_stream_length; } virtual int64_t Position() const override { return m_activeLength + XBMC->GetFilePosition(m_inputHandle); } virtual int Read(byte *buffer, size_t length) override; int64_t Seek(int64_t position, int whence) override; bool RollingFileOpen(); virtual bool GetStreamInfo(); virtual PVR_ERROR GetStreamTimes(PVR_STREAM_TIMES *) override; }; } pvr.nextpvr-3.3.18-Leia/src/buffers/Seeker.cpp000066400000000000000000000124741360274650100211530ustar00rootroot00000000000000/* * Copyright (C) 2017 Mike Burgett * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "Seeker.h" using namespace timeshift; using namespace ADDON; bool Seeker::InitSeek(int64_t offset, int whence) { int64_t temp; m_xStreamOffset = m_iBlockOffset = 0; m_bSeeking = m_bSeekBlockRequested = m_bSeekBlockReceived = m_streamPositionSet = false; if (whence == SEEK_SET) { temp = offset; } else if (whence == SEEK_CUR) { temp = offset + m_pSd->streamPosition; } else if (whence == SEEK_END) { temp = offset + m_pSd->lastKnownLength; } else { return false; // Unrecognized. } // Prevent seeking beyond live point. if (temp > m_pSd->lastKnownLength) temp = m_pSd->lastKnownLength; m_iBlockOffset = temp % m_pSd->inputBlockSize; m_xStreamOffset = temp - m_iBlockOffset; m_bSeeking = true; XBMC->Log(LOG_DEBUG, "block: %d, stream: %lli, m_bSeeking: %d", m_iBlockOffset, m_xStreamOffset, m_bSeeking); return true; } bool Seeker::PreprocessSeek() { XBMC->Log(LOG_DEBUG, "PreprocessSeek()"); bool do_seek = false; // if true, we have to do seek the non-optimized way. int64_t curStreamPtr = m_pSd->streamPosition.load(); int curOffset = curStreamPtr % m_pSd->inputBlockSize; int64_t curBlock = curStreamPtr - curOffset; // Moving within the same block (happens at every playback start) if (curBlock == m_xStreamOffset) { // We're in the same block! int moveOffset = m_iBlockOffset - curOffset; XBMC->Log(LOG_DEBUG, "%s:%d: curBlock: %lli, curOffset: %d, moveBack: %d", __FUNCTION__, __LINE__, curBlock, curOffset, moveOffset); m_pSd->streamPosition.fetch_add(moveOffset); m_cirBuf->AdjustBytes(moveOffset); m_bSeeking = false; } else { if (curBlock < m_xStreamOffset) { // seek forward int64_t seekTarget = m_xStreamOffset + m_iBlockOffset; XBMC->Log(LOG_DEBUG, "%s:%d: curBlock: %lli, m_xStreamOffset: %lli, m_pSd->lastBlockBuffered: %lli", __FUNCTION__, __LINE__, curBlock, m_xStreamOffset, m_pSd->lastBlockBuffered); if (m_xStreamOffset <= m_pSd->lastBlockBuffered) { // Seeking forward in buffer. int seekDiff = (int )(seekTarget - curStreamPtr); m_pSd->streamPosition.store(seekTarget); m_cirBuf->AdjustBytes(seekDiff); } else if (m_xStreamOffset < m_pSd->requestBlock) { // Block not buffered, but has been requested. m_bSeekBlockRequested = true; m_cirBuf->Reset(); XBMC->Log(LOG_DEBUG, "%s:%d: currentWindowSize = %d", __FUNCTION__, __LINE__, m_pSd->currentWindowSize); m_pSd->currentWindowSize -= (int )((curBlock - m_pSd->lastBlockBuffered) / m_pSd->inputBlockSize); m_pSd->currentWindowSize = std::min(0, m_pSd->currentWindowSize); XBMC->Log(LOG_DEBUG, "%s:%d: currentWindowSize = %d", __FUNCTION__, __LINE__, m_pSd->currentWindowSize); } else { // Outside both buffer, and requested range, handle 'normally' XBMC->Log(LOG_DEBUG, "%s:%d:", __FUNCTION__, __LINE__); do_seek = true; } } else { // Only seek backwards we can optimize was handled already XBMC->Log(LOG_DEBUG, "%s:%d:", __FUNCTION__, __LINE__); do_seek = true; } } XBMC->Log(LOG_DEBUG, "PreprocessSeek() returning %d", do_seek); if (do_seek) { // 'clear' the circular buffer. m_cirBuf->Reset(); m_pSd->currentWindowSize = 0; // Full request window. } return do_seek; } void Seeker::ProcessRequests() { if (m_bSeeking) { m_streamPositionSet = false; if (!m_bSeekBlockRequested) { m_pSd->requestBlock = m_xStreamOffset; m_pSd->currentWindowSize = 0; // Request all blocks in window m_bSeekBlockRequested = true; } } } bool Seeker::PostprocessSeek(int64_t blockNo) { // seeked block has just been buffered! // reset seek mechanism bool retVal = false; if (m_bSeeking) { if (blockNo == m_xStreamOffset) { if (!m_streamPositionSet) { m_pSd->streamPosition.store(m_xStreamOffset + m_iBlockOffset); m_cirBuf->AdjustBytes(m_iBlockOffset); m_streamPositionSet = true; XBMC->Log(LOG_DEBUG, "%s:%d - m_xStreamOffset: %llu, m_iBlockOffset: %d", __FUNCTION__, __LINE__, m_xStreamOffset, m_iBlockOffset); } if (m_iBlockOffset) { // Go around one more time. XBMC->Log(LOG_DEBUG, "%s:%d", __FUNCTION__, __LINE__); m_iBlockOffset = 0; m_xStreamOffset += m_pSd->inputBlockSize; retVal = false; } else { m_bSeekBlockRequested = false; m_bSeeking = false; m_xStreamOffset = -1; retVal = true; } } } return retVal; } pvr.nextpvr-3.3.18-Leia/src/buffers/Seeker.h000066400000000000000000000040151360274650100206100ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2017 Mike Burgett * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #if defined(TARGET_WINDOWS) #include #endif #include "../client.h" #include "CircularBuffer.h" #include "session.h" namespace timeshift { class Seeker { public: Seeker(session_data_t *sd, CircularBuffer *cirBuf) : m_pSd(sd), m_cirBuf(cirBuf), m_xStreamOffset(0), m_iBlockOffset(0), m_bSeeking(false), m_bSeekBlockRequested(false), m_bSeekBlockReceived(false), m_streamPositionSet(false) {} ~Seeker() {} bool InitSeek(int64_t offset, int whence); bool Active() { return m_bSeeking; } bool BlockRequested() { return m_bSeekBlockRequested; } bool PreprocessSeek(); void ProcessRequests(); bool PostprocessSeek(int64_t); int64_t SeekStreamOffset() { if (m_bSeeking) return m_xStreamOffset; return -1; } void Clear() { m_xStreamOffset = 0; m_iBlockOffset = 0; m_bSeeking = m_bSeekBlockRequested = m_bSeekBlockReceived = m_streamPositionSet = false; } private: session_data_t *m_pSd; CircularBuffer *m_cirBuf; int64_t m_xStreamOffset; int32_t m_iBlockOffset; bool m_bSeeking; bool m_bSeekBlockRequested; bool m_bSeekBlockReceived; bool m_streamPositionSet; }; } pvr.nextpvr-3.3.18-Leia/src/buffers/TimeshiftBuffer.cpp000066400000000000000000000433341360274650100230220ustar00rootroot00000000000000/* * Copyright (C) 2015 Sam Stenvall * Copyright (C) 2017 Mike Burgett [modifications to use memory-ring buffer * for server-side tsb] * * Block request and processing logic copied from liveshift.cpp and * RingBuffer.cpp which are Copyright (C) Team XBMC and distributed * under the same license. * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "TimeshiftBuffer.h" using namespace timeshift; using namespace ADDON; const int TimeshiftBuffer::INPUT_READ_LENGTH = 32768; const int TimeshiftBuffer::BUFFER_BLOCKS = 48; const int TimeshiftBuffer::WINDOW_SIZE = std::max(6, (BUFFER_BLOCKS/2)); // Fix a stupid #define on Windows which causes XBMC->DeleteFile() to break #ifdef _WIN32 #undef DeleteFile #endif // _WIN32 TimeshiftBuffer::TimeshiftBuffer() : Buffer(), m_circularBuffer(INPUT_READ_LENGTH * BUFFER_BLOCKS), m_seek(&m_sd, &m_circularBuffer), m_streamingclient(nullptr), m_CanPause(true) { XBMC->Log(LOG_DEBUG, "TimeshiftBuffer created!"); m_sd.lastKnownLength.store(0); m_sd.ptsBegin.store(0); m_sd.ptsEnd.store(0); m_sd.tsbStart.store(0); m_sd.streamPosition.store(0); m_sd.iBytesPerSecond = 0; m_sd.sessionStartTime.store(0); m_sd.tsbStartTime.store(0); m_sd.tsbRollOff = 0; m_sd.lastBlockBuffered = 0; m_sd.lastBufferTime = 0; m_sd.currentWindowSize = 0; m_sd.requestNumber = 0; m_sd.requestBlock = 0; m_sd.isPaused = false; m_sd.pauseStart = 0; m_sd.lastPauseAdjust = 0; } TimeshiftBuffer::~TimeshiftBuffer() { TimeshiftBuffer::Close(); } bool TimeshiftBuffer::Open(const std::string inputUrl) { XBMC->Log(LOG_DEBUG, "TimeshiftBuffer::Open()"); Buffer::Open(""); // To set the time stream starts m_sd.sessionStartTime.store(m_startTime); m_sd.tsbStartTime.store(m_sd.sessionStartTime.load()); m_streamingclient = new NextPVR::Socket(NextPVR::af_inet, NextPVR::pf_inet, NextPVR::sock_stream, NextPVR::tcp); if (!m_streamingclient->create()) { XBMC->Log(LOG_ERROR, "%s:%d: Could not connect create streaming socket", __FUNCTION__, __LINE__); return false; } if (!m_streamingclient->connect(g_szHostname, g_iPort)) { XBMC->Log(LOG_ERROR, "%s:%d: Could not connect to NextPVR backend (%s:%d) for streaming", __FUNCTION__, __LINE__, g_szHostname.c_str(), g_iPort); return false; } m_streamingclient->send(inputUrl.c_str(), strlen(inputUrl.c_str())); char line[256]; sprintf(line, "Connection: close\r\n"); m_streamingclient->send(line, strlen(line)); sprintf(line, "\r\n"); m_streamingclient->send(line, strlen(line)); //m_currentLivePosition = 0; char buf[1024]; int read = m_streamingclient->receive(buf, sizeof buf, 0); if (read < 0) return false; for (int i=0; i 0) { XBMC->Log(LOG_DEBUG, "remainder: %s", &buf[i+4]); WriteData((byte *)&buf[i+4], remainder, 0); } char header[256]; if (i < sizeof(header)) { memset(header, 0, sizeof(header)); memcpy(header, buf, i); XBMC->Log(LOG_DEBUG, "%s", header); if (strstr(header, "HTTP/1.1 404") != NULL) { XBMC->Log(LOG_DEBUG, "Unable to start channel. 404"); XBMC->QueueNotification(QUEUE_INFO, "Tuner not available"); return false; } } m_streamingclient->set_non_blocking(0); break; } } XBMC->Log(LOG_DEBUG, "TSB: Opened streaming connection!"); // Start the input thread m_inputThread = std::thread([this]() { ConsumeInput(); }); m_tsbThread = std::thread([this]() { TSBTimerProc(); }); XBMC->Log(LOG_DEBUG, "Open grabbing lock"); std::unique_lock lock(m_mutex); XBMC->Log(LOG_DEBUG, "Open Continuing"); int minLength = BUFFER_BLOCKS * INPUT_READ_LENGTH; XBMC->Log(LOG_DEBUG, "Open waiting for %d bytes to buffer", minLength); m_reader.wait_for(lock, std::chrono::seconds(1), [this, minLength]() { return m_circularBuffer.BytesAvailable() >= minLength; }); XBMC->Log(LOG_DEBUG, "Open Continuing %d / %d", m_circularBuffer.BytesAvailable(), minLength); // Make sure data is flowing, before declaring success. if (m_circularBuffer.BytesAvailable() != 0) return true; else return false; } void TimeshiftBuffer::Close() { XBMC->Log(LOG_DEBUG, "TimeshiftBuffer::Close()"); // Wait for the input thread to terminate Buffer::Close(); m_writer.notify_one(); // In case it's sleeping. if (m_inputThread.joinable()) m_inputThread.join(); if (m_tsbThread.joinable()) m_tsbThread.join(); if (m_streamingclient) { m_streamingclient->close(); m_streamingclient = nullptr; } // Reset session data m_sd.requestBlock = 0; m_sd.requestNumber = 0; m_sd.lastKnownLength.store(0); m_sd.ptsBegin.store(0); m_sd.ptsEnd.store(0); m_sd.tsbStart.store(0); m_sd.sessionStartTime.store(0); m_sd.tsbStartTime.store(0); m_sd.tsbRollOff = 0; m_sd.iBytesPerSecond = 0; m_sd.lastBlockBuffered = 0; m_sd.lastBufferTime = 0; m_sd.streamPosition.store(0); m_sd.currentWindowSize = 0; m_sd.inputBlockSize = INPUT_READ_LENGTH; m_sd.isPaused = false; m_sd.pauseStart = 0; m_sd.lastPauseAdjust = 0; m_circularBuffer.Reset(); Reset(); } void TimeshiftBuffer::Reset() { XBMC->Log(LOG_DEBUG, "TimeshiftBuffer::Reset()"); // Close any open handles std::unique_lock lock(m_mutex); m_circularBuffer.Reset(); // Reset m_seek.Clear(); } int TimeshiftBuffer::Read(byte *buffer, size_t length) { int bytesRead = 0; std::unique_lock lock(m_mutex); XBMC->Log(LOG_DEBUG, "TimeshiftBuffer::Read() %d @ %lli", length, m_sd.streamPosition.load()); // Wait until we have enough data if (! m_reader.wait_for(lock, std::chrono::seconds(m_readTimeout), [this, length]() { return m_circularBuffer.BytesAvailable() >= (int )length; })) { XBMC->Log(LOG_DEBUG, "Timeout waiting for bytes!! [buffer underflow]"); } bytesRead = m_circularBuffer.ReadBytes(buffer, length); m_sd.streamPosition.fetch_add(length); if (m_circularBuffer.BytesFree() >= INPUT_READ_LENGTH) { // wake the filler thread if there's room in the buffer m_writer.notify_one(); } if (bytesRead != length) XBMC->Log(LOG_DEBUG, "Read returns %d for %d request.", bytesRead, length); return bytesRead; } // // When seeking, we're going to have to flush the buffers already in transit (already requested) // and only make data available when we get the seeked-to block in. // int64_t TimeshiftBuffer::Seek(int64_t position, int whence) { bool sleep = false; XBMC->Log(LOG_DEBUG, "TimeshiftBuffer::Seek()"); int64_t highLimit = m_sd.lastKnownLength.load() - m_sd.iBytesPerSecond; int64_t lowLimit = m_sd.tsbStart.load() + (m_sd.iBytesPerSecond << 2); // Add Roughly 4 seconds to account for estimating the start. if (position > highLimit) { XBMC->Log(LOG_ERROR, "Seek requested to %lld, limiting to %lld\n", position, highLimit); position = highLimit; } else if (position < lowLimit) { XBMC->Log(LOG_ERROR, "Seek requested to %lld, limiting to %lld\n", position, lowLimit); position = lowLimit; } { std::unique_lock lock(m_mutex); // m_streamPositon is the offset in the stream that will be read next, // so if that matches the seek position, don't seek. XBMC->Log(LOG_DEBUG, "Seek: %d %d %llu %llu", SEEK_SET, whence, m_sd.streamPosition.load(), position); if ((whence == SEEK_SET) && (position == m_sd.streamPosition.load())) return position; m_seek.InitSeek(position, whence); if (m_seek.PreprocessSeek()) { internalRequestBlocks(); m_writer.notify_one(); // wake consumer. sleep = true; } } if (sleep) { std::unique_lock sLock(m_sLock); XBMC->Log(LOG_DEBUG, "Seek Waiting"); m_seeker.wait(sLock); } XBMC->Log(LOG_DEBUG, "Seek() returning %lli", position); return position; } PVR_ERROR TimeshiftBuffer::GetStreamTimes(PVR_STREAM_TIMES *stimes) { stimes->startTime = m_sd.sessionStartTime.load(); stimes->ptsStart = 0; stimes->ptsBegin = m_sd.ptsBegin.load(); stimes->ptsEnd = m_sd.ptsEnd.load(); // XBMC->Log(LOG_ERROR, "GetStreamTimes: %d, %lli, %lli, %lli", // stimes->startTime, stimes->ptsStart, stimes->ptsBegin, stimes->ptsEnd); return PVR_ERROR_NO_ERROR; } PVR_ERROR TimeshiftBuffer::GetStreamReadChunkSize(int* chunksize) { // Make this a tunable parameter? *chunksize = TimeshiftBuffer::INPUT_READ_LENGTH; return PVR_ERROR_NO_ERROR; } void TimeshiftBuffer::RequestBlocks() { std::unique_lock lock(m_mutex); internalRequestBlocks(); } void TimeshiftBuffer::internalRequestBlocks() { // XBMC->Log(LOG_DEBUG, "TimeshiftBuffer::RequestBlocks()"); m_seek.ProcessRequests(); // Handle outstanding seek request, if there is one. // send read request (using a basic sliding window protocol) for (int i = m_sd.currentWindowSize; i < WINDOW_SIZE; i++) { int64_t blockOffset = m_sd.requestBlock; char request[48]; memset(request, 0, sizeof(request)); snprintf(request, sizeof(request), "Range: bytes=%llu-%llu-%d", blockOffset, (blockOffset+INPUT_READ_LENGTH), m_sd.requestNumber); XBMC->Log(LOG_DEBUG, "sending request: %s\n", request); if (m_streamingclient->send(request, sizeof(request)) != sizeof(request)) { XBMC->Log(LOG_DEBUG, "NOT ALL BYTES SENT!"); } m_sd.requestBlock += INPUT_READ_LENGTH; m_sd.requestNumber++; m_sd.currentWindowSize++; } } uint32_t TimeshiftBuffer::WatchForBlock(byte *buffer, uint64_t *block) { // XBMC->Log(LOG_DEBUG, "TimeshiftBuffer::WatchForBlock()"); int64_t watchFor = -1; // Any (next) block uint32_t returnBytes = 0; int retries = WINDOW_SIZE + 1; std::unique_lock lock(m_mutex); if (m_seek.Active()) { if (m_seek.BlockRequested()) { // Can't watch for blocks that haven't been requested! watchFor = m_seek.SeekStreamOffset(); XBMC->Log(LOG_DEBUG, "%s:%d: watching for bloc %llu", __FUNCTION__, __LINE__, watchFor); } else { return returnBytes; } } //if (watchFor == -1) // XBMC->Log(LOG_DEBUG, "waiting for next block"); //else // XBMC->Log(LOG_DEBUG, "about to wait for block with offset: %llu\n", watchFor); while (retries) { if (!m_streamingclient->is_valid()) { XBMC->Log(LOG_DEBUG, "about to call receive(), socket is invalid\n"); return returnBytes; } if (m_streamingclient->read_ready()) { // read response header char response[128]; memset(response, 0, sizeof(response)); int responseByteCount = m_streamingclient->receive(response, sizeof(response), sizeof(response)); XBMC->Log(LOG_DEBUG, "%s:%d: responseByteCount: %d\n", __FUNCTION__, __LINE__, responseByteCount); if (responseByteCount > 0) { XBMC->Log(LOG_DEBUG, "%s:%d: got: %s\n", __FUNCTION__, __LINE__, response); } else if (responseByteCount < 0) { return 0; } #if defined(TARGET_WINDOWS) else if (responseByteCount < 0 && errno == WSAEWOULDBLOCK) #else else if (responseByteCount < 0 && errno == EAGAIN) #endif { #if defined(TARGET_WINDOWS) Sleep(50); #else usleep(50000); #endif XBMC->Log(LOG_DEBUG, "got: %d", errno); retries--; continue; } // parse response header long long payloadOffset; int payloadSize; long long fileSize; int dummy; sscanf(response, "%llu:%d %llu %d", &payloadOffset, &payloadSize, &fileSize, &dummy); XBMC->Log(LOG_DEBUG, "PKT_IN: %llu:%d %llu %d", payloadOffset, payloadSize, fileSize, dummy); if (m_sd.lastKnownLength.load() != fileSize) { m_sd.lastKnownLength.store(fileSize); } // read response payload int bytesRead = 0; do { bytesRead = m_streamingclient->receive((char *)buffer, INPUT_READ_LENGTH, payloadSize); #if defined(TARGET_WINDOWS) } while (bytesRead < 0 && errno == WSAEWOULDBLOCK); #else } while (bytesRead < 0 && errno == EAGAIN); #endif if ((watchFor == -1) || (payloadOffset == watchFor)) { if (m_circularBuffer.BytesAvailable() == 0) // Buffer empty! m_sd.streamPosition.store(payloadOffset); *block = payloadOffset; returnBytes = payloadSize; if (m_sd.currentWindowSize > 0) m_sd.currentWindowSize--; XBMC->Log(LOG_DEBUG, "Returning block %llu for buffering", payloadOffset); break; // We want to buffer this payload. } } } return returnBytes; } /* Write data to ring buffer from buffer specified in 'buf'. Amount read in is * specified by 'size'. */ bool TimeshiftBuffer::WriteData(const byte *buf, unsigned int size, uint64_t blockNum) { std::unique_lock lock(m_mutex); if (m_circularBuffer.WriteBytes(buf, size)) { m_sd.lastBlockBuffered = blockNum; return true; } XBMC->Log(LOG_ERROR, "%s:%d: Error writing block to circularBuffer!", __FUNCTION__, __LINE__); return false; } void TimeshiftBuffer::TSBTimerProc() { // ONLY use atomic types/ops inR session_data, don't mess with // the locks! while (m_active) { std::this_thread::sleep_for(std::chrono::seconds(1)); // Let's try 1 per second. // First, take a snapshot time_t now = time(NULL); time_t sessionStartTime = m_sd.sessionStartTime.load(); time_t tsbStartTime = m_sd.tsbStartTime.load(); int64_t lastKnownLength = m_sd.lastKnownLength.load(); uint64_t streamPosition = m_sd.streamPosition.load(); int64_t tsbStart = m_sd.tsbStart.load(); time_t iBytesPerSecond = m_sd.iBytesPerSecond; bool isPaused = m_sd.isPaused; time_t pauseStart = m_sd.pauseStart; time_t lastPauseAdjust = m_sd.lastPauseAdjust; if (tsbStartTime == 0) { tsbStartTime = sessionStartTime; } // Now perform the calculations time_t elapsed = now - tsbStartTime; //XBMC->Log(LOG_ERROR, "TSBTimerProc: time_diff: %d, tsbStartTime: %d", elapsed, tsbStartTime); if (elapsed > g_timeShiftBufferSeconds) { // Roll the tsb forward int tsbRoll = elapsed - g_timeShiftBufferSeconds; elapsed = g_timeShiftBufferSeconds; tsbStart += (tsbRoll * iBytesPerSecond); tsbStartTime += tsbRoll; // XBMC->Log(LOG_ERROR, "startTime: %d, start: %lli, isPaused: %d, tsbRoll: %d", tsbStartTime, tsbStart, isPaused, tsbRoll); } if (m_sd.isPaused) { if ((now > pauseStart) && (now > lastPauseAdjust)) { // If we're paused, we stop requesting/receiving buffers, so lastKnownLength doesn't get updated. Fudge it here. lastKnownLength += ((now - lastPauseAdjust) * iBytesPerSecond); lastPauseAdjust = now; } } int totalTime = now - sessionStartTime; // total seconds we've been tuned to this channel. iBytesPerSecond = totalTime ? (int )(lastKnownLength / totalTime) : 0; // lastKnownLength (total bytes buffered) / number_of_seconds buffered. // Write everything back m_sd.tsbStartTime.store(tsbStartTime); m_sd.tsbStart.store(tsbStart); m_sd.lastKnownLength.store(lastKnownLength); m_sd.iBytesPerSecond = iBytesPerSecond; m_sd.ptsBegin.store((tsbStartTime - sessionStartTime) * DVD_TIME_BASE); m_sd.ptsEnd.store((now - sessionStartTime) * DVD_TIME_BASE); m_sd.lastPauseAdjust = lastPauseAdjust; // XBMC->Log(LOG_ERROR, "tsb_start: %lli, end: %llu, B/sec: %d", // tsbStart, lastKnownLength, iBytesPerSecond); } } void TimeshiftBuffer::ConsumeInput() { XBMC->Log(LOG_DEBUG, "TimeshiftBuffer::ConsumeInput()"); byte *buffer = new byte[INPUT_READ_LENGTH]; while (m_active) { memset(buffer, 0, INPUT_READ_LENGTH); RequestBlocks(); uint32_t read; uint64_t blockNo; while ((read = WatchForBlock(buffer, &blockNo))) { // XBMC->Log(LOG_DEBUG, "Processing %d byte block", read); if (WriteData(buffer, read, blockNo)) { std::unique_lock lock(m_mutex); //XBMC->Log(LOG_DEBUG, "Data Buffered"); //XBMC->Log(LOG_DEBUG, "Notifying reader"); // Signal that we have data again if (m_seek.Active()) { if (m_seek.PostprocessSeek(blockNo)) { XBMC->Log(LOG_DEBUG, "Notify Seek"); m_seeker.notify_one(); } } m_reader.notify_one(); } else { XBMC->Log(LOG_DEBUG, "Error Buffering Data!!"); } std::this_thread::yield(); std::unique_lock lock(m_mutex); if (m_circularBuffer.BytesFree() < INPUT_READ_LENGTH) { m_writer.wait(lock, [this]() { return (!m_active || (m_circularBuffer.BytesFree() >= INPUT_READ_LENGTH)); }); } if (!m_active || ((blockNo + INPUT_READ_LENGTH) == m_sd.requestBlock)) break; } } XBMC->Log(LOG_DEBUG, "CONSUMER THREAD IS EXITING!!!"); delete[] buffer; } pvr.nextpvr-3.3.18-Leia/src/buffers/TimeshiftBuffer.h000066400000000000000000000104301360274650100224560ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2015 Sam Stenvall * * Block request and processing logic copied from liveshift.cpp and * RingBuffer.cpp which are Copyright (C) Team XBMC and distributed * under the same license. * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "Buffer.h" #include #include #include #include #include "../Socket.h" #include "CircularBuffer.h" #include "Seeker.h" #include "session.h" namespace timeshift { /** * Timeshift buffer which buffers into a file */ class TimeshiftBuffer : public Buffer { public: TimeshiftBuffer(); virtual ~TimeshiftBuffer(); virtual bool Open(const std::string inputUrl) override; virtual void Close() override; virtual int Read(byte *buffer, size_t length) override; virtual int64_t Seek(int64_t position, int whence) override; virtual bool CanPauseStream() const override { return m_CanPause; } virtual void PauseStream(bool bPause) override { if ((m_sd.isPaused = bPause)) m_sd.lastPauseAdjust = m_sd.pauseStart = time(nullptr); else m_sd.lastPauseAdjust = m_sd.pauseStart = 0; } virtual bool CanSeekStream() const override { return true; } virtual int64_t Position() const override { return m_sd.streamPosition.load(); // very approximate } virtual int64_t Length() const override { return m_sd.lastKnownLength.load(); } virtual bool IsTimeshifting() const override { if (m_active) return true; return false; } virtual PVR_ERROR GetStreamTimes(PVR_STREAM_TIMES *) override; virtual PVR_ERROR GetStreamReadChunkSize(int *chunksize) override; private: const static int INPUT_READ_LENGTH; const static int WINDOW_SIZE; const static int BUFFER_BLOCKS; NextPVR::Socket *m_streamingclient; /** * The method that runs on m_inputThread. It reads data from the input * handle and writes it to the output handle */ void ConsumeInput(); void TSBTimerProc(); bool WriteData(const byte *, unsigned int, uint64_t); /** * Closes any open file handles and resets all file positions */ void Reset(); /** * Sends requests for blocks to backend. */ void RequestBlocks(void); // Acquires lock, calls internalRequestBlocks(); void internalRequestBlocks(void); // Call when already holding lock. /** * Pull in incoming blocks. */ uint32_t WatchForBlock(byte *, uint64_t *); /** * The thread that reads from m_inputHandle and writes to the output * handles */ std::thread m_inputThread; /** * The thread that keeps track of the size of the current tsb, and * drags the starting time forward when slip seconds is exceeded */ std::thread m_tsbThread; /** * Protects m_output*Handle */ // mutable std::mutex m_mutex moved to base class /** * Protects seek completion */ mutable std::mutex m_sLock; /** * Signaled whenever new packets have been added to the buffer */ mutable std::condition_variable m_reader; /** * Signaled whenever data has read from the buffer */ mutable std::condition_variable m_writer; /** * Signaled whenever seek processing is complete. */ mutable std::condition_variable m_seeker; /** * The current write position in the buffer file */ Seeker m_seek; CircularBuffer m_circularBuffer; session_data_t m_sd; bool m_CanPause; }; } pvr.nextpvr-3.3.18-Leia/src/buffers/session.h000066400000000000000000000040201360274650100210510ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2017 Mike Burgett * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include #include namespace timeshift { typedef struct { /** * The offset into stream of the last block we successfully buffered. */ volatile int64_t lastBlockBuffered; /** * Sliding window variable, should be in range 0..WINDOW_SIZE */ int currentWindowSize; /** * Requests sent to back end this session. */ int requestNumber; /** * */ int inputBlockSize; volatile bool isPaused; volatile time_t pauseStart; volatile time_t lastPauseAdjust; /** * The next block to request. */ int64_t requestBlock; /** * The last known length of the timeshift file on backend */ volatile std::atomic lastKnownLength; volatile std::atomic ptsBegin; volatile std::atomic ptsEnd; volatile std::atomic tsbStart; volatile int iBytesPerSecond; volatile std::atomic sessionStartTime; volatile std::atomic tsbStartTime; volatile time_t tsbRollOff; volatile time_t lastBufferTime; /** * The next position a read will access. (in stream, not buffer) */ std::atomic streamPosition; } session_data_t; } pvr.nextpvr-3.3.18-Leia/src/client.cpp000066400000000000000000000530051360274650100175520ustar00rootroot00000000000000/* * Copyright (C) 2005-2011 Team XBMC * http://www.xbmc.org * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "client.h" #include "kodi/xbmc_pvr_dll.h" #include "pvrclient-nextpvr.h" #include "uri.h" using namespace std; using namespace ADDON; #define PVR_MIN_API_VERSION "1.2.0" /* User adjustable settings are saved here. * Default values are defined inside client.h * and exported to the other source files. */ std::string g_szHostname = DEFAULT_HOST; ///< The Host name or IP of the NextPVR server std::string g_szPin = DEFAULT_PIN; ///< The PIN for the NextPVR server int g_iPort = DEFAULT_PORT; ///< The web listening port (default: 8866) int16_t g_timeShiftBufferSeconds = 0; std::string g_host_mac = ""; eStreamingMethod g_livestreamingmethod = RealTime; eNowPlaying g_NowPlaying = NotPlaying; int g_wol_timeout; bool g_wol_enabled; bool g_KodiLook; /* Client member variables */ ADDON_STATUS m_CurStatus = ADDON_STATUS_UNKNOWN; cPVRClientNextPVR *g_client = NULL; std::string g_szUserPath = ""; std::string g_szClientPath = ""; bool g_bUseTimeshift; /* obsolete but settings.xml might have it */ CHelper_libXBMC_addon *XBMC = NULL; CHelper_libXBMC_pvr *PVR = NULL; bool g_bDownloadGuideArtwork = false; extern "C" { void ADDON_ReadSettings(void); /*********************************************************** * Standard AddOn related public library functions ***********************************************************/ //-- Create ------------------------------------------------------------------- // Called after loading of the dll, all steps to become Client functional // must be performed here. //----------------------------------------------------------------------------- ADDON_STATUS ADDON_Create(void* hdl, void* props) { if (!hdl || !props) return ADDON_STATUS_UNKNOWN; PVR_PROPERTIES* pvrprops = (PVR_PROPERTIES*)props; XBMC = new CHelper_libXBMC_addon; if (!XBMC->RegisterMe(hdl)) { SAFE_DELETE(XBMC); return ADDON_STATUS_PERMANENT_FAILURE; } PVR = new CHelper_libXBMC_pvr; if (!PVR->RegisterMe(hdl)) { SAFE_DELETE(PVR); SAFE_DELETE(XBMC); return ADDON_STATUS_PERMANENT_FAILURE; } XBMC->Log(LOG_INFO, "Creating NextPVR PVR-Client"); m_CurStatus = ADDON_STATUS_UNKNOWN; g_szUserPath = pvrprops->strUserPath; g_szClientPath = pvrprops->strClientPath; ADDON_ReadSettings(); /* Create connection to NextPVR XBMC TV client */ g_client = new cPVRClientNextPVR(); if (!g_client->Connect()) { SAFE_DELETE(g_client); SAFE_DELETE(PVR); SAFE_DELETE(XBMC); m_CurStatus = ADDON_STATUS_LOST_CONNECTION; return m_CurStatus; } m_CurStatus = ADDON_STATUS_OK; return m_CurStatus; } //-- Destroy ------------------------------------------------------------------ // Used during destruction of the client, all steps to do clean and safe Create // again must be done. //----------------------------------------------------------------------------- void ADDON_Destroy() { SAFE_DELETE(g_client); SAFE_DELETE(PVR); SAFE_DELETE(XBMC); m_CurStatus = ADDON_STATUS_UNKNOWN; } //-- GetStatus ---------------------------------------------------------------- // Report the current Add-On Status to XBMC // Note currently not called but needed to load //----------------------------------------------------------------------------- ADDON_STATUS ADDON_GetStatus() { /* check whether we're still connected */ if (m_CurStatus == ADDON_STATUS_OK && g_client && !g_client->IsUp()) m_CurStatus = ADDON_STATUS_LOST_CONNECTION; return m_CurStatus; } void ADDON_ReadSettings(void) { /* Read setting "host" from settings.xml */ char buffer[1024]; if (!XBMC) return; /* Connection settings */ /***********************/ if (XBMC->GetSetting("host", &buffer)) { g_szHostname = buffer; uri::decode(g_szHostname); } else { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'host' setting, falling back to '127.0.0.1' as default"); g_szHostname = DEFAULT_HOST; } /* Read setting "port" from settings.xml */ if (!XBMC->GetSetting("port", &g_iPort)) { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'port' setting, falling back to '8866' as default"); g_iPort = DEFAULT_PORT; } /* Read setting "pin" from settings.xml */ if (XBMC->GetSetting("pin", &buffer)) { g_szPin = buffer; } else { g_szPin = DEFAULT_PIN; } /* Read setting "livestreamingmethod" from settings.xml */ if (!XBMC->GetSetting("livestreamingmethod", &g_livestreamingmethod)) { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'livestreamingmethod' setting"); g_livestreamingmethod = DEFAULT_LIVE_STREAM; } if (!XBMC->GetSetting("usetimeshift", &g_bUseTimeshift)) { g_bUseTimeshift = false; } if (g_livestreamingmethod == DEFAULT_LIVE_STREAM) { /* Use obsolete setting "usetimeshift" from settings.xml when Real Time*/ if (!g_bUseTimeshift) { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'usetimeshift' setting, continue as default"); } else { g_livestreamingmethod = Timeshift; } } /* Read setting "guideartwork" from settings.xml */ if (!XBMC->GetSetting("guideartwork", &g_bDownloadGuideArtwork)) { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'guideartwork' setting, falling back to 'true' as default"); g_bDownloadGuideArtwork = DEFAULT_GUIDE_ARTWORK; } if (XBMC->GetSetting("host_mac", &buffer)) { g_host_mac = buffer; } if (!XBMC->GetSetting("wolenable", &g_wol_enabled)) { g_wol_enabled = false; } if (!XBMC->GetSetting("woltimeout", &g_wol_timeout)) { g_wol_timeout = 20; } if (!XBMC->GetSetting("kodilook", &g_KodiLook)) { g_KodiLook = false; } /* Log the current settings for debugging purposes */ XBMC->Log(LOG_DEBUG, "settings: host='%s', port=%i, mac=%4.4s...", g_szHostname.c_str(), g_iPort, g_host_mac.c_str()); } //-- SetSetting --------------------------------------------------------------- // Called everytime a setting is changed by the user and to inform AddOn about // new setting and to do required stuff to apply it. //----------------------------------------------------------------------------- ADDON_STATUS ADDON_SetSetting(const char *settingName, const void *settingValue) { string str = settingName; // SetSetting can occur when the addon is enabled, but TV support still // disabled. In that case the addon is not loaded, so we should not try // to change its settings. if (!XBMC) return ADDON_STATUS_OK; if (str == "host") { string tmp_sHostname = (const char*) settingValue; if (tmp_sHostname != g_szHostname) { XBMC->Log(LOG_INFO, "Changed Setting 'host' from %s to %s", g_szHostname.c_str(), tmp_sHostname.c_str()); g_szHostname = tmp_sHostname; return ADDON_STATUS_NEED_RESTART; } } else if (str == "port") { if (g_iPort != *(int*) settingValue) { XBMC->Log(LOG_INFO, "Changed Setting 'port' from %u to %u", g_iPort, *(int*) settingValue); g_iPort = *(int*) settingValue; return ADDON_STATUS_NEED_RESTART; } } else if (str == "pin") { string tmp_sPin = (const char*) settingValue; if (tmp_sPin != g_szPin) { XBMC->Log(LOG_INFO, "Changed Setting 'pin'"); g_szPin = tmp_sPin; return ADDON_STATUS_NEED_RESTART; } } else if (str == "usetimeshift") { if (g_bUseTimeshift != *(bool *)settingValue) { XBMC->Log(LOG_INFO, "Changed setting 'usetimeshift' from %u to %u", g_bUseTimeshift, *(bool*) settingValue); g_bUseTimeshift = *(bool*) settingValue; return ADDON_STATUS_NEED_RESTART; } } else if (str == "guideartwork") { if ( g_bDownloadGuideArtwork != *(bool*)settingValue) { XBMC->Log(LOG_INFO, "Changed setting 'guideartwork' from %u to %u", g_bDownloadGuideArtwork, *(bool*)settingValue); g_bDownloadGuideArtwork = *(bool*)settingValue; } } else if (str == "kodilook") { if ( g_KodiLook != *(bool*)settingValue) { XBMC->Log(LOG_INFO, "Changed setting 'kodilook' from %u to %u", g_KodiLook, *(bool*)settingValue); g_KodiLook = *(bool*)settingValue; if (g_client) PVR->TriggerRecordingUpdate(); } } else if (str == "livestreamingmethod") { eStreamingMethod setting_livestreamingmethod = *(eStreamingMethod*) settingValue; if (g_livestreamingmethod == ClientTimeshift) { if (setting_livestreamingmethod == RealTime) { g_livestreamingmethod = RealTime; return ADDON_STATUS_NEED_RESTART; } } else { if (g_livestreamingmethod != setting_livestreamingmethod) { g_livestreamingmethod = setting_livestreamingmethod; return ADDON_STATUS_NEED_RESTART; } } } else if (str == "host_mac") { if ( g_host_mac != (const char *)settingValue ) { XBMC->Log(LOG_INFO, "Changed setting 'host_mac' from %4.4s... to %4.4s...", g_host_mac.c_str(), (const char *)settingValue ); g_host_mac = (const char *) settingValue; return ADDON_STATUS_OK ; } } return ADDON_STATUS_OK; } /*********************************************************** * PVR Client AddOn specific public library functions ***********************************************************/ void OnSystemSleep() { if (g_client) g_client->OnSystemSleep(); } void OnSystemWake() { if (g_client) g_client->OnSystemWake(); } void OnPowerSavingActivated() { } void OnPowerSavingDeactivated() { } //-- GetAddonCapabilities ----------------------------------------------------- // Tell XBMC our requirements //----------------------------------------------------------------------------- PVR_ERROR GetAddonCapabilities(PVR_ADDON_CAPABILITIES *pCapabilities) { XBMC->Log(LOG_DEBUG, "->GetProperties()"); //pCapabilities->bSupportsTimeshift = true; //removed from Frodo API pCapabilities->bSupportsEPG = true; pCapabilities->bSupportsRecordings = true; pCapabilities->bSupportsRecordingsUndelete = false; pCapabilities->bSupportsTimers = true; pCapabilities->bSupportsTV = true; pCapabilities->bSupportsRadio = true; pCapabilities->bSupportsChannelGroups = true; pCapabilities->bHandlesInputStream = true; pCapabilities->bHandlesDemuxing = false; pCapabilities->bSupportsChannelScan = false; pCapabilities->bSupportsLastPlayedPosition = true; pCapabilities->bSupportsRecordingEdl = true; pCapabilities->bSupportsRecordingsRename = false; pCapabilities->bSupportsRecordingsLifetimeChange = false; pCapabilities->bSupportsDescrambleInfo = false; return PVR_ERROR_NO_ERROR; } PVR_ERROR GetStreamProperties(PVR_STREAM_PROPERTIES *pProperties) { return PVR_ERROR_NOT_IMPLEMENTED; } //-- GetBackendName ----------------------------------------------------------- // Return the Name of the Backend //----------------------------------------------------------------------------- const char * GetBackendName(void) { if (g_client) return g_client->GetBackendName(); else return ""; } //-- GetBackendVersion -------------------------------------------------------- // Return the Version of the Backend as String //----------------------------------------------------------------------------- const char * GetBackendVersion(void) { if (g_client) return g_client->GetBackendVersion(); else return ""; } //-- GetConnectionString ------------------------------------------------------ // Return a String with connection info, if available //----------------------------------------------------------------------------- const char * GetConnectionString(void) { if (g_client) return g_client->GetConnectionString(); else return "addon error!"; } //-- GetBackendHostname ------------------------------------------------------- // Return a String with the backend host name //----------------------------------------------------------------------------- const char * GetBackendHostname(void) { return g_szHostname.c_str(); } //-- GetDriveSpace ------------------------------------------------------------ // Return the Total and Free Drive space on the PVR Backend //----------------------------------------------------------------------------- PVR_ERROR GetDriveSpace(long long *iTotal, long long *iUsed) { if (!g_client) return PVR_ERROR_SERVER_ERROR; else return g_client->GetDriveSpace(iTotal, iUsed); } PVR_ERROR OpenDialogChannelScan() { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR CallMenuHook(const PVR_MENUHOOK &menuhook, const PVR_MENUHOOK_DATA &item) { return PVR_ERROR_NOT_IMPLEMENTED; } /*******************************************/ /** PVR EPG Functions **/ PVR_ERROR GetEPGForChannel(ADDON_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd) { if (!g_client) return PVR_ERROR_SERVER_ERROR; else return g_client->GetEpg(handle, channel, iStart, iEnd); } /*******************************************/ /** PVR Channel Functions **/ int GetChannelsAmount() { if (!g_client) return 0; else return g_client->GetNumChannels(); } PVR_ERROR GetChannels(ADDON_HANDLE handle, bool bRadio) { if (!g_client) return PVR_ERROR_SERVER_ERROR; else return g_client->GetChannels(handle, bRadio); } PVR_ERROR DeleteChannel(const PVR_CHANNEL &channel) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR RenameChannel(const PVR_CHANNEL &channel) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR OpenDialogChannelSettings(const PVR_CHANNEL &channelinfo) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR OpenDialogChannelAdd(const PVR_CHANNEL &channelinfo) { return PVR_ERROR_NOT_IMPLEMENTED; } /*******************************************/ /** PVR Channel group Functions **/ int GetChannelGroupsAmount(void) { if (!g_client) return 0; else return g_client->GetChannelGroupsAmount(); } PVR_ERROR GetChannelGroups(ADDON_HANDLE handle, bool bRadio) { if (!g_client) return PVR_ERROR_SERVER_ERROR; else return g_client->GetChannelGroups(handle, bRadio); } PVR_ERROR GetChannelGroupMembers(ADDON_HANDLE handle, const PVR_CHANNEL_GROUP &group) { if (!g_client) return PVR_ERROR_SERVER_ERROR; else return g_client->GetChannelGroupMembers(handle, group); } /*******************************************/ /** PVR Recording Functions **/ int GetRecordingsAmount(bool deleted) { if (!g_client) return 0; else return g_client->GetNumRecordings(); } PVR_ERROR GetRecordings(ADDON_HANDLE handle, bool deleted) { if (!g_client) return PVR_ERROR_SERVER_ERROR; else return g_client->GetRecordings(handle); } PVR_ERROR DeleteRecording(const PVR_RECORDING &recording) { if (!g_client) return PVR_ERROR_SERVER_ERROR; else return g_client->DeleteRecording(recording); } PVR_ERROR RenameRecording(const PVR_RECORDING &recording) { return PVR_ERROR_NOT_IMPLEMENTED; } /*******************************************/ /** PVR Timer Functions **/ PVR_ERROR GetTimerTypes(PVR_TIMER_TYPE types[], int *size) { if (g_client) return g_client->GetTimerTypes(types, size); return PVR_ERROR_SERVER_ERROR; } int GetTimersAmount(void) { if (!g_client) return 0; else return g_client->GetNumTimers(); } PVR_ERROR GetTimers(ADDON_HANDLE handle) { if (!g_client) return PVR_ERROR_SERVER_ERROR; else return g_client->GetTimers(handle); } PVR_ERROR AddTimer(const PVR_TIMER &timer) { if (!g_client) return PVR_ERROR_SERVER_ERROR; else return g_client->AddTimer(timer); } PVR_ERROR DeleteTimer(const PVR_TIMER &timer, bool bForceDelete) { if (!g_client) return PVR_ERROR_SERVER_ERROR; else return g_client->DeleteTimer(timer, bForceDelete); } PVR_ERROR UpdateTimer(const PVR_TIMER &timer) { if (!g_client) return PVR_ERROR_SERVER_ERROR; else return g_client->UpdateTimer(timer); } /*******************************************/ /** PVR Live Stream Functions **/ bool OpenLiveStream(const PVR_CHANNEL &channelinfo) { if (!g_client) return false; else return g_client->OpenLiveStream(channelinfo); } void CloseLiveStream() { if (g_client) g_client->CloseLiveStream(); } int ReadLiveStream(unsigned char *pBuffer, unsigned int iBufferSize) { if (!g_client) return 0; else return g_client->ReadLiveStream(pBuffer, iBufferSize); } long long SeekLiveStream(long long iPosition, int iWhence) { if (!g_client) return -1; else return g_client->SeekLiveStream(iPosition, iWhence); } long long LengthLiveStream(void) { if (!g_client) return -1; else return g_client->LengthLiveStream(); } PVR_ERROR SignalStatus(PVR_SIGNAL_STATUS &signalStatus) { if (!g_client) return PVR_ERROR_SERVER_ERROR; else return g_client->SignalStatus(signalStatus); } PVR_ERROR GetChannelStreamProperties(const PVR_CHANNEL* channel, PVR_NAMED_VALUE* properties, unsigned int* iPropertiesCount) { if (g_client) return g_client->GetChannelStreamProperties(*channel,properties,iPropertiesCount); return PVR_ERROR_NOT_IMPLEMENTED; } /*******************************************/ /** PVR Recording Stream Functions **/ bool OpenRecordedStream(const PVR_RECORDING &recording) { if (!g_client) return false; else return g_client->OpenRecordedStream(recording); } void CloseRecordedStream(void) { if (g_client) g_client->CloseRecordedStream(); } int ReadRecordedStream(unsigned char *pBuffer, unsigned int iBufferSize) { if (!g_client) return 0; else return g_client->ReadRecordedStream(pBuffer, iBufferSize); } long long SeekRecordedStream(long long iPosition, int iWhence) { if (!g_client) return -1; else return g_client->SeekRecordedStream(iPosition, iWhence); } long long LengthRecordedStream(void) { if (!g_client) return -1; else return g_client->LengthRecordedStream(); } bool CanPauseStream(void) { if (g_client) return g_client->CanPauseStream(); return false; } void PauseStream(bool bPaused) { if (g_client) g_client->PauseStream(bPaused); } bool CanSeekStream(void) { if (g_client) return g_client->CanPauseStream(); return false; } PVR_ERROR SetRecordingLastPlayedPosition(const PVR_RECORDING &recording, int lastplayedposition) { if (g_client) return g_client->SetRecordingLastPlayedPosition(recording, lastplayedposition); return PVR_ERROR_SERVER_ERROR; } int GetRecordingLastPlayedPosition(const PVR_RECORDING &recording) { if (g_client) return g_client->GetRecordingLastPlayedPosition(recording); return -1; } PVR_ERROR GetRecordingEdl(const PVR_RECORDING &recording, PVR_EDL_ENTRY entries[], int *size) { if (g_client) return g_client->GetRecordingEdl(recording, entries, size); return PVR_ERROR_SERVER_ERROR; } bool IsTimeshifting(void) { if (g_client) return g_client->IsTimeshifting(); return false; } bool IsRealTimeStream(void) { if (g_client) return g_client->IsRealTimeStream(); return false; } PVR_ERROR GetStreamTimes(PVR_STREAM_TIMES *stimes) { if (g_client) return g_client->GetStreamTimes(stimes); return PVR_ERROR_SERVER_ERROR; } PVR_ERROR GetStreamReadChunkSize(int* chunksize) { if (g_client) return g_client->GetStreamReadChunkSize(chunksize); return PVR_ERROR_SERVER_ERROR; } /** UNUSED API FUNCTIONS */ DemuxPacket* DemuxRead(void) { return NULL; } void DemuxAbort(void) {} void DemuxReset(void) {} void DemuxFlush(void) {} PVR_ERROR SetRecordingPlayCount(const PVR_RECORDING &recording, int count) { return PVR_ERROR_NOT_IMPLEMENTED; } bool SeekTime(double,bool,double*) { return false; } void SetSpeed(int) {}; PVR_ERROR UndeleteRecording(const PVR_RECORDING& recording) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR DeleteAllRecordingsFromTrash() { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR SetEPGTimeFrame(int) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR GetDescrambleInfo(PVR_DESCRAMBLE_INFO*) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR SetRecordingLifetime(const PVR_RECORDING*) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR GetRecordingStreamProperties(const PVR_RECORDING*, PVR_NAMED_VALUE*, unsigned int*) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR IsEPGTagRecordable(const EPG_TAG*, bool*) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR IsEPGTagPlayable(const EPG_TAG*, bool*) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR GetEPGTagStreamProperties(const EPG_TAG*, PVR_NAMED_VALUE*, unsigned int*) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR GetEPGTagEdl(const EPG_TAG* epgTag, PVR_EDL_ENTRY edl[], int *size) { return PVR_ERROR_NOT_IMPLEMENTED; } } //end extern "C" pvr.nextpvr-3.3.18-Leia/src/client.h000066400000000000000000000050651360274650100172220ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2011 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * http://www.gnu.org/copyleft/gpl.html * */ #ifndef CLIENT_H #define CLIENT_H #include "kodi/libXBMC_addon.h" #include "kodi/libXBMC_pvr.h" #include "kodi/libKODI_guilib.h" enum eStreamingMethod { Timeshift = 0, RollingFile = 1, RealTime = 2, ClientTimeshift = 3 }; enum eNowPlaying { NotPlaying = 0, TV = 1, Radio = 2, Recording = 3 }; #define DEFAULT_HOST "127.0.0.1" #define DEFAULT_PORT 8866 #define DEFAULT_PIN "0000" #define DEFAULT_RADIO true #define DEFAULT_USE_TIMESHIFT false #define DEFAULT_GUIDE_ARTWORK false #define DEFAULT_LIVE_STREAM RealTime extern std::string g_szUserPath; ///< The Path to the user directory inside user profile extern std::string g_szClientPath; ///< The Path where this driver is located /* Client Settings */ extern std::string g_szHostname; extern int g_iPort; extern std::string g_szPin; extern std::string g_host_mac; extern int g_wol_timeout; extern bool g_wol_enabled; extern bool g_bRadioEnabled; extern bool g_bUseTimeshift; extern bool g_KodiLook; extern int16_t g_timeShiftBufferSeconds; extern eStreamingMethod g_livestreamingmethod; extern eNowPlaying g_NowPlaying; extern ADDON::CHelper_libXBMC_addon *XBMC; extern CHelper_libXBMC_pvr *PVR; extern int g_iTVServerXBMCBuild; extern int g_ServerTimeOffset; typedef unsigned char byte; #define READ_NO_CACHE 0 /*! * @brief PVR macros for string exchange */ #define PVR_STRCPY(dest, source) do { strncpy(dest, source, sizeof(dest)-1); dest[sizeof(dest)-1] = '\0'; } while(0) #define PVR_STRCLR(dest) memset(dest, 0, sizeof(dest)) #endif /* CLIENT_H */ pvr.nextpvr-3.3.18-Leia/src/md5.cpp000066400000000000000000000231201360274650100167540ustar00rootroot00000000000000/* * Copyright (C) 2009 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "md5.h" #include typedef unsigned char md5byte; static void MD5Init(struct MD5Context *context); static void MD5Update(struct MD5Context *context, md5byte const *buf, unsigned len); static void MD5Final(md5byte digest[16], struct MD5Context *context); static void MD5Transform(uint32_t buf[4], uint32_t const in[16]); PVRXBMC::XBMC_MD5::XBMC_MD5(void) { MD5Init(&m_ctx); } PVRXBMC::XBMC_MD5::~XBMC_MD5(void) {} void PVRXBMC::XBMC_MD5::append(const void *inBuf, size_t inLen) { MD5Update(&m_ctx, (md5byte*)inBuf, inLen); } void PVRXBMC::XBMC_MD5::append(const std::string& str) { append((unsigned char*) str.c_str(), (unsigned int) str.length()); } void PVRXBMC::XBMC_MD5::getDigest(unsigned char digest[16]) { MD5Final(digest, &m_ctx); } void PVRXBMC::XBMC_MD5::getDigest(std::string& digest) { unsigned char szBuf[16] = {'\0'}; getDigest(szBuf); digest = StringUtils::Format("%02X%02X%02X%02X%02X%02X%02X%02X"\ "%02X%02X%02X%02X%02X%02X%02X%02X", szBuf[0], szBuf[1], szBuf[2], szBuf[3], szBuf[4], szBuf[5], szBuf[6], szBuf[7], szBuf[8], szBuf[9], szBuf[10], szBuf[11], szBuf[12], szBuf[13], szBuf[14], szBuf[15]); } std::string PVRXBMC::XBMC_MD5::GetMD5(const std::string &text) { if (text.empty()) return ""; XBMC_MD5 state; std::string digest; state.append(text); state.getDigest(digest); return digest; } /* * This code implements the MD5 message-digest algorithm. * The algorithm is due to Ron Rivest. This code was * written by Colin Plumb in 1993, no copyright is claimed. * This code is in the public domain; do with it what you wish. * * Equivalent code is available from RSA Data Security, Inc. * This code has been tested against that, and is equivalent, * except that you don't need to include two pages of legalese * with every copy. * * To compute the message digest of a chunk of bytes, declare an * MD5Context structure, pass it to MD5Init, call MD5Update as * needed on buffers full of bytes, and then call MD5Final, which * will fill a supplied 16-byte array with the digest. * * Changed so as no longer to depend on Colin Plumb's `usual.h' header * definitions; now uses stuff from dpkg's config.h. * - Ian Jackson . * Still in the public domain. */ #include "md5.h" #include /* for stupid systems */ #include /* for memcpy() */ #if defined(HAVE_CONFIG_H) && !defined(_WIN32) #include "../config.h" #endif #ifdef WORDS_BIGENDIAN void byteSwap(uint32_t *buf, unsigned words) { md5byte *p = (md5byte *)buf; do { *buf++ = (uint32_t)((unsigned)p[3] << 8 | p[2]) << 16 | ((unsigned)p[1] << 8 | p[0]); p += 4; } while (--words); } #else #define byteSwap(buf,words) #endif /* * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious * initialization constants. */ static void MD5Init(struct MD5Context *ctx) { ctx->buf[0] = 0x67452301; ctx->buf[1] = 0xefcdab89; ctx->buf[2] = 0x98badcfe; ctx->buf[3] = 0x10325476; ctx->bytes[0] = 0; ctx->bytes[1] = 0; } /* * Update context to reflect the concatenation of another buffer full * of bytes. */ static void MD5Update(struct MD5Context *ctx, md5byte const *buf, unsigned len) { uint32_t t; /* Update byte count */ t = ctx->bytes[0]; if ((ctx->bytes[0] = t + len) < t) ctx->bytes[1]++; /* Carry from low to high */ t = 64 - (t & 0x3f); /* Space available in ctx->in (at least 1) */ if (t > len) { memcpy((md5byte *)ctx->in + 64 - t, buf, len); return; } /* First chunk is an odd size */ memcpy((md5byte *)ctx->in + 64 - t, buf, t); byteSwap(ctx->in, 16); MD5Transform(ctx->buf, ctx->in); buf += t; len -= t; /* Process data in 64-byte chunks */ while (len >= 64) { memcpy(ctx->in, buf, 64); byteSwap(ctx->in, 16); MD5Transform(ctx->buf, ctx->in); buf += 64; len -= 64; } /* Handle any remaining bytes of data. */ memcpy(ctx->in, buf, len); } /* * Final wrapup - pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) */ static void MD5Final(md5byte digest[16], struct MD5Context *ctx) { int count = ctx->bytes[0] & 0x3f; /* Number of bytes in ctx->in */ md5byte *p = (md5byte *)ctx->in + count; /* Set the first char of padding to 0x80. There is always room. */ *p++ = 0x80; /* Bytes of padding needed to make 56 bytes (-8..55) */ count = 56 - 1 - count; if (count < 0) { /* Padding forces an extra block */ memset(p, 0, count + 8); byteSwap(ctx->in, 16); MD5Transform(ctx->buf, ctx->in); p = (md5byte *)ctx->in; count = 56; } memset(p, 0, count); byteSwap(ctx->in, 14); /* Append length in bits and transform */ ctx->in[14] = ctx->bytes[0] << 3; ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29; MD5Transform(ctx->buf, ctx->in); byteSwap(ctx->buf, 4); memcpy(digest, ctx->buf, 16); memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ } #ifndef ASM_MD5 /* The four core functions - F1 is optimized somewhat */ /* #define F1(x, y, z) (x & y | ~x & z) */ #define F1(x, y, z) (z ^ (x & (y ^ z))) #define F2(x, y, z) F1(z, x, y) #define F3(x, y, z) (x ^ y ^ z) #define F4(x, y, z) (y ^ (x | ~z)) /* This is the central step in the MD5 algorithm. */ #define MD5STEP(f,w,x,y,z,in,s) \ (w += f(x,y,z) + in, w = (w<>(32-s)) + x) /* * The core of the MD5 algorithm, this alters an existing MD5 hash to * reflect the addition of 16 longwords of new data. MD5Update blocks * the data and converts bytes into longwords for this routine. */ static void MD5Transform(uint32_t buf[4], uint32_t const in[16]) { register uint32_t a, b, c, d; a = buf[0]; b = buf[1]; c = buf[2]; d = buf[3]; MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); buf[0] += a; buf[1] += b; buf[2] += c; buf[3] += d; } #endif pvr.nextpvr-3.3.18-Leia/src/md5.h000066400000000000000000000026661360274650100164350ustar00rootroot00000000000000/* * Copyright (C) 2009 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * http://www.gnu.org/copyleft/gpl.html * */ #ifndef _MD5_H_ #define _MD5_H_ 1 #include struct MD5Context { uint32_t buf[4]; uint32_t bytes[2]; uint32_t in[16]; }; namespace PVRXBMC { class XBMC_MD5 { public: XBMC_MD5(void); ~XBMC_MD5(void); void append(const void *inBuf, size_t inLen); void append(const std::string& str); void getDigest(unsigned char digest[16]); void getDigest(std::string& digest); /*! \brief Get the MD5 digest of the given text \param text text to compute the MD5 for \return MD5 digest */ static std::string GetMD5(const std::string &text); private: MD5Context m_ctx; }; } #endif pvr.nextpvr-3.3.18-Leia/src/os-dependent.h000066400000000000000000000023271360274650100203270ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2011 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #if defined(TARGET_WINDOWS) #define WIN32_LEAN_AND_MEAN // Enable LEAN_AND_MEAN support #define NOMINMAX // don't define min() and max() to prevent a clash with std::min() and std::max #endif #include "p8-platform/os.h" #if defined(TARGET_WINDOWS) # include "windows/os_windows.h" #else # include "posix/os_posix.h" #endif #if defined(TARGET_DARWIN) # ifndef PTHREAD_MUTEX_RECURSIVE_NP # define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE # endif #endif pvr.nextpvr-3.3.18-Leia/src/pvrclient-nextpvr.cpp000066400000000000000000002446721360274650100220220ustar00rootroot00000000000000/* * Copyright (C) 2005-2011 Team XBMC * http://www.xbmc.org * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include #include #include #include #include #include #include "kodi/util/XMLUtils.h" #include "client.h" #include "pvrclient-nextpvr.h" #include "BackendRequest.h" #include "md5.h" #if defined(TARGET_WINDOWS) #define atoll(S) _atoi64(S) #else #define MAXINT64 ULONG_MAX #endif #include using namespace std; using namespace ADDON; extern "C" { ADDON_STATUS ADDON_SetSetting(const char *settingName, const void *settingValue); } /* Globals */ int g_iNextPVRXBMCBuild = 0; extern bool g_bDownloadGuideArtwork; int g_ServerTimeOffset = 0; /* PVR client version (don't forget to update also the addon.xml and the Changelog.txt files) */ #define PVRCLIENT_NEXTPVR_VERSION_STRING "1.0.0.0" #define NEXTPVRC_MIN_VERSION_STRING "3.6.0" #define DEBUGGING_XML 0 #if DEBUGGING_XML void dump_to_log( TiXmlNode* pParent, unsigned int indent); #else #define dump_to_log(x, y) #endif #define DEBUGGING_API 0 #if DEBUGGING_API #define LOG_API_CALL(f) XBMC->Log(LOG_INFO, "%s: called!", f) #define LOG_API_IRET(f,i) XBMC->Log(LOG_INFO, "%s: returns %d", f, i) #else #define LOG_API_CALL(f) #define LOG_API_IRET(f,i) #endif const char SAFE[256] = { /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ /* 0 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 1 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 2 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 3 */ 1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0, /* 4 */ 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, /* 5 */ 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, /* 6 */ 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, /* 7 */ 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, /* 8 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 9 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* A */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* B */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* C */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* D */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* E */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* F */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }; std::string UriEncode(const std::string sSrc) { const char DEC2HEX[16 + 1] = "0123456789ABCDEF"; const unsigned char * pSrc = (const unsigned char *)sSrc.c_str(); const int SRC_LEN = sSrc.length(); unsigned char * const pStart = new unsigned char[SRC_LEN * 3]; unsigned char * pEnd = pStart; const unsigned char * const SRC_END = pSrc + SRC_LEN; for (; pSrc < SRC_END; ++pSrc) { if (SAFE[*pSrc]) { *pEnd++ = *pSrc; } else { // escape this char *pEnd++ = '%'; *pEnd++ = DEC2HEX[*pSrc >> 4]; *pEnd++ = DEC2HEX[*pSrc & 0x0F]; } } std::string sResult((char *)pStart, (char *)pEnd); delete [] pStart; return sResult; } /************************************************************/ /** Class interface */ cPVRClientNextPVR::cPVRClientNextPVR() { m_iCurrentChannel = -1; m_tcpclient = new NextPVR::Socket(NextPVR::af_inet, NextPVR::pf_inet, NextPVR::sock_stream, NextPVR::tcp); m_streamingclient = new NextPVR::Socket(NextPVR::af_inet, NextPVR::pf_inet, NextPVR::sock_stream, NextPVR::tcp); m_bConnected = false; NextPVR::m_backEnd = new NextPVR::Request(); m_iChannelCount = 0; m_currentRecordingLength = 0; m_supportsLiveTimeshift = false; m_currentLiveLength = 0; m_currentLivePosition = 0; m_defaultLimit = NEXTPVR_LIMIT_ASMANY; m_defaultShowType = NEXTPVR_SHOWTYPE_ANY; m_lastRecordingUpdateTime = MAXINT64; // time of last recording check - force forever m_timeshiftBuffer = new timeshift::DummyBuffer(); m_recordingBuffer = new timeshift::RecordingBuffer(); m_realTimeBuffer = new timeshift::DummyBuffer(); m_livePlayer = nullptr; CreateThread(); } cPVRClientNextPVR::~cPVRClientNextPVR() { StopThread(); XBMC->Log(LOG_DEBUG, "->~cPVRClientNextPVR()"); if (m_bConnected) Disconnect(); SAFE_DELETE(m_tcpclient); } std::vector cPVRClientNextPVR::split(const std::string& s, const std::string& delim, const bool keep_empty) { std::vector result; if (delim.empty()) { result.push_back(s); return result; } std::string::const_iterator substart = s.begin(), subend; while (true) { subend = search(substart, s.end(), delim.begin(), delim.end()); std::string temp(substart, subend); if (keep_empty || !temp.empty()) { result.push_back(temp); } if (subend == s.end()) { break; } substart = subend + delim.size(); } return result; } bool cPVRClientNextPVR::Connect() { string result; m_bConnected = false; // initiate session std::string response; SendWakeOnLan(); if (DoRequest("/service?method=session.initiate&ver=1.0&device=xbmc", response) == HTTP_OK) { TiXmlDocument doc; if (doc.Parse(response.c_str()) != NULL) { TiXmlElement* saltNode = doc.RootElement()->FirstChildElement("salt"); TiXmlElement* sidNode = doc.RootElement()->FirstChildElement("sid"); if (saltNode != NULL && sidNode != NULL) { // extract and store sid PVR_STRCLR(m_sid); PVR_STRCPY(m_sid, sidNode->FirstChild()->Value()); NextPVR::m_backEnd->setSID(m_sid); // extract salt char salt[64]; PVR_STRCLR(salt); PVR_STRCPY(salt, saltNode->FirstChild()->Value()); // a bit of debug XBMC->Log(LOG_DEBUG, "session.initiate returns: sid=%s salt=%s", m_sid, salt); std::string pinMD5 = PVRXBMC::XBMC_MD5::GetMD5(g_szPin); StringUtils::ToLower(pinMD5); // calculate combined MD5 std::string combinedMD5; combinedMD5.append(":"); combinedMD5.append(pinMD5); combinedMD5.append(":"); combinedMD5.append(salt); // get digest std::string md5 = PVRXBMC::XBMC_MD5::GetMD5(combinedMD5); // login session std::string loginResponse; char request[512]; sprintf(request, "/service?method=session.login&sid=%s&md5=%s", m_sid, md5.c_str()); if (DoRequest(request, loginResponse) == HTTP_OK) { if (strstr(loginResponse.c_str(), "")) { // check server version std::string settings; if (DoRequest("/service?method=setting.list", settings) == HTTP_OK) { // if it's a NextPVR server, check the verions. WinTV Extend servers work a slightly different way. TiXmlDocument settingsDoc; int version = 0; if (settingsDoc.Parse(settings.c_str()) != NULL) { //XBMC->Log(LOG_NOTICE, "Settings:\n"); //dump_to_log(&settingsDoc, 0); TiXmlElement* versionNode = settingsDoc.RootElement()->FirstChildElement("NextPVRVersion"); if (versionNode == NULL) { // WinTV Extend server } else { // NextPVR server version = atoi(versionNode->FirstChild()->Value()); XBMC->Log(LOG_DEBUG, "NextPVR version: %d", version); // is the server new enough if (version < 30600) { XBMC->Log(LOG_ERROR, "Your NextPVR version '%d' is too old. Please upgrade to '%s' or higher!", version, NEXTPVRC_MIN_VERSION_STRING); XBMC->QueueNotification(QUEUE_ERROR, XBMC->GetLocalizedString(30050)); XBMC->QueueNotification(QUEUE_ERROR, XBMC->GetLocalizedString(30051), NEXTPVRC_MIN_VERSION_STRING); return false; } else if (version >= 50000) { if ( g_livestreamingmethod != RealTime) { if (version >= 50001) { g_livestreamingmethod = ClientTimeshift; } else { g_livestreamingmethod = RealTime; XBMC->QueueNotification(QUEUE_ERROR,"NextPVR v5.0.1+ required for timeshift"); } } } } TiXmlElement* liveTimeshiftNode = settingsDoc.RootElement()->FirstChildElement("LiveTimeshift"); if ( (liveTimeshiftNode != NULL && g_livestreamingmethod != RealTime) || g_livestreamingmethod == ClientTimeshift) { m_supportsLiveTimeshift = true; g_timeShiftBufferSeconds = atoi(settingsDoc.RootElement()->FirstChildElement("SlipSeconds")->FirstChild()->Value()); XBMC->Log(LOG_NOTICE, "time shift buffer in seconds == %d\n", g_timeShiftBufferSeconds); if (g_livestreamingmethod == RollingFile && version < 40204 ) { XBMC->QueueNotification(QUEUE_ERROR,"v4.2.4 required for Extended mode"); Sleep(2000); g_livestreamingmethod = Timeshift; } if (g_livestreamingmethod != Timeshift ) { delete m_timeshiftBuffer; if (version < 50000 ) { XBMC->Log(LOG_NOTICE, "Rolling File Based Buffering"); m_timeshiftBuffer = new timeshift::RollingFile(); } else { XBMC->Log(LOG_NOTICE, "Client Timeshift Based Buffering"); m_timeshiftBuffer = new timeshift::ClientTimeShift(); } } else { XBMC->Log(LOG_NOTICE, "Timeshift is true!!"); delete m_timeshiftBuffer; m_timeshiftBuffer = new timeshift::TimeshiftBuffer(); } } // load padding defaults m_iDefaultPrePadding = 1; m_iDefaultPostPadding = 2; if ( settingsDoc.RootElement()->FirstChildElement("PrePadding") != NULL && settingsDoc.RootElement()->FirstChildElement("PrePadding")->FirstChild() != NULL) { m_iDefaultPrePadding = atoi(settingsDoc.RootElement()->FirstChildElement("PrePadding")->FirstChild()->Value()); m_iDefaultPostPadding = atoi( settingsDoc.RootElement()->FirstChildElement("PostPadding")->FirstChild()->Value()); } if ( settingsDoc.RootElement()->FirstChildElement("RecordingDirectories") != NULL && settingsDoc.RootElement()->FirstChildElement("RecordingDirectories")->FirstChild() != NULL) { vector directories = split(settingsDoc.RootElement()->FirstChildElement("RecordingDirectories")->FirstChild()->Value(), ",", false); for (size_t i = 0; i < directories.size(); i++) { m_recordingDirectories.push_back(directories[i]); } } if ( settingsDoc.RootElement()->FirstChildElement("TimeEpoch") != NULL) { g_ServerTimeOffset = time(nullptr) - atoi(settingsDoc.RootElement()->FirstChildElement("TimeEpoch")->FirstChild()->Value()); XBMC->Log(LOG_NOTICE, "Server time offset in seconds: %d", g_ServerTimeOffset); } if ( settingsDoc.RootElement()->FirstChildElement("ServerMAC") != NULL && settingsDoc.RootElement()->FirstChildElement("ServerMAC")->FirstChild() != NULL) { char rawMAC[13]; PVR_STRCPY(rawMAC,settingsDoc.RootElement()->FirstChildElement("ServerMAC")->FirstChild()->Value()); if (strlen(rawMAC)==12) { char mac[18]; sprintf(mac,"%2.2s:%2.2s:%2.2s:%2.2s:%2.2s:%2.2s",rawMAC,&rawMAC[2],&rawMAC[4],&rawMAC[6],&rawMAC[8],&rawMAC[10]); XBMC->Log(LOG_DEBUG, "Server MAC addres %4.4s...",mac); std::string smac = mac; if (g_host_mac != smac) { SaveSettings("host_mac", smac); } } } } } m_bConnected = true; LoadLiveStreams(); XBMC->Log(LOG_DEBUG, "session.login successful"); return true; } } else { XBMC->Log(LOG_DEBUG, "session.login failed"); PVR->ConnectionStateChange( "Access denied", PVR_CONNECTION_STATE_ACCESS_DENIED, XBMC->GetLocalizedString(30052)); m_bConnected = false; } } } } else { PVR->ConnectionStateChange( "Could not connect to server", PVR_CONNECTION_STATE_SERVER_UNREACHABLE ,NULL); } return false; } void cPVRClientNextPVR::Disconnect() { string result; m_bConnected = false; } /* IsUp() * \brief Check if we have a valid session to nextpvr * \return True when a session is active */ bool cPVRClientNextPVR::IsUp() { LOG_API_CALL(__FUNCTION__); // check time since last time Recordings were updated, update if it has been awhile if (m_bConnected == true && g_NowPlaying == NotPlaying && m_lastRecordingUpdateTime != MAXINT64 && time(0) > (m_lastRecordingUpdateTime + 60 )) { TiXmlDocument doc; char request[512]; sprintf(request, "/service?method=recording.lastupdated"); std::string response; if (DoRequest(request, response) == HTTP_OK) { if (doc.Parse(response.c_str()) != NULL) { TiXmlElement* last_update = doc.RootElement()->FirstChildElement("last_update"); if (last_update != NULL) { int64_t update_time = atoll(last_update->GetText()); if (update_time > m_lastRecordingUpdateTime) { m_lastRecordingUpdateTime = MAXINT64; PVR->TriggerRecordingUpdate(); PVR->TriggerTimerUpdate(); } else { m_lastRecordingUpdateTime = time(0); } } else { m_lastRecordingUpdateTime = MAXINT64; } } } else { m_lastRecordingUpdateTime = time(0); } } return m_bConnected; } void *cPVRClientNextPVR::Process(void) { LOG_API_CALL(__FUNCTION__); while (!IsStopped()) { IsUp(); Sleep(2500); } return NULL; } void cPVRClientNextPVR::OnSystemSleep() { m_lastRecordingUpdateTime = MAXINT64; Disconnect(); PVR->ConnectionStateChange( "sleeping", PVR_CONNECTION_STATE_DISCONNECTED, NULL); Sleep(1000); } void cPVRClientNextPVR::OnSystemWake() { PVR->ConnectionStateChange( "waking", PVR_CONNECTION_STATE_CONNECTING, NULL); int count = 0; for (;count < 5; count++) { if (Connect()) { PVR->ConnectionStateChange( "connected", PVR_CONNECTION_STATE_CONNECTED, NULL); break; } Sleep(500); } XBMC->Log(LOG_INFO, "On NextPVR Wake %d %d",m_bConnected, count); } void cPVRClientNextPVR::SendWakeOnLan() { if (g_wol_enabled == true ) { if (g_szHostname == "127.0.0.1" || g_szHostname == "localhost" || g_szHostname == "::1") { g_wol_enabled = false; return; } int count = 0; for (;count < g_wol_timeout; count++) { if (NextPVR::m_backEnd->PingBackend()) { return; } XBMC->WakeOnLan(g_host_mac.c_str()); XBMC->Log(LOG_DEBUG, "WOL sent %d",count); Sleep(1000); } } } /************************************************************/ /** General handling */ // Used among others for the server name string in the "Recordings" view const char* cPVRClientNextPVR::GetBackendName(void) { LOG_API_CALL(__FUNCTION__); if (!m_bConnected) { return g_szHostname.c_str(); } XBMC->Log(LOG_DEBUG, "->GetBackendName()"); if (m_BackendName.length() == 0) { m_BackendName = "NextPVR ("; m_BackendName += g_szHostname.c_str(); m_BackendName += ")"; } return m_BackendName.c_str(); } const char* cPVRClientNextPVR::GetBackendVersion(void) { LOG_API_CALL(__FUNCTION__); if (!m_bConnected) return "0.0"; return "1.0"; } const char* cPVRClientNextPVR::GetConnectionString(void) { static std::string strConnectionString = "connected"; return strConnectionString.c_str(); } PVR_ERROR cPVRClientNextPVR::GetDriveSpace(long long *iTotal, long long *iUsed) { LOG_API_CALL(__FUNCTION__); string result; vector fields; *iTotal = 0; *iUsed = 0; if (!m_bConnected) return PVR_ERROR_SERVER_ERROR; return PVR_ERROR_NO_ERROR; } /************************************************************/ /** EPG handling */ PVR_ERROR cPVRClientNextPVR::GetEpg(ADDON_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd) { EPG_TAG broadcast; std::string response; char request[512]; LOG_API_CALL(__FUNCTION__); if ( iEnd < (time(nullptr) - 24 * 3600)) { XBMC->Log(LOG_DEBUG, "Skipping expired EPG data %d %ld %lld",channel.iUniqueId,iStart, iEnd); return PVR_ERROR_INVALID_PARAMETERS; } sprintf(request, "/service?method=channel.listings&channel_id=%d&start=%d&end=%d", channel.iUniqueId, (int)iStart, (int)iEnd); if (DoRequest(request, response) == HTTP_OK) { TiXmlDocument doc; if (doc.Parse(response.c_str()) != NULL) { TiXmlElement* listingsNode = doc.RootElement()->FirstChildElement("listings"); TiXmlElement* pListingNode; for( pListingNode = listingsNode->FirstChildElement("l"); pListingNode; pListingNode=pListingNode->NextSiblingElement()) { memset(&broadcast, 0, sizeof(EPG_TAG)); string title; string description; string subtitle; title = pListingNode->FirstChildElement("name")->FirstChild()->Value(); if (pListingNode->FirstChildElement("description") != NULL && pListingNode->FirstChildElement("description")->FirstChild() != NULL) { description = pListingNode->FirstChildElement("description")->FirstChild()->Value(); } else { description = ""; } if (pListingNode->FirstChildElement("subtitle") != NULL && pListingNode->FirstChildElement("subtitle")->FirstChild() != NULL) { subtitle = pListingNode->FirstChildElement("subtitle")->FirstChild()->Value(); if (description == subtitle + ":") { description = ""; } else if (StringUtils::StartsWith(description,subtitle + ": ")) { description = description.substr(subtitle.length()+2); } } else { subtitle = ""; } if (pListingNode->FirstChildElement("year") != NULL && pListingNode->FirstChildElement("year")->FirstChild() != NULL) { broadcast.iYear = atoi(pListingNode->FirstChildElement("year")->FirstChild()->Value()); title += " (" + std::to_string(broadcast.iYear) + ")"; } else { broadcast.iYear = 0; } char start[32]; strncpy(start, pListingNode->FirstChildElement("start")->FirstChild()->Value(), sizeof start); start[10] = '\0'; char end[32]; strncpy(end, pListingNode->FirstChildElement("end")->FirstChild()->Value(), sizeof end); end[10] = '\0'; broadcast.iUniqueBroadcastId = atoi(pListingNode->FirstChildElement("id")->FirstChild()->Value()); broadcast.strTitle = title.c_str(); broadcast.strEpisodeName = subtitle.c_str(); broadcast.iUniqueChannelId = channel.iUniqueId; broadcast.startTime = atol(start); broadcast.endTime = atol(end); broadcast.strPlotOutline = NULL; //unused broadcast.strPlot = description.c_str(); broadcast.strOriginalTitle = NULL; // unused broadcast.strCast = NULL; // unused broadcast.strDirector = NULL; // unused broadcast.strWriter = NULL; // unused broadcast.strIMDBNumber = NULL; // unused // artwork URL char artworkPath[128]; artworkPath[0] = '\0'; if (g_bDownloadGuideArtwork) { snprintf(artworkPath, sizeof(artworkPath), "http://%s:%d/service?method=channel.show.artwork&sid=%s&event_id=%d", g_szHostname.c_str(), g_iPort, m_sid, broadcast.iUniqueBroadcastId); broadcast.strIconPath = artworkPath; } char genre[128]; genre[0] = '\0'; if (pListingNode->FirstChildElement("genre") != NULL && pListingNode->FirstChildElement("genre")->FirstChild() != NULL) { broadcast.iGenreType = EPG_GENRE_USE_STRING; PVR_STRCPY(genre, pListingNode->FirstChildElement("genre")->FirstChild()->Value()); broadcast.strGenreDescription = genre; } else { // genre type if (pListingNode->FirstChildElement("genre_type") != NULL && pListingNode->FirstChildElement("genre_type")->FirstChild() != NULL) { broadcast.iGenreType = atoi(pListingNode->FirstChildElement("genre_type")->FirstChild()->Value()); } // genre subtype if (pListingNode->FirstChildElement("genre_subtype") != NULL && pListingNode->FirstChildElement("genre_subtype")->FirstChild() != NULL) { broadcast.iGenreSubType = atoi(pListingNode->FirstChildElement("genre_subtype")->FirstChild()->Value()); } } if (pListingNode->FirstChildElement("season") != NULL && pListingNode->FirstChildElement("season")->FirstChild() != NULL) { broadcast.iSeriesNumber = atoi(pListingNode->FirstChildElement("season")->FirstChild()->Value()); } else { broadcast.iSeriesNumber = 0; } if (pListingNode->FirstChildElement("episode") != NULL && pListingNode->FirstChildElement("episode")->FirstChild() != NULL) { broadcast.iEpisodeNumber = atoi(pListingNode->FirstChildElement("episode")->FirstChild()->Value()); } else { broadcast.iEpisodeNumber = 0; } broadcast.firstAired = 0; // unused broadcast.iParentalRating = 0; // unused broadcast.iStarRating = 0; // unused broadcast.bNotify = false; broadcast.iEpisodePartNumber = 0; // unused PVR->TransferEpgEntry(handle, &broadcast); } } } return PVR_ERROR_NO_ERROR; } /************************************************************/ /** Channel handling */ int cPVRClientNextPVR::GetNumChannels(void) { LOG_API_CALL(__FUNCTION__); if (m_iChannelCount != -1) return m_iChannelCount; // need something more optimal, but this will do for now... std::string response; if (DoRequest("/service?method=channel.list", response) == HTTP_OK) { TiXmlDocument doc; if (doc.Parse(response.c_str()) != NULL) { m_iChannelCount = 0; TiXmlElement* channelsNode = doc.RootElement()->FirstChildElement("channels"); TiXmlElement* pChannelNode; for( pChannelNode = channelsNode->FirstChildElement("channel"); pChannelNode; pChannelNode=pChannelNode->NextSiblingElement()) { m_iChannelCount++; } } } return m_iChannelCount; } std::string cPVRClientNextPVR::GetChannelIcon(int channelID) { LOG_API_CALL(__FUNCTION__); std::string iconFilename = GetChannelIconFileName(channelID); // do we already have the icon file? if (XBMC->FileExists(iconFilename.c_str(), false)) { return iconFilename; } char strURL[256]; sprintf(strURL, "/service?method=channel.icon&channel_id=%d", channelID); if (NextPVR::m_backEnd->FileCopy(strURL, iconFilename) == HTTP_OK) { return iconFilename; } return ""; } std::string cPVRClientNextPVR::GetChannelIconFileName(int channelID) { char filename[64]; snprintf(filename, sizeof(filename), "nextpvr-ch%d.png", channelID); std::string iconFilename("special://userdata/addon_data/pvr.nextpvr/"); return iconFilename + filename; } void cPVRClientNextPVR::LoadLiveStreams() { char strURL[256]; sprintf(strURL, "/public/LiveStreams.xml"); m_liveStreams.clear(); if (NextPVR::m_backEnd->FileCopy(strURL, "special://userdata/addon_data/pvr.nextpvr/LiveStreams.xml") == HTTP_OK) { TiXmlDocument doc; char *liveStreams = XBMC->TranslateSpecialProtocol("special://userdata/addon_data/pvr.nextpvr/LiveStreams.xml"); XBMC->Log(LOG_DEBUG, "Loading LiveStreams.xml %s", liveStreams); if (doc.LoadFile(liveStreams)) { TiXmlElement* streamsNode = doc.FirstChildElement("streams"); if (streamsNode) { TiXmlElement* streamNode; for( streamNode = streamsNode->FirstChildElement("stream"); streamNode; streamNode=streamNode->NextSiblingElement()) { std::string key_value; if ( streamNode->QueryStringAttribute("id", &key_value)==TIXML_SUCCESS) { try { if (streamNode->FirstChild()) { int channelID = std::stoi(key_value); XBMC->Log(LOG_DEBUG, "%d %s",channelID, streamNode->FirstChild()->Value()); m_liveStreams[channelID] = streamNode->FirstChild()->Value(); } } catch (...) { XBMC->Log(LOG_DEBUG, "%s:%d",__FUNCTION__,__LINE__); } } } } } } } PVR_ERROR cPVRClientNextPVR::GetChannels(ADDON_HANDLE handle, bool bRadio) { PVR_CHANNEL tag; std::string stream; LOG_API_CALL(__FUNCTION__); m_channelTypes.clear(); int channelCount = 0; std::string response; if (DoRequest("/service?method=channel.list", response) == HTTP_OK) { TiXmlDocument doc; if (doc.Parse(response.c_str()) != NULL) { //XBMC->Log(LOG_NOTICE, "Channels:\n"); //dump_to_log(&doc, 0); channelCount = 0; TiXmlElement* channelsNode = doc.RootElement()->FirstChildElement("channels"); TiXmlElement* pChannelNode; for( pChannelNode = channelsNode->FirstChildElement("channel"); pChannelNode; pChannelNode=pChannelNode->NextSiblingElement()) { memset(&tag, 0, sizeof(PVR_CHANNEL)); TiXmlElement* channelTypeNode = pChannelNode->FirstChildElement("type"); tag.iUniqueId = atoi(pChannelNode->FirstChildElement("id")->FirstChild()->Value()); if (strcmp(channelTypeNode->FirstChild()->Value(), "0xa") == 0) { tag.bIsRadio = true; PVR_STRCPY(tag.strInputFormat, "application/octet-stream"); } else { tag.bIsRadio = false; if (!IsChannelAPlugin(tag.iUniqueId)) PVR_STRCPY(tag.strInputFormat, "video/mp2t"); } if (bRadio != tag.bIsRadio) continue; tag.iChannelNumber = atoi(pChannelNode->FirstChildElement("number")->FirstChild()->Value()); // handle major.minor style subchannels if (pChannelNode->FirstChildElement("minor")) { tag.iSubChannelNumber = atoi(pChannelNode->FirstChildElement("minor")->FirstChild()->Value()); } PVR_STRCPY(tag.strChannelName, pChannelNode->FirstChildElement("name")->FirstChild()->Value()); // check if we need to download a channel icon if (pChannelNode->FirstChildElement("icon")) { std::string iconFile = GetChannelIcon(tag.iUniqueId); if (iconFile.length() > 0) { PVR_STRCPY(tag.strIconPath, iconFile.c_str()); } } if ( !m_channelTypes[tag.iUniqueId]) { m_channelTypes[tag.iUniqueId] = tag.bIsRadio; } // transfer channel to XBMC PVR->TransferChannelEntry(handle, &tag); channelCount++; } } m_iChannelCount = channelCount; } return PVR_ERROR_NO_ERROR; } /************************************************************/ /** Channel group handling **/ int cPVRClientNextPVR::GetChannelGroupsAmount(void) { LOG_API_CALL(__FUNCTION__); // Not directly possible at the moment XBMC->Log(LOG_DEBUG, "GetChannelGroupsAmount"); int groups = 0; std::string response; if (DoRequest("/service?method=channel.groups", response) == HTTP_OK) { TiXmlDocument doc; if (doc.Parse(response.c_str()) != NULL) { TiXmlElement* groupsNode = doc.RootElement()->FirstChildElement("groups"); TiXmlElement* pGroupNode; for( pGroupNode = groupsNode->FirstChildElement("group"); pGroupNode; pGroupNode=pGroupNode->NextSiblingElement()) { groups++; } } } return groups; } PVR_ERROR cPVRClientNextPVR::GetChannelGroups(ADDON_HANDLE handle, bool bRadio) { PVR_CHANNEL_GROUP tag; LOG_API_CALL(__FUNCTION__); // nextpvr doesn't have a separate concept of radio channel groups if (bRadio) return PVR_ERROR_NO_ERROR; // for tv, use the groups returned by nextpvr std::string response; if (DoRequest("/service?method=channel.groups", response) == HTTP_OK) { TiXmlDocument doc; if (doc.Parse(response.c_str()) != NULL) { TiXmlElement* groupsNode = doc.RootElement()->FirstChildElement("groups"); TiXmlElement* pGroupNode; for( pGroupNode = groupsNode->FirstChildElement("group"); pGroupNode; pGroupNode=pGroupNode->NextSiblingElement()) { memset(&tag, 0, sizeof(PVR_CHANNEL_GROUP)); tag.bIsRadio = false; tag.iPosition = 0; // groups default order, unused std::string group; if ( XMLUtils::GetString(pGroupNode,"name",group) ) { // tell XBMC about channel, ignoring "All Channels" since xbmc has an built in group with effectively the same function strcpy(tag.strGroupName,group.c_str()); if (strcmp(tag.strGroupName, "All Channels") != 0 && tag.strGroupName[0]!=0) { PVR->TransferChannelGroup(handle, &tag); } } } } else { XBMC->Log(LOG_DEBUG, "GetChannelGroupsAmount"); } } return PVR_ERROR_NO_ERROR; } PVR_ERROR cPVRClientNextPVR::GetChannelStreamProperties(const PVR_CHANNEL &channel, PVR_NAMED_VALUE *properties, unsigned int *iPropertiesCount) { if (IsChannelAPlugin(channel.iUniqueId)!= 0) { strncpy(properties[0].strName, PVR_STREAM_PROPERTY_STREAMURL, sizeof(properties[0].strName) - 1); strncpy(properties[0].strValue,m_liveStreams[channel.iUniqueId].c_str(), sizeof(properties[0].strValue) - 1); *iPropertiesCount = 1; return PVR_ERROR_NO_ERROR; } return PVR_ERROR_NOT_IMPLEMENTED; } bool cPVRClientNextPVR::IsChannelAPlugin(int uid) { if (m_liveStreams.count(uid)!= 0) if (StringUtils::StartsWith(m_liveStreams[uid],"plugin:")) return true; return false; } PVR_ERROR cPVRClientNextPVR::GetChannelGroupMembers(ADDON_HANDLE handle, const PVR_CHANNEL_GROUP &group) { std::string encodedGroupName = UriEncode(group.strGroupName); LOG_API_CALL(__FUNCTION__); char request[512]; sprintf(request, "/service?method=channel.list&group_id=%s", encodedGroupName.c_str()); std::string response; if (DoRequest(request, response) == HTTP_OK) { PVR_CHANNEL_GROUP_MEMBER tag; TiXmlDocument doc; if (doc.Parse(response.c_str()) != NULL) { TiXmlElement* channelsNode = doc.RootElement()->FirstChildElement("channels"); TiXmlElement* pChannelNode; for( pChannelNode = channelsNode->FirstChildElement("channel"); pChannelNode; pChannelNode=pChannelNode->NextSiblingElement()) { memset(&tag, 0, sizeof(PVR_CHANNEL_GROUP_MEMBER)); strncpy(tag.strGroupName, group.strGroupName, sizeof(tag.strGroupName)); tag.iChannelUniqueId = atoi(pChannelNode->FirstChildElement("id")->FirstChild()->Value()); tag.iChannelNumber = atoi(pChannelNode->FirstChildElement("number")->FirstChild()->Value()); PVR->TransferChannelGroupMember(handle, &tag); } } } return PVR_ERROR_NO_ERROR; } /************************************************************/ /** Record handling **/ int cPVRClientNextPVR::GetNumRecordings(void) { // need something more optimal, but this will do for now... // Return -1 on error. LOG_API_CALL(__FUNCTION__); if (m_iRecordingCount != 0) return m_iRecordingCount; std::string response; if (DoRequest("/service?method=recording.list&filter=ready", response) == HTTP_OK) { TiXmlDocument doc; if (doc.Parse(response.c_str()) != NULL) { TiXmlElement* recordingsNode = doc.RootElement()->FirstChildElement("recordings"); if (recordingsNode != NULL) { TiXmlElement* pRecordingNode; m_iRecordingCount = 0; for( pRecordingNode = recordingsNode->FirstChildElement("recording"); pRecordingNode; pRecordingNode=pRecordingNode->NextSiblingElement()) { m_iRecordingCount++; } } } } LOG_API_IRET(__FUNCTION__, m_iRecordingCount); return m_iRecordingCount; } PVR_ERROR cPVRClientNextPVR::GetRecordings(ADDON_HANDLE handle) { // include already-completed recordings PVR_ERROR returnValue = PVR_ERROR_NO_ERROR; m_hostFilenames.clear(); LOG_API_CALL(__FUNCTION__); int recordingCount = 0; std::string response; if (DoRequest("/service?method=recording.list&filter=all", response) == HTTP_OK) { TiXmlDocument doc; if (doc.Parse(response.c_str()) != NULL) { dump_to_log(&doc, 0); PVR_RECORDING tag; TiXmlElement* recordingsNode = doc.RootElement()->FirstChildElement("recordings"); TiXmlElement* pRecordingNode; for( pRecordingNode = recordingsNode->FirstChildElement("recording"); pRecordingNode; pRecordingNode=pRecordingNode->NextSiblingElement()) { memset(&tag, 0, sizeof(PVR_RECORDING)); if (UpdatePvrRecording(pRecordingNode, &tag)) { recordingCount++; PVR->TransferRecordingEntry(handle, &tag); } } } m_iRecordingCount = recordingCount; XBMC->Log(LOG_DEBUG, "Updated recordings %lld", m_lastRecordingUpdateTime); } else { returnValue = PVR_ERROR_SERVER_ERROR; } m_lastRecordingUpdateTime = time(0); LOG_API_IRET(__FUNCTION__, returnValue); return returnValue; } bool cPVRClientNextPVR::UpdatePvrRecording(TiXmlElement* pRecordingNode, PVR_RECORDING *tag) { tag->recordingTime = atol(pRecordingNode->FirstChildElement("start_time_ticks")->FirstChild()->Value()); std::string status = pRecordingNode->FirstChildElement("status")->FirstChild()->Value(); if (status=="Pending" && tag->recordingTime > time(nullptr) + g_ServerTimeOffset) { // skip timers return false; } tag->iDuration = atoi(pRecordingNode->FirstChildElement("duration_seconds")->FirstChild()->Value()); if (status == "Ready" || status == "Pending" || status == "Recording") { snprintf(tag->strDirectory,sizeof(tag->strDirectory),"/%s",pRecordingNode->FirstChildElement("name")->FirstChild()->Value()); if (pRecordingNode->FirstChildElement("desc") != NULL && pRecordingNode->FirstChildElement("desc")->FirstChild() != NULL) { PVR_STRCPY(tag->strPlot, pRecordingNode->FirstChildElement("desc")->FirstChild()->Value()); } } else if (status == "Failed") { snprintf(tag->strDirectory,sizeof(tag->strDirectory),"/%s/%s",XBMC->GetLocalizedString(30166),pRecordingNode->FirstChildElement("name")->FirstChild()->Value()); if (pRecordingNode->FirstChildElement("reason") != NULL && pRecordingNode->FirstChildElement("reason")->FirstChild() != NULL) { PVR_STRCPY(tag->strPlot, pRecordingNode->FirstChildElement("reason")->FirstChild()->Value()); } if (tag->iDuration < 0) { tag->iDuration = 0; } } else if (status == "Conflict") { // shouldn't happen; return false; } else { XBMC->Log(LOG_ERROR, "Unknown status %s",status.c_str()); return false; } if (status == "Recording") { if (pRecordingNode->FirstChildElement("epg_event_oid")) { // EPG Event ID is not valid on most older recordings if (atoi(pRecordingNode->FirstChildElement("recurring_parent")->FirstChild()->Value()) != 0 && pRecordingNode->FirstChildElement("epg_event_oid") != NULL && pRecordingNode->FirstChildElement("epg_event_oid")->FirstChild() != NULL) { tag->iEpgEventId = atoi(pRecordingNode->FirstChildElement("epg_event_oid")->FirstChild()->Value()); } else { // need check for older one offs tag->iEpgEventId = atoi(pRecordingNode->FirstChildElement("epg_event_oid")->FirstChild()->Value()); } } } PVR_STRCPY(tag->strRecordingId, pRecordingNode->FirstChildElement("id")->FirstChild()->Value()); PVR_STRCPY(tag->strTitle, pRecordingNode->FirstChildElement("name")->FirstChild()->Value()); if (pRecordingNode->FirstChildElement("subtitle") != NULL && pRecordingNode->FirstChildElement("subtitle")->FirstChild() != NULL) { if (g_KodiLook) { ParseNextPVRSubtitle(pRecordingNode->FirstChildElement("subtitle")->FirstChild()->Value(), tag); } else { PVR_STRCPY(tag->strTitle, pRecordingNode->FirstChildElement("subtitle")->FirstChild()->Value()); } } if (pRecordingNode->FirstChildElement("playback_position") != NULL && pRecordingNode->FirstChildElement("playback_position")->FirstChild() != NULL) { tag->iLastPlayedPosition = atoi(pRecordingNode->FirstChildElement("playback_position")->FirstChild()->Value()); } if (pRecordingNode->FirstChildElement("channel_id") != NULL && pRecordingNode->FirstChildElement("channel_id")->FirstChild() != NULL) { tag->iChannelUid = atoi(pRecordingNode->FirstChildElement("channel_id")->FirstChild()->Value()); if (tag->iChannelUid == 0) { tag->iChannelUid = PVR_CHANNEL_INVALID_UID; } else { strcpy(tag->strIconPath,GetChannelIconFileName(tag->iChannelUid).c_str()); } } else { tag->iChannelUid = PVR_CHANNEL_INVALID_UID; } if (pRecordingNode->FirstChildElement("file") != NULL && pRecordingNode->FirstChildElement("file")->FirstChild() != NULL) { m_hostFilenames[tag->strRecordingId] = pRecordingNode->FirstChildElement("file")->FirstChild()->Value(); } else { m_hostFilenames[tag->strRecordingId] = ""; } tag->channelType = PVR_RECORDING_CHANNEL_TYPE_UNKNOWN; if ( tag->iChannelUid != PVR_CHANNEL_INVALID_UID) { if ( m_channelTypes[tag->iChannelUid]) { if ( m_channelTypes[tag->iChannelUid] == true) { tag->channelType = PVR_RECORDING_CHANNEL_TYPE_RADIO; } else { tag->channelType = PVR_RECORDING_CHANNEL_TYPE_TV; } } } if (tag->channelType != PVR_RECORDING_CHANNEL_TYPE_RADIO) { char artworkPath[512]; snprintf(artworkPath, sizeof(artworkPath), "http://%s:%d/service?method=recording.artwork&sid=%s&recording_id=%s", g_szHostname.c_str(), g_iPort, m_sid, tag->strRecordingId); PVR_STRCPY(tag->strThumbnailPath, artworkPath); snprintf(artworkPath, sizeof(artworkPath), "http://%s:%d/service?method=recording.fanart&sid=%s&recording_id=%s", g_szHostname.c_str(), g_iPort, m_sid, tag->strRecordingId); PVR_STRCPY(tag->strFanartPath, artworkPath); } return true; } void cPVRClientNextPVR::ParseNextPVRSubtitle( const char *episodeName, PVR_RECORDING *tag) { string strEpisodeName = episodeName; std::regex base_regex("S(\\d\\d)E(\\d+) - ?(.+)?"); std::smatch base_match; if (std::regex_match(strEpisodeName , base_match, base_regex)) { if (base_match.size() == 3 || base_match.size() == 4) { std::ssub_match base_sub_match = base_match[1]; tag->iSeriesNumber = std::stoi(base_sub_match.str()); base_sub_match = base_match[2]; tag->iEpisodeNumber = std::stoi(base_sub_match.str()); if (base_match.size() == 4) { base_sub_match = base_match[3]; strcpy(tag->strEpisodeName,base_sub_match.str().c_str()); } } } else { PVR_STRCPY(tag->strEpisodeName , strEpisodeName.c_str()); } } PVR_ERROR cPVRClientNextPVR::DeleteRecording(const PVR_RECORDING &recording) { LOG_API_CALL(__FUNCTION__); XBMC->Log(LOG_DEBUG, "DeleteRecording"); char request[512]; if (recording.recordingTime < time(nullptr) && recording.recordingTime + recording.iDuration > time(nullptr)) return PVR_ERROR_RECORDING_RUNNING; sprintf(request, "/service?method=recording.delete&recording_id=%s", recording.strRecordingId); std::string response; if (DoRequest(request, response) == HTTP_OK) { if (strstr(response.c_str(), "")) { return PVR_ERROR_NO_ERROR; } } else { XBMC->Log(LOG_DEBUG, "DeleteRecording failed"); } return PVR_ERROR_FAILED; } PVR_ERROR cPVRClientNextPVR::SetRecordingLastPlayedPosition(const PVR_RECORDING &recording, int lastplayedposition) { LOG_API_CALL(__FUNCTION__); XBMC->Log(LOG_DEBUG, "SetRecordingLastPlayedPosition"); char request[512]; sprintf(request, "/service?method=recording.watched.set&recording_id=%s&position=%d", recording.strRecordingId, lastplayedposition); std::string response; if (DoRequest(request, response) == HTTP_OK) { if (strstr(response.c_str(), "") == NULL) { XBMC->Log(LOG_DEBUG, "SetRecordingLastPlayedPosition failed"); return PVR_ERROR_FAILED; } m_lastRecordingUpdateTime = 0; } return PVR_ERROR_NO_ERROR; } int cPVRClientNextPVR::GetRecordingLastPlayedPosition(const PVR_RECORDING &recording) { LOG_API_CALL(__FUNCTION__); return recording.iLastPlayedPosition; } PVR_ERROR cPVRClientNextPVR::GetRecordingEdl(const PVR_RECORDING& recording, PVR_EDL_ENTRY entries[], int *size) { LOG_API_CALL(__FUNCTION__); XBMC->Log(LOG_DEBUG, "GetRecordingEdl"); char request[512]; sprintf(request, "/service?method=recording.edl&recording_id=%s", recording.strRecordingId); std::string response; if (DoRequest(request, response) == HTTP_OK) { if (strstr(response.c_str(), "") != NULL) { TiXmlDocument doc; if (doc.Parse(response.c_str()) != NULL) { int index = 0; TiXmlElement* commercialsNode = doc.RootElement()->FirstChildElement("commercials"); TiXmlElement* pCommercialNode; for( pCommercialNode = commercialsNode->FirstChildElement("commercial"); pCommercialNode; pCommercialNode=pCommercialNode->NextSiblingElement()) { PVR_EDL_ENTRY entry; entry.start = atoi(pCommercialNode->FirstChildElement("start")->FirstChild()->Value()) * 1000; entry.end = atoi(pCommercialNode->FirstChildElement("end")->FirstChild()->Value()) * 1000 ; entry.type = PVR_EDL_TYPE_COMBREAK; entries[index] = entry; index++; } *size = index; return PVR_ERROR_NO_ERROR; } } } return PVR_ERROR_FAILED; } /************************************************************/ /** Timer handling */ int cPVRClientNextPVR::GetNumTimers(void) { LOG_API_CALL(__FUNCTION__); // Return -1 in case of error. if (m_iTimerCount != -1) return m_iTimerCount; std::string response; int timerCount = -1; // get list of recurring recordings if (DoRequest("/service?method=recording.recurring.list", response) == HTTP_OK) { TiXmlDocument doc; if (doc.Parse(response.c_str()) != NULL) { TiXmlElement* recordingsNode = doc.RootElement()->FirstChildElement("recurrings"); if (recordingsNode != NULL) { TiXmlElement* pRecordingNode; for( pRecordingNode = recordingsNode->FirstChildElement("recurring"); pRecordingNode; pRecordingNode=pRecordingNode->NextSiblingElement()) { timerCount++; } } } } // get list of pending recordings response = ""; if (DoRequest("/service?method=recording.list&filter=pending", response) == HTTP_OK) { TiXmlDocument doc; if (doc.Parse(response.c_str()) != NULL) { TiXmlElement* recordingsNode = doc.RootElement()->FirstChildElement("recordings"); if (recordingsNode != NULL) { TiXmlElement* pRecordingNode; for( pRecordingNode = recordingsNode->FirstChildElement("recording"); pRecordingNode; pRecordingNode=pRecordingNode->NextSiblingElement()) { timerCount++; } } } } if (timerCount > -1) { m_iTimerCount = timerCount + 1; } LOG_API_IRET(__FUNCTION__, timerCount); return m_iTimerCount; } PVR_ERROR cPVRClientNextPVR::GetTimers(ADDON_HANDLE handle) { std::string response; PVR_ERROR returnValue = PVR_ERROR_NO_ERROR; LOG_API_CALL(__FUNCTION__); int timerCount = 0; // first add the recurring recordings if (DoRequest("/service?method=recording.recurring.list&filter=pending", response) == HTTP_OK) { TiXmlDocument doc; if (doc.Parse(response.c_str()) != NULL) { PVR_TIMER tag; TiXmlElement* recurringsNode = doc.RootElement()->FirstChildElement("recurrings"); TiXmlElement* pRecurringNode; for( pRecurringNode = recurringsNode->FirstChildElement("recurring"); pRecurringNode; pRecurringNode=pRecurringNode->NextSiblingElement()) { memset(&tag, 0, sizeof(tag)); TiXmlElement* pMatchRulesNode = pRecurringNode->FirstChildElement("matchrules");// ->FirstChildElement("Rules"); TiXmlElement* pRulesNode = pMatchRulesNode->FirstChildElement("Rules");// ->FirstChildElement("Rules"); tag.iClientIndex = atoi(pRecurringNode->FirstChildElement("id")->FirstChild()->Value()); tag.iClientChannelUid = atoi(pRulesNode->FirstChildElement("ChannelOID")->FirstChild()->Value()); tag.iTimerType = pRulesNode->FirstChildElement("EPGTitle") ? TIMER_REPEATING_EPG : TIMER_REPEATING_MANUAL; // start/end time if (pRulesNode->FirstChildElement("StartTimeTicks") != NULL) { tag.startTime = atol(pRulesNode->FirstChildElement("StartTimeTicks")->FirstChild()->Value()); if (tag.startTime < time(nullptr)) { tag.startTime = 0; } else { tag.endTime = atol(pRulesNode->FirstChildElement("EndTimeTicks")->FirstChild()->Value()); } } // keyword recordings if (pRulesNode->FirstChildElement("AdvancedRules") != NULL) { std::string advancedRulesText = pRulesNode->FirstChildElement("AdvancedRules")->FirstChild()->Value(); if (advancedRulesText.find("KEYWORD: ") != string::npos) { tag.iTimerType = TIMER_REPEATING_KEYWORD; tag.startTime = 0; tag.endTime = 0; tag.bStartAnyTime = true; tag.bEndAnyTime = true; strncpy(tag.strEpgSearchString, &advancedRulesText.c_str()[9], sizeof(tag.strEpgSearchString) - 1); } } // days tag.iWeekdays = PVR_WEEKDAY_ALLDAYS; if (pRulesNode->FirstChildElement("Days") != NULL) { std::string daysText = pRulesNode->FirstChildElement("Days")->FirstChild()->Value(); tag.iWeekdays = PVR_WEEKDAY_NONE; if (daysText.find("SUN") != string::npos) tag.iWeekdays |= PVR_WEEKDAY_SUNDAY; if (daysText.find("MON") != string::npos) tag.iWeekdays |= PVR_WEEKDAY_MONDAY; if (daysText.find("TUE") != string::npos) tag.iWeekdays |= PVR_WEEKDAY_TUESDAY; if (daysText.find("WED") != string::npos) tag.iWeekdays |= PVR_WEEKDAY_WEDNESDAY; if (daysText.find("THU") != string::npos) tag.iWeekdays |= PVR_WEEKDAY_THURSDAY; if (daysText.find("FRI") != string::npos) tag.iWeekdays |= PVR_WEEKDAY_FRIDAY; if (daysText.find("SAT") != string::npos) tag.iWeekdays |= PVR_WEEKDAY_SATURDAY; } // pre/post padding if (pRulesNode->FirstChildElement("PrePadding") != NULL) { tag.iMarginStart = atoi(pRulesNode->FirstChildElement("PrePadding")->FirstChild()->Value()); tag.iMarginEnd = atoi(pRulesNode->FirstChildElement("PostPadding")->FirstChild()->Value()); } // number of recordings to keep if (pRulesNode->FirstChildElement("Keep") != NULL) { tag.iMaxRecordings = atoi(pRulesNode->FirstChildElement("Keep")->FirstChild()->Value()); } // prevent duplicates if (pRulesNode->FirstChildElement("OnlyNewEpisodes") != NULL) { if (strcmp(pRulesNode->FirstChildElement("OnlyNewEpisodes")->FirstChild()->Value(), "true") == 0) { tag.iPreventDuplicateEpisodes = 1; } } // recordings directory ID if (pRulesNode->FirstChildElement("RecordingDirectoryID") != NULL) { tag.iRecordingGroup = 0; if (pRulesNode->FirstChildElement("RecordingDirectoryID")->FirstChild() != NULL) { std::string recordingDirectoryID = pRulesNode->FirstChildElement("RecordingDirectoryID")->FirstChild()->Value(); int i = 0; for (auto it = m_recordingDirectories.begin(); it != m_recordingDirectories.end(); ++it, i++) { std::string bracketed = "[" + m_recordingDirectories[i] + "]"; if (bracketed == recordingDirectoryID) { tag.iRecordingGroup = i; break; } } } } PVR_STRCPY(tag.strTitle,pRecurringNode->FirstChildElement("name")->FirstChild()->Value()); tag.state = PVR_TIMER_STATE_SCHEDULED; PVR_STRCPY(tag.strSummary, "summary"); // pass timer to xbmc timerCount++; PVR->TransferTimerEntry(handle, &tag); } } // next add the one-off recordings. response = ""; if (DoRequest("/service?method=recording.list&filter=pending", response) == HTTP_OK) { TiXmlDocument doc; if (doc.Parse(response.c_str()) != NULL) { PVR_TIMER tag; TiXmlElement* recordingsNode = doc.RootElement()->FirstChildElement("recordings"); TiXmlElement* pRecordingNode; for( pRecordingNode = recordingsNode->FirstChildElement("recording"); pRecordingNode; pRecordingNode=pRecordingNode->NextSiblingElement()) { memset(&tag, 0, sizeof(tag)); UpdatePvrTimer(pRecordingNode, &tag); // pass timer to xbmc timerCount++; PVR->TransferTimerEntry(handle, &tag); } } response = ""; if (DoRequest("/service?method=recording.list&filter=conflict", response) == HTTP_OK) { TiXmlDocument doc; if (doc.Parse(response.c_str()) != NULL) { PVR_TIMER tag; TiXmlElement* recordingsNode = doc.RootElement()->FirstChildElement("recordings"); TiXmlElement* pRecordingNode; for( pRecordingNode = recordingsNode->FirstChildElement("recording"); pRecordingNode; pRecordingNode=pRecordingNode->NextSiblingElement()) { memset(&tag, 0, sizeof(tag)); UpdatePvrTimer(pRecordingNode, &tag); // pass timer to xbmc timerCount++; PVR->TransferTimerEntry(handle, &tag); } m_iTimerCount = timerCount; } } } } else { returnValue = PVR_ERROR_SERVER_ERROR; } LOG_API_IRET(__FUNCTION__, returnValue); return returnValue; } bool cPVRClientNextPVR::UpdatePvrTimer(TiXmlElement* pRecordingNode, PVR_TIMER *tag) { tag->iTimerType = pRecordingNode->FirstChildElement("epg_event_oid") ? TIMER_ONCE_EPG : TIMER_ONCE_MANUAL; tag->iClientIndex = atoi(pRecordingNode->FirstChildElement("id")->FirstChild()->Value()); tag->iClientChannelUid = atoi(pRecordingNode->FirstChildElement("channel_id")->FirstChild()->Value()); if (pRecordingNode->FirstChildElement("recurring_parent") != NULL) { tag->iParentClientIndex = atoi(pRecordingNode->FirstChildElement("recurring_parent")->FirstChild()->Value()); if (tag->iParentClientIndex != PVR_TIMER_NO_PARENT) { if (tag->iTimerType == TIMER_ONCE_EPG) { tag->iTimerType = TIMER_ONCE_EPG_CHILD; } else { tag->iTimerType = TIMER_ONCE_MANUAL_CHILD; } } if (pRecordingNode->FirstChildElement("epg_event_oid") != NULL && pRecordingNode->FirstChildElement("epg_event_oid")->FirstChild() != NULL) { tag->iEpgUid = atoi(pRecordingNode->FirstChildElement("epg_event_oid")->FirstChild()->Value()); XBMC->Log(LOG_DEBUG, "Setting timer epg id %d %d", tag->iClientIndex, tag->iEpgUid); } } // pre-padding if (pRecordingNode->FirstChildElement("pre_padding") != NULL) { tag->iMarginStart = atoi(pRecordingNode->FirstChildElement("pre_padding")->FirstChild()->Value()); } // post-padding if (pRecordingNode->FirstChildElement("post_padding") != NULL) { tag->iMarginEnd = atoi(pRecordingNode->FirstChildElement("post_padding")->FirstChild()->Value()); } // name PVR_STRCPY(tag->strTitle, pRecordingNode->FirstChildElement("name")->FirstChild()->Value()); // description if (pRecordingNode->FirstChildElement("desc") != NULL && pRecordingNode->FirstChildElement("desc")->FirstChild() != NULL) { PVR_STRCPY(tag->strSummary, pRecordingNode->FirstChildElement("desc")->FirstChild()->Value()); } // start/end time char start[32]; strncpy(start, pRecordingNode->FirstChildElement("start_time_ticks")->FirstChild()->Value(), sizeof start); start[10] = '\0'; tag->startTime = atol(start); tag->endTime = tag->startTime + atoi(pRecordingNode->FirstChildElement("duration_seconds")->FirstChild()->Value()); tag->state = PVR_TIMER_STATE_SCHEDULED; if (pRecordingNode->FirstChildElement("status") != NULL && pRecordingNode->FirstChildElement("status")->FirstChild() != NULL) { std::string status = pRecordingNode->FirstChildElement("status")->FirstChild()->Value(); if (status == "Recording" || (status == "Pending" && tag->startTime < time(nullptr) + g_ServerTimeOffset) ) { tag->state = PVR_TIMER_STATE_RECORDING; } else if (status == "Conflict") { tag->state = PVR_TIMER_STATE_CONFLICT_NOK; } } return true; } namespace { struct TimerType : PVR_TIMER_TYPE { TimerType(unsigned int id, unsigned int attributes, const std::string &description, const std::vector< std::pair > &maxRecordingsValues, int maxRecordingsDefault, const std::vector< std::pair > &dupEpisodesValues, int dupEpisodesDefault, const std::vector< std::pair > &recordingGroupsValues, int recordingGroupDefault ) { memset(this, 0, sizeof(PVR_TIMER_TYPE)); iId = id; iAttributes = attributes; iMaxRecordingsSize = maxRecordingsValues.size(); iMaxRecordingsDefault = maxRecordingsDefault; iPreventDuplicateEpisodesSize = dupEpisodesValues.size(); iPreventDuplicateEpisodesDefault = dupEpisodesDefault; iRecordingGroupSize = recordingGroupsValues.size(); iRecordingGroupDefault = recordingGroupDefault; strncpy(strDescription, description.c_str(), sizeof(strDescription)-1); int i = 0; for (auto it = maxRecordingsValues.begin(); it != maxRecordingsValues.end(); ++it, ++i) { maxRecordings[i].iValue = it->first; strncpy(maxRecordings[i].strDescription, it->second.c_str(), sizeof(maxRecordings[i].strDescription) - 1); } i = 0; for (auto it = dupEpisodesValues.begin(); it != dupEpisodesValues.end(); ++it, ++i) { preventDuplicateEpisodes[i].iValue = it->first; strncpy(preventDuplicateEpisodes[i].strDescription, it->second.c_str(), sizeof(preventDuplicateEpisodes[i].strDescription) - 1); } i = 0; for (auto it = recordingGroupsValues.begin(); it != recordingGroupsValues.end(); ++it, ++i) { recordingGroup[i].iValue = it->first; strncpy(recordingGroup[i].strDescription, it->second.c_str(), sizeof(recordingGroup[i].strDescription) - 1); } } }; } // unnamed namespace PVR_ERROR cPVRClientNextPVR::GetTimerTypes(PVR_TIMER_TYPE types[], int *size) { LOG_API_CALL(__FUNCTION__); static const int MSG_ONETIME_MANUAL = 30140; static const int MSG_ONETIME_GUIDE = 30141; static const int MSG_REPEATING_MANUAL = 30142; static const int MSG_REPEATING_GUIDE = 30143; static const int MSG_REPEATING_CHILD = 30144; static const int MSG_REPEATING_KEYWORD = 30145; static const int MSG_KEEPALL = 30150; static const int MSG_KEEP1 = 30151; static const int MSG_KEEP2 = 30152; static const int MSG_KEEP3 = 30153; static const int MSG_KEEP4 = 30154; static const int MSG_KEEP5 = 30155; static const int MSG_KEEP6 = 30156; static const int MSG_KEEP7 = 30157; static const int MSG_KEEP10 = 30158; static const int MSG_SHOWTYPE_FIRSTRUNONLY = 30160; static const int MSG_SHOWTYPE_ANY = 30161; /* PVR_Timer.iMaxRecordings values and presentation. */ static std::vector< std::pair > recordingLimitValues; if (recordingLimitValues.size() == 0) { recordingLimitValues.push_back(std::make_pair(NEXTPVR_LIMIT_ASMANY, XBMC->GetLocalizedString(MSG_KEEPALL))); recordingLimitValues.push_back(std::make_pair(NEXTPVR_LIMIT_1, XBMC->GetLocalizedString(MSG_KEEP1))); recordingLimitValues.push_back(std::make_pair(NEXTPVR_LIMIT_2, XBMC->GetLocalizedString(MSG_KEEP2))); recordingLimitValues.push_back(std::make_pair(NEXTPVR_LIMIT_3, XBMC->GetLocalizedString(MSG_KEEP3))); recordingLimitValues.push_back(std::make_pair(NEXTPVR_LIMIT_4, XBMC->GetLocalizedString(MSG_KEEP4))); recordingLimitValues.push_back(std::make_pair(NEXTPVR_LIMIT_5, XBMC->GetLocalizedString(MSG_KEEP5))); recordingLimitValues.push_back(std::make_pair(NEXTPVR_LIMIT_6, XBMC->GetLocalizedString(MSG_KEEP6))); recordingLimitValues.push_back(std::make_pair(NEXTPVR_LIMIT_7, XBMC->GetLocalizedString(MSG_KEEP7))); recordingLimitValues.push_back(std::make_pair(NEXTPVR_LIMIT_10, XBMC->GetLocalizedString(MSG_KEEP10))); } /* PVR_Timer.iPreventDuplicateEpisodes values and presentation.*/ static std::vector< std::pair > showTypeValues; if (showTypeValues.size() == 0) { showTypeValues.push_back(std::make_pair(NEXTPVR_SHOWTYPE_FIRSTRUNONLY, XBMC->GetLocalizedString(MSG_SHOWTYPE_FIRSTRUNONLY))); showTypeValues.push_back(std::make_pair(NEXTPVR_SHOWTYPE_ANY, XBMC->GetLocalizedString(MSG_SHOWTYPE_ANY))); } /* PVR_Timer.iRecordingGroup values and presentation */ int i = 0; static std::vector< std::pair > recordingGroupValues; for (auto it = m_recordingDirectories.begin(); it != m_recordingDirectories.end(); ++it, i++) { recordingGroupValues.push_back(std::make_pair(i, m_recordingDirectories[i])); } static const unsigned int TIMER_MANUAL_ATTRIBS = PVR_TIMER_TYPE_IS_MANUAL | PVR_TIMER_TYPE_SUPPORTS_CHANNELS | PVR_TIMER_TYPE_SUPPORTS_START_TIME | PVR_TIMER_TYPE_SUPPORTS_END_TIME | PVR_TIMER_TYPE_SUPPORTS_RECORDING_GROUP | PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN; static const unsigned int TIMER_EPG_ATTRIBS = PVR_TIMER_TYPE_REQUIRES_EPG_TAG_ON_CREATE | PVR_TIMER_TYPE_SUPPORTS_CHANNELS | PVR_TIMER_TYPE_SUPPORTS_RECORDING_GROUP | PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN; static const unsigned int TIMER_REPEATING_MANUAL_ATTRIBS = PVR_TIMER_TYPE_IS_REPEATING | PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN | PVR_TIMER_TYPE_SUPPORTS_RECORDING_GROUP | PVR_TIMER_TYPE_SUPPORTS_WEEKDAYS | PVR_TIMER_TYPE_SUPPORTS_MAX_RECORDINGS; static const unsigned int TIMER_REPEATING_EPG_ATTRIBS = PVR_TIMER_TYPE_IS_REPEATING | PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN | PVR_TIMER_TYPE_SUPPORTS_WEEKDAYS | PVR_TIMER_TYPE_SUPPORTS_RECORDING_GROUP | PVR_TIMER_TYPE_SUPPORTS_RECORD_ONLY_NEW_EPISODES | PVR_TIMER_TYPE_SUPPORTS_ANY_CHANNEL | PVR_TIMER_TYPE_SUPPORTS_MAX_RECORDINGS; static const unsigned int TIMER_CHILD_ATTRIBUTES = PVR_TIMER_TYPE_SUPPORTS_START_TIME | PVR_TIMER_TYPE_SUPPORTS_END_TIME | PVR_TIMER_TYPE_FORBIDS_NEW_INSTANCES; static const unsigned int TIMER_KEYWORD_ATTRIBS = PVR_TIMER_TYPE_SUPPORTS_CHANNELS | PVR_TIMER_TYPE_SUPPORTS_TITLE_EPG_MATCH | PVR_TIMER_TYPE_SUPPORTS_RECORDING_GROUP | PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN; static const unsigned int TIMER_REPEATING_KEYWORD_ATTRIBS = PVR_TIMER_TYPE_IS_REPEATING | PVR_TIMER_TYPE_SUPPORTS_RECORD_ONLY_NEW_EPISODES | PVR_TIMER_TYPE_SUPPORTS_ANY_CHANNEL | PVR_TIMER_TYPE_SUPPORTS_MAX_RECORDINGS; /* Timer types definition.*/ static std::vector< std::unique_ptr< TimerType > > timerTypes; if (timerTypes.size() == 0) { timerTypes.push_back( /* One-shot manual (time and channel based) */ std::unique_ptr(new TimerType( /* Type id. */ TIMER_ONCE_MANUAL, /* Attributes. */ TIMER_MANUAL_ATTRIBS, /* Description. */ XBMC->GetLocalizedString(MSG_ONETIME_MANUAL), // "One time (manual)", /* Values definitions for attributes. */ recordingLimitValues, m_defaultLimit, showTypeValues, m_defaultShowType, recordingGroupValues, 0))); timerTypes.push_back( /* One-shot epg based */ std::unique_ptr(new TimerType( /* Type id. */ TIMER_ONCE_EPG, /* Attributes. */ TIMER_EPG_ATTRIBS, /* Description. */ XBMC->GetLocalizedString(MSG_ONETIME_GUIDE), // "One time (guide)", /* Values definitions for attributes. */ recordingLimitValues, m_defaultLimit, showTypeValues, m_defaultShowType, recordingGroupValues, 0))); timerTypes.push_back( /* Repeating manual (time and channel based) Parent */ std::unique_ptr(new TimerType( /* Type id. */ TIMER_REPEATING_MANUAL, /* Attributes. */ TIMER_MANUAL_ATTRIBS | TIMER_REPEATING_MANUAL_ATTRIBS, /* Description. */ XBMC->GetLocalizedString(MSG_REPEATING_MANUAL), // "Repeating (manual)" /* Values definitions for attributes. */ recordingLimitValues, m_defaultLimit, showTypeValues, m_defaultShowType, recordingGroupValues, 0))); timerTypes.push_back( /* Repeating epg based Parent*/ std::unique_ptr(new TimerType( /* Type id. */ TIMER_REPEATING_EPG, /* Attributes. */ TIMER_EPG_ATTRIBS | TIMER_REPEATING_EPG_ATTRIBS, /* Description. */ XBMC->GetLocalizedString(MSG_REPEATING_GUIDE), // "Repeating (guide)" /* Values definitions for attributes. */ recordingLimitValues, m_defaultLimit, showTypeValues, m_defaultShowType, recordingGroupValues, 0))); timerTypes.push_back( /* Read-only one-shot for timers generated by timerec */ std::unique_ptr(new TimerType( /* Type id. */ TIMER_ONCE_MANUAL_CHILD, /* Attributes. */ TIMER_MANUAL_ATTRIBS | TIMER_CHILD_ATTRIBUTES, /* Description. */ XBMC->GetLocalizedString(MSG_REPEATING_CHILD), // "Created by Repeating Timer" /* Values definitions for attributes. */ recordingLimitValues, m_defaultLimit, showTypeValues, m_defaultShowType, recordingGroupValues, 0))); timerTypes.push_back( /* Read-only one-shot for timers generated by autorec */ std::unique_ptr(new TimerType( /* Type id. */ TIMER_ONCE_EPG_CHILD, /* Attributes. */ TIMER_EPG_ATTRIBS | TIMER_CHILD_ATTRIBUTES, /* Description. */ XBMC->GetLocalizedString(MSG_REPEATING_CHILD), // "Created by Repeating Timer" /* Values definitions for attributes. */ recordingLimitValues, m_defaultLimit, showTypeValues, m_defaultShowType, recordingGroupValues, 0))); timerTypes.push_back( /* Repeating epg based Parent*/ std::unique_ptr(new TimerType( /* Type id. */ TIMER_REPEATING_KEYWORD, /* Attributes. */ TIMER_KEYWORD_ATTRIBS | TIMER_REPEATING_KEYWORD_ATTRIBS, /* Description. */ XBMC->GetLocalizedString(MSG_REPEATING_KEYWORD), // "Repeating (keyword)" /* Values definitions for attributes. */ recordingLimitValues, m_defaultLimit, showTypeValues, m_defaultShowType, recordingGroupValues, 0))); } /* Copy data to target array. */ i = 0; for (auto it = timerTypes.begin(); it != timerTypes.end(); ++it, ++i) types[i] = **it; *size = timerTypes.size(); return PVR_ERROR_NO_ERROR; } std::string cPVRClientNextPVR::GetDayString(int dayMask) { std::string days; if (dayMask == (PVR_WEEKDAY_SATURDAY | PVR_WEEKDAY_SUNDAY)) { days = "WEEKENDS"; } else if (dayMask == (PVR_WEEKDAY_MONDAY | PVR_WEEKDAY_TUESDAY | PVR_WEEKDAY_WEDNESDAY | PVR_WEEKDAY_THURSDAY | PVR_WEEKDAY_FRIDAY)) { days = "WEEKDAYS"; } else { if (dayMask & PVR_WEEKDAY_SATURDAY) days += "SAT:"; if (dayMask & PVR_WEEKDAY_SUNDAY) days += "SUN:"; if (dayMask & PVR_WEEKDAY_MONDAY) days += "MON:"; if (dayMask & PVR_WEEKDAY_TUESDAY) days += "TUE:"; if (dayMask & PVR_WEEKDAY_WEDNESDAY) days += "WED:"; if (dayMask & PVR_WEEKDAY_THURSDAY) days += "THU:"; if (dayMask & PVR_WEEKDAY_FRIDAY) days += "FRI:"; } return days; } PVR_ERROR cPVRClientNextPVR::AddTimer(const PVR_TIMER &timerinfo) { // editing recording is not supported //if (timerinfo.iClientIndex != PVR_TIMER_NO_CLIENT_INDEX) //{ // return PVR_ERROR_NOT_IMPLEMENTED; //} char request[1024]; char preventDuplicates[16]; LOG_API_CALL(__FUNCTION__); if (timerinfo.iPreventDuplicateEpisodes) strcpy(preventDuplicates, "true"); else strcpy(preventDuplicates, "false"); std::string encodedName = UriEncode(timerinfo.strTitle); std::string encodedKeyword = UriEncode(timerinfo.strEpgSearchString); std::string days = GetDayString(timerinfo.iWeekdays); std:string directory = UriEncode( m_recordingDirectories[timerinfo.iRecordingGroup]); switch (timerinfo.iTimerType) { case TIMER_ONCE_MANUAL: XBMC->Log(LOG_DEBUG, "TIMER_ONCE_MANUAL"); // build one-off recording request snprintf(request, sizeof(request), "/service?method=recording.save&name=%s&channel=%d&time_t=%d&duration=%d&pre_padding=%d&post_padding=%d&directory_id=%s", encodedName.c_str(), timerinfo.iClientChannelUid, (int)timerinfo.startTime, (int)(timerinfo.endTime - timerinfo.startTime), (int)timerinfo.iMarginStart, (int)timerinfo.iMarginEnd, directory.c_str() ); break; case TIMER_ONCE_EPG: XBMC->Log(LOG_DEBUG, "TIMER_ONCE_EPG"); // build one-off recording request snprintf(request, sizeof(request), "/service?method=recording.save&recording_id=%d&event_id=%d&pre_padding=%d&post_padding=%d&directory_id=%s", timerinfo.iClientIndex, timerinfo.iEpgUid, (int)timerinfo.iMarginStart, (int)timerinfo.iMarginEnd, directory.c_str()); break; case TIMER_REPEATING_EPG: if (timerinfo.iClientChannelUid == PVR_TIMER_ANY_CHANNEL) { // Fake a manual recording XBMC->Log(LOG_DEBUG, "TIMER_REPEATING_EPG ANY CHANNEL"); string title = encodedName + "%"; snprintf(request, sizeof(request), "/service?method=recording.recurring.save&name=%s&channel_id=%d&start_time=%d&end_time=%d&keep=%d&pre_padding=%d&post_padding=%d&day_mask=%s&directory_id=%s,&keyword=%s", encodedName.c_str(), timerinfo.iClientChannelUid, (int)timerinfo.startTime, (int)timerinfo.endTime, (int)timerinfo.iMaxRecordings, (int)timerinfo.iMarginStart, (int)timerinfo.iMarginEnd, days.c_str(), directory.c_str(), title.c_str() ); } else { XBMC->Log(LOG_DEBUG, "TIMER_REPEATING_EPG"); // build recurring recording request snprintf(request, sizeof(request), "/service?method=recording.recurring.save&recurring_id=%d&event_id=%d&keep=%d&pre_padding=%d&post_padding=%d&day_mask=%s&directory_id=%s&only_new=%s", timerinfo.iClientIndex, timerinfo.iEpgUid, (int)timerinfo.iMaxRecordings, (int)timerinfo.iMarginStart, (int)timerinfo.iMarginEnd, days.c_str(), directory.c_str(), preventDuplicates ); } break; case TIMER_REPEATING_MANUAL: XBMC->Log(LOG_DEBUG, "TIMER_REPEATING_MANUAL"); // build manual recurring request snprintf(request, sizeof(request), "/service?method=recording.recurring.save&recurring_id=%d&name=%s&channel_id=%d&start_time=%d&end_time=%d&keep=%d&pre_padding=%d&post_padding=%d&day_mask=%s&directory_id=%s", timerinfo.iClientIndex, encodedName.c_str(), timerinfo.iClientChannelUid, (int)timerinfo.startTime, (int)timerinfo.endTime, (int)timerinfo.iMaxRecordings, (int)timerinfo.iMarginStart, (int)timerinfo.iMarginEnd, days.c_str(), directory.c_str() ); break; case TIMER_REPEATING_KEYWORD: XBMC->Log(LOG_DEBUG, "TIMER_REPEATING_KEYWORD"); // build manual recurring request snprintf(request, sizeof(request), "/service?method=recording.recurring.save&recurring_id=%d&name=%s&channel_id=%d&start_time=%d&end_time=%d&keep=%d&pre_padding=%d&post_padding=%d&directory_id=%s&keyword=%s&only_new=%s", timerinfo.iClientIndex, encodedName.c_str(), timerinfo.iClientChannelUid, (int)timerinfo.startTime, (int)timerinfo.endTime, (int)timerinfo.iMaxRecordings, (int)timerinfo.iMarginStart, (int)timerinfo.iMarginEnd, directory.c_str(), encodedKeyword.c_str(), preventDuplicates ); break; } // send request to NextPVR std::string response; if (DoRequest(request, response) == HTTP_OK) { if (strstr(response.c_str(), "")) { if (timerinfo.startTime <= time(nullptr) && timerinfo.endTime > time(nullptr)) PVR->TriggerRecordingUpdate(); PVR->TriggerTimerUpdate(); return PVR_ERROR_NO_ERROR; } } return PVR_ERROR_FAILED; } PVR_ERROR cPVRClientNextPVR::DeleteTimer(const PVR_TIMER &timer, bool bForceDelete) { char request[512]; LOG_API_CALL(__FUNCTION__); sprintf(request, "/service?method=recording.delete&recording_id=%d", timer.iClientIndex); // handle recurring recordings if (timer.iTimerType >= TIMER_REPEATING_MIN && timer.iTimerType <= TIMER_REPEATING_MAX) { sprintf(request, "/service?method=recording.recurring.delete&recurring_id=%d", timer.iClientIndex); } std::string response; if (DoRequest(request, response) == HTTP_OK) { if (strstr(response.c_str(), "")) { PVR->TriggerTimerUpdate(); if (timer.startTime <= time(nullptr) && timer.endTime > time(nullptr)) PVR->TriggerRecordingUpdate(); return PVR_ERROR_NO_ERROR; } } return PVR_ERROR_FAILED; } PVR_ERROR cPVRClientNextPVR::UpdateTimer(const PVR_TIMER &timerinfo) { LOG_API_CALL(__FUNCTION__); // not supported return AddTimer(timerinfo); } /************************************************************/ /** Live stream handling */ bool cPVRClientNextPVR::OpenLiveStream(const PVR_CHANNEL &channelinfo) { char line[256]; LOG_API_CALL(__FUNCTION__); if (channelinfo.bIsRadio == false) { g_NowPlaying = TV; } else { g_NowPlaying = Radio; } if (m_liveStreams.count(channelinfo.iUniqueId)!= 0) { snprintf(line,sizeof(line),"%s",m_liveStreams[channelinfo.iUniqueId].c_str()); m_livePlayer = m_realTimeBuffer; } else if (channelinfo.bIsRadio == false && m_supportsLiveTimeshift && g_livestreamingmethod == Timeshift) { sprintf(line, "GET /live?channeloid=%d&mode=liveshift&client=XBMC-%s HTTP/1.0\r\n", channelinfo.iUniqueId, m_sid); m_livePlayer = m_timeshiftBuffer; } else if (g_livestreamingmethod == RollingFile) { sprintf(line, "http://%s:%d/live?channeloid=%d&client=XBMC-%s&epgmode=true", g_szHostname.c_str(), g_iPort, channelinfo.iUniqueId, m_sid); m_livePlayer = m_timeshiftBuffer; } else if (g_livestreamingmethod == ClientTimeshift) { sprintf(line, "http://%s:%d/live?channeloid=%d&client=%s&sid=%s", g_szHostname.c_str(), g_iPort, channelinfo.iUniqueId, m_sid,m_sid); m_livePlayer = m_timeshiftBuffer; m_livePlayer->Channel(channelinfo.iUniqueId); } else { sprintf(line, "http://%s:%d/live?channeloid=%d&client=XBMC-%s", g_szHostname.c_str(), g_iPort, channelinfo.iUniqueId, m_sid); m_livePlayer = m_realTimeBuffer; } XBMC->Log(LOG_NOTICE, "Calling Open(%s) on tsb!", line); if (m_livePlayer->Open(line)) { return true; } return false; } int cPVRClientNextPVR::ReadLiveStream(unsigned char *pBuffer, unsigned int iBufferSize) { LOG_API_CALL(__FUNCTION__); return m_livePlayer->Read(pBuffer, iBufferSize); } void cPVRClientNextPVR::CloseLiveStream(void) { LOG_API_CALL(__FUNCTION__); XBMC->Log(LOG_DEBUG, "CloseLiveStream"); if (m_livePlayer != nullptr) { XBMC->Log(LOG_DEBUG, "CloseLiveStream"); m_livePlayer->Close(); m_livePlayer = nullptr; } XBMC->Log(LOG_DEBUG, "CloseLiveStream@exit"); g_NowPlaying = NotPlaying; } long long cPVRClientNextPVR::SeekLiveStream(long long iPosition, int iWhence) { long long retVal; LOG_API_CALL(__FUNCTION__); XBMC->Log(LOG_DEBUG, "calling seek(%lli %d)", iPosition, iWhence); retVal = m_livePlayer->Seek(iPosition, iWhence); XBMC->Log(LOG_DEBUG, "returned from seek()"); return retVal; } long long cPVRClientNextPVR::LengthLiveStream(void) { LOG_API_CALL(__FUNCTION__); XBMC->Log(LOG_DEBUG, "seek length(%lli)", m_livePlayer->Length()); return m_livePlayer->Length(); } PVR_ERROR cPVRClientNextPVR::SignalStatus(PVR_SIGNAL_STATUS &signalStatus) { LOG_API_CALL(__FUNCTION__); // Not supported yet return PVR_ERROR_NO_ERROR; } bool cPVRClientNextPVR::CanPauseStream(void) { LOG_API_CALL(__FUNCTION__); if (g_NowPlaying == Recording ) { return true; } else { bool retval = m_livePlayer->CanPauseStream(); return retval; } } void cPVRClientNextPVR::PauseStream(bool bPaused) { LOG_API_CALL(__FUNCTION__); if (g_NowPlaying == Recording ) m_recordingBuffer->PauseStream(bPaused); else m_livePlayer->PauseStream(bPaused); } bool cPVRClientNextPVR::CanSeekStream(void) { LOG_API_CALL(__FUNCTION__); if (g_NowPlaying == Recording ) return true; else return m_livePlayer->CanSeekStream(); } /************************************************************/ /** Record stream handling */ bool cPVRClientNextPVR::OpenRecordedStream(const PVR_RECORDING &recording) { PVR_RECORDING copyRecording = recording; LOG_API_CALL(__FUNCTION__); m_currentRecordingLength = 0; m_currentRecordingPosition = 0; char line[1024]; g_NowPlaying = Recording; strcpy(copyRecording.strDirectory,m_hostFilenames[recording.strRecordingId].c_str()); snprintf(line, sizeof(line), "http://%s:%d/live?recording=%s&client=XBMC-%s", g_szHostname.c_str(), g_iPort, recording.strRecordingId, m_sid); return m_recordingBuffer->Open(line,copyRecording); } void cPVRClientNextPVR::CloseRecordedStream(void) { LOG_API_CALL(__FUNCTION__); m_recordingBuffer->Close(); m_recordingBuffer->SetDuration(0); m_currentRecordingLength = 0; m_currentRecordingPosition = 0; g_NowPlaying = NotPlaying; } int cPVRClientNextPVR::ReadRecordedStream(unsigned char *pBuffer, unsigned int iBufferSize) { LOG_API_CALL(__FUNCTION__); iBufferSize = m_recordingBuffer->Read(pBuffer, iBufferSize); return iBufferSize; } long long cPVRClientNextPVR::SeekRecordedStream(long long iPosition, int iWhence) { LOG_API_CALL(__FUNCTION__); return m_recordingBuffer->Seek(iPosition, iWhence); } long long cPVRClientNextPVR::LengthRecordedStream(void) { LOG_API_CALL(__FUNCTION__); return m_recordingBuffer->Length(); } /************************************************************/ /** http handling */ int cPVRClientNextPVR::DoRequest(const char *resource, std::string &response) { int resultCode = NextPVR::m_backEnd->DoRequest(resource, response); return resultCode; } bool cPVRClientNextPVR::IsTimeshifting() { LOG_API_CALL(__FUNCTION__); if (g_NowPlaying == Recording ) return false; else return m_livePlayer->IsTimeshifting(); } bool cPVRClientNextPVR::IsRealTimeStream() { LOG_API_CALL(__FUNCTION__); bool retval; if (g_NowPlaying == Recording ) { retval = m_recordingBuffer->IsRealTimeStream(); } else { retval = m_livePlayer->IsRealTimeStream(); } return retval; } PVR_ERROR cPVRClientNextPVR::GetStreamTimes(PVR_STREAM_TIMES *stimes) { PVR_ERROR rez; LOG_API_CALL(__FUNCTION__); if (g_NowPlaying == Recording ) rez = m_recordingBuffer->GetStreamTimes(stimes); else rez = m_livePlayer->GetStreamTimes(stimes); #if DEBUGGING_API XBMC->Log(LOG_ERROR, "GetStreamTimes: start: %d", stimes->startTime); XBMC->Log(LOG_ERROR, " ptsStart: %lld", stimes->ptsStart); XBMC->Log(LOG_ERROR, " ptsBegin: %lld", stimes->ptsBegin); XBMC->Log(LOG_ERROR, " ptsEnd: %lld", stimes->ptsEnd); #endif return rez; } PVR_ERROR cPVRClientNextPVR::GetStreamReadChunkSize(int* chunksize) { PVR_ERROR rez; if (g_NowPlaying == Recording ) rez = m_recordingBuffer->GetStreamReadChunkSize(chunksize); else rez = m_livePlayer->GetStreamReadChunkSize(chunksize); LOG_API_IRET(__FUNCTION__, *chunksize); return rez; } bool cPVRClientNextPVR::SaveSettings(std::string name, std::string value) { bool found = false; TiXmlDocument doc; char *settings = XBMC->TranslateSpecialProtocol("special://profile/addon_data/pvr.nextpvr/settings.xml"); if (doc.LoadFile(settings)) { //Get Root Node TiXmlElement* rootNode = doc.FirstChildElement("settings"); if (rootNode) { TiXmlElement* childNode; for( childNode = rootNode->FirstChildElement("setting"); childNode; childNode=childNode->NextSiblingElement()) { std::string key_value; if ( childNode->QueryStringAttribute("id", &key_value)==TIXML_SUCCESS) { if (key_value == name) { if (childNode->FirstChild()) { childNode->FirstChild()->SetValue( value ); found = true; break; } return false; } } } if (found == false) { TiXmlElement *newSetting = new TiXmlElement( "setting" ); TiXmlText *newvalue = new TiXmlText( value ); newSetting->SetAttribute("id", name); newSetting->LinkEndChild( newvalue ); rootNode->LinkEndChild( newSetting); } ADDON_SetSetting(name.c_str(),value.c_str()); doc.SaveFile(settings); } } else { XBMC->Log(LOG_ERROR, "Error loading setting.xml %s", settings); } XBMC->FreeString(settings); return true; } #if DEBUGGING_XML // ---------------------------------------------------------------------- // LOG dump and indenting utility functions // ---------------------------------------------------------------------- const unsigned int NUM_INDENTS_PER_SPACE=2; const char * getIndent( unsigned int numIndents ) { static const char * pINDENT=" + "; static const unsigned int LENGTH=strlen( pINDENT ); unsigned int n=numIndents*NUM_INDENTS_PER_SPACE; if ( n > LENGTH ) n = LENGTH; return &pINDENT[ LENGTH-n ]; } // same as getIndent but no "+" at the end const char * getIndentAlt( unsigned int numIndents ) { static const char * pINDENT=" "; static const unsigned int LENGTH=strlen( pINDENT ); unsigned int n=numIndents*NUM_INDENTS_PER_SPACE; if ( n > LENGTH ) n = LENGTH; return &pINDENT[ LENGTH-n ]; } int dump_attribs_to_stdout(TiXmlElement* pElement, unsigned int indent) { if ( !pElement ) return 0; TiXmlAttribute* pAttrib=pElement->FirstAttribute(); int i=0; int ival; double dval; const char* pIndent=getIndent(indent); // XBMC->Log(LOG_NOTICE, "\n"); while (pAttrib) { char buf[1024]; sprintf(buf, "%s%s: value=[%s]", pIndent, pAttrib->Name(), pAttrib->Value()); // XBMC->Log(LOG_NOTICE, "%s%s: value=[%s]", pIndent, pAttrib->Name(), pAttrib->Value()); if (pAttrib->QueryIntValue(&ival)==TIXML_SUCCESS) { sprintf(buf + strlen(buf), " int=%d", ival); // XBMC->Log(LOG_NOTICE, " int=%d", ival); } if (pAttrib->QueryDoubleValue(&dval)==TIXML_SUCCESS) { sprintf(buf + strlen(buf), " d=%1.1f", dval); // XBMC->Log(LOG_NOTICE, " d=%1.1f", dval); } XBMC->Log(LOG_NOTICE, "%s", buf ); i++; pAttrib=pAttrib->Next(); } return i; } void dump_to_log( TiXmlNode* pParent, unsigned int indent) { if ( !pParent ) return; char buf[2048]; TiXmlNode* pChild; TiXmlText* pText; int t = pParent->Type(); sprintf(buf, "%s", getIndent(indent)); // XBMC->Log(LOG_NOTICE, "%s", getIndent(indent)); int num; switch ( t ) { case TiXmlNode::TINYXML_DOCUMENT: sprintf(buf + strlen(buf), "Document"); // XBMC->Log(LOG_NOTICE, "Document" ); break; case TiXmlNode::TINYXML_ELEMENT: sprintf(buf + strlen(buf), "Element [%s]", pParent->Value()); // XBMC->Log(LOG_NOTICE, "Element [%s]", pParent->Value() ); num=dump_attribs_to_stdout(pParent->ToElement(), indent+1); switch(num) { case 0: sprintf(buf + strlen(buf), " (No attributes)"); // XBMC->Log(LOG_NOTICE, " (No attributes)"); break; case 1: sprintf(buf + strlen(buf), "%s1 attribute", getIndentAlt(indent)); // XBMC->Log(LOG_NOTICE, "%s1 attribute", getIndentAlt(indent)); break; default: sprintf(buf + strlen(buf), "%s%d attributes", getIndentAlt(indent), num); // XBMC->Log(LOG_NOTICE, "%s%d attributes", getIndentAlt(indent), num); break; } break; case TiXmlNode::TINYXML_COMMENT: sprintf(buf + strlen(buf), "Comment: [%s]", pParent->Value()); //XBMC->Log(LOG_NOTICE, "Comment: [%s]", pParent->Value()); break; case TiXmlNode::TINYXML_UNKNOWN: sprintf(buf + strlen(buf), "Unknown"); // XBMC->Log(LOG_NOTICE, "Unknown" ); break; case TiXmlNode::TINYXML_TEXT: pText = pParent->ToText(); sprintf(buf + strlen(buf), "Text: [%s]", pText->Value()); // XBMC->Log(LOG_NOTICE, "Text: [%s]", pText->Value() ); break; case TiXmlNode::TINYXML_DECLARATION: sprintf(buf + strlen(buf), "Declaration"); // XBMC->Log(LOG_NOTICE, "Declaration" ); break; default: break; } XBMC->Log(LOG_ERROR, "%s\n", buf ); for ( pChild = pParent->FirstChild(); pChild != 0; pChild = pChild->NextSibling()) { dump_to_log( pChild, indent+1 ); } } #endif // DEBUGGING_XML pvr.nextpvr-3.3.18-Leia/src/pvrclient-nextpvr.h000066400000000000000000000170321360274650100214530ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2011 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include /* Master defines for client control */ #include "kodi/xbmc_pvr_types.h" /* Local includes */ #include "Socket.h" #include "p8-platform/threads/mutex.h" #include "p8-platform/threads/threads.h" #include "tinyxml.h" #include "buffers/DummyBuffer.h" #include "buffers/TimeshiftBuffer.h" #include "buffers/RecordingBuffer.h" #include "buffers/RollingFile.h" #include "buffers/ClientTimeshift.h" #include #define SAFE_DELETE(p) do { delete (p); (p)=NULL; } while (0) /* timer type ids */ #define TIMER_MANUAL_MIN (PVR_TIMER_TYPE_NONE + 1) #define TIMER_ONCE_MANUAL (TIMER_MANUAL_MIN + 0) #define TIMER_ONCE_EPG (TIMER_MANUAL_MIN + 1) #define TIMER_ONCE_KEYWORD (TIMER_MANUAL_MIN + 2) #define TIMER_ONCE_MANUAL_CHILD (TIMER_MANUAL_MIN + 3) #define TIMER_ONCE_EPG_CHILD (TIMER_MANUAL_MIN + 4) #define TIMER_ONCE_KEYWORD_CHILD (TIMER_MANUAL_MIN + 5) #define TIMER_MANUAL_MAX (TIMER_MANUAL_MIN + 5) #define TIMER_REPEATING_MIN (TIMER_MANUAL_MAX + 1) #define TIMER_REPEATING_MANUAL (TIMER_REPEATING_MIN + 0) #define TIMER_REPEATING_EPG (TIMER_REPEATING_MIN + 1) #define TIMER_REPEATING_KEYWORD (TIMER_REPEATING_MIN + 2) #define TIMER_REPEATING_MAX (TIMER_REPEATING_MIN + 2) typedef enum { NEXTPVR_SHOWTYPE_ANY = 0, NEXTPVR_SHOWTYPE_FIRSTRUNONLY = 1, } nextpvr_showtype_t; typedef enum { NEXTPVR_LIMIT_ASMANY = 0, NEXTPVR_LIMIT_1 = 1, NEXTPVR_LIMIT_2 = 2, NEXTPVR_LIMIT_3 = 3, NEXTPVR_LIMIT_4 = 4, NEXTPVR_LIMIT_5 = 5, NEXTPVR_LIMIT_6 = 6, NEXTPVR_LIMIT_7 = 7, NEXTPVR_LIMIT_10 = 10 } nextpvr_recordinglimit_t; class cPVRClientNextPVR : P8PLATFORM::CThread { public: /* Class interface */ cPVRClientNextPVR(); ~cPVRClientNextPVR(); /* Server handling */ bool Connect(); void Disconnect(); bool IsUp(); void OnSystemSleep(); void OnSystemWake(); /* General handling */ const char* GetBackendName(void); const char* GetBackendVersion(void); const char* GetConnectionString(void); PVR_ERROR GetDriveSpace(long long *iTotal, long long *iUsed); PVR_ERROR GetBackendTime(time_t *localTime, int *gmtOffset); PVR_ERROR GetStreamTimes(PVR_STREAM_TIMES *stimes); PVR_ERROR GetStreamReadChunkSize(int* chunksize); /* EPG handling */ PVR_ERROR GetEpg(ADDON_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart = 0, time_t iEnd = 0); /* Channel handling */ int GetNumChannels(void); PVR_ERROR GetChannels(ADDON_HANDLE handle, bool bRadio); PVR_ERROR GetChannelStreamProperties(const PVR_CHANNEL &channel, PVR_NAMED_VALUE *properties, unsigned int *iPropertiesCount); bool IsChannelAPlugin(int uid); /* Channel group handling */ int GetChannelGroupsAmount(void); PVR_ERROR GetChannelGroups(ADDON_HANDLE handle, bool bRadio); PVR_ERROR GetChannelGroupMembers(ADDON_HANDLE handle, const PVR_CHANNEL_GROUP &group); /* Record handling **/ int GetNumRecordings(void); PVR_ERROR GetRecordings(ADDON_HANDLE handle); PVR_ERROR DeleteRecording(const PVR_RECORDING &recording); PVR_ERROR SetRecordingLastPlayedPosition(const PVR_RECORDING &recording, int lastplayedposition); int GetRecordingLastPlayedPosition(const PVR_RECORDING &recording); PVR_ERROR GetRecordingEdl(const PVR_RECORDING& recording, PVR_EDL_ENTRY[], int *size); PVR_ERROR GetRecordingStreamProperties(const PVR_RECORDING*, PVR_NAMED_VALUE*, unsigned int*); bool UpdatePvrRecording(TiXmlElement* pRecordingNode, PVR_RECORDING *tag); void ParseNextPVRSubtitle( const char *episodeName, PVR_RECORDING *tag); /* Timer handling */ int GetNumTimers(void); PVR_ERROR GetTimerTypes(PVR_TIMER_TYPE types[], int *size); PVR_ERROR GetTimers(ADDON_HANDLE handle); PVR_ERROR GetTimerInfo(unsigned int timernumber, PVR_TIMER &timer); PVR_ERROR AddTimer(const PVR_TIMER &timer); PVR_ERROR DeleteTimer(const PVR_TIMER &timer, bool bForceDelete = false); PVR_ERROR UpdateTimer(const PVR_TIMER &timer); bool UpdatePvrTimer(TiXmlElement* pRecordingNode, PVR_TIMER *tag); /* Live stream handling */ bool OpenLiveStream(const PVR_CHANNEL &channel); void CloseLiveStream(); int ReadLiveStream(unsigned char *pBuffer, unsigned int iBufferSize); PVR_ERROR SignalStatus(PVR_SIGNAL_STATUS &signalStatus); long long SeekLiveStream(long long iPosition, int iWhence = SEEK_SET); long long LengthLiveStream(void); bool CanPauseStream(void); void PauseStream(bool bPause); bool CanSeekStream(void); bool IsTimeshifting(void); bool IsRealTimeStream(void); /* Record stream handling */ bool OpenRecordedStream(const PVR_RECORDING &recording); void CloseRecordedStream(void); int ReadRecordedStream(unsigned char *pBuffer, unsigned int iBufferSize); long long SeekRecordedStream(long long iPosition, int iWhence = SEEK_SET); long long LengthRecordedStream(void); /* background connection monitoring */ void *Process(void); protected: NextPVR::Socket *m_tcpclient; NextPVR::Socket *m_streamingclient; private: std::string GetDayString(int dayMask); std::vector split(const std::string& s, const std::string& delim, const bool keep_empty); bool GetChannel(unsigned int number, PVR_CHANNEL &channeldata); bool LoadGenreXML(const std::string &filename); int DoRequest(const char *resource, std::string &response); std::string GetChannelIcon(int channelID); std::string GetChannelIconFileName(int channelID); void Close(); int m_iCurrentChannel; bool m_bConnected; std::string m_BackendName; P8PLATFORM::CMutex m_mutex; long long m_currentRecordingLength; long long m_currentRecordingPosition; bool m_supportsLiveTimeshift; long long m_currentLiveLength; long long m_currentLivePosition; int m_iDefaultPrePadding; int m_iDefaultPostPadding; std::vector< std::string > m_recordingDirectories; int64_t m_lastRecordingUpdateTime; char m_sid[64]; // update these at end of counting loop can be called during action int m_iChannelCount = -1; int m_iRecordingCount = -1; int m_iTimerCount = -1; int m_defaultLimit; int m_defaultShowType; time_t m_tsbStartTime; int m_timeShiftBufferSeconds; timeshift::Buffer *m_timeshiftBuffer; timeshift::Buffer *m_livePlayer; timeshift::Buffer *m_realTimeBuffer; timeshift::RecordingBuffer *m_recordingBuffer; std::map m_hostFilenames; std::map m_channelTypes; // returns isRadio std::map m_liveStreams; void SendWakeOnLan(); bool SaveSettings(std::string name, std::string value); void LoadLiveStreams(); }; pvr.nextpvr-3.3.18-Leia/src/uri.cpp000066400000000000000000000245521360274650100171000ustar00rootroot00000000000000/* * Copyright (C) 2005-2011 Team XBMC * http://www.xbmc.org * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "uri.h" namespace uri { const char ENCODE_BEGIN_CHAR = '%'; const traits SCHEME_TRAITS = { 0, 0, ':', { CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CVA2,CINV,CVA2,CVA2,CINV, CVA2,CVA2,CVA2,CVA2,CVA2,CVA2,CVA2,CVA2, CVA2,CVA2,CEND,CINV,CINV,CINV,CINV,CINV, CINV,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CINV,CINV,CINV,CINV,CINV, CINV,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CINV,CINV,CINV,CINV,CINV, // 127 7F CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, } }; const traits AUTHORITY_TRAITS = { "//", 0, 0, { CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CEND,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, // 127 7F CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, } }; const traits PATH_TRAITS = { 0, 0, 0, { // '/' is invalid CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CVAL,CINV,CINV,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CINV, CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CVAL,CINV,CVAL,CINV,CINV, CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CINV,CINV,CINV,CINV,CVAL, CINV,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CINV,CINV,CINV,CVAL,CINV, // 127 7F CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, } }; const traits QUERY_TRAITS = { 0, '?', 0, { // '=' and '&' are invalid CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CVAL,CINV,CINV,CVAL,CVAL,CINV,CVAL, CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CVAL,CINV,CINV,CINV,CVAL, CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CINV,CINV,CINV,CINV,CVAL, CINV,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CINV,CINV,CINV,CVAL,CINV, // 127 7F CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, } }; const traits FRAGMENT_TRAITS = { 0, '#', 0, { CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CVAL,CINV,CINV,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CVAL,CINV,CVAL,CINV,CVAL, CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CINV,CINV,CINV,CINV,CVAL, CINV,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL,CVAL, CVAL,CVAL,CVAL,CINV,CINV,CINV,CVAL,CINV, // 127 7F CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, CINV,CINV,CINV,CINV,CINV,CINV,CINV,CINV, } }; bool parse_hex(const std::string& s, size_t pos, char& chr) { if (s.size() < pos + 2) return false; unsigned int v; unsigned int c = (unsigned int) s[pos]; if ('0' <= c && c <= '9') v = (c - '0') << 4; else if ('A' <= c && c <= 'F') v = (10 + (c - 'A')) << 4; else if ('a' <= c && c <= 'f') v = (10 + (c - 'a')) << 4; else return false; c = (unsigned int) s[pos + 1]; if ('0' <= c && c <= '9') v += c - '0'; else if ('A' <= c && c <= 'F') v += 10 + (c - 'A'); else if ('a' <= c && c <= 'f') v += 10 + (c - 'a'); else return false; chr = (char) v; // Set output. return true; } void append_hex(char v, std::string& s) { unsigned int c = (unsigned char) v & 0xF0; c >>= 4; s.insert(s.end(), (char)((9 < c) ? (c - 10) + 'A' : c + '0')); c = v & 0x0F; s.insert(s.end(), (char)((9 < c) ? (c - 10) + 'A' : c + '0')); } std::string encode(const traits& ts, const std::string& comp) { std::string::const_iterator f = comp.begin(); std::string::const_iterator anchor = f; std::string s; for (; f != comp.end();) { char c = *f; if (ts.char_class[(unsigned char)c] < CVAL || c == ENCODE_BEGIN_CHAR) { // Must encode. s.append(anchor, f); // Catch up to this char. s.append(1, ENCODE_BEGIN_CHAR); append_hex(c, s); // Convert. anchor = ++f; } else { ++f; } } return (anchor == comp.begin()) ? comp : s.append(anchor, comp.end()); } bool decode(std::string& s) { size_t pos = s.find(ENCODE_BEGIN_CHAR); if (pos == std::string::npos) { // Handle the "99%" case fast. return true; } std::string v; for (size_t i = 0;;) { if (pos == std::string::npos) { v.append(s, i, s.size() - i); // Append up to end. break; } v.append(s, i, pos - i); // Append up to char. i = pos + 3; // Skip all 3 chars. char c; if (!parse_hex(s, pos + 1, c)) { // Convert hex. return false; } v.insert(v.end(), c); // Append converted hex. pos = s.find(ENCODE_BEGIN_CHAR, i); // Find next } s = v; return true; } } //namespace URI pvr.nextpvr-3.3.18-Leia/src/uri.h000066400000000000000000000053371360274650100165450ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2011 Team XBMC * http://www.xbmc.org * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include namespace uri { /// Char class. typedef enum char_class_e : signed char { CINV = -2, ///< invalid CEND = -1, ///< end delimitor CVAL = 0, ///< valid any position CVA2 = 1, ///< valid anywhere but 1st position } char_class_e_type; /// Traits used for parsing and encoding components. struct traits { const char* begin_cstring; ///< begin cstring (or 0 if none) const char begin_char; ///< begin char (or 0 if none) const char end_char; ///< end char (or 0 if none) const char_class_e_type char_class[256]; ///< map of char to class }; /** * \brief Encode the URI (sub) component. * Note that this should be used on the subcomponents before appending to * subdelimiter chars, if any. * * From the RFC: URI producing applications should percent-encode data octets * are specifically allowed by the URI scheme to represent data in that * component. If a reserved character is found in a URI component and * no delimiting role is known for that character, then it must be * interpreted as representing the data octet corresponding to that * character's encoding in US-ASCII. * @see http://tools.ietf.org/html/rfc3986 * @see decode std::string encode(const traits& ts, const std::string& comp); */ std::string encode(const traits& ts, const std::string& comp); /** * Decode the pct-encoded (hex) sequences, if any, return success. * Does not change string on error. * @see http://tools.ietf.org/html/rfc3986#section-2.1 * @see encode * \param s A reference to the std::string to decode */ bool decode(std::string& s); extern const char ENCODE_BEGIN_CHAR; ///< encode begin char ('\%') extern const traits SCHEME_TRAITS; ///< scheme traits extern const traits AUTHORITY_TRAITS; ///< authority traits extern const traits PATH_TRAITS; ///< path traits extern const traits QUERY_TRAITS; ///< query traits extern const traits FRAGMENT_TRAITS; ///< fragment traits }